Imported Upstream version 1.42.0 upstream/1.42.0
authorJinWang An <jinwang.an@samsung.com>
Wed, 1 Dec 2021 08:53:27 +0000 (17:53 +0900)
committerJinWang An <jinwang.an@samsung.com>
Wed, 1 Dec 2021 08:53:27 +0000 (17:53 +0900)
1888 files changed:
.bazelignore
.github/ISSUE_TEMPLATE/bug_report.md
.github/ISSUE_TEMPLATE/cleanup_request.md
.github/ISSUE_TEMPLATE/feature_request.md
.github/ISSUE_TEMPLATE/question.md
.github/pull_request_template.md
.github/workflows/pr-auto-fix.yaml
.gitmodules
BUILD
BUILDING.md
CMakeLists.txt
LICENSE
Makefile
Rakefile
WORKSPACE
_metadata.py
bazel/BUILD
bazel/_gevent_test_main.py [new file with mode: 0644]
bazel/gevent_test.bzl [new file with mode: 0644]
bazel/grpc_build_system.bzl
bazel/grpc_deps.bzl
bazel/grpc_python_deps.bzl
bazel/internal_python_rules.bzl [new file with mode: 0644]
bazel/protobuf.bzl
bazel/python_rules.bzl
bazel/test/python_test_repo/BUILD
bazel/test/python_test_repo/dummy_plugin.py [deleted file]
bazel/test/python_test_repo/import_from_proto_library_package.py [new file with mode: 0644]
bazel/test/python_test_repo/import_from_this_package.py [new file with mode: 0644]
bazel/test/python_test_repo/in_subpackage/BUILD [new file with mode: 0644]
bazel/test/python_test_repo/in_subpackage/subpackage.proto [new file with mode: 0644]
bazel/test/python_test_repo/namespaced/upper/example/BUILD
bazel/test/python_test_repo/transitive_proto_dep.py [new file with mode: 0644]
bazel/update_mirror.sh
build_autogenerated.yaml
build_config.rb
build_handwritten.yaml
config.m4
config.w32
doc/environment_variables.md
doc/g_stands_for.md
doc/grpc_xds_features.md
doc/load-balancing.md
examples/android/binder/java/io/grpc/binder/cpp/README.md [new file with mode: 0644]
examples/android/binder/java/io/grpc/binder/cpp/example/AndroidManifest.xml [deleted file]
examples/android/binder/java/io/grpc/binder/cpp/example/BUILD [deleted file]
examples/android/binder/java/io/grpc/binder/cpp/example/ButtonPressHandler.java [deleted file]
examples/android/binder/java/io/grpc/binder/cpp/example/MainActivity.java [deleted file]
examples/android/binder/java/io/grpc/binder/cpp/example/README.md [deleted file]
examples/android/binder/java/io/grpc/binder/cpp/example/native.cc [deleted file]
examples/android/binder/java/io/grpc/binder/cpp/exampleclient/AndroidManifest.xml [new file with mode: 0644]
examples/android/binder/java/io/grpc/binder/cpp/exampleclient/BUILD [new file with mode: 0644]
examples/android/binder/java/io/grpc/binder/cpp/exampleclient/ButtonPressHandler.java [new file with mode: 0644]
examples/android/binder/java/io/grpc/binder/cpp/exampleclient/MainActivity.java [new file with mode: 0644]
examples/android/binder/java/io/grpc/binder/cpp/exampleclient/native.cc [new file with mode: 0644]
examples/android/binder/java/io/grpc/binder/cpp/exampleclient/res/layout/activity_main.xml [moved from examples/android/binder/java/io/grpc/binder/cpp/example/res/layout/activity_main.xml with 100% similarity]
examples/android/binder/java/io/grpc/binder/cpp/exampleclient/res/values/strings.xml [moved from examples/android/binder/java/io/grpc/binder/cpp/example/res/values/strings.xml with 100% similarity]
examples/android/binder/java/io/grpc/binder/cpp/exampleserver/BUILD
examples/android/binder/java/io/grpc/binder/cpp/exampleserver/ExportedEndpointService.java
examples/android/binder/java/io/grpc/binder/cpp/exampleserver/native.cc
examples/cpp/compression/BUILD
examples/cpp/helloworld/BUILD
examples/cpp/keyvaluestore/BUILD
examples/cpp/load_balancing/BUILD
examples/cpp/metadata/BUILD
examples/cpp/route_guide/BUILD
examples/objective-c/BUILD
examples/protos/BUILD
examples/python/async_streaming/client.py
examples/python/data_transmission/BUILD
gRPC-C++.podspec
gRPC-Core.podspec
gRPC-ProtoRPC.podspec
gRPC-RxLibrary.podspec
gRPC.podspec
grpc.def
grpc.gemspec
grpc.gyp
include/grpc/event_engine/event_engine.h
include/grpc/event_engine/internal/memory_allocator_impl.h [new file with mode: 0644]
include/grpc/event_engine/memory_allocator.h [new file with mode: 0644]
include/grpc/event_engine/slice_allocator.h [deleted file]
include/grpc/grpc.h
include/grpc/grpc_security.h
include/grpc/grpc_security_constants.h
include/grpc/impl/codegen/port_platform.h
include/grpcpp/create_channel_binder.h [new file with mode: 0644]
include/grpcpp/impl/codegen/core_codegen.h
include/grpcpp/impl/codegen/core_codegen_interface.h
include/grpcpp/impl/codegen/server_context.h
include/grpcpp/impl/codegen/sync_stream.h
include/grpcpp/security/authorization_policy_provider.h
include/grpcpp/security/binder_credentials.h [new file with mode: 0644]
include/grpcpp/security/binder_security_policy.h [new file with mode: 0644]
package.xml
requirements.bazel.txt
setup.py
src/boringssl/boringssl_prefix_symbols.h
src/core/ext/filters/client_channel/backend_metric.cc
src/core/ext/filters/client_channel/backup_poller.cc
src/core/ext/filters/client_channel/channel_connectivity.cc
src/core/ext/filters/client_channel/client_channel.cc
src/core/ext/filters/client_channel/client_channel.h
src/core/ext/filters/client_channel/client_channel_factory.cc
src/core/ext/filters/client_channel/client_channel_factory.h
src/core/ext/filters/client_channel/client_channel_plugin.cc
src/core/ext/filters/client_channel/config_selector.cc
src/core/ext/filters/client_channel/config_selector.h
src/core/ext/filters/client_channel/connector.h
src/core/ext/filters/client_channel/dynamic_filters.cc
src/core/ext/filters/client_channel/global_subchannel_pool.h
src/core/ext/filters/client_channel/health/health_check_client.cc
src/core/ext/filters/client_channel/http_connect_handshaker.h
src/core/ext/filters/client_channel/lb_policy.h
src/core/ext/filters/client_channel/lb_policy/child_policy_handler.cc
src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc
src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h
src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_balancer_addresses.cc
src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc
src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc
src/core/ext/filters/client_channel/lb_policy/priority/priority.cc
src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc
src/core/ext/filters/client_channel/lb_policy/rls/rls.cc [new file with mode: 0644]
src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc
src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc
src/core/ext/filters/client_channel/lb_policy/xds/cds.cc
src/core/ext/filters/client_channel/lb_policy/xds/xds_channel_args.h
src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_impl.cc
src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_manager.cc
src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_resolver.cc
src/core/ext/filters/client_channel/lb_policy_factory.h
src/core/ext/filters/client_channel/resolver.h
src/core/ext/filters/client_channel/resolver/binder/README.md [new file with mode: 0644]
src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc [new file with mode: 0644]
src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc
src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc
src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc
src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h
src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc
src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc
src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc
src/core/ext/filters/client_channel/resolver_factory.h
src/core/ext/filters/client_channel/resolver_registry.cc
src/core/ext/filters/client_channel/resolver_result_parsing.cc
src/core/ext/filters/client_channel/resolver_result_parsing.h
src/core/ext/filters/client_channel/retry_filter.cc
src/core/ext/filters/client_channel/retry_service_config.h
src/core/ext/filters/client_channel/retry_throttle.cc
src/core/ext/filters/client_channel/server_address.h
src/core/ext/filters/client_channel/service_config.cc [deleted file]
src/core/ext/filters/client_channel/service_config.h [deleted file]
src/core/ext/filters/client_channel/service_config_call_data.h [deleted file]
src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc
src/core/ext/filters/client_channel/service_config_parser.cc [deleted file]
src/core/ext/filters/client_channel/service_config_parser.h [deleted file]
src/core/ext/filters/client_channel/subchannel.cc
src/core/ext/filters/client_channel/subchannel.h
src/core/ext/filters/client_channel/subchannel_pool_interface.cc
src/core/ext/filters/client_channel/subchannel_pool_interface.h
src/core/ext/filters/client_idle/client_idle_filter.cc
src/core/ext/filters/client_idle/idle_filter_state.cc [new file with mode: 0644]
src/core/ext/filters/client_idle/idle_filter_state.h [new file with mode: 0644]
src/core/ext/filters/deadline/deadline_filter.cc
src/core/ext/filters/fault_injection/fault_injection_filter.cc
src/core/ext/filters/fault_injection/service_config_parser.cc
src/core/ext/filters/fault_injection/service_config_parser.h
src/core/ext/filters/http/client/http_client_filter.cc
src/core/ext/filters/http/client_authority_filter.cc
src/core/ext/filters/http/http_filters_plugin.cc
src/core/ext/filters/http/message_compress/message_compress_filter.cc
src/core/ext/filters/http/message_compress/message_decompress_filter.cc
src/core/ext/filters/http/server/http_server_filter.cc
src/core/ext/filters/load_reporting/server_load_reporting_filter.cc
src/core/ext/filters/max_age/max_age_filter.cc
src/core/ext/filters/message_size/message_size_filter.cc
src/core/ext/filters/message_size/message_size_filter.h
src/core/ext/filters/server_config_selector/server_config_selector.cc [new file with mode: 0644]
src/core/ext/filters/server_config_selector/server_config_selector.h [new file with mode: 0644]
src/core/ext/filters/server_config_selector/server_config_selector_filter.cc [new file with mode: 0644]
src/core/ext/filters/server_config_selector/server_config_selector_filter.h [new file with mode: 0644]
src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc [deleted file]
src/core/ext/filters/workarounds/workaround_cronet_compression_filter.h [deleted file]
src/core/ext/filters/workarounds/workaround_utils.cc [deleted file]
src/core/ext/filters/workarounds/workaround_utils.h [deleted file]
src/core/ext/service_config/service_config.cc [new file with mode: 0644]
src/core/ext/service_config/service_config.h [new file with mode: 0644]
src/core/ext/service_config/service_config_call_data.h [new file with mode: 0644]
src/core/ext/service_config/service_config_parser.cc [new file with mode: 0644]
src/core/ext/service_config/service_config_parser.h [new file with mode: 0644]
src/core/ext/transport/binder/client/BUILD [deleted file]
src/core/ext/transport/binder/client/binder_connector.cc [new file with mode: 0644]
src/core/ext/transport/binder/client/binder_connector.h [new file with mode: 0644]
src/core/ext/transport/binder/client/channel_create.cc
src/core/ext/transport/binder/client/channel_create.h [deleted file]
src/core/ext/transport/binder/client/channel_create_impl.cc
src/core/ext/transport/binder/client/channel_create_impl.h
src/core/ext/transport/binder/client/connection_id_generator.cc [new file with mode: 0644]
src/core/ext/transport/binder/client/connection_id_generator.h [new file with mode: 0644]
src/core/ext/transport/binder/client/endpoint_binder_pool.cc [new file with mode: 0644]
src/core/ext/transport/binder/client/endpoint_binder_pool.h [new file with mode: 0644]
src/core/ext/transport/binder/client/jni_utils.cc
src/core/ext/transport/binder/client/jni_utils.h
src/core/ext/transport/binder/client/security_policy_setting.cc [new file with mode: 0644]
src/core/ext/transport/binder/client/security_policy_setting.h [new file with mode: 0644]
src/core/ext/transport/binder/java/io/grpc/binder/cpp/BUILD
src/core/ext/transport/binder/java/io/grpc/binder/cpp/GrpcBinderConnection.java [new file with mode: 0644]
src/core/ext/transport/binder/java/io/grpc/binder/cpp/GrpcCppServerBuilder.java [new file with mode: 0644]
src/core/ext/transport/binder/java/io/grpc/binder/cpp/NativeConnectionHelper.java
src/core/ext/transport/binder/java/io/grpc/binder/cpp/SyncServiceConnection.java [deleted file]
src/core/ext/transport/binder/security_policy/binder_security_policy.cc [new file with mode: 0644]
src/core/ext/transport/binder/security_policy/internal_only_security_policy.h [new file with mode: 0644]
src/core/ext/transport/binder/security_policy/security_policy.h [new file with mode: 0644]
src/core/ext/transport/binder/server/BUILD [deleted file]
src/core/ext/transport/binder/server/binder_server.cc
src/core/ext/transport/binder/server/binder_server.h
src/core/ext/transport/binder/server/binder_server_credentials.cc
src/core/ext/transport/binder/server/binder_server_credentials.h [deleted file]
src/core/ext/transport/binder/transport/BUILD [deleted file]
src/core/ext/transport/binder/transport/binder_stream.h
src/core/ext/transport/binder/transport/binder_transport.cc
src/core/ext/transport/binder/transport/binder_transport.h
src/core/ext/transport/binder/utils/BUILD [deleted file]
src/core/ext/transport/binder/utils/transport_stream_receiver.h
src/core/ext/transport/binder/utils/transport_stream_receiver_impl.cc
src/core/ext/transport/binder/utils/transport_stream_receiver_impl.h
src/core/ext/transport/binder/wire_format/BUILD [deleted file]
src/core/ext/transport/binder/wire_format/binder.h
src/core/ext/transport/binder/wire_format/binder_android.cc
src/core/ext/transport/binder/wire_format/binder_android.h
src/core/ext/transport/binder/wire_format/binder_constants.cc
src/core/ext/transport/binder/wire_format/binder_constants.h
src/core/ext/transport/binder/wire_format/transaction.cc
src/core/ext/transport/binder/wire_format/transaction.h
src/core/ext/transport/binder/wire_format/wire_reader.h
src/core/ext/transport/binder/wire_format/wire_reader_impl.cc
src/core/ext/transport/binder/wire_format/wire_reader_impl.h
src/core/ext/transport/binder/wire_format/wire_writer.cc
src/core/ext/transport/binder/wire_format/wire_writer.h
src/core/ext/transport/chttp2/client/authority.cc [deleted file]
src/core/ext/transport/chttp2/client/authority.h [deleted file]
src/core/ext/transport/chttp2/client/chttp2_connector.cc
src/core/ext/transport/chttp2/client/insecure/channel_create.cc
src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc
src/core/ext/transport/chttp2/server/chttp2_server.cc
src/core/ext/transport/chttp2/transport/chttp2_slice_allocator.cc [deleted file]
src/core/ext/transport/chttp2/transport/chttp2_slice_allocator.h [deleted file]
src/core/ext/transport/chttp2/transport/chttp2_transport.cc
src/core/ext/transport/chttp2/transport/flow_control.cc
src/core/ext/transport/chttp2/transport/flow_control.h
src/core/ext/transport/chttp2/transport/frame_data.cc
src/core/ext/transport/chttp2/transport/frame_goaway.cc
src/core/ext/transport/chttp2/transport/frame_ping.cc
src/core/ext/transport/chttp2/transport/frame_rst_stream.cc
src/core/ext/transport/chttp2/transport/frame_settings.cc
src/core/ext/transport/chttp2/transport/hpack_constants.h
src/core/ext/transport/chttp2/transport/hpack_encoder.cc
src/core/ext/transport/chttp2/transport/hpack_encoder.h
src/core/ext/transport/chttp2/transport/hpack_encoder_index.h
src/core/ext/transport/chttp2/transport/hpack_parser.cc
src/core/ext/transport/chttp2/transport/hpack_parser.h
src/core/ext/transport/chttp2/transport/hpack_parser_table.cc
src/core/ext/transport/chttp2/transport/hpack_parser_table.h
src/core/ext/transport/chttp2/transport/incoming_metadata.cc [deleted file]
src/core/ext/transport/chttp2/transport/incoming_metadata.h [deleted file]
src/core/ext/transport/chttp2/transport/internal.h
src/core/ext/transport/chttp2/transport/parsing.cc
src/core/ext/transport/chttp2/transport/popularity_count.h
src/core/ext/transport/chttp2/transport/writing.cc
src/core/ext/transport/cronet/BUILD
src/core/ext/transport/cronet/client/secure/cronet_channel_create.cc
src/core/ext/transport/cronet/plugin_registry/grpc_cronet_plugin_registry.cc
src/core/ext/transport/cronet/transport/cronet_status.cc
src/core/ext/transport/cronet/transport/cronet_status.h
src/core/ext/transport/cronet/transport/cronet_transport.cc
src/core/ext/transport/inproc/inproc_transport.cc
src/core/ext/upb-generated/envoy/config/cluster/v3/cluster.upb.c
src/core/ext/upb-generated/envoy/config/cluster/v3/cluster.upb.h
src/core/ext/upb-generated/envoy/config/core/v3/base.upb.c
src/core/ext/upb-generated/envoy/config/core/v3/base.upb.h
src/core/ext/upb-generated/envoy/config/core/v3/health_check.upb.c
src/core/ext/upb-generated/envoy/config/core/v3/health_check.upb.h
src/core/ext/upb-generated/envoy/config/core/v3/protocol.upb.c
src/core/ext/upb-generated/envoy/config/core/v3/protocol.upb.h
src/core/ext/upb-generated/envoy/config/endpoint/v3/endpoint_components.upb.c
src/core/ext/upb-generated/envoy/config/rbac/v3/rbac.upb.c
src/core/ext/upb-generated/envoy/config/rbac/v3/rbac.upb.h
src/core/ext/upb-generated/envoy/config/route/v3/route_components.upb.c
src/core/ext/upb-generated/envoy/config/route/v3/route_components.upb.h
src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls.upb.c [new file with mode: 0644]
src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls.upb.h [new file with mode: 0644]
src/core/ext/upb-generated/udpa/annotations/security.upb.c
src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c [deleted file]
src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h [deleted file]
src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.c [deleted file]
src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.h [deleted file]
src/core/ext/upb-generated/xds/annotations/v3/status.upb.c [new file with mode: 0644]
src/core/ext/upb-generated/xds/annotations/v3/status.upb.h [new file with mode: 0644]
src/core/ext/upb-generated/xds/core/v3/authority.upb.c
src/core/ext/upb-generated/xds/core/v3/collection_entry.upb.c
src/core/ext/upb-generated/xds/core/v3/context_params.upb.c
src/core/ext/upb-generated/xds/core/v3/resource.upb.c
src/core/ext/upb-generated/xds/core/v3/resource_locator.upb.c
src/core/ext/upb-generated/xds/core/v3/resource_name.upb.c
src/core/ext/upb-generated/xds/data/orca/v3/orca_load_report.upb.c [new file with mode: 0644]
src/core/ext/upb-generated/xds/data/orca/v3/orca_load_report.upb.h [new file with mode: 0644]
src/core/ext/upb-generated/xds/type/v3/typed_struct.upb.c [new file with mode: 0644]
src/core/ext/upb-generated/xds/type/v3/typed_struct.upb.h [new file with mode: 0644]
src/core/ext/upbdefs-generated/envoy/config/cluster/v3/cluster.upbdefs.c
src/core/ext/upbdefs-generated/envoy/config/cluster/v3/cluster.upbdefs.h
src/core/ext/upbdefs-generated/envoy/config/core/v3/base.upbdefs.c
src/core/ext/upbdefs-generated/envoy/config/core/v3/base.upbdefs.h
src/core/ext/upbdefs-generated/envoy/config/core/v3/health_check.upbdefs.c
src/core/ext/upbdefs-generated/envoy/config/core/v3/protocol.upbdefs.c
src/core/ext/upbdefs-generated/envoy/config/endpoint/v3/endpoint_components.upbdefs.c
src/core/ext/upbdefs-generated/envoy/config/rbac/v3/rbac.upbdefs.c
src/core/ext/upbdefs-generated/envoy/config/route/v3/route_components.upbdefs.c
src/core/ext/upbdefs-generated/src/proto/grpc/gcp/altscontext.upbdefs.c [deleted file]
src/core/ext/upbdefs-generated/src/proto/grpc/gcp/altscontext.upbdefs.h [deleted file]
src/core/ext/upbdefs-generated/src/proto/grpc/gcp/handshaker.upbdefs.c [deleted file]
src/core/ext/upbdefs-generated/src/proto/grpc/gcp/handshaker.upbdefs.h [deleted file]
src/core/ext/upbdefs-generated/src/proto/grpc/gcp/transport_security_common.upbdefs.c [deleted file]
src/core/ext/upbdefs-generated/src/proto/grpc/gcp/transport_security_common.upbdefs.h [deleted file]
src/core/ext/upbdefs-generated/src/proto/grpc/health/v1/health.upbdefs.c [deleted file]
src/core/ext/upbdefs-generated/src/proto/grpc/health/v1/health.upbdefs.h [deleted file]
src/core/ext/upbdefs-generated/src/proto/grpc/lb/v1/load_balancer.upbdefs.c [deleted file]
src/core/ext/upbdefs-generated/src/proto/grpc/lb/v1/load_balancer.upbdefs.h [deleted file]
src/core/ext/upbdefs-generated/udpa/annotations/migrate.upbdefs.c
src/core/ext/upbdefs-generated/udpa/annotations/security.upbdefs.c
src/core/ext/upbdefs-generated/udpa/annotations/sensitive.upbdefs.c
src/core/ext/upbdefs-generated/udpa/annotations/status.upbdefs.c
src/core/ext/upbdefs-generated/udpa/annotations/versioning.upbdefs.c
src/core/ext/upbdefs-generated/udpa/data/orca/v1/orca_load_report.upbdefs.c [deleted file]
src/core/ext/upbdefs-generated/udpa/data/orca/v1/orca_load_report.upbdefs.h [deleted file]
src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.c [deleted file]
src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.h [deleted file]
src/core/ext/upbdefs-generated/xds/annotations/v3/status.upbdefs.c [new file with mode: 0644]
src/core/ext/upbdefs-generated/xds/annotations/v3/status.upbdefs.h [new file with mode: 0644]
src/core/ext/upbdefs-generated/xds/core/v3/authority.upbdefs.c
src/core/ext/upbdefs-generated/xds/core/v3/collection_entry.upbdefs.c
src/core/ext/upbdefs-generated/xds/core/v3/context_params.upbdefs.c
src/core/ext/upbdefs-generated/xds/core/v3/resource.upbdefs.c
src/core/ext/upbdefs-generated/xds/core/v3/resource_locator.upbdefs.c
src/core/ext/upbdefs-generated/xds/core/v3/resource_name.upbdefs.c
src/core/ext/upbdefs-generated/xds/data/orca/v3/orca_load_report.upbdefs.c [new file with mode: 0644]
src/core/ext/upbdefs-generated/xds/data/orca/v3/orca_load_report.upbdefs.h [new file with mode: 0644]
src/core/ext/upbdefs-generated/xds/type/v3/typed_struct.upbdefs.c [new file with mode: 0644]
src/core/ext/upbdefs-generated/xds/type/v3/typed_struct.upbdefs.h [new file with mode: 0644]
src/core/ext/xds/xds_api.cc
src/core/ext/xds/xds_api.h
src/core/ext/xds/xds_bootstrap.h
src/core/ext/xds/xds_certificate_provider.cc
src/core/ext/xds/xds_channel_stack_modifier.cc [new file with mode: 0644]
src/core/ext/xds/xds_channel_stack_modifier.h [new file with mode: 0644]
src/core/ext/xds/xds_client.cc
src/core/ext/xds/xds_client.h
src/core/ext/xds/xds_client_stats.h
src/core/ext/xds/xds_server_config_fetcher.cc
src/core/lib/address_utils/parse_address.cc
src/core/lib/avl/avl.cc
src/core/lib/backoff/backoff.cc
src/core/lib/channel/channel_args.cc
src/core/lib/channel/channel_args.h
src/core/lib/channel/channel_stack_builder.cc
src/core/lib/channel/channel_trace.cc
src/core/lib/channel/channel_trace.h
src/core/lib/channel/channelz.cc
src/core/lib/channel/channelz.h
src/core/lib/channel/channelz_registry.cc
src/core/lib/channel/channelz_registry.h
src/core/lib/channel/connected_channel.cc
src/core/lib/channel/connected_channel.h
src/core/lib/compression/compression.cc
src/core/lib/compression/compression_args.cc
src/core/lib/compression/compression_internal.cc
src/core/lib/compression/compression_internal.h
src/core/lib/config/core_configuration.cc
src/core/lib/config/core_configuration.h
src/core/lib/debug/stats.cc
src/core/lib/debug/stats_data.cc
src/core/lib/event_engine/memory_allocator.cc [new file with mode: 0644]
src/core/lib/gpr/atm.cc
src/core/lib/gpr/cpu_posix.cc
src/core/lib/gpr/string.cc
src/core/lib/gpr/tls.h
src/core/lib/gpr/useful.h
src/core/lib/gprpp/arena.h
src/core/lib/gprpp/bitset.h
src/core/lib/gprpp/capture.h
src/core/lib/gprpp/chunked_vector.h [new file with mode: 0644]
src/core/lib/gprpp/construct_destruct.h
src/core/lib/gprpp/match.h
src/core/lib/gprpp/memory.h
src/core/lib/gprpp/overload.h
src/core/lib/gprpp/status_helper.cc
src/core/lib/gprpp/status_helper.h
src/core/lib/gprpp/table.h
src/core/lib/http/httpcli.cc
src/core/lib/http/parser.cc
src/core/lib/iomgr/call_combiner.cc
src/core/lib/iomgr/combiner.cc
src/core/lib/iomgr/endpoint_cfstream.cc
src/core/lib/iomgr/error.cc
src/core/lib/iomgr/error.h
src/core/lib/iomgr/error_cfstream.cc
src/core/lib/iomgr/ev_epoll1_linux.cc
src/core/lib/iomgr/ev_epollex_linux.cc
src/core/lib/iomgr/ev_poll_posix.cc
src/core/lib/iomgr/event_engine/closure.cc
src/core/lib/iomgr/event_engine/closure.h
src/core/lib/iomgr/event_engine/endpoint.cc
src/core/lib/iomgr/event_engine/iomgr.cc
src/core/lib/iomgr/event_engine/pollset.cc
src/core/lib/iomgr/event_engine/resolver.cc
src/core/lib/iomgr/event_engine/tcp.cc
src/core/lib/iomgr/event_engine/timer.cc
src/core/lib/iomgr/exec_ctx.cc
src/core/lib/iomgr/executor.cc
src/core/lib/iomgr/executor/mpmcqueue.cc
src/core/lib/iomgr/executor/mpmcqueue.h
src/core/lib/iomgr/iomgr.cc
src/core/lib/iomgr/iomgr_internal.cc
src/core/lib/iomgr/iomgr_internal.h
src/core/lib/iomgr/load_file.cc
src/core/lib/iomgr/lockfree_event.cc
src/core/lib/iomgr/pollset_custom.cc
src/core/lib/iomgr/pollset_custom.h
src/core/lib/iomgr/resolve_address_posix.cc
src/core/lib/iomgr/resource_quota.cc
src/core/lib/iomgr/socket_factory_posix.cc
src/core/lib/iomgr/socket_mutator.cc
src/core/lib/iomgr/socket_utils_common_posix.cc
src/core/lib/iomgr/tcp_client_cfstream.cc
src/core/lib/iomgr/tcp_client_custom.cc
src/core/lib/iomgr/tcp_client_posix.cc
src/core/lib/iomgr/tcp_client_windows.cc
src/core/lib/iomgr/tcp_posix.cc
src/core/lib/iomgr/tcp_server_custom.cc
src/core/lib/iomgr/tcp_server_posix.cc
src/core/lib/iomgr/tcp_server_windows.cc
src/core/lib/iomgr/tcp_windows.cc
src/core/lib/iomgr/timer_generic.cc
src/core/lib/iomgr/timer_heap.cc
src/core/lib/iomgr/udp_server.cc [deleted file]
src/core/lib/iomgr/udp_server.h [deleted file]
src/core/lib/json/json_util.cc
src/core/lib/json/json_util.h
src/core/lib/json/json_writer.cc
src/core/lib/promise/activity.cc
src/core/lib/promise/activity.h
src/core/lib/promise/context.h
src/core/lib/promise/detail/basic_join.h
src/core/lib/promise/detail/basic_seq.h
src/core/lib/promise/detail/promise_factory.h
src/core/lib/promise/detail/promise_like.h
src/core/lib/promise/detail/status.h
src/core/lib/promise/detail/switch.h
src/core/lib/promise/exec_ctx_wakeup_scheduler.h [new file with mode: 0644]
src/core/lib/promise/for_each.h
src/core/lib/promise/if.h
src/core/lib/promise/intra_activity_waiter.h
src/core/lib/promise/join.h
src/core/lib/promise/latch.h
src/core/lib/promise/loop.h
src/core/lib/promise/map.h
src/core/lib/promise/observable.h
src/core/lib/promise/pipe.h
src/core/lib/promise/poll.h
src/core/lib/promise/promise.h
src/core/lib/promise/race.h
src/core/lib/promise/seq.h
src/core/lib/promise/try_join.h
src/core/lib/promise/try_seq.h
src/core/lib/promise/wait_set.h
src/core/lib/resource_quota/memory_quota.cc [new file with mode: 0644]
src/core/lib/resource_quota/memory_quota.h [new file with mode: 0644]
src/core/lib/resource_quota/resource_quota.cc [new file with mode: 0644]
src/core/lib/resource_quota/resource_quota.h [new file with mode: 0644]
src/core/lib/resource_quota/thread_quota.cc [new file with mode: 0644]
src/core/lib/resource_quota/thread_quota.h [new file with mode: 0644]
src/core/lib/security/authorization/authorization_policy_provider.h
src/core/lib/security/authorization/authorization_policy_provider_vtable.cc
src/core/lib/security/authorization/evaluate_args.cc
src/core/lib/security/authorization/grpc_authorization_engine.h
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/matchers.cc
src/core/lib/security/authorization/sdk_server_authz_filter.cc
src/core/lib/security/context/security_context.cc
src/core/lib/security/credentials/composite/composite_credentials.cc
src/core/lib/security/credentials/credentials.cc
src/core/lib/security/credentials/credentials.h
src/core/lib/security/credentials/external/external_account_credentials.cc
src/core/lib/security/credentials/external/external_account_credentials.h
src/core/lib/security/credentials/google_default/google_default_credentials.cc
src/core/lib/security/credentials/jwt/jwt_verifier.cc
src/core/lib/security/credentials/plugin/plugin_credentials.cc
src/core/lib/security/security_connector/fake/fake_security_connector.cc
src/core/lib/security/security_connector/security_connector.cc
src/core/lib/security/security_connector/security_connector.h
src/core/lib/security/security_connector/ssl_utils.cc
src/core/lib/security/security_connector/tls/tls_security_connector.cc
src/core/lib/security/security_connector/tls/tls_security_connector.h
src/core/lib/security/transport/client_auth_filter.cc
src/core/lib/security/transport/security_handshaker.cc
src/core/lib/security/transport/server_auth_filter.cc
src/core/lib/security/transport/tsi_error.cc
src/core/lib/slice/slice.cc
src/core/lib/slice/slice_api.cc [new file with mode: 0644]
src/core/lib/slice/slice_buffer.cc
src/core/lib/slice/slice_intern.cc
src/core/lib/slice/slice_internal.h
src/core/lib/slice/slice_refcount.cc [new file with mode: 0644]
src/core/lib/slice/slice_refcount.h [new file with mode: 0644]
src/core/lib/slice/slice_refcount_base.h [new file with mode: 0644]
src/core/lib/slice/slice_split.cc [new file with mode: 0644]
src/core/lib/slice/slice_split.h [new file with mode: 0644]
src/core/lib/slice/slice_string_helpers.cc
src/core/lib/slice/slice_string_helpers.h
src/core/lib/slice/static_slice.cc [new file with mode: 0644]
src/core/lib/slice/static_slice.h [new file with mode: 0644]
src/core/lib/surface/builtins.cc [new file with mode: 0644]
src/core/lib/surface/builtins.h [new file with mode: 0644]
src/core/lib/surface/call.cc
src/core/lib/surface/call.h
src/core/lib/surface/channel.cc
src/core/lib/surface/channel.h
src/core/lib/surface/channel_init.cc
src/core/lib/surface/channel_init.h
src/core/lib/surface/completion_queue.cc
src/core/lib/surface/init.cc
src/core/lib/surface/init_secure.cc
src/core/lib/surface/lame_client.cc
src/core/lib/surface/lame_client.h
src/core/lib/surface/server.cc
src/core/lib/surface/server.h
src/core/lib/surface/validate_metadata.cc
src/core/lib/surface/version.cc
src/core/lib/transport/authority_override.cc [deleted file]
src/core/lib/transport/authority_override.h [deleted file]
src/core/lib/transport/bdp_estimator.cc
src/core/lib/transport/error_utils.cc
src/core/lib/transport/error_utils.h
src/core/lib/transport/metadata.cc
src/core/lib/transport/metadata.h
src/core/lib/transport/metadata_batch.cc
src/core/lib/transport/metadata_batch.h
src/core/lib/transport/parsed_metadata.h [new file with mode: 0644]
src/core/lib/transport/pid_controller.cc
src/core/lib/transport/static_metadata.cc
src/core/lib/transport/static_metadata.h
src/core/lib/transport/status_metadata.cc
src/core/lib/transport/transport.cc
src/core/lib/transport/transport_op_string.cc
src/core/plugin_registry/grpc_plugin_registry.cc
src/core/plugin_registry/grpc_unsecure_plugin_registry.cc
src/core/tsi/alts/crypt/aes_gcm.cc
src/core/tsi/alts/frame_protector/alts_frame_protector.cc
src/core/tsi/alts/frame_protector/frame_handler.cc
src/core/tsi/alts/handshaker/alts_handshaker_client.cc
src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc
src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.cc
src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.cc
src/core/tsi/fake_transport_security.cc
src/core/tsi/local_transport_security.cc
src/core/tsi/ssl/session_cache/ssl_session_cache.cc
src/core/tsi/ssl/session_cache/ssl_session_cache.h
src/core/tsi/ssl_transport_security.cc
src/core/tsi/test_creds/BUILD
src/core/tsi/transport_security.cc
src/core/tsi/transport_security.h
src/core/tsi/transport_security_interface.h
src/cpp/Protobuf-C++.podspec [deleted file]
src/cpp/README.md
src/cpp/client/secure_credentials.cc
src/cpp/common/channel_filter.cc
src/cpp/common/channel_filter.h
src/cpp/common/completion_queue_cc.cc
src/cpp/common/core_codegen.cc
src/cpp/common/validate_service_config.cc
src/cpp/common/version_cc.cc
src/cpp/ext/filters/census/client_filter.cc
src/cpp/ext/filters/census/client_filter.h
src/cpp/ext/filters/census/open_census_call_tracer.h
src/cpp/ext/filters/census/server_filter.cc
src/cpp/server/authorization_policy_provider.cc
src/cpp/server/load_reporter/get_cpu_stats_linux.cc
src/cpp/server/server_builder.cc
src/cpp/server/server_context.cc
src/csharp/Grpc.Core.Api/Metadata.cs
src/csharp/Grpc.Core.Api/VersionInfo.cs
src/csharp/Grpc.Core.Tests/MetadataTest.cs
src/csharp/Grpc.Core.Xamarin/build/Xamarin.iOS10/Grpc.Core.Xamarin.targets
src/csharp/build/dependencies.props
src/objective-c/!ProtoCompiler-gRPCCppPlugin.podspec
src/objective-c/!ProtoCompiler-gRPCPlugin.podspec
src/objective-c/!ProtoCompiler.podspec
src/objective-c/BoringSSL-GRPC.podspec
src/objective-c/GRPCClient/GRPCCallOptions.h
src/objective-c/GRPCClient/GRPCCallOptions.m
src/objective-c/GRPCClient/version.h
src/objective-c/Libuv-gRPC.podspec [new file with mode: 0644]
src/objective-c/examples/BUILD
src/objective-c/examples/InterceptorSample/Podfile
src/objective-c/examples/RemoteTestClient/RemoteTest.podspec
src/objective-c/examples/Sample/Podfile
src/objective-c/examples/SwiftSample/Podfile
src/objective-c/examples/tvOS-sample/Podfile
src/objective-c/examples/watchOS-sample/Podfile
src/objective-c/manual_tests/Podfile
src/objective-c/tests/BUILD
src/objective-c/tests/Connectivity/Podfile
src/objective-c/tests/CoreTests/CoreTests.xcodeproj/project.pbxproj [new file with mode: 0644]
src/objective-c/tests/CoreTests/CoreTests/EventEngineTimerTests.mm [new file with mode: 0644]
src/objective-c/tests/CoreTests/Podfile [new file with mode: 0644]
src/objective-c/tests/InteropTests/InteropTests.m
src/objective-c/tests/Podfile
src/objective-c/tests/Tests.xcodeproj/project.pbxproj
src/objective-c/tests/UnitTests/GRPCClientTests.m
src/objective-c/tests/build_tests.sh
src/objective-c/tests/run_one_test.sh
src/objective-c/tests/version.h
src/php/composer.json
src/php/docker/grpc-ext/Dockerfile
src/php/docker/grpc-src/Dockerfile
src/php/docker/i386/Dockerfile
src/php/docker/php-future/Dockerfile
src/php/docker/php-src/Dockerfile
src/php/docker/php-zts/Dockerfile
src/php/docker/php8/Dockerfile
src/php/ext/grpc/channel_credentials.c
src/php/ext/grpc/version.h
src/php/tests/generated_code/AbstractGeneratedCodeTest.php
src/php/tests/generated_code/GeneratedCodeTest.php
src/php/tests/generated_code/GeneratedCodeWithCallbackTest.php
src/php/tests/generated_code/math_server.php
src/proto/grpc/channelz/BUILD
src/proto/grpc/core/BUILD
src/proto/grpc/gcp/BUILD
src/proto/grpc/health/v1/BUILD
src/proto/grpc/http_over_grpc/BUILD
src/proto/grpc/lb/v1/BUILD
src/proto/grpc/lookup/v1/BUILD [new file with mode: 0644]
src/proto/grpc/lookup/v1/rls.proto [new file with mode: 0644]
src/proto/grpc/reflection/v1alpha/BUILD
src/proto/grpc/status/BUILD
src/proto/grpc/testing/BUILD
src/proto/grpc/testing/duplicate/BUILD
src/proto/grpc/testing/xds/BUILD
src/proto/grpc/testing/xds/orca_load_report_for_test.proto [deleted file]
src/proto/grpc/testing/xds/v3/BUILD
src/proto/grpc/testing/xds/v3/csds.proto
src/proto/grpc/testing/xds/v3/orca_load_report.proto
src/proto/grpc/testing/xds/v3/route.proto
src/python/grpcio/grpc/_cython/_cygrpc/aio/common.pyx.pxi
src/python/grpcio/grpc/_cython/_cygrpc/aio/server.pxd.pxi
src/python/grpcio/grpc/_cython/_cygrpc/aio/server.pyx.pxi
src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi
src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
src/python/grpcio/grpc/_cython/_cygrpc/grpc_gevent.pyx.pxi
src/python/grpcio/grpc/_cython/_cygrpc/iomgr.pxd.pxi
src/python/grpcio/grpc/_grpcio_metadata.py
src/python/grpcio/grpc/aio/_base_channel.py
src/python/grpcio/grpc/aio/_base_server.py
src/python/grpcio/grpc/aio/_call.py
src/python/grpcio/grpc/aio/_channel.py
src/python/grpcio/grpc/aio/_interceptor.py
src/python/grpcio/grpc/aio/_typing.py
src/python/grpcio/grpc_core_dependencies.py
src/python/grpcio/grpc_version.py
src/python/grpcio_admin/grpc_version.py
src/python/grpcio_admin/setup.py
src/python/grpcio_channelz/grpc_channelz/v1/BUILD.bazel
src/python/grpcio_channelz/grpc_version.py
src/python/grpcio_channelz/setup.py
src/python/grpcio_csds/grpc_version.py
src/python/grpcio_csds/setup.py
src/python/grpcio_health_checking/grpc_health/v1/BUILD.bazel
src/python/grpcio_health_checking/grpc_version.py
src/python/grpcio_health_checking/setup.py
src/python/grpcio_reflection/grpc_reflection/v1alpha/BUILD.bazel
src/python/grpcio_reflection/grpc_version.py
src/python/grpcio_reflection/setup.py
src/python/grpcio_status/grpc_version.py
src/python/grpcio_status/setup.py
src/python/grpcio_testing/grpc_version.py
src/python/grpcio_tests/grpc_version.py
src/python/grpcio_tests/tests/admin/BUILD.bazel
src/python/grpcio_tests/tests/admin/test_admin.py
src/python/grpcio_tests/tests/channelz/BUILD.bazel
src/python/grpcio_tests/tests/channelz/_channelz_servicer_test.py
src/python/grpcio_tests/tests/csds/BUILD.bazel
src/python/grpcio_tests/tests/csds/test_csds.py
src/python/grpcio_tests/tests/health_check/BUILD.bazel
src/python/grpcio_tests/tests/health_check/_health_servicer_test.py
src/python/grpcio_tests/tests/interop/BUILD.bazel
src/python/grpcio_tests/tests/interop/_insecure_intraop_test.py
src/python/grpcio_tests/tests/interop/_secure_intraop_test.py
src/python/grpcio_tests/tests/reflection/BUILD.bazel
src/python/grpcio_tests/tests/reflection/_reflection_servicer_test.py
src/python/grpcio_tests/tests/status/BUILD.bazel
src/python/grpcio_tests/tests/status/_grpc_status_test.py
src/python/grpcio_tests/tests/unit/BUILD.bazel
src/python/grpcio_tests/tests/unit/_compression_test.py
src/python/grpcio_tests/tests/unit/_contextvars_propagation_test.py
src/python/grpcio_tests/tests/unit/_dynamic_stubs_test.py
src/python/grpcio_tests/tests/unit/_local_credentials_test.py
src/python/grpcio_tests/tests/unit/_metadata_code_details_test.py
src/python/grpcio_tests/tests/unit/_reconnect_test.py
src/python/grpcio_tests/tests/unit/_rpc_part_1_test.py
src/python/grpcio_tests/tests/unit/_rpc_part_2_test.py
src/python/grpcio_tests/tests/unit/test_common.py
src/python/grpcio_tests/tests_aio/tests.json
src/python/grpcio_tests/tests_aio/unit/_constants.py
src/python/grpcio_tests/tests_aio/unit/compatibility_test.py
src/python/grpcio_tests/tests_aio/unit/done_callback_test.py
src/python/grpcio_tests/tests_aio/unit/server_test.py
src/ruby/ext/grpc/extconf.rb
src/ruby/ext/grpc/rb_grpc_imports.generated.c
src/ruby/ext/grpc/rb_grpc_imports.generated.h
src/ruby/lib/grpc/version.rb
src/ruby/pb/src/proto/grpc/testing/test_pb.rb
src/ruby/qps/src/proto/grpc/testing/benchmark_service_pb.rb
src/ruby/qps/src/proto/grpc/testing/control_pb.rb
src/ruby/qps/src/proto/grpc/testing/report_qps_scenario_service_pb.rb
src/ruby/qps/src/proto/grpc/testing/stats_pb.rb
src/ruby/qps/src/proto/grpc/testing/worker_service_pb.rb
src/ruby/spec/client_server_spec.rb
src/ruby/tools/version.rb
templates/CMakeLists.txt.template
templates/Makefile.template
templates/gRPC-C++.podspec.template
templates/gRPC-Core.podspec.template
templates/grpc.gemspec.template
templates/src/objective-c/!ProtoCompiler-gRPCCppPlugin.podspec.template
templates/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec.template
templates/src/objective-c/!ProtoCompiler.podspec.template
templates/src/objective-c/BoringSSL-GRPC.podspec.template
templates/src/objective-c/Libuv-gRPC.podspec.template [new file with mode: 0644]
templates/src/php/docker/grpc-ext/Dockerfile.template
templates/src/php/docker/grpc-src/Dockerfile.template
templates/src/php/docker/i386/Dockerfile.template
templates/src/php/docker/php-future/Dockerfile.template
templates/src/php/docker/php-src/Dockerfile.template
templates/src/php/docker/php-zts/Dockerfile.template
templates/src/php/docker/php8/Dockerfile.template
templates/src/ruby/ext/grpc/extconf.rb.template
templates/tools/dockerfile/bazel.include
templates/tools/dockerfile/interoptest/grpc_interop_php7/Dockerfile.template
templates/tools/dockerfile/libuv_install.include [deleted file]
templates/tools/dockerfile/php7_deps.include
templates/tools/dockerfile/test/cxx_clang_12_x64/Dockerfile.template [new file with mode: 0644]
templates/tools/dockerfile/test/cxx_clang_4_x64/Dockerfile.template [new file with mode: 0644]
templates/tools/dockerfile/test/cxx_gcc_11_x64/Dockerfile.template [new file with mode: 0644]
templates/tools/dockerfile/test/cxx_jessie_x64/Dockerfile.template
templates/tools/dockerfile/test/cxx_ubuntu1804_x64/Dockerfile.template [deleted file]
templates/tools/dockerfile/test/php7_debian9_x64/Dockerfile.template [new file with mode: 0644]
templates/tools/dockerfile/test/php7_jessie_x64/Dockerfile.template [deleted file]
templates/tools/fuzzer/runners.template [deleted file]
test/core/avl/BUILD
test/core/backoff/BUILD
test/core/bad_client/BUILD
test/core/bad_client/bad_client.cc
test/core/bad_client/tests/bad_streaming_id.cc
test/core/bad_client/tests/head_of_line_blocking.cc
test/core/bad_client/tests/out_of_bounds.cc
test/core/bad_client/tests/unknown_frame.cc
test/core/bad_client/tests/window_overflow.cc
test/core/bad_connection/BUILD
test/core/bad_connection/close_fd_test.cc
test/core/bad_ssl/BUILD
test/core/channel/BUILD
test/core/channel/channel_args_test.cc
test/core/channel/channel_stack_builder_test.cc
test/core/channel/channel_stack_test.cc
test/core/channel/minimal_stack_is_minimal_test.cc
test/core/client_channel/BUILD
test/core/client_channel/resolvers/BUILD
test/core/client_channel/resolvers/binder_resolver_test.cc [new file with mode: 0644]
test/core/client_channel/rls_lb_config_parser_test.cc [new file with mode: 0644]
test/core/client_channel/service_config_test.cc
test/core/client_idle/BUILD [new file with mode: 0644]
test/core/client_idle/idle_filter_state_test.cc [new file with mode: 0644]
test/core/compression/BUILD
test/core/compression/compression_test.cc
test/core/debug/BUILD
test/core/end2end/BUILD
test/core/end2end/end2end_nosec_tests.cc
test/core/end2end/end2end_tests.cc
test/core/end2end/fixtures/h2_full+workarounds.cc [deleted file]
test/core/end2end/fixtures/h2_http_proxy.cc
test/core/end2end/fixtures/http_proxy_fixture.cc
test/core/end2end/fixtures/proxy.cc
test/core/end2end/fuzzers/BUILD
test/core/end2end/fuzzers/api_fuzzer.cc [new file with mode: 0644]
test/core/end2end/fuzzers/api_fuzzer.dictionary [new file with mode: 0644]
test/core/end2end/fuzzers/api_fuzzer.proto [new file with mode: 0644]
test/core/end2end/fuzzers/api_fuzzer_corpus/0 [new file with mode: 0644]
test/core/end2end/fuzzers/api_fuzzer_corpus/channelz-crash [new file with mode: 0644]
test/core/end2end/fuzzers/api_fuzzer_corpus/crash-on-unknown-compression-algorithm [new file with mode: 0644]
test/core/end2end/fuzzers/api_fuzzer_corpus/create_connection.textproto [new file with mode: 0644]
test/core/end2end/fuzzers/api_fuzzer_corpus/get-leak [new file with mode: 0644]
test/core/end2end/fuzzers/api_fuzzer_corpus/shifty-mcshifter [new file with mode: 0644]
test/core/end2end/fuzzers/api_fuzzer_corpus/testcase-4953856886308864 [new file with mode: 0644]
test/core/end2end/fuzzers/api_fuzzer_corpus/testcase-5212802075197440 [new file with mode: 0644]
test/core/end2end/fuzzers/api_fuzzer_corpus/testcase-6703968097271808 [new file with mode: 0644]
test/core/end2end/fuzzers/api_fuzzer_corpus/validator-fail [new file with mode: 0644]
test/core/end2end/fuzzers/hpack.dictionary
test/core/end2end/fuzzers/server_fuzzer.cc
test/core/end2end/generate_tests.bzl
test/core/end2end/goaway_server_test.cc
test/core/end2end/inproc_callback_test.cc
test/core/end2end/tests/cancel_test_helpers.h
test/core/end2end/tests/compressed_payload.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/retry_cancel_with_multiple_send_batches.cc
test/core/end2end/tests/retry_recv_trailing_metadata_error.cc
test/core/end2end/tests/retry_send_op_fails.cc
test/core/end2end/tests/sdk_authz.cc
test/core/end2end/tests/simple_request.cc
test/core/end2end/tests/stream_compression_compressed_payload.cc
test/core/end2end/tests/workaround_cronet_compression.cc [deleted file]
test/core/event_engine/BUILD
test/core/event_engine/test_suite/README.md [new file with mode: 0644]
test/core/event_engine/test_suite/event_engine_test.cc [new file with mode: 0644]
test/core/event_engine/test_suite/event_engine_test.h [new file with mode: 0644]
test/core/event_engine/test_suite/timer_test.cc [new file with mode: 0644]
test/core/fling/BUILD
test/core/gpr/BUILD
test/core/gpr/useful_test.cc
test/core/gprpp/BUILD
test/core/gprpp/bitset_test.cc
test/core/gprpp/chunked_vector_corpora/crash-a0868ce3a0f76feefcc715148ed9e71fa0738c2a [new file with mode: 0644]
test/core/gprpp/chunked_vector_corpora/testcase-5405829431427072 [new file with mode: 0644]
test/core/gprpp/chunked_vector_fuzzer.cc [new file with mode: 0644]
test/core/gprpp/chunked_vector_fuzzer.proto [new file with mode: 0644]
test/core/gprpp/chunked_vector_test.cc [new file with mode: 0644]
test/core/gprpp/status_helper_test.cc
test/core/gprpp/table_test.cc
test/core/handshake/BUILD
test/core/http/BUILD
test/core/iomgr/BUILD
test/core/iomgr/endpoint_tests.cc
test/core/iomgr/error_test.cc
test/core/iomgr/ios/CFStreamTests/CFStreamEndpointTests.mm
test/core/iomgr/ios/CFStreamTests/Podfile
test/core/iomgr/ios/CFStreamTests/build_tests.sh
test/core/iomgr/mpmcqueue_test.cc
test/core/iomgr/socket_utils_test.cc
test/core/iomgr/tcp_posix_test.cc
test/core/iomgr/tcp_server_posix_test.cc
test/core/iomgr/timer_heap_test.cc
test/core/iomgr/timer_list_test.cc
test/core/iomgr/udp_server_test.cc [deleted file]
test/core/iomgr/work_serializer_test.cc
test/core/json/BUILD
test/core/nanopb/BUILD
test/core/network_benchmarks/BUILD
test/core/promise/BUILD
test/core/promise/activity_test.cc
test/core/promise/benchmark/BUILD [new file with mode: 0644]
test/core/promise/benchmark/competition.cc [new file with mode: 0644]
test/core/promise/benchmark/filter_stack.cc [new file with mode: 0644]
test/core/promise/benchmark/filter_stack.h [new file with mode: 0644]
test/core/promise/exec_ctx_wakeup_scheduler_test.cc [new file with mode: 0644]
test/core/promise/for_each_test.cc
test/core/promise/latch_test.cc
test/core/promise/loop_test.cc
test/core/promise/observable_test.cc
test/core/promise/pipe_test.cc
test/core/promise/promise_fuzzer.cc [new file with mode: 0644]
test/core/promise/promise_fuzzer.proto [new file with mode: 0644]
test/core/promise/promise_fuzzer_corpus/b858cb282617fb0956d960215c8e84d1ccf909c6 [new file with mode: 0644]
test/core/promise/promise_fuzzer_corpus/crash-4758aec0c3e382d4fb3e398d634d8da72ed0d574 [new file with mode: 0644]
test/core/promise/promise_fuzzer_corpus/leak-90b749c0ca79c7a11d25f4b6f0594af99fe4a78f [new file with mode: 0644]
test/core/promise/test_wakeup_schedulers.h [new file with mode: 0644]
test/core/resource_quota/BUILD [new file with mode: 0644]
test/core/resource_quota/call_checker.h [new file with mode: 0644]
test/core/resource_quota/memory_quota_fuzzer.cc [new file with mode: 0644]
test/core/resource_quota/memory_quota_fuzzer.proto [new file with mode: 0644]
test/core/resource_quota/memory_quota_fuzzer_corpus/0 [new file with mode: 0644]
test/core/resource_quota/memory_quota_fuzzer_corpus/nullchk [new file with mode: 0644]
test/core/resource_quota/memory_quota_fuzzer_corpus/testcase-4574576847224832 [new file with mode: 0644]
test/core/resource_quota/memory_quota_fuzzer_corpus/testcase-4574576847224832-after-creduce [new file with mode: 0644]
test/core/resource_quota/memory_quota_fuzzer_corpus/testcase-5651890842501120 [new file with mode: 0644]
test/core/resource_quota/memory_quota_fuzzer_corpus/testcase-replenish-nullchk [new file with mode: 0644]
test/core/resource_quota/memory_quota_fuzzer_corpus/testcase-replenish-nullchk-after-creduce [new file with mode: 0644]
test/core/resource_quota/memory_quota_stress_test.cc [new file with mode: 0644]
test/core/resource_quota/memory_quota_test.cc [new file with mode: 0644]
test/core/resource_quota/resource_quota_test.cc [new file with mode: 0644]
test/core/resource_quota/thread_quota_test.cc [new file with mode: 0644]
test/core/security/BUILD
test/core/security/authorization/test_policies/BUILD [new file with mode: 0644]
test/core/security/authorization/test_policies/invalid_policy.json [new file with mode: 0644]
test/core/security/authorization/test_policies/valid_policy_1.json [new file with mode: 0644]
test/core/security/authorization/test_policies/valid_policy_2.json [new file with mode: 0644]
test/core/security/authorization_matchers_test.cc
test/core/security/aws_request_signer_test.cc
test/core/security/credentials_test.cc
test/core/security/etc/BUILD
test/core/security/grpc_authorization_policy_provider_test.cc
test/core/security/grpc_tls_certificate_distributor_test.cc
test/core/security/grpc_tls_certificate_provider_test.cc
test/core/security/tls_security_connector_test.cc
test/core/server_config_selector/BUILD [new file with mode: 0644]
test/core/server_config_selector/server_config_selector_test.cc [new file with mode: 0644]
test/core/slice/BUILD
test/core/slice/slice_intern_test.cc [new file with mode: 0644]
test/core/slice/slice_split_test.cc [new file with mode: 0644]
test/core/slice/slice_string_helpers_test.cc
test/core/slice/slice_test.cc
test/core/surface/BUILD
test/core/surface/lame_client_test.cc
test/core/surface/public_headers_must_be_c89.c
test/core/surface/secure_channel_create_test.cc
test/core/transport/BUILD
test/core/transport/bdp_estimator_test.cc
test/core/transport/binder/BUILD
test/core/transport/binder/binder_transport_test.cc
test/core/transport/binder/end2end/BUILD
test/core/transport/binder/end2end/binder_server_test.cc
test/core/transport/binder/end2end/echo.proto [deleted file]
test/core/transport/binder/end2end/echo_service.cc [deleted file]
test/core/transport/binder/end2end/echo_service.h [deleted file]
test/core/transport/binder/end2end/end2end_binder_transport_test.cc
test/core/transport/binder/end2end/fake_binder.cc
test/core/transport/binder/end2end/fake_binder.h
test/core/transport/binder/end2end/fake_binder_test.cc
test/core/transport/binder/end2end/testing_channel_create.cc
test/core/transport/binder/endpoint_binder_pool_test.cc [new file with mode: 0644]
test/core/transport/binder/mock_objects.cc
test/core/transport/binder/mock_objects.h
test/core/transport/binder/wire_reader_test.cc
test/core/transport/chttp2/BUILD
test/core/transport/chttp2/hpack_encoder_test.cc
test/core/transport/chttp2/hpack_parser_corpus/0141fcddc9807ee093313b2256f1306fbbdc6cda [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/0255050a9ccb25f46d6c1bf6a5a8a4c0c7635599 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/0320a995a8c76c64c8a0e0297f632b76d9bc92d6 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/042091aeac4cc255506b96fa11c7354e699fde76 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/051268ade45dbed0aab896d7d9f4d10ba89d3b09 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/0696e7bf7837d98de01c915d3c9d80e5d21b30d2 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/06995c2f3f01c7ec50547415dc324c64030b7a3e [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/06f7ce769fe07804fc842462d4be8c1aa2ba82c2 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/0781b055c85ab8fbd0a3d0080a32e394af8761c4 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/080e1f19e6061c5bcac31add2095f87f6ce46129 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/0828169ba82152a8907f1001e3d98804397d4610 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/08ffc4a4160e9fe6f322c28870a89a41fd9c37d7 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/090a7a758898a6e7c9108b7e8a1cb9cda383e707 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/0940663729501b750a18542e1041cc26385c6148 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/0a10bd140c6c5fb109a0816ca061739688a6db9a [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/0a4d3fda02cdcb7adad1daa80d65780c9c8d1464 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/0ad812832efa33e086874fbf3496664d3f1b4dbe [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/0c9996d4fef87bacd7a001e99a515b3ba3d5788f [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/0d6210208831fe55951af56cdeee3d54a91a5361 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/0d784965b2262df7ed7a1eb57b92a718cc76bde8 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/0dc9e41eedf35ccedf4e2b0d230ead7c4d72fdb2 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/0dd470c8939ed535de6b36f7b7bfb68aeace493e [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/0e61e471fa6d3405daef4276ee00cf5fc189f378 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/0e9196f951874edbb5ed098739ea5c8b6c0751c2 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/11442d93a554b9e7f9ab02782bbf9443bf6e1ddc [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/11833b795d04eda5a3af56ef7b3c3a26a8ee3444 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/141272316382b0f3e9ec841c735b84e7aa517c3e [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/15ae43369798e48c396dfe7d53a21878b96e66c8 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/166bf1843c229d34a2880d234dd166c27bdc11fd [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/179e8ac763b4051a953a38b6b3b1f1e1f6cc6c9e [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/17faf0ba8a491a835d35977a9007b90ab7d30d2a [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/188f6cf2470e95b228341de305ef839b27f01a5c [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/1ab3e52adace335d02e2b5130eb4f7c918add7fd [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/1b5150514364e2c17f5a4edac1b7af99b936f55a [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/1e8befb98cbaba059d6771abd1680e19484e7723 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/1e9b962969c359bc2ff766704c8ca8e25f5eccfc [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/1f80af104acf41b912bf4a48fb938267e3718719 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/1fcc4afd6f48e83d61ea74970df3ca9dcd8ec291 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/213a734ccdb813b18ad9f2dd99b7f9967ee1460b [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/2151945f43991c27e123c45dc72b93752a47e65f [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/21545d998c27a5a1572a89a552937752432b1c14 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/23c7443fa1ab713e7c34ec50222b1b8cceaedc65 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/2445bb2c6779712dc9e14c01fecb7103f8732858 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/244b0a20500e31d3c538418800db816b07f4d210 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/2461b9fa6b5bc4b6424dec5b9a18d4ec7c309112 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/24ec2f3e17d3850564788f3fed17a5c586c44658 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/2537b8d6b902b8dfc6e17f194cf7d05ddecf74cf [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/253ad01acea4b7038edc3f2a8c4a0c0f5c4dcd05 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/256d0bbdbed22f5867a6f503bf082011e61ee12b [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/26f0e88adbd8f8cdf778131a35b33ecf8711fa49 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/2e5dd8fb9d2a31fad9d681eda697d085b647b57c [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/2fdfd2abf30c636ec8c841f1ac26594e25664f0f [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/311dac5092e36134d3490f98aa4207425e0ee941 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/320fe6224a5b691c0425e34b6b14e8c6fe9f9620 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/3255f1c7441a7150dc3c33022bfbe8c956c7b7b1 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/33bc9db104eb72891fb096f34cbac191b3f9918d [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/342ff1db70a7616b4ef76c03a42802c6702c18cb [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/344c011df992ccfc0ec682c14a1cb2d7959998c7 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/35775efb9d0d68fa07987b9a84934389b528e436 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/3650168db6fe115fb1e73eed4b76cd224d977d01 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/38228bf98cdb50fd3fa830ba5a9d4c7399063dff [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/38717bee901151b22a10beb12c6623ccc844d3c2 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/3a4bb427a85bdc5bf66ac71db073c99e0dc9f881 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/3ab48621d9b8f075369099a8ec7517bd23fd6e70 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/3aec8d9311130dfbb6584fe6e619579c21992b5f [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/3b14837f22905dcb04f93aed2aa69bf95924fb9d [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/3be63c163805927e04fd7f84d96122c48240e601 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/3bf2e349747c0f539181e0d4084a5fe506811a9e [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/3c5af4d73e94d0e8ad5666b6acb340f929031e95 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/3d2b25346a9671d83bd082d170a45eed739bae6b [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/3de7b860c3fba2bc55707fd6875dce276f2f249b [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/3e2004ff9f40e398e0f41138a25a8b66e3d843d9 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/3f8983e457033cc85997c356935ba9c21460e86b [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/4105669086d83a20f8d991088553ba08202478cd [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/4180619316eef7912d1cf52ffe85897242e1ae88 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/420291d7139d9246de747739fd98102434a742dd [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/4256437fc5897c0cd5d755816e4e68c7be326849 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/42b25a5413c536478a3e63da5adef4250babf2f4 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/42bef44ae751a45c671d9da5b1231d2ac747a48d [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/438c3c9045c3cf7910aceec34f77b47a70ca4abd [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/43af96b4f65ed0ace7236427f2f8833c4835989e [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/44c6119bb91a452d6128ce0ea0d62938800779ea [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/46d595331689ae01d77aff387747a98ff3480096 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/471a307b81dc37459087d41532741c5c9d7ba836 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/48900b4a5557530922ce45c15ad0d3b0a337520d [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/48bcce2c6487b18706ef0c609ca39c456215bac8 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/49027bbd3f3f3cafa315843c8fe8280f86985273 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/499376c5e291da2f9c25999abf4960fab5a92ec8 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/4a3b7ce0cdf217963a0b692769e5d6f4befe73b8 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/4a3fdb96bc8c80f1992f0f72f963f84856cbade8 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/4aae80e05793d7adb42a7e6e8a5283b677318777 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/4c7a034d3a3b4f29d99caf021a0e9bbb89706c2e [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/4ce8a43fb17a075627160812ad26c25210d8a82d [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/5032a75a98cd14d4dab75c1c5e2cd981abb19dcf [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/50b3f4b6aed97f442496d27f3b4315a18ba76d5f [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/51064b88a98658d48a0da7f1545c2d1293ad9538 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/51752f12d59fadaaa0dc72e6370612b84ee1555b [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/51eff6fcbfe1a51ceb3f5f2140c01eea89b4313d [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/51f65f681cf3a1218d83ad58642c06deaea86210 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/521809903d36db80b1ccd707f354361f2bf05075 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/5278e3581c069624157fd9176eddf52c0e58df67 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/52fe8f0e1fa270ea16f66c93f2ffab265ce059e8 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/53de87ae94acdc8e58a369459c12a3240f1294fe [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/54a2b3993c3483745f6314c870a038a8e58f97a7 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/55d60c2e5040a38be8ca41de63e137e3fef892a4 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/5653c44a5b520bdf2bdc599b7966f1d7c44950b3 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/5838b5a683229ebb6e6277e2810863e642b8afc2 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/588d225784891ac88e30ac6eb5651d63fac34083 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/58d51c21a20b6549567a0ab8fee29d162dd3fc5a [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/58f1036d8ff855841ec25b3c33e85a8fec0d94b7 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/5a99df42fb7bbafa2d55714ee235b1c46776b2ad [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/5b42793550699b2c015bed677cfcddc052f73513 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/5b8ca72ba00231c38b19f582127e6a146eba4282 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/5baa13dc95da05e7ba02bbe9583ea24517a29a1a [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/5bab61eb53176449e25c2c82f172b82cb13ffb9d [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/5c6f6b6f7f3e7b435f060abb73c20d2b773a7f56 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/5c9fd9cc7100feaeead1e0e45201945a6e76fd85 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/5ff49c9edc7361797a951585f3e180222c8dd95d [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/6129954942e26c2a9ec071b6659675745613cf3c [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/61fa69b6b51b0ed91914fe48779173f8d26a1d54 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/6362ac61cfb6e964aff78f3cd648475dfd5fd4e9 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/644deba51c79b6ebd470bd4367452941045d112a [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/64beae98e2276749b133e6368c9e0f19a79eba96 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/64d7add9192301fd878854dc96f9fa9053f03992 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/65566df65e8f55428b6672cc351df414fa8f936c [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/65bb703af35d5afb824cd68c41d7a1aeb3848d35 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/66c537bf59cb3667c037b3517be3d31245c9da8a [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/66f576baeb0c9435a56eb7375dadc5b5d630ed87 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/67b4cec5183659aeae0f5bc71b3adf0542a11828 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/68c94721eda2f62481bff9f1d183df70498d0c5b [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/68ee8169a65d58edb9fc1c752ea81dfec383203c [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/6b203d49bbba6ee74def0d35c2266e06ad3c45d9 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/6d580f28d785c0bf87ac351a31a89289449feadb [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/6f231dec759eb2105e09263d53e171de19a92c74 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/70ff6621a09e4f641538cb1b27e8b382b2f56a94 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/71981b55f27a1eb6274eda247048fa2c597f5004 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/71c2b0bebf7f0e916e4ab7eb36d47ccca2b9101c [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/74610e278a5b90aa12ce1beaf222c4306b02ed43 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/748ee9817eba56ec9938601a0e380c74bad4563f [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/7727e3eeb2a48c46bf5a678c300ff8a38b8ffe3a [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/78176d80c1d74c4b1b820d386ae483ac4d1d92b7 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/789abb571563a6795220046f76b7cf0ade90743c [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/78f5ff40e5554aa9c31b45f79a7ae9699f93e7fd [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/7a28fc2e9c72d51d29e87eed63ed405c9779b5e1 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/7a42083be21dce7f96edef1f3b3b2fea0bcaeb3f [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/7a51275b11ecb1efec9251390531681c8d6f2481 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/7b9682cd7a3984698f6eac034c59c0f91b4fb83d [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/7ba7239a29d6183960e3986abc8f19cfb548b905 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/7d3b3d5f23d0ede9f7e5dbd1115db58c8a54a213 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/7ff3b6239b04479a9caf67f45b2d0c619f712815 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/8035c81c95dedfc27c3649064f98f49e3e72c21f [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/804e1052842ce4d44b9c775ade2b18fcb8ce7bcf [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/80514b85933ea9bdd3462595f949c5af24409b87 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/8057c32b8bd28a5ec2105d62f2abe8cf69c9f5fc [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/806a3bd4e078d91adeacedfd3e47ef8ae229244a [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/8090444f98218e65ff9594789ff22bbea3c0497c [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/80e516692955d5f224706f268e247858858e16d8 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/810a1372fa97380265f5529c5043ae96f007f5bb [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/8127597d3c146b2a89579e44daef9d03a0f941ec [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/82ed571f8922caa572d13b4cc9b5c5fabafaade9 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/8328e86178800f87a3bf6f80749984f45b0cd0e8 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/84441efd7d8bdb0ce2fac28f218d3d5d4d77f1d4 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/84cbf70f45a64d5a01d1c96367b6d6160134f1ad [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/85eb0f4502a51e646dab4ae08eabd90613cdf8e1 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/86080f33e4eae21b37863c253ce61eaa13021a97 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/862e3ccf601ee0f7fbd8b23e6811fd50485a118f [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/86bae059b18af8ae263e5ae0022b67da0cfc0fbe [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/870f9cc4bd89c6c04c6a51ceae1efa8634627cd6 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/8762a523cdb78d2344d553fa52a229bd63c44e51 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/894211571f9153c3c2ea4102541dac69be8aaa9c [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/894e9b7832c52acb04bfa994ef53c7105d8db206 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/8b0e12978b8e2eecf62346e438e47d0993845693 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/8b3fa0bd4f289eff6a04a5205e04baaeafbdf637 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/8d1deedd1e463f8c95129a6f839c380a7c83ab04 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/8d1e029bd72381e382c87e61b4c5a9741d80d644 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/8dd1983889b6632228d4897c365a1e6124d101e1 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/8dfc2183691385432f92957cff0b2538e5a0ebfa [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/8eb9b86b4f0aa79b8ef84b44e1fb03094e7bb426 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/8ec540c36da3814e93da765bf2ff0825b59c1bd0 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/8f1bec32f4b8e64062f5405a096543e61d771076 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/8f3e48c49d0794909f6e8e61e5a4312edf484c33 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/8fbbf3c0eaa25b64d0a97a8ee08006539e649199 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/907d0021d42d0fdc867fd02d3609cdce13c8a055 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/919511c217a3427c22cad4a71aae31a6cd47b193 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/9267c81c3283da8193c198de05e05fa30631a453 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/92e80997a4237d76f10b70dae2870b7255c97435 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/935322db76f5d4c74c2dc68fc4631915b8e24323 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/939f2627ef6263d0176566de267ff3eb910e6a60 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/94adea6a0d9a44bee6f5e88adcee57be9e9e3597 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/94dcbe0d3352bd9b230096b8dce9c6d8d63f9d51 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/95dad738f60e3e5eb0f1cdafd91ad461f4418e8f [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/960c0a21c9e5c1a61b93b34da3189b0de1c264df [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/96903512b1f1dec08206123f024b62d0e31cd4dc [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/96a89c005e8d9992e34cc149b0be096ad0051446 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/97db8a66dd513eea47a5a25115508f4e59984854 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/98f2cb84ad89550cf56ee54e11f1448ae7287247 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/993497422a59b7f9f0f6db8c867339b5c9e4c978 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/999821e3750a7f2c9db663d2d100b4404c225040 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/99b2ed83be40cab431d1940e8de2dc3ebfe9352f [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/99e888b7372b29256dbefd476855ff73584cc00f [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/9b18087deb3cfafa1b964aa65d8ee980bc61404e [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/9b3c745ea3e313909a228a07b49aae110b02ae4a [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/9be1ce0ba77758928ff5e9c45139b1624cbe9c2d [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/9c703141efd69eb8f32a58133c8035fb585e0f4c [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/9c7f77981677499f0426a0ffb5cb79d5fe55dcb2 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/9ca59e6cadaa5be9af30dfe5620d1bcd70f442e5 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/9d139835d91474e8d8361d65698a31b8b38c4f7b [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/9e2179564a99e96e179c96f28802a0a2759b581c [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/9e56bb3b68d2e2617cb2d2f0f3941f7fc832e462 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/9f318b2c2ff9cf4615bd06ba13bdd086b4ad08c6 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/9f8d90b1480989fc46ea2f1c66cf687638994587 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/a09db5715f0bc3879a0e18e4db5a6b5640b254a3 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/a0c59a090818bca29d76ccf9843f7e2faf330ddf [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/a1cf10478e5e01a0d951c743a3dd45aa5fc409f2 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/a22c0f03f8c005a4612a9dcbcd6a643334c35d2f [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/a3154b8ed26b3461f2b091c732da00b63ce8bed3 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/a84a1ed1a24e753a27adfd3ba806f06fc44f899f [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/a871e7ce66afd4f57702cd1299de06cd08995561 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/a8dc736ea964586b7dcbf2bc065ec4675d1daba3 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/a91a835836c72217824f0b63491d9b623130502a [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/ab97c1f6033dc7d96f69b9e1461fd594c16f4ebf [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/ac8a8c23acd8c290a11dc7828f7f397957fa6400 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/ac94b2788f5252f9e2e8502c7c75e04bef4c0b76 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/ad03b4f58470c43db6593a35be48989486d754f9 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/af417c83e831a96fda1bdde99a1af6509ef2df3d [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/affd292cd2ce3306b4651cc7ec0ec0524cbbae3d [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/b0587e6e319f4b56d877e7ed46bc7da9b1e7249c [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/b166aa66b5b3ad178bc38aee5768226c8adc082f [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/b1ade0571262c6e5f1d72f6d25ebb513d2055bc9 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/b244c690157ff21d073940ef8c77d1898f37cf8e [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/b523091ee4f17d20f51f9b5cf82293465cf61780 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/b7d4d49ac2c530eb8444a449feb689ee50fd210d [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/b855c161121bfa29c6fb22d3c0236fae4af6984e [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/bc4263a92952d56168b354f723eaa43a33cd0b35 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/bcaa71abf23b2e5130e0cc464755fe769bf4aaa7 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/bcf4684ce097faa7e9d99b6e93cc2de24f57aee3 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/bdca6504d2ee7925f62e176355bb481344772075 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/beb208fd8675ba7de2ecb12998d2d628d579ca7c [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/bf0c98689ab81fc32787023300caf9a4175583dc [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/bf479e97b39b697e715663de6a1e78dd58d64122 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/bf826c96be94d1b42eea0666f7239cc5f699a375 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/c17650d19ae4a48abb36739c83d8979453f5705f [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/c1e5307d88feda2c3b15fc221cba92bcf41622bf [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/c249f408c552a0408eab3fe1d1cbeca95cd537c1 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/c26b460aebc9082c519539069f7e060042989696 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/c2eae71daad0d3561ab4d09b8b85372b8d790bc1 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/c37fda8d02e99132a1de99f959596c784ab8a53c [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/c4836760377a7091fb20f4afa9c712875792b9a7 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/c48caad597176404f776d532d4baf9faf7655ee2 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/c4eff0f59986fc5ab09d5bd95f394292f2882659 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/c5fc2086d167c8c3a7d9ec778db69c5fa14a59fe [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/c600877ce547166eb1b9d83afbe128d98767f8a3 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/c6a98fdaf6de78e59e1a149a43f3e42222d650b7 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/c8d22f7fb4f37f2d8cc7953fa2d599d38d899aec [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/c90951c19b24bac84296e3ec32cdeafe99e99cfb [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/c95ff2a172626efb50e94aa6781feba609820076 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/ca6c557afb9c571de62e9b65ca6469a6133760da [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/cb2d0fb23f66c968af2e80d59f71d4c1aed96fbd [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/cc60a642cc2037ad3c459a57381b8f65d8d7aa35 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/ccd3b8aa26c52f6d9c607c26ebdf621142aff745 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/ccdfd1354997eb117bd76b75440a7e4ff20bf564 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/cd7a7b8f08c189e95ae3e2ea44b9015000e823f3 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/ce05678d812a5f8ae8e115938410116ce9169456 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/ce6b642b81373f05baa2a6fe6e9d5d1387046285 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/cf84d06e4dddb997a79a41f9b6122bf620bbdb4b [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/cfbcc3e8cd65aa8b654688145ade34b8789468a6 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/clusterfuzz-testcase-5298216461402112 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/clusterfuzz-testcase-minimized-4857057310146560 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/crash-5ac3e1ea7764cfb6383629574262f82dc7b3cada [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/d000502f32ca5620d7745f39ff6be3b547e26a6d [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/d131f83ee73450ff45565d0c638be7d8beeb30d9 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/d1c7ae01a81a122c2fd7c5d8debcae7566e9ee2f [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/d2817b89d7aaa7fa880c077b1a67168ec2f4f0f7 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/d3ccd7039dd34baef465c4b78baa7a30312a8f07 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/d4cfaf3b59b22b654d7af80ee6715ce5015bfdc0 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/d5670827c8e8d4c95ac0f738c0790c19916c0336 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/d59d7e94863f1ed89cacfbaabf7bc59946036c8f [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/d6d8b478e6d13945f7a6f7d27f424ff57ca12f7f [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/d76d0c7f24ae3cc3f530d5306b8dcc15290c7ff2 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/d8b15e9e555ad9900ba4be8cc9f87bef75725b24 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/d9748abd540810c2449c3dd39a0ebb62754e520f [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/da9fc821f0c1e00728b139b36269bc3d21c0a8cc [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/dcd1bd94ad97b4e67fd7e12ff1bf7c039eb17f66 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/dd3ba9b139e13324fc76cd62af84b00ca8b87205 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/de0a9dce0ea4e4bfdcb13f788ae728bf979fed25 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/deb6f9a930d9b31586ede19fd8fd3caae0e5b1f2 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/dee95e0280b70681eddfb68e3b418126c5661e18 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/df01203edfa2dfe9e108ddde786ae48235624fef [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/df0adbe2523508e9afb42a58d98c2657710d6033 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/e05fcba1b22f658c8bd6f3c330b2b3c9faebf977 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/e145caa75d73e3d819a9cb4b6217f1f53112f3f8 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/e1d86c0094657386197d191855b5645ac1dd5936 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/e25adf8de44f5978d00b7e8c52aee89c5cd1fe93 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/e29f05162e3d96d5549f96aa4a54c868535b2847 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/e3a970ac8636d29da3ded328b876ed3550cb3209 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/e3cfdc862187b4ec28bd4fb2ced5094bb5b09909 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/e4ce52007d001806fc9368b62c124dfc56e8471c [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/e52173f0bc3325629046e85e2dc41acc6ba7d1c3 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/e6589006e3bda4c57247ad66fcd73ac00ee2cbe2 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/e67c79d0ed89ab2d5e8d81127df22876e636ac44 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/e6fab7572fb2a1c6e107b6f83cffd103a233d021 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/e790f5d312957dbfd20abdefe4b1735779ff9689 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/e8809017a4cf6c1e80a93f661166ead961f26bb4 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/e9733e973c33b38c2087b7f1deb36688b3b14259 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/ea8134769855d574f6673bf0301eb2e24632c6eb [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/eb489536e4e5589a93a17cd36669475b8f2a5e1b [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/eb48ebd4d01e5623dd16ae61938b3333fab3ce78 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/eb6ca7624384239c7f7e0d83edb7cc334b7926d7 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/ec9457ad41ed745ea9377ffdb16ad09f981daa7f [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/edff5256a2d60d0e51caef25dc1d6f1643dad6d5 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/ee4d9c5d22512da42726f47213ff56404d1d81d1 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/eef2f30b5e2ecd98ebefb12d57aba8b4ad52d904 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/ef23911de1a27d03d2d4983ca1527e17d6a7092b [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/ef5b7fc62a2daecf1e8f928b1fa3ebd028413a41 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/ef718258ca1870198e91a2fbc1eaa90b620673fb [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/efb46deb37a78f41dd760f6b7203b20956eb114e [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/efdd6824bd2456e3e408e0e84369c4fa3aa14f41 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/efec040a5de1969df5e37e4bc50a0a8f0de341d8 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/f1e30464c24dc1d7cec7ec1dd2adec8512232b43 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/f27a617b936814476770a3b31a5afb80d0f3b423 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/f3f0d99ac2962f8fddb25c65fb4c8c6eb63518a9 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/f4628084cf46f139babb886a782b4ab5977d5d2e [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/f4753e8881e4b3c71f2728149be7d04cc648f6a6 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/f4b48c4f3f310ed767755267210f212dd62bd715 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/f4d6ff635ae4fda497221da4bfa3e593df59a44e [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/f52f4d51aaaed0f9c3a20936cf5efd25d0692f67 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/f7cf30724ab740918eee6e4a6b6658ae3d7706e8 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/f823828ffd2a60efee36f1de52cb0f024ac5b4bb [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/f8760761bd5ab7b47376bfbc5a44e16b2d5ca800 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/fb15042c268625089ef6c8aa3d8a6f12d1d02c74 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/fc3dd4292d6884a770199596f5e9cbc1e869e5fb [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/fcc06696e641a7743bfd2f3b7ecd88e7b727e00a [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/fd34ec90fe8f9218fd25c3eac151aec998cff6d8 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/fdf548cde981fab4fb17bd63a124b75eddc5c836 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/fe47fb18b064e26479c3c3140082bd01065e897a [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/ff2097734bd7bb8451aece13c9336c4624735170 [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/ff2c949863eb4e14d9e835c51591304403d91b6c [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/ff7d6ff060e63355701b2e655c802902338497de [deleted file]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-0141fcddc9807ee093313b2256f1306fbbdc6cda [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-0255050a9ccb25f46d6c1bf6a5a8a4c0c7635599 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-0320a995a8c76c64c8a0e0297f632b76d9bc92d6 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-042091aeac4cc255506b96fa11c7354e699fde76 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-051268ade45dbed0aab896d7d9f4d10ba89d3b09 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-0696e7bf7837d98de01c915d3c9d80e5d21b30d2 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-06995c2f3f01c7ec50547415dc324c64030b7a3e [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-06f7ce769fe07804fc842462d4be8c1aa2ba82c2 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-0781b055c85ab8fbd0a3d0080a32e394af8761c4 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-080e1f19e6061c5bcac31add2095f87f6ce46129 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-0828169ba82152a8907f1001e3d98804397d4610 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-08ffc4a4160e9fe6f322c28870a89a41fd9c37d7 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-090a7a758898a6e7c9108b7e8a1cb9cda383e707 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-0940663729501b750a18542e1041cc26385c6148 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-0a10bd140c6c5fb109a0816ca061739688a6db9a [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-0a4d3fda02cdcb7adad1daa80d65780c9c8d1464 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-0ad812832efa33e086874fbf3496664d3f1b4dbe [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-0c9996d4fef87bacd7a001e99a515b3ba3d5788f [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-0d6210208831fe55951af56cdeee3d54a91a5361 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-0d784965b2262df7ed7a1eb57b92a718cc76bde8 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-0dc9e41eedf35ccedf4e2b0d230ead7c4d72fdb2 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-0dd470c8939ed535de6b36f7b7bfb68aeace493e [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-0e61e471fa6d3405daef4276ee00cf5fc189f378 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-0e9196f951874edbb5ed098739ea5c8b6c0751c2 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-11442d93a554b9e7f9ab02782bbf9443bf6e1ddc [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-11833b795d04eda5a3af56ef7b3c3a26a8ee3444 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-141272316382b0f3e9ec841c735b84e7aa517c3e [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-15ae43369798e48c396dfe7d53a21878b96e66c8 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-166bf1843c229d34a2880d234dd166c27bdc11fd [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-179e8ac763b4051a953a38b6b3b1f1e1f6cc6c9e [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-17faf0ba8a491a835d35977a9007b90ab7d30d2a [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-188f6cf2470e95b228341de305ef839b27f01a5c [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-1ab3e52adace335d02e2b5130eb4f7c918add7fd [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-1b5150514364e2c17f5a4edac1b7af99b936f55a [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-1e8befb98cbaba059d6771abd1680e19484e7723 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-1e9b962969c359bc2ff766704c8ca8e25f5eccfc [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-1f80af104acf41b912bf4a48fb938267e3718719 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-1fcc4afd6f48e83d61ea74970df3ca9dcd8ec291 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-213a734ccdb813b18ad9f2dd99b7f9967ee1460b [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-2151945f43991c27e123c45dc72b93752a47e65f [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-21545d998c27a5a1572a89a552937752432b1c14 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-23c7443fa1ab713e7c34ec50222b1b8cceaedc65 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-2445bb2c6779712dc9e14c01fecb7103f8732858 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-244b0a20500e31d3c538418800db816b07f4d210 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-2461b9fa6b5bc4b6424dec5b9a18d4ec7c309112 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-24ec2f3e17d3850564788f3fed17a5c586c44658 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-2537b8d6b902b8dfc6e17f194cf7d05ddecf74cf [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-253ad01acea4b7038edc3f2a8c4a0c0f5c4dcd05 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-256d0bbdbed22f5867a6f503bf082011e61ee12b [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-26f0e88adbd8f8cdf778131a35b33ecf8711fa49 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-2e5dd8fb9d2a31fad9d681eda697d085b647b57c [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-2fdfd2abf30c636ec8c841f1ac26594e25664f0f [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-311dac5092e36134d3490f98aa4207425e0ee941 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-320fe6224a5b691c0425e34b6b14e8c6fe9f9620 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-3255f1c7441a7150dc3c33022bfbe8c956c7b7b1 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-33bc9db104eb72891fb096f34cbac191b3f9918d [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-342ff1db70a7616b4ef76c03a42802c6702c18cb [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-344c011df992ccfc0ec682c14a1cb2d7959998c7 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-35775efb9d0d68fa07987b9a84934389b528e436 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-3650168db6fe115fb1e73eed4b76cd224d977d01 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-38228bf98cdb50fd3fa830ba5a9d4c7399063dff [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-38717bee901151b22a10beb12c6623ccc844d3c2 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-3a4bb427a85bdc5bf66ac71db073c99e0dc9f881 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-3ab48621d9b8f075369099a8ec7517bd23fd6e70 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-3aec8d9311130dfbb6584fe6e619579c21992b5f [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-3b14837f22905dcb04f93aed2aa69bf95924fb9d [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-3be63c163805927e04fd7f84d96122c48240e601 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-3bf2e349747c0f539181e0d4084a5fe506811a9e [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-3c5af4d73e94d0e8ad5666b6acb340f929031e95 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-3d2b25346a9671d83bd082d170a45eed739bae6b [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-3de7b860c3fba2bc55707fd6875dce276f2f249b [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-3e2004ff9f40e398e0f41138a25a8b66e3d843d9 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-3f8983e457033cc85997c356935ba9c21460e86b [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-4105669086d83a20f8d991088553ba08202478cd [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-4180619316eef7912d1cf52ffe85897242e1ae88 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-420291d7139d9246de747739fd98102434a742dd [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-4256437fc5897c0cd5d755816e4e68c7be326849 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-42b25a5413c536478a3e63da5adef4250babf2f4 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-42bef44ae751a45c671d9da5b1231d2ac747a48d [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-438c3c9045c3cf7910aceec34f77b47a70ca4abd [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-43af96b4f65ed0ace7236427f2f8833c4835989e [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-44c6119bb91a452d6128ce0ea0d62938800779ea [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-46d595331689ae01d77aff387747a98ff3480096 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-471a307b81dc37459087d41532741c5c9d7ba836 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-48900b4a5557530922ce45c15ad0d3b0a337520d [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-48bcce2c6487b18706ef0c609ca39c456215bac8 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-49027bbd3f3f3cafa315843c8fe8280f86985273 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-499376c5e291da2f9c25999abf4960fab5a92ec8 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-4a3b7ce0cdf217963a0b692769e5d6f4befe73b8 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-4a3fdb96bc8c80f1992f0f72f963f84856cbade8 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-4aae80e05793d7adb42a7e6e8a5283b677318777 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-4c7a034d3a3b4f29d99caf021a0e9bbb89706c2e [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-4ce8a43fb17a075627160812ad26c25210d8a82d [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-5032a75a98cd14d4dab75c1c5e2cd981abb19dcf [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-50b3f4b6aed97f442496d27f3b4315a18ba76d5f [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-51064b88a98658d48a0da7f1545c2d1293ad9538 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-51752f12d59fadaaa0dc72e6370612b84ee1555b [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-51eff6fcbfe1a51ceb3f5f2140c01eea89b4313d [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-51f65f681cf3a1218d83ad58642c06deaea86210 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-521809903d36db80b1ccd707f354361f2bf05075 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-5278e3581c069624157fd9176eddf52c0e58df67 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-52fe8f0e1fa270ea16f66c93f2ffab265ce059e8 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-53de87ae94acdc8e58a369459c12a3240f1294fe [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-54a2b3993c3483745f6314c870a038a8e58f97a7 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-55d60c2e5040a38be8ca41de63e137e3fef892a4 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-5653c44a5b520bdf2bdc599b7966f1d7c44950b3 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-5838b5a683229ebb6e6277e2810863e642b8afc2 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-588d225784891ac88e30ac6eb5651d63fac34083 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-58d51c21a20b6549567a0ab8fee29d162dd3fc5a [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-58f1036d8ff855841ec25b3c33e85a8fec0d94b7 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-5a99df42fb7bbafa2d55714ee235b1c46776b2ad [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-5b42793550699b2c015bed677cfcddc052f73513 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-5b8ca72ba00231c38b19f582127e6a146eba4282 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-5baa13dc95da05e7ba02bbe9583ea24517a29a1a [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-5bab61eb53176449e25c2c82f172b82cb13ffb9d [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-5c6f6b6f7f3e7b435f060abb73c20d2b773a7f56 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-5c9fd9cc7100feaeead1e0e45201945a6e76fd85 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-5ff49c9edc7361797a951585f3e180222c8dd95d [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-6129954942e26c2a9ec071b6659675745613cf3c [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-61fa69b6b51b0ed91914fe48779173f8d26a1d54 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-6362ac61cfb6e964aff78f3cd648475dfd5fd4e9 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-644deba51c79b6ebd470bd4367452941045d112a [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-64beae98e2276749b133e6368c9e0f19a79eba96 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-64d7add9192301fd878854dc96f9fa9053f03992 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-65566df65e8f55428b6672cc351df414fa8f936c [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-65bb703af35d5afb824cd68c41d7a1aeb3848d35 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-66c537bf59cb3667c037b3517be3d31245c9da8a [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-66f576baeb0c9435a56eb7375dadc5b5d630ed87 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-67b4cec5183659aeae0f5bc71b3adf0542a11828 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-68c94721eda2f62481bff9f1d183df70498d0c5b [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-68ee8169a65d58edb9fc1c752ea81dfec383203c [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-6b203d49bbba6ee74def0d35c2266e06ad3c45d9 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-6d580f28d785c0bf87ac351a31a89289449feadb [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-6f231dec759eb2105e09263d53e171de19a92c74 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-70ff6621a09e4f641538cb1b27e8b382b2f56a94 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-71981b55f27a1eb6274eda247048fa2c597f5004 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-71c2b0bebf7f0e916e4ab7eb36d47ccca2b9101c [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-74610e278a5b90aa12ce1beaf222c4306b02ed43 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-748ee9817eba56ec9938601a0e380c74bad4563f [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-7727e3eeb2a48c46bf5a678c300ff8a38b8ffe3a [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-78176d80c1d74c4b1b820d386ae483ac4d1d92b7 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-789abb571563a6795220046f76b7cf0ade90743c [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-78f5ff40e5554aa9c31b45f79a7ae9699f93e7fd [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-7a28fc2e9c72d51d29e87eed63ed405c9779b5e1 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-7a42083be21dce7f96edef1f3b3b2fea0bcaeb3f [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-7a51275b11ecb1efec9251390531681c8d6f2481 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-7b9682cd7a3984698f6eac034c59c0f91b4fb83d [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-7ba7239a29d6183960e3986abc8f19cfb548b905 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-7d3b3d5f23d0ede9f7e5dbd1115db58c8a54a213 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-7ff3b6239b04479a9caf67f45b2d0c619f712815 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-8035c81c95dedfc27c3649064f98f49e3e72c21f [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-804e1052842ce4d44b9c775ade2b18fcb8ce7bcf [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-80514b85933ea9bdd3462595f949c5af24409b87 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-8057c32b8bd28a5ec2105d62f2abe8cf69c9f5fc [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-806a3bd4e078d91adeacedfd3e47ef8ae229244a [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-8090444f98218e65ff9594789ff22bbea3c0497c [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-80e516692955d5f224706f268e247858858e16d8 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-810a1372fa97380265f5529c5043ae96f007f5bb [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-8127597d3c146b2a89579e44daef9d03a0f941ec [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-82ed571f8922caa572d13b4cc9b5c5fabafaade9 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-8328e86178800f87a3bf6f80749984f45b0cd0e8 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-84441efd7d8bdb0ce2fac28f218d3d5d4d77f1d4 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-84cbf70f45a64d5a01d1c96367b6d6160134f1ad [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-85eb0f4502a51e646dab4ae08eabd90613cdf8e1 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-86080f33e4eae21b37863c253ce61eaa13021a97 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-862e3ccf601ee0f7fbd8b23e6811fd50485a118f [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-86bae059b18af8ae263e5ae0022b67da0cfc0fbe [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-870f9cc4bd89c6c04c6a51ceae1efa8634627cd6 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-8762a523cdb78d2344d553fa52a229bd63c44e51 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-894211571f9153c3c2ea4102541dac69be8aaa9c [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-894e9b7832c52acb04bfa994ef53c7105d8db206 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-8b0e12978b8e2eecf62346e438e47d0993845693 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-8b3fa0bd4f289eff6a04a5205e04baaeafbdf637 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-8d1deedd1e463f8c95129a6f839c380a7c83ab04 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-8d1e029bd72381e382c87e61b4c5a9741d80d644 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-8dd1983889b6632228d4897c365a1e6124d101e1 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-8dfc2183691385432f92957cff0b2538e5a0ebfa [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-8eb9b86b4f0aa79b8ef84b44e1fb03094e7bb426 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-8ec540c36da3814e93da765bf2ff0825b59c1bd0 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-8f1bec32f4b8e64062f5405a096543e61d771076 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-8f3e48c49d0794909f6e8e61e5a4312edf484c33 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-8fbbf3c0eaa25b64d0a97a8ee08006539e649199 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-907d0021d42d0fdc867fd02d3609cdce13c8a055 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-919511c217a3427c22cad4a71aae31a6cd47b193 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-9267c81c3283da8193c198de05e05fa30631a453 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-92e80997a4237d76f10b70dae2870b7255c97435 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-935322db76f5d4c74c2dc68fc4631915b8e24323 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-939f2627ef6263d0176566de267ff3eb910e6a60 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-94adea6a0d9a44bee6f5e88adcee57be9e9e3597 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-94dcbe0d3352bd9b230096b8dce9c6d8d63f9d51 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-95dad738f60e3e5eb0f1cdafd91ad461f4418e8f [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-960c0a21c9e5c1a61b93b34da3189b0de1c264df [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-96903512b1f1dec08206123f024b62d0e31cd4dc [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-96a89c005e8d9992e34cc149b0be096ad0051446 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-97db8a66dd513eea47a5a25115508f4e59984854 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-98f2cb84ad89550cf56ee54e11f1448ae7287247 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-993497422a59b7f9f0f6db8c867339b5c9e4c978 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-999821e3750a7f2c9db663d2d100b4404c225040 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-99b2ed83be40cab431d1940e8de2dc3ebfe9352f [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-99e888b7372b29256dbefd476855ff73584cc00f [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-9b18087deb3cfafa1b964aa65d8ee980bc61404e [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-9b3c745ea3e313909a228a07b49aae110b02ae4a [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-9be1ce0ba77758928ff5e9c45139b1624cbe9c2d [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-9c703141efd69eb8f32a58133c8035fb585e0f4c [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-9c7f77981677499f0426a0ffb5cb79d5fe55dcb2 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-9ca59e6cadaa5be9af30dfe5620d1bcd70f442e5 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-9d139835d91474e8d8361d65698a31b8b38c4f7b [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-9e2179564a99e96e179c96f28802a0a2759b581c [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-9e56bb3b68d2e2617cb2d2f0f3941f7fc832e462 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-9f318b2c2ff9cf4615bd06ba13bdd086b4ad08c6 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-9f8d90b1480989fc46ea2f1c66cf687638994587 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-a09db5715f0bc3879a0e18e4db5a6b5640b254a3 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-a0c59a090818bca29d76ccf9843f7e2faf330ddf [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-a1cf10478e5e01a0d951c743a3dd45aa5fc409f2 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-a22c0f03f8c005a4612a9dcbcd6a643334c35d2f [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-a3154b8ed26b3461f2b091c732da00b63ce8bed3 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-a84a1ed1a24e753a27adfd3ba806f06fc44f899f [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-a871e7ce66afd4f57702cd1299de06cd08995561 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-a8dc736ea964586b7dcbf2bc065ec4675d1daba3 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-a91a835836c72217824f0b63491d9b623130502a [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-ab97c1f6033dc7d96f69b9e1461fd594c16f4ebf [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-ac8a8c23acd8c290a11dc7828f7f397957fa6400 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-ac94b2788f5252f9e2e8502c7c75e04bef4c0b76 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-ad03b4f58470c43db6593a35be48989486d754f9 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-af417c83e831a96fda1bdde99a1af6509ef2df3d [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-affd292cd2ce3306b4651cc7ec0ec0524cbbae3d [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-b0587e6e319f4b56d877e7ed46bc7da9b1e7249c [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-b166aa66b5b3ad178bc38aee5768226c8adc082f [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-b1ade0571262c6e5f1d72f6d25ebb513d2055bc9 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-b244c690157ff21d073940ef8c77d1898f37cf8e [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-b523091ee4f17d20f51f9b5cf82293465cf61780 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-b7d4d49ac2c530eb8444a449feb689ee50fd210d [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-b855c161121bfa29c6fb22d3c0236fae4af6984e [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-bc4263a92952d56168b354f723eaa43a33cd0b35 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-bcaa71abf23b2e5130e0cc464755fe769bf4aaa7 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-bcf4684ce097faa7e9d99b6e93cc2de24f57aee3 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-bdca6504d2ee7925f62e176355bb481344772075 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-beb208fd8675ba7de2ecb12998d2d628d579ca7c [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-bf0c98689ab81fc32787023300caf9a4175583dc [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-bf479e97b39b697e715663de6a1e78dd58d64122 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-bf826c96be94d1b42eea0666f7239cc5f699a375 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-c17650d19ae4a48abb36739c83d8979453f5705f [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-c1e5307d88feda2c3b15fc221cba92bcf41622bf [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-c249f408c552a0408eab3fe1d1cbeca95cd537c1 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-c26b460aebc9082c519539069f7e060042989696 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-c2eae71daad0d3561ab4d09b8b85372b8d790bc1 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-c37fda8d02e99132a1de99f959596c784ab8a53c [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-c4836760377a7091fb20f4afa9c712875792b9a7 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-c48caad597176404f776d532d4baf9faf7655ee2 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-c4eff0f59986fc5ab09d5bd95f394292f2882659 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-c5fc2086d167c8c3a7d9ec778db69c5fa14a59fe [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-c600877ce547166eb1b9d83afbe128d98767f8a3 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-c6a98fdaf6de78e59e1a149a43f3e42222d650b7 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-c8d22f7fb4f37f2d8cc7953fa2d599d38d899aec [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-c90951c19b24bac84296e3ec32cdeafe99e99cfb [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-c95ff2a172626efb50e94aa6781feba609820076 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-ca6c557afb9c571de62e9b65ca6469a6133760da [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-cb2d0fb23f66c968af2e80d59f71d4c1aed96fbd [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-cc60a642cc2037ad3c459a57381b8f65d8d7aa35 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-ccd3b8aa26c52f6d9c607c26ebdf621142aff745 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-ccdfd1354997eb117bd76b75440a7e4ff20bf564 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-cd7a7b8f08c189e95ae3e2ea44b9015000e823f3 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-ce05678d812a5f8ae8e115938410116ce9169456 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-ce6b642b81373f05baa2a6fe6e9d5d1387046285 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-cf84d06e4dddb997a79a41f9b6122bf620bbdb4b [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-cfbcc3e8cd65aa8b654688145ade34b8789468a6 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-clusterfuzz-testcase-5298216461402112 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-clusterfuzz-testcase-minimized-4857057310146560 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-crash-5ac3e1ea7764cfb6383629574262f82dc7b3cada [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-d000502f32ca5620d7745f39ff6be3b547e26a6d [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-d131f83ee73450ff45565d0c638be7d8beeb30d9 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-d1c7ae01a81a122c2fd7c5d8debcae7566e9ee2f [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-d2817b89d7aaa7fa880c077b1a67168ec2f4f0f7 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-d3ccd7039dd34baef465c4b78baa7a30312a8f07 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-d4cfaf3b59b22b654d7af80ee6715ce5015bfdc0 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-d5670827c8e8d4c95ac0f738c0790c19916c0336 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-d59d7e94863f1ed89cacfbaabf7bc59946036c8f [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-d6d8b478e6d13945f7a6f7d27f424ff57ca12f7f [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-d76d0c7f24ae3cc3f530d5306b8dcc15290c7ff2 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-d8b15e9e555ad9900ba4be8cc9f87bef75725b24 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-d9748abd540810c2449c3dd39a0ebb62754e520f [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-da9fc821f0c1e00728b139b36269bc3d21c0a8cc [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-dcd1bd94ad97b4e67fd7e12ff1bf7c039eb17f66 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-dd3ba9b139e13324fc76cd62af84b00ca8b87205 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-de0a9dce0ea4e4bfdcb13f788ae728bf979fed25 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-deb6f9a930d9b31586ede19fd8fd3caae0e5b1f2 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-dee95e0280b70681eddfb68e3b418126c5661e18 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-df01203edfa2dfe9e108ddde786ae48235624fef [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-df0adbe2523508e9afb42a58d98c2657710d6033 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-e05fcba1b22f658c8bd6f3c330b2b3c9faebf977 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-e145caa75d73e3d819a9cb4b6217f1f53112f3f8 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-e1d86c0094657386197d191855b5645ac1dd5936 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-e25adf8de44f5978d00b7e8c52aee89c5cd1fe93 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-e29f05162e3d96d5549f96aa4a54c868535b2847 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-e3a970ac8636d29da3ded328b876ed3550cb3209 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-e3cfdc862187b4ec28bd4fb2ced5094bb5b09909 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-e4ce52007d001806fc9368b62c124dfc56e8471c [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-e52173f0bc3325629046e85e2dc41acc6ba7d1c3 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-e6589006e3bda4c57247ad66fcd73ac00ee2cbe2 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-e67c79d0ed89ab2d5e8d81127df22876e636ac44 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-e6fab7572fb2a1c6e107b6f83cffd103a233d021 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-e790f5d312957dbfd20abdefe4b1735779ff9689 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-e8809017a4cf6c1e80a93f661166ead961f26bb4 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-e9733e973c33b38c2087b7f1deb36688b3b14259 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-ea8134769855d574f6673bf0301eb2e24632c6eb [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-eb489536e4e5589a93a17cd36669475b8f2a5e1b [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-eb48ebd4d01e5623dd16ae61938b3333fab3ce78 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-eb6ca7624384239c7f7e0d83edb7cc334b7926d7 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-ec9457ad41ed745ea9377ffdb16ad09f981daa7f [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-edff5256a2d60d0e51caef25dc1d6f1643dad6d5 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-ee4d9c5d22512da42726f47213ff56404d1d81d1 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-eef2f30b5e2ecd98ebefb12d57aba8b4ad52d904 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-ef23911de1a27d03d2d4983ca1527e17d6a7092b [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-ef5b7fc62a2daecf1e8f928b1fa3ebd028413a41 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-ef718258ca1870198e91a2fbc1eaa90b620673fb [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-efb46deb37a78f41dd760f6b7203b20956eb114e [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-efdd6824bd2456e3e408e0e84369c4fa3aa14f41 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-efec040a5de1969df5e37e4bc50a0a8f0de341d8 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-f1e30464c24dc1d7cec7ec1dd2adec8512232b43 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-f27a617b936814476770a3b31a5afb80d0f3b423 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-f3f0d99ac2962f8fddb25c65fb4c8c6eb63518a9 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-f4628084cf46f139babb886a782b4ab5977d5d2e [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-f4753e8881e4b3c71f2728149be7d04cc648f6a6 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-f4b48c4f3f310ed767755267210f212dd62bd715 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-f4d6ff635ae4fda497221da4bfa3e593df59a44e [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-f52f4d51aaaed0f9c3a20936cf5efd25d0692f67 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-f7cf30724ab740918eee6e4a6b6658ae3d7706e8 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-f823828ffd2a60efee36f1de52cb0f024ac5b4bb [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-f8760761bd5ab7b47376bfbc5a44e16b2d5ca800 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-fb15042c268625089ef6c8aa3d8a6f12d1d02c74 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-fc3dd4292d6884a770199596f5e9cbc1e869e5fb [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-fcc06696e641a7743bfd2f3b7ecd88e7b727e00a [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-fd34ec90fe8f9218fd25c3eac151aec998cff6d8 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-fdf548cde981fab4fb17bd63a124b75eddc5c836 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-fe47fb18b064e26479c3c3140082bd01065e897a [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-ff2097734bd7bb8451aece13c9336c4624735170 [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-ff2c949863eb4e14d9e835c51591304403d91b6c [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_corpus/upgraded-ff7d6ff060e63355701b2e655c802902338497de [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_fuzzer.proto [new file with mode: 0644]
test/core/transport/chttp2/hpack_parser_fuzzer_test.cc
test/core/transport/chttp2/hpack_parser_table_test.cc
test/core/transport/chttp2/hpack_parser_test.cc
test/core/transport/error_utils_test.cc
test/core/transport/metadata_map_test.cc [new file with mode: 0644]
test/core/transport/metadata_test.cc
test/core/transport/parsed_metadata_test.cc [new file with mode: 0644]
test/core/transport/static_metadata_test.cc
test/core/tsi/BUILD
test/core/tsi/alts/crypt/BUILD
test/core/tsi/alts/crypt/aes_gcm_test.cc
test/core/tsi/alts/crypt/gsec_test_util.cc
test/core/tsi/alts/fake_handshaker/BUILD
test/core/tsi/alts/frame_protector/BUILD
test/core/tsi/alts/frame_protector/frame_handler_test.cc
test/core/tsi/alts/handshaker/BUILD
test/core/tsi/alts/zero_copy_frame_protector/BUILD
test/core/tsi/ssl_transport_security_test.cc
test/core/tsi/test_creds/crl_data/15e5c67a.0 [new symlink]
test/core/tsi/test_creds/crl_data/26fefe27.0 [new symlink]
test/core/tsi/test_creds/crl_data/BUILD [new file with mode: 0644]
test/core/tsi/test_creds/crl_data/README [new file with mode: 0644]
test/core/tsi/test_creds/crl_data/ab06acdd.0 [new symlink]
test/core/tsi/test_creds/crl_data/ab06acdd.r0 [new symlink]
test/core/tsi/test_creds/crl_data/ca-openssl.cnf [new file with mode: 0644]
test/core/tsi/test_creds/crl_data/ca.key [new file with mode: 0644]
test/core/tsi/test_creds/crl_data/ca.pem [new file with mode: 0644]
test/core/tsi/test_creds/crl_data/current.crl [new file with mode: 0644]
test/core/tsi/test_creds/crl_data/demoCA/crlnumber [new file with mode: 0644]
test/core/tsi/test_creds/crl_data/demoCA/crlnumber.old [new file with mode: 0644]
test/core/tsi/test_creds/crl_data/demoCA/index.txt [new file with mode: 0644]
test/core/tsi/test_creds/crl_data/demoCA/index.txt.attr [new file with mode: 0644]
test/core/tsi/test_creds/crl_data/demoCA/index.txt.old [new file with mode: 0644]
test/core/tsi/test_creds/crl_data/revoked.key [new file with mode: 0644]
test/core/tsi/test_creds/crl_data/revoked.pem [new file with mode: 0644]
test/core/tsi/test_creds/crl_data/valid.key [new file with mode: 0644]
test/core/tsi/test_creds/crl_data/valid.pem [new file with mode: 0644]
test/core/tsi/transport_security_test_lib.cc
test/core/uri/BUILD
test/core/util/BUILD
test/core/util/cmdline.cc
test/core/util/evaluate_args_test_util.h
test/core/util/fuzzer_corpus_test.cc
test/core/util/fuzzer_util.cc
test/core/util/grpc_fuzzer.bzl
test/core/util/histogram.cc
test/core/util/slice_splitter.cc
test/core/util/subprocess_posix.cc
test/core/util/test_lb_policies.cc
test/core/util/test_lb_policies.h
test/core/util/trickle_endpoint.cc
test/core/util/ubsan_suppressions.txt
test/core/xds/BUILD
test/core/xds/xds_channel_stack_modifier_test.cc [new file with mode: 0644]
test/cpp/client/BUILD
test/cpp/client/client_channel_stress_test.cc
test/cpp/cocoapods/Podfile
test/cpp/codegen/BUILD
test/cpp/common/BUILD
test/cpp/common/channel_arguments_test.cc
test/cpp/end2end/BUILD
test/cpp/end2end/client_lb_end2end_test.cc
test/cpp/end2end/counted_service.h [new file with mode: 0644]
test/cpp/end2end/end2end_test.cc
test/cpp/end2end/grpclb_end2end_test.cc
test/cpp/end2end/rls_end2end_test.cc [new file with mode: 0644]
test/cpp/end2end/sdk_authz_end2end_test.cc
test/cpp/end2end/test_service_impl.h
test/cpp/end2end/xds/BUILD [new file with mode: 0644]
test/cpp/end2end/xds/xds_credentials_end2end_test.cc [moved from test/cpp/end2end/xds_credentials_end2end_test.cc with 100% similarity]
test/cpp/end2end/xds/xds_end2end_test.cc [new file with mode: 0644]
test/cpp/end2end/xds/xds_server.cc [new file with mode: 0644]
test/cpp/end2end/xds/xds_server.h [new file with mode: 0644]
test/cpp/end2end/xds_end2end_test.cc [deleted file]
test/cpp/ext/filters/census/BUILD
test/cpp/grpclb/BUILD
test/cpp/interop/BUILD
test/cpp/ios/Podfile
test/cpp/microbenchmarks/BUILD
test/cpp/microbenchmarks/bm_call_create.cc
test/cpp/microbenchmarks/bm_chttp2_hpack.cc
test/cpp/microbenchmarks/bm_chttp2_transport.cc
test/cpp/microbenchmarks/bm_cq_multiple_threads.cc
test/cpp/microbenchmarks/bm_error.cc
test/cpp/microbenchmarks/bm_fullstack_trickle.cc
test/cpp/microbenchmarks/bm_opencensus_plugin.cc
test/cpp/microbenchmarks/bm_threadpool.cc
test/cpp/microbenchmarks/fullstack_fixtures.h
test/cpp/microbenchmarks/grpc_benchmark_config.bzl [new file with mode: 0644]
test/cpp/naming/BUILD
test/cpp/naming/utils/BUILD
test/cpp/performance/BUILD
test/cpp/performance/writes_per_rpc_test.cc
test/cpp/qps/BUILD
test/cpp/qps/client.h
test/cpp/qps/driver.cc
test/cpp/qps/gen_build_yaml.py [deleted file]
test/cpp/qps/inproc_sync_unary_ping_pong_test.cc
test/cpp/qps/json_run_localhost_scenario_gen.py
test/cpp/qps/json_run_localhost_scenarios.bzl
test/cpp/qps/qps_json_driver_scenario_gen.py
test/cpp/qps/qps_json_driver_scenarios.bzl
test/cpp/qps/qps_openloop_test.cc
test/cpp/qps/scenario_generator_helper.py [new file with mode: 0755]
test/cpp/qps/secure_sync_unary_ping_pong_test.cc
test/cpp/qps/worker.cc
test/cpp/server/BUILD
test/cpp/server/authorization_policy_provider_test.cc
test/cpp/server/load_reporter/BUILD
test/cpp/server/load_reporter/load_reporter_test.cc
test/cpp/test/BUILD
test/cpp/thread_manager/BUILD
test/cpp/util/BUILD
test/cpp/util/cli_call.cc
test/cpp/util/cli_call.h
test/cpp/util/cli_call_test.cc
test/distrib/bazel/run_bazel_distrib_test.sh [new file with mode: 0755]
test/distrib/bazel/test_latest_bazel_version.sh [new file with mode: 0755]
test/distrib/bazel/test_single_bazel_version.sh [new file with mode: 0755]
third_party/BUILD
third_party/address_sorting/address_sorting_posix.c
third_party/libprotobuf_mutator.BUILD [new file with mode: 0644]
third_party/protobuf.patch
third_party/rake-compiler-dock/rake_arm64-darwin/Dockerfile [new file with mode: 0644]
third_party/rake-compiler-dock/rake_x86_64-darwin/Dockerfile [new file with mode: 0644]
third_party/rules_python.patch [new file with mode: 0644]
third_party/toolchains/BUILD
tools/bazel
tools/bazel.rc
tools/buildgen/extract_metadata_from_bazel_xml.py
tools/buildgen/plugins/make_fuzzer_tests.py [deleted file]
tools/codegen/core/gen_static_metadata.py
tools/codegen/core/gen_stats_data.py
tools/codegen/core/gen_upb_api.sh
tools/codegen/core/gen_upb_api_from_bazel_xml.py [new file with mode: 0755]
tools/distrib/python/grpc_version.py
tools/distrib/python/grpcio_tools/grpc_version.py
tools/distrib/python/grpcio_tools/protoc_lib_deps.py
tools/distrib/python/grpcio_tools/setup.py
tools/distrib/python/xds_protos/setup.py
tools/distrib/run_clang_tidy.py
tools/dockerfile/distribtest/python_dev_buster_x64/Dockerfile [new file with mode: 0644]
tools/dockerfile/distribtest/python_dev_buster_x86/Dockerfile [new file with mode: 0644]
tools/dockerfile/distribtest/python_dev_fedora23_x64/Dockerfile [deleted file]
tools/dockerfile/distribtest/python_dev_fedora34_x64/Dockerfile [new file with mode: 0644]
tools/dockerfile/distribtest/python_dev_jessie_x64/Dockerfile [deleted file]
tools/dockerfile/distribtest/python_dev_jessie_x86/Dockerfile [deleted file]
tools/dockerfile/interoptest/grpc_interop_php7/Dockerfile
tools/dockerfile/test/bazel/Dockerfile
tools/dockerfile/test/binder_transport_apk/Dockerfile
tools/dockerfile/test/cxx_clang_12_x64/Dockerfile [new file with mode: 0644]
tools/dockerfile/test/cxx_clang_4_x64/Dockerfile [new file with mode: 0644]
tools/dockerfile/test/cxx_gcc_11_x64/Dockerfile [new file with mode: 0644]
tools/dockerfile/test/cxx_jessie_x64/Dockerfile
tools/dockerfile/test/cxx_ubuntu1804_x64/Dockerfile [deleted file]
tools/dockerfile/test/php7_debian9_x64/Dockerfile [new file with mode: 0644]
tools/dockerfile/test/php7_jessie_x64/Dockerfile [deleted file]
tools/dockerfile/test/python_alpine_x64/Dockerfile
tools/dockerfile/test/sanity/Dockerfile
tools/doxygen/Doxyfile.c++
tools/doxygen/Doxyfile.c++.internal
tools/doxygen/Doxyfile.core
tools/doxygen/Doxyfile.core.internal
tools/doxygen/Doxyfile.objc
tools/doxygen/Doxyfile.objc.internal
tools/doxygen/Doxyfile.php
tools/fuzzer/build_and_run_fuzzer.sh [deleted file]
tools/fuzzer/options/client_fuzzer.options [deleted file]
tools/fuzzer/options/fuzzer.options [deleted file]
tools/fuzzer/options/fuzzer_response.options [deleted file]
tools/fuzzer/options/fuzzer_serverlist.options [deleted file]
tools/fuzzer/options/hpack_parser_fuzzer_test.options [deleted file]
tools/fuzzer/options/percent_decode_fuzzer.options [deleted file]
tools/fuzzer/options/percent_encode_fuzzer.options [deleted file]
tools/fuzzer/options/request_fuzzer.options [deleted file]
tools/fuzzer/options/response_fuzzer.options [deleted file]
tools/fuzzer/options/server_fuzzer.options [deleted file]
tools/fuzzer/options/ssl_server_fuzzer.options [deleted file]
tools/fuzzer/options/uri_fuzzer_test.options [deleted file]
tools/fuzzer/runners/alts_credentials_fuzzer.sh [deleted file]
tools/fuzzer/runners/client_fuzzer.sh [deleted file]
tools/fuzzer/runners/hpack_parser_fuzzer_test.sh [deleted file]
tools/fuzzer/runners/http_request_fuzzer_test.sh [deleted file]
tools/fuzzer/runners/http_response_fuzzer_test.sh [deleted file]
tools/fuzzer/runners/json_fuzzer_test.sh [deleted file]
tools/fuzzer/runners/nanopb_fuzzer_response_test.sh [deleted file]
tools/fuzzer/runners/nanopb_fuzzer_serverlist_test.sh [deleted file]
tools/fuzzer/runners/percent_decode_fuzzer.sh [deleted file]
tools/fuzzer/runners/percent_encode_fuzzer.sh [deleted file]
tools/fuzzer/runners/server_fuzzer.sh [deleted file]
tools/fuzzer/runners/ssl_server_fuzzer.sh [deleted file]
tools/fuzzer/runners/uri_fuzzer_test.sh [deleted file]
tools/github/pr_latency.py [deleted file]
tools/internal_ci/helper_scripts/prepare_build_macos_rc
tools/internal_ci/linux/aws/grpc_bazel_test_c_cpp_aarch64.sh
tools/internal_ci/linux/grpc_bazel_distribtest.cfg [new file with mode: 0644]
tools/internal_ci/linux/grpc_bazel_distribtest.sh [new file with mode: 0755]
tools/internal_ci/linux/grpc_bazel_distribtest_latest.cfg [new file with mode: 0644]
tools/internal_ci/linux/grpc_bazel_distribtest_latest.sh [new file with mode: 0755]
tools/internal_ci/linux/grpc_binder_transport_apk_build_in_docker.sh
tools/internal_ci/linux/grpc_e2e_performance_gke.cfg
tools/internal_ci/linux/grpc_e2e_performance_gke.sh
tools/internal_ci/linux/grpc_e2e_performance_gke_experiment.cfg [new file with mode: 0644]
tools/internal_ci/linux/grpc_e2e_performance_gke_experiment.sh [new file with mode: 0755]
tools/internal_ci/linux/grpc_e2e_performance_v2.cfg
tools/internal_ci/linux/grpc_e2e_performance_v2.sh [deleted file]
tools/internal_ci/linux/grpc_line_count.cfg [deleted file]
tools/internal_ci/linux/grpc_line_count.sh [deleted file]
tools/internal_ci/linux/grpc_portability_build_only.cfg
tools/internal_ci/linux/grpc_run_tests_matrix.sh
tools/internal_ci/linux/grpc_xds_bazel_python_test_in_docker.sh
tools/internal_ci/linux/grpc_xds_bazel_test_in_docker.sh
tools/internal_ci/linux/grpc_xds_csharp.cfg [deleted file]
tools/internal_ci/linux/grpc_xds_csharp.sh [deleted file]
tools/internal_ci/linux/grpc_xds_csharp_test_in_docker.sh [deleted file]
tools/internal_ci/linux/grpc_xds_k8s.cfg [deleted file]
tools/internal_ci/linux/grpc_xds_k8s_lb.cfg
tools/internal_ci/linux/grpc_xds_k8s_lb.sh
tools/internal_ci/linux/grpc_xds_k8s_xlang.cfg
tools/internal_ci/linux/grpc_xds_k8s_xlang.sh
tools/internal_ci/linux/grpc_xds_v3_csharp.cfg [deleted file]
tools/internal_ci/linux/grpc_xds_v3_csharp.sh [deleted file]
tools/internal_ci/linux/grpc_xds_v3_csharp_test_in_docker.sh [deleted file]
tools/internal_ci/linux/psm-security.cfg [new file with mode: 0644]
tools/internal_ci/linux/psm-security.sh [moved from tools/internal_ci/linux/grpc_xds_k8s.sh with 100% similarity]
tools/internal_ci/windows/bazel_rbe.bat
tools/internal_ci/windows/grpc_basictests_csharp.cfg
tools/internal_ci/windows/grpc_basictests_python.cfg
tools/internal_ci/windows/pull_request/grpc_basictests_csharp.cfg
tools/interop_matrix/client_matrix.py
tools/line_count/collect-history.py [deleted file]
tools/line_count/collect-now.sh [deleted file]
tools/line_count/summarize-history.py [deleted file]
tools/line_count/yaml2csv.py [deleted file]
tools/profiling/bloat/bloat_diff.py
tools/profiling/microbenchmarks/bm_json.py
tools/remote_build/rbe_common.bazelrc
tools/run_tests/artifacts/distribtest_targets.py
tools/run_tests/generated/tests.json
tools/run_tests/performance/README.md
tools/run_tests/performance/loadtest_config.py
tools/run_tests/performance/scenario_config.py
tools/run_tests/performance/templates/loadtest_template_basic_all_languages.yaml
tools/run_tests/performance/templates/loadtest_template_prebuilt_all_languages.yaml
tools/run_tests/python_utils/check_on_pr.py
tools/run_tests/python_utils/jobset.py
tools/run_tests/python_utils/upload_test_results.py
tools/run_tests/run_tests.py
tools/run_tests/run_tests_matrix.py
tools/run_tests/run_xds_tests.py
tools/run_tests/sanity/build_banned_constructs.sh [new file with mode: 0755]
tools/run_tests/sanity/check_bazel_workspace.py
tools/run_tests/sanity/check_package_name.py [new file with mode: 0755]
tools/run_tests/sanity/check_port_platform.py
tools/run_tests/sanity/check_qps_scenario_changes.py
tools/run_tests/sanity/check_submodules.sh
tools/run_tests/sanity/core_banned_functions.py
tools/run_tests/sanity/sanity_tests.yaml
tools/run_tests/xds_k8s_test_driver/README.md
tools/run_tests/xds_k8s_test_driver/framework/infrastructure/gcp/api.py
tools/run_tests/xds_k8s_test_driver/framework/infrastructure/gcp/compute.py
tools/run_tests/xds_k8s_test_driver/framework/infrastructure/gcp/network_security.py
tools/run_tests/xds_k8s_test_driver/framework/infrastructure/traffic_director.py
tools/run_tests/xds_k8s_test_driver/framework/xds_flags.py
tools/run_tests/xds_k8s_test_driver/framework/xds_k8s_testcase.py
tools/run_tests/xds_k8s_test_driver/framework/xds_url_map_test_resources.py
tools/run_tests/xds_k8s_test_driver/framework/xds_url_map_testcase.py
tools/run_tests/xds_k8s_test_driver/kubernetes-manifests/server-secure.deployment.yaml
tools/run_tests/xds_k8s_test_driver/tests/authz_test.py [new file with mode: 0644]
tools/run_tests/xds_k8s_test_driver/tests/url_map/affinity_test.py
tools/run_tests/xds_k8s_test_driver/tests/url_map/retry_test.py
tools/run_tests/xds_k8s_test_driver/tests/url_map/timeout_test.py

index 0334334..160716e 100644 (file)
@@ -6,12 +6,22 @@ bins
 libs
 objs
 third_party/abseil-cpp
+third_party/benchmark
+third_party/boringssl
 third_party/bloaty
 third_party/boringssl-with-bazel
+third_party/envoy-api
 third_party/googleapis
 third_party/googletest
 third_party/opencensus-proto
 third_party/protobuf
 third_party/protoc-gen-validate
-third_party/udpa
+third_party/re2
 third_party/upb
+third_party/xds
+
+bazel/test/python_test_repo
+
+# Directories generated by setuptools build containing BUILD files.
+src/python/grpcio_tests/src/
+tools/distrib/python/grpcio_tools/grpc_root/
index 111533e..dbec90a 100644 (file)
@@ -2,7 +2,7 @@
 name: Report a bug
 about: Create a report to help us improve
 labels: kind/bug, priority/P2
-assignees: drfloob
+assignees: veblush
 
 ---
 
index 6652601..d821fef 100644 (file)
@@ -2,7 +2,7 @@
 name: Request a cleanup
 about: Suggest a cleanup in our repository
 labels: kind/internal cleanup, priority/P2
-assignees: drfloob
+assignees: veblush
 
 ---
 
index adc5b1c..5a2f61d 100644 (file)
@@ -2,7 +2,7 @@
 name: Request a feature
 about: Suggest an idea for this project
 labels: kind/enhancement, priority/P2
-assignees: drfloob
+assignees: veblush
 
 ---
 
index 770a386..68f5dfb 100644 (file)
@@ -2,7 +2,7 @@
 name: Ask a question
 about: Ask a question
 labels: kind/question, priority/P3
-assignees: drfloob
+assignees: veblush
 
 ---
 
index 5424b01..366b686 100644 (file)
@@ -8,4 +8,4 @@ If you know who should review your pull request, please remove the mentioning be
 
 -->
 
-@drfloob
+@veblush
index 8cb40ae..920f620 100644 (file)
@@ -5,13 +5,20 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       # Cache bazel build
+      - name: Get current time
+        uses: srfrnk/current-time@master
+        id: current-time
+        with:
+          format: YYYYWW
       - name: Cache bazel
         uses: actions/cache@v2
         env:
           cache-name: bazel-cache
         with:
           path: ~/.cache/bazel
-          key: ${{ runner.os }}-${{ env.cache-name }}
+          # formattedTime here is like 202132 - the year concatenated with the week
+          # as this changes every week, we cycle to a new cache once per week.
+          key: ${{ runner.os }}-${{ steps.current-time.outputs.formattedTime }}
       # Cancel current runs if they're still running
       # (saves processing on fast pushes)
       - name: Cancel Previous Runs
index 767f03b..1a2ef10 100644 (file)
@@ -40,9 +40,6 @@
 [submodule "third_party/protoc-gen-validate"]
        path = third_party/protoc-gen-validate
        url = https://github.com/envoyproxy/protoc-gen-validate.git
-[submodule "third_party/udpa"]
-       path = third_party/udpa
-       url = https://github.com/cncf/udpa.git
 [submodule "third_party/libuv"]
        path = third_party/libuv
        url = https://github.com/libuv/libuv.git
@@ -52,3 +49,6 @@
 [submodule "third_party/opentelemetry"]
        path = third_party/opentelemetry
        url = https://github.com/open-telemetry/opentelemetry-proto.git
+[submodule "third_party/xds"]
+       path = third_party/xds
+       url = https://github.com/cncf/xds.git
diff --git a/BUILD b/BUILD
index 7e56a55..7bea9d2 100644 (file)
--- a/BUILD
+++ b/BUILD
@@ -19,11 +19,12 @@ load(
     "grpc_cc_library",
     "grpc_generate_one_off_targets",
     "grpc_upb_proto_library",
+    "grpc_upb_proto_reflection_library",
     "python_config_settings",
 )
 load("@bazel_skylib//lib:selects.bzl", "selects")
 
-licenses(["notice"])
+licenses(["reciprocal"])
 
 package(
     default_visibility = ["//visibility:public"],
@@ -48,6 +49,17 @@ config_setting(
     values = {"define": "grpc_no_xds=true"},
 )
 
+# When gRPC is build as shared library, binder transport code might still
+# get included even when user's code does not depend on it. In that case
+# --define=grpc_no_binder=true can be used to disable binder transport
+# related code to reduce binary size.
+# For users using build system other than bazel, they can define
+# GRPC_NO_BINDER to achieve the same effect.
+config_setting(
+    name = "grpc_no_binder_define",
+    values = {"define": "grpc_no_binder=true"},
+)
+
 config_setting(
     name = "android",
     values = {"crosstool_top": "//external:android/crosstool"},
@@ -71,6 +83,31 @@ selects.config_setting_group(
     ],
 )
 
+selects.config_setting_group(
+    name = "grpc_no_binder",
+    match_any = [
+        ":grpc_no_binder_define",
+        # We do not need binder on ios.
+        ":ios",
+    ],
+)
+
+selects.config_setting_group(
+    name = "grpc_no_rls",
+    match_any = [
+        # Disable RLS support on mobile platforms where it is not likely to be
+        # needed and where reducing the binary size is more important.
+        ":android",
+        ":ios",
+    ],
+)
+
+# Fuzzers can be built as fuzzers or as tests
+config_setting(
+    name = "grpc_build_fuzzers",
+    values = {"define": "grpc_build_fuzzers=true"},
+)
+
 config_setting(
     name = "grpc_allow_exceptions",
     values = {"define": "GRPC_ALLOW_EXCEPTIONS=1"},
@@ -109,11 +146,11 @@ config_setting(
 python_config_settings()
 
 # This should be updated along with build_handwritten.yaml
-g_stands_for = "goat"  # @unused
+g_stands_for = "granola"  # @unused
 
-core_version = "19.0.0"  # @unused
+core_version = "20.0.0"  # @unused
 
-version = "1.41.1"  # @unused
+version = "1.42.0"  # @unused
 
 GPR_PUBLIC_HDRS = [
     "include/grpc/support/alloc.h",
@@ -155,7 +192,8 @@ GRPC_PUBLIC_EVENT_ENGINE_HDRS = [
     "include/grpc/event_engine/endpoint_config.h",
     "include/grpc/event_engine/event_engine.h",
     "include/grpc/event_engine/port.h",
-    "include/grpc/event_engine/slice_allocator.h",
+    "include/grpc/event_engine/memory_allocator.h",
+    "include/grpc/event_engine/internal/memory_allocator_impl.h",
 ]
 
 GRPC_SECURE_PUBLIC_HDRS = [
@@ -353,13 +391,24 @@ grpc_cc_library(
     deps = [
         "config",
         "gpr_base",
-        "grpc_base_c",
+        "grpc_base",
         "grpc_common",
         "grpc_lb_policy_grpclb",
         "grpc_trace",
+        "slice",
     ],
 )
 
+GRPC_XDS_TARGETS = [
+    "grpc_lb_policy_cds",
+    "grpc_lb_policy_xds_cluster_impl",
+    "grpc_lb_policy_xds_cluster_manager",
+    "grpc_lb_policy_xds_cluster_resolver",
+    "grpc_resolver_xds",
+    "grpc_resolver_c2p",
+    "grpc_xds_server_config_fetcher",
+]
+
 grpc_cc_library(
     name = "grpc",
     srcs = [
@@ -369,21 +418,22 @@ grpc_cc_library(
     defines = select({
         "grpc_no_xds": ["GRPC_NO_XDS"],
         "//conditions:default": [],
+    }) + select({
+        "grpc_no_rls": ["GRPC_NO_RLS"],
+        "//conditions:default": [],
     }),
     language = "c++",
     public_hdrs = GRPC_PUBLIC_HDRS + GRPC_SECURE_PUBLIC_HDRS,
-    select_deps = {
-        "grpc_no_xds": [],
-        "//conditions:default": [
-            "grpc_lb_policy_cds",
-            "grpc_lb_policy_xds_cluster_impl",
-            "grpc_lb_policy_xds_cluster_manager",
-            "grpc_lb_policy_xds_cluster_resolver",
-            "grpc_resolver_xds",
-            "grpc_resolver_c2p",
-            "grpc_xds_server_config_fetcher",
-        ],
-    },
+    select_deps = [
+        {
+            "grpc_no_xds": [],
+            "//conditions:default": GRPC_XDS_TARGETS,
+        },
+        {
+            "grpc_no_rls": [],
+            "//conditions:default": ["grpc_lb_policy_rls"],
+        },
+    ],
     standalone = True,
     visibility = [
         "@grpc:public",
@@ -391,13 +441,14 @@ grpc_cc_library(
     deps = [
         "config",
         "gpr_base",
-        "grpc_base_c",
+        "grpc_base",
         "grpc_common",
         "grpc_lb_policy_grpclb_secure",
         "grpc_secure",
         "grpc_trace",
         "grpc_transport_chttp2_client_secure",
         "grpc_transport_chttp2_server_secure",
+        "slice",
     ],
 )
 
@@ -421,19 +472,28 @@ grpc_cc_library(
     ],
     language = "c++",
     public_hdrs = GRPCXX_PUBLIC_HDRS,
-    select_deps = {
-        "grpc_no_xds": [],
-        "//conditions:default": [
-            "grpc++_xds_client",
-            "grpc++_xds_server",
-        ],
-    },
+    select_deps = [
+        {
+            "grpc_no_xds": [],
+            "//conditions:default": [
+                "grpc++_xds_client",
+                "grpc++_xds_server",
+            ],
+        },
+        {
+            "grpc_no_binder": [],
+            "//conditions:default": [
+                "grpc++_binder",
+            ],
+        },
+    ],
     standalone = True,
     visibility = [
         "@grpc:public",
     ],
     deps = [
         "grpc++_internals",
+        "slice",
     ],
 )
 
@@ -467,16 +527,94 @@ grpc_cc_library(
     language = "c++",
     public_hdrs = GRPCXX_PUBLIC_HDRS,
     deps = [
+        "error",
         "gpr_base",
         "grpc",
         "grpc++_base",
         "grpc++_codegen_base",
         "grpc++_codegen_base_src",
         "grpc++_codegen_proto",
-        "grpc_base_c",
+        "grpc_base",
         "grpc_codegen",
         "grpc_secure",
+        "json",
         "ref_counted_ptr",
+        "slice",
+    ],
+)
+
+grpc_cc_library(
+    name = "grpc++_binder",
+    srcs = [
+        "src/core/ext/transport/binder/client/binder_connector.cc",
+        "src/core/ext/transport/binder/client/channel_create.cc",
+        "src/core/ext/transport/binder/client/channel_create_impl.cc",
+        "src/core/ext/transport/binder/client/connection_id_generator.cc",
+        "src/core/ext/transport/binder/client/endpoint_binder_pool.cc",
+        "src/core/ext/transport/binder/client/jni_utils.cc",
+        "src/core/ext/transport/binder/client/security_policy_setting.cc",
+        "src/core/ext/transport/binder/security_policy/binder_security_policy.cc",
+        "src/core/ext/transport/binder/server/binder_server.cc",
+        "src/core/ext/transport/binder/server/binder_server_credentials.cc",
+        "src/core/ext/transport/binder/transport/binder_transport.cc",
+        "src/core/ext/transport/binder/utils/transport_stream_receiver_impl.cc",
+        "src/core/ext/transport/binder/wire_format/binder_android.cc",
+        "src/core/ext/transport/binder/wire_format/binder_constants.cc",
+        "src/core/ext/transport/binder/wire_format/transaction.cc",
+        "src/core/ext/transport/binder/wire_format/wire_reader_impl.cc",
+        "src/core/ext/transport/binder/wire_format/wire_writer.cc",
+    ],
+    hdrs = [
+        "src/core/ext/transport/binder/client/binder_connector.h",
+        "src/core/ext/transport/binder/client/channel_create_impl.h",
+        "src/core/ext/transport/binder/client/connection_id_generator.h",
+        "src/core/ext/transport/binder/client/endpoint_binder_pool.h",
+        "src/core/ext/transport/binder/client/jni_utils.h",
+        "src/core/ext/transport/binder/client/security_policy_setting.h",
+        "src/core/ext/transport/binder/server/binder_server.h",
+        "src/core/ext/transport/binder/transport/binder_stream.h",
+        "src/core/ext/transport/binder/transport/binder_transport.h",
+        "src/core/ext/transport/binder/utils/transport_stream_receiver.h",
+        "src/core/ext/transport/binder/utils/transport_stream_receiver_impl.h",
+        "src/core/ext/transport/binder/wire_format/binder.h",
+        "src/core/ext/transport/binder/wire_format/binder_android.h",
+        "src/core/ext/transport/binder/wire_format/binder_constants.h",
+        "src/core/ext/transport/binder/wire_format/transaction.h",
+        "src/core/ext/transport/binder/wire_format/wire_reader.h",
+        "src/core/ext/transport/binder/wire_format/wire_reader_impl.h",
+        "src/core/ext/transport/binder/wire_format/wire_writer.h",
+    ],
+    defines = select({
+        "grpc_no_binder": ["GRPC_NO_BINDER"],
+        "//conditions:default": [],
+    }),
+    external_deps = [
+        "absl/base:core_headers",
+        "absl/container:flat_hash_map",
+        "absl/memory",
+        "absl/status",
+        "absl/strings",
+        "absl/synchronization",
+        "absl/status:statusor",
+        "absl/time",
+    ],
+    language = "c++",
+    public_hdrs = [
+        "include/grpcpp/security/binder_security_policy.h",
+        "include/grpcpp/create_channel_binder.h",
+        "include/grpcpp/security/binder_credentials.h",
+    ],
+    deps = [
+        "gpr",
+        "gpr_base",
+        "gpr_platform",
+        "grpc",
+        "grpc++_base",
+        "grpc_base",
+        "grpc_client_channel",
+        "grpc_codegen",
+        "orphanable",
+        "slice_refcount",
     ],
 )
 
@@ -602,7 +740,7 @@ grpc_cc_library(
     visibility = ["@grpc:public"],
     deps = [
         "gpr_base",
-        "grpc_base_c",
+        "grpc_base",
         "grpc_trace",
     ],
 )
@@ -615,13 +753,21 @@ grpc_cc_library(
     external_deps = [
         "absl/synchronization",
     ],
-    language = "c++",
     deps = [
         "gpr_codegen",
     ],
 )
 
 grpc_cc_library(
+    name = "useful",
+    hdrs = ["src/core/lib/gpr/useful.h"],
+    language = "c++",
+    deps = [
+        "gpr_platform",
+    ],
+)
+
+grpc_cc_library(
     name = "gpr_base",
     srcs = [
         "src/core/lib/gpr/alloc.cc",
@@ -679,7 +825,6 @@ grpc_cc_library(
         "src/core/lib/gpr/string_windows.h",
         "src/core/lib/gpr/time_precise.h",
         "src/core/lib/gpr/tmpfile.h",
-        "src/core/lib/gpr/useful.h",
         "src/core/lib/gprpp/arena.h",
         "src/core/lib/gprpp/examine_stack.h",
         "src/core/lib/gprpp/fork.h",
@@ -721,6 +866,8 @@ grpc_cc_library(
         "gpr_codegen",
         "gpr_tls",
         "grpc_codegen",
+        "protobuf_any_upb",
+        "useful",
     ],
 )
 
@@ -731,6 +878,16 @@ grpc_cc_library(
 )
 
 grpc_cc_library(
+    name = "chunked_vector",
+    hdrs = ["src/core/lib/gprpp/chunked_vector.h"],
+    external_deps = ["absl/utility"],
+    deps = [
+        # TODO(ctiller): weaken this to just arena when that splits into its own target
+        "gpr_base",
+    ],
+)
+
+grpc_cc_library(
     name = "capture",
     external_deps = ["absl/utility"],
     language = "c++",
@@ -774,6 +931,7 @@ grpc_cc_library(
     language = "c++",
     public_hdrs = [
         "include/grpc/impl/codegen/port_platform.h",
+        "include/grpc/support/port_platform.h",
     ],
 )
 
@@ -800,7 +958,8 @@ grpc_cc_library(
         "src/core/lib/config/core_configuration.h",
     ],
     deps = [
-        "gpr_platform",
+        "channel_init",
+        "gpr_base",
         "handshaker_registry",
     ],
 )
@@ -849,6 +1008,7 @@ grpc_cc_library(
     public_hdrs = ["src/core/lib/gprpp/bitset.h"],
     deps = [
         "gpr_platform",
+        "useful",
     ],
 )
 
@@ -1103,6 +1263,18 @@ grpc_cc_library(
 )
 
 grpc_cc_library(
+    name = "exec_ctx_wakeup_scheduler",
+    hdrs = [
+        "src/core/lib/promise/exec_ctx_wakeup_scheduler.h",
+    ],
+    language = "c++",
+    deps = [
+        "exec_ctx",
+        "gpr_base",
+    ],
+)
+
+grpc_cc_library(
     name = "wait_set",
     external_deps = [
         "absl/container:flat_hash_set",
@@ -1252,7 +1424,171 @@ grpc_cc_library(
 )
 
 grpc_cc_library(
-    name = "grpc_base_c",
+    name = "event_engine_memory_allocator",
+    srcs = [
+        "src/core/lib/event_engine/memory_allocator.cc",
+    ],
+    hdrs = [
+        "include/grpc/event_engine/internal/memory_allocator_impl.h",
+        "include/grpc/event_engine/memory_allocator.h",
+    ],
+    language = "c++",
+    deps = [
+        "gpr_platform",
+        "ref_counted",
+        "slice",
+        "slice_refcount",
+    ],
+)
+
+grpc_cc_library(
+    name = "memory_quota",
+    srcs = [
+        "src/core/lib/resource_quota/memory_quota.cc",
+    ],
+    hdrs = [
+        "src/core/lib/resource_quota/memory_quota.h",
+    ],
+    deps = [
+        "activity",
+        "dual_ref_counted",
+        "event_engine_memory_allocator",
+        "exec_ctx_wakeup_scheduler",
+        "gpr_base",
+        "loop",
+        "orphanable",
+        "poll",
+        "race",
+        "ref_counted_ptr",
+        "seq",
+        "slice_refcount",
+        "useful",
+    ],
+)
+
+grpc_cc_library(
+    name = "thread_quota",
+    srcs = [
+        "src/core/lib/resource_quota/thread_quota.cc",
+    ],
+    hdrs = [
+        "src/core/lib/resource_quota/thread_quota.h",
+    ],
+    deps = [
+        "gpr_base",
+        "ref_counted",
+    ],
+)
+
+grpc_cc_library(
+    name = "resource_quota",
+    srcs = [
+        "src/core/lib/resource_quota/resource_quota.cc",
+    ],
+    hdrs = [
+        "src/core/lib/resource_quota/resource_quota.h",
+    ],
+    deps = [
+        "gpr_base",
+        "memory_quota",
+        "ref_counted",
+        "thread_quota",
+    ],
+)
+
+grpc_cc_library(
+    name = "slice_refcount",
+    srcs = [
+        "src/core/lib/slice/slice_refcount.cc",
+        "src/core/lib/slice/static_slice.cc",
+    ],
+    hdrs = [
+        "src/core/lib/slice/slice_refcount.h",
+        "src/core/lib/slice/slice_refcount_base.h",
+        "src/core/lib/slice/slice_utils.h",
+        "src/core/lib/slice/static_slice.h",
+    ],
+    public_hdrs = [
+        "include/grpc/slice.h",
+    ],
+    deps = [
+        "gpr_base",
+        "ref_counted",
+    ],
+)
+
+grpc_cc_library(
+    name = "slice",
+    srcs = [
+        "src/core/lib/slice/slice.cc",
+        "src/core/lib/slice/slice_string_helpers.cc",
+    ],
+    hdrs = [
+        "src/core/lib/slice/slice_internal.h",
+        "src/core/lib/slice/slice_string_helpers.h",
+    ],
+    deps = [
+        "gpr_base",
+        "ref_counted",
+        "slice_refcount",
+    ],
+)
+
+grpc_cc_library(
+    name = "error",
+    srcs = [
+        "src/core/lib/iomgr/error.cc",
+    ],
+    hdrs = [
+        "src/core/lib/iomgr/error.h",
+        "src/core/lib/iomgr/error_internal.h",
+    ],
+    deps = [
+        "gpr",
+        "grpc_codegen",
+        "grpc_trace",
+        "slice",
+        "slice_refcount",
+        "useful",
+    ],
+)
+
+grpc_cc_library(
+    name = "closure",
+    hdrs = [
+        "src/core/lib/iomgr/closure.h",
+    ],
+    deps = [
+        "error",
+        "gpr",
+    ],
+)
+
+grpc_cc_library(
+    name = "exec_ctx",
+    srcs = [
+        "src/core/lib/iomgr/combiner.cc",
+        "src/core/lib/iomgr/exec_ctx.cc",
+        "src/core/lib/iomgr/executor.cc",
+        "src/core/lib/iomgr/iomgr_internal.cc",
+    ],
+    hdrs = [
+        "src/core/lib/iomgr/combiner.h",
+        "src/core/lib/iomgr/exec_ctx.h",
+        "src/core/lib/iomgr/executor.h",
+        "src/core/lib/iomgr/iomgr_internal.h",
+    ],
+    deps = [
+        "closure",
+        "error",
+        "gpr_base",
+        "gpr_tls",
+        "useful",
+    ],
+)
+
+grpc_cc_library(
+    name = "grpc_base",
     srcs = [
         "src/core/lib/address_utils/parse_address.cc",
         "src/core/lib/address_utils/sockaddr_utils.cc",
@@ -1285,14 +1621,12 @@ grpc_cc_library(
         "src/core/lib/iomgr/buffer_list.cc",
         "src/core/lib/iomgr/call_combiner.cc",
         "src/core/lib/iomgr/cfstream_handle.cc",
-        "src/core/lib/iomgr/combiner.cc",
         "src/core/lib/iomgr/dualstack_socket_posix.cc",
         "src/core/lib/iomgr/endpoint.cc",
         "src/core/lib/iomgr/endpoint_cfstream.cc",
         "src/core/lib/iomgr/endpoint_pair_event_engine.cc",
         "src/core/lib/iomgr/endpoint_pair_posix.cc",
         "src/core/lib/iomgr/endpoint_pair_windows.cc",
-        "src/core/lib/iomgr/error.cc",
         "src/core/lib/iomgr/error_cfstream.cc",
         "src/core/lib/iomgr/ev_apple.cc",
         "src/core/lib/iomgr/ev_epoll1_linux.cc",
@@ -1308,8 +1642,6 @@ grpc_cc_library(
         "src/core/lib/iomgr/event_engine/resolver.cc",
         "src/core/lib/iomgr/event_engine/tcp.cc",
         "src/core/lib/iomgr/event_engine/timer.cc",
-        "src/core/lib/iomgr/exec_ctx.cc",
-        "src/core/lib/iomgr/executor.cc",
         "src/core/lib/iomgr/executor/mpmcqueue.cc",
         "src/core/lib/iomgr/executor/threadpool.cc",
         "src/core/lib/iomgr/fork_posix.cc",
@@ -1323,7 +1655,6 @@ grpc_cc_library(
         "src/core/lib/iomgr/iocp_windows.cc",
         "src/core/lib/iomgr/iomgr.cc",
         "src/core/lib/iomgr/iomgr_custom.cc",
-        "src/core/lib/iomgr/iomgr_internal.cc",
         "src/core/lib/iomgr/iomgr_posix.cc",
         "src/core/lib/iomgr/iomgr_posix_cfstream.cc",
         "src/core/lib/iomgr/iomgr_windows.cc",
@@ -1370,7 +1701,6 @@ grpc_cc_library(
         "src/core/lib/iomgr/timer_generic.cc",
         "src/core/lib/iomgr/timer_heap.cc",
         "src/core/lib/iomgr/timer_manager.cc",
-        "src/core/lib/iomgr/udp_server.cc",
         "src/core/lib/iomgr/unix_sockets_posix.cc",
         "src/core/lib/iomgr/unix_sockets_posix_noop.cc",
         "src/core/lib/iomgr/wakeup_fd_eventfd.cc",
@@ -1378,33 +1708,29 @@ grpc_cc_library(
         "src/core/lib/iomgr/wakeup_fd_pipe.cc",
         "src/core/lib/iomgr/wakeup_fd_posix.cc",
         "src/core/lib/iomgr/work_serializer.cc",
-        "src/core/lib/json/json_reader.cc",
-        "src/core/lib/json/json_util.cc",
-        "src/core/lib/json/json_writer.cc",
         "src/core/lib/slice/b64.cc",
         "src/core/lib/slice/percent_encoding.cc",
-        "src/core/lib/slice/slice.cc",
+        "src/core/lib/slice/slice_api.cc",
         "src/core/lib/slice/slice_buffer.cc",
         "src/core/lib/slice/slice_intern.cc",
-        "src/core/lib/slice/slice_string_helpers.cc",
+        "src/core/lib/slice/slice_split.cc",
         "src/core/lib/surface/api_trace.cc",
+        "src/core/lib/surface/builtins.cc",
         "src/core/lib/surface/byte_buffer.cc",
         "src/core/lib/surface/byte_buffer_reader.cc",
         "src/core/lib/surface/call.cc",
         "src/core/lib/surface/call_details.cc",
         "src/core/lib/surface/call_log_batch.cc",
         "src/core/lib/surface/channel.cc",
-        "src/core/lib/surface/channel_init.cc",
         "src/core/lib/surface/channel_ping.cc",
-        "src/core/lib/surface/channel_stack_type.cc",
         "src/core/lib/surface/completion_queue.cc",
         "src/core/lib/surface/completion_queue_factory.cc",
         "src/core/lib/surface/event_string.cc",
+        "src/core/lib/surface/lame_client.cc",
         "src/core/lib/surface/metadata_array.cc",
         "src/core/lib/surface/server.cc",
         "src/core/lib/surface/validate_metadata.cc",
         "src/core/lib/surface/version.cc",
-        "src/core/lib/transport/authority_override.cc",
         "src/core/lib/transport/bdp_estimator.cc",
         "src/core/lib/transport/byte_stream.cc",
         "src/core/lib/transport/connectivity_state.cc",
@@ -1421,6 +1747,8 @@ grpc_cc_library(
         "src/core/lib/uri/uri_parser.cc",
     ],
     hdrs = [
+        "src/core/lib/transport/error_utils.h",
+        "src/core/lib/transport/http2_errors.h",
         "src/core/lib/address_utils/parse_address.h",
         "src/core/lib/address_utils/sockaddr_utils.h",
         "src/core/lib/avl/avl.h",
@@ -1436,6 +1764,7 @@ grpc_cc_library(
         "src/core/lib/channel/context.h",
         "src/core/lib/channel/handshaker.h",
         "src/core/lib/channel/status_util.h",
+        "src/core/lib/slice/slice_split.h",
         "src/core/lib/compression/algorithm_metadata.h",
         "src/core/lib/compression/compression_args.h",
         "src/core/lib/compression/compression_internal.h",
@@ -1454,15 +1783,11 @@ grpc_cc_library(
         "src/core/lib/iomgr/buffer_list.h",
         "src/core/lib/iomgr/call_combiner.h",
         "src/core/lib/iomgr/cfstream_handle.h",
-        "src/core/lib/iomgr/closure.h",
-        "src/core/lib/iomgr/combiner.h",
         "src/core/lib/iomgr/dynamic_annotations.h",
         "src/core/lib/iomgr/endpoint.h",
         "src/core/lib/iomgr/endpoint_cfstream.h",
         "src/core/lib/iomgr/endpoint_pair.h",
-        "src/core/lib/iomgr/error.h",
         "src/core/lib/iomgr/error_cfstream.h",
-        "src/core/lib/iomgr/error_internal.h",
         "src/core/lib/iomgr/ev_apple.h",
         "src/core/lib/iomgr/ev_epoll1_linux.h",
         "src/core/lib/iomgr/ev_epollex_linux.h",
@@ -1474,8 +1799,6 @@ grpc_cc_library(
         "src/core/lib/iomgr/event_engine/pollset.h",
         "src/core/lib/iomgr/event_engine/promise.h",
         "src/core/lib/iomgr/event_engine/resolved_address_internal.h",
-        "src/core/lib/iomgr/exec_ctx.h",
-        "src/core/lib/iomgr/executor.h",
         "src/core/lib/iomgr/executor/mpmcqueue.h",
         "src/core/lib/iomgr/executor/threadpool.h",
         "src/core/lib/iomgr/gethostname.h",
@@ -1484,7 +1807,6 @@ grpc_cc_library(
         "src/core/lib/iomgr/iocp_windows.h",
         "src/core/lib/iomgr/iomgr.h",
         "src/core/lib/iomgr/iomgr_custom.h",
-        "src/core/lib/iomgr/iomgr_internal.h",
         "src/core/lib/iomgr/is_epollexclusive_available.h",
         "src/core/lib/iomgr/load_file.h",
         "src/core/lib/iomgr/lockfree_event.h",
@@ -1523,24 +1845,17 @@ grpc_cc_library(
         "src/core/lib/iomgr/timer_generic.h",
         "src/core/lib/iomgr/timer_heap.h",
         "src/core/lib/iomgr/timer_manager.h",
-        "src/core/lib/iomgr/udp_server.h",
         "src/core/lib/iomgr/unix_sockets_posix.h",
         "src/core/lib/iomgr/wakeup_fd_pipe.h",
         "src/core/lib/iomgr/wakeup_fd_posix.h",
         "src/core/lib/iomgr/work_serializer.h",
-        "src/core/lib/json/json.h",
-        "src/core/lib/json/json_util.h",
         "src/core/lib/slice/b64.h",
         "src/core/lib/slice/percent_encoding.h",
-        "src/core/lib/slice/slice_internal.h",
-        "src/core/lib/slice/slice_string_helpers.h",
-        "src/core/lib/slice/slice_utils.h",
         "src/core/lib/surface/api_trace.h",
+        "src/core/lib/surface/builtins.h",
         "src/core/lib/surface/call.h",
         "src/core/lib/surface/call_test_only.h",
         "src/core/lib/surface/channel.h",
-        "src/core/lib/surface/channel_init.h",
-        "src/core/lib/surface/channel_stack_type.h",
         "src/core/lib/surface/completion_queue.h",
         "src/core/lib/surface/completion_queue_factory.h",
         "src/core/lib/surface/event_string.h",
@@ -1548,14 +1863,12 @@ grpc_cc_library(
         "src/core/lib/surface/lame_client.h",
         "src/core/lib/surface/server.h",
         "src/core/lib/surface/validate_metadata.h",
-        "src/core/lib/transport/authority_override.h",
         "src/core/lib/transport/bdp_estimator.h",
         "src/core/lib/transport/byte_stream.h",
         "src/core/lib/transport/connectivity_state.h",
-        "src/core/lib/transport/error_utils.h",
-        "src/core/lib/transport/http2_errors.h",
         "src/core/lib/transport/metadata.h",
         "src/core/lib/transport/metadata_batch.h",
+        "src/core/lib/transport/parsed_metadata.h",
         "src/core/lib/transport/pid_controller.h",
         "src/core/lib/transport/static_metadata.h",
         "src/core/lib/transport/status_conversion.h",
@@ -1564,6 +1877,22 @@ grpc_cc_library(
         "src/core/lib/transport/transport.h",
         "src/core/lib/transport/transport_impl.h",
         "src/core/lib/uri/uri_parser.h",
+    ] +
+    # TODO(ctiller): remove these
+    # These headers used to be vended by this target, but they have been split
+    # out into separate targets now. In order to transition downstream code, we
+    # re-export these headers from here for now, and when LSC's have completed
+    # to clean this up, we'll remove these.
+    [
+        "src/core/lib/iomgr/closure.h",
+        "src/core/lib/iomgr/error.h",
+        "src/core/lib/iomgr/error_internal.h",
+        "src/core/lib/slice/slice_internal.h",
+        "src/core/lib/slice/slice_string_helpers.h",
+        "src/core/lib/iomgr/exec_ctx.h",
+        "src/core/lib/iomgr/executor.h",
+        "src/core/lib/iomgr/combiner.h",
+        "src/core/lib/iomgr/iomgr_internal.h",
     ],
     external_deps = [
         "absl/container:flat_hash_map",
@@ -1582,28 +1911,55 @@ grpc_cc_library(
     visibility = ["@grpc:alt_grpc_base_legacy"],
     deps = [
         "bitset",
+        "channel_stack_type",
+        "chunked_vector",
+        "closure",
+        "config",
         "dual_ref_counted",
+        "error",
+        "exec_ctx",
         "gpr_base",
         "gpr_codegen",
         "gpr_tls",
         "grpc_codegen",
         "grpc_trace",
+        "json",
         "orphanable",
         "ref_counted",
         "ref_counted_ptr",
+        "slice",
+        "slice_refcount",
+        "table",
+        "useful",
     ],
 )
 
 grpc_cc_library(
-    name = "grpc_base",
+    name = "channel_stack_type",
     srcs = [
-        "src/core/lib/surface/lame_client.cc",
+        "src/core/lib/surface/channel_stack_type.cc",
+    ],
+    hdrs = [
+        "src/core/lib/surface/channel_stack_type.h",
     ],
     language = "c++",
-    visibility = ["@grpc:alt_grpc_base_legacy"],
     deps = [
         "gpr_base",
-        "grpc_base_c",
+    ],
+)
+
+grpc_cc_library(
+    name = "channel_init",
+    srcs = [
+        "src/core/lib/surface/channel_init.cc",
+    ],
+    hdrs = [
+        "src/core/lib/surface/channel_init.h",
+    ],
+    language = "c++",
+    deps = [
+        "channel_stack_type",
+        "gpr_base",
     ],
 )
 
@@ -1628,12 +1984,35 @@ grpc_cc_library(
         "grpc_resolver_fake",
         "grpc_resolver_dns_native",
         "grpc_resolver_sockaddr",
+        "grpc_resolver_binder",
         "grpc_transport_chttp2_client_insecure",
         "grpc_transport_chttp2_server_insecure",
         "grpc_transport_inproc",
         "grpc_fault_injection_filter",
-        "grpc_workaround_cronet_compression_filter",
-        "grpc_server_backward_compatibility",
+    ],
+)
+
+grpc_cc_library(
+    name = "grpc_service_config",
+    srcs = [
+        "src/core/ext/service_config/service_config.cc",
+        "src/core/ext/service_config/service_config_parser.cc",
+    ],
+    hdrs = [
+        "src/core/ext/service_config/service_config.h",
+        "src/core/ext/service_config/service_config_call_data.h",
+        "src/core/ext/service_config/service_config_parser.h",
+    ],
+    external_deps = [
+        "absl/container:inlined_vector",
+        "absl/strings",
+    ],
+    language = "c++",
+    deps = [
+        "error",
+        "gpr_base",
+        "grpc_base",
+        "json",
     ],
 )
 
@@ -1665,9 +2044,7 @@ grpc_cc_library(
         "src/core/ext/filters/client_channel/retry_service_config.cc",
         "src/core/ext/filters/client_channel/retry_throttle.cc",
         "src/core/ext/filters/client_channel/server_address.cc",
-        "src/core/ext/filters/client_channel/service_config.cc",
         "src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc",
-        "src/core/ext/filters/client_channel/service_config_parser.cc",
         "src/core/ext/filters/client_channel/subchannel.cc",
         "src/core/ext/filters/client_channel/subchannel_pool_interface.cc",
     ],
@@ -1699,9 +2076,6 @@ grpc_cc_library(
         "src/core/ext/filters/client_channel/retry_service_config.h",
         "src/core/ext/filters/client_channel/retry_throttle.h",
         "src/core/ext/filters/client_channel/server_address.h",
-        "src/core/ext/filters/client_channel/service_config.h",
-        "src/core/ext/filters/client_channel/service_config_call_data.h",
-        "src/core/ext/filters/client_channel/service_config_parser.h",
         "src/core/ext/filters/client_channel/subchannel.h",
         "src/core/ext/filters/client_channel/subchannel_interface.h",
         "src/core/ext/filters/client_channel/subchannel_pool_interface.h",
@@ -1715,21 +2089,74 @@ grpc_cc_library(
         "upb_lib",
     ],
     language = "c++",
-    visibility = ["@grpc:client_channel"],
+    visibility = ["@grpc:client_channel"],
+    deps = [
+        "config",
+        "debug_location",
+        "error",
+        "gpr_base",
+        "grpc_base",
+        "grpc_client_authority_filter",
+        "grpc_deadline_filter",
+        "grpc_health_upb",
+        "grpc_service_config",
+        "grpc_trace",
+        "handshaker_registry",
+        "json",
+        "json_util",
+        "orphanable",
+        "ref_counted",
+        "ref_counted_ptr",
+        "slice",
+        "useful",
+        "xds_orca_upb",
+    ],
+)
+
+grpc_cc_library(
+    name = "grpc_server_config_selector",
+    srcs = [
+        "src/core/ext/filters/server_config_selector/server_config_selector.cc",
+    ],
+    hdrs = [
+        "src/core/ext/filters/server_config_selector/server_config_selector.h",
+    ],
+    language = "c++",
+    deps = [
+        "gpr_base",
+        "grpc_base",
+        "grpc_service_config",
+    ],
+)
+
+grpc_cc_library(
+    name = "grpc_server_config_selector_filter",
+    srcs = [
+        "src/core/ext/filters/server_config_selector/server_config_selector_filter.cc",
+    ],
+    hdrs = [
+        "src/core/ext/filters/server_config_selector/server_config_selector_filter.h",
+    ],
+    language = "c++",
+    deps = [
+        "gpr_base",
+        "grpc_base",
+        "grpc_server_config_selector",
+        "grpc_service_config",
+    ],
+)
+
+grpc_cc_library(
+    name = "idle_filter_state",
+    srcs = [
+        "src/core/ext/filters/client_idle/idle_filter_state.cc",
+    ],
+    hdrs = [
+        "src/core/ext/filters/client_idle/idle_filter_state.h",
+    ],
+    language = "c++",
     deps = [
-        "config",
-        "debug_location",
-        "gpr_base",
-        "grpc_base_c",
-        "grpc_client_authority_filter",
-        "grpc_deadline_filter",
-        "grpc_health_upb",
-        "grpc_trace",
-        "handshaker_registry",
-        "orphanable",
-        "ref_counted",
-        "ref_counted_ptr",
-        "udpa_orca_upb",
+        "gpr_platform",
     ],
 )
 
@@ -1738,10 +2165,11 @@ grpc_cc_library(
     srcs = [
         "src/core/ext/filters/client_idle/client_idle_filter.cc",
     ],
-    language = "c++",
     deps = [
+        "config",
         "gpr_base",
-        "grpc_base_c",
+        "grpc_base",
+        "idle_filter_state",
     ],
 )
 
@@ -1755,8 +2183,9 @@ grpc_cc_library(
     ],
     language = "c++",
     deps = [
+        "config",
         "gpr_base",
-        "grpc_base_c",
+        "grpc_base",
     ],
 )
 
@@ -1770,8 +2199,10 @@ grpc_cc_library(
     ],
     language = "c++",
     deps = [
+        "config",
         "gpr_base",
-        "grpc_base_c",
+        "grpc_base",
+        "slice",
     ],
 )
 
@@ -1785,8 +2216,11 @@ grpc_cc_library(
     ],
     language = "c++",
     deps = [
+        "channel_stack_type",
+        "config",
         "gpr_base",
-        "grpc_base_c",
+        "grpc_base",
+        "slice",
     ],
 )
 
@@ -1801,10 +2235,11 @@ grpc_cc_library(
     external_deps = ["absl/strings:str_format"],
     language = "c++",
     deps = [
+        "config",
         "gpr_base",
-        "grpc_base_c",
-        "grpc_client_channel",
+        "grpc_base",
         "grpc_codegen",
+        "grpc_service_config",
         "ref_counted",
         "ref_counted_ptr",
     ],
@@ -1824,8 +2259,9 @@ grpc_cc_library(
     language = "c++",
     deps = [
         "gpr_base",
-        "grpc_base_c",
-        "grpc_client_channel",
+        "grpc_base",
+        "grpc_service_config",
+        "json_util",
     ],
 )
 
@@ -1851,25 +2287,11 @@ grpc_cc_library(
     ],
     language = "c++",
     deps = [
+        "config",
         "gpr_base",
-        "grpc_base_c",
+        "grpc_base",
         "grpc_message_size_filter",
-    ],
-)
-
-grpc_cc_library(
-    name = "grpc_workaround_cronet_compression_filter",
-    srcs = [
-        "src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc",
-    ],
-    hdrs = [
-        "src/core/ext/filters/workarounds/workaround_cronet_compression_filter.h",
-    ],
-    language = "c++",
-    deps = [
-        "gpr_base",
-        "grpc_base_c",
-        "grpc_server_backward_compatibility",
+        "slice",
     ],
 )
 
@@ -1904,8 +2326,9 @@ grpc_cc_library(
     visibility = ["@grpc:grpclb"],
     deps = [
         "gpr_base",
-        "grpc_base_c",
+        "grpc_base",
         "grpc_client_channel",
+        "useful",
     ],
 )
 
@@ -1934,16 +2357,21 @@ grpc_cc_library(
     ],
     language = "c++",
     deps = [
+        "config",
+        "error",
         "google_api_upb",
         "gpr_base",
-        "grpc_base_c",
+        "grpc_base",
         "grpc_client_channel",
         "grpc_grpclb_balancer_addresses",
         "grpc_lb_upb",
         "grpc_resolver_fake",
         "grpc_transport_chttp2_client_insecure",
         "orphanable",
+        "protobuf_duration_upb",
+        "protobuf_timestamp_upb",
         "ref_counted_ptr",
+        "slice",
     ],
 )
 
@@ -1972,9 +2400,11 @@ grpc_cc_library(
     ],
     language = "c++",
     deps = [
+        "config",
+        "error",
         "google_api_upb",
         "gpr_base",
-        "grpc_base_c",
+        "grpc_base",
         "grpc_client_channel",
         "grpc_grpclb_balancer_addresses",
         "grpc_lb_upb",
@@ -1982,7 +2412,44 @@ grpc_cc_library(
         "grpc_secure",
         "grpc_transport_chttp2_client_secure",
         "orphanable",
+        "protobuf_duration_upb",
+        "protobuf_timestamp_upb",
         "ref_counted_ptr",
+        "slice",
+    ],
+)
+
+grpc_upb_proto_library(
+    name = "rls_upb",
+    deps = ["//src/proto/grpc/lookup/v1:rls_proto_descriptor"],
+)
+
+grpc_cc_library(
+    name = "grpc_lb_policy_rls",
+    srcs = [
+        "src/core/ext/filters/client_channel/lb_policy/rls/rls.cc",
+    ],
+    external_deps = [
+        "absl/container:inlined_vector",
+        "absl/hash",
+        "absl/memory",
+        "absl/strings",
+        "upb_lib",
+    ],
+    language = "c++",
+    deps = [
+        "dual_ref_counted",
+        "gpr_base",
+        "gpr_codegen",
+        "grpc_base",
+        "grpc_client_channel",
+        "grpc_codegen",
+        "grpc_secure",
+        "json",
+        "json_util",
+        "orphanable",
+        "ref_counted",
+        "rls_upb",
     ],
 )
 
@@ -2035,10 +2502,11 @@ grpc_cc_library(
         "envoy_core_upb",
         "envoy_core_upbdefs",
         "envoy_type_upb",
+        "error",
         "google_api_upb",
         "gpr_base",
         "gpr_codegen",
-        "grpc_base_c",
+        "grpc_base",
         "grpc_client_channel",
         "grpc_codegen",
         "grpc_fault_injection_filter",
@@ -2046,10 +2514,36 @@ grpc_cc_library(
         "grpc_matchers",
         "grpc_secure",
         "grpc_transport_chttp2_client_secure",
+        "json",
+        "json_util",
         "orphanable",
+        "protobuf_any_upb",
+        "protobuf_duration_upb",
+        "protobuf_struct_upb",
+        "protobuf_timestamp_upb",
+        "protobuf_wrappers_upb",
         "ref_counted_ptr",
-        "udpa_type_upb",
-        "udpa_type_upbdefs",
+        "slice",
+        "slice_refcount",
+        "xds_type_upb",
+        "xds_type_upbdefs",
+    ],
+)
+
+grpc_cc_library(
+    name = "grpc_xds_channel_stack_modifier",
+    srcs = [
+        "src/core/ext/xds/xds_channel_stack_modifier.cc",
+    ],
+    hdrs = [
+        "src/core/ext/xds/xds_channel_stack_modifier.h",
+    ],
+    language = "c++",
+    deps = [
+        "channel_init",
+        "config",
+        "gpr_base",
+        "grpc_base",
     ],
 )
 
@@ -2064,7 +2558,8 @@ grpc_cc_library(
     language = "c++",
     deps = [
         "gpr_base",
-        "grpc_base_c",
+        "grpc_base",
+        "grpc_xds_channel_stack_modifier",
         "grpc_xds_client",
     ],
 )
@@ -2082,9 +2577,12 @@ grpc_cc_library(
     ],
     language = "c++",
     deps = [
+        "error",
         "gpr_base",
-        "grpc_base_c",
+        "grpc_base",
         "grpc_xds_client",
+        "json_util",
+        "slice",
     ],
 )
 
@@ -2099,7 +2597,7 @@ grpc_cc_library(
     language = "c++",
     deps = [
         "gpr_base",
-        "grpc_base_c",
+        "grpc_base",
         "grpc_client_channel",
         "grpc_xds_client",
         "orphanable",
@@ -2123,7 +2621,7 @@ grpc_cc_library(
     language = "c++",
     deps = [
         "gpr_base",
-        "grpc_base_c",
+        "grpc_base",
         "grpc_client_channel",
         "grpc_xds_client",
     ],
@@ -2141,7 +2639,7 @@ grpc_cc_library(
     language = "c++",
     deps = [
         "gpr_base",
-        "grpc_base_c",
+        "grpc_base",
         "grpc_client_channel",
         "grpc_lb_address_filtering",
         "grpc_lb_policy_ring_hash",
@@ -2165,7 +2663,7 @@ grpc_cc_library(
     language = "c++",
     deps = [
         "gpr_base",
-        "grpc_base_c",
+        "grpc_base",
         "grpc_client_channel",
         "grpc_lb_xds_channel_args",
         "grpc_lb_xds_common",
@@ -2187,7 +2685,7 @@ grpc_cc_library(
     language = "c++",
     deps = [
         "gpr_base",
-        "grpc_base_c",
+        "grpc_base",
         "grpc_client_channel",
         "grpc_resolver_xds_header",
         "orphanable",
@@ -2210,7 +2708,7 @@ grpc_cc_library(
     language = "c++",
     deps = [
         "gpr_base",
-        "grpc_base_c",
+        "grpc_base",
         "grpc_client_channel",
     ],
 )
@@ -2223,7 +2721,7 @@ grpc_cc_library(
     language = "c++",
     deps = [
         "gpr_base",
-        "grpc_base_c",
+        "grpc_base",
         "grpc_client_channel",
     ],
 )
@@ -2236,7 +2734,7 @@ grpc_cc_library(
     language = "c++",
     deps = [
         "gpr_base",
-        "grpc_base_c",
+        "grpc_base",
         "grpc_client_channel",
         "grpc_lb_subchannel_list",
     ],
@@ -2257,7 +2755,7 @@ grpc_cc_library(
     language = "c++",
     deps = [
         "gpr_base",
-        "grpc_base_c",
+        "grpc_base",
         "grpc_client_channel",
         "grpc_lb_subchannel_list",
         "grpc_trace",
@@ -2273,7 +2771,7 @@ grpc_cc_library(
     language = "c++",
     deps = [
         "gpr_base",
-        "grpc_base_c",
+        "grpc_base",
         "grpc_client_channel",
         "grpc_lb_subchannel_list",
         "grpc_trace",
@@ -2293,7 +2791,7 @@ grpc_cc_library(
     language = "c++",
     deps = [
         "gpr_base",
-        "grpc_base_c",
+        "grpc_base",
         "grpc_client_channel",
         "grpc_lb_address_filtering",
         "orphanable",
@@ -2313,7 +2811,7 @@ grpc_cc_library(
     language = "c++",
     deps = [
         "gpr_base",
-        "grpc_base_c",
+        "grpc_base",
         "grpc_client_channel",
         "grpc_lb_address_filtering",
         "orphanable",
@@ -2338,10 +2836,12 @@ grpc_cc_library(
     ],
     language = "c++",
     deps = [
+        "error",
         "gpr",
         "grpc++_base",
-        "grpc_base_c",
+        "grpc_base",
         "grpc_secure",
+        "slice",
     ],
     alwayslink = 1,
 )
@@ -2360,7 +2860,7 @@ grpc_cc_library(
         "gpr",
         "gpr_codegen",
         "grpc++",
-        "grpc_base_c",
+        "grpc_base",
     ],
 )
 
@@ -2395,6 +2895,7 @@ grpc_cc_library(
         "gpr_codegen",
         "lb_server_load_reporting_filter",
         "lb_server_load_reporting_service_server_builder_plugin",
+        "slice",
     ],
 )
 
@@ -2466,7 +2967,7 @@ grpc_cc_library(
     language = "c++",
     deps = [
         "gpr_base",
-        "grpc_base_c",
+        "grpc_base",
     ],
 )
 
@@ -2481,7 +2982,7 @@ grpc_cc_library(
     language = "c++",
     deps = [
         "gpr_base",
-        "grpc_base_c",
+        "grpc_base",
         "grpc_client_channel",
         "grpc_resolver_dns_selection",
     ],
@@ -2512,11 +3013,14 @@ grpc_cc_library(
     ],
     language = "c++",
     deps = [
+        "error",
         "gpr_base",
-        "grpc_base_c",
+        "grpc_base",
         "grpc_client_channel",
         "grpc_grpclb_balancer_addresses",
         "grpc_resolver_dns_selection",
+        "grpc_service_config",
+        "json",
     ],
 )
 
@@ -2531,8 +3035,26 @@ grpc_cc_library(
     language = "c++",
     deps = [
         "gpr_base",
-        "grpc_base_c",
+        "grpc_base",
+        "grpc_client_channel",
+        "slice",
+    ],
+)
+
+grpc_cc_library(
+    name = "grpc_resolver_binder",
+    srcs = [
+        "src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc",
+    ],
+    external_deps = [
+        "absl/strings",
+    ],
+    language = "c++",
+    deps = [
+        "gpr_base",
+        "grpc_base",
         "grpc_client_channel",
+        "slice",
     ],
 )
 
@@ -2547,8 +3069,10 @@ grpc_cc_library(
     ],
     deps = [
         "gpr_base",
-        "grpc_base_c",
+        "grpc_base",
         "grpc_client_channel",
+        "slice",
+        "useful",
     ],
 )
 
@@ -2573,7 +3097,7 @@ grpc_cc_library(
     language = "c++",
     deps = [
         "gpr_base",
-        "grpc_base_c",
+        "grpc_base",
         "grpc_client_channel",
         "grpc_lb_policy_ring_hash",
         "grpc_xds_client",
@@ -2589,7 +3113,7 @@ grpc_cc_library(
     deps = [
         "alts_util",
         "gpr_base",
-        "grpc_base_c",
+        "grpc_base",
         "grpc_client_channel",
         "grpc_xds_client",
     ],
@@ -2710,18 +3234,22 @@ grpc_cc_library(
     deps = [
         "alts_util",
         "config",
+        "error",
         "gpr_base",
         "grpc_base",
-        "grpc_base_c",
         "grpc_client_channel",
         "grpc_codegen",
         "grpc_lb_xds_channel_args",
         "grpc_trace",
         "grpc_transport_chttp2_alpn",
+        "json",
         "ref_counted",
         "ref_counted_ptr",
+        "slice",
+        "slice_refcount",
         "tsi",
         "tsi_interface",
+        "useful",
     ],
 )
 
@@ -2738,7 +3266,7 @@ grpc_cc_library(
     language = "c++",
     deps = [
         "google_api_upb",
-        "grpc_base_c",
+        "grpc_base",
     ],
 )
 
@@ -2760,7 +3288,7 @@ grpc_cc_library(
     language = "c++",
     deps = [
         "gpr_base",
-        "grpc_base_c",
+        "grpc_base",
     ],
 )
 
@@ -2784,7 +3312,7 @@ grpc_cc_library(
     language = "c++",
     deps = [
         "gpr_base",
-        "grpc_base_c",
+        "grpc_base",
         "grpc_matchers",
         "grpc_secure",
     ],
@@ -2808,9 +3336,11 @@ grpc_cc_library(
     language = "c++",
     deps = [
         "gpr_base",
+        "grpc_base",
         "grpc_matchers",
         "grpc_rbac_engine",
         "grpc_secure",
+        "useful",
     ],
 )
 
@@ -2851,7 +3381,7 @@ grpc_cc_library(
         "envoy_ads_upb",
         "google_api_upb",
         "gpr_base",
-        "grpc_base_c",
+        "grpc_base",
         "grpc_mock_cel",
         "grpc_rbac_engine",
     ],
@@ -2917,7 +3447,6 @@ grpc_cc_library(
         "src/core/ext/transport/chttp2/transport/bin_decoder.cc",
         "src/core/ext/transport/chttp2/transport/bin_encoder.cc",
         "src/core/ext/transport/chttp2/transport/chttp2_plugin.cc",
-        "src/core/ext/transport/chttp2/transport/chttp2_slice_allocator.cc",
         "src/core/ext/transport/chttp2/transport/chttp2_transport.cc",
         "src/core/ext/transport/chttp2/transport/context_list.cc",
         "src/core/ext/transport/chttp2/transport/flow_control.cc",
@@ -2933,7 +3462,6 @@ grpc_cc_library(
         "src/core/ext/transport/chttp2/transport/hpack_utils.cc",
         "src/core/ext/transport/chttp2/transport/http2_settings.cc",
         "src/core/ext/transport/chttp2/transport/huffsyms.cc",
-        "src/core/ext/transport/chttp2/transport/incoming_metadata.cc",
         "src/core/ext/transport/chttp2/transport/parsing.cc",
         "src/core/ext/transport/chttp2/transport/stream_lists.cc",
         "src/core/ext/transport/chttp2/transport/stream_map.cc",
@@ -2943,7 +3471,6 @@ grpc_cc_library(
     hdrs = [
         "src/core/ext/transport/chttp2/transport/bin_decoder.h",
         "src/core/ext/transport/chttp2/transport/bin_encoder.h",
-        "src/core/ext/transport/chttp2/transport/chttp2_slice_allocator.h",
         "src/core/ext/transport/chttp2/transport/chttp2_transport.h",
         "src/core/ext/transport/chttp2/transport/context_list.h",
         "src/core/ext/transport/chttp2/transport/flow_control.h",
@@ -2960,7 +3487,6 @@ grpc_cc_library(
         "src/core/ext/transport/chttp2/transport/hpack_utils.h",
         "src/core/ext/transport/chttp2/transport/http2_settings.h",
         "src/core/ext/transport/chttp2/transport/huffsyms.h",
-        "src/core/ext/transport/chttp2/transport/incoming_metadata.h",
         "src/core/ext/transport/chttp2/transport/internal.h",
         "src/core/ext/transport/chttp2/transport/stream_map.h",
         "src/core/ext/transport/chttp2/transport/varint.h",
@@ -2976,7 +3502,7 @@ grpc_cc_library(
     visibility = ["@grpc:grpclb"],
     deps = [
         "gpr_base",
-        "grpc_base_c",
+        "grpc_base",
         "grpc_http_filters",
         "grpc_trace",
         "grpc_transport_chttp2_alpn",
@@ -2985,6 +3511,9 @@ grpc_cc_library(
         "hpack_encoder_table",
         "match",
         "popularity_count",
+        "slice",
+        "slice_refcount",
+        "useful",
     ],
 )
 
@@ -2999,26 +3528,26 @@ grpc_cc_library(
     language = "c++",
     deps = [
         "gpr_base",
+        "useful",
     ],
 )
 
 grpc_cc_library(
     name = "grpc_transport_chttp2_client_connector",
     srcs = [
-        "src/core/ext/transport/chttp2/client/authority.cc",
         "src/core/ext/transport/chttp2/client/chttp2_connector.cc",
     ],
     hdrs = [
-        "src/core/ext/transport/chttp2/client/authority.h",
         "src/core/ext/transport/chttp2/client/chttp2_connector.h",
     ],
     language = "c++",
     deps = [
         "config",
         "gpr_base",
-        "grpc_base_c",
+        "grpc_base",
         "grpc_client_channel",
         "grpc_transport_chttp2",
+        "slice",
     ],
 )
 
@@ -3031,7 +3560,7 @@ grpc_cc_library(
     language = "c++",
     deps = [
         "gpr_base",
-        "grpc_base_c",
+        "grpc_base",
         "grpc_client_channel",
         "grpc_transport_chttp2",
         "grpc_transport_chttp2_client_connector",
@@ -3045,12 +3574,14 @@ grpc_cc_library(
     ],
     language = "c++",
     deps = [
+        "error",
         "gpr_base",
-        "grpc_base_c",
+        "grpc_base",
         "grpc_client_channel",
         "grpc_secure",
         "grpc_transport_chttp2",
         "grpc_transport_chttp2_client_connector",
+        "slice",
     ],
 )
 
@@ -3070,12 +3601,13 @@ grpc_cc_library(
     deps = [
         "config",
         "gpr_base",
-        "grpc_base_c",
+        "grpc_base",
         "grpc_codegen",
         "grpc_http_filters",
         "grpc_transport_chttp2",
         "ref_counted",
         "ref_counted_ptr",
+        "slice",
     ],
 )
 
@@ -3091,7 +3623,7 @@ grpc_cc_library(
     language = "c++",
     deps = [
         "gpr_base",
-        "grpc_base_c",
+        "grpc_base",
         "grpc_transport_chttp2",
         "grpc_transport_chttp2_server",
     ],
@@ -3108,7 +3640,7 @@ grpc_cc_library(
     language = "c++",
     deps = [
         "gpr_base",
-        "grpc_base_c",
+        "grpc_base",
         "grpc_secure",
         "grpc_transport_chttp2",
         "grpc_transport_chttp2_server",
@@ -3128,8 +3660,9 @@ grpc_cc_library(
     language = "c++",
     deps = [
         "gpr_base",
-        "grpc_base_c",
+        "grpc_base",
         "grpc_trace",
+        "slice",
     ],
 )
 
@@ -3191,8 +3724,10 @@ grpc_cc_library(
     visibility = ["@grpc:alts_frame_protector"],
     deps = [
         "gpr_base",
-        "grpc_base_c",
+        "grpc_base",
+        "slice",
         "tsi_interface",
+        "useful",
     ],
 )
 
@@ -3222,7 +3757,7 @@ grpc_cc_library(
     deps = [
         "alts_upb",
         "gpr",
-        "grpc_base_c",
+        "grpc_base",
     ],
 )
 
@@ -3267,9 +3802,11 @@ grpc_cc_library(
         "alts_frame_protector",
         "alts_util",
         "gpr_base",
-        "grpc_base_c",
+        "grpc_base",
         "grpc_transport_chttp2_client_insecure",
+        "slice",
         "tsi_interface",
+        "useful",
     ],
 )
 
@@ -3287,18 +3824,20 @@ grpc_cc_library(
     public_hdrs = GRPCXX_PUBLIC_HDRS,
     visibility = ["@grpc:alt_grpc++_base_legacy"],
     deps = [
+        "config",
         "gpr_base",
         "grpc",
         "grpc++_codegen_base",
         "grpc++_codegen_base_src",
         "grpc++_internal_hdrs_only",
-        "grpc_base_c",
-        "grpc_client_channel",
+        "grpc_base",
         "grpc_codegen",
         "grpc_health_upb",
+        "grpc_service_config",
         "grpc_trace",
         "grpc_transport_inproc",
         "ref_counted",
+        "useful",
     ],
 )
 
@@ -3317,18 +3856,20 @@ grpc_cc_library(
     tags = ["avoid_dep"],
     visibility = ["@grpc:alt_grpc++_base_unsecure_legacy"],
     deps = [
+        "config",
         "gpr_base",
         "grpc++_codegen_base",
         "grpc++_codegen_base_src",
         "grpc++_internal_hdrs_only",
-        "grpc_base_c",
-        "grpc_client_channel",
+        "grpc_base",
         "grpc_codegen",
         "grpc_health_upb",
+        "grpc_service_config",
         "grpc_trace",
         "grpc_transport_inproc",
         "grpc_unsecure",
         "ref_counted",
+        "useful",
     ],
 )
 
@@ -3544,10 +4085,10 @@ grpc_cc_library(
     public_hdrs = [
         "include/grpcpp/ext/admin_services.h",
     ],
-    select_deps = {
+    select_deps = [{
         "grpc_no_xds": [],
         "//conditions:default": ["//:grpcpp_csds"],
-    },
+    }],
     deps = [
         "gpr",
         "grpc++",
@@ -3578,22 +4119,7 @@ grpc_cc_library(
     deps = [
         "gpr_base",
         "grpc++",
-        "grpc_base_c",
-    ],
-)
-
-grpc_cc_library(
-    name = "grpc_server_backward_compatibility",
-    srcs = [
-        "src/core/ext/filters/workarounds/workaround_utils.cc",
-    ],
-    hdrs = [
-        "src/core/ext/filters/workarounds/workaround_utils.h",
-    ],
-    language = "c++",
-    deps = [
-        "gpr_base",
-        "grpc_base_c",
+        "grpc_base",
     ],
 )
 
@@ -3654,7 +4180,7 @@ grpc_cc_library(
         "census",
         "gpr_base",
         "grpc++",
-        "grpc_base_c",
+        "grpc_base",
     ],
 )
 
@@ -3805,6 +4331,11 @@ grpc_cc_library(
         "envoy_type_upb",
         "google_api_upb",
         "proto_gen_validate_upb",
+        "protobuf_any_upb",
+        "protobuf_duration_upb",
+        "protobuf_struct_upb",
+        "protobuf_timestamp_upb",
+        "protobuf_wrappers_upb",
         "udpa_annotations_upb",
         "xds_core_upb",
     ],
@@ -4008,7 +4539,13 @@ grpc_cc_library(
         "envoy_type_upb",
         "google_api_upb",
         "proto_gen_validate_upb",
+        "protobuf_any_upb",
+        "protobuf_duration_upb",
+        "protobuf_empty_upb",
+        "protobuf_struct_upb",
+        "protobuf_wrappers_upb",
         "udpa_annotations_upb",
+        "xds_annotations_upb",
         "xds_core_upb",
     ],
 )
@@ -4107,6 +4644,7 @@ grpc_cc_library(
         "envoy_annotations_upb",
         "google_api_upb",
         "proto_gen_validate_upb",
+        "protobuf_wrappers_upb",
         "udpa_annotations_upb",
     ],
 )
@@ -4176,6 +4714,8 @@ grpc_cc_library(
     language = "c++",
     deps = [
         "google_api_upb",
+        "protobuf_duration_upb",
+        "protobuf_timestamp_upb",
     ],
 )
 
@@ -4201,19 +4741,19 @@ grpc_cc_library(
     ],
 )
 
-# Once upb code-gen issue is resolved, replace udpa_orca_upb with this.
+# Once upb code-gen issue is resolved, replace xds_orca_upb with this.
 # grpc_upb_proto_library(
-#     name = "udpa_orca_upb",
-#     deps = ["@envoy_api//udpa/data/orca/v1:orca_load_report"]
+#     name = "xds_orca_upb",
+#     deps = ["@envoy_api//xds/data/orca/v3:orca_load_report"]
 # )
 
 grpc_cc_library(
-    name = "udpa_orca_upb",
+    name = "xds_orca_upb",
     srcs = [
-        "src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c",
+        "src/core/ext/upb-generated/xds/data/orca/v3/orca_load_report.upb.c",
     ],
     hdrs = [
-        "src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h",
+        "src/core/ext/upb-generated/xds/data/orca/v3/orca_load_report.upb.h",
     ],
     external_deps = [
         "upb_lib",
@@ -4285,6 +4825,43 @@ grpc_cc_library(
 )
 
 grpc_cc_library(
+    name = "xds_annotations_upb",
+    srcs = [
+        "src/core/ext/upb-generated/xds/annotations/v3/status.upb.c",
+    ],
+    hdrs = [
+        "src/core/ext/upb-generated/xds/annotations/v3/status.upb.h",
+    ],
+    external_deps = [
+        "upb_lib",
+        "upb_lib_descriptor",
+        "upb_generated_code_support__only_for_generated_code_do_not_use__i_give_permission_to_break_me",
+    ],
+    language = "c++",
+)
+
+grpc_cc_library(
+    name = "xds_annotations_upbdefs",
+    srcs = [
+        "src/core/ext/upbdefs-generated/xds/annotations/v3/status.upbdefs.c",
+    ],
+    hdrs = [
+        "src/core/ext/upbdefs-generated/xds/annotations/v3/status.upbdefs.h",
+    ],
+    external_deps = [
+        "upb_lib",
+        "upb_lib_descriptor_reflection",
+        "upb_textformat_lib",
+        "upb_reflection",
+        "upb_generated_code_support__only_for_generated_code_do_not_use__i_give_permission_to_break_me",
+    ],
+    language = "c++",
+    deps = [
+        "xds_annotations_upb",
+    ],
+)
+
+grpc_cc_library(
     name = "xds_core_upb",
     srcs = [
         "src/core/ext/upb-generated/xds/core/v3/authority.upb.c",
@@ -4311,7 +4888,9 @@ grpc_cc_library(
     deps = [
         "google_api_upb",
         "proto_gen_validate_upb",
+        "protobuf_any_upb",
         "udpa_annotations_upb",
+        "xds_annotations_upb",
     ],
 )
 
@@ -4345,17 +4924,18 @@ grpc_cc_library(
         "google_api_upbdefs",
         "proto_gen_validate_upbdefs",
         "udpa_annotations_upbdefs",
+        "xds_annotations_upbdefs",
         "xds_core_upb",
     ],
 )
 
 grpc_cc_library(
-    name = "udpa_type_upb",
+    name = "xds_type_upb",
     srcs = [
-        "src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.c",
+        "src/core/ext/upb-generated/xds/type/v3/typed_struct.upb.c",
     ],
     hdrs = [
-        "src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.h",
+        "src/core/ext/upb-generated/xds/type/v3/typed_struct.upb.h",
     ],
     external_deps = [
         "upb_lib",
@@ -4366,16 +4946,17 @@ grpc_cc_library(
     deps = [
         "google_api_upb",
         "proto_gen_validate_upb",
+        "protobuf_struct_upb",
     ],
 )
 
 grpc_cc_library(
-    name = "udpa_type_upbdefs",
+    name = "xds_type_upbdefs",
     srcs = [
-        "src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.c",
+        "src/core/ext/upbdefs-generated/xds/type/v3/typed_struct.upbdefs.c",
     ],
     hdrs = [
-        "src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.h",
+        "src/core/ext/upbdefs-generated/xds/type/v3/typed_struct.upbdefs.h",
     ],
     external_deps = [
         "upb_lib",
@@ -4391,28 +4972,30 @@ grpc_cc_library(
     ],
 )
 
-# Once upb code-gen issue is resolved, replace grpc_health_upb with this.
-# grpc_upb_proto_library(
-#     name = "grpc_health_upb",
-#     deps = ["//src/proto/grpc/health/v1:health_proto_descriptor"],
-# )
-
-grpc_cc_library(
+grpc_upb_proto_library(
     name = "grpc_health_upb",
-    srcs = [
-        "src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.c",
-    ],
-    hdrs = [
-        "src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.h",
-    ],
-    external_deps = [
-        "upb_lib",
-        "upb_lib_descriptor",
-        "upb_generated_code_support__only_for_generated_code_do_not_use__i_give_permission_to_break_me",
-    ],
-    language = "c++",
+    deps = ["//src/proto/grpc/health/v1:health_proto_descriptor"],
 )
 
+WELL_KNOWN_PROTO_TARGETS = [
+    "any",
+    "duration",
+    "empty",
+    "struct",
+    "timestamp",
+    "wrappers",
+]
+
+[grpc_upb_proto_library(
+    name = "protobuf_" + target + "_upb",
+    deps = ["@com_google_protobuf//:" + target + "_proto"],
+) for target in WELL_KNOWN_PROTO_TARGETS]
+
+[grpc_upb_proto_reflection_library(
+    name = "protobuf_" + target + "_upbdefs",
+    deps = ["@com_google_protobuf//:" + target + "_proto"],
+) for target in WELL_KNOWN_PROTO_TARGETS]
+
 # Once upb code-gen issue is resolved, remove this.
 grpc_cc_library(
     name = "google_api_upb",
@@ -4421,12 +5004,6 @@ grpc_cc_library(
         "src/core/ext/upb-generated/google/api/expr/v1alpha1/checked.upb.c",
         "src/core/ext/upb-generated/google/api/expr/v1alpha1/syntax.upb.c",
         "src/core/ext/upb-generated/google/api/http.upb.c",
-        "src/core/ext/upb-generated/google/protobuf/any.upb.c",
-        "src/core/ext/upb-generated/google/protobuf/duration.upb.c",
-        "src/core/ext/upb-generated/google/protobuf/empty.upb.c",
-        "src/core/ext/upb-generated/google/protobuf/struct.upb.c",
-        "src/core/ext/upb-generated/google/protobuf/timestamp.upb.c",
-        "src/core/ext/upb-generated/google/protobuf/wrappers.upb.c",
         "src/core/ext/upb-generated/google/rpc/status.upb.c",
     ],
     hdrs = [
@@ -4434,12 +5011,6 @@ grpc_cc_library(
         "src/core/ext/upb-generated/google/api/expr/v1alpha1/checked.upb.h",
         "src/core/ext/upb-generated/google/api/expr/v1alpha1/syntax.upb.h",
         "src/core/ext/upb-generated/google/api/http.upb.h",
-        "src/core/ext/upb-generated/google/protobuf/any.upb.h",
-        "src/core/ext/upb-generated/google/protobuf/duration.upb.h",
-        "src/core/ext/upb-generated/google/protobuf/empty.upb.h",
-        "src/core/ext/upb-generated/google/protobuf/struct.upb.h",
-        "src/core/ext/upb-generated/google/protobuf/timestamp.upb.h",
-        "src/core/ext/upb-generated/google/protobuf/wrappers.upb.h",
         "src/core/ext/upb-generated/google/rpc/status.upb.h",
     ],
     external_deps = [
@@ -4448,6 +5019,14 @@ grpc_cc_library(
         "upb_generated_code_support__only_for_generated_code_do_not_use__i_give_permission_to_break_me",
     ],
     language = "c++",
+    deps = [
+        "protobuf_any_upb",
+        "protobuf_duration_upb",
+        "protobuf_empty_upb",
+        "protobuf_struct_upb",
+        "protobuf_timestamp_upb",
+        "protobuf_wrappers_upb",
+    ],
 )
 
 grpc_cc_library(
@@ -4455,23 +5034,11 @@ grpc_cc_library(
     srcs = [
         "src/core/ext/upbdefs-generated/google/api/annotations.upbdefs.c",
         "src/core/ext/upbdefs-generated/google/api/http.upbdefs.c",
-        "src/core/ext/upbdefs-generated/google/protobuf/any.upbdefs.c",
-        "src/core/ext/upbdefs-generated/google/protobuf/duration.upbdefs.c",
-        "src/core/ext/upbdefs-generated/google/protobuf/empty.upbdefs.c",
-        "src/core/ext/upbdefs-generated/google/protobuf/struct.upbdefs.c",
-        "src/core/ext/upbdefs-generated/google/protobuf/timestamp.upbdefs.c",
-        "src/core/ext/upbdefs-generated/google/protobuf/wrappers.upbdefs.c",
         "src/core/ext/upbdefs-generated/google/rpc/status.upbdefs.c",
     ],
     hdrs = [
         "src/core/ext/upbdefs-generated/google/api/annotations.upbdefs.h",
         "src/core/ext/upbdefs-generated/google/api/http.upbdefs.h",
-        "src/core/ext/upbdefs-generated/google/protobuf/any.upbdefs.h",
-        "src/core/ext/upbdefs-generated/google/protobuf/duration.upbdefs.h",
-        "src/core/ext/upbdefs-generated/google/protobuf/empty.upbdefs.h",
-        "src/core/ext/upbdefs-generated/google/protobuf/struct.upbdefs.h",
-        "src/core/ext/upbdefs-generated/google/protobuf/timestamp.upbdefs.h",
-        "src/core/ext/upbdefs-generated/google/protobuf/wrappers.upbdefs.h",
         "src/core/ext/upbdefs-generated/google/rpc/status.upbdefs.h",
     ],
     external_deps = [
@@ -4483,33 +5050,18 @@ grpc_cc_library(
     ],
     language = "c++",
     deps = [
-        "google_api_upb",
+        "protobuf_any_upbdefs",
+        "protobuf_duration_upbdefs",
+        "protobuf_empty_upbdefs",
+        "protobuf_struct_upbdefs",
+        "protobuf_timestamp_upbdefs",
+        "protobuf_wrappers_upbdefs",
     ],
 )
 
-# Once upb code-gen issue is resolved, replace grpc_lb_upb with this.
-# grpc_upb_proto_library(
-#     name = "grpc_lb_upb",
-#     deps = ["//src/proto/grpc/lb/v1:load_balancer_proto_descriptor"],
-# )
-
-grpc_cc_library(
+grpc_upb_proto_library(
     name = "grpc_lb_upb",
-    srcs = [
-        "src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c",
-    ],
-    hdrs = [
-        "src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.h",
-    ],
-    external_deps = [
-        "upb_lib",
-        "upb_lib_descriptor",
-        "upb_generated_code_support__only_for_generated_code_do_not_use__i_give_permission_to_break_me",
-    ],
-    language = "c++",
-    deps = [
-        "google_api_upb",
-    ],
+    deps = ["//src/proto/grpc/lb/v1:load_balancer_proto_descriptor"],
 )
 
 # Once upb code-gen issue is resolved, replace meshca_upb with this.
@@ -4532,33 +5084,46 @@ grpc_cc_library(
     language = "c++",
     deps = [
         "google_api_upb",
+        "protobuf_duration_upb",
     ],
 )
 
-# Once upb code-gen issue is resolved, replace alts_upb with this.
-# grpc_upb_proto_library(
-#     name = "alts_upb",
-#     deps = ["//src/proto/grpc/gcp:alts_handshaker_proto"],
-# )
+grpc_upb_proto_library(
+    name = "alts_upb",
+    deps = ["//src/proto/grpc/gcp:alts_handshaker_proto"],
+)
 
 grpc_cc_library(
-    name = "alts_upb",
+    name = "json",
     srcs = [
-        "src/core/ext/upb-generated/src/proto/grpc/gcp/altscontext.upb.c",
-        "src/core/ext/upb-generated/src/proto/grpc/gcp/handshaker.upb.c",
-        "src/core/ext/upb-generated/src/proto/grpc/gcp/transport_security_common.upb.c",
+        "src/core/lib/json/json_reader.cc",
+        "src/core/lib/json/json_writer.cc",
     ],
     hdrs = [
-        "src/core/ext/upb-generated/src/proto/grpc/gcp/altscontext.upb.h",
-        "src/core/ext/upb-generated/src/proto/grpc/gcp/handshaker.upb.h",
-        "src/core/ext/upb-generated/src/proto/grpc/gcp/transport_security_common.upb.h",
+        "src/core/lib/json/json.h",
     ],
     external_deps = [
-        "upb_lib",
-        "upb_lib_descriptor",
-        "upb_generated_code_support__only_for_generated_code_do_not_use__i_give_permission_to_break_me",
+        "absl/strings",
+        "absl/strings:str_format",
+    ],
+    deps = [
+        "error",
+        "exec_ctx",
+        "gpr_base",
+    ],
+)
+
+grpc_cc_library(
+    name = "json_util",
+    srcs = ["src/core/lib/json/json_util.cc"],
+    hdrs = ["src/core/lib/json/json_util.h"],
+    external_deps = [
+        "absl/strings",
+    ],
+    deps = [
+        "gpr_base",
+        "json",
     ],
-    language = "c++",
 )
 
 grpc_generate_one_off_targets()
index 3c8e241..80dadc6 100644 (file)
@@ -272,7 +272,7 @@ $ make
 By default gRPC uses [protocol buffers](https://github.com/protocolbuffers/protobuf),
 you will need the `protoc` compiler to generate stub server and client code.
 
-If you compile gRPC from source, as described below, the Makefile will
+If you compile gRPC from source, as described above, the Makefile will
 automatically try compiling the `protoc` in third_party if you cloned the
 repository recursively and it detects that you do not already have 'protoc' compiler
 installed.
index 2cad896..8248866 100644 (file)
 cmake_minimum_required(VERSION 3.5.1)
 
 set(PACKAGE_NAME          "grpc")
-set(PACKAGE_VERSION       "1.41.1")
-set(gRPC_CORE_VERSION     "19.0.0")
-set(gRPC_CORE_SOVERSION   "19")
-set(gRPC_CPP_VERSION      "1.41.1")
-set(gRPC_CPP_SOVERSION    "1.41")
-set(gRPC_CSHARP_VERSION   "2.41.1")
-set(gRPC_CSHARP_SOVERSION "2.41")
+set(PACKAGE_VERSION       "1.42.0")
+set(gRPC_CORE_VERSION     "20.0.0")
+set(gRPC_CORE_SOVERSION   "20")
+set(gRPC_CPP_VERSION      "1.42.0")
+set(gRPC_CPP_SOVERSION    "1.42")
+set(gRPC_CSHARP_VERSION   "2.42.0")
+set(gRPC_CSHARP_SOVERSION "2.42")
 set(PACKAGE_STRING        "${PACKAGE_NAME} ${PACKAGE_VERSION}")
 set(PACKAGE_TARNAME       "${PACKAGE_NAME}-${PACKAGE_VERSION}")
 set(PACKAGE_BUGREPORT     "https://github.com/grpc/grpc/issues/")
@@ -251,7 +251,7 @@ endif()
 if (gRPC_XDS_USER_AGENT_IS_CSHARP)
   # The value of the defines needs to contain quotes.
   # See https://github.com/grpc/grpc/blob/fbf32836a418cc84f58786700273b65cb9174e1d/src/core/ext/xds/xds_api.cc#L854
-  add_definitions("-DGRPC_XDS_USER_AGENT_NAME_SUFFIX=\"csharp\"" "-DGRPC_XDS_USER_AGENT_VERSION_SUFFIX=\"2.41.1\"")
+  add_definitions("-DGRPC_XDS_USER_AGENT_NAME_SUFFIX=\"csharp\"" "-DGRPC_XDS_USER_AGENT_VERSION_SUFFIX=\"2.42.0\"")
 endif()
 
 include(cmake/abseil-cpp.cmake)
@@ -274,7 +274,7 @@ elseif(UNIX)
 endif()
 
 if(WIN32)
-  set(_gRPC_BASELIB_LIBRARIES wsock32 ws2_32 crypt32)
+  set(_gRPC_BASELIB_LIBRARIES ws2_32 crypt32)
 endif()
 
 # Create directory for generated .proto files
@@ -395,6 +395,9 @@ protobuf_generate_grpc_cpp(
   src/proto/grpc/lb/v1/load_balancer.proto
 )
 protobuf_generate_grpc_cpp(
+  src/proto/grpc/lookup/v1/rls.proto
+)
+protobuf_generate_grpc_cpp(
   src/proto/grpc/reflection/v1alpha/reflection.proto
 )
 protobuf_generate_grpc_cpp(
@@ -455,9 +458,6 @@ protobuf_generate_grpc_cpp(
   src/proto/grpc/testing/xds/lrs_for_test.proto
 )
 protobuf_generate_grpc_cpp(
-  src/proto/grpc/testing/xds/orca_load_report_for_test.proto
-)
-protobuf_generate_grpc_cpp(
   src/proto/grpc/testing/xds/v3/address.proto
 )
 protobuf_generate_grpc_cpp(
@@ -509,6 +509,9 @@ protobuf_generate_grpc_cpp(
   src/proto/grpc/testing/xds/v3/lrs.proto
 )
 protobuf_generate_grpc_cpp(
+  src/proto/grpc/testing/xds/v3/orca_load_report.proto
+)
+protobuf_generate_grpc_cpp(
   src/proto/grpc/testing/xds/v3/percent.proto
 )
 protobuf_generate_grpc_cpp(
@@ -533,9 +536,6 @@ protobuf_generate_grpc_cpp(
   src/proto/grpc/testing/xds/v3/tls.proto
 )
 protobuf_generate_grpc_cpp(
-  test/core/transport/binder/end2end/echo.proto
-)
-protobuf_generate_grpc_cpp(
   test/core/tsi/alts/fake_handshaker/handshaker.proto
 )
 protobuf_generate_grpc_cpp(
@@ -574,7 +574,6 @@ if(gRPC_BUILD_TESTS)
   add_dependencies(buildtests_c buffer_list_test)
   add_dependencies(buildtests_c channel_args_test)
   add_dependencies(buildtests_c channel_create_test)
-  add_dependencies(buildtests_c channel_stack_builder_test)
   add_dependencies(buildtests_c channel_stack_test)
   add_dependencies(buildtests_c check_gcp_environment_linux_test)
   add_dependencies(buildtests_c check_gcp_environment_windows_test)
@@ -599,7 +598,6 @@ if(gRPC_BUILD_TESTS)
   endif()
   add_dependencies(buildtests_c endpoint_pair_test)
   add_dependencies(buildtests_c env_test)
-  add_dependencies(buildtests_c error_test)
   if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
     add_dependencies(buildtests_c ev_epollex_linux_test)
   endif()
@@ -633,8 +631,6 @@ if(gRPC_BUILD_TESTS)
   add_dependencies(buildtests_c histogram_test)
   add_dependencies(buildtests_c host_port_test)
   add_dependencies(buildtests_c hpack_encoder_test)
-  add_dependencies(buildtests_c hpack_parser_table_test)
-  add_dependencies(buildtests_c hpack_parser_test)
   if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
     add_dependencies(buildtests_c httpcli_test)
   endif()
@@ -648,6 +644,9 @@ if(gRPC_BUILD_TESTS)
   add_dependencies(buildtests_c lame_client_test)
   add_dependencies(buildtests_c load_file_test)
   add_dependencies(buildtests_c manual_constructor_test)
+  if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
+    add_dependencies(buildtests_c memory_quota_stress_test)
+  endif()
   add_dependencies(buildtests_c message_compress_test)
   add_dependencies(buildtests_c metadata_test)
   add_dependencies(buildtests_c minimal_stack_is_minimal_test)
@@ -674,7 +673,6 @@ if(gRPC_BUILD_TESTS)
     add_dependencies(buildtests_c resolve_address_using_native_resolver_posix_test)
   endif()
   add_dependencies(buildtests_c resolve_address_using_native_resolver_test)
-  add_dependencies(buildtests_c resource_quota_test)
   add_dependencies(buildtests_c secure_channel_create_test)
   add_dependencies(buildtests_c secure_endpoint_test)
   add_dependencies(buildtests_c security_connector_test)
@@ -684,6 +682,8 @@ if(gRPC_BUILD_TESTS)
   endif()
   add_dependencies(buildtests_c server_test)
   add_dependencies(buildtests_c slice_buffer_test)
+  add_dependencies(buildtests_c slice_intern_test)
+  add_dependencies(buildtests_c slice_split_test)
   add_dependencies(buildtests_c slice_string_helpers_test)
   add_dependencies(buildtests_c sockaddr_resolver_test)
   if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
@@ -710,6 +710,7 @@ if(gRPC_BUILD_TESTS)
     add_dependencies(buildtests_c tcp_server_posix_test)
   endif()
   add_dependencies(buildtests_c test_core_gpr_time_test)
+  add_dependencies(buildtests_c test_core_iomgr_resource_quota_test)
   add_dependencies(buildtests_c test_core_security_credentials_test)
   add_dependencies(buildtests_c test_core_slice_slice_test)
   add_dependencies(buildtests_c thd_test)
@@ -720,10 +721,6 @@ if(gRPC_BUILD_TESTS)
   add_dependencies(buildtests_c timer_list_test)
   add_dependencies(buildtests_c transport_security_common_api_test)
   add_dependencies(buildtests_c transport_security_test)
-  if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
-    add_dependencies(buildtests_c udp_server_test)
-  endif()
-  add_dependencies(buildtests_c useful_test)
   add_dependencies(buildtests_c varint_test)
 
   add_custom_target(buildtests_cxx)
@@ -753,72 +750,10 @@ if(gRPC_BUILD_TESTS)
   if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
     add_dependencies(buildtests_cxx bdp_estimator_test)
   endif()
+  add_dependencies(buildtests_cxx binder_resolver_test)
   add_dependencies(buildtests_cxx binder_server_test)
   add_dependencies(buildtests_cxx binder_transport_test)
   add_dependencies(buildtests_cxx bitset_test)
-  if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
-    add_dependencies(buildtests_cxx bm_alarm)
-  endif()
-  if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
-    add_dependencies(buildtests_cxx bm_arena)
-  endif()
-  if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
-    add_dependencies(buildtests_cxx bm_byte_buffer)
-  endif()
-  if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
-    add_dependencies(buildtests_cxx bm_call_create)
-  endif()
-  if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
-    add_dependencies(buildtests_cxx bm_callback_streaming_ping_pong)
-  endif()
-  if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
-    add_dependencies(buildtests_cxx bm_callback_unary_ping_pong)
-  endif()
-  if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
-    add_dependencies(buildtests_cxx bm_channel)
-  endif()
-  if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
-    add_dependencies(buildtests_cxx bm_chttp2_hpack)
-  endif()
-  if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
-    add_dependencies(buildtests_cxx bm_chttp2_transport)
-  endif()
-  if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
-    add_dependencies(buildtests_cxx bm_closure)
-  endif()
-  if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
-    add_dependencies(buildtests_cxx bm_cq)
-  endif()
-  if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
-    add_dependencies(buildtests_cxx bm_cq_multiple_threads)
-  endif()
-  if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
-    add_dependencies(buildtests_cxx bm_error)
-  endif()
-  if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
-    add_dependencies(buildtests_cxx bm_fullstack_streaming_ping_pong)
-  endif()
-  if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
-    add_dependencies(buildtests_cxx bm_fullstack_streaming_pump)
-  endif()
-  if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
-    add_dependencies(buildtests_cxx bm_fullstack_trickle)
-  endif()
-  if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
-    add_dependencies(buildtests_cxx bm_fullstack_unary_ping_pong)
-  endif()
-  if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
-    add_dependencies(buildtests_cxx bm_metadata)
-  endif()
-  if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
-    add_dependencies(buildtests_cxx bm_pollset)
-  endif()
-  if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
-    add_dependencies(buildtests_cxx bm_threadpool)
-  endif()
-  if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
-    add_dependencies(buildtests_cxx bm_timer)
-  endif()
   add_dependencies(buildtests_cxx byte_buffer_test)
   add_dependencies(buildtests_cxx byte_stream_test)
   add_dependencies(buildtests_cxx cancel_ares_query_test)
@@ -829,10 +764,12 @@ if(gRPC_BUILD_TESTS)
   add_dependencies(buildtests_cxx cfstream_test)
   add_dependencies(buildtests_cxx channel_arguments_test)
   add_dependencies(buildtests_cxx channel_filter_test)
+  add_dependencies(buildtests_cxx channel_stack_builder_test)
   add_dependencies(buildtests_cxx channel_trace_test)
   add_dependencies(buildtests_cxx channelz_registry_test)
   add_dependencies(buildtests_cxx channelz_service_test)
   add_dependencies(buildtests_cxx channelz_test)
+  add_dependencies(buildtests_cxx chunked_vector_test)
   add_dependencies(buildtests_cxx cli_call_test)
   add_dependencies(buildtests_cxx client_callback_end2end_test)
   if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
@@ -857,14 +794,17 @@ if(gRPC_BUILD_TESTS)
   add_dependencies(buildtests_cxx duplicate_header_bad_client_test)
   add_dependencies(buildtests_cxx end2end_binder_transport_test)
   add_dependencies(buildtests_cxx end2end_test)
+  add_dependencies(buildtests_cxx endpoint_binder_pool_test)
   add_dependencies(buildtests_cxx endpoint_config_test)
   add_dependencies(buildtests_cxx error_details_test)
+  add_dependencies(buildtests_cxx error_test)
   add_dependencies(buildtests_cxx error_utils_test)
   add_dependencies(buildtests_cxx evaluate_args_test)
   if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
     add_dependencies(buildtests_cxx examine_stack_test)
   endif()
   add_dependencies(buildtests_cxx exception_test)
+  add_dependencies(buildtests_cxx exec_ctx_wakeup_scheduler_test)
   add_dependencies(buildtests_cxx fake_binder_test)
   add_dependencies(buildtests_cxx file_watcher_certificate_provider_factory_test)
   add_dependencies(buildtests_cxx filter_end2end_test)
@@ -895,8 +835,11 @@ if(gRPC_BUILD_TESTS)
   add_dependencies(buildtests_cxx headers_bad_client_test)
   add_dependencies(buildtests_cxx health_service_end2end_test)
   add_dependencies(buildtests_cxx hpack_encoder_index_test)
+  add_dependencies(buildtests_cxx hpack_parser_table_test)
+  add_dependencies(buildtests_cxx hpack_parser_test)
   add_dependencies(buildtests_cxx http2_client)
   add_dependencies(buildtests_cxx hybrid_end2end_test)
+  add_dependencies(buildtests_cxx idle_filter_state_test)
   add_dependencies(buildtests_cxx if_test)
   add_dependencies(buildtests_cxx init_test)
   add_dependencies(buildtests_cxx initial_settings_frame_bad_client_test)
@@ -917,16 +860,18 @@ if(gRPC_BUILD_TESTS)
   add_dependencies(buildtests_cxx loop_test)
   add_dependencies(buildtests_cxx match_test)
   add_dependencies(buildtests_cxx matchers_test)
+  add_dependencies(buildtests_cxx memory_quota_test)
   add_dependencies(buildtests_cxx message_allocator_end2end_test)
+  add_dependencies(buildtests_cxx metadata_map_test)
   add_dependencies(buildtests_cxx miscompile_with_no_unique_address_test)
   add_dependencies(buildtests_cxx mock_stream_test)
   add_dependencies(buildtests_cxx mock_test)
   add_dependencies(buildtests_cxx nonblocking_test)
-  add_dependencies(buildtests_cxx noop-benchmark)
   add_dependencies(buildtests_cxx observable_test)
   add_dependencies(buildtests_cxx orphanable_test)
   add_dependencies(buildtests_cxx out_of_bounds_bad_client_test)
   add_dependencies(buildtests_cxx overload_test)
+  add_dependencies(buildtests_cxx parsed_metadata_test)
   add_dependencies(buildtests_cxx pid_controller_test)
   add_dependencies(buildtests_cxx pipe_test)
   add_dependencies(buildtests_cxx poll_test)
@@ -948,6 +893,8 @@ if(gRPC_BUILD_TESTS)
     add_dependencies(buildtests_cxx remove_stream_from_stalled_lists_test)
   endif()
   add_dependencies(buildtests_cxx retry_throttle_test)
+  add_dependencies(buildtests_cxx rls_end2end_test)
+  add_dependencies(buildtests_cxx rls_lb_config_parser_test)
   add_dependencies(buildtests_cxx sdk_authz_end2end_test)
   add_dependencies(buildtests_cxx secure_auth_context_test)
   add_dependencies(buildtests_cxx seq_test)
@@ -959,6 +906,7 @@ if(gRPC_BUILD_TESTS)
     add_dependencies(buildtests_cxx server_builder_with_socket_mutator_test)
   endif()
   add_dependencies(buildtests_cxx server_chttp2_test)
+  add_dependencies(buildtests_cxx server_config_selector_test)
   add_dependencies(buildtests_cxx server_context_test_spouse_test)
   add_dependencies(buildtests_cxx server_early_return_test)
   add_dependencies(buildtests_cxx server_interceptors_end2end_test)
@@ -989,11 +937,13 @@ if(gRPC_BUILD_TESTS)
   endif()
   add_dependencies(buildtests_cxx string_ref_test)
   add_dependencies(buildtests_cxx table_test)
+  add_dependencies(buildtests_cxx test_core_resource_quota_resource_quota_test)
   add_dependencies(buildtests_cxx test_cpp_client_credentials_test)
   add_dependencies(buildtests_cxx test_cpp_server_credentials_test)
   add_dependencies(buildtests_cxx test_cpp_util_slice_test)
   add_dependencies(buildtests_cxx test_cpp_util_time_test)
   add_dependencies(buildtests_cxx thread_manager_test)
+  add_dependencies(buildtests_cxx thread_quota_test)
   if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
     add_dependencies(buildtests_cxx thread_stress_test)
   endif()
@@ -1010,6 +960,7 @@ if(gRPC_BUILD_TESTS)
   add_dependencies(buildtests_cxx try_seq_test)
   add_dependencies(buildtests_cxx unknown_frame_bad_client_test)
   add_dependencies(buildtests_cxx uri_parser_test)
+  add_dependencies(buildtests_cxx useful_test)
   add_dependencies(buildtests_cxx window_overflow_bad_client_test)
   add_dependencies(buildtests_cxx wire_reader_test)
   add_dependencies(buildtests_cxx wire_writer_test)
@@ -1028,19 +979,6 @@ if(gRPC_BUILD_TESTS)
   endif()
   add_dependencies(buildtests_cxx xds_interop_client)
   add_dependencies(buildtests_cxx xds_interop_server)
-  add_dependencies(buildtests_cxx alts_credentials_fuzzer_one_entry)
-  add_dependencies(buildtests_cxx client_fuzzer_one_entry)
-  add_dependencies(buildtests_cxx hpack_parser_fuzzer_test_one_entry)
-  add_dependencies(buildtests_cxx http_request_fuzzer_test_one_entry)
-  add_dependencies(buildtests_cxx http_response_fuzzer_test_one_entry)
-  add_dependencies(buildtests_cxx json_fuzzer_test_one_entry)
-  add_dependencies(buildtests_cxx nanopb_fuzzer_response_test_one_entry)
-  add_dependencies(buildtests_cxx nanopb_fuzzer_serverlist_test_one_entry)
-  add_dependencies(buildtests_cxx percent_decode_fuzzer_one_entry)
-  add_dependencies(buildtests_cxx percent_encode_fuzzer_one_entry)
-  add_dependencies(buildtests_cxx server_fuzzer_one_entry)
-  add_dependencies(buildtests_cxx ssl_server_fuzzer_one_entry)
-  add_dependencies(buildtests_cxx uri_fuzzer_test_one_entry)
 
   add_custom_target(buildtests
     DEPENDS buildtests_c buildtests_cxx)
@@ -1196,7 +1134,6 @@ add_library(end2end_nosec_tests
   test/core/end2end/tests/stream_compression_ping_pong_streaming.cc
   test/core/end2end/tests/streaming_error_response.cc
   test/core/end2end/tests/trailing_metadata.cc
-  test/core/end2end/tests/workaround_cronet_compression.cc
   test/core/end2end/tests/write_buffering.cc
   test/core/end2end/tests/write_buffering_at_end.cc
   test/core/util/test_lb_policies.cc
@@ -1344,7 +1281,6 @@ add_library(end2end_tests
   test/core/end2end/tests/stream_compression_ping_pong_streaming.cc
   test/core/end2end/tests/streaming_error_response.cc
   test/core/end2end/tests/trailing_metadata.cc
-  test/core/end2end/tests/workaround_cronet_compression.cc
   test/core/end2end/tests/write_buffering.cc
   test/core/end2end/tests/write_buffering_at_end.cc
   test/core/util/test_lb_policies.cc
@@ -1583,6 +1519,7 @@ add_library(grpc
   src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc
   src/core/ext/filters/client_channel/lb_policy/priority/priority.cc
   src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc
+  src/core/ext/filters/client_channel/lb_policy/rls/rls.cc
   src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc
   src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc
   src/core/ext/filters/client_channel/lb_policy/xds/cds.cc
@@ -1593,6 +1530,7 @@ add_library(grpc
   src/core/ext/filters/client_channel/local_subchannel_pool.cc
   src/core/ext/filters/client_channel/proxy_mapper_registry.cc
   src/core/ext/filters/client_channel/resolver.cc
+  src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc
   src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc
   src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_event_engine.cc
   src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc
@@ -1613,12 +1551,11 @@ add_library(grpc
   src/core/ext/filters/client_channel/retry_service_config.cc
   src/core/ext/filters/client_channel/retry_throttle.cc
   src/core/ext/filters/client_channel/server_address.cc
-  src/core/ext/filters/client_channel/service_config.cc
   src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc
-  src/core/ext/filters/client_channel/service_config_parser.cc
   src/core/ext/filters/client_channel/subchannel.cc
   src/core/ext/filters/client_channel/subchannel_pool_interface.cc
   src/core/ext/filters/client_idle/client_idle_filter.cc
+  src/core/ext/filters/client_idle/idle_filter_state.cc
   src/core/ext/filters/deadline/deadline_filter.cc
   src/core/ext/filters/fault_injection/fault_injection_filter.cc
   src/core/ext/filters/fault_injection/service_config_parser.cc
@@ -1630,10 +1567,9 @@ add_library(grpc
   src/core/ext/filters/http/server/http_server_filter.cc
   src/core/ext/filters/max_age/max_age_filter.cc
   src/core/ext/filters/message_size/message_size_filter.cc
-  src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc
-  src/core/ext/filters/workarounds/workaround_utils.cc
+  src/core/ext/service_config/service_config.cc
+  src/core/ext/service_config/service_config_parser.cc
   src/core/ext/transport/chttp2/alpn/alpn.cc
-  src/core/ext/transport/chttp2/client/authority.cc
   src/core/ext/transport/chttp2/client/chttp2_connector.cc
   src/core/ext/transport/chttp2/client/insecure/channel_create.cc
   src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc
@@ -1645,7 +1581,6 @@ add_library(grpc
   src/core/ext/transport/chttp2/transport/bin_decoder.cc
   src/core/ext/transport/chttp2/transport/bin_encoder.cc
   src/core/ext/transport/chttp2/transport/chttp2_plugin.cc
-  src/core/ext/transport/chttp2/transport/chttp2_slice_allocator.cc
   src/core/ext/transport/chttp2/transport/chttp2_transport.cc
   src/core/ext/transport/chttp2/transport/context_list.cc
   src/core/ext/transport/chttp2/transport/flow_control.cc
@@ -1662,7 +1597,6 @@ add_library(grpc
   src/core/ext/transport/chttp2/transport/hpack_utils.cc
   src/core/ext/transport/chttp2/transport/http2_settings.cc
   src/core/ext/transport/chttp2/transport/huffsyms.cc
-  src/core/ext/transport/chttp2/transport/incoming_metadata.cc
   src/core/ext/transport/chttp2/transport/parsing.cc
   src/core/ext/transport/chttp2/transport/stream_lists.cc
   src/core/ext/transport/chttp2/transport/stream_map.cc
@@ -1747,20 +1681,22 @@ add_library(grpc
   src/core/ext/upb-generated/src/proto/grpc/gcp/transport_security_common.upb.c
   src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.c
   src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c
+  src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls.upb.c
   src/core/ext/upb-generated/udpa/annotations/migrate.upb.c
   src/core/ext/upb-generated/udpa/annotations/security.upb.c
   src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c
   src/core/ext/upb-generated/udpa/annotations/status.upb.c
   src/core/ext/upb-generated/udpa/annotations/versioning.upb.c
-  src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c
-  src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.c
   src/core/ext/upb-generated/validate/validate.upb.c
+  src/core/ext/upb-generated/xds/annotations/v3/status.upb.c
   src/core/ext/upb-generated/xds/core/v3/authority.upb.c
   src/core/ext/upb-generated/xds/core/v3/collection_entry.upb.c
   src/core/ext/upb-generated/xds/core/v3/context_params.upb.c
   src/core/ext/upb-generated/xds/core/v3/resource.upb.c
   src/core/ext/upb-generated/xds/core/v3/resource_locator.upb.c
   src/core/ext/upb-generated/xds/core/v3/resource_name.upb.c
+  src/core/ext/upb-generated/xds/data/orca/v3/orca_load_report.upb.c
+  src/core/ext/upb-generated/xds/type/v3/typed_struct.upb.c
   src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.c
   src/core/ext/upbdefs-generated/envoy/annotations/deprecation.upbdefs.c
   src/core/ext/upbdefs-generated/envoy/annotations/resource.upbdefs.c
@@ -1846,20 +1782,22 @@ add_library(grpc
   src/core/ext/upbdefs-generated/udpa/annotations/sensitive.upbdefs.c
   src/core/ext/upbdefs-generated/udpa/annotations/status.upbdefs.c
   src/core/ext/upbdefs-generated/udpa/annotations/versioning.upbdefs.c
-  src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.c
   src/core/ext/upbdefs-generated/validate/validate.upbdefs.c
+  src/core/ext/upbdefs-generated/xds/annotations/v3/status.upbdefs.c
   src/core/ext/upbdefs-generated/xds/core/v3/authority.upbdefs.c
   src/core/ext/upbdefs-generated/xds/core/v3/collection_entry.upbdefs.c
   src/core/ext/upbdefs-generated/xds/core/v3/context_params.upbdefs.c
   src/core/ext/upbdefs-generated/xds/core/v3/resource.upbdefs.c
   src/core/ext/upbdefs-generated/xds/core/v3/resource_locator.upbdefs.c
   src/core/ext/upbdefs-generated/xds/core/v3/resource_name.upbdefs.c
+  src/core/ext/upbdefs-generated/xds/type/v3/typed_struct.upbdefs.c
   src/core/ext/xds/certificate_provider_registry.cc
   src/core/ext/xds/certificate_provider_store.cc
   src/core/ext/xds/file_watcher_certificate_provider_factory.cc
   src/core/ext/xds/xds_api.cc
   src/core/ext/xds/xds_bootstrap.cc
   src/core/ext/xds/xds_certificate_provider.cc
+  src/core/ext/xds/xds_channel_stack_modifier.cc
   src/core/ext/xds/xds_client.cc
   src/core/ext/xds/xds_client_stats.cc
   src/core/ext/xds/xds_http_fault_filter.cc
@@ -1985,7 +1923,6 @@ add_library(grpc
   src/core/lib/iomgr/timer_generic.cc
   src/core/lib/iomgr/timer_heap.cc
   src/core/lib/iomgr/timer_manager.cc
-  src/core/lib/iomgr/udp_server.cc
   src/core/lib/iomgr/unix_sockets_posix.cc
   src/core/lib/iomgr/unix_sockets_posix_noop.cc
   src/core/lib/iomgr/wakeup_fd_eventfd.cc
@@ -2055,10 +1992,15 @@ add_library(grpc
   src/core/lib/slice/b64.cc
   src/core/lib/slice/percent_encoding.cc
   src/core/lib/slice/slice.cc
+  src/core/lib/slice/slice_api.cc
   src/core/lib/slice/slice_buffer.cc
   src/core/lib/slice/slice_intern.cc
+  src/core/lib/slice/slice_refcount.cc
+  src/core/lib/slice/slice_split.cc
   src/core/lib/slice/slice_string_helpers.cc
+  src/core/lib/slice/static_slice.cc
   src/core/lib/surface/api_trace.cc
+  src/core/lib/surface/builtins.cc
   src/core/lib/surface/byte_buffer.cc
   src/core/lib/surface/byte_buffer_reader.cc
   src/core/lib/surface/call.cc
@@ -2078,7 +2020,6 @@ add_library(grpc
   src/core/lib/surface/server.cc
   src/core/lib/surface/validate_metadata.cc
   src/core/lib/surface/version.cc
-  src/core/lib/transport/authority_override.cc
   src/core/lib/transport/bdp_estimator.cc
   src/core/lib/transport/byte_stream.cc
   src/core/lib/transport/connectivity_state.cc
@@ -2163,8 +2104,10 @@ target_link_libraries(grpc
   absl::flat_hash_map
   absl::inlined_vector
   absl::bind_front
+  absl::hash
   absl::statusor
   absl::variant
+  absl::utility
   gpr
   ${_gRPC_SSL_LIBRARIES}
   address_sorting
@@ -2180,8 +2123,9 @@ foreach(_hdr
   include/grpc/compression.h
   include/grpc/event_engine/endpoint_config.h
   include/grpc/event_engine/event_engine.h
+  include/grpc/event_engine/internal/memory_allocator_impl.h
+  include/grpc/event_engine/memory_allocator.h
   include/grpc/event_engine/port.h
-  include/grpc/event_engine/slice_allocator.h
   include/grpc/fork.h
   include/grpc/grpc.h
   include/grpc/grpc_posix.h
@@ -2424,6 +2368,7 @@ add_library(grpc_unsecure
   src/core/ext/filters/client_channel/local_subchannel_pool.cc
   src/core/ext/filters/client_channel/proxy_mapper_registry.cc
   src/core/ext/filters/client_channel/resolver.cc
+  src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc
   src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc
   src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_event_engine.cc
   src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc
@@ -2442,12 +2387,11 @@ add_library(grpc_unsecure
   src/core/ext/filters/client_channel/retry_service_config.cc
   src/core/ext/filters/client_channel/retry_throttle.cc
   src/core/ext/filters/client_channel/server_address.cc
-  src/core/ext/filters/client_channel/service_config.cc
   src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc
-  src/core/ext/filters/client_channel/service_config_parser.cc
   src/core/ext/filters/client_channel/subchannel.cc
   src/core/ext/filters/client_channel/subchannel_pool_interface.cc
   src/core/ext/filters/client_idle/client_idle_filter.cc
+  src/core/ext/filters/client_idle/idle_filter_state.cc
   src/core/ext/filters/deadline/deadline_filter.cc
   src/core/ext/filters/fault_injection/fault_injection_filter.cc
   src/core/ext/filters/fault_injection/service_config_parser.cc
@@ -2459,10 +2403,9 @@ add_library(grpc_unsecure
   src/core/ext/filters/http/server/http_server_filter.cc
   src/core/ext/filters/max_age/max_age_filter.cc
   src/core/ext/filters/message_size/message_size_filter.cc
-  src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc
-  src/core/ext/filters/workarounds/workaround_utils.cc
+  src/core/ext/service_config/service_config.cc
+  src/core/ext/service_config/service_config_parser.cc
   src/core/ext/transport/chttp2/alpn/alpn.cc
-  src/core/ext/transport/chttp2/client/authority.cc
   src/core/ext/transport/chttp2/client/chttp2_connector.cc
   src/core/ext/transport/chttp2/client/insecure/channel_create.cc
   src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc
@@ -2472,7 +2415,6 @@ add_library(grpc_unsecure
   src/core/ext/transport/chttp2/transport/bin_decoder.cc
   src/core/ext/transport/chttp2/transport/bin_encoder.cc
   src/core/ext/transport/chttp2/transport/chttp2_plugin.cc
-  src/core/ext/transport/chttp2/transport/chttp2_slice_allocator.cc
   src/core/ext/transport/chttp2/transport/chttp2_transport.cc
   src/core/ext/transport/chttp2/transport/context_list.cc
   src/core/ext/transport/chttp2/transport/flow_control.cc
@@ -2489,7 +2431,6 @@ add_library(grpc_unsecure
   src/core/ext/transport/chttp2/transport/hpack_utils.cc
   src/core/ext/transport/chttp2/transport/http2_settings.cc
   src/core/ext/transport/chttp2/transport/huffsyms.cc
-  src/core/ext/transport/chttp2/transport/incoming_metadata.cc
   src/core/ext/transport/chttp2/transport/parsing.cc
   src/core/ext/transport/chttp2/transport/stream_lists.cc
   src/core/ext/transport/chttp2/transport/stream_map.cc
@@ -2499,8 +2440,8 @@ add_library(grpc_unsecure
   src/core/ext/transport/inproc/inproc_transport.cc
   src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.c
   src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c
-  src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c
   src/core/ext/upb-generated/validate/validate.upb.c
+  src/core/ext/upb-generated/xds/data/orca/v3/orca_load_report.upb.c
   src/core/lib/address_utils/parse_address.cc
   src/core/lib/address_utils/sockaddr_utils.cc
   src/core/lib/avl/avl.cc
@@ -2620,7 +2561,6 @@ add_library(grpc_unsecure
   src/core/lib/iomgr/timer_generic.cc
   src/core/lib/iomgr/timer_heap.cc
   src/core/lib/iomgr/timer_manager.cc
-  src/core/lib/iomgr/udp_server.cc
   src/core/lib/iomgr/unix_sockets_posix.cc
   src/core/lib/iomgr/unix_sockets_posix_noop.cc
   src/core/lib/iomgr/wakeup_fd_eventfd.cc
@@ -2635,10 +2575,15 @@ add_library(grpc_unsecure
   src/core/lib/slice/b64.cc
   src/core/lib/slice/percent_encoding.cc
   src/core/lib/slice/slice.cc
+  src/core/lib/slice/slice_api.cc
   src/core/lib/slice/slice_buffer.cc
   src/core/lib/slice/slice_intern.cc
+  src/core/lib/slice/slice_refcount.cc
+  src/core/lib/slice/slice_split.cc
   src/core/lib/slice/slice_string_helpers.cc
+  src/core/lib/slice/static_slice.cc
   src/core/lib/surface/api_trace.cc
+  src/core/lib/surface/builtins.cc
   src/core/lib/surface/byte_buffer.cc
   src/core/lib/surface/byte_buffer_reader.cc
   src/core/lib/surface/call.cc
@@ -2658,7 +2603,6 @@ add_library(grpc_unsecure
   src/core/lib/surface/server.cc
   src/core/lib/surface/validate_metadata.cc
   src/core/lib/surface/version.cc
-  src/core/lib/transport/authority_override.cc
   src/core/lib/transport/bdp_estimator.cc
   src/core/lib/transport/byte_stream.cc
   src/core/lib/transport/connectivity_state.cc
@@ -2718,6 +2662,7 @@ target_link_libraries(grpc_unsecure
   absl::bind_front
   absl::statusor
   absl::variant
+  absl::utility
   gpr
   address_sorting
 )
@@ -2732,8 +2677,9 @@ foreach(_hdr
   include/grpc/compression.h
   include/grpc/event_engine/endpoint_config.h
   include/grpc/event_engine/event_engine.h
+  include/grpc/event_engine/internal/memory_allocator_impl.h
+  include/grpc/event_engine/memory_allocator.h
   include/grpc/event_engine/port.h
-  include/grpc/event_engine/slice_allocator.h
   include/grpc/fork.h
   include/grpc/grpc.h
   include/grpc/grpc_posix.h
@@ -2828,6 +2774,23 @@ endif()
 endif()
 
 add_library(grpc++
+  src/core/ext/transport/binder/client/binder_connector.cc
+  src/core/ext/transport/binder/client/channel_create.cc
+  src/core/ext/transport/binder/client/channel_create_impl.cc
+  src/core/ext/transport/binder/client/connection_id_generator.cc
+  src/core/ext/transport/binder/client/endpoint_binder_pool.cc
+  src/core/ext/transport/binder/client/jni_utils.cc
+  src/core/ext/transport/binder/client/security_policy_setting.cc
+  src/core/ext/transport/binder/security_policy/binder_security_policy.cc
+  src/core/ext/transport/binder/server/binder_server.cc
+  src/core/ext/transport/binder/server/binder_server_credentials.cc
+  src/core/ext/transport/binder/transport/binder_transport.cc
+  src/core/ext/transport/binder/utils/transport_stream_receiver_impl.cc
+  src/core/ext/transport/binder/wire_format/binder_android.cc
+  src/core/ext/transport/binder/wire_format/binder_constants.cc
+  src/core/ext/transport/binder/wire_format/transaction.cc
+  src/core/ext/transport/binder/wire_format/wire_reader_impl.cc
+  src/core/ext/transport/binder/wire_format/wire_writer.cc
   src/cpp/client/channel_cc.cc
   src/cpp/client/client_callback.cc
   src/cpp/client/client_context.cc
@@ -3000,6 +2963,7 @@ foreach(_hdr
   include/grpcpp/client_context.h
   include/grpcpp/completion_queue.h
   include/grpcpp/create_channel.h
+  include/grpcpp/create_channel_binder.h
   include/grpcpp/create_channel_posix.h
   include/grpcpp/ext/health_check_service_server_builder_option.h
   include/grpcpp/generic/async_generic_service.h
@@ -3073,6 +3037,8 @@ foreach(_hdr
   include/grpcpp/security/auth_context.h
   include/grpcpp/security/auth_metadata_processor.h
   include/grpcpp/security/authorization_policy_provider.h
+  include/grpcpp/security/binder_credentials.h
+  include/grpcpp/security/binder_security_policy.h
   include/grpcpp/security/credentials.h
   include/grpcpp/security/server_credentials.h
   include/grpcpp/security/tls_certificate_provider.h
@@ -3828,7 +3794,7 @@ foreach(_hdr
 endforeach()
 
 
-if(gRPC_INSTALL AND NOT CMAKE_CROSSCOMPILING)
+if(gRPC_INSTALL)
   install(TARGETS grpc_plugin_support EXPORT gRPCTargets
     RUNTIME DESTINATION ${gRPC_INSTALL_BINDIR}
     LIBRARY DESTINATION ${gRPC_INSTALL_LIBDIR}
@@ -4744,33 +4710,6 @@ target_link_libraries(channel_create_test
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(channel_stack_builder_test
-  test/core/channel/channel_stack_builder_test.cc
-)
-
-target_include_directories(channel_stack_builder_test
-  PRIVATE
-    ${CMAKE_CURRENT_SOURCE_DIR}
-    ${CMAKE_CURRENT_SOURCE_DIR}/include
-    ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-    ${_gRPC_RE2_INCLUDE_DIR}
-    ${_gRPC_SSL_INCLUDE_DIR}
-    ${_gRPC_UPB_GENERATED_DIR}
-    ${_gRPC_UPB_GRPC_GENERATED_DIR}
-    ${_gRPC_UPB_INCLUDE_DIR}
-    ${_gRPC_XXHASH_INCLUDE_DIR}
-    ${_gRPC_ZLIB_INCLUDE_DIR}
-)
-
-target_link_libraries(channel_stack_builder_test
-  ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc_test_util
-)
-
-
-endif()
-if(gRPC_BUILD_TESTS)
-
 add_executable(channel_stack_test
   test/core/channel/channel_stack_test.cc
 )
@@ -5265,34 +5204,6 @@ target_link_libraries(env_test
 
 endif()
 if(gRPC_BUILD_TESTS)
-
-add_executable(error_test
-  test/core/iomgr/endpoint_tests.cc
-  test/core/iomgr/error_test.cc
-)
-
-target_include_directories(error_test
-  PRIVATE
-    ${CMAKE_CURRENT_SOURCE_DIR}
-    ${CMAKE_CURRENT_SOURCE_DIR}/include
-    ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-    ${_gRPC_RE2_INCLUDE_DIR}
-    ${_gRPC_SSL_INCLUDE_DIR}
-    ${_gRPC_UPB_GENERATED_DIR}
-    ${_gRPC_UPB_GRPC_GENERATED_DIR}
-    ${_gRPC_UPB_INCLUDE_DIR}
-    ${_gRPC_XXHASH_INCLUDE_DIR}
-    ${_gRPC_ZLIB_INCLUDE_DIR}
-)
-
-target_link_libraries(error_test
-  ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc_test_util
-)
-
-
-endif()
-if(gRPC_BUILD_TESTS)
 if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 
   add_executable(ev_epollex_linux_test
@@ -5836,60 +5747,6 @@ target_link_libraries(hpack_encoder_test
 
 endif()
 if(gRPC_BUILD_TESTS)
-
-add_executable(hpack_parser_table_test
-  test/core/transport/chttp2/hpack_parser_table_test.cc
-)
-
-target_include_directories(hpack_parser_table_test
-  PRIVATE
-    ${CMAKE_CURRENT_SOURCE_DIR}
-    ${CMAKE_CURRENT_SOURCE_DIR}/include
-    ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-    ${_gRPC_RE2_INCLUDE_DIR}
-    ${_gRPC_SSL_INCLUDE_DIR}
-    ${_gRPC_UPB_GENERATED_DIR}
-    ${_gRPC_UPB_GRPC_GENERATED_DIR}
-    ${_gRPC_UPB_INCLUDE_DIR}
-    ${_gRPC_XXHASH_INCLUDE_DIR}
-    ${_gRPC_ZLIB_INCLUDE_DIR}
-)
-
-target_link_libraries(hpack_parser_table_test
-  ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc_test_util
-)
-
-
-endif()
-if(gRPC_BUILD_TESTS)
-
-add_executable(hpack_parser_test
-  test/core/transport/chttp2/hpack_parser_test.cc
-)
-
-target_include_directories(hpack_parser_test
-  PRIVATE
-    ${CMAKE_CURRENT_SOURCE_DIR}
-    ${CMAKE_CURRENT_SOURCE_DIR}/include
-    ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-    ${_gRPC_RE2_INCLUDE_DIR}
-    ${_gRPC_SSL_INCLUDE_DIR}
-    ${_gRPC_UPB_GENERATED_DIR}
-    ${_gRPC_UPB_GRPC_GENERATED_DIR}
-    ${_gRPC_UPB_INCLUDE_DIR}
-    ${_gRPC_XXHASH_INCLUDE_DIR}
-    ${_gRPC_ZLIB_INCLUDE_DIR}
-)
-
-target_link_libraries(hpack_parser_test
-  ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc_test_util
-)
-
-
-endif()
-if(gRPC_BUILD_TESTS)
 if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 
   add_executable(httpcli_test
@@ -6147,6 +6004,50 @@ target_link_libraries(manual_constructor_test
 
 endif()
 if(gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
+
+  add_executable(memory_quota_stress_test
+    src/core/lib/debug/trace.cc
+    src/core/lib/event_engine/memory_allocator.cc
+    src/core/lib/iomgr/combiner.cc
+    src/core/lib/iomgr/error.cc
+    src/core/lib/iomgr/exec_ctx.cc
+    src/core/lib/iomgr/executor.cc
+    src/core/lib/iomgr/iomgr_internal.cc
+    src/core/lib/promise/activity.cc
+    src/core/lib/resource_quota/memory_quota.cc
+    src/core/lib/slice/slice.cc
+    src/core/lib/slice/slice_refcount.cc
+    src/core/lib/slice/slice_string_helpers.cc
+    src/core/lib/slice/static_slice.cc
+    test/core/resource_quota/memory_quota_stress_test.cc
+  )
+
+  target_include_directories(memory_quota_stress_test
+    PRIVATE
+      ${CMAKE_CURRENT_SOURCE_DIR}
+      ${CMAKE_CURRENT_SOURCE_DIR}/include
+      ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
+      ${_gRPC_RE2_INCLUDE_DIR}
+      ${_gRPC_SSL_INCLUDE_DIR}
+      ${_gRPC_UPB_GENERATED_DIR}
+      ${_gRPC_UPB_GRPC_GENERATED_DIR}
+      ${_gRPC_UPB_INCLUDE_DIR}
+      ${_gRPC_XXHASH_INCLUDE_DIR}
+      ${_gRPC_ZLIB_INCLUDE_DIR}
+  )
+
+  target_link_libraries(memory_quota_stress_test
+    ${_gRPC_ALLTARGETS_LIBRARIES}
+    absl::statusor
+    absl::variant
+    gpr
+  )
+
+
+endif()
+endif()
+if(gRPC_BUILD_TESTS)
 
 add_executable(message_compress_test
   test/core/compression/message_compress_test.cc
@@ -6653,33 +6554,6 @@ target_link_libraries(resolve_address_using_native_resolver_test
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(resource_quota_test
-  test/core/iomgr/resource_quota_test.cc
-)
-
-target_include_directories(resource_quota_test
-  PRIVATE
-    ${CMAKE_CURRENT_SOURCE_DIR}
-    ${CMAKE_CURRENT_SOURCE_DIR}/include
-    ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-    ${_gRPC_RE2_INCLUDE_DIR}
-    ${_gRPC_SSL_INCLUDE_DIR}
-    ${_gRPC_UPB_GENERATED_DIR}
-    ${_gRPC_UPB_GRPC_GENERATED_DIR}
-    ${_gRPC_UPB_INCLUDE_DIR}
-    ${_gRPC_XXHASH_INCLUDE_DIR}
-    ${_gRPC_ZLIB_INCLUDE_DIR}
-)
-
-target_link_libraries(resource_quota_test
-  ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc_test_util
-)
-
-
-endif()
-if(gRPC_BUILD_TESTS)
-
 add_executable(secure_channel_create_test
   test/core/surface/secure_channel_create_test.cc
 )
@@ -6873,11 +6747,11 @@ target_link_libraries(slice_buffer_test
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(slice_string_helpers_test
-  test/core/slice/slice_string_helpers_test.cc
+add_executable(slice_intern_test
+  test/core/slice/slice_intern_test.cc
 )
 
-target_include_directories(slice_string_helpers_test
+target_include_directories(slice_intern_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -6891,7 +6765,7 @@ target_include_directories(slice_string_helpers_test
     ${_gRPC_ZLIB_INCLUDE_DIR}
 )
 
-target_link_libraries(slice_string_helpers_test
+target_link_libraries(slice_intern_test
   ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
 )
@@ -6900,11 +6774,11 @@ target_link_libraries(slice_string_helpers_test
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(sockaddr_resolver_test
-  test/core/client_channel/resolvers/sockaddr_resolver_test.cc
+add_executable(slice_split_test
+  test/core/slice/slice_split_test.cc
 )
 
-target_include_directories(sockaddr_resolver_test
+target_include_directories(slice_split_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -6918,7 +6792,7 @@ target_include_directories(sockaddr_resolver_test
     ${_gRPC_ZLIB_INCLUDE_DIR}
 )
 
-target_link_libraries(sockaddr_resolver_test
+target_link_libraries(slice_split_test
   ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
 )
@@ -6926,28 +6800,87 @@ target_link_libraries(sockaddr_resolver_test
 
 endif()
 if(gRPC_BUILD_TESTS)
-if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
-
-  add_executable(socket_utils_test
-    test/core/iomgr/socket_utils_test.cc
-  )
 
-  target_include_directories(socket_utils_test
-    PRIVATE
-      ${CMAKE_CURRENT_SOURCE_DIR}
-      ${CMAKE_CURRENT_SOURCE_DIR}/include
-      ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-      ${_gRPC_RE2_INCLUDE_DIR}
-      ${_gRPC_SSL_INCLUDE_DIR}
-      ${_gRPC_UPB_GENERATED_DIR}
-      ${_gRPC_UPB_GRPC_GENERATED_DIR}
-      ${_gRPC_UPB_INCLUDE_DIR}
-      ${_gRPC_XXHASH_INCLUDE_DIR}
-      ${_gRPC_ZLIB_INCLUDE_DIR}
-  )
+add_executable(slice_string_helpers_test
+  src/core/lib/debug/trace.cc
+  src/core/lib/slice/slice.cc
+  src/core/lib/slice/slice_refcount.cc
+  src/core/lib/slice/slice_string_helpers.cc
+  src/core/lib/slice/static_slice.cc
+  test/core/slice/slice_string_helpers_test.cc
+)
 
-  target_link_libraries(socket_utils_test
-    ${_gRPC_ALLTARGETS_LIBRARIES}
+target_include_directories(slice_string_helpers_test
+  PRIVATE
+    ${CMAKE_CURRENT_SOURCE_DIR}
+    ${CMAKE_CURRENT_SOURCE_DIR}/include
+    ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
+    ${_gRPC_RE2_INCLUDE_DIR}
+    ${_gRPC_SSL_INCLUDE_DIR}
+    ${_gRPC_UPB_GENERATED_DIR}
+    ${_gRPC_UPB_GRPC_GENERATED_DIR}
+    ${_gRPC_UPB_INCLUDE_DIR}
+    ${_gRPC_XXHASH_INCLUDE_DIR}
+    ${_gRPC_ZLIB_INCLUDE_DIR}
+)
+
+target_link_libraries(slice_string_helpers_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  gpr
+)
+
+
+endif()
+if(gRPC_BUILD_TESTS)
+
+add_executable(sockaddr_resolver_test
+  test/core/client_channel/resolvers/sockaddr_resolver_test.cc
+)
+
+target_include_directories(sockaddr_resolver_test
+  PRIVATE
+    ${CMAKE_CURRENT_SOURCE_DIR}
+    ${CMAKE_CURRENT_SOURCE_DIR}/include
+    ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
+    ${_gRPC_RE2_INCLUDE_DIR}
+    ${_gRPC_SSL_INCLUDE_DIR}
+    ${_gRPC_UPB_GENERATED_DIR}
+    ${_gRPC_UPB_GRPC_GENERATED_DIR}
+    ${_gRPC_UPB_INCLUDE_DIR}
+    ${_gRPC_XXHASH_INCLUDE_DIR}
+    ${_gRPC_ZLIB_INCLUDE_DIR}
+)
+
+target_link_libraries(sockaddr_resolver_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  grpc_test_util
+)
+
+
+endif()
+if(gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+
+  add_executable(socket_utils_test
+    test/core/iomgr/socket_utils_test.cc
+  )
+
+  target_include_directories(socket_utils_test
+    PRIVATE
+      ${CMAKE_CURRENT_SOURCE_DIR}
+      ${CMAKE_CURRENT_SOURCE_DIR}/include
+      ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
+      ${_gRPC_RE2_INCLUDE_DIR}
+      ${_gRPC_SSL_INCLUDE_DIR}
+      ${_gRPC_UPB_GENERATED_DIR}
+      ${_gRPC_UPB_GRPC_GENERATED_DIR}
+      ${_gRPC_UPB_INCLUDE_DIR}
+      ${_gRPC_XXHASH_INCLUDE_DIR}
+      ${_gRPC_ZLIB_INCLUDE_DIR}
+  )
+
+  target_link_libraries(socket_utils_test
+    ${_gRPC_ALLTARGETS_LIBRARIES}
     grpc_test_util
   )
 
@@ -7317,6 +7250,33 @@ target_link_libraries(test_core_gpr_time_test
 endif()
 if(gRPC_BUILD_TESTS)
 
+add_executable(test_core_iomgr_resource_quota_test
+  test/core/iomgr/resource_quota_test.cc
+)
+
+target_include_directories(test_core_iomgr_resource_quota_test
+  PRIVATE
+    ${CMAKE_CURRENT_SOURCE_DIR}
+    ${CMAKE_CURRENT_SOURCE_DIR}/include
+    ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
+    ${_gRPC_RE2_INCLUDE_DIR}
+    ${_gRPC_SSL_INCLUDE_DIR}
+    ${_gRPC_UPB_GENERATED_DIR}
+    ${_gRPC_UPB_GRPC_GENERATED_DIR}
+    ${_gRPC_UPB_INCLUDE_DIR}
+    ${_gRPC_XXHASH_INCLUDE_DIR}
+    ${_gRPC_ZLIB_INCLUDE_DIR}
+)
+
+target_link_libraries(test_core_iomgr_resource_quota_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  grpc_test_util
+)
+
+
+endif()
+if(gRPC_BUILD_TESTS)
+
 add_executable(test_core_security_credentials_test
   test/core/security/credentials_test.cc
 )
@@ -7345,6 +7305,11 @@ endif()
 if(gRPC_BUILD_TESTS)
 
 add_executable(test_core_slice_slice_test
+  src/core/lib/debug/trace.cc
+  src/core/lib/slice/slice.cc
+  src/core/lib/slice/slice_refcount.cc
+  src/core/lib/slice/slice_string_helpers.cc
+  src/core/lib/slice/static_slice.cc
   test/core/slice/slice_test.cc
 )
 
@@ -7364,7 +7329,7 @@ target_include_directories(test_core_slice_slice_test
 
 target_link_libraries(test_core_slice_slice_test
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc_test_util
+  gpr
 )
 
 
@@ -7586,62 +7551,6 @@ target_link_libraries(transport_security_test
 
 endif()
 if(gRPC_BUILD_TESTS)
-if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
-
-  add_executable(udp_server_test
-    test/core/iomgr/udp_server_test.cc
-  )
-
-  target_include_directories(udp_server_test
-    PRIVATE
-      ${CMAKE_CURRENT_SOURCE_DIR}
-      ${CMAKE_CURRENT_SOURCE_DIR}/include
-      ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-      ${_gRPC_RE2_INCLUDE_DIR}
-      ${_gRPC_SSL_INCLUDE_DIR}
-      ${_gRPC_UPB_GENERATED_DIR}
-      ${_gRPC_UPB_GRPC_GENERATED_DIR}
-      ${_gRPC_UPB_INCLUDE_DIR}
-      ${_gRPC_XXHASH_INCLUDE_DIR}
-      ${_gRPC_ZLIB_INCLUDE_DIR}
-  )
-
-  target_link_libraries(udp_server_test
-    ${_gRPC_ALLTARGETS_LIBRARIES}
-    grpc_test_util
-  )
-
-
-endif()
-endif()
-if(gRPC_BUILD_TESTS)
-
-add_executable(useful_test
-  test/core/gpr/useful_test.cc
-)
-
-target_include_directories(useful_test
-  PRIVATE
-    ${CMAKE_CURRENT_SOURCE_DIR}
-    ${CMAKE_CURRENT_SOURCE_DIR}/include
-    ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-    ${_gRPC_RE2_INCLUDE_DIR}
-    ${_gRPC_SSL_INCLUDE_DIR}
-    ${_gRPC_UPB_GENERATED_DIR}
-    ${_gRPC_UPB_GRPC_GENERATED_DIR}
-    ${_gRPC_UPB_INCLUDE_DIR}
-    ${_gRPC_XXHASH_INCLUDE_DIR}
-    ${_gRPC_ZLIB_INCLUDE_DIR}
-)
-
-target_link_libraries(useful_test
-  ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc_test_util
-)
-
-
-endif()
-if(gRPC_BUILD_TESTS)
 
 add_executable(varint_test
   test/core/transport/chttp2/varint_test.cc
@@ -8383,6 +8292,41 @@ endif()
 endif()
 if(gRPC_BUILD_TESTS)
 
+add_executable(binder_resolver_test
+  test/core/client_channel/resolvers/binder_resolver_test.cc
+  third_party/googletest/googletest/src/gtest-all.cc
+  third_party/googletest/googlemock/src/gmock-all.cc
+)
+
+target_include_directories(binder_resolver_test
+  PRIVATE
+    ${CMAKE_CURRENT_SOURCE_DIR}
+    ${CMAKE_CURRENT_SOURCE_DIR}/include
+    ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
+    ${_gRPC_RE2_INCLUDE_DIR}
+    ${_gRPC_SSL_INCLUDE_DIR}
+    ${_gRPC_UPB_GENERATED_DIR}
+    ${_gRPC_UPB_GRPC_GENERATED_DIR}
+    ${_gRPC_UPB_INCLUDE_DIR}
+    ${_gRPC_XXHASH_INCLUDE_DIR}
+    ${_gRPC_ZLIB_INCLUDE_DIR}
+    third_party/googletest/googletest/include
+    third_party/googletest/googletest
+    third_party/googletest/googlemock/include
+    third_party/googletest/googlemock
+    ${_gRPC_PROTO_GENS_DIR}
+)
+
+target_link_libraries(binder_resolver_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  grpc_test_util
+)
+
+
+endif()
+if(gRPC_BUILD_TESTS)
+
 add_executable(binder_server_test
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc
@@ -8396,22 +8340,7 @@ add_executable(binder_server_test
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/test/core/transport/binder/end2end/echo.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/test/core/transport/binder/end2end/echo.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/test/core/transport/binder/end2end/echo.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/test/core/transport/binder/end2end/echo.grpc.pb.h
-  src/core/ext/transport/binder/client/channel_create_impl.cc
-  src/core/ext/transport/binder/server/binder_server.cc
-  src/core/ext/transport/binder/server/binder_server_credentials.cc
-  src/core/ext/transport/binder/transport/binder_transport.cc
-  src/core/ext/transport/binder/utils/transport_stream_receiver_impl.cc
-  src/core/ext/transport/binder/wire_format/binder_android.cc
-  src/core/ext/transport/binder/wire_format/binder_constants.cc
-  src/core/ext/transport/binder/wire_format/transaction.cc
-  src/core/ext/transport/binder/wire_format/wire_reader_impl.cc
-  src/core/ext/transport/binder/wire_format/wire_writer.cc
   test/core/transport/binder/end2end/binder_server_test.cc
-  test/core/transport/binder/end2end/echo_service.cc
   test/core/transport/binder/end2end/fake_binder.cc
   test/cpp/end2end/test_service_impl.cc
   third_party/googletest/googletest/src/gtest-all.cc
@@ -8449,12 +8378,60 @@ endif()
 if(gRPC_BUILD_TESTS)
 
 add_executable(binder_transport_test
+  src/core/ext/transport/binder/client/binder_connector.cc
+  src/core/ext/transport/binder/client/channel_create.cc
+  src/core/ext/transport/binder/client/channel_create_impl.cc
+  src/core/ext/transport/binder/client/connection_id_generator.cc
+  src/core/ext/transport/binder/client/endpoint_binder_pool.cc
+  src/core/ext/transport/binder/client/jni_utils.cc
+  src/core/ext/transport/binder/client/security_policy_setting.cc
+  src/core/ext/transport/binder/security_policy/binder_security_policy.cc
+  src/core/ext/transport/binder/server/binder_server.cc
+  src/core/ext/transport/binder/server/binder_server_credentials.cc
   src/core/ext/transport/binder/transport/binder_transport.cc
   src/core/ext/transport/binder/utils/transport_stream_receiver_impl.cc
+  src/core/ext/transport/binder/wire_format/binder_android.cc
   src/core/ext/transport/binder/wire_format/binder_constants.cc
   src/core/ext/transport/binder/wire_format/transaction.cc
   src/core/ext/transport/binder/wire_format/wire_reader_impl.cc
   src/core/ext/transport/binder/wire_format/wire_writer.cc
+  src/cpp/client/channel_cc.cc
+  src/cpp/client/client_callback.cc
+  src/cpp/client/client_context.cc
+  src/cpp/client/client_interceptor.cc
+  src/cpp/client/create_channel.cc
+  src/cpp/client/create_channel_internal.cc
+  src/cpp/client/create_channel_posix.cc
+  src/cpp/client/credentials_cc.cc
+  src/cpp/codegen/codegen_init.cc
+  src/cpp/common/alarm.cc
+  src/cpp/common/channel_arguments.cc
+  src/cpp/common/channel_filter.cc
+  src/cpp/common/completion_queue_cc.cc
+  src/cpp/common/core_codegen.cc
+  src/cpp/common/resource_quota_cc.cc
+  src/cpp/common/rpc_method.cc
+  src/cpp/common/validate_service_config.cc
+  src/cpp/common/version_cc.cc
+  src/cpp/server/async_generic_service.cc
+  src/cpp/server/channel_argument_option.cc
+  src/cpp/server/create_default_thread_pool.cc
+  src/cpp/server/dynamic_thread_pool.cc
+  src/cpp/server/external_connection_acceptor_impl.cc
+  src/cpp/server/health/default_health_check_service.cc
+  src/cpp/server/health/health_check_service.cc
+  src/cpp/server/health/health_check_service_server_builder_option.cc
+  src/cpp/server/server_builder.cc
+  src/cpp/server/server_callback.cc
+  src/cpp/server/server_cc.cc
+  src/cpp/server/server_context.cc
+  src/cpp/server/server_credentials.cc
+  src/cpp/server/server_posix.cc
+  src/cpp/thread_manager/thread_manager.cc
+  src/cpp/util/byte_buffer_cc.cc
+  src/cpp/util/status.cc
+  src/cpp/util/string_ref.cc
+  src/cpp/util/time_cc.cc
   test/core/transport/binder/binder_transport_test.cc
   test/core/transport/binder/mock_objects.cc
   third_party/googletest/googletest/src/gtest-all.cc
@@ -8523,798 +8500,12 @@ target_link_libraries(bitset_test
 
 endif()
 if(gRPC_BUILD_TESTS)
-if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
 
-  add_executable(bm_alarm
-    test/cpp/microbenchmarks/bm_alarm.cc
-    third_party/googletest/googletest/src/gtest-all.cc
-    third_party/googletest/googlemock/src/gmock-all.cc
-  )
-
-  target_include_directories(bm_alarm
-    PRIVATE
-      ${CMAKE_CURRENT_SOURCE_DIR}
-      ${CMAKE_CURRENT_SOURCE_DIR}/include
-      ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-      ${_gRPC_RE2_INCLUDE_DIR}
-      ${_gRPC_SSL_INCLUDE_DIR}
-      ${_gRPC_UPB_GENERATED_DIR}
-      ${_gRPC_UPB_GRPC_GENERATED_DIR}
-      ${_gRPC_UPB_INCLUDE_DIR}
-      ${_gRPC_XXHASH_INCLUDE_DIR}
-      ${_gRPC_ZLIB_INCLUDE_DIR}
-      third_party/googletest/googletest/include
-      third_party/googletest/googletest
-      third_party/googletest/googlemock/include
-      third_party/googletest/googlemock
-      ${_gRPC_PROTO_GENS_DIR}
-  )
-
-  target_link_libraries(bm_alarm
-    ${_gRPC_PROTOBUF_LIBRARIES}
-    ${_gRPC_ALLTARGETS_LIBRARIES}
-    benchmark_helpers
-  )
-
-
-endif()
-endif()
-if(gRPC_BUILD_TESTS)
-if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
-
-  add_executable(bm_arena
-    test/cpp/microbenchmarks/bm_arena.cc
-    third_party/googletest/googletest/src/gtest-all.cc
-    third_party/googletest/googlemock/src/gmock-all.cc
-  )
-
-  target_include_directories(bm_arena
-    PRIVATE
-      ${CMAKE_CURRENT_SOURCE_DIR}
-      ${CMAKE_CURRENT_SOURCE_DIR}/include
-      ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-      ${_gRPC_RE2_INCLUDE_DIR}
-      ${_gRPC_SSL_INCLUDE_DIR}
-      ${_gRPC_UPB_GENERATED_DIR}
-      ${_gRPC_UPB_GRPC_GENERATED_DIR}
-      ${_gRPC_UPB_INCLUDE_DIR}
-      ${_gRPC_XXHASH_INCLUDE_DIR}
-      ${_gRPC_ZLIB_INCLUDE_DIR}
-      third_party/googletest/googletest/include
-      third_party/googletest/googletest
-      third_party/googletest/googlemock/include
-      third_party/googletest/googlemock
-      ${_gRPC_PROTO_GENS_DIR}
-  )
-
-  target_link_libraries(bm_arena
-    ${_gRPC_PROTOBUF_LIBRARIES}
-    ${_gRPC_ALLTARGETS_LIBRARIES}
-    benchmark_helpers
-  )
-
-
-endif()
-endif()
-if(gRPC_BUILD_TESTS)
-if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
-
-  add_executable(bm_byte_buffer
-    test/cpp/microbenchmarks/bm_byte_buffer.cc
-    third_party/googletest/googletest/src/gtest-all.cc
-    third_party/googletest/googlemock/src/gmock-all.cc
-  )
-
-  target_include_directories(bm_byte_buffer
-    PRIVATE
-      ${CMAKE_CURRENT_SOURCE_DIR}
-      ${CMAKE_CURRENT_SOURCE_DIR}/include
-      ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-      ${_gRPC_RE2_INCLUDE_DIR}
-      ${_gRPC_SSL_INCLUDE_DIR}
-      ${_gRPC_UPB_GENERATED_DIR}
-      ${_gRPC_UPB_GRPC_GENERATED_DIR}
-      ${_gRPC_UPB_INCLUDE_DIR}
-      ${_gRPC_XXHASH_INCLUDE_DIR}
-      ${_gRPC_ZLIB_INCLUDE_DIR}
-      third_party/googletest/googletest/include
-      third_party/googletest/googletest
-      third_party/googletest/googlemock/include
-      third_party/googletest/googlemock
-      ${_gRPC_PROTO_GENS_DIR}
-  )
-
-  target_link_libraries(bm_byte_buffer
-    ${_gRPC_PROTOBUF_LIBRARIES}
-    ${_gRPC_ALLTARGETS_LIBRARIES}
-    benchmark_helpers
-  )
-
-
-endif()
-endif()
-if(gRPC_BUILD_TESTS)
-if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
-
-  add_executable(bm_call_create
-    test/cpp/microbenchmarks/bm_call_create.cc
-    third_party/googletest/googletest/src/gtest-all.cc
-    third_party/googletest/googlemock/src/gmock-all.cc
-  )
-
-  target_include_directories(bm_call_create
-    PRIVATE
-      ${CMAKE_CURRENT_SOURCE_DIR}
-      ${CMAKE_CURRENT_SOURCE_DIR}/include
-      ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-      ${_gRPC_RE2_INCLUDE_DIR}
-      ${_gRPC_SSL_INCLUDE_DIR}
-      ${_gRPC_UPB_GENERATED_DIR}
-      ${_gRPC_UPB_GRPC_GENERATED_DIR}
-      ${_gRPC_UPB_INCLUDE_DIR}
-      ${_gRPC_XXHASH_INCLUDE_DIR}
-      ${_gRPC_ZLIB_INCLUDE_DIR}
-      third_party/googletest/googletest/include
-      third_party/googletest/googletest
-      third_party/googletest/googlemock/include
-      third_party/googletest/googlemock
-      ${_gRPC_PROTO_GENS_DIR}
-  )
-
-  target_link_libraries(bm_call_create
-    ${_gRPC_PROTOBUF_LIBRARIES}
-    ${_gRPC_ALLTARGETS_LIBRARIES}
-    benchmark_helpers
-  )
-
-
-endif()
-endif()
-if(gRPC_BUILD_TESTS)
-if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
-
-  add_executable(bm_callback_streaming_ping_pong
-    test/cpp/microbenchmarks/bm_callback_streaming_ping_pong.cc
-    test/cpp/microbenchmarks/callback_test_service.cc
-    test/cpp/util/byte_buffer_proto_helper.cc
-    test/cpp/util/string_ref_helper.cc
-    test/cpp/util/subprocess.cc
-    third_party/googletest/googletest/src/gtest-all.cc
-    third_party/googletest/googlemock/src/gmock-all.cc
-  )
-
-  target_include_directories(bm_callback_streaming_ping_pong
-    PRIVATE
-      ${CMAKE_CURRENT_SOURCE_DIR}
-      ${CMAKE_CURRENT_SOURCE_DIR}/include
-      ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-      ${_gRPC_RE2_INCLUDE_DIR}
-      ${_gRPC_SSL_INCLUDE_DIR}
-      ${_gRPC_UPB_GENERATED_DIR}
-      ${_gRPC_UPB_GRPC_GENERATED_DIR}
-      ${_gRPC_UPB_INCLUDE_DIR}
-      ${_gRPC_XXHASH_INCLUDE_DIR}
-      ${_gRPC_ZLIB_INCLUDE_DIR}
-      third_party/googletest/googletest/include
-      third_party/googletest/googletest
-      third_party/googletest/googlemock/include
-      third_party/googletest/googlemock
-      ${_gRPC_PROTO_GENS_DIR}
-  )
-
-  target_link_libraries(bm_callback_streaming_ping_pong
-    ${_gRPC_PROTOBUF_LIBRARIES}
-    ${_gRPC_ALLTARGETS_LIBRARIES}
-    benchmark_helpers
-  )
-
-
-endif()
-endif()
-if(gRPC_BUILD_TESTS)
-if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
-
-  add_executable(bm_callback_unary_ping_pong
-    test/cpp/microbenchmarks/bm_callback_unary_ping_pong.cc
-    test/cpp/microbenchmarks/callback_test_service.cc
-    test/cpp/util/byte_buffer_proto_helper.cc
-    test/cpp/util/string_ref_helper.cc
-    test/cpp/util/subprocess.cc
-    third_party/googletest/googletest/src/gtest-all.cc
-    third_party/googletest/googlemock/src/gmock-all.cc
-  )
-
-  target_include_directories(bm_callback_unary_ping_pong
-    PRIVATE
-      ${CMAKE_CURRENT_SOURCE_DIR}
-      ${CMAKE_CURRENT_SOURCE_DIR}/include
-      ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-      ${_gRPC_RE2_INCLUDE_DIR}
-      ${_gRPC_SSL_INCLUDE_DIR}
-      ${_gRPC_UPB_GENERATED_DIR}
-      ${_gRPC_UPB_GRPC_GENERATED_DIR}
-      ${_gRPC_UPB_INCLUDE_DIR}
-      ${_gRPC_XXHASH_INCLUDE_DIR}
-      ${_gRPC_ZLIB_INCLUDE_DIR}
-      third_party/googletest/googletest/include
-      third_party/googletest/googletest
-      third_party/googletest/googlemock/include
-      third_party/googletest/googlemock
-      ${_gRPC_PROTO_GENS_DIR}
-  )
-
-  target_link_libraries(bm_callback_unary_ping_pong
-    ${_gRPC_PROTOBUF_LIBRARIES}
-    ${_gRPC_ALLTARGETS_LIBRARIES}
-    benchmark_helpers
-  )
-
-
-endif()
-endif()
-if(gRPC_BUILD_TESTS)
-if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
-
-  add_executable(bm_channel
-    test/cpp/microbenchmarks/bm_channel.cc
-    third_party/googletest/googletest/src/gtest-all.cc
-    third_party/googletest/googlemock/src/gmock-all.cc
-  )
-
-  target_include_directories(bm_channel
-    PRIVATE
-      ${CMAKE_CURRENT_SOURCE_DIR}
-      ${CMAKE_CURRENT_SOURCE_DIR}/include
-      ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-      ${_gRPC_RE2_INCLUDE_DIR}
-      ${_gRPC_SSL_INCLUDE_DIR}
-      ${_gRPC_UPB_GENERATED_DIR}
-      ${_gRPC_UPB_GRPC_GENERATED_DIR}
-      ${_gRPC_UPB_INCLUDE_DIR}
-      ${_gRPC_XXHASH_INCLUDE_DIR}
-      ${_gRPC_ZLIB_INCLUDE_DIR}
-      third_party/googletest/googletest/include
-      third_party/googletest/googletest
-      third_party/googletest/googlemock/include
-      third_party/googletest/googlemock
-      ${_gRPC_PROTO_GENS_DIR}
-  )
-
-  target_link_libraries(bm_channel
-    ${_gRPC_PROTOBUF_LIBRARIES}
-    ${_gRPC_ALLTARGETS_LIBRARIES}
-    benchmark_helpers
-  )
-
-
-endif()
-endif()
-if(gRPC_BUILD_TESTS)
-if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
-
-  add_executable(bm_chttp2_hpack
-    test/cpp/microbenchmarks/bm_chttp2_hpack.cc
-    third_party/googletest/googletest/src/gtest-all.cc
-    third_party/googletest/googlemock/src/gmock-all.cc
-  )
-
-  target_include_directories(bm_chttp2_hpack
-    PRIVATE
-      ${CMAKE_CURRENT_SOURCE_DIR}
-      ${CMAKE_CURRENT_SOURCE_DIR}/include
-      ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-      ${_gRPC_RE2_INCLUDE_DIR}
-      ${_gRPC_SSL_INCLUDE_DIR}
-      ${_gRPC_UPB_GENERATED_DIR}
-      ${_gRPC_UPB_GRPC_GENERATED_DIR}
-      ${_gRPC_UPB_INCLUDE_DIR}
-      ${_gRPC_XXHASH_INCLUDE_DIR}
-      ${_gRPC_ZLIB_INCLUDE_DIR}
-      third_party/googletest/googletest/include
-      third_party/googletest/googletest
-      third_party/googletest/googlemock/include
-      third_party/googletest/googlemock
-      ${_gRPC_PROTO_GENS_DIR}
-  )
-
-  target_link_libraries(bm_chttp2_hpack
-    ${_gRPC_PROTOBUF_LIBRARIES}
-    ${_gRPC_ALLTARGETS_LIBRARIES}
-    benchmark_helpers
-  )
-
-
-endif()
-endif()
-if(gRPC_BUILD_TESTS)
-if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
-
-  add_executable(bm_chttp2_transport
-    test/cpp/microbenchmarks/bm_chttp2_transport.cc
-    third_party/googletest/googletest/src/gtest-all.cc
-    third_party/googletest/googlemock/src/gmock-all.cc
-  )
-
-  target_include_directories(bm_chttp2_transport
-    PRIVATE
-      ${CMAKE_CURRENT_SOURCE_DIR}
-      ${CMAKE_CURRENT_SOURCE_DIR}/include
-      ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-      ${_gRPC_RE2_INCLUDE_DIR}
-      ${_gRPC_SSL_INCLUDE_DIR}
-      ${_gRPC_UPB_GENERATED_DIR}
-      ${_gRPC_UPB_GRPC_GENERATED_DIR}
-      ${_gRPC_UPB_INCLUDE_DIR}
-      ${_gRPC_XXHASH_INCLUDE_DIR}
-      ${_gRPC_ZLIB_INCLUDE_DIR}
-      third_party/googletest/googletest/include
-      third_party/googletest/googletest
-      third_party/googletest/googlemock/include
-      third_party/googletest/googlemock
-      ${_gRPC_PROTO_GENS_DIR}
-  )
-
-  target_link_libraries(bm_chttp2_transport
-    ${_gRPC_PROTOBUF_LIBRARIES}
-    ${_gRPC_ALLTARGETS_LIBRARIES}
-    benchmark_helpers
-  )
-
-
-endif()
-endif()
-if(gRPC_BUILD_TESTS)
-if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
-
-  add_executable(bm_closure
-    test/cpp/microbenchmarks/bm_closure.cc
-    third_party/googletest/googletest/src/gtest-all.cc
-    third_party/googletest/googlemock/src/gmock-all.cc
-  )
-
-  target_include_directories(bm_closure
-    PRIVATE
-      ${CMAKE_CURRENT_SOURCE_DIR}
-      ${CMAKE_CURRENT_SOURCE_DIR}/include
-      ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-      ${_gRPC_RE2_INCLUDE_DIR}
-      ${_gRPC_SSL_INCLUDE_DIR}
-      ${_gRPC_UPB_GENERATED_DIR}
-      ${_gRPC_UPB_GRPC_GENERATED_DIR}
-      ${_gRPC_UPB_INCLUDE_DIR}
-      ${_gRPC_XXHASH_INCLUDE_DIR}
-      ${_gRPC_ZLIB_INCLUDE_DIR}
-      third_party/googletest/googletest/include
-      third_party/googletest/googletest
-      third_party/googletest/googlemock/include
-      third_party/googletest/googlemock
-      ${_gRPC_PROTO_GENS_DIR}
-  )
-
-  target_link_libraries(bm_closure
-    ${_gRPC_PROTOBUF_LIBRARIES}
-    ${_gRPC_ALLTARGETS_LIBRARIES}
-    benchmark_helpers
-  )
-
-
-endif()
-endif()
-if(gRPC_BUILD_TESTS)
-if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
-
-  add_executable(bm_cq
-    test/cpp/microbenchmarks/bm_cq.cc
-    third_party/googletest/googletest/src/gtest-all.cc
-    third_party/googletest/googlemock/src/gmock-all.cc
-  )
-
-  target_include_directories(bm_cq
-    PRIVATE
-      ${CMAKE_CURRENT_SOURCE_DIR}
-      ${CMAKE_CURRENT_SOURCE_DIR}/include
-      ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-      ${_gRPC_RE2_INCLUDE_DIR}
-      ${_gRPC_SSL_INCLUDE_DIR}
-      ${_gRPC_UPB_GENERATED_DIR}
-      ${_gRPC_UPB_GRPC_GENERATED_DIR}
-      ${_gRPC_UPB_INCLUDE_DIR}
-      ${_gRPC_XXHASH_INCLUDE_DIR}
-      ${_gRPC_ZLIB_INCLUDE_DIR}
-      third_party/googletest/googletest/include
-      third_party/googletest/googletest
-      third_party/googletest/googlemock/include
-      third_party/googletest/googlemock
-      ${_gRPC_PROTO_GENS_DIR}
-  )
-
-  target_link_libraries(bm_cq
-    ${_gRPC_PROTOBUF_LIBRARIES}
-    ${_gRPC_ALLTARGETS_LIBRARIES}
-    benchmark_helpers
-  )
-
-
-endif()
-endif()
-if(gRPC_BUILD_TESTS)
-if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
-
-  add_executable(bm_cq_multiple_threads
-    test/cpp/microbenchmarks/bm_cq_multiple_threads.cc
-    third_party/googletest/googletest/src/gtest-all.cc
-    third_party/googletest/googlemock/src/gmock-all.cc
-  )
-
-  target_include_directories(bm_cq_multiple_threads
-    PRIVATE
-      ${CMAKE_CURRENT_SOURCE_DIR}
-      ${CMAKE_CURRENT_SOURCE_DIR}/include
-      ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-      ${_gRPC_RE2_INCLUDE_DIR}
-      ${_gRPC_SSL_INCLUDE_DIR}
-      ${_gRPC_UPB_GENERATED_DIR}
-      ${_gRPC_UPB_GRPC_GENERATED_DIR}
-      ${_gRPC_UPB_INCLUDE_DIR}
-      ${_gRPC_XXHASH_INCLUDE_DIR}
-      ${_gRPC_ZLIB_INCLUDE_DIR}
-      third_party/googletest/googletest/include
-      third_party/googletest/googletest
-      third_party/googletest/googlemock/include
-      third_party/googletest/googlemock
-      ${_gRPC_PROTO_GENS_DIR}
-  )
-
-  target_link_libraries(bm_cq_multiple_threads
-    ${_gRPC_PROTOBUF_LIBRARIES}
-    ${_gRPC_ALLTARGETS_LIBRARIES}
-    benchmark_helpers
-  )
-
-
-endif()
-endif()
-if(gRPC_BUILD_TESTS)
-if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
-
-  add_executable(bm_error
-    test/cpp/microbenchmarks/bm_error.cc
-    third_party/googletest/googletest/src/gtest-all.cc
-    third_party/googletest/googlemock/src/gmock-all.cc
-  )
-
-  target_include_directories(bm_error
-    PRIVATE
-      ${CMAKE_CURRENT_SOURCE_DIR}
-      ${CMAKE_CURRENT_SOURCE_DIR}/include
-      ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-      ${_gRPC_RE2_INCLUDE_DIR}
-      ${_gRPC_SSL_INCLUDE_DIR}
-      ${_gRPC_UPB_GENERATED_DIR}
-      ${_gRPC_UPB_GRPC_GENERATED_DIR}
-      ${_gRPC_UPB_INCLUDE_DIR}
-      ${_gRPC_XXHASH_INCLUDE_DIR}
-      ${_gRPC_ZLIB_INCLUDE_DIR}
-      third_party/googletest/googletest/include
-      third_party/googletest/googletest
-      third_party/googletest/googlemock/include
-      third_party/googletest/googlemock
-      ${_gRPC_PROTO_GENS_DIR}
-  )
-
-  target_link_libraries(bm_error
-    ${_gRPC_PROTOBUF_LIBRARIES}
-    ${_gRPC_ALLTARGETS_LIBRARIES}
-    benchmark_helpers
-  )
-
-
-endif()
-endif()
-if(gRPC_BUILD_TESTS)
-if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
-
-  add_executable(bm_fullstack_streaming_ping_pong
-    test/cpp/microbenchmarks/bm_fullstack_streaming_ping_pong.cc
-    third_party/googletest/googletest/src/gtest-all.cc
-    third_party/googletest/googlemock/src/gmock-all.cc
-  )
-
-  target_include_directories(bm_fullstack_streaming_ping_pong
-    PRIVATE
-      ${CMAKE_CURRENT_SOURCE_DIR}
-      ${CMAKE_CURRENT_SOURCE_DIR}/include
-      ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-      ${_gRPC_RE2_INCLUDE_DIR}
-      ${_gRPC_SSL_INCLUDE_DIR}
-      ${_gRPC_UPB_GENERATED_DIR}
-      ${_gRPC_UPB_GRPC_GENERATED_DIR}
-      ${_gRPC_UPB_INCLUDE_DIR}
-      ${_gRPC_XXHASH_INCLUDE_DIR}
-      ${_gRPC_ZLIB_INCLUDE_DIR}
-      third_party/googletest/googletest/include
-      third_party/googletest/googletest
-      third_party/googletest/googlemock/include
-      third_party/googletest/googlemock
-      ${_gRPC_PROTO_GENS_DIR}
-  )
-
-  target_link_libraries(bm_fullstack_streaming_ping_pong
-    ${_gRPC_PROTOBUF_LIBRARIES}
-    ${_gRPC_ALLTARGETS_LIBRARIES}
-    benchmark_helpers
-  )
-
-
-endif()
-endif()
-if(gRPC_BUILD_TESTS)
-if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
-
-  add_executable(bm_fullstack_streaming_pump
-    test/cpp/microbenchmarks/bm_fullstack_streaming_pump.cc
-    third_party/googletest/googletest/src/gtest-all.cc
-    third_party/googletest/googlemock/src/gmock-all.cc
-  )
-
-  target_include_directories(bm_fullstack_streaming_pump
-    PRIVATE
-      ${CMAKE_CURRENT_SOURCE_DIR}
-      ${CMAKE_CURRENT_SOURCE_DIR}/include
-      ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-      ${_gRPC_RE2_INCLUDE_DIR}
-      ${_gRPC_SSL_INCLUDE_DIR}
-      ${_gRPC_UPB_GENERATED_DIR}
-      ${_gRPC_UPB_GRPC_GENERATED_DIR}
-      ${_gRPC_UPB_INCLUDE_DIR}
-      ${_gRPC_XXHASH_INCLUDE_DIR}
-      ${_gRPC_ZLIB_INCLUDE_DIR}
-      third_party/googletest/googletest/include
-      third_party/googletest/googletest
-      third_party/googletest/googlemock/include
-      third_party/googletest/googlemock
-      ${_gRPC_PROTO_GENS_DIR}
-  )
-
-  target_link_libraries(bm_fullstack_streaming_pump
-    ${_gRPC_PROTOBUF_LIBRARIES}
-    ${_gRPC_ALLTARGETS_LIBRARIES}
-    benchmark_helpers
-  )
-
-
-endif()
-endif()
-if(gRPC_BUILD_TESTS)
-if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
-
-  add_executable(bm_fullstack_trickle
-    test/cpp/microbenchmarks/bm_fullstack_trickle.cc
-    third_party/googletest/googletest/src/gtest-all.cc
-    third_party/googletest/googlemock/src/gmock-all.cc
-  )
-
-  target_include_directories(bm_fullstack_trickle
-    PRIVATE
-      ${CMAKE_CURRENT_SOURCE_DIR}
-      ${CMAKE_CURRENT_SOURCE_DIR}/include
-      ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-      ${_gRPC_RE2_INCLUDE_DIR}
-      ${_gRPC_SSL_INCLUDE_DIR}
-      ${_gRPC_UPB_GENERATED_DIR}
-      ${_gRPC_UPB_GRPC_GENERATED_DIR}
-      ${_gRPC_UPB_INCLUDE_DIR}
-      ${_gRPC_XXHASH_INCLUDE_DIR}
-      ${_gRPC_ZLIB_INCLUDE_DIR}
-      third_party/googletest/googletest/include
-      third_party/googletest/googletest
-      third_party/googletest/googlemock/include
-      third_party/googletest/googlemock
-      ${_gRPC_PROTO_GENS_DIR}
-  )
-
-  target_link_libraries(bm_fullstack_trickle
-    ${_gRPC_PROTOBUF_LIBRARIES}
-    ${_gRPC_ALLTARGETS_LIBRARIES}
-    absl::flags
-    benchmark_helpers
-  )
-
-
-endif()
-endif()
-if(gRPC_BUILD_TESTS)
-if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
-
-  add_executable(bm_fullstack_unary_ping_pong
-    test/cpp/microbenchmarks/bm_fullstack_unary_ping_pong.cc
-    third_party/googletest/googletest/src/gtest-all.cc
-    third_party/googletest/googlemock/src/gmock-all.cc
-  )
-
-  target_include_directories(bm_fullstack_unary_ping_pong
-    PRIVATE
-      ${CMAKE_CURRENT_SOURCE_DIR}
-      ${CMAKE_CURRENT_SOURCE_DIR}/include
-      ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-      ${_gRPC_RE2_INCLUDE_DIR}
-      ${_gRPC_SSL_INCLUDE_DIR}
-      ${_gRPC_UPB_GENERATED_DIR}
-      ${_gRPC_UPB_GRPC_GENERATED_DIR}
-      ${_gRPC_UPB_INCLUDE_DIR}
-      ${_gRPC_XXHASH_INCLUDE_DIR}
-      ${_gRPC_ZLIB_INCLUDE_DIR}
-      third_party/googletest/googletest/include
-      third_party/googletest/googletest
-      third_party/googletest/googlemock/include
-      third_party/googletest/googlemock
-      ${_gRPC_PROTO_GENS_DIR}
-  )
-
-  target_link_libraries(bm_fullstack_unary_ping_pong
-    ${_gRPC_PROTOBUF_LIBRARIES}
-    ${_gRPC_ALLTARGETS_LIBRARIES}
-    benchmark_helpers
-  )
-
-
-endif()
-endif()
-if(gRPC_BUILD_TESTS)
-if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
-
-  add_executable(bm_metadata
-    test/cpp/microbenchmarks/bm_metadata.cc
-    third_party/googletest/googletest/src/gtest-all.cc
-    third_party/googletest/googlemock/src/gmock-all.cc
-  )
-
-  target_include_directories(bm_metadata
-    PRIVATE
-      ${CMAKE_CURRENT_SOURCE_DIR}
-      ${CMAKE_CURRENT_SOURCE_DIR}/include
-      ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-      ${_gRPC_RE2_INCLUDE_DIR}
-      ${_gRPC_SSL_INCLUDE_DIR}
-      ${_gRPC_UPB_GENERATED_DIR}
-      ${_gRPC_UPB_GRPC_GENERATED_DIR}
-      ${_gRPC_UPB_INCLUDE_DIR}
-      ${_gRPC_XXHASH_INCLUDE_DIR}
-      ${_gRPC_ZLIB_INCLUDE_DIR}
-      third_party/googletest/googletest/include
-      third_party/googletest/googletest
-      third_party/googletest/googlemock/include
-      third_party/googletest/googlemock
-      ${_gRPC_PROTO_GENS_DIR}
-  )
-
-  target_link_libraries(bm_metadata
-    ${_gRPC_PROTOBUF_LIBRARIES}
-    ${_gRPC_ALLTARGETS_LIBRARIES}
-    benchmark_helpers
-  )
-
-
-endif()
-endif()
-if(gRPC_BUILD_TESTS)
-if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
-
-  add_executable(bm_pollset
-    test/cpp/microbenchmarks/bm_pollset.cc
-    third_party/googletest/googletest/src/gtest-all.cc
-    third_party/googletest/googlemock/src/gmock-all.cc
-  )
-
-  target_include_directories(bm_pollset
-    PRIVATE
-      ${CMAKE_CURRENT_SOURCE_DIR}
-      ${CMAKE_CURRENT_SOURCE_DIR}/include
-      ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-      ${_gRPC_RE2_INCLUDE_DIR}
-      ${_gRPC_SSL_INCLUDE_DIR}
-      ${_gRPC_UPB_GENERATED_DIR}
-      ${_gRPC_UPB_GRPC_GENERATED_DIR}
-      ${_gRPC_UPB_INCLUDE_DIR}
-      ${_gRPC_XXHASH_INCLUDE_DIR}
-      ${_gRPC_ZLIB_INCLUDE_DIR}
-      third_party/googletest/googletest/include
-      third_party/googletest/googletest
-      third_party/googletest/googlemock/include
-      third_party/googletest/googlemock
-      ${_gRPC_PROTO_GENS_DIR}
-  )
-
-  target_link_libraries(bm_pollset
-    ${_gRPC_PROTOBUF_LIBRARIES}
-    ${_gRPC_ALLTARGETS_LIBRARIES}
-    benchmark_helpers
-  )
-
-
-endif()
-endif()
-if(gRPC_BUILD_TESTS)
-if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
-
-  add_executable(bm_threadpool
-    test/cpp/microbenchmarks/bm_threadpool.cc
-    third_party/googletest/googletest/src/gtest-all.cc
-    third_party/googletest/googlemock/src/gmock-all.cc
-  )
-
-  target_include_directories(bm_threadpool
-    PRIVATE
-      ${CMAKE_CURRENT_SOURCE_DIR}
-      ${CMAKE_CURRENT_SOURCE_DIR}/include
-      ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-      ${_gRPC_RE2_INCLUDE_DIR}
-      ${_gRPC_SSL_INCLUDE_DIR}
-      ${_gRPC_UPB_GENERATED_DIR}
-      ${_gRPC_UPB_GRPC_GENERATED_DIR}
-      ${_gRPC_UPB_INCLUDE_DIR}
-      ${_gRPC_XXHASH_INCLUDE_DIR}
-      ${_gRPC_ZLIB_INCLUDE_DIR}
-      third_party/googletest/googletest/include
-      third_party/googletest/googletest
-      third_party/googletest/googlemock/include
-      third_party/googletest/googlemock
-      ${_gRPC_PROTO_GENS_DIR}
-  )
-
-  target_link_libraries(bm_threadpool
-    ${_gRPC_PROTOBUF_LIBRARIES}
-    ${_gRPC_ALLTARGETS_LIBRARIES}
-    benchmark_helpers
-  )
-
-
-endif()
-endif()
-if(gRPC_BUILD_TESTS)
-if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
-
-  add_executable(bm_timer
-    test/cpp/microbenchmarks/bm_timer.cc
-    third_party/googletest/googletest/src/gtest-all.cc
-    third_party/googletest/googlemock/src/gmock-all.cc
-  )
-
-  target_include_directories(bm_timer
-    PRIVATE
-      ${CMAKE_CURRENT_SOURCE_DIR}
-      ${CMAKE_CURRENT_SOURCE_DIR}/include
-      ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-      ${_gRPC_RE2_INCLUDE_DIR}
-      ${_gRPC_SSL_INCLUDE_DIR}
-      ${_gRPC_UPB_GENERATED_DIR}
-      ${_gRPC_UPB_GRPC_GENERATED_DIR}
-      ${_gRPC_UPB_INCLUDE_DIR}
-      ${_gRPC_XXHASH_INCLUDE_DIR}
-      ${_gRPC_ZLIB_INCLUDE_DIR}
-      third_party/googletest/googletest/include
-      third_party/googletest/googletest
-      third_party/googletest/googlemock/include
-      third_party/googletest/googlemock
-      ${_gRPC_PROTO_GENS_DIR}
-  )
-
-  target_link_libraries(bm_timer
-    ${_gRPC_PROTOBUF_LIBRARIES}
-    ${_gRPC_ALLTARGETS_LIBRARIES}
-    benchmark_helpers
-  )
-
-
-endif()
-endif()
-if(gRPC_BUILD_TESTS)
-
-add_executable(byte_buffer_test
-  test/cpp/util/byte_buffer_test.cc
-  third_party/googletest/googletest/src/gtest-all.cc
-  third_party/googletest/googlemock/src/gmock-all.cc
-)
+add_executable(byte_buffer_test
+  test/cpp/util/byte_buffer_test.cc
+  third_party/googletest/googletest/src/gtest-all.cc
+  third_party/googletest/googlemock/src/gmock-all.cc
+)
 
 target_include_directories(byte_buffer_test
   PRIVATE
@@ -9683,6 +8874,41 @@ target_link_libraries(channel_filter_test
 endif()
 if(gRPC_BUILD_TESTS)
 
+add_executable(channel_stack_builder_test
+  test/core/channel/channel_stack_builder_test.cc
+  third_party/googletest/googletest/src/gtest-all.cc
+  third_party/googletest/googlemock/src/gmock-all.cc
+)
+
+target_include_directories(channel_stack_builder_test
+  PRIVATE
+    ${CMAKE_CURRENT_SOURCE_DIR}
+    ${CMAKE_CURRENT_SOURCE_DIR}/include
+    ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
+    ${_gRPC_RE2_INCLUDE_DIR}
+    ${_gRPC_SSL_INCLUDE_DIR}
+    ${_gRPC_UPB_GENERATED_DIR}
+    ${_gRPC_UPB_GRPC_GENERATED_DIR}
+    ${_gRPC_UPB_INCLUDE_DIR}
+    ${_gRPC_XXHASH_INCLUDE_DIR}
+    ${_gRPC_ZLIB_INCLUDE_DIR}
+    third_party/googletest/googletest/include
+    third_party/googletest/googletest
+    third_party/googletest/googlemock/include
+    third_party/googletest/googlemock
+    ${_gRPC_PROTO_GENS_DIR}
+)
+
+target_link_libraries(channel_stack_builder_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  grpc_test_util
+)
+
+
+endif()
+if(gRPC_BUILD_TESTS)
+
 add_executable(channel_trace_test
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/channelz/channelz.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/channelz/channelz.grpc.pb.cc
@@ -9820,7 +9046,99 @@ add_executable(channelz_test
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(channelz_test
+target_include_directories(channelz_test
+  PRIVATE
+    ${CMAKE_CURRENT_SOURCE_DIR}
+    ${CMAKE_CURRENT_SOURCE_DIR}/include
+    ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
+    ${_gRPC_RE2_INCLUDE_DIR}
+    ${_gRPC_SSL_INCLUDE_DIR}
+    ${_gRPC_UPB_GENERATED_DIR}
+    ${_gRPC_UPB_GRPC_GENERATED_DIR}
+    ${_gRPC_UPB_INCLUDE_DIR}
+    ${_gRPC_XXHASH_INCLUDE_DIR}
+    ${_gRPC_ZLIB_INCLUDE_DIR}
+    third_party/googletest/googletest/include
+    third_party/googletest/googletest
+    third_party/googletest/googlemock/include
+    third_party/googletest/googlemock
+    ${_gRPC_PROTO_GENS_DIR}
+)
+
+target_link_libraries(channelz_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  grpc++
+  grpc_test_util
+)
+
+
+endif()
+if(gRPC_BUILD_TESTS)
+
+add_executable(chunked_vector_test
+  src/core/ext/upb-generated/google/api/annotations.upb.c
+  src/core/ext/upb-generated/google/api/expr/v1alpha1/checked.upb.c
+  src/core/ext/upb-generated/google/api/expr/v1alpha1/syntax.upb.c
+  src/core/ext/upb-generated/google/api/http.upb.c
+  src/core/ext/upb-generated/google/protobuf/any.upb.c
+  src/core/ext/upb-generated/google/protobuf/duration.upb.c
+  src/core/ext/upb-generated/google/protobuf/empty.upb.c
+  src/core/ext/upb-generated/google/protobuf/struct.upb.c
+  src/core/ext/upb-generated/google/protobuf/timestamp.upb.c
+  src/core/ext/upb-generated/google/protobuf/wrappers.upb.c
+  src/core/ext/upb-generated/google/rpc/status.upb.c
+  src/core/lib/gpr/alloc.cc
+  src/core/lib/gpr/atm.cc
+  src/core/lib/gpr/cpu_iphone.cc
+  src/core/lib/gpr/cpu_linux.cc
+  src/core/lib/gpr/cpu_posix.cc
+  src/core/lib/gpr/cpu_windows.cc
+  src/core/lib/gpr/env_linux.cc
+  src/core/lib/gpr/env_posix.cc
+  src/core/lib/gpr/env_windows.cc
+  src/core/lib/gpr/log.cc
+  src/core/lib/gpr/log_android.cc
+  src/core/lib/gpr/log_linux.cc
+  src/core/lib/gpr/log_posix.cc
+  src/core/lib/gpr/log_windows.cc
+  src/core/lib/gpr/murmur_hash.cc
+  src/core/lib/gpr/string.cc
+  src/core/lib/gpr/string_posix.cc
+  src/core/lib/gpr/string_util_windows.cc
+  src/core/lib/gpr/string_windows.cc
+  src/core/lib/gpr/sync.cc
+  src/core/lib/gpr/sync_abseil.cc
+  src/core/lib/gpr/sync_posix.cc
+  src/core/lib/gpr/sync_windows.cc
+  src/core/lib/gpr/time.cc
+  src/core/lib/gpr/time_posix.cc
+  src/core/lib/gpr/time_precise.cc
+  src/core/lib/gpr/time_windows.cc
+  src/core/lib/gpr/tmpfile_msys.cc
+  src/core/lib/gpr/tmpfile_posix.cc
+  src/core/lib/gpr/tmpfile_windows.cc
+  src/core/lib/gpr/wrap_memcpy.cc
+  src/core/lib/gprpp/arena.cc
+  src/core/lib/gprpp/examine_stack.cc
+  src/core/lib/gprpp/fork.cc
+  src/core/lib/gprpp/global_config_env.cc
+  src/core/lib/gprpp/host_port.cc
+  src/core/lib/gprpp/mpscq.cc
+  src/core/lib/gprpp/stat_posix.cc
+  src/core/lib/gprpp/stat_windows.cc
+  src/core/lib/gprpp/status_helper.cc
+  src/core/lib/gprpp/thd_posix.cc
+  src/core/lib/gprpp/thd_windows.cc
+  src/core/lib/gprpp/time_util.cc
+  src/core/lib/profiling/basic_timers.cc
+  src/core/lib/profiling/stap_timers.cc
+  test/core/gprpp/chunked_vector_test.cc
+  third_party/googletest/googletest/src/gtest-all.cc
+  third_party/googletest/googlemock/src/gmock-all.cc
+)
+
+target_include_directories(chunked_vector_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -9839,11 +9157,21 @@ target_include_directories(channelz_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(channelz_test
+target_link_libraries(chunked_vector_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc++
-  grpc_test_util
+  absl::base
+  absl::core_headers
+  absl::memory
+  absl::status
+  absl::cord
+  absl::str_format
+  absl::strings
+  absl::synchronization
+  absl::time
+  absl::optional
+  absl::utility
+  upb
 )
 
 
@@ -10117,10 +9445,10 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
     ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
     ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
     ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/orca_load_report_for_test.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/orca_load_report_for_test.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/orca_load_report_for_test.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/orca_load_report_for_test.grpc.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/orca_load_report.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/orca_load_report.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/orca_load_report.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/orca_load_report.grpc.pb.h
     test/core/util/test_lb_policies.cc
     test/cpp/end2end/client_lb_end2end_test.cc
     test/cpp/end2end/test_service_impl.cc
@@ -10478,6 +9806,8 @@ add_executable(core_configuration_test
   src/core/lib/gprpp/time_util.cc
   src/core/lib/profiling/basic_timers.cc
   src/core/lib/profiling/stap_timers.cc
+  src/core/lib/surface/channel_init.cc
+  src/core/lib/surface/channel_stack_type.cc
   test/core/config/core_configuration_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
@@ -10678,57 +10008,22 @@ endif()
 if(gRPC_BUILD_TESTS)
 
 add_executable(end2end_binder_transport_test
-  ${_gRPC_PROTO_GENS_DIR}/test/core/transport/binder/end2end/echo.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/test/core/transport/binder/end2end/echo.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/test/core/transport/binder/end2end/echo.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/test/core/transport/binder/end2end/echo.grpc.pb.h
-  src/core/ext/transport/binder/transport/binder_transport.cc
-  src/core/ext/transport/binder/utils/transport_stream_receiver_impl.cc
-  src/core/ext/transport/binder/wire_format/binder_constants.cc
-  src/core/ext/transport/binder/wire_format/transaction.cc
-  src/core/ext/transport/binder/wire_format/wire_reader_impl.cc
-  src/core/ext/transport/binder/wire_format/wire_writer.cc
-  src/cpp/client/channel_cc.cc
-  src/cpp/client/client_callback.cc
-  src/cpp/client/client_context.cc
-  src/cpp/client/client_interceptor.cc
-  src/cpp/client/create_channel.cc
-  src/cpp/client/create_channel_internal.cc
-  src/cpp/client/create_channel_posix.cc
-  src/cpp/client/credentials_cc.cc
-  src/cpp/codegen/codegen_init.cc
-  src/cpp/common/alarm.cc
-  src/cpp/common/channel_arguments.cc
-  src/cpp/common/channel_filter.cc
-  src/cpp/common/completion_queue_cc.cc
-  src/cpp/common/core_codegen.cc
-  src/cpp/common/resource_quota_cc.cc
-  src/cpp/common/rpc_method.cc
-  src/cpp/common/validate_service_config.cc
-  src/cpp/common/version_cc.cc
-  src/cpp/server/async_generic_service.cc
-  src/cpp/server/channel_argument_option.cc
-  src/cpp/server/create_default_thread_pool.cc
-  src/cpp/server/dynamic_thread_pool.cc
-  src/cpp/server/external_connection_acceptor_impl.cc
-  src/cpp/server/health/default_health_check_service.cc
-  src/cpp/server/health/health_check_service.cc
-  src/cpp/server/health/health_check_service_server_builder_option.cc
-  src/cpp/server/server_builder.cc
-  src/cpp/server/server_callback.cc
-  src/cpp/server/server_cc.cc
-  src/cpp/server/server_context.cc
-  src/cpp/server/server_credentials.cc
-  src/cpp/server/server_posix.cc
-  src/cpp/thread_manager/thread_manager.cc
-  src/cpp/util/byte_buffer_cc.cc
-  src/cpp/util/status.cc
-  src/cpp/util/string_ref.cc
-  src/cpp/util/time_cc.cc
-  test/core/transport/binder/end2end/echo_service.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
   test/core/transport/binder/end2end/end2end_binder_transport_test.cc
   test/core/transport/binder/end2end/fake_binder.cc
   test/core/transport/binder/end2end/testing_channel_create.cc
+  test/cpp/end2end/test_service_impl.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
@@ -10756,7 +10051,7 @@ target_link_libraries(end2end_binder_transport_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
   absl::random_random
-  grpc_test_util
+  grpc++_test_util
 )
 
 
@@ -10817,6 +10112,96 @@ target_link_libraries(end2end_test
 endif()
 if(gRPC_BUILD_TESTS)
 
+add_executable(endpoint_binder_pool_test
+  src/core/ext/transport/binder/client/binder_connector.cc
+  src/core/ext/transport/binder/client/channel_create.cc
+  src/core/ext/transport/binder/client/channel_create_impl.cc
+  src/core/ext/transport/binder/client/connection_id_generator.cc
+  src/core/ext/transport/binder/client/endpoint_binder_pool.cc
+  src/core/ext/transport/binder/client/jni_utils.cc
+  src/core/ext/transport/binder/client/security_policy_setting.cc
+  src/core/ext/transport/binder/security_policy/binder_security_policy.cc
+  src/core/ext/transport/binder/server/binder_server.cc
+  src/core/ext/transport/binder/server/binder_server_credentials.cc
+  src/core/ext/transport/binder/transport/binder_transport.cc
+  src/core/ext/transport/binder/utils/transport_stream_receiver_impl.cc
+  src/core/ext/transport/binder/wire_format/binder_android.cc
+  src/core/ext/transport/binder/wire_format/binder_constants.cc
+  src/core/ext/transport/binder/wire_format/transaction.cc
+  src/core/ext/transport/binder/wire_format/wire_reader_impl.cc
+  src/core/ext/transport/binder/wire_format/wire_writer.cc
+  src/cpp/client/channel_cc.cc
+  src/cpp/client/client_callback.cc
+  src/cpp/client/client_context.cc
+  src/cpp/client/client_interceptor.cc
+  src/cpp/client/create_channel.cc
+  src/cpp/client/create_channel_internal.cc
+  src/cpp/client/create_channel_posix.cc
+  src/cpp/client/credentials_cc.cc
+  src/cpp/codegen/codegen_init.cc
+  src/cpp/common/alarm.cc
+  src/cpp/common/channel_arguments.cc
+  src/cpp/common/channel_filter.cc
+  src/cpp/common/completion_queue_cc.cc
+  src/cpp/common/core_codegen.cc
+  src/cpp/common/resource_quota_cc.cc
+  src/cpp/common/rpc_method.cc
+  src/cpp/common/validate_service_config.cc
+  src/cpp/common/version_cc.cc
+  src/cpp/server/async_generic_service.cc
+  src/cpp/server/channel_argument_option.cc
+  src/cpp/server/create_default_thread_pool.cc
+  src/cpp/server/dynamic_thread_pool.cc
+  src/cpp/server/external_connection_acceptor_impl.cc
+  src/cpp/server/health/default_health_check_service.cc
+  src/cpp/server/health/health_check_service.cc
+  src/cpp/server/health/health_check_service_server_builder_option.cc
+  src/cpp/server/server_builder.cc
+  src/cpp/server/server_callback.cc
+  src/cpp/server/server_cc.cc
+  src/cpp/server/server_context.cc
+  src/cpp/server/server_credentials.cc
+  src/cpp/server/server_posix.cc
+  src/cpp/thread_manager/thread_manager.cc
+  src/cpp/util/byte_buffer_cc.cc
+  src/cpp/util/status.cc
+  src/cpp/util/string_ref.cc
+  src/cpp/util/time_cc.cc
+  test/core/transport/binder/endpoint_binder_pool_test.cc
+  test/core/transport/binder/mock_objects.cc
+  third_party/googletest/googletest/src/gtest-all.cc
+  third_party/googletest/googlemock/src/gmock-all.cc
+)
+
+target_include_directories(endpoint_binder_pool_test
+  PRIVATE
+    ${CMAKE_CURRENT_SOURCE_DIR}
+    ${CMAKE_CURRENT_SOURCE_DIR}/include
+    ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
+    ${_gRPC_RE2_INCLUDE_DIR}
+    ${_gRPC_SSL_INCLUDE_DIR}
+    ${_gRPC_UPB_GENERATED_DIR}
+    ${_gRPC_UPB_GRPC_GENERATED_DIR}
+    ${_gRPC_UPB_INCLUDE_DIR}
+    ${_gRPC_XXHASH_INCLUDE_DIR}
+    ${_gRPC_ZLIB_INCLUDE_DIR}
+    third_party/googletest/googletest/include
+    third_party/googletest/googletest
+    third_party/googletest/googlemock/include
+    third_party/googletest/googlemock
+    ${_gRPC_PROTO_GENS_DIR}
+)
+
+target_link_libraries(endpoint_binder_pool_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  grpc_test_util
+)
+
+
+endif()
+if(gRPC_BUILD_TESTS)
+
 add_executable(endpoint_config_test
   test/core/event_engine/endpoint_config_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
@@ -10896,6 +10281,42 @@ target_link_libraries(error_details_test
 endif()
 if(gRPC_BUILD_TESTS)
 
+add_executable(error_test
+  test/core/iomgr/endpoint_tests.cc
+  test/core/iomgr/error_test.cc
+  third_party/googletest/googletest/src/gtest-all.cc
+  third_party/googletest/googlemock/src/gmock-all.cc
+)
+
+target_include_directories(error_test
+  PRIVATE
+    ${CMAKE_CURRENT_SOURCE_DIR}
+    ${CMAKE_CURRENT_SOURCE_DIR}/include
+    ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
+    ${_gRPC_RE2_INCLUDE_DIR}
+    ${_gRPC_SSL_INCLUDE_DIR}
+    ${_gRPC_UPB_GENERATED_DIR}
+    ${_gRPC_UPB_GRPC_GENERATED_DIR}
+    ${_gRPC_UPB_INCLUDE_DIR}
+    ${_gRPC_XXHASH_INCLUDE_DIR}
+    ${_gRPC_ZLIB_INCLUDE_DIR}
+    third_party/googletest/googletest/include
+    third_party/googletest/googletest
+    third_party/googletest/googlemock/include
+    third_party/googletest/googlemock
+    ${_gRPC_PROTO_GENS_DIR}
+)
+
+target_link_libraries(error_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  grpc_test_util
+)
+
+
+endif()
+if(gRPC_BUILD_TESTS)
+
 add_executable(error_utils_test
   test/core/transport/error_utils_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
@@ -11050,12 +10471,109 @@ target_link_libraries(exception_test
 endif()
 if(gRPC_BUILD_TESTS)
 
+add_executable(exec_ctx_wakeup_scheduler_test
+  src/core/lib/debug/trace.cc
+  src/core/lib/iomgr/combiner.cc
+  src/core/lib/iomgr/error.cc
+  src/core/lib/iomgr/exec_ctx.cc
+  src/core/lib/iomgr/executor.cc
+  src/core/lib/iomgr/iomgr_internal.cc
+  src/core/lib/promise/activity.cc
+  src/core/lib/slice/slice.cc
+  src/core/lib/slice/slice_refcount.cc
+  src/core/lib/slice/slice_string_helpers.cc
+  src/core/lib/slice/static_slice.cc
+  test/core/promise/exec_ctx_wakeup_scheduler_test.cc
+  third_party/googletest/googletest/src/gtest-all.cc
+  third_party/googletest/googlemock/src/gmock-all.cc
+)
+
+target_include_directories(exec_ctx_wakeup_scheduler_test
+  PRIVATE
+    ${CMAKE_CURRENT_SOURCE_DIR}
+    ${CMAKE_CURRENT_SOURCE_DIR}/include
+    ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
+    ${_gRPC_RE2_INCLUDE_DIR}
+    ${_gRPC_SSL_INCLUDE_DIR}
+    ${_gRPC_UPB_GENERATED_DIR}
+    ${_gRPC_UPB_GRPC_GENERATED_DIR}
+    ${_gRPC_UPB_INCLUDE_DIR}
+    ${_gRPC_XXHASH_INCLUDE_DIR}
+    ${_gRPC_ZLIB_INCLUDE_DIR}
+    third_party/googletest/googletest/include
+    third_party/googletest/googletest
+    third_party/googletest/googlemock/include
+    third_party/googletest/googlemock
+    ${_gRPC_PROTO_GENS_DIR}
+)
+
+target_link_libraries(exec_ctx_wakeup_scheduler_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  absl::statusor
+  absl::variant
+  gpr
+)
+
+
+endif()
+if(gRPC_BUILD_TESTS)
+
 add_executable(fake_binder_test
+  src/core/ext/transport/binder/client/binder_connector.cc
+  src/core/ext/transport/binder/client/channel_create.cc
+  src/core/ext/transport/binder/client/channel_create_impl.cc
+  src/core/ext/transport/binder/client/connection_id_generator.cc
+  src/core/ext/transport/binder/client/endpoint_binder_pool.cc
+  src/core/ext/transport/binder/client/jni_utils.cc
+  src/core/ext/transport/binder/client/security_policy_setting.cc
+  src/core/ext/transport/binder/security_policy/binder_security_policy.cc
+  src/core/ext/transport/binder/server/binder_server.cc
+  src/core/ext/transport/binder/server/binder_server_credentials.cc
+  src/core/ext/transport/binder/transport/binder_transport.cc
   src/core/ext/transport/binder/utils/transport_stream_receiver_impl.cc
+  src/core/ext/transport/binder/wire_format/binder_android.cc
   src/core/ext/transport/binder/wire_format/binder_constants.cc
   src/core/ext/transport/binder/wire_format/transaction.cc
   src/core/ext/transport/binder/wire_format/wire_reader_impl.cc
   src/core/ext/transport/binder/wire_format/wire_writer.cc
+  src/cpp/client/channel_cc.cc
+  src/cpp/client/client_callback.cc
+  src/cpp/client/client_context.cc
+  src/cpp/client/client_interceptor.cc
+  src/cpp/client/create_channel.cc
+  src/cpp/client/create_channel_internal.cc
+  src/cpp/client/create_channel_posix.cc
+  src/cpp/client/credentials_cc.cc
+  src/cpp/codegen/codegen_init.cc
+  src/cpp/common/alarm.cc
+  src/cpp/common/channel_arguments.cc
+  src/cpp/common/channel_filter.cc
+  src/cpp/common/completion_queue_cc.cc
+  src/cpp/common/core_codegen.cc
+  src/cpp/common/resource_quota_cc.cc
+  src/cpp/common/rpc_method.cc
+  src/cpp/common/validate_service_config.cc
+  src/cpp/common/version_cc.cc
+  src/cpp/server/async_generic_service.cc
+  src/cpp/server/channel_argument_option.cc
+  src/cpp/server/create_default_thread_pool.cc
+  src/cpp/server/dynamic_thread_pool.cc
+  src/cpp/server/external_connection_acceptor_impl.cc
+  src/cpp/server/health/default_health_check_service.cc
+  src/cpp/server/health/health_check_service.cc
+  src/cpp/server/health/health_check_service_server_builder_option.cc
+  src/cpp/server/server_builder.cc
+  src/cpp/server/server_callback.cc
+  src/cpp/server/server_cc.cc
+  src/cpp/server/server_context.cc
+  src/cpp/server/server_credentials.cc
+  src/cpp/server/server_posix.cc
+  src/cpp/thread_manager/thread_manager.cc
+  src/cpp/util/byte_buffer_cc.cc
+  src/cpp/util/status.cc
+  src/cpp/util/string_ref.cc
+  src/cpp/util/time_cc.cc
   test/core/transport/binder/end2end/fake_binder.cc
   test/core/transport/binder/end2end/fake_binder_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
@@ -11679,7 +11197,7 @@ target_link_libraries(grpc_cpp_plugin
 
 
 
-if(gRPC_INSTALL AND NOT CMAKE_CROSSCOMPILING)
+if(gRPC_INSTALL)
   install(TARGETS grpc_cpp_plugin EXPORT gRPCTargets
     RUNTIME DESTINATION ${gRPC_INSTALL_BINDIR}
     LIBRARY DESTINATION ${gRPC_INSTALL_LIBDIR}
@@ -11718,7 +11236,7 @@ target_link_libraries(grpc_csharp_plugin
 
 
 
-if(gRPC_INSTALL AND NOT CMAKE_CROSSCOMPILING)
+if(gRPC_INSTALL)
   install(TARGETS grpc_csharp_plugin EXPORT gRPCTargets
     RUNTIME DESTINATION ${gRPC_INSTALL_BINDIR}
     LIBRARY DESTINATION ${gRPC_INSTALL_LIBDIR}
@@ -11757,7 +11275,7 @@ target_link_libraries(grpc_node_plugin
 
 
 
-if(gRPC_INSTALL AND NOT CMAKE_CROSSCOMPILING)
+if(gRPC_INSTALL)
   install(TARGETS grpc_node_plugin EXPORT gRPCTargets
     RUNTIME DESTINATION ${gRPC_INSTALL_BINDIR}
     LIBRARY DESTINATION ${gRPC_INSTALL_LIBDIR}
@@ -11796,7 +11314,7 @@ target_link_libraries(grpc_objective_c_plugin
 
 
 
-if(gRPC_INSTALL AND NOT CMAKE_CROSSCOMPILING)
+if(gRPC_INSTALL)
   install(TARGETS grpc_objective_c_plugin EXPORT gRPCTargets
     RUNTIME DESTINATION ${gRPC_INSTALL_BINDIR}
     LIBRARY DESTINATION ${gRPC_INSTALL_LIBDIR}
@@ -11835,7 +11353,7 @@ target_link_libraries(grpc_php_plugin
 
 
 
-if(gRPC_INSTALL AND NOT CMAKE_CROSSCOMPILING)
+if(gRPC_INSTALL)
   install(TARGETS grpc_php_plugin EXPORT gRPCTargets
     RUNTIME DESTINATION ${gRPC_INSTALL_BINDIR}
     LIBRARY DESTINATION ${gRPC_INSTALL_LIBDIR}
@@ -11874,7 +11392,7 @@ target_link_libraries(grpc_python_plugin
 
 
 
-if(gRPC_INSTALL AND NOT CMAKE_CROSSCOMPILING)
+if(gRPC_INSTALL)
   install(TARGETS grpc_python_plugin EXPORT gRPCTargets
     RUNTIME DESTINATION ${gRPC_INSTALL_BINDIR}
     LIBRARY DESTINATION ${gRPC_INSTALL_LIBDIR}
@@ -11913,7 +11431,7 @@ target_link_libraries(grpc_ruby_plugin
 
 
 
-if(gRPC_INSTALL AND NOT CMAKE_CROSSCOMPILING)
+if(gRPC_INSTALL)
   install(TARGETS grpc_ruby_plugin EXPORT gRPCTargets
     RUNTIME DESTINATION ${gRPC_INSTALL_BINDIR}
     LIBRARY DESTINATION ${gRPC_INSTALL_LIBDIR}
@@ -12168,242 +11686,29 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
       third_party/googletest/googletest/include
       third_party/googletest/googletest
       third_party/googletest/googlemock/include
-      third_party/googletest/googlemock
-      ${_gRPC_PROTO_GENS_DIR}
-  )
-
-  target_link_libraries(grpclb_end2end_test
-    ${_gRPC_PROTOBUF_LIBRARIES}
-    ${_gRPC_ALLTARGETS_LIBRARIES}
-    grpc++_test_config
-    grpc++_test_util
-  )
-
-
-endif()
-endif()
-if(gRPC_BUILD_TESTS)
-
-add_executable(h2_ssl_session_reuse_test
-  test/core/end2end/h2_ssl_session_reuse_test.cc
-  third_party/googletest/googletest/src/gtest-all.cc
-  third_party/googletest/googlemock/src/gmock-all.cc
-)
-
-target_include_directories(h2_ssl_session_reuse_test
-  PRIVATE
-    ${CMAKE_CURRENT_SOURCE_DIR}
-    ${CMAKE_CURRENT_SOURCE_DIR}/include
-    ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-    ${_gRPC_RE2_INCLUDE_DIR}
-    ${_gRPC_SSL_INCLUDE_DIR}
-    ${_gRPC_UPB_GENERATED_DIR}
-    ${_gRPC_UPB_GRPC_GENERATED_DIR}
-    ${_gRPC_UPB_INCLUDE_DIR}
-    ${_gRPC_XXHASH_INCLUDE_DIR}
-    ${_gRPC_ZLIB_INCLUDE_DIR}
-    third_party/googletest/googletest/include
-    third_party/googletest/googletest
-    third_party/googletest/googlemock/include
-    third_party/googletest/googlemock
-    ${_gRPC_PROTO_GENS_DIR}
-)
-
-target_link_libraries(h2_ssl_session_reuse_test
-  ${_gRPC_PROTOBUF_LIBRARIES}
-  ${_gRPC_ALLTARGETS_LIBRARIES}
-  end2end_tests
-)
-
-
-endif()
-if(gRPC_BUILD_TESTS)
-
-add_executable(head_of_line_blocking_bad_client_test
-  test/core/bad_client/bad_client.cc
-  test/core/bad_client/tests/head_of_line_blocking.cc
-  test/core/end2end/cq_verifier.cc
-  third_party/googletest/googletest/src/gtest-all.cc
-  third_party/googletest/googlemock/src/gmock-all.cc
-)
-
-target_include_directories(head_of_line_blocking_bad_client_test
-  PRIVATE
-    ${CMAKE_CURRENT_SOURCE_DIR}
-    ${CMAKE_CURRENT_SOURCE_DIR}/include
-    ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-    ${_gRPC_RE2_INCLUDE_DIR}
-    ${_gRPC_SSL_INCLUDE_DIR}
-    ${_gRPC_UPB_GENERATED_DIR}
-    ${_gRPC_UPB_GRPC_GENERATED_DIR}
-    ${_gRPC_UPB_INCLUDE_DIR}
-    ${_gRPC_XXHASH_INCLUDE_DIR}
-    ${_gRPC_ZLIB_INCLUDE_DIR}
-    third_party/googletest/googletest/include
-    third_party/googletest/googletest
-    third_party/googletest/googlemock/include
-    third_party/googletest/googlemock
-    ${_gRPC_PROTO_GENS_DIR}
-)
-
-target_link_libraries(head_of_line_blocking_bad_client_test
-  ${_gRPC_PROTOBUF_LIBRARIES}
-  ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc_test_util
-)
-
-
-endif()
-if(gRPC_BUILD_TESTS)
-
-add_executable(headers_bad_client_test
-  test/core/bad_client/bad_client.cc
-  test/core/bad_client/tests/headers.cc
-  test/core/end2end/cq_verifier.cc
-  third_party/googletest/googletest/src/gtest-all.cc
-  third_party/googletest/googlemock/src/gmock-all.cc
-)
-
-target_include_directories(headers_bad_client_test
-  PRIVATE
-    ${CMAKE_CURRENT_SOURCE_DIR}
-    ${CMAKE_CURRENT_SOURCE_DIR}/include
-    ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-    ${_gRPC_RE2_INCLUDE_DIR}
-    ${_gRPC_SSL_INCLUDE_DIR}
-    ${_gRPC_UPB_GENERATED_DIR}
-    ${_gRPC_UPB_GRPC_GENERATED_DIR}
-    ${_gRPC_UPB_INCLUDE_DIR}
-    ${_gRPC_XXHASH_INCLUDE_DIR}
-    ${_gRPC_ZLIB_INCLUDE_DIR}
-    third_party/googletest/googletest/include
-    third_party/googletest/googletest
-    third_party/googletest/googlemock/include
-    third_party/googletest/googlemock
-    ${_gRPC_PROTO_GENS_DIR}
-)
-
-target_link_libraries(headers_bad_client_test
-  ${_gRPC_PROTOBUF_LIBRARIES}
-  ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc_test_util
-)
-
-
-endif()
-if(gRPC_BUILD_TESTS)
-
-add_executable(health_service_end2end_test
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/health/v1/health.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/health/v1/health.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/health/v1/health.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/health/v1/health.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
-  test/cpp/end2end/health_service_end2end_test.cc
-  test/cpp/end2end/test_health_check_service_impl.cc
-  test/cpp/end2end/test_service_impl.cc
-  third_party/googletest/googletest/src/gtest-all.cc
-  third_party/googletest/googlemock/src/gmock-all.cc
-)
-
-target_include_directories(health_service_end2end_test
-  PRIVATE
-    ${CMAKE_CURRENT_SOURCE_DIR}
-    ${CMAKE_CURRENT_SOURCE_DIR}/include
-    ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-    ${_gRPC_RE2_INCLUDE_DIR}
-    ${_gRPC_SSL_INCLUDE_DIR}
-    ${_gRPC_UPB_GENERATED_DIR}
-    ${_gRPC_UPB_GRPC_GENERATED_DIR}
-    ${_gRPC_UPB_INCLUDE_DIR}
-    ${_gRPC_XXHASH_INCLUDE_DIR}
-    ${_gRPC_ZLIB_INCLUDE_DIR}
-    third_party/googletest/googletest/include
-    third_party/googletest/googletest
-    third_party/googletest/googlemock/include
-    third_party/googletest/googlemock
-    ${_gRPC_PROTO_GENS_DIR}
-)
-
-target_link_libraries(health_service_end2end_test
-  ${_gRPC_PROTOBUF_LIBRARIES}
-  ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc++_test_util
-)
-
-
-endif()
-if(gRPC_BUILD_TESTS)
-
-add_executable(hpack_encoder_index_test
-  test/core/transport/chttp2/hpack_encoder_index_test.cc
-  third_party/googletest/googletest/src/gtest-all.cc
-  third_party/googletest/googlemock/src/gmock-all.cc
-)
-
-target_include_directories(hpack_encoder_index_test
-  PRIVATE
-    ${CMAKE_CURRENT_SOURCE_DIR}
-    ${CMAKE_CURRENT_SOURCE_DIR}/include
-    ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-    ${_gRPC_RE2_INCLUDE_DIR}
-    ${_gRPC_SSL_INCLUDE_DIR}
-    ${_gRPC_UPB_GENERATED_DIR}
-    ${_gRPC_UPB_GRPC_GENERATED_DIR}
-    ${_gRPC_UPB_INCLUDE_DIR}
-    ${_gRPC_XXHASH_INCLUDE_DIR}
-    ${_gRPC_ZLIB_INCLUDE_DIR}
-    third_party/googletest/googletest/include
-    third_party/googletest/googletest
-    third_party/googletest/googlemock/include
-    third_party/googletest/googlemock
-    ${_gRPC_PROTO_GENS_DIR}
-)
+      third_party/googletest/googlemock
+      ${_gRPC_PROTO_GENS_DIR}
+  )
 
-target_link_libraries(hpack_encoder_index_test
-  ${_gRPC_PROTOBUF_LIBRARIES}
-  ${_gRPC_ALLTARGETS_LIBRARIES}
-  absl::optional
-)
+  target_link_libraries(grpclb_end2end_test
+    ${_gRPC_PROTOBUF_LIBRARIES}
+    ${_gRPC_ALLTARGETS_LIBRARIES}
+    grpc++_test_config
+    grpc++_test_util
+  )
 
 
 endif()
+endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(http2_client
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.grpc.pb.h
-  test/cpp/interop/http2_client.cc
+add_executable(h2_ssl_session_reuse_test
+  test/core/end2end/h2_ssl_session_reuse_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(http2_client
+target_include_directories(h2_ssl_session_reuse_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -12422,41 +11727,25 @@ target_include_directories(http2_client
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(http2_client
+target_link_libraries(h2_ssl_session_reuse_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc++_test_config
-  grpc++_test_util
+  end2end_tests
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(hybrid_end2end_test
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
-  test/cpp/end2end/hybrid_end2end_test.cc
-  test/cpp/end2end/test_service_impl.cc
+add_executable(head_of_line_blocking_bad_client_test
+  test/core/bad_client/bad_client.cc
+  test/core/bad_client/tests/head_of_line_blocking.cc
+  test/core/end2end/cq_verifier.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(hybrid_end2end_test
+target_include_directories(head_of_line_blocking_bad_client_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -12475,23 +11764,25 @@ target_include_directories(hybrid_end2end_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(hybrid_end2end_test
+target_link_libraries(head_of_line_blocking_bad_client_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc++_test_util
+  grpc_test_util
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(if_test
-  test/core/promise/if_test.cc
+add_executable(headers_bad_client_test
+  test/core/bad_client/bad_client.cc
+  test/core/bad_client/tests/headers.cc
+  test/core/end2end/cq_verifier.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(if_test
+target_include_directories(headers_bad_client_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -12510,24 +11801,45 @@ target_include_directories(if_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(if_test
+target_link_libraries(headers_bad_client_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  absl::statusor
-  absl::variant
+  grpc_test_util
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(init_test
-  test/core/surface/init_test.cc
+add_executable(health_service_end2end_test
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/health/v1/health.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/health/v1/health.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/health/v1/health.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/health/v1/health.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
+  test/cpp/end2end/health_service_end2end_test.cc
+  test/cpp/end2end/test_health_check_service_impl.cc
+  test/cpp/end2end/test_service_impl.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(init_test
+target_include_directories(health_service_end2end_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -12546,25 +11858,23 @@ target_include_directories(init_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(init_test
+target_link_libraries(health_service_end2end_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc_test_util
+  grpc++_test_util
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(initial_settings_frame_bad_client_test
-  test/core/bad_client/bad_client.cc
-  test/core/bad_client/tests/initial_settings_frame.cc
-  test/core/end2end/cq_verifier.cc
+add_executable(hpack_encoder_index_test
+  test/core/transport/chttp2/hpack_encoder_index_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(initial_settings_frame_bad_client_test
+target_include_directories(hpack_encoder_index_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -12583,23 +11893,23 @@ target_include_directories(initial_settings_frame_bad_client_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(initial_settings_frame_bad_client_test
+target_link_libraries(hpack_encoder_index_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc_test_util
+  absl::optional
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(insecure_security_connector_test
-  test/core/security/insecure_security_connector_test.cc
+add_executable(hpack_parser_table_test
+  test/core/transport/chttp2/hpack_parser_table_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(insecure_security_connector_test
+target_include_directories(hpack_parser_table_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -12618,7 +11928,7 @@ target_include_directories(insecure_security_connector_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(insecure_security_connector_test
+target_link_libraries(hpack_parser_table_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
@@ -12628,28 +11938,13 @@ target_link_libraries(insecure_security_connector_test
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(interop_client
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.grpc.pb.h
-  test/core/security/oauth2_utils.cc
-  test/cpp/interop/client.cc
-  test/cpp/interop/client_helper.cc
-  test/cpp/interop/interop_client.cc
+add_executable(hpack_parser_test
+  test/core/transport/chttp2/hpack_parser_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(interop_client
+target_include_directories(hpack_parser_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -12668,18 +11963,17 @@ target_include_directories(interop_client
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(interop_client
+target_link_libraries(hpack_parser_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc++_test_config
-  grpc++_test_util
+  grpc_test_util
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(interop_server
+add_executable(http2_client
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.grpc.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.pb.h
@@ -12692,14 +11986,12 @@ add_executable(interop_server
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.grpc.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.pb.h
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.grpc.pb.h
-  test/cpp/interop/interop_server.cc
-  test/cpp/interop/interop_server_bootstrap.cc
-  test/cpp/interop/server_helper.cc
+  test/cpp/interop/http2_client.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(interop_server
+target_include_directories(http2_client
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -12718,7 +12010,7 @@ target_include_directories(interop_server
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(interop_server
+target_link_libraries(http2_client
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc++_test_config
@@ -12728,87 +12020,31 @@ target_link_libraries(interop_server
 
 endif()
 if(gRPC_BUILD_TESTS)
-if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
-
-  add_executable(interop_test
-    test/cpp/interop/interop_test.cc
-    third_party/googletest/googletest/src/gtest-all.cc
-    third_party/googletest/googlemock/src/gmock-all.cc
-  )
-
-  target_include_directories(interop_test
-    PRIVATE
-      ${CMAKE_CURRENT_SOURCE_DIR}
-      ${CMAKE_CURRENT_SOURCE_DIR}/include
-      ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-      ${_gRPC_RE2_INCLUDE_DIR}
-      ${_gRPC_SSL_INCLUDE_DIR}
-      ${_gRPC_UPB_GENERATED_DIR}
-      ${_gRPC_UPB_GRPC_GENERATED_DIR}
-      ${_gRPC_UPB_INCLUDE_DIR}
-      ${_gRPC_XXHASH_INCLUDE_DIR}
-      ${_gRPC_ZLIB_INCLUDE_DIR}
-      third_party/googletest/googletest/include
-      third_party/googletest/googletest
-      third_party/googletest/googlemock/include
-      third_party/googletest/googlemock
-      ${_gRPC_PROTO_GENS_DIR}
-  )
-
-  target_link_libraries(interop_test
-    ${_gRPC_PROTOBUF_LIBRARIES}
-    ${_gRPC_ALLTARGETS_LIBRARIES}
-    grpc++_test_config
-    grpc++_test_util
-  )
-
-
-endif()
-endif()
-if(gRPC_BUILD_TESTS)
-
-add_executable(join_test
-  test/core/promise/join_test.cc
-  third_party/googletest/googletest/src/gtest-all.cc
-  third_party/googletest/googlemock/src/gmock-all.cc
-)
-
-target_include_directories(join_test
-  PRIVATE
-    ${CMAKE_CURRENT_SOURCE_DIR}
-    ${CMAKE_CURRENT_SOURCE_DIR}/include
-    ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-    ${_gRPC_RE2_INCLUDE_DIR}
-    ${_gRPC_SSL_INCLUDE_DIR}
-    ${_gRPC_UPB_GENERATED_DIR}
-    ${_gRPC_UPB_GRPC_GENERATED_DIR}
-    ${_gRPC_UPB_INCLUDE_DIR}
-    ${_gRPC_XXHASH_INCLUDE_DIR}
-    ${_gRPC_ZLIB_INCLUDE_DIR}
-    third_party/googletest/googletest/include
-    third_party/googletest/googletest
-    third_party/googletest/googlemock/include
-    third_party/googletest/googlemock
-    ${_gRPC_PROTO_GENS_DIR}
-)
-
-target_link_libraries(join_test
-  ${_gRPC_PROTOBUF_LIBRARIES}
-  ${_gRPC_ALLTARGETS_LIBRARIES}
-  absl::variant
-)
-
-
-endif()
-if(gRPC_BUILD_TESTS)
 
-add_executable(json_test
-  test/core/json/json_test.cc
+add_executable(hybrid_end2end_test
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
+  test/cpp/end2end/hybrid_end2end_test.cc
+  test/cpp/end2end/test_service_impl.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(json_test
+target_include_directories(hybrid_end2end_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -12827,25 +12063,24 @@ target_include_directories(json_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(json_test
+target_link_libraries(hybrid_end2end_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc_test_util
+  grpc++_test_util
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(large_metadata_bad_client_test
-  test/core/bad_client/bad_client.cc
-  test/core/bad_client/tests/large_metadata.cc
-  test/core/end2end/cq_verifier.cc
+add_executable(idle_filter_state_test
+  src/core/ext/filters/client_idle/idle_filter_state.cc
+  test/core/client_idle/idle_filter_state_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(large_metadata_bad_client_test
+target_include_directories(idle_filter_state_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -12864,80 +12099,22 @@ target_include_directories(large_metadata_bad_client_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(large_metadata_bad_client_test
+target_link_libraries(idle_filter_state_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc_test_util
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(latch_test
-  src/core/ext/upb-generated/google/api/annotations.upb.c
-  src/core/ext/upb-generated/google/api/expr/v1alpha1/checked.upb.c
-  src/core/ext/upb-generated/google/api/expr/v1alpha1/syntax.upb.c
-  src/core/ext/upb-generated/google/api/http.upb.c
-  src/core/ext/upb-generated/google/protobuf/any.upb.c
-  src/core/ext/upb-generated/google/protobuf/duration.upb.c
-  src/core/ext/upb-generated/google/protobuf/empty.upb.c
-  src/core/ext/upb-generated/google/protobuf/struct.upb.c
-  src/core/ext/upb-generated/google/protobuf/timestamp.upb.c
-  src/core/ext/upb-generated/google/protobuf/wrappers.upb.c
-  src/core/ext/upb-generated/google/rpc/status.upb.c
-  src/core/lib/gpr/alloc.cc
-  src/core/lib/gpr/atm.cc
-  src/core/lib/gpr/cpu_iphone.cc
-  src/core/lib/gpr/cpu_linux.cc
-  src/core/lib/gpr/cpu_posix.cc
-  src/core/lib/gpr/cpu_windows.cc
-  src/core/lib/gpr/env_linux.cc
-  src/core/lib/gpr/env_posix.cc
-  src/core/lib/gpr/env_windows.cc
-  src/core/lib/gpr/log.cc
-  src/core/lib/gpr/log_android.cc
-  src/core/lib/gpr/log_linux.cc
-  src/core/lib/gpr/log_posix.cc
-  src/core/lib/gpr/log_windows.cc
-  src/core/lib/gpr/murmur_hash.cc
-  src/core/lib/gpr/string.cc
-  src/core/lib/gpr/string_posix.cc
-  src/core/lib/gpr/string_util_windows.cc
-  src/core/lib/gpr/string_windows.cc
-  src/core/lib/gpr/sync.cc
-  src/core/lib/gpr/sync_abseil.cc
-  src/core/lib/gpr/sync_posix.cc
-  src/core/lib/gpr/sync_windows.cc
-  src/core/lib/gpr/time.cc
-  src/core/lib/gpr/time_posix.cc
-  src/core/lib/gpr/time_precise.cc
-  src/core/lib/gpr/time_windows.cc
-  src/core/lib/gpr/tmpfile_msys.cc
-  src/core/lib/gpr/tmpfile_posix.cc
-  src/core/lib/gpr/tmpfile_windows.cc
-  src/core/lib/gpr/wrap_memcpy.cc
-  src/core/lib/gprpp/arena.cc
-  src/core/lib/gprpp/examine_stack.cc
-  src/core/lib/gprpp/fork.cc
-  src/core/lib/gprpp/global_config_env.cc
-  src/core/lib/gprpp/host_port.cc
-  src/core/lib/gprpp/mpscq.cc
-  src/core/lib/gprpp/stat_posix.cc
-  src/core/lib/gprpp/stat_windows.cc
-  src/core/lib/gprpp/status_helper.cc
-  src/core/lib/gprpp/thd_posix.cc
-  src/core/lib/gprpp/thd_windows.cc
-  src/core/lib/gprpp/time_util.cc
-  src/core/lib/profiling/basic_timers.cc
-  src/core/lib/profiling/stap_timers.cc
-  src/core/lib/promise/activity.cc
-  test/core/promise/latch_test.cc
+add_executable(if_test
+  test/core/promise/if_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(latch_test
+target_include_directories(if_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -12956,39 +12133,24 @@ target_include_directories(latch_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(latch_test
+target_link_libraries(if_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  absl::base
-  absl::core_headers
-  absl::memory
-  absl::status
   absl::statusor
-  absl::cord
-  absl::str_format
-  absl::strings
-  absl::synchronization
-  absl::time
-  absl::optional
   absl::variant
-  upb
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(lb_get_cpu_stats_test
-  src/cpp/server/load_reporter/get_cpu_stats_linux.cc
-  src/cpp/server/load_reporter/get_cpu_stats_macos.cc
-  src/cpp/server/load_reporter/get_cpu_stats_unsupported.cc
-  src/cpp/server/load_reporter/get_cpu_stats_windows.cc
-  test/cpp/server/load_reporter/get_cpu_stats_test.cc
+add_executable(init_test
+  test/core/surface/init_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(lb_get_cpu_stats_test
+target_include_directories(init_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -13007,10 +12169,9 @@ target_include_directories(lb_get_cpu_stats_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(lb_get_cpu_stats_test
+target_link_libraries(init_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc++
   grpc_test_util
 )
 
@@ -13018,14 +12179,15 @@ target_link_libraries(lb_get_cpu_stats_test
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(lb_load_data_store_test
-  src/cpp/server/load_reporter/load_data_store.cc
-  test/cpp/server/load_reporter/load_data_store_test.cc
+add_executable(initial_settings_frame_bad_client_test
+  test/core/bad_client/bad_client.cc
+  test/core/bad_client/tests/initial_settings_frame.cc
+  test/core/end2end/cq_verifier.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(lb_load_data_store_test
+target_include_directories(initial_settings_frame_bad_client_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -13044,10 +12206,9 @@ target_include_directories(lb_load_data_store_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(lb_load_data_store_test
+target_link_libraries(initial_settings_frame_bad_client_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc++
   grpc_test_util
 )
 
@@ -13055,13 +12216,13 @@ target_link_libraries(lb_load_data_store_test
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(linux_system_roots_test
-  test/core/security/linux_system_roots_test.cc
+add_executable(insecure_security_connector_test
+  test/core/security/insecure_security_connector_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(linux_system_roots_test
+target_include_directories(insecure_security_connector_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -13080,7 +12241,7 @@ target_include_directories(linux_system_roots_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(linux_system_roots_test
+target_link_libraries(insecure_security_connector_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
@@ -13090,13 +12251,28 @@ target_link_libraries(linux_system_roots_test
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(log_test
-  test/core/gpr/log_test.cc
+add_executable(interop_client
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.grpc.pb.h
+  test/core/security/oauth2_utils.cc
+  test/cpp/interop/client.cc
+  test/cpp/interop/client_helper.cc
+  test/cpp/interop/interop_client.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(log_test
+target_include_directories(interop_client
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -13115,23 +12291,38 @@ target_include_directories(log_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(log_test
+target_link_libraries(interop_client
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc_test_util
+  grpc++_test_config
+  grpc++_test_util
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(loop_test
-  test/core/promise/loop_test.cc
+add_executable(interop_server
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.grpc.pb.h
+  test/cpp/interop/interop_server.cc
+  test/cpp/interop/interop_server_bootstrap.cc
+  test/cpp/interop/server_helper.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(loop_test
+target_include_directories(interop_server
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -13150,23 +12341,62 @@ target_include_directories(loop_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(loop_test
+target_link_libraries(interop_server
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  absl::variant
+  grpc++_test_config
+  grpc++_test_util
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 
-add_executable(match_test
-  test/core/gprpp/match_test.cc
+  add_executable(interop_test
+    test/cpp/interop/interop_test.cc
+    third_party/googletest/googletest/src/gtest-all.cc
+    third_party/googletest/googlemock/src/gmock-all.cc
+  )
+
+  target_include_directories(interop_test
+    PRIVATE
+      ${CMAKE_CURRENT_SOURCE_DIR}
+      ${CMAKE_CURRENT_SOURCE_DIR}/include
+      ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
+      ${_gRPC_RE2_INCLUDE_DIR}
+      ${_gRPC_SSL_INCLUDE_DIR}
+      ${_gRPC_UPB_GENERATED_DIR}
+      ${_gRPC_UPB_GRPC_GENERATED_DIR}
+      ${_gRPC_UPB_INCLUDE_DIR}
+      ${_gRPC_XXHASH_INCLUDE_DIR}
+      ${_gRPC_ZLIB_INCLUDE_DIR}
+      third_party/googletest/googletest/include
+      third_party/googletest/googletest
+      third_party/googletest/googlemock/include
+      third_party/googletest/googlemock
+      ${_gRPC_PROTO_GENS_DIR}
+  )
+
+  target_link_libraries(interop_test
+    ${_gRPC_PROTOBUF_LIBRARIES}
+    ${_gRPC_ALLTARGETS_LIBRARIES}
+    grpc++_test_config
+    grpc++_test_util
+  )
+
+
+endif()
+endif()
+if(gRPC_BUILD_TESTS)
+
+add_executable(join_test
+  test/core/promise/join_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(match_test
+target_include_directories(join_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -13185,7 +12415,7 @@ target_include_directories(match_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(match_test
+target_link_libraries(join_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
   absl::variant
@@ -13195,13 +12425,13 @@ target_link_libraries(match_test
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(matchers_test
-  test/core/security/matchers_test.cc
+add_executable(json_test
+  test/core/json/json_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(matchers_test
+target_include_directories(json_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -13220,36 +12450,25 @@ target_include_directories(matchers_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(matchers_test
-  ${_gRPC_PROTOBUF_LIBRARIES}
-  ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc_test_util
-)
-
-
-endif()
-if(gRPC_BUILD_TESTS)
-
-add_executable(message_allocator_end2end_test
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
-  test/cpp/end2end/message_allocator_end2end_test.cc
-  test/cpp/end2end/test_service_impl.cc
+target_link_libraries(json_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  grpc_test_util
+)
+
+
+endif()
+if(gRPC_BUILD_TESTS)
+
+add_executable(large_metadata_bad_client_test
+  test/core/bad_client/bad_client.cc
+  test/core/bad_client/tests/large_metadata.cc
+  test/core/end2end/cq_verifier.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(message_allocator_end2end_test
+target_include_directories(large_metadata_bad_client_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -13268,23 +12487,80 @@ target_include_directories(message_allocator_end2end_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(message_allocator_end2end_test
+target_link_libraries(large_metadata_bad_client_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc++_test_util
+  grpc_test_util
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(miscompile_with_no_unique_address_test
-  test/core/compiler_bugs/miscompile_with_no_unique_address_test.cc
+add_executable(latch_test
+  src/core/ext/upb-generated/google/api/annotations.upb.c
+  src/core/ext/upb-generated/google/api/expr/v1alpha1/checked.upb.c
+  src/core/ext/upb-generated/google/api/expr/v1alpha1/syntax.upb.c
+  src/core/ext/upb-generated/google/api/http.upb.c
+  src/core/ext/upb-generated/google/protobuf/any.upb.c
+  src/core/ext/upb-generated/google/protobuf/duration.upb.c
+  src/core/ext/upb-generated/google/protobuf/empty.upb.c
+  src/core/ext/upb-generated/google/protobuf/struct.upb.c
+  src/core/ext/upb-generated/google/protobuf/timestamp.upb.c
+  src/core/ext/upb-generated/google/protobuf/wrappers.upb.c
+  src/core/ext/upb-generated/google/rpc/status.upb.c
+  src/core/lib/gpr/alloc.cc
+  src/core/lib/gpr/atm.cc
+  src/core/lib/gpr/cpu_iphone.cc
+  src/core/lib/gpr/cpu_linux.cc
+  src/core/lib/gpr/cpu_posix.cc
+  src/core/lib/gpr/cpu_windows.cc
+  src/core/lib/gpr/env_linux.cc
+  src/core/lib/gpr/env_posix.cc
+  src/core/lib/gpr/env_windows.cc
+  src/core/lib/gpr/log.cc
+  src/core/lib/gpr/log_android.cc
+  src/core/lib/gpr/log_linux.cc
+  src/core/lib/gpr/log_posix.cc
+  src/core/lib/gpr/log_windows.cc
+  src/core/lib/gpr/murmur_hash.cc
+  src/core/lib/gpr/string.cc
+  src/core/lib/gpr/string_posix.cc
+  src/core/lib/gpr/string_util_windows.cc
+  src/core/lib/gpr/string_windows.cc
+  src/core/lib/gpr/sync.cc
+  src/core/lib/gpr/sync_abseil.cc
+  src/core/lib/gpr/sync_posix.cc
+  src/core/lib/gpr/sync_windows.cc
+  src/core/lib/gpr/time.cc
+  src/core/lib/gpr/time_posix.cc
+  src/core/lib/gpr/time_precise.cc
+  src/core/lib/gpr/time_windows.cc
+  src/core/lib/gpr/tmpfile_msys.cc
+  src/core/lib/gpr/tmpfile_posix.cc
+  src/core/lib/gpr/tmpfile_windows.cc
+  src/core/lib/gpr/wrap_memcpy.cc
+  src/core/lib/gprpp/arena.cc
+  src/core/lib/gprpp/examine_stack.cc
+  src/core/lib/gprpp/fork.cc
+  src/core/lib/gprpp/global_config_env.cc
+  src/core/lib/gprpp/host_port.cc
+  src/core/lib/gprpp/mpscq.cc
+  src/core/lib/gprpp/stat_posix.cc
+  src/core/lib/gprpp/stat_windows.cc
+  src/core/lib/gprpp/status_helper.cc
+  src/core/lib/gprpp/thd_posix.cc
+  src/core/lib/gprpp/thd_windows.cc
+  src/core/lib/gprpp/time_util.cc
+  src/core/lib/profiling/basic_timers.cc
+  src/core/lib/profiling/stap_timers.cc
+  src/core/lib/promise/activity.cc
+  test/core/promise/latch_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(miscompile_with_no_unique_address_test
+target_include_directories(latch_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -13303,34 +12579,39 @@ target_include_directories(miscompile_with_no_unique_address_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(miscompile_with_no_unique_address_test
+target_link_libraries(latch_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
+  absl::base
+  absl::core_headers
+  absl::memory
+  absl::status
+  absl::statusor
+  absl::cord
+  absl::str_format
+  absl::strings
+  absl::synchronization
+  absl::time
+  absl::optional
+  absl::variant
+  upb
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(mock_stream_test
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
-  test/cpp/test/mock_stream_test.cc
+add_executable(lb_get_cpu_stats_test
+  src/cpp/server/load_reporter/get_cpu_stats_linux.cc
+  src/cpp/server/load_reporter/get_cpu_stats_macos.cc
+  src/cpp/server/load_reporter/get_cpu_stats_unsupported.cc
+  src/cpp/server/load_reporter/get_cpu_stats_windows.cc
+  test/cpp/server/load_reporter/get_cpu_stats_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(mock_stream_test
+target_include_directories(lb_get_cpu_stats_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -13349,40 +12630,25 @@ target_include_directories(mock_stream_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(mock_stream_test
+target_link_libraries(lb_get_cpu_stats_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc++_test
-  grpc++_test_util
+  grpc++
+  grpc_test_util
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(mock_test
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
-  test/cpp/end2end/mock_test.cc
+add_executable(lb_load_data_store_test
+  src/cpp/server/load_reporter/load_data_store.cc
+  test/cpp/server/load_reporter/load_data_store_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(mock_test
+target_include_directories(lb_load_data_store_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -13401,36 +12667,24 @@ target_include_directories(mock_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(mock_test
+target_link_libraries(lb_load_data_store_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc++_test
-  grpc++_test_util
+  grpc++
+  grpc_test_util
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(nonblocking_test
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
-  test/cpp/end2end/nonblocking_test.cc
+add_executable(linux_system_roots_test
+  test/core/security/linux_system_roots_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(nonblocking_test
+target_include_directories(linux_system_roots_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -13449,23 +12703,23 @@ target_include_directories(nonblocking_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(nonblocking_test
+target_link_libraries(linux_system_roots_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc++_test_util
+  grpc_test_util
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(noop-benchmark
-  test/cpp/microbenchmarks/noop-benchmark.cc
+add_executable(log_test
+  test/core/gpr/log_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(noop-benchmark
+target_include_directories(log_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -13484,10 +12738,9 @@ target_include_directories(noop-benchmark
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(noop-benchmark
+target_link_libraries(log_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  ${_gRPC_BENCHMARK_LIBRARIES}
   grpc_test_util
 )
 
@@ -13495,70 +12748,48 @@ target_link_libraries(noop-benchmark
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(observable_test
-  src/core/ext/upb-generated/google/api/annotations.upb.c
-  src/core/ext/upb-generated/google/api/expr/v1alpha1/checked.upb.c
-  src/core/ext/upb-generated/google/api/expr/v1alpha1/syntax.upb.c
-  src/core/ext/upb-generated/google/api/http.upb.c
-  src/core/ext/upb-generated/google/protobuf/any.upb.c
-  src/core/ext/upb-generated/google/protobuf/duration.upb.c
-  src/core/ext/upb-generated/google/protobuf/empty.upb.c
-  src/core/ext/upb-generated/google/protobuf/struct.upb.c
-  src/core/ext/upb-generated/google/protobuf/timestamp.upb.c
-  src/core/ext/upb-generated/google/protobuf/wrappers.upb.c
-  src/core/ext/upb-generated/google/rpc/status.upb.c
-  src/core/lib/gpr/alloc.cc
-  src/core/lib/gpr/atm.cc
-  src/core/lib/gpr/cpu_iphone.cc
-  src/core/lib/gpr/cpu_linux.cc
-  src/core/lib/gpr/cpu_posix.cc
-  src/core/lib/gpr/cpu_windows.cc
-  src/core/lib/gpr/env_linux.cc
-  src/core/lib/gpr/env_posix.cc
-  src/core/lib/gpr/env_windows.cc
-  src/core/lib/gpr/log.cc
-  src/core/lib/gpr/log_android.cc
-  src/core/lib/gpr/log_linux.cc
-  src/core/lib/gpr/log_posix.cc
-  src/core/lib/gpr/log_windows.cc
-  src/core/lib/gpr/murmur_hash.cc
-  src/core/lib/gpr/string.cc
-  src/core/lib/gpr/string_posix.cc
-  src/core/lib/gpr/string_util_windows.cc
-  src/core/lib/gpr/string_windows.cc
-  src/core/lib/gpr/sync.cc
-  src/core/lib/gpr/sync_abseil.cc
-  src/core/lib/gpr/sync_posix.cc
-  src/core/lib/gpr/sync_windows.cc
-  src/core/lib/gpr/time.cc
-  src/core/lib/gpr/time_posix.cc
-  src/core/lib/gpr/time_precise.cc
-  src/core/lib/gpr/time_windows.cc
-  src/core/lib/gpr/tmpfile_msys.cc
-  src/core/lib/gpr/tmpfile_posix.cc
-  src/core/lib/gpr/tmpfile_windows.cc
-  src/core/lib/gpr/wrap_memcpy.cc
-  src/core/lib/gprpp/arena.cc
-  src/core/lib/gprpp/examine_stack.cc
-  src/core/lib/gprpp/fork.cc
-  src/core/lib/gprpp/global_config_env.cc
-  src/core/lib/gprpp/host_port.cc
-  src/core/lib/gprpp/mpscq.cc
-  src/core/lib/gprpp/stat_posix.cc
-  src/core/lib/gprpp/stat_windows.cc
-  src/core/lib/gprpp/status_helper.cc
-  src/core/lib/gprpp/thd_posix.cc
-  src/core/lib/gprpp/thd_windows.cc
-  src/core/lib/gprpp/time_util.cc
-  src/core/lib/profiling/basic_timers.cc
-  src/core/lib/profiling/stap_timers.cc
-  src/core/lib/promise/activity.cc
-  test/core/promise/observable_test.cc
+add_executable(loop_test
+  test/core/promise/loop_test.cc
+  third_party/googletest/googletest/src/gtest-all.cc
+  third_party/googletest/googlemock/src/gmock-all.cc
+)
+
+target_include_directories(loop_test
+  PRIVATE
+    ${CMAKE_CURRENT_SOURCE_DIR}
+    ${CMAKE_CURRENT_SOURCE_DIR}/include
+    ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
+    ${_gRPC_RE2_INCLUDE_DIR}
+    ${_gRPC_SSL_INCLUDE_DIR}
+    ${_gRPC_UPB_GENERATED_DIR}
+    ${_gRPC_UPB_GRPC_GENERATED_DIR}
+    ${_gRPC_UPB_INCLUDE_DIR}
+    ${_gRPC_XXHASH_INCLUDE_DIR}
+    ${_gRPC_ZLIB_INCLUDE_DIR}
+    third_party/googletest/googletest/include
+    third_party/googletest/googletest
+    third_party/googletest/googlemock/include
+    third_party/googletest/googlemock
+    ${_gRPC_PROTO_GENS_DIR}
+)
+
+target_link_libraries(loop_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  absl::variant
+)
+
+
+endif()
+if(gRPC_BUILD_TESTS)
+
+add_executable(match_test
+  test/core/gprpp/match_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(observable_test
+target_include_directories(match_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -13577,36 +12808,23 @@ target_include_directories(observable_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(observable_test
+target_link_libraries(match_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  absl::base
-  absl::core_headers
-  absl::flat_hash_set
-  absl::memory
-  absl::status
-  absl::statusor
-  absl::cord
-  absl::str_format
-  absl::strings
-  absl::synchronization
-  absl::time
-  absl::optional
   absl::variant
-  upb
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(orphanable_test
-  test/core/gprpp/orphanable_test.cc
+add_executable(matchers_test
+  test/core/security/matchers_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(orphanable_test
+target_include_directories(matchers_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -13625,7 +12843,7 @@ target_include_directories(orphanable_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(orphanable_test
+target_link_libraries(matchers_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
@@ -13635,15 +12853,26 @@ target_link_libraries(orphanable_test
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(out_of_bounds_bad_client_test
-  test/core/bad_client/bad_client.cc
-  test/core/bad_client/tests/out_of_bounds.cc
-  test/core/end2end/cq_verifier.cc
+add_executable(memory_quota_test
+  src/core/lib/debug/trace.cc
+  src/core/lib/event_engine/memory_allocator.cc
+  src/core/lib/iomgr/combiner.cc
+  src/core/lib/iomgr/error.cc
+  src/core/lib/iomgr/exec_ctx.cc
+  src/core/lib/iomgr/executor.cc
+  src/core/lib/iomgr/iomgr_internal.cc
+  src/core/lib/promise/activity.cc
+  src/core/lib/resource_quota/memory_quota.cc
+  src/core/lib/slice/slice.cc
+  src/core/lib/slice/slice_refcount.cc
+  src/core/lib/slice/slice_string_helpers.cc
+  src/core/lib/slice/static_slice.cc
+  test/core/resource_quota/memory_quota_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(out_of_bounds_bad_client_test
+target_include_directories(memory_quota_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -13662,23 +12891,38 @@ target_include_directories(out_of_bounds_bad_client_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(out_of_bounds_bad_client_test
+target_link_libraries(memory_quota_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc_test_util
+  absl::statusor
+  absl::variant
+  gpr
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(overload_test
-  test/core/gprpp/overload_test.cc
+add_executable(message_allocator_end2end_test
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
+  test/cpp/end2end/message_allocator_end2end_test.cc
+  test/cpp/end2end/test_service_impl.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(overload_test
+target_include_directories(message_allocator_end2end_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -13697,22 +12941,23 @@ target_include_directories(overload_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(overload_test
+target_link_libraries(message_allocator_end2end_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
+  grpc++_test_util
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(pid_controller_test
-  test/core/transport/pid_controller_test.cc
+add_executable(metadata_map_test
+  test/core/transport/metadata_map_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(pid_controller_test
+target_include_directories(metadata_map_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -13731,7 +12976,7 @@ target_include_directories(pid_controller_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(pid_controller_test
+target_link_libraries(metadata_map_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
@@ -13741,70 +12986,13 @@ target_link_libraries(pid_controller_test
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(pipe_test
-  src/core/ext/upb-generated/google/api/annotations.upb.c
-  src/core/ext/upb-generated/google/api/expr/v1alpha1/checked.upb.c
-  src/core/ext/upb-generated/google/api/expr/v1alpha1/syntax.upb.c
-  src/core/ext/upb-generated/google/api/http.upb.c
-  src/core/ext/upb-generated/google/protobuf/any.upb.c
-  src/core/ext/upb-generated/google/protobuf/duration.upb.c
-  src/core/ext/upb-generated/google/protobuf/empty.upb.c
-  src/core/ext/upb-generated/google/protobuf/struct.upb.c
-  src/core/ext/upb-generated/google/protobuf/timestamp.upb.c
-  src/core/ext/upb-generated/google/protobuf/wrappers.upb.c
-  src/core/ext/upb-generated/google/rpc/status.upb.c
-  src/core/lib/gpr/alloc.cc
-  src/core/lib/gpr/atm.cc
-  src/core/lib/gpr/cpu_iphone.cc
-  src/core/lib/gpr/cpu_linux.cc
-  src/core/lib/gpr/cpu_posix.cc
-  src/core/lib/gpr/cpu_windows.cc
-  src/core/lib/gpr/env_linux.cc
-  src/core/lib/gpr/env_posix.cc
-  src/core/lib/gpr/env_windows.cc
-  src/core/lib/gpr/log.cc
-  src/core/lib/gpr/log_android.cc
-  src/core/lib/gpr/log_linux.cc
-  src/core/lib/gpr/log_posix.cc
-  src/core/lib/gpr/log_windows.cc
-  src/core/lib/gpr/murmur_hash.cc
-  src/core/lib/gpr/string.cc
-  src/core/lib/gpr/string_posix.cc
-  src/core/lib/gpr/string_util_windows.cc
-  src/core/lib/gpr/string_windows.cc
-  src/core/lib/gpr/sync.cc
-  src/core/lib/gpr/sync_abseil.cc
-  src/core/lib/gpr/sync_posix.cc
-  src/core/lib/gpr/sync_windows.cc
-  src/core/lib/gpr/time.cc
-  src/core/lib/gpr/time_posix.cc
-  src/core/lib/gpr/time_precise.cc
-  src/core/lib/gpr/time_windows.cc
-  src/core/lib/gpr/tmpfile_msys.cc
-  src/core/lib/gpr/tmpfile_posix.cc
-  src/core/lib/gpr/tmpfile_windows.cc
-  src/core/lib/gpr/wrap_memcpy.cc
-  src/core/lib/gprpp/arena.cc
-  src/core/lib/gprpp/examine_stack.cc
-  src/core/lib/gprpp/fork.cc
-  src/core/lib/gprpp/global_config_env.cc
-  src/core/lib/gprpp/host_port.cc
-  src/core/lib/gprpp/mpscq.cc
-  src/core/lib/gprpp/stat_posix.cc
-  src/core/lib/gprpp/stat_windows.cc
-  src/core/lib/gprpp/status_helper.cc
-  src/core/lib/gprpp/thd_posix.cc
-  src/core/lib/gprpp/thd_windows.cc
-  src/core/lib/gprpp/time_util.cc
-  src/core/lib/profiling/basic_timers.cc
-  src/core/lib/profiling/stap_timers.cc
-  src/core/lib/promise/activity.cc
-  test/core/promise/pipe_test.cc
+add_executable(miscompile_with_no_unique_address_test
+  test/core/compiler_bugs/miscompile_with_no_unique_address_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(pipe_test
+target_include_directories(miscompile_with_no_unique_address_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -13823,35 +13011,34 @@ target_include_directories(pipe_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(pipe_test
+target_link_libraries(miscompile_with_no_unique_address_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  absl::base
-  absl::core_headers
-  absl::memory
-  absl::status
-  absl::statusor
-  absl::cord
-  absl::str_format
-  absl::strings
-  absl::synchronization
-  absl::time
-  absl::optional
-  absl::variant
-  upb
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(poll_test
-  test/core/promise/poll_test.cc
+add_executable(mock_stream_test
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
+  test/cpp/test/mock_stream_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(poll_test
+target_include_directories(mock_stream_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -13870,23 +13057,40 @@ target_include_directories(poll_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(poll_test
+target_link_libraries(mock_stream_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  absl::variant
+  grpc++_test
+  grpc++_test_util
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(popularity_count_test
-  test/core/transport/chttp2/popularity_count_test.cc
+add_executable(mock_test
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
+  test/cpp/end2end/mock_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(popularity_count_test
+target_include_directories(mock_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -13905,16 +13109,18 @@ target_include_directories(popularity_count_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(popularity_count_test
+target_link_libraries(mock_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
+  grpc++_test
+  grpc++_test_util
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(port_sharing_end2end_test
+add_executable(nonblocking_test
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h
@@ -13927,13 +13133,104 @@ add_executable(port_sharing_end2end_test
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
-  test/cpp/end2end/port_sharing_end2end_test.cc
-  test/cpp/end2end/test_service_impl.cc
+  test/cpp/end2end/nonblocking_test.cc
+  third_party/googletest/googletest/src/gtest-all.cc
+  third_party/googletest/googlemock/src/gmock-all.cc
+)
+
+target_include_directories(nonblocking_test
+  PRIVATE
+    ${CMAKE_CURRENT_SOURCE_DIR}
+    ${CMAKE_CURRENT_SOURCE_DIR}/include
+    ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
+    ${_gRPC_RE2_INCLUDE_DIR}
+    ${_gRPC_SSL_INCLUDE_DIR}
+    ${_gRPC_UPB_GENERATED_DIR}
+    ${_gRPC_UPB_GRPC_GENERATED_DIR}
+    ${_gRPC_UPB_INCLUDE_DIR}
+    ${_gRPC_XXHASH_INCLUDE_DIR}
+    ${_gRPC_ZLIB_INCLUDE_DIR}
+    third_party/googletest/googletest/include
+    third_party/googletest/googletest
+    third_party/googletest/googlemock/include
+    third_party/googletest/googlemock
+    ${_gRPC_PROTO_GENS_DIR}
+)
+
+target_link_libraries(nonblocking_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  grpc++_test_util
+)
+
+
+endif()
+if(gRPC_BUILD_TESTS)
+
+add_executable(observable_test
+  src/core/ext/upb-generated/google/api/annotations.upb.c
+  src/core/ext/upb-generated/google/api/expr/v1alpha1/checked.upb.c
+  src/core/ext/upb-generated/google/api/expr/v1alpha1/syntax.upb.c
+  src/core/ext/upb-generated/google/api/http.upb.c
+  src/core/ext/upb-generated/google/protobuf/any.upb.c
+  src/core/ext/upb-generated/google/protobuf/duration.upb.c
+  src/core/ext/upb-generated/google/protobuf/empty.upb.c
+  src/core/ext/upb-generated/google/protobuf/struct.upb.c
+  src/core/ext/upb-generated/google/protobuf/timestamp.upb.c
+  src/core/ext/upb-generated/google/protobuf/wrappers.upb.c
+  src/core/ext/upb-generated/google/rpc/status.upb.c
+  src/core/lib/gpr/alloc.cc
+  src/core/lib/gpr/atm.cc
+  src/core/lib/gpr/cpu_iphone.cc
+  src/core/lib/gpr/cpu_linux.cc
+  src/core/lib/gpr/cpu_posix.cc
+  src/core/lib/gpr/cpu_windows.cc
+  src/core/lib/gpr/env_linux.cc
+  src/core/lib/gpr/env_posix.cc
+  src/core/lib/gpr/env_windows.cc
+  src/core/lib/gpr/log.cc
+  src/core/lib/gpr/log_android.cc
+  src/core/lib/gpr/log_linux.cc
+  src/core/lib/gpr/log_posix.cc
+  src/core/lib/gpr/log_windows.cc
+  src/core/lib/gpr/murmur_hash.cc
+  src/core/lib/gpr/string.cc
+  src/core/lib/gpr/string_posix.cc
+  src/core/lib/gpr/string_util_windows.cc
+  src/core/lib/gpr/string_windows.cc
+  src/core/lib/gpr/sync.cc
+  src/core/lib/gpr/sync_abseil.cc
+  src/core/lib/gpr/sync_posix.cc
+  src/core/lib/gpr/sync_windows.cc
+  src/core/lib/gpr/time.cc
+  src/core/lib/gpr/time_posix.cc
+  src/core/lib/gpr/time_precise.cc
+  src/core/lib/gpr/time_windows.cc
+  src/core/lib/gpr/tmpfile_msys.cc
+  src/core/lib/gpr/tmpfile_posix.cc
+  src/core/lib/gpr/tmpfile_windows.cc
+  src/core/lib/gpr/wrap_memcpy.cc
+  src/core/lib/gprpp/arena.cc
+  src/core/lib/gprpp/examine_stack.cc
+  src/core/lib/gprpp/fork.cc
+  src/core/lib/gprpp/global_config_env.cc
+  src/core/lib/gprpp/host_port.cc
+  src/core/lib/gprpp/mpscq.cc
+  src/core/lib/gprpp/stat_posix.cc
+  src/core/lib/gprpp/stat_windows.cc
+  src/core/lib/gprpp/status_helper.cc
+  src/core/lib/gprpp/thd_posix.cc
+  src/core/lib/gprpp/thd_windows.cc
+  src/core/lib/gprpp/time_util.cc
+  src/core/lib/profiling/basic_timers.cc
+  src/core/lib/profiling/stap_timers.cc
+  src/core/lib/promise/activity.cc
+  test/core/promise/observable_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(port_sharing_end2end_test
+target_include_directories(observable_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -13952,23 +13249,36 @@ target_include_directories(port_sharing_end2end_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(port_sharing_end2end_test
+target_link_libraries(observable_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc++_test_util
+  absl::base
+  absl::core_headers
+  absl::flat_hash_set
+  absl::memory
+  absl::status
+  absl::statusor
+  absl::cord
+  absl::str_format
+  absl::strings
+  absl::synchronization
+  absl::time
+  absl::optional
+  absl::variant
+  upb
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(promise_factory_test
-  test/core/promise/promise_factory_test.cc
+add_executable(orphanable_test
+  test/core/gprpp/orphanable_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(promise_factory_test
+target_include_directories(orphanable_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -13987,26 +13297,25 @@ target_include_directories(promise_factory_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(promise_factory_test
+target_link_libraries(orphanable_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  absl::bind_front
-  absl::optional
-  absl::variant
-  absl::utility
+  grpc_test_util
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(promise_map_test
-  test/core/promise/map_test.cc
+add_executable(out_of_bounds_bad_client_test
+  test/core/bad_client/bad_client.cc
+  test/core/bad_client/tests/out_of_bounds.cc
+  test/core/end2end/cq_verifier.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(promise_map_test
+target_include_directories(out_of_bounds_bad_client_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -14025,24 +13334,23 @@ target_include_directories(promise_map_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(promise_map_test
+target_link_libraries(out_of_bounds_bad_client_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  absl::optional
-  absl::variant
+  grpc_test_util
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(promise_test
-  test/core/promise/promise_test.cc
+add_executable(overload_test
+  test/core/gprpp/overload_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(promise_test
+target_include_directories(overload_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -14061,42 +13369,22 @@ target_include_directories(promise_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(promise_test
+target_link_libraries(overload_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  absl::optional
-  absl::variant
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(proto_server_reflection_test
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
-  test/cpp/end2end/proto_server_reflection_test.cc
-  test/cpp/end2end/test_service_impl.cc
-  test/cpp/util/proto_reflection_descriptor_database.cc
+add_executable(parsed_metadata_test
+  test/core/transport/parsed_metadata_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(proto_server_reflection_test
+target_include_directories(parsed_metadata_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -14115,24 +13403,23 @@ target_include_directories(proto_server_reflection_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(proto_server_reflection_test
+target_link_libraries(parsed_metadata_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc++_reflection
-  grpc++_test_util
+  grpc_test_util
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(proto_utils_test
-  test/cpp/codegen/proto_utils_test.cc
+add_executable(pid_controller_test
+  test/core/transport/pid_controller_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(proto_utils_test
+target_include_directories(pid_controller_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -14151,10 +13438,9 @@ target_include_directories(proto_utils_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(proto_utils_test
+target_link_libraries(pid_controller_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc++
   grpc_test_util
 )
 
@@ -14162,59 +13448,70 @@ target_link_libraries(proto_utils_test
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(qps_json_driver
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/core/stats.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/core/stats.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/core/stats.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/core/stats.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/benchmark_service.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/benchmark_service.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/benchmark_service.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/benchmark_service.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/control.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/control.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/control.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/control.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/payloads.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/payloads.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/payloads.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/payloads.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/report_qps_scenario_service.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/report_qps_scenario_service.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/report_qps_scenario_service.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/report_qps_scenario_service.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/stats.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/stats.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/stats.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/stats.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/worker_service.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/worker_service.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/worker_service.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/worker_service.grpc.pb.h
-  src/cpp/util/core_stats.cc
-  test/cpp/qps/benchmark_config.cc
-  test/cpp/qps/client_async.cc
-  test/cpp/qps/client_callback.cc
-  test/cpp/qps/client_sync.cc
-  test/cpp/qps/driver.cc
-  test/cpp/qps/parse_json.cc
-  test/cpp/qps/qps_json_driver.cc
-  test/cpp/qps/qps_server_builder.cc
-  test/cpp/qps/qps_worker.cc
-  test/cpp/qps/report.cc
-  test/cpp/qps/server_async.cc
-  test/cpp/qps/server_callback.cc
-  test/cpp/qps/server_sync.cc
-  test/cpp/qps/usage_timer.cc
+add_executable(pipe_test
+  src/core/ext/upb-generated/google/api/annotations.upb.c
+  src/core/ext/upb-generated/google/api/expr/v1alpha1/checked.upb.c
+  src/core/ext/upb-generated/google/api/expr/v1alpha1/syntax.upb.c
+  src/core/ext/upb-generated/google/api/http.upb.c
+  src/core/ext/upb-generated/google/protobuf/any.upb.c
+  src/core/ext/upb-generated/google/protobuf/duration.upb.c
+  src/core/ext/upb-generated/google/protobuf/empty.upb.c
+  src/core/ext/upb-generated/google/protobuf/struct.upb.c
+  src/core/ext/upb-generated/google/protobuf/timestamp.upb.c
+  src/core/ext/upb-generated/google/protobuf/wrappers.upb.c
+  src/core/ext/upb-generated/google/rpc/status.upb.c
+  src/core/lib/gpr/alloc.cc
+  src/core/lib/gpr/atm.cc
+  src/core/lib/gpr/cpu_iphone.cc
+  src/core/lib/gpr/cpu_linux.cc
+  src/core/lib/gpr/cpu_posix.cc
+  src/core/lib/gpr/cpu_windows.cc
+  src/core/lib/gpr/env_linux.cc
+  src/core/lib/gpr/env_posix.cc
+  src/core/lib/gpr/env_windows.cc
+  src/core/lib/gpr/log.cc
+  src/core/lib/gpr/log_android.cc
+  src/core/lib/gpr/log_linux.cc
+  src/core/lib/gpr/log_posix.cc
+  src/core/lib/gpr/log_windows.cc
+  src/core/lib/gpr/murmur_hash.cc
+  src/core/lib/gpr/string.cc
+  src/core/lib/gpr/string_posix.cc
+  src/core/lib/gpr/string_util_windows.cc
+  src/core/lib/gpr/string_windows.cc
+  src/core/lib/gpr/sync.cc
+  src/core/lib/gpr/sync_abseil.cc
+  src/core/lib/gpr/sync_posix.cc
+  src/core/lib/gpr/sync_windows.cc
+  src/core/lib/gpr/time.cc
+  src/core/lib/gpr/time_posix.cc
+  src/core/lib/gpr/time_precise.cc
+  src/core/lib/gpr/time_windows.cc
+  src/core/lib/gpr/tmpfile_msys.cc
+  src/core/lib/gpr/tmpfile_posix.cc
+  src/core/lib/gpr/tmpfile_windows.cc
+  src/core/lib/gpr/wrap_memcpy.cc
+  src/core/lib/gprpp/arena.cc
+  src/core/lib/gprpp/examine_stack.cc
+  src/core/lib/gprpp/fork.cc
+  src/core/lib/gprpp/global_config_env.cc
+  src/core/lib/gprpp/host_port.cc
+  src/core/lib/gprpp/mpscq.cc
+  src/core/lib/gprpp/stat_posix.cc
+  src/core/lib/gprpp/stat_windows.cc
+  src/core/lib/gprpp/status_helper.cc
+  src/core/lib/gprpp/thd_posix.cc
+  src/core/lib/gprpp/thd_windows.cc
+  src/core/lib/gprpp/time_util.cc
+  src/core/lib/profiling/basic_timers.cc
+  src/core/lib/profiling/stap_timers.cc
+  src/core/lib/promise/activity.cc
+  test/core/promise/pipe_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(qps_json_driver
+target_include_directories(pipe_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -14233,62 +13530,35 @@ target_include_directories(qps_json_driver
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(qps_json_driver
+target_link_libraries(pipe_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc++_test_config
-  grpc++_test_util
+  absl::base
+  absl::core_headers
+  absl::memory
+  absl::status
+  absl::statusor
+  absl::cord
+  absl::str_format
+  absl::strings
+  absl::synchronization
+  absl::time
+  absl::optional
+  absl::variant
+  upb
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(qps_worker
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/core/stats.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/core/stats.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/core/stats.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/core/stats.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/benchmark_service.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/benchmark_service.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/benchmark_service.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/benchmark_service.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/control.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/control.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/control.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/control.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/payloads.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/payloads.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/payloads.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/payloads.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/stats.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/stats.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/stats.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/stats.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/worker_service.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/worker_service.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/worker_service.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/worker_service.grpc.pb.h
-  src/cpp/util/core_stats.cc
-  test/cpp/qps/client_async.cc
-  test/cpp/qps/client_callback.cc
-  test/cpp/qps/client_sync.cc
-  test/cpp/qps/qps_server_builder.cc
-  test/cpp/qps/qps_worker.cc
-  test/cpp/qps/server_async.cc
-  test/cpp/qps/server_callback.cc
-  test/cpp/qps/server_sync.cc
-  test/cpp/qps/usage_timer.cc
-  test/cpp/qps/worker.cc
+add_executable(poll_test
+  test/core/promise/poll_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(qps_worker
+target_include_directories(poll_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -14307,24 +13577,23 @@ target_include_directories(qps_worker
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(qps_worker
+target_link_libraries(poll_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc++_test_config
-  grpc++_test_util
+  absl::variant
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(race_test
-  test/core/promise/race_test.cc
+add_executable(popularity_count_test
+  test/core/transport/chttp2/popularity_count_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(race_test
+target_include_directories(popularity_count_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -14343,21 +13612,16 @@ target_include_directories(race_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(race_test
+target_link_libraries(popularity_count_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  absl::variant
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(raw_end2end_test
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h
+add_executable(port_sharing_end2end_test
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h
@@ -14370,13 +13634,13 @@ add_executable(raw_end2end_test
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
-  test/cpp/end2end/raw_end2end_test.cc
+  test/cpp/end2end/port_sharing_end2end_test.cc
   test/cpp/end2end/test_service_impl.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(raw_end2end_test
+target_include_directories(port_sharing_end2end_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -14395,7 +13659,7 @@ target_include_directories(raw_end2end_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(raw_end2end_test
+target_link_libraries(port_sharing_end2end_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc++_test_util
@@ -14405,53 +13669,13 @@ target_link_libraries(raw_end2end_test
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(rbac_translator_test
-  src/core/lib/security/authorization/grpc_authorization_engine.cc
-  src/core/lib/security/authorization/grpc_authorization_policy_provider.cc
-  src/core/lib/security/authorization/matchers.cc
-  src/core/lib/security/authorization/rbac_policy.cc
-  src/core/lib/security/authorization/rbac_translator.cc
-  test/core/security/rbac_translator_test.cc
-  third_party/googletest/googletest/src/gtest-all.cc
-  third_party/googletest/googlemock/src/gmock-all.cc
-)
-
-target_include_directories(rbac_translator_test
-  PRIVATE
-    ${CMAKE_CURRENT_SOURCE_DIR}
-    ${CMAKE_CURRENT_SOURCE_DIR}/include
-    ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-    ${_gRPC_RE2_INCLUDE_DIR}
-    ${_gRPC_SSL_INCLUDE_DIR}
-    ${_gRPC_UPB_GENERATED_DIR}
-    ${_gRPC_UPB_GRPC_GENERATED_DIR}
-    ${_gRPC_UPB_INCLUDE_DIR}
-    ${_gRPC_XXHASH_INCLUDE_DIR}
-    ${_gRPC_ZLIB_INCLUDE_DIR}
-    third_party/googletest/googletest/include
-    third_party/googletest/googletest
-    third_party/googletest/googlemock/include
-    third_party/googletest/googlemock
-    ${_gRPC_PROTO_GENS_DIR}
-)
-
-target_link_libraries(rbac_translator_test
-  ${_gRPC_PROTOBUF_LIBRARIES}
-  ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc_test_util
-)
-
-
-endif()
-if(gRPC_BUILD_TESTS)
-
-add_executable(ref_counted_ptr_test
-  test/core/gprpp/ref_counted_ptr_test.cc
+add_executable(promise_factory_test
+  test/core/promise/promise_factory_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(ref_counted_ptr_test
+target_include_directories(promise_factory_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -14470,23 +13694,26 @@ target_include_directories(ref_counted_ptr_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(ref_counted_ptr_test
+target_link_libraries(promise_factory_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc_test_util
+  absl::bind_front
+  absl::optional
+  absl::variant
+  absl::utility
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(ref_counted_test
-  test/core/gprpp/ref_counted_test.cc
+add_executable(promise_map_test
+  test/core/promise/map_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(ref_counted_test
+target_include_directories(promise_map_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -14505,60 +13732,24 @@ target_include_directories(ref_counted_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(ref_counted_test
+target_link_libraries(promise_map_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc_test_util
+  absl::optional
+  absl::variant
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
-if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
-
-  add_executable(remove_stream_from_stalled_lists_test
-    test/core/transport/chttp2/remove_stream_from_stalled_lists_test.cc
-    third_party/googletest/googletest/src/gtest-all.cc
-    third_party/googletest/googlemock/src/gmock-all.cc
-  )
-
-  target_include_directories(remove_stream_from_stalled_lists_test
-    PRIVATE
-      ${CMAKE_CURRENT_SOURCE_DIR}
-      ${CMAKE_CURRENT_SOURCE_DIR}/include
-      ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-      ${_gRPC_RE2_INCLUDE_DIR}
-      ${_gRPC_SSL_INCLUDE_DIR}
-      ${_gRPC_UPB_GENERATED_DIR}
-      ${_gRPC_UPB_GRPC_GENERATED_DIR}
-      ${_gRPC_UPB_INCLUDE_DIR}
-      ${_gRPC_XXHASH_INCLUDE_DIR}
-      ${_gRPC_ZLIB_INCLUDE_DIR}
-      third_party/googletest/googletest/include
-      third_party/googletest/googletest
-      third_party/googletest/googlemock/include
-      third_party/googletest/googlemock
-      ${_gRPC_PROTO_GENS_DIR}
-  )
-
-  target_link_libraries(remove_stream_from_stalled_lists_test
-    ${_gRPC_PROTOBUF_LIBRARIES}
-    ${_gRPC_ALLTARGETS_LIBRARIES}
-    grpc_test_util
-  )
-
-
-endif()
-endif()
-if(gRPC_BUILD_TESTS)
 
-add_executable(retry_throttle_test
-  test/core/client_channel/retry_throttle_test.cc
+add_executable(promise_test
+  test/core/promise/promise_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(retry_throttle_test
+target_include_directories(promise_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -14577,17 +13768,22 @@ target_include_directories(retry_throttle_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(retry_throttle_test
+target_link_libraries(promise_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc_test_util
+  absl::optional
+  absl::variant
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(sdk_authz_end2end_test
+add_executable(proto_server_reflection_test
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h
@@ -14600,19 +13796,14 @@ add_executable(sdk_authz_end2end_test
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
-  src/core/lib/security/authorization/grpc_authorization_engine.cc
-  src/core/lib/security/authorization/grpc_authorization_policy_provider.cc
-  src/core/lib/security/authorization/matchers.cc
-  src/core/lib/security/authorization/rbac_policy.cc
-  src/core/lib/security/authorization/rbac_translator.cc
-  src/cpp/server/authorization_policy_provider.cc
-  test/cpp/end2end/sdk_authz_end2end_test.cc
+  test/cpp/end2end/proto_server_reflection_test.cc
   test/cpp/end2end/test_service_impl.cc
+  test/cpp/util/proto_reflection_descriptor_database.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(sdk_authz_end2end_test
+target_include_directories(proto_server_reflection_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -14631,9 +13822,10 @@ target_include_directories(sdk_authz_end2end_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(sdk_authz_end2end_test
+target_link_libraries(proto_server_reflection_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
+  grpc++_reflection
   grpc++_test_util
 )
 
@@ -14641,13 +13833,13 @@ target_link_libraries(sdk_authz_end2end_test
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(secure_auth_context_test
-  test/cpp/common/secure_auth_context_test.cc
+add_executable(proto_utils_test
+  test/cpp/codegen/proto_utils_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(secure_auth_context_test
+target_include_directories(proto_utils_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -14666,23 +13858,70 @@ target_include_directories(secure_auth_context_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(secure_auth_context_test
+target_link_libraries(proto_utils_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc++_test_util
+  grpc++
+  grpc_test_util
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(seq_test
-  test/core/promise/seq_test.cc
+add_executable(qps_json_driver
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/core/stats.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/core/stats.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/core/stats.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/core/stats.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/benchmark_service.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/benchmark_service.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/benchmark_service.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/benchmark_service.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/control.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/control.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/control.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/control.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/payloads.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/payloads.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/payloads.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/payloads.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/report_qps_scenario_service.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/report_qps_scenario_service.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/report_qps_scenario_service.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/report_qps_scenario_service.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/stats.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/stats.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/stats.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/stats.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/worker_service.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/worker_service.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/worker_service.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/worker_service.grpc.pb.h
+  src/cpp/util/core_stats.cc
+  test/cpp/qps/benchmark_config.cc
+  test/cpp/qps/client_async.cc
+  test/cpp/qps/client_callback.cc
+  test/cpp/qps/client_sync.cc
+  test/cpp/qps/driver.cc
+  test/cpp/qps/parse_json.cc
+  test/cpp/qps/qps_json_driver.cc
+  test/cpp/qps/qps_server_builder.cc
+  test/cpp/qps/qps_worker.cc
+  test/cpp/qps/report.cc
+  test/cpp/qps/server_async.cc
+  test/cpp/qps/server_callback.cc
+  test/cpp/qps/server_sync.cc
+  test/cpp/qps/usage_timer.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(seq_test
+target_include_directories(qps_json_driver
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -14701,40 +13940,62 @@ target_include_directories(seq_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(seq_test
+target_link_libraries(qps_json_driver
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  absl::variant
+  grpc++_test_config
+  grpc++_test_util
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(server_builder_plugin_test
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
-  test/cpp/end2end/server_builder_plugin_test.cc
-  test/cpp/end2end/test_service_impl.cc
+add_executable(qps_worker
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/core/stats.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/core/stats.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/core/stats.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/core/stats.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/benchmark_service.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/benchmark_service.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/benchmark_service.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/benchmark_service.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/control.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/control.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/control.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/control.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/payloads.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/payloads.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/payloads.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/payloads.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/stats.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/stats.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/stats.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/stats.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/worker_service.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/worker_service.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/worker_service.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/worker_service.grpc.pb.h
+  src/cpp/util/core_stats.cc
+  test/cpp/qps/client_async.cc
+  test/cpp/qps/client_callback.cc
+  test/cpp/qps/client_sync.cc
+  test/cpp/qps/qps_server_builder.cc
+  test/cpp/qps/qps_worker.cc
+  test/cpp/qps/server_async.cc
+  test/cpp/qps/server_callback.cc
+  test/cpp/qps/server_sync.cc
+  test/cpp/qps/usage_timer.cc
+  test/cpp/qps/worker.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(server_builder_plugin_test
+target_include_directories(qps_worker
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -14753,123 +14014,24 @@ target_include_directories(server_builder_plugin_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(server_builder_plugin_test
+target_link_libraries(qps_worker
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
+  grpc++_test_config
   grpc++_test_util
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
-if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
-
-  add_executable(server_builder_test
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
-    test/cpp/server/server_builder_test.cc
-    third_party/googletest/googletest/src/gtest-all.cc
-    third_party/googletest/googlemock/src/gmock-all.cc
-  )
-
-  target_include_directories(server_builder_test
-    PRIVATE
-      ${CMAKE_CURRENT_SOURCE_DIR}
-      ${CMAKE_CURRENT_SOURCE_DIR}/include
-      ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-      ${_gRPC_RE2_INCLUDE_DIR}
-      ${_gRPC_SSL_INCLUDE_DIR}
-      ${_gRPC_UPB_GENERATED_DIR}
-      ${_gRPC_UPB_GRPC_GENERATED_DIR}
-      ${_gRPC_UPB_INCLUDE_DIR}
-      ${_gRPC_XXHASH_INCLUDE_DIR}
-      ${_gRPC_ZLIB_INCLUDE_DIR}
-      third_party/googletest/googletest/include
-      third_party/googletest/googletest
-      third_party/googletest/googlemock/include
-      third_party/googletest/googlemock
-      ${_gRPC_PROTO_GENS_DIR}
-  )
-
-  target_link_libraries(server_builder_test
-    ${_gRPC_PROTOBUF_LIBRARIES}
-    ${_gRPC_ALLTARGETS_LIBRARIES}
-    grpc++_unsecure
-    grpc_test_util_unsecure
-  )
-
-
-endif()
-endif()
-if(gRPC_BUILD_TESTS)
-if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
-
-  add_executable(server_builder_with_socket_mutator_test
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
-    test/cpp/server/server_builder_with_socket_mutator_test.cc
-    third_party/googletest/googletest/src/gtest-all.cc
-    third_party/googletest/googlemock/src/gmock-all.cc
-  )
-
-  target_include_directories(server_builder_with_socket_mutator_test
-    PRIVATE
-      ${CMAKE_CURRENT_SOURCE_DIR}
-      ${CMAKE_CURRENT_SOURCE_DIR}/include
-      ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-      ${_gRPC_RE2_INCLUDE_DIR}
-      ${_gRPC_SSL_INCLUDE_DIR}
-      ${_gRPC_UPB_GENERATED_DIR}
-      ${_gRPC_UPB_GRPC_GENERATED_DIR}
-      ${_gRPC_UPB_INCLUDE_DIR}
-      ${_gRPC_XXHASH_INCLUDE_DIR}
-      ${_gRPC_ZLIB_INCLUDE_DIR}
-      third_party/googletest/googletest/include
-      third_party/googletest/googletest
-      third_party/googletest/googlemock/include
-      third_party/googletest/googlemock
-      ${_gRPC_PROTO_GENS_DIR}
-  )
-
-  target_link_libraries(server_builder_with_socket_mutator_test
-    ${_gRPC_PROTOBUF_LIBRARIES}
-    ${_gRPC_ALLTARGETS_LIBRARIES}
-    grpc++_unsecure
-    grpc_test_util_unsecure
-  )
-
-
-endif()
-endif()
-if(gRPC_BUILD_TESTS)
 
-add_executable(server_chttp2_test
-  test/core/surface/server_chttp2_test.cc
+add_executable(race_test
+  test/core/promise/race_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(server_chttp2_test
+target_include_directories(race_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -14888,23 +14050,40 @@ target_include_directories(server_chttp2_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(server_chttp2_test
+target_link_libraries(race_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc_test_util
+  absl::variant
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(server_context_test_spouse_test
-  test/cpp/test/server_context_test_spouse_test.cc
+add_executable(raw_end2end_test
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
+  test/cpp/end2end/raw_end2end_test.cc
+  test/cpp/end2end/test_service_impl.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(server_context_test_spouse_test
+target_include_directories(raw_end2end_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -14923,10 +14102,9 @@ target_include_directories(server_context_test_spouse_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(server_context_test_spouse_test
+target_link_libraries(raw_end2end_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc++_test
   grpc++_test_util
 )
 
@@ -14934,25 +14112,18 @@ target_link_libraries(server_context_test_spouse_test
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(server_early_return_test
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
-  test/cpp/end2end/server_early_return_test.cc
+add_executable(rbac_translator_test
+  src/core/lib/security/authorization/grpc_authorization_engine.cc
+  src/core/lib/security/authorization/grpc_authorization_policy_provider.cc
+  src/core/lib/security/authorization/matchers.cc
+  src/core/lib/security/authorization/rbac_policy.cc
+  src/core/lib/security/authorization/rbac_translator.cc
+  test/core/security/rbac_translator_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(server_early_return_test
+target_include_directories(rbac_translator_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -14971,37 +14142,23 @@ target_include_directories(server_early_return_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(server_early_return_test
+target_link_libraries(rbac_translator_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc++_test_util
+  grpc_test_util
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(server_interceptors_end2end_test
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
-  test/cpp/end2end/interceptors_util.cc
-  test/cpp/end2end/server_interceptors_end2end_test.cc
-  test/cpp/end2end/test_service_impl.cc
+add_executable(ref_counted_ptr_test
+  test/core/gprpp/ref_counted_ptr_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(server_interceptors_end2end_test
+target_include_directories(ref_counted_ptr_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -15020,25 +14177,23 @@ target_include_directories(server_interceptors_end2end_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(server_interceptors_end2end_test
+target_link_libraries(ref_counted_ptr_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc++_test_util
+  grpc_test_util
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(server_registered_method_bad_client_test
-  test/core/bad_client/bad_client.cc
-  test/core/bad_client/tests/server_registered_method.cc
-  test/core/end2end/cq_verifier.cc
+add_executable(ref_counted_test
+  test/core/gprpp/ref_counted_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(server_registered_method_bad_client_test
+target_include_directories(ref_counted_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -15057,7 +14212,7 @@ target_include_directories(server_registered_method_bad_client_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(server_registered_method_bad_client_test
+target_link_libraries(ref_counted_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
@@ -15068,25 +14223,13 @@ endif()
 if(gRPC_BUILD_TESTS)
 if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 
-  add_executable(server_request_call_test
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
-    test/cpp/server/server_request_call_test.cc
+  add_executable(remove_stream_from_stalled_lists_test
+    test/core/transport/chttp2/remove_stream_from_stalled_lists_test.cc
     third_party/googletest/googletest/src/gtest-all.cc
     third_party/googletest/googlemock/src/gmock-all.cc
   )
 
-  target_include_directories(server_request_call_test
+  target_include_directories(remove_stream_from_stalled_lists_test
     PRIVATE
       ${CMAKE_CURRENT_SOURCE_DIR}
       ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -15105,11 +14248,10 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
       ${_gRPC_PROTO_GENS_DIR}
   )
 
-  target_link_libraries(server_request_call_test
+  target_link_libraries(remove_stream_from_stalled_lists_test
     ${_gRPC_PROTOBUF_LIBRARIES}
     ${_gRPC_ALLTARGETS_LIBRARIES}
-    grpc++_unsecure
-    grpc_test_util_unsecure
+    grpc_test_util
   )
 
 
@@ -15117,7 +14259,46 @@ endif()
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(service_config_end2end_test
+add_executable(retry_throttle_test
+  test/core/client_channel/retry_throttle_test.cc
+  third_party/googletest/googletest/src/gtest-all.cc
+  third_party/googletest/googlemock/src/gmock-all.cc
+)
+
+target_include_directories(retry_throttle_test
+  PRIVATE
+    ${CMAKE_CURRENT_SOURCE_DIR}
+    ${CMAKE_CURRENT_SOURCE_DIR}/include
+    ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
+    ${_gRPC_RE2_INCLUDE_DIR}
+    ${_gRPC_SSL_INCLUDE_DIR}
+    ${_gRPC_UPB_GENERATED_DIR}
+    ${_gRPC_UPB_GRPC_GENERATED_DIR}
+    ${_gRPC_UPB_INCLUDE_DIR}
+    ${_gRPC_XXHASH_INCLUDE_DIR}
+    ${_gRPC_ZLIB_INCLUDE_DIR}
+    third_party/googletest/googletest/include
+    third_party/googletest/googletest
+    third_party/googletest/googlemock/include
+    third_party/googletest/googlemock
+    ${_gRPC_PROTO_GENS_DIR}
+)
+
+target_link_libraries(retry_throttle_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  grpc_test_util
+)
+
+
+endif()
+if(gRPC_BUILD_TESTS)
+
+add_executable(rls_end2end_test
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/lookup/v1/rls.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/lookup/v1/rls.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/lookup/v1/rls.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/lookup/v1/rls.grpc.pb.h
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.h
@@ -15134,13 +14315,14 @@ add_executable(service_config_end2end_test
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
-  test/cpp/end2end/service_config_end2end_test.cc
+  test/core/util/test_lb_policies.cc
+  test/cpp/end2end/rls_end2end_test.cc
   test/cpp/end2end/test_service_impl.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(service_config_end2end_test
+target_include_directories(rls_end2end_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -15159,9 +14341,10 @@ target_include_directories(service_config_end2end_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(service_config_end2end_test
+target_link_libraries(rls_end2end_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
+  grpc++_test_config
   grpc++_test_util
 )
 
@@ -15169,13 +14352,13 @@ target_link_libraries(service_config_end2end_test
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(service_config_test
-  test/core/client_channel/service_config_test.cc
+add_executable(rls_lb_config_parser_test
+  test/core/client_channel/rls_lb_config_parser_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(service_config_test
+target_include_directories(rls_lb_config_parser_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -15194,7 +14377,7 @@ target_include_directories(service_config_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(service_config_test
+target_link_libraries(rls_lb_config_parser_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
@@ -15204,13 +14387,32 @@ target_link_libraries(service_config_test
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(settings_timeout_test
-  test/core/transport/chttp2/settings_timeout_test.cc
+add_executable(sdk_authz_end2end_test
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
+  src/core/lib/security/authorization/grpc_authorization_engine.cc
+  src/core/lib/security/authorization/grpc_authorization_policy_provider.cc
+  src/core/lib/security/authorization/matchers.cc
+  src/core/lib/security/authorization/rbac_policy.cc
+  src/core/lib/security/authorization/rbac_translator.cc
+  src/cpp/server/authorization_policy_provider.cc
+  test/cpp/end2end/sdk_authz_end2end_test.cc
+  test/cpp/end2end/test_service_impl.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(settings_timeout_test
+target_include_directories(sdk_authz_end2end_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -15229,39 +14431,23 @@ target_include_directories(settings_timeout_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(settings_timeout_test
+target_link_libraries(sdk_authz_end2end_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc_test_util
+  grpc++_test_util
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(shutdown_test
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
-  test/cpp/end2end/shutdown_test.cc
+add_executable(secure_auth_context_test
+  test/cpp/common/secure_auth_context_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(shutdown_test
+target_include_directories(secure_auth_context_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -15280,7 +14466,7 @@ target_include_directories(shutdown_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(shutdown_test
+target_link_libraries(secure_auth_context_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc++_test_util
@@ -15290,15 +14476,13 @@ target_link_libraries(shutdown_test
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(simple_request_bad_client_test
-  test/core/bad_client/bad_client.cc
-  test/core/bad_client/tests/simple_request.cc
-  test/core/end2end/cq_verifier.cc
+add_executable(seq_test
+  test/core/promise/seq_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(simple_request_bad_client_test
+target_include_directories(seq_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -15317,23 +14501,40 @@ target_include_directories(simple_request_bad_client_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(simple_request_bad_client_test
+target_link_libraries(seq_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc_test_util
+  absl::variant
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(sockaddr_utils_test
-  test/core/address_utils/sockaddr_utils_test.cc
+add_executable(server_builder_plugin_test
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
+  test/cpp/end2end/server_builder_plugin_test.cc
+  test/cpp/end2end/test_service_impl.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(sockaddr_utils_test
+target_include_directories(server_builder_plugin_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -15352,10 +14553,10 @@ target_include_directories(sockaddr_utils_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(sockaddr_utils_test
+target_link_libraries(server_builder_plugin_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc_test_util
+  grpc++_test_util
 )
 
 
@@ -15363,13 +14564,75 @@ endif()
 if(gRPC_BUILD_TESTS)
 if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 
-  add_executable(stack_tracer_test
-    test/core/util/stack_tracer_test.cc
+  add_executable(server_builder_test
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
+    test/cpp/server/server_builder_test.cc
+    third_party/googletest/googletest/src/gtest-all.cc
+    third_party/googletest/googlemock/src/gmock-all.cc
+  )
+
+  target_include_directories(server_builder_test
+    PRIVATE
+      ${CMAKE_CURRENT_SOURCE_DIR}
+      ${CMAKE_CURRENT_SOURCE_DIR}/include
+      ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
+      ${_gRPC_RE2_INCLUDE_DIR}
+      ${_gRPC_SSL_INCLUDE_DIR}
+      ${_gRPC_UPB_GENERATED_DIR}
+      ${_gRPC_UPB_GRPC_GENERATED_DIR}
+      ${_gRPC_UPB_INCLUDE_DIR}
+      ${_gRPC_XXHASH_INCLUDE_DIR}
+      ${_gRPC_ZLIB_INCLUDE_DIR}
+      third_party/googletest/googletest/include
+      third_party/googletest/googletest
+      third_party/googletest/googlemock/include
+      third_party/googletest/googlemock
+      ${_gRPC_PROTO_GENS_DIR}
+  )
+
+  target_link_libraries(server_builder_test
+    ${_gRPC_PROTOBUF_LIBRARIES}
+    ${_gRPC_ALLTARGETS_LIBRARIES}
+    grpc++_unsecure
+    grpc_test_util_unsecure
+  )
+
+
+endif()
+endif()
+if(gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+
+  add_executable(server_builder_with_socket_mutator_test
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
+    test/cpp/server/server_builder_with_socket_mutator_test.cc
     third_party/googletest/googletest/src/gtest-all.cc
     third_party/googletest/googlemock/src/gmock-all.cc
   )
 
-  target_include_directories(stack_tracer_test
+  target_include_directories(server_builder_with_socket_mutator_test
     PRIVATE
       ${CMAKE_CURRENT_SOURCE_DIR}
       ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -15388,10 +14651,11 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
       ${_gRPC_PROTO_GENS_DIR}
   )
 
-  target_link_libraries(stack_tracer_test
+  target_link_libraries(server_builder_with_socket_mutator_test
     ${_gRPC_PROTOBUF_LIBRARIES}
     ${_gRPC_ALLTARGETS_LIBRARIES}
-    grpc_test_util
+    grpc++_unsecure
+    grpc_test_util_unsecure
   )
 
 
@@ -15399,13 +14663,13 @@ endif()
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(stat_test
-  test/core/gprpp/stat_test.cc
+add_executable(server_chttp2_test
+  test/core/surface/server_chttp2_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(stat_test
+target_include_directories(server_chttp2_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -15424,7 +14688,7 @@ target_include_directories(stat_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(stat_test
+target_link_libraries(server_chttp2_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
@@ -15434,13 +14698,14 @@ target_link_libraries(stat_test
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(static_metadata_test
-  test/core/transport/static_metadata_test.cc
+add_executable(server_config_selector_test
+  src/core/ext/filters/server_config_selector/server_config_selector.cc
+  test/core/server_config_selector/server_config_selector_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(static_metadata_test
+target_include_directories(server_config_selector_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -15459,7 +14724,7 @@ target_include_directories(static_metadata_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(static_metadata_test
+target_link_libraries(server_config_selector_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
@@ -15469,13 +14734,13 @@ target_link_libraries(static_metadata_test
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(stats_test
-  test/core/debug/stats_test.cc
+add_executable(server_context_test_spouse_test
+  test/cpp/test/server_context_test_spouse_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(stats_test
+target_include_directories(server_context_test_spouse_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -15494,23 +14759,36 @@ target_include_directories(stats_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(stats_test
+target_link_libraries(server_context_test_spouse_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc_test_util
+  grpc++_test
+  grpc++_test_util
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(status_helper_test
-  test/core/gprpp/status_helper_test.cc
+add_executable(server_early_return_test
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
+  test/cpp/end2end/server_early_return_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(status_helper_test
+target_include_directories(server_early_return_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -15529,23 +14807,37 @@ target_include_directories(status_helper_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(status_helper_test
+target_link_libraries(server_early_return_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc_test_util
+  grpc++_test_util
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(status_metadata_test
-  test/core/transport/status_metadata_test.cc
+add_executable(server_interceptors_end2end_test
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
+  test/cpp/end2end/interceptors_util.cc
+  test/cpp/end2end/server_interceptors_end2end_test.cc
+  test/cpp/end2end/test_service_impl.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(status_metadata_test
+target_include_directories(server_interceptors_end2end_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -15564,23 +14856,25 @@ target_include_directories(status_metadata_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(status_metadata_test
+target_link_libraries(server_interceptors_end2end_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc_test_util
+  grpc++_test_util
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(status_util_test
-  test/core/channel/status_util_test.cc
+add_executable(server_registered_method_bad_client_test
+  test/core/bad_client/bad_client.cc
+  test/core/bad_client/tests/server_registered_method.cc
+  test/core/end2end/cq_verifier.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(status_util_test
+target_include_directories(server_registered_method_bad_client_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -15599,7 +14893,7 @@ target_include_directories(status_util_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(status_util_test
+target_link_libraries(server_registered_method_bad_client_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
@@ -15610,49 +14904,7 @@ endif()
 if(gRPC_BUILD_TESTS)
 if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 
-  add_executable(stranded_event_test
-    test/core/end2end/cq_verifier.cc
-    test/core/iomgr/stranded_event_test.cc
-    third_party/googletest/googletest/src/gtest-all.cc
-    third_party/googletest/googlemock/src/gmock-all.cc
-  )
-
-  target_include_directories(stranded_event_test
-    PRIVATE
-      ${CMAKE_CURRENT_SOURCE_DIR}
-      ${CMAKE_CURRENT_SOURCE_DIR}/include
-      ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-      ${_gRPC_RE2_INCLUDE_DIR}
-      ${_gRPC_SSL_INCLUDE_DIR}
-      ${_gRPC_UPB_GENERATED_DIR}
-      ${_gRPC_UPB_GRPC_GENERATED_DIR}
-      ${_gRPC_UPB_INCLUDE_DIR}
-      ${_gRPC_XXHASH_INCLUDE_DIR}
-      ${_gRPC_ZLIB_INCLUDE_DIR}
-      third_party/googletest/googletest/include
-      third_party/googletest/googletest
-      third_party/googletest/googlemock/include
-      third_party/googletest/googlemock
-      ${_gRPC_PROTO_GENS_DIR}
-  )
-
-  target_link_libraries(stranded_event_test
-    ${_gRPC_PROTOBUF_LIBRARIES}
-    ${_gRPC_ALLTARGETS_LIBRARIES}
-    grpc_test_util
-  )
-
-
-endif()
-endif()
-if(gRPC_BUILD_TESTS)
-if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
-
-  add_executable(streaming_throughput_test
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h
+  add_executable(server_request_call_test
     ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
     ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc
     ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h
@@ -15665,12 +14917,12 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
     ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
     ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
     ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
-    test/cpp/end2end/streaming_throughput_test.cc
+    test/cpp/server/server_request_call_test.cc
     third_party/googletest/googletest/src/gtest-all.cc
     third_party/googletest/googlemock/src/gmock-all.cc
   )
 
-  target_include_directories(streaming_throughput_test
+  target_include_directories(server_request_call_test
     PRIVATE
       ${CMAKE_CURRENT_SOURCE_DIR}
       ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -15689,10 +14941,11 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
       ${_gRPC_PROTO_GENS_DIR}
   )
 
-  target_link_libraries(streaming_throughput_test
+  target_link_libraries(server_request_call_test
     ${_gRPC_PROTOBUF_LIBRARIES}
     ${_gRPC_ALLTARGETS_LIBRARIES}
-    grpc++_test_util
+    grpc++_unsecure
+    grpc_test_util_unsecure
   )
 
 
@@ -15700,13 +14953,30 @@ endif()
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(string_ref_test
-  test/cpp/util/string_ref_test.cc
+add_executable(service_config_end2end_test
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
+  test/cpp/end2end/service_config_end2end_test.cc
+  test/cpp/end2end/test_service_impl.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(string_ref_test
+target_include_directories(service_config_end2end_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -15725,10 +14995,44 @@ target_include_directories(string_ref_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(string_ref_test
+target_link_libraries(service_config_end2end_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  grpc++_test_util
+)
+
+
+endif()
+if(gRPC_BUILD_TESTS)
+
+add_executable(service_config_test
+  test/core/client_channel/service_config_test.cc
+  third_party/googletest/googletest/src/gtest-all.cc
+  third_party/googletest/googlemock/src/gmock-all.cc
+)
+
+target_include_directories(service_config_test
+  PRIVATE
+    ${CMAKE_CURRENT_SOURCE_DIR}
+    ${CMAKE_CURRENT_SOURCE_DIR}/include
+    ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
+    ${_gRPC_RE2_INCLUDE_DIR}
+    ${_gRPC_SSL_INCLUDE_DIR}
+    ${_gRPC_UPB_GENERATED_DIR}
+    ${_gRPC_UPB_GRPC_GENERATED_DIR}
+    ${_gRPC_UPB_INCLUDE_DIR}
+    ${_gRPC_XXHASH_INCLUDE_DIR}
+    ${_gRPC_ZLIB_INCLUDE_DIR}
+    third_party/googletest/googletest/include
+    third_party/googletest/googletest
+    third_party/googletest/googlemock/include
+    third_party/googletest/googlemock
+    ${_gRPC_PROTO_GENS_DIR}
+)
+
+target_link_libraries(service_config_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc++
   grpc_test_util
 )
 
@@ -15736,13 +15040,64 @@ target_link_libraries(string_ref_test
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(table_test
-  test/core/gprpp/table_test.cc
+add_executable(settings_timeout_test
+  test/core/transport/chttp2/settings_timeout_test.cc
+  third_party/googletest/googletest/src/gtest-all.cc
+  third_party/googletest/googlemock/src/gmock-all.cc
+)
+
+target_include_directories(settings_timeout_test
+  PRIVATE
+    ${CMAKE_CURRENT_SOURCE_DIR}
+    ${CMAKE_CURRENT_SOURCE_DIR}/include
+    ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
+    ${_gRPC_RE2_INCLUDE_DIR}
+    ${_gRPC_SSL_INCLUDE_DIR}
+    ${_gRPC_UPB_GENERATED_DIR}
+    ${_gRPC_UPB_GRPC_GENERATED_DIR}
+    ${_gRPC_UPB_INCLUDE_DIR}
+    ${_gRPC_XXHASH_INCLUDE_DIR}
+    ${_gRPC_ZLIB_INCLUDE_DIR}
+    third_party/googletest/googletest/include
+    third_party/googletest/googletest
+    third_party/googletest/googlemock/include
+    third_party/googletest/googlemock
+    ${_gRPC_PROTO_GENS_DIR}
+)
+
+target_link_libraries(settings_timeout_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  grpc_test_util
+)
+
+
+endif()
+if(gRPC_BUILD_TESTS)
+
+add_executable(shutdown_test
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
+  test/cpp/end2end/shutdown_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(table_test
+target_include_directories(shutdown_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -15761,24 +15116,25 @@ target_include_directories(table_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(table_test
+target_link_libraries(shutdown_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  absl::optional
-  absl::utility
+  grpc++_test_util
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(test_cpp_client_credentials_test
-  test/cpp/client/credentials_test.cc
+add_executable(simple_request_bad_client_test
+  test/core/bad_client/bad_client.cc
+  test/core/bad_client/tests/simple_request.cc
+  test/core/end2end/cq_verifier.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(test_cpp_client_credentials_test
+target_include_directories(simple_request_bad_client_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -15797,10 +15153,9 @@ target_include_directories(test_cpp_client_credentials_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(test_cpp_client_credentials_test
+target_link_libraries(simple_request_bad_client_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc++
   grpc_test_util
 )
 
@@ -15808,13 +15163,13 @@ target_link_libraries(test_cpp_client_credentials_test
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(test_cpp_server_credentials_test
-  test/cpp/server/credentials_test.cc
+add_executable(sockaddr_utils_test
+  test/core/address_utils/sockaddr_utils_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(test_cpp_server_credentials_test
+target_include_directories(sockaddr_utils_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -15833,24 +15188,60 @@ target_include_directories(test_cpp_server_credentials_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(test_cpp_server_credentials_test
+target_link_libraries(sockaddr_utils_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc++
   grpc_test_util
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 
-add_executable(test_cpp_util_slice_test
-  test/cpp/util/slice_test.cc
+  add_executable(stack_tracer_test
+    test/core/util/stack_tracer_test.cc
+    third_party/googletest/googletest/src/gtest-all.cc
+    third_party/googletest/googlemock/src/gmock-all.cc
+  )
+
+  target_include_directories(stack_tracer_test
+    PRIVATE
+      ${CMAKE_CURRENT_SOURCE_DIR}
+      ${CMAKE_CURRENT_SOURCE_DIR}/include
+      ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
+      ${_gRPC_RE2_INCLUDE_DIR}
+      ${_gRPC_SSL_INCLUDE_DIR}
+      ${_gRPC_UPB_GENERATED_DIR}
+      ${_gRPC_UPB_GRPC_GENERATED_DIR}
+      ${_gRPC_UPB_INCLUDE_DIR}
+      ${_gRPC_XXHASH_INCLUDE_DIR}
+      ${_gRPC_ZLIB_INCLUDE_DIR}
+      third_party/googletest/googletest/include
+      third_party/googletest/googletest
+      third_party/googletest/googlemock/include
+      third_party/googletest/googlemock
+      ${_gRPC_PROTO_GENS_DIR}
+  )
+
+  target_link_libraries(stack_tracer_test
+    ${_gRPC_PROTOBUF_LIBRARIES}
+    ${_gRPC_ALLTARGETS_LIBRARIES}
+    grpc_test_util
+  )
+
+
+endif()
+endif()
+if(gRPC_BUILD_TESTS)
+
+add_executable(stat_test
+  test/core/gprpp/stat_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(test_cpp_util_slice_test
+target_include_directories(stat_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -15869,23 +15260,23 @@ target_include_directories(test_cpp_util_slice_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(test_cpp_util_slice_test
+target_link_libraries(stat_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc++_test_util
+  grpc_test_util
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(test_cpp_util_time_test
-  test/cpp/util/time_test.cc
+add_executable(static_metadata_test
+  test/core/transport/static_metadata_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(test_cpp_util_time_test
+target_include_directories(static_metadata_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -15904,23 +15295,23 @@ target_include_directories(test_cpp_util_time_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(test_cpp_util_time_test
+target_link_libraries(static_metadata_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc++_test_util
+  grpc_test_util
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(thread_manager_test
-  test/cpp/thread_manager/thread_manager_test.cc
+add_executable(stats_test
+  test/core/debug/stats_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(thread_manager_test
+target_include_directories(stats_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -15939,115 +15330,23 @@ target_include_directories(thread_manager_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(thread_manager_test
+target_link_libraries(stats_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc++_test_config
-  grpc++_test_util
+  grpc_test_util
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
-if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
-
-  add_executable(thread_stress_test
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
-    test/cpp/end2end/thread_stress_test.cc
-    third_party/googletest/googletest/src/gtest-all.cc
-    third_party/googletest/googlemock/src/gmock-all.cc
-  )
-
-  target_include_directories(thread_stress_test
-    PRIVATE
-      ${CMAKE_CURRENT_SOURCE_DIR}
-      ${CMAKE_CURRENT_SOURCE_DIR}/include
-      ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-      ${_gRPC_RE2_INCLUDE_DIR}
-      ${_gRPC_SSL_INCLUDE_DIR}
-      ${_gRPC_UPB_GENERATED_DIR}
-      ${_gRPC_UPB_GRPC_GENERATED_DIR}
-      ${_gRPC_UPB_INCLUDE_DIR}
-      ${_gRPC_XXHASH_INCLUDE_DIR}
-      ${_gRPC_ZLIB_INCLUDE_DIR}
-      third_party/googletest/googletest/include
-      third_party/googletest/googletest
-      third_party/googletest/googlemock/include
-      third_party/googletest/googlemock
-      ${_gRPC_PROTO_GENS_DIR}
-  )
-
-  target_link_libraries(thread_stress_test
-    ${_gRPC_PROTOBUF_LIBRARIES}
-    ${_gRPC_ALLTARGETS_LIBRARIES}
-    grpc++_test_util
-  )
-
-
-endif()
-endif()
-if(gRPC_BUILD_TESTS)
-if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
-
-  add_executable(time_jump_test
-    test/cpp/common/time_jump_test.cc
-    third_party/googletest/googletest/src/gtest-all.cc
-    third_party/googletest/googlemock/src/gmock-all.cc
-  )
-
-  target_include_directories(time_jump_test
-    PRIVATE
-      ${CMAKE_CURRENT_SOURCE_DIR}
-      ${CMAKE_CURRENT_SOURCE_DIR}/include
-      ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-      ${_gRPC_RE2_INCLUDE_DIR}
-      ${_gRPC_SSL_INCLUDE_DIR}
-      ${_gRPC_UPB_GENERATED_DIR}
-      ${_gRPC_UPB_GRPC_GENERATED_DIR}
-      ${_gRPC_UPB_INCLUDE_DIR}
-      ${_gRPC_XXHASH_INCLUDE_DIR}
-      ${_gRPC_ZLIB_INCLUDE_DIR}
-      third_party/googletest/googletest/include
-      third_party/googletest/googletest
-      third_party/googletest/googlemock/include
-      third_party/googletest/googlemock
-      ${_gRPC_PROTO_GENS_DIR}
-  )
-
-  target_link_libraries(time_jump_test
-    ${_gRPC_PROTOBUF_LIBRARIES}
-    ${_gRPC_ALLTARGETS_LIBRARIES}
-    grpc++
-    grpc_test_util
-  )
-
-
-endif()
-endif()
-if(gRPC_BUILD_TESTS)
 
-add_executable(time_util_test
-  test/core/gprpp/time_util_test.cc
+add_executable(status_helper_test
+  test/core/gprpp/status_helper_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(time_util_test
+target_include_directories(status_helper_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -16066,7 +15365,7 @@ target_include_directories(time_util_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(time_util_test
+target_link_libraries(status_helper_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
@@ -16076,13 +15375,13 @@ target_link_libraries(time_util_test
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(timer_test
-  test/cpp/common/timer_test.cc
+add_executable(status_metadata_test
+  test/core/transport/status_metadata_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(timer_test
+target_include_directories(status_metadata_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -16101,10 +15400,9 @@ target_include_directories(timer_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(timer_test
+target_link_libraries(status_metadata_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc++
   grpc_test_util
 )
 
@@ -16112,13 +15410,13 @@ target_link_libraries(timer_test
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(tls_security_connector_test
-  test/core/security/tls_security_connector_test.cc
+add_executable(status_util_test
+  test/core/channel/status_util_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(tls_security_connector_test
+target_include_directories(status_util_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -16137,7 +15435,7 @@ target_include_directories(tls_security_connector_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(tls_security_connector_test
+target_link_libraries(status_util_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
@@ -16146,50 +15444,105 @@ target_link_libraries(tls_security_connector_test
 
 endif()
 if(gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+
+  add_executable(stranded_event_test
+    test/core/end2end/cq_verifier.cc
+    test/core/iomgr/stranded_event_test.cc
+    third_party/googletest/googletest/src/gtest-all.cc
+    third_party/googletest/googlemock/src/gmock-all.cc
+  )
+
+  target_include_directories(stranded_event_test
+    PRIVATE
+      ${CMAKE_CURRENT_SOURCE_DIR}
+      ${CMAKE_CURRENT_SOURCE_DIR}/include
+      ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
+      ${_gRPC_RE2_INCLUDE_DIR}
+      ${_gRPC_SSL_INCLUDE_DIR}
+      ${_gRPC_UPB_GENERATED_DIR}
+      ${_gRPC_UPB_GRPC_GENERATED_DIR}
+      ${_gRPC_UPB_INCLUDE_DIR}
+      ${_gRPC_XXHASH_INCLUDE_DIR}
+      ${_gRPC_ZLIB_INCLUDE_DIR}
+      third_party/googletest/googletest/include
+      third_party/googletest/googletest
+      third_party/googletest/googlemock/include
+      third_party/googletest/googlemock
+      ${_gRPC_PROTO_GENS_DIR}
+  )
+
+  target_link_libraries(stranded_event_test
+    ${_gRPC_PROTOBUF_LIBRARIES}
+    ${_gRPC_ALLTARGETS_LIBRARIES}
+    grpc_test_util
+  )
+
+
+endif()
+endif()
+if(gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 
-add_executable(tls_test
-  test/core/gpr/tls_test.cc
-  third_party/googletest/googletest/src/gtest-all.cc
-  third_party/googletest/googlemock/src/gmock-all.cc
-)
+  add_executable(streaming_throughput_test
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
+    test/cpp/end2end/streaming_throughput_test.cc
+    third_party/googletest/googletest/src/gtest-all.cc
+    third_party/googletest/googlemock/src/gmock-all.cc
+  )
 
-target_include_directories(tls_test
-  PRIVATE
-    ${CMAKE_CURRENT_SOURCE_DIR}
-    ${CMAKE_CURRENT_SOURCE_DIR}/include
-    ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-    ${_gRPC_RE2_INCLUDE_DIR}
-    ${_gRPC_SSL_INCLUDE_DIR}
-    ${_gRPC_UPB_GENERATED_DIR}
-    ${_gRPC_UPB_GRPC_GENERATED_DIR}
-    ${_gRPC_UPB_INCLUDE_DIR}
-    ${_gRPC_XXHASH_INCLUDE_DIR}
-    ${_gRPC_ZLIB_INCLUDE_DIR}
-    third_party/googletest/googletest/include
-    third_party/googletest/googletest
-    third_party/googletest/googlemock/include
-    third_party/googletest/googlemock
-    ${_gRPC_PROTO_GENS_DIR}
-)
+  target_include_directories(streaming_throughput_test
+    PRIVATE
+      ${CMAKE_CURRENT_SOURCE_DIR}
+      ${CMAKE_CURRENT_SOURCE_DIR}/include
+      ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
+      ${_gRPC_RE2_INCLUDE_DIR}
+      ${_gRPC_SSL_INCLUDE_DIR}
+      ${_gRPC_UPB_GENERATED_DIR}
+      ${_gRPC_UPB_GRPC_GENERATED_DIR}
+      ${_gRPC_UPB_INCLUDE_DIR}
+      ${_gRPC_XXHASH_INCLUDE_DIR}
+      ${_gRPC_ZLIB_INCLUDE_DIR}
+      third_party/googletest/googletest/include
+      third_party/googletest/googletest
+      third_party/googletest/googlemock/include
+      third_party/googletest/googlemock
+      ${_gRPC_PROTO_GENS_DIR}
+  )
 
-target_link_libraries(tls_test
-  ${_gRPC_PROTOBUF_LIBRARIES}
-  ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc_test_util
-)
+  target_link_libraries(streaming_throughput_test
+    ${_gRPC_PROTOBUF_LIBRARIES}
+    ${_gRPC_ALLTARGETS_LIBRARIES}
+    grpc++_test_util
+  )
 
 
 endif()
+endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(too_many_pings_test
-  test/core/end2end/cq_verifier.cc
-  test/core/transport/chttp2/too_many_pings_test.cc
+add_executable(string_ref_test
+  test/cpp/util/string_ref_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(too_many_pings_test
+target_include_directories(string_ref_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -16208,26 +15561,24 @@ target_include_directories(too_many_pings_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(too_many_pings_test
+target_link_libraries(string_ref_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc++_test_config
-  grpc++_test_util
+  grpc++
+  grpc_test_util
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(transport_stream_receiver_test
-  src/core/ext/transport/binder/utils/transport_stream_receiver_impl.cc
-  src/core/ext/transport/binder/wire_format/transaction.cc
-  test/core/transport/binder/transport_stream_receiver_test.cc
+add_executable(table_test
+  test/core/gprpp/table_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(transport_stream_receiver_test
+target_include_directories(table_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -16246,23 +15597,39 @@ target_include_directories(transport_stream_receiver_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(transport_stream_receiver_test
+target_link_libraries(table_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc_test_util
+  absl::optional
+  absl::utility
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(try_join_test
-  test/core/promise/try_join_test.cc
+add_executable(test_core_resource_quota_resource_quota_test
+  src/core/lib/debug/trace.cc
+  src/core/lib/event_engine/memory_allocator.cc
+  src/core/lib/iomgr/combiner.cc
+  src/core/lib/iomgr/error.cc
+  src/core/lib/iomgr/exec_ctx.cc
+  src/core/lib/iomgr/executor.cc
+  src/core/lib/iomgr/iomgr_internal.cc
+  src/core/lib/promise/activity.cc
+  src/core/lib/resource_quota/memory_quota.cc
+  src/core/lib/resource_quota/resource_quota.cc
+  src/core/lib/resource_quota/thread_quota.cc
+  src/core/lib/slice/slice.cc
+  src/core/lib/slice/slice_refcount.cc
+  src/core/lib/slice/slice_string_helpers.cc
+  src/core/lib/slice/static_slice.cc
+  test/core/resource_quota/resource_quota_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(try_join_test
+target_include_directories(test_core_resource_quota_resource_quota_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -16281,25 +15648,25 @@ target_include_directories(try_join_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(try_join_test
+target_link_libraries(test_core_resource_quota_resource_quota_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  absl::status
   absl::statusor
   absl::variant
+  gpr
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(try_seq_test
-  test/core/promise/try_seq_test.cc
+add_executable(test_cpp_client_credentials_test
+  test/cpp/client/credentials_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(try_seq_test
+target_include_directories(test_cpp_client_credentials_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -16318,27 +15685,24 @@ target_include_directories(try_seq_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(try_seq_test
+target_link_libraries(test_cpp_client_credentials_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  absl::status
-  absl::statusor
-  absl::variant
+  grpc++
+  grpc_test_util
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(unknown_frame_bad_client_test
-  test/core/bad_client/bad_client.cc
-  test/core/bad_client/tests/unknown_frame.cc
-  test/core/end2end/cq_verifier.cc
+add_executable(test_cpp_server_credentials_test
+  test/cpp/server/credentials_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(unknown_frame_bad_client_test
+target_include_directories(test_cpp_server_credentials_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -16357,9 +15721,10 @@ target_include_directories(unknown_frame_bad_client_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(unknown_frame_bad_client_test
+target_link_libraries(test_cpp_server_credentials_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
+  grpc++
   grpc_test_util
 )
 
@@ -16367,13 +15732,13 @@ target_link_libraries(unknown_frame_bad_client_test
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(uri_parser_test
-  test/core/uri/uri_parser_test.cc
+add_executable(test_cpp_util_slice_test
+  test/cpp/util/slice_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(uri_parser_test
+target_include_directories(test_cpp_util_slice_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -16392,25 +15757,23 @@ target_include_directories(uri_parser_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(uri_parser_test
+target_link_libraries(test_cpp_util_slice_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc_test_util
+  grpc++_test_util
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(window_overflow_bad_client_test
-  test/core/bad_client/bad_client.cc
-  test/core/bad_client/tests/window_overflow.cc
-  test/core/end2end/cq_verifier.cc
+add_executable(test_cpp_util_time_test
+  test/cpp/util/time_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(window_overflow_bad_client_test
+target_include_directories(test_cpp_util_time_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -16429,29 +15792,23 @@ target_include_directories(window_overflow_bad_client_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(window_overflow_bad_client_test
+target_link_libraries(test_cpp_util_time_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc_test_util
+  grpc++_test_util
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(wire_reader_test
-  src/core/ext/transport/binder/utils/transport_stream_receiver_impl.cc
-  src/core/ext/transport/binder/wire_format/binder_constants.cc
-  src/core/ext/transport/binder/wire_format/transaction.cc
-  src/core/ext/transport/binder/wire_format/wire_reader_impl.cc
-  src/core/ext/transport/binder/wire_format/wire_writer.cc
-  test/core/transport/binder/mock_objects.cc
-  test/core/transport/binder/wire_reader_test.cc
+add_executable(thread_manager_test
+  test/cpp/thread_manager/thread_manager_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(wire_reader_test
+target_include_directories(thread_manager_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -16470,29 +15827,26 @@ target_include_directories(wire_reader_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(wire_reader_test
+target_link_libraries(thread_manager_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc_test_util
+  grpc++_test_config
+  grpc++_test_util
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(wire_writer_test
-  src/core/ext/transport/binder/utils/transport_stream_receiver_impl.cc
-  src/core/ext/transport/binder/wire_format/binder_constants.cc
-  src/core/ext/transport/binder/wire_format/transaction.cc
-  src/core/ext/transport/binder/wire_format/wire_reader_impl.cc
-  src/core/ext/transport/binder/wire_format/wire_writer.cc
-  test/core/transport/binder/mock_objects.cc
-  test/core/transport/binder/wire_writer_test.cc
+add_executable(thread_quota_test
+  src/core/lib/debug/trace.cc
+  src/core/lib/resource_quota/thread_quota.cc
+  test/core/resource_quota/thread_quota_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(wire_writer_test
+target_include_directories(thread_quota_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -16511,10 +15865,10 @@ target_include_directories(wire_writer_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(wire_writer_test
+target_link_libraries(thread_quota_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc_test_util
+  gpr
 )
 
 
@@ -16522,13 +15876,29 @@ endif()
 if(gRPC_BUILD_TESTS)
 if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 
-  add_executable(work_serializer_test
-    test/core/iomgr/work_serializer_test.cc
+  add_executable(thread_stress_test
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
+    test/cpp/end2end/thread_stress_test.cc
     third_party/googletest/googletest/src/gtest-all.cc
     third_party/googletest/googlemock/src/gmock-all.cc
   )
 
-  target_include_directories(work_serializer_test
+  target_include_directories(thread_stress_test
     PRIVATE
       ${CMAKE_CURRENT_SOURCE_DIR}
       ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -16547,59 +15917,25 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
       ${_gRPC_PROTO_GENS_DIR}
   )
 
-  target_link_libraries(work_serializer_test
+  target_link_libraries(thread_stress_test
     ${_gRPC_PROTOBUF_LIBRARIES}
     ${_gRPC_ALLTARGETS_LIBRARIES}
-    grpc_test_util
+    grpc++_test_util
   )
 
 
 endif()
 endif()
-if(gRPC_BUILD_TESTS)
-if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
-
-  add_executable(writes_per_rpc_test
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
-    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/memory_counters.cc
-    test/core/util/mock_endpoint.cc
-    test/core/util/parse_hexstring.cc
-    test/core/util/passthru_endpoint.cc
-    test/core/util/port.cc
-    test/core/util/port_isolated_runtime_environment.cc
-    test/core/util/port_server_client.cc
-    test/core/util/reconnect_server.cc
-    test/core/util/resolve_localhost_ip46.cc
-    test/core/util/resource_user_util.cc
-    test/core/util/slice_splitter.cc
-    test/core/util/stack_tracer.cc
-    test/core/util/subprocess_posix.cc
-    test/core/util/subprocess_windows.cc
-    test/core/util/test_config.cc
-    test/core/util/test_tcp_server.cc
-    test/core/util/tracer_util.cc
-    test/core/util/trickle_endpoint.cc
-    test/cpp/performance/writes_per_rpc_test.cc
+if(gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+
+  add_executable(time_jump_test
+    test/cpp/common/time_jump_test.cc
     third_party/googletest/googletest/src/gtest-all.cc
     third_party/googletest/googlemock/src/gmock-all.cc
   )
 
-  target_include_directories(writes_per_rpc_test
+  target_include_directories(time_jump_test
     PRIVATE
       ${CMAKE_CURRENT_SOURCE_DIR}
       ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -16618,13 +15954,11 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
       ${_gRPC_PROTO_GENS_DIR}
   )
 
-  target_link_libraries(writes_per_rpc_test
+  target_link_libraries(time_jump_test
     ${_gRPC_PROTOBUF_LIBRARIES}
     ${_gRPC_ALLTARGETS_LIBRARIES}
-    absl::failure_signal_handler
-    absl::stacktrace
-    absl::symbolize
     grpc++
+    grpc_test_util
   )
 
 
@@ -16632,13 +15966,13 @@ endif()
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(xds_bootstrap_test
-  test/core/xds/xds_bootstrap_test.cc
+add_executable(time_util_test
+  test/core/gprpp/time_util_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(xds_bootstrap_test
+target_include_directories(time_util_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -16657,7 +15991,7 @@ target_include_directories(xds_bootstrap_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(xds_bootstrap_test
+target_link_libraries(time_util_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
@@ -16667,13 +16001,13 @@ target_link_libraries(xds_bootstrap_test
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(xds_certificate_provider_test
-  test/core/xds/xds_certificate_provider_test.cc
+add_executable(timer_test
+  test/cpp/common/timer_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(xds_certificate_provider_test
+target_include_directories(timer_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -16692,9 +16026,10 @@ target_include_directories(xds_certificate_provider_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(xds_certificate_provider_test
+target_link_libraries(timer_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
+  grpc++
   grpc_test_util
 )
 
@@ -16702,61 +16037,13 @@ target_link_libraries(xds_certificate_provider_test
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(xds_credentials_end2end_test
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
-  test/cpp/end2end/test_service_impl.cc
-  test/cpp/end2end/xds_credentials_end2end_test.cc
-  third_party/googletest/googletest/src/gtest-all.cc
-  third_party/googletest/googlemock/src/gmock-all.cc
-)
-
-target_include_directories(xds_credentials_end2end_test
-  PRIVATE
-    ${CMAKE_CURRENT_SOURCE_DIR}
-    ${CMAKE_CURRENT_SOURCE_DIR}/include
-    ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-    ${_gRPC_RE2_INCLUDE_DIR}
-    ${_gRPC_SSL_INCLUDE_DIR}
-    ${_gRPC_UPB_GENERATED_DIR}
-    ${_gRPC_UPB_GRPC_GENERATED_DIR}
-    ${_gRPC_UPB_INCLUDE_DIR}
-    ${_gRPC_XXHASH_INCLUDE_DIR}
-    ${_gRPC_ZLIB_INCLUDE_DIR}
-    third_party/googletest/googletest/include
-    third_party/googletest/googletest
-    third_party/googletest/googlemock/include
-    third_party/googletest/googlemock
-    ${_gRPC_PROTO_GENS_DIR}
-)
-
-target_link_libraries(xds_credentials_end2end_test
-  ${_gRPC_PROTOBUF_LIBRARIES}
-  ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc++_test_util
-)
-
-
-endif()
-if(gRPC_BUILD_TESTS)
-
-add_executable(xds_credentials_test
-  test/core/security/xds_credentials_test.cc
+add_executable(tls_security_connector_test
+  test/core/security/tls_security_connector_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(xds_credentials_test
+target_include_directories(tls_security_connector_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -16775,229 +16062,23 @@ target_include_directories(xds_credentials_test
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(xds_credentials_test
-  ${_gRPC_PROTOBUF_LIBRARIES}
-  ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc_test_util
-)
-
-
-endif()
-if(gRPC_BUILD_TESTS)
-if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
-
-  add_executable(xds_end2end_test
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.grpc.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/cds_for_test.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/cds_for_test.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/cds_for_test.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/cds_for_test.grpc.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.grpc.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lds_rds_for_test.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lds_rds_for_test.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lds_rds_for_test.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lds_rds_for_test.grpc.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.grpc.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/address.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/address.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/address.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/address.grpc.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/ads.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/ads.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/ads.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/ads.grpc.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/aggregate_cluster.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/aggregate_cluster.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/aggregate_cluster.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/aggregate_cluster.grpc.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.grpc.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/cluster.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/cluster.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/cluster.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/cluster.grpc.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.grpc.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_source.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_source.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_source.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_source.grpc.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.grpc.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/discovery.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/discovery.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/discovery.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/discovery.grpc.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/endpoint.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/endpoint.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/endpoint.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/endpoint.grpc.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/extension.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/extension.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/extension.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/extension.grpc.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/fault.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/fault.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/fault.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/fault.grpc.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/fault_common.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/fault_common.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/fault_common.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/fault_common.grpc.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/http_connection_manager.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/http_connection_manager.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/http_connection_manager.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/http_connection_manager.grpc.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/listener.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/listener.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/listener.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/listener.grpc.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/load_report.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/load_report.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/load_report.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/load_report.grpc.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/lrs.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/lrs.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/lrs.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/lrs.grpc.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.grpc.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/protocol.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/protocol.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/protocol.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/protocol.grpc.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/range.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/range.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/range.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/range.grpc.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/regex.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/regex.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/regex.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/regex.grpc.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/route.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/route.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/route.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/route.grpc.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/router.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/router.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/router.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/router.grpc.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/string.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/string.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/string.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/string.grpc.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/tls.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/tls.grpc.pb.cc
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/tls.pb.h
-    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/tls.grpc.pb.h
-    src/cpp/server/csds/csds.cc
-    test/cpp/end2end/test_service_impl.cc
-    test/cpp/end2end/xds_end2end_test.cc
-    third_party/googletest/googletest/src/gtest-all.cc
-    third_party/googletest/googlemock/src/gmock-all.cc
-  )
-
-  target_include_directories(xds_end2end_test
-    PRIVATE
-      ${CMAKE_CURRENT_SOURCE_DIR}
-      ${CMAKE_CURRENT_SOURCE_DIR}/include
-      ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-      ${_gRPC_RE2_INCLUDE_DIR}
-      ${_gRPC_SSL_INCLUDE_DIR}
-      ${_gRPC_UPB_GENERATED_DIR}
-      ${_gRPC_UPB_GRPC_GENERATED_DIR}
-      ${_gRPC_UPB_INCLUDE_DIR}
-      ${_gRPC_XXHASH_INCLUDE_DIR}
-      ${_gRPC_ZLIB_INCLUDE_DIR}
-      third_party/googletest/googletest/include
-      third_party/googletest/googletest
-      third_party/googletest/googlemock/include
-      third_party/googletest/googlemock
-      ${_gRPC_PROTO_GENS_DIR}
-  )
-
-  target_link_libraries(xds_end2end_test
-    ${_gRPC_PROTOBUF_LIBRARIES}
-    ${_gRPC_ALLTARGETS_LIBRARIES}
-    grpc++_test_config
-    grpc++_test_util
-  )
+target_link_libraries(tls_security_connector_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  grpc_test_util
+)
 
 
 endif()
-endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(xds_interop_client
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.grpc.pb.h
-  src/cpp/server/admin/admin_services.cc
-  src/cpp/server/csds/csds.cc
-  test/cpp/interop/xds_interop_client.cc
+add_executable(tls_test
+  test/core/gpr/tls_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(xds_interop_client
+target_include_directories(tls_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -17016,62 +16097,24 @@ target_include_directories(xds_interop_client
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(xds_interop_client
+target_link_libraries(tls_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  absl::flags
-  grpc++_reflection
-  grpcpp_channelz
   grpc_test_util
-  grpc++_test_config
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(xds_interop_server
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/health/v1/health.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/health/v1/health.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/health/v1/health.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/health/v1/health.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.grpc.pb.h
-  src/cpp/server/admin/admin_services.cc
-  src/cpp/server/csds/csds.cc
-  test/cpp/end2end/test_health_check_service_impl.cc
-  test/cpp/interop/xds_interop_server.cc
+add_executable(too_many_pings_test
+  test/core/end2end/cq_verifier.cc
+  test/core/transport/chttp2/too_many_pings_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(xds_interop_server
+target_include_directories(too_many_pings_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -17090,28 +16133,78 @@ target_include_directories(xds_interop_server
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(xds_interop_server
+target_link_libraries(too_many_pings_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  absl::flags
-  grpc++_reflection
-  grpcpp_channelz
-  grpc_test_util
   grpc++_test_config
+  grpc++_test_util
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(alts_credentials_fuzzer_one_entry
-  test/core/security/alts_credentials_fuzzer.cc
-  test/core/util/one_corpus_entry_fuzzer.cc
+add_executable(transport_stream_receiver_test
+  src/core/ext/transport/binder/client/binder_connector.cc
+  src/core/ext/transport/binder/client/channel_create.cc
+  src/core/ext/transport/binder/client/channel_create_impl.cc
+  src/core/ext/transport/binder/client/connection_id_generator.cc
+  src/core/ext/transport/binder/client/endpoint_binder_pool.cc
+  src/core/ext/transport/binder/client/jni_utils.cc
+  src/core/ext/transport/binder/client/security_policy_setting.cc
+  src/core/ext/transport/binder/security_policy/binder_security_policy.cc
+  src/core/ext/transport/binder/server/binder_server.cc
+  src/core/ext/transport/binder/server/binder_server_credentials.cc
+  src/core/ext/transport/binder/transport/binder_transport.cc
+  src/core/ext/transport/binder/utils/transport_stream_receiver_impl.cc
+  src/core/ext/transport/binder/wire_format/binder_android.cc
+  src/core/ext/transport/binder/wire_format/binder_constants.cc
+  src/core/ext/transport/binder/wire_format/transaction.cc
+  src/core/ext/transport/binder/wire_format/wire_reader_impl.cc
+  src/core/ext/transport/binder/wire_format/wire_writer.cc
+  src/cpp/client/channel_cc.cc
+  src/cpp/client/client_callback.cc
+  src/cpp/client/client_context.cc
+  src/cpp/client/client_interceptor.cc
+  src/cpp/client/create_channel.cc
+  src/cpp/client/create_channel_internal.cc
+  src/cpp/client/create_channel_posix.cc
+  src/cpp/client/credentials_cc.cc
+  src/cpp/codegen/codegen_init.cc
+  src/cpp/common/alarm.cc
+  src/cpp/common/channel_arguments.cc
+  src/cpp/common/channel_filter.cc
+  src/cpp/common/completion_queue_cc.cc
+  src/cpp/common/core_codegen.cc
+  src/cpp/common/resource_quota_cc.cc
+  src/cpp/common/rpc_method.cc
+  src/cpp/common/validate_service_config.cc
+  src/cpp/common/version_cc.cc
+  src/cpp/server/async_generic_service.cc
+  src/cpp/server/channel_argument_option.cc
+  src/cpp/server/create_default_thread_pool.cc
+  src/cpp/server/dynamic_thread_pool.cc
+  src/cpp/server/external_connection_acceptor_impl.cc
+  src/cpp/server/health/default_health_check_service.cc
+  src/cpp/server/health/health_check_service.cc
+  src/cpp/server/health/health_check_service_server_builder_option.cc
+  src/cpp/server/server_builder.cc
+  src/cpp/server/server_callback.cc
+  src/cpp/server/server_cc.cc
+  src/cpp/server/server_context.cc
+  src/cpp/server/server_credentials.cc
+  src/cpp/server/server_posix.cc
+  src/cpp/thread_manager/thread_manager.cc
+  src/cpp/util/byte_buffer_cc.cc
+  src/cpp/util/status.cc
+  src/cpp/util/string_ref.cc
+  src/cpp/util/time_cc.cc
+  test/core/transport/binder/transport_stream_receiver_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(alts_credentials_fuzzer_one_entry
+target_include_directories(transport_stream_receiver_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -17130,26 +16223,23 @@ target_include_directories(alts_credentials_fuzzer_one_entry
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(alts_credentials_fuzzer_one_entry
+target_link_libraries(transport_stream_receiver_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  absl::flags
   grpc_test_util
-  grpc++_test_config
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(client_fuzzer_one_entry
-  test/core/end2end/fuzzers/client_fuzzer.cc
-  test/core/util/one_corpus_entry_fuzzer.cc
+add_executable(try_join_test
+  test/core/promise/try_join_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(client_fuzzer_one_entry
+target_include_directories(try_join_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -17168,26 +16258,25 @@ target_include_directories(client_fuzzer_one_entry
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(client_fuzzer_one_entry
+target_link_libraries(try_join_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  absl::flags
-  grpc_test_util
-  grpc++_test_config
+  absl::status
+  absl::statusor
+  absl::variant
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(hpack_parser_fuzzer_test_one_entry
-  test/core/transport/chttp2/hpack_parser_fuzzer_test.cc
-  test/core/util/one_corpus_entry_fuzzer.cc
+add_executable(try_seq_test
+  test/core/promise/try_seq_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(hpack_parser_fuzzer_test_one_entry
+target_include_directories(try_seq_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -17206,26 +16295,62 @@ target_include_directories(hpack_parser_fuzzer_test_one_entry
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(hpack_parser_fuzzer_test_one_entry
+target_link_libraries(try_seq_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  absl::status
+  absl::statusor
+  absl::variant
+)
+
+
+endif()
+if(gRPC_BUILD_TESTS)
+
+add_executable(unknown_frame_bad_client_test
+  test/core/bad_client/bad_client.cc
+  test/core/bad_client/tests/unknown_frame.cc
+  test/core/end2end/cq_verifier.cc
+  third_party/googletest/googletest/src/gtest-all.cc
+  third_party/googletest/googlemock/src/gmock-all.cc
+)
+
+target_include_directories(unknown_frame_bad_client_test
+  PRIVATE
+    ${CMAKE_CURRENT_SOURCE_DIR}
+    ${CMAKE_CURRENT_SOURCE_DIR}/include
+    ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
+    ${_gRPC_RE2_INCLUDE_DIR}
+    ${_gRPC_SSL_INCLUDE_DIR}
+    ${_gRPC_UPB_GENERATED_DIR}
+    ${_gRPC_UPB_GRPC_GENERATED_DIR}
+    ${_gRPC_UPB_INCLUDE_DIR}
+    ${_gRPC_XXHASH_INCLUDE_DIR}
+    ${_gRPC_ZLIB_INCLUDE_DIR}
+    third_party/googletest/googletest/include
+    third_party/googletest/googletest
+    third_party/googletest/googlemock/include
+    third_party/googletest/googlemock
+    ${_gRPC_PROTO_GENS_DIR}
+)
+
+target_link_libraries(unknown_frame_bad_client_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  absl::flags
   grpc_test_util
-  grpc++_test_config
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(http_request_fuzzer_test_one_entry
-  test/core/http/request_fuzzer.cc
-  test/core/util/one_corpus_entry_fuzzer.cc
+add_executable(uri_parser_test
+  test/core/uri/uri_parser_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(http_request_fuzzer_test_one_entry
+target_include_directories(uri_parser_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -17244,26 +16369,59 @@ target_include_directories(http_request_fuzzer_test_one_entry
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(http_request_fuzzer_test_one_entry
+target_link_libraries(uri_parser_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  absl::flags
   grpc_test_util
-  grpc++_test_config
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(http_response_fuzzer_test_one_entry
-  test/core/http/response_fuzzer.cc
-  test/core/util/one_corpus_entry_fuzzer.cc
+add_executable(useful_test
+  test/core/gpr/useful_test.cc
+  third_party/googletest/googletest/src/gtest-all.cc
+  third_party/googletest/googlemock/src/gmock-all.cc
+)
+
+target_include_directories(useful_test
+  PRIVATE
+    ${CMAKE_CURRENT_SOURCE_DIR}
+    ${CMAKE_CURRENT_SOURCE_DIR}/include
+    ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
+    ${_gRPC_RE2_INCLUDE_DIR}
+    ${_gRPC_SSL_INCLUDE_DIR}
+    ${_gRPC_UPB_GENERATED_DIR}
+    ${_gRPC_UPB_GRPC_GENERATED_DIR}
+    ${_gRPC_UPB_INCLUDE_DIR}
+    ${_gRPC_XXHASH_INCLUDE_DIR}
+    ${_gRPC_ZLIB_INCLUDE_DIR}
+    third_party/googletest/googletest/include
+    third_party/googletest/googletest
+    third_party/googletest/googlemock/include
+    third_party/googletest/googlemock
+    ${_gRPC_PROTO_GENS_DIR}
+)
+
+target_link_libraries(useful_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+)
+
+
+endif()
+if(gRPC_BUILD_TESTS)
+
+add_executable(window_overflow_bad_client_test
+  test/core/bad_client/bad_client.cc
+  test/core/bad_client/tests/window_overflow.cc
+  test/core/end2end/cq_verifier.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(http_response_fuzzer_test_one_entry
+target_include_directories(window_overflow_bad_client_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -17282,26 +16440,78 @@ target_include_directories(http_response_fuzzer_test_one_entry
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(http_response_fuzzer_test_one_entry
+target_link_libraries(window_overflow_bad_client_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  absl::flags
   grpc_test_util
-  grpc++_test_config
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(json_fuzzer_test_one_entry
-  test/core/json/fuzzer.cc
-  test/core/util/one_corpus_entry_fuzzer.cc
+add_executable(wire_reader_test
+  src/core/ext/transport/binder/client/binder_connector.cc
+  src/core/ext/transport/binder/client/channel_create.cc
+  src/core/ext/transport/binder/client/channel_create_impl.cc
+  src/core/ext/transport/binder/client/connection_id_generator.cc
+  src/core/ext/transport/binder/client/endpoint_binder_pool.cc
+  src/core/ext/transport/binder/client/jni_utils.cc
+  src/core/ext/transport/binder/client/security_policy_setting.cc
+  src/core/ext/transport/binder/security_policy/binder_security_policy.cc
+  src/core/ext/transport/binder/server/binder_server.cc
+  src/core/ext/transport/binder/server/binder_server_credentials.cc
+  src/core/ext/transport/binder/transport/binder_transport.cc
+  src/core/ext/transport/binder/utils/transport_stream_receiver_impl.cc
+  src/core/ext/transport/binder/wire_format/binder_android.cc
+  src/core/ext/transport/binder/wire_format/binder_constants.cc
+  src/core/ext/transport/binder/wire_format/transaction.cc
+  src/core/ext/transport/binder/wire_format/wire_reader_impl.cc
+  src/core/ext/transport/binder/wire_format/wire_writer.cc
+  src/cpp/client/channel_cc.cc
+  src/cpp/client/client_callback.cc
+  src/cpp/client/client_context.cc
+  src/cpp/client/client_interceptor.cc
+  src/cpp/client/create_channel.cc
+  src/cpp/client/create_channel_internal.cc
+  src/cpp/client/create_channel_posix.cc
+  src/cpp/client/credentials_cc.cc
+  src/cpp/codegen/codegen_init.cc
+  src/cpp/common/alarm.cc
+  src/cpp/common/channel_arguments.cc
+  src/cpp/common/channel_filter.cc
+  src/cpp/common/completion_queue_cc.cc
+  src/cpp/common/core_codegen.cc
+  src/cpp/common/resource_quota_cc.cc
+  src/cpp/common/rpc_method.cc
+  src/cpp/common/validate_service_config.cc
+  src/cpp/common/version_cc.cc
+  src/cpp/server/async_generic_service.cc
+  src/cpp/server/channel_argument_option.cc
+  src/cpp/server/create_default_thread_pool.cc
+  src/cpp/server/dynamic_thread_pool.cc
+  src/cpp/server/external_connection_acceptor_impl.cc
+  src/cpp/server/health/default_health_check_service.cc
+  src/cpp/server/health/health_check_service.cc
+  src/cpp/server/health/health_check_service_server_builder_option.cc
+  src/cpp/server/server_builder.cc
+  src/cpp/server/server_callback.cc
+  src/cpp/server/server_cc.cc
+  src/cpp/server/server_context.cc
+  src/cpp/server/server_credentials.cc
+  src/cpp/server/server_posix.cc
+  src/cpp/thread_manager/thread_manager.cc
+  src/cpp/util/byte_buffer_cc.cc
+  src/cpp/util/status.cc
+  src/cpp/util/string_ref.cc
+  src/cpp/util/time_cc.cc
+  test/core/transport/binder/mock_objects.cc
+  test/core/transport/binder/wire_reader_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(json_fuzzer_test_one_entry
+target_include_directories(wire_reader_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -17320,26 +16530,78 @@ target_include_directories(json_fuzzer_test_one_entry
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(json_fuzzer_test_one_entry
+target_link_libraries(wire_reader_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  absl::flags
   grpc_test_util
-  grpc++_test_config
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(nanopb_fuzzer_response_test_one_entry
-  test/core/nanopb/fuzzer_response.cc
-  test/core/util/one_corpus_entry_fuzzer.cc
+add_executable(wire_writer_test
+  src/core/ext/transport/binder/client/binder_connector.cc
+  src/core/ext/transport/binder/client/channel_create.cc
+  src/core/ext/transport/binder/client/channel_create_impl.cc
+  src/core/ext/transport/binder/client/connection_id_generator.cc
+  src/core/ext/transport/binder/client/endpoint_binder_pool.cc
+  src/core/ext/transport/binder/client/jni_utils.cc
+  src/core/ext/transport/binder/client/security_policy_setting.cc
+  src/core/ext/transport/binder/security_policy/binder_security_policy.cc
+  src/core/ext/transport/binder/server/binder_server.cc
+  src/core/ext/transport/binder/server/binder_server_credentials.cc
+  src/core/ext/transport/binder/transport/binder_transport.cc
+  src/core/ext/transport/binder/utils/transport_stream_receiver_impl.cc
+  src/core/ext/transport/binder/wire_format/binder_android.cc
+  src/core/ext/transport/binder/wire_format/binder_constants.cc
+  src/core/ext/transport/binder/wire_format/transaction.cc
+  src/core/ext/transport/binder/wire_format/wire_reader_impl.cc
+  src/core/ext/transport/binder/wire_format/wire_writer.cc
+  src/cpp/client/channel_cc.cc
+  src/cpp/client/client_callback.cc
+  src/cpp/client/client_context.cc
+  src/cpp/client/client_interceptor.cc
+  src/cpp/client/create_channel.cc
+  src/cpp/client/create_channel_internal.cc
+  src/cpp/client/create_channel_posix.cc
+  src/cpp/client/credentials_cc.cc
+  src/cpp/codegen/codegen_init.cc
+  src/cpp/common/alarm.cc
+  src/cpp/common/channel_arguments.cc
+  src/cpp/common/channel_filter.cc
+  src/cpp/common/completion_queue_cc.cc
+  src/cpp/common/core_codegen.cc
+  src/cpp/common/resource_quota_cc.cc
+  src/cpp/common/rpc_method.cc
+  src/cpp/common/validate_service_config.cc
+  src/cpp/common/version_cc.cc
+  src/cpp/server/async_generic_service.cc
+  src/cpp/server/channel_argument_option.cc
+  src/cpp/server/create_default_thread_pool.cc
+  src/cpp/server/dynamic_thread_pool.cc
+  src/cpp/server/external_connection_acceptor_impl.cc
+  src/cpp/server/health/default_health_check_service.cc
+  src/cpp/server/health/health_check_service.cc
+  src/cpp/server/health/health_check_service_server_builder_option.cc
+  src/cpp/server/server_builder.cc
+  src/cpp/server/server_callback.cc
+  src/cpp/server/server_cc.cc
+  src/cpp/server/server_context.cc
+  src/cpp/server/server_credentials.cc
+  src/cpp/server/server_posix.cc
+  src/cpp/thread_manager/thread_manager.cc
+  src/cpp/util/byte_buffer_cc.cc
+  src/cpp/util/status.cc
+  src/cpp/util/string_ref.cc
+  src/cpp/util/time_cc.cc
+  test/core/transport/binder/mock_objects.cc
+  test/core/transport/binder/wire_writer_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(nanopb_fuzzer_response_test_one_entry
+target_include_directories(wire_writer_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -17358,26 +16620,134 @@ target_include_directories(nanopb_fuzzer_response_test_one_entry
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(nanopb_fuzzer_response_test_one_entry
+target_link_libraries(wire_writer_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  absl::flags
   grpc_test_util
-  grpc++_test_config
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+
+  add_executable(work_serializer_test
+    test/core/iomgr/work_serializer_test.cc
+    third_party/googletest/googletest/src/gtest-all.cc
+    third_party/googletest/googlemock/src/gmock-all.cc
+  )
+
+  target_include_directories(work_serializer_test
+    PRIVATE
+      ${CMAKE_CURRENT_SOURCE_DIR}
+      ${CMAKE_CURRENT_SOURCE_DIR}/include
+      ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
+      ${_gRPC_RE2_INCLUDE_DIR}
+      ${_gRPC_SSL_INCLUDE_DIR}
+      ${_gRPC_UPB_GENERATED_DIR}
+      ${_gRPC_UPB_GRPC_GENERATED_DIR}
+      ${_gRPC_UPB_INCLUDE_DIR}
+      ${_gRPC_XXHASH_INCLUDE_DIR}
+      ${_gRPC_ZLIB_INCLUDE_DIR}
+      third_party/googletest/googletest/include
+      third_party/googletest/googletest
+      third_party/googletest/googlemock/include
+      third_party/googletest/googlemock
+      ${_gRPC_PROTO_GENS_DIR}
+  )
+
+  target_link_libraries(work_serializer_test
+    ${_gRPC_PROTOBUF_LIBRARIES}
+    ${_gRPC_ALLTARGETS_LIBRARIES}
+    grpc_test_util
+  )
+
+
+endif()
+endif()
+if(gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+
+  add_executable(writes_per_rpc_test
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
+    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/memory_counters.cc
+    test/core/util/mock_endpoint.cc
+    test/core/util/parse_hexstring.cc
+    test/core/util/passthru_endpoint.cc
+    test/core/util/port.cc
+    test/core/util/port_isolated_runtime_environment.cc
+    test/core/util/port_server_client.cc
+    test/core/util/reconnect_server.cc
+    test/core/util/resolve_localhost_ip46.cc
+    test/core/util/resource_user_util.cc
+    test/core/util/slice_splitter.cc
+    test/core/util/stack_tracer.cc
+    test/core/util/subprocess_posix.cc
+    test/core/util/subprocess_windows.cc
+    test/core/util/test_config.cc
+    test/core/util/test_tcp_server.cc
+    test/core/util/tracer_util.cc
+    test/core/util/trickle_endpoint.cc
+    test/cpp/performance/writes_per_rpc_test.cc
+    third_party/googletest/googletest/src/gtest-all.cc
+    third_party/googletest/googlemock/src/gmock-all.cc
+  )
+
+  target_include_directories(writes_per_rpc_test
+    PRIVATE
+      ${CMAKE_CURRENT_SOURCE_DIR}
+      ${CMAKE_CURRENT_SOURCE_DIR}/include
+      ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
+      ${_gRPC_RE2_INCLUDE_DIR}
+      ${_gRPC_SSL_INCLUDE_DIR}
+      ${_gRPC_UPB_GENERATED_DIR}
+      ${_gRPC_UPB_GRPC_GENERATED_DIR}
+      ${_gRPC_UPB_INCLUDE_DIR}
+      ${_gRPC_XXHASH_INCLUDE_DIR}
+      ${_gRPC_ZLIB_INCLUDE_DIR}
+      third_party/googletest/googletest/include
+      third_party/googletest/googletest
+      third_party/googletest/googlemock/include
+      third_party/googletest/googlemock
+      ${_gRPC_PROTO_GENS_DIR}
+  )
+
+  target_link_libraries(writes_per_rpc_test
+    ${_gRPC_PROTOBUF_LIBRARIES}
+    ${_gRPC_ALLTARGETS_LIBRARIES}
+    absl::failure_signal_handler
+    absl::stacktrace
+    absl::symbolize
+    grpc++
+  )
+
+
+endif()
+endif()
+if(gRPC_BUILD_TESTS)
 
-add_executable(nanopb_fuzzer_serverlist_test_one_entry
-  test/core/nanopb/fuzzer_serverlist.cc
-  test/core/util/one_corpus_entry_fuzzer.cc
+add_executable(xds_bootstrap_test
+  test/core/xds/xds_bootstrap_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(nanopb_fuzzer_serverlist_test_one_entry
+target_include_directories(xds_bootstrap_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -17396,26 +16766,23 @@ target_include_directories(nanopb_fuzzer_serverlist_test_one_entry
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(nanopb_fuzzer_serverlist_test_one_entry
+target_link_libraries(xds_bootstrap_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  absl::flags
   grpc_test_util
-  grpc++_test_config
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(percent_decode_fuzzer_one_entry
-  test/core/slice/percent_decode_fuzzer.cc
-  test/core/util/one_corpus_entry_fuzzer.cc
+add_executable(xds_certificate_provider_test
+  test/core/xds/xds_certificate_provider_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(percent_decode_fuzzer_one_entry
+target_include_directories(xds_certificate_provider_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -17434,26 +16801,36 @@ target_include_directories(percent_decode_fuzzer_one_entry
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(percent_decode_fuzzer_one_entry
+target_link_libraries(xds_certificate_provider_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  absl::flags
   grpc_test_util
-  grpc++_test_config
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(percent_encode_fuzzer_one_entry
-  test/core/slice/percent_encode_fuzzer.cc
-  test/core/util/one_corpus_entry_fuzzer.cc
+add_executable(xds_credentials_end2end_test
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
+  test/cpp/end2end/test_service_impl.cc
+  test/cpp/end2end/xds/xds_credentials_end2end_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(percent_encode_fuzzer_one_entry
+target_include_directories(xds_credentials_end2end_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -17472,26 +16849,23 @@ target_include_directories(percent_encode_fuzzer_one_entry
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(percent_encode_fuzzer_one_entry
+target_link_libraries(xds_credentials_end2end_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  absl::flags
-  grpc_test_util
-  grpc++_test_config
+  grpc++_test_util
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(server_fuzzer_one_entry
-  test/core/end2end/fuzzers/server_fuzzer.cc
-  test/core/util/one_corpus_entry_fuzzer.cc
+add_executable(xds_credentials_test
+  test/core/security/xds_credentials_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(server_fuzzer_one_entry
+target_include_directories(xds_credentials_test
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -17510,26 +16884,230 @@ target_include_directories(server_fuzzer_one_entry
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(server_fuzzer_one_entry
+target_link_libraries(xds_credentials_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  absl::flags
   grpc_test_util
-  grpc++_test_config
 )
 
 
 endif()
 if(gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+
+  add_executable(xds_end2end_test
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.grpc.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/cds_for_test.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/cds_for_test.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/cds_for_test.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/cds_for_test.grpc.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.grpc.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lds_rds_for_test.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lds_rds_for_test.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lds_rds_for_test.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lds_rds_for_test.grpc.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.grpc.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/address.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/address.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/address.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/address.grpc.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/ads.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/ads.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/ads.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/ads.grpc.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/aggregate_cluster.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/aggregate_cluster.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/aggregate_cluster.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/aggregate_cluster.grpc.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.grpc.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/cluster.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/cluster.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/cluster.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/cluster.grpc.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.grpc.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_source.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_source.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_source.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_source.grpc.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.grpc.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/discovery.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/discovery.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/discovery.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/discovery.grpc.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/endpoint.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/endpoint.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/endpoint.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/endpoint.grpc.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/extension.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/extension.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/extension.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/extension.grpc.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/fault.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/fault.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/fault.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/fault.grpc.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/fault_common.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/fault_common.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/fault_common.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/fault_common.grpc.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/http_connection_manager.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/http_connection_manager.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/http_connection_manager.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/http_connection_manager.grpc.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/listener.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/listener.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/listener.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/listener.grpc.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/load_report.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/load_report.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/load_report.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/load_report.grpc.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/lrs.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/lrs.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/lrs.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/lrs.grpc.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.grpc.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/protocol.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/protocol.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/protocol.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/protocol.grpc.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/range.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/range.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/range.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/range.grpc.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/regex.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/regex.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/regex.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/regex.grpc.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/route.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/route.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/route.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/route.grpc.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/router.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/router.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/router.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/router.grpc.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/string.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/string.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/string.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/string.grpc.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/tls.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/tls.grpc.pb.cc
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/tls.pb.h
+    ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/tls.grpc.pb.h
+    src/cpp/server/csds/csds.cc
+    test/cpp/end2end/test_service_impl.cc
+    test/cpp/end2end/xds/xds_end2end_test.cc
+    test/cpp/end2end/xds/xds_server.cc
+    third_party/googletest/googletest/src/gtest-all.cc
+    third_party/googletest/googlemock/src/gmock-all.cc
+  )
+
+  target_include_directories(xds_end2end_test
+    PRIVATE
+      ${CMAKE_CURRENT_SOURCE_DIR}
+      ${CMAKE_CURRENT_SOURCE_DIR}/include
+      ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
+      ${_gRPC_RE2_INCLUDE_DIR}
+      ${_gRPC_SSL_INCLUDE_DIR}
+      ${_gRPC_UPB_GENERATED_DIR}
+      ${_gRPC_UPB_GRPC_GENERATED_DIR}
+      ${_gRPC_UPB_INCLUDE_DIR}
+      ${_gRPC_XXHASH_INCLUDE_DIR}
+      ${_gRPC_ZLIB_INCLUDE_DIR}
+      third_party/googletest/googletest/include
+      third_party/googletest/googletest
+      third_party/googletest/googlemock/include
+      third_party/googletest/googlemock
+      ${_gRPC_PROTO_GENS_DIR}
+  )
+
+  target_link_libraries(xds_end2end_test
+    ${_gRPC_PROTOBUF_LIBRARIES}
+    ${_gRPC_ALLTARGETS_LIBRARIES}
+    grpc++_test_config
+    grpc++_test_util
+  )
+
+
+endif()
+endif()
+if(gRPC_BUILD_TESTS)
 
-add_executable(ssl_server_fuzzer_one_entry
-  test/core/security/ssl_server_fuzzer.cc
-  test/core/util/one_corpus_entry_fuzzer.cc
+add_executable(xds_interop_client
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.grpc.pb.h
+  src/cpp/server/admin/admin_services.cc
+  src/cpp/server/csds/csds.cc
+  test/cpp/interop/xds_interop_client.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(ssl_server_fuzzer_one_entry
+target_include_directories(xds_interop_client
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -17548,10 +17126,12 @@ target_include_directories(ssl_server_fuzzer_one_entry
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(ssl_server_fuzzer_one_entry
+target_link_libraries(xds_interop_client
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
   absl::flags
+  grpc++_reflection
+  grpcpp_channelz
   grpc_test_util
   grpc++_test_config
 )
@@ -17560,14 +17140,48 @@ target_link_libraries(ssl_server_fuzzer_one_entry
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(uri_fuzzer_test_one_entry
-  test/core/uri/uri_fuzzer_test.cc
-  test/core/util/one_corpus_entry_fuzzer.cc
+add_executable(xds_interop_server
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/health/v1/health.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/health/v1/health.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/health/v1/health.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/health/v1/health.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.grpc.pb.h
+  src/cpp/server/admin/admin_services.cc
+  src/cpp/server/csds/csds.cc
+  test/cpp/end2end/test_health_check_service_impl.cc
+  test/cpp/interop/xds_interop_server.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
 )
 
-target_include_directories(uri_fuzzer_test_one_entry
+target_include_directories(xds_interop_server
   PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -17586,10 +17200,12 @@ target_include_directories(uri_fuzzer_test_one_entry
     ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(uri_fuzzer_test_one_entry
+target_link_libraries(xds_interop_server
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
   absl::flags
+  grpc++_reflection
+  grpcpp_channelz
   grpc_test_util
   grpc++_test_config
 )
@@ -17664,7 +17280,7 @@ generate_pkgconfig(
   "gRPC"
   "high performance general RPC framework"
   "${gRPC_CORE_VERSION}"
-  "gpr openssl absl_base absl_bind_front absl_cord absl_core_headers absl_flat_hash_map absl_inlined_vector absl_memory absl_optional absl_status absl_statusor absl_str_format absl_strings absl_synchronization absl_time absl_variant"
+  "gpr openssl absl_base absl_bind_front absl_cord absl_core_headers absl_flat_hash_map absl_hash absl_inlined_vector absl_memory absl_optional absl_status absl_statusor absl_str_format absl_strings absl_synchronization absl_time absl_utility absl_variant"
   "-lgrpc -laddress_sorting -lre2 -lupb -lcares -lz"
   ""
   "grpc.pc")
@@ -17674,7 +17290,7 @@ generate_pkgconfig(
   "gRPC unsecure"
   "high performance general RPC framework without SSL"
   "${gRPC_CORE_VERSION}"
-  "gpr absl_base absl_bind_front absl_cord absl_core_headers absl_flat_hash_map absl_inlined_vector absl_memory absl_optional absl_status absl_statusor absl_str_format absl_strings absl_synchronization absl_time absl_variant"
+  "gpr absl_base absl_bind_front absl_cord absl_core_headers absl_flat_hash_map absl_inlined_vector absl_memory absl_optional absl_status absl_statusor absl_str_format absl_strings absl_synchronization absl_time absl_utility absl_variant"
   "-lgrpc_unsecure"
   ""
   "grpc_unsecure.pc")
@@ -17684,7 +17300,7 @@ generate_pkgconfig(
   "gRPC++"
   "C++ wrapper for gRPC"
   "${gRPC_CPP_VERSION}"
-  "grpc absl_base absl_bind_front absl_cord absl_core_headers absl_flat_hash_map absl_inlined_vector absl_memory absl_optional absl_status absl_statusor absl_str_format absl_strings absl_synchronization absl_time absl_variant"
+  "grpc absl_base absl_bind_front absl_cord absl_core_headers absl_flat_hash_map absl_hash absl_inlined_vector absl_memory absl_optional absl_status absl_statusor absl_str_format absl_strings absl_synchronization absl_time absl_utility absl_variant"
   "-lgrpc++"
   ""
   "grpc++.pc")
@@ -17694,7 +17310,7 @@ generate_pkgconfig(
   "gRPC++ unsecure"
   "C++ wrapper for gRPC without SSL"
   "${gRPC_CPP_VERSION}"
-  "grpc_unsecure absl_base absl_bind_front absl_cord absl_core_headers absl_flat_hash_map absl_inlined_vector absl_memory absl_optional absl_status absl_statusor absl_str_format absl_strings absl_synchronization absl_time absl_variant"
+  "grpc_unsecure absl_base absl_bind_front absl_cord absl_core_headers absl_flat_hash_map absl_inlined_vector absl_memory absl_optional absl_status absl_statusor absl_str_format absl_strings absl_synchronization absl_time absl_utility absl_variant"
   "-lgrpc++_unsecure"
   ""
   "grpc++_unsecure.pc")
diff --git a/LICENSE b/LICENSE
index d645695..74ec4aa 100644 (file)
--- a/LICENSE
+++ b/LICENSE
    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.
+
+-----------------------------------------------------------
+
+BSD 3-Clause License
+
+Copyright 2016, Google Inc.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its
+contributors may be used to endorse or promote products derived from this
+software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+THE POSSIBILITY OF SUCH DAMAGE.
+
+-----------------------------------------------------------
+
+Mozilla Public License, v. 2.0
+
+This Source Code Form is subject to the terms of the Mozilla Public License,
+v. 2.0. If a copy of the MPL was not distributed with this file, You can
+obtain one at https://mozilla.org/MPL/2.0/.
index e7715fe..bae0e92 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -454,9 +454,9 @@ E = @echo
 Q = @
 endif
 
-CORE_VERSION = 19.0.0
-CPP_VERSION = 1.41.1
-CSHARP_VERSION = 2.41.1
+CORE_VERSION = 20.0.0
+CPP_VERSION = 1.42.0
+CSHARP_VERSION = 2.42.0
 
 CPPFLAGS_NO_ARCH += $(addprefix -I, $(INCLUDES)) $(addprefix -D, $(DEFINES))
 CPPFLAGS += $(CPPFLAGS_NO_ARCH) $(ARCH_FLAGS)
@@ -492,7 +492,7 @@ SHARED_EXT_CORE = dll
 SHARED_EXT_CPP = dll
 SHARED_EXT_CSHARP = dll
 SHARED_PREFIX =
-SHARED_VERSION_CORE = -19
+SHARED_VERSION_CORE = -20
 SHARED_VERSION_CPP = -1
 SHARED_VERSION_CSHARP = -2
 else ifeq ($(SYSTEM),Darwin)
@@ -579,7 +579,7 @@ CPPFLAGS := -Ithird_party/address_sorting/include $(CPPFLAGS)
 GRPC_ABSEIL_DEP = $(LIBDIR)/$(CONFIG)/libgrpc_abseil.a
 GRPC_ABSEIL_MERGE_LIBS = $(LIBDIR)/$(CONFIG)/libgrpc_abseil.a
 ifeq ($(HOST_IS_X86_64),true)
-ABSL_RANDOM_HWAES_FLAGS = -maes -msse4
+ABSL_RANDOM_HWAES_FLAGS = -maes
 else
 ABSL_RANDOM_HWAES_FLAGS =
 endif
@@ -891,8 +891,8 @@ $(LIBDIR)/$(CONFIG)/libaddress_sorting$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE):
 ifeq ($(SYSTEM),Darwin)
        $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)address_sorting$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libaddress_sorting$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBADDRESS_SORTING_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS)
 else
-       $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libaddress_sorting.so.19 -o $(LIBDIR)/$(CONFIG)/libaddress_sorting$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBADDRESS_SORTING_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS)
-       $(Q) ln -sf $(SHARED_PREFIX)address_sorting$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libaddress_sorting$(SHARED_VERSION_CORE).so.19
+       $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libaddress_sorting.so.20 -o $(LIBDIR)/$(CONFIG)/libaddress_sorting$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBADDRESS_SORTING_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS)
+       $(Q) ln -sf $(SHARED_PREFIX)address_sorting$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libaddress_sorting$(SHARED_VERSION_CORE).so.20
        $(Q) ln -sf $(SHARED_PREFIX)address_sorting$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libaddress_sorting$(SHARED_VERSION_CORE).so
 endif
 endif
@@ -1031,8 +1031,8 @@ $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGPR_OB
 ifeq ($(SYSTEM),Darwin)
        $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGPR_OBJS) $(LIBDIR)/$(CONFIG)/libupb.a $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS)
 else
-       $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgpr.so.19 -o $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGPR_OBJS) $(LIBDIR)/$(CONFIG)/libupb.a $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS)
-       $(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).so.19
+       $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgpr.so.20 -o $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGPR_OBJS) $(LIBDIR)/$(CONFIG)/libupb.a $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS)
+       $(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).so.20
        $(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).so
 endif
 endif
@@ -1071,6 +1071,7 @@ LIBGRPC_SRC = \
     src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc \
     src/core/ext/filters/client_channel/lb_policy/priority/priority.cc \
     src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc \
+    src/core/ext/filters/client_channel/lb_policy/rls/rls.cc \
     src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc \
     src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc \
     src/core/ext/filters/client_channel/lb_policy/xds/cds.cc \
@@ -1081,6 +1082,7 @@ LIBGRPC_SRC = \
     src/core/ext/filters/client_channel/local_subchannel_pool.cc \
     src/core/ext/filters/client_channel/proxy_mapper_registry.cc \
     src/core/ext/filters/client_channel/resolver.cc \
+    src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc \
     src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc \
     src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_event_engine.cc \
     src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc \
@@ -1101,12 +1103,11 @@ LIBGRPC_SRC = \
     src/core/ext/filters/client_channel/retry_service_config.cc \
     src/core/ext/filters/client_channel/retry_throttle.cc \
     src/core/ext/filters/client_channel/server_address.cc \
-    src/core/ext/filters/client_channel/service_config.cc \
     src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc \
-    src/core/ext/filters/client_channel/service_config_parser.cc \
     src/core/ext/filters/client_channel/subchannel.cc \
     src/core/ext/filters/client_channel/subchannel_pool_interface.cc \
     src/core/ext/filters/client_idle/client_idle_filter.cc \
+    src/core/ext/filters/client_idle/idle_filter_state.cc \
     src/core/ext/filters/deadline/deadline_filter.cc \
     src/core/ext/filters/fault_injection/fault_injection_filter.cc \
     src/core/ext/filters/fault_injection/service_config_parser.cc \
@@ -1118,10 +1119,9 @@ LIBGRPC_SRC = \
     src/core/ext/filters/http/server/http_server_filter.cc \
     src/core/ext/filters/max_age/max_age_filter.cc \
     src/core/ext/filters/message_size/message_size_filter.cc \
-    src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc \
-    src/core/ext/filters/workarounds/workaround_utils.cc \
+    src/core/ext/service_config/service_config.cc \
+    src/core/ext/service_config/service_config_parser.cc \
     src/core/ext/transport/chttp2/alpn/alpn.cc \
-    src/core/ext/transport/chttp2/client/authority.cc \
     src/core/ext/transport/chttp2/client/chttp2_connector.cc \
     src/core/ext/transport/chttp2/client/insecure/channel_create.cc \
     src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc \
@@ -1133,7 +1133,6 @@ LIBGRPC_SRC = \
     src/core/ext/transport/chttp2/transport/bin_decoder.cc \
     src/core/ext/transport/chttp2/transport/bin_encoder.cc \
     src/core/ext/transport/chttp2/transport/chttp2_plugin.cc \
-    src/core/ext/transport/chttp2/transport/chttp2_slice_allocator.cc \
     src/core/ext/transport/chttp2/transport/chttp2_transport.cc \
     src/core/ext/transport/chttp2/transport/context_list.cc \
     src/core/ext/transport/chttp2/transport/flow_control.cc \
@@ -1150,7 +1149,6 @@ LIBGRPC_SRC = \
     src/core/ext/transport/chttp2/transport/hpack_utils.cc \
     src/core/ext/transport/chttp2/transport/http2_settings.cc \
     src/core/ext/transport/chttp2/transport/huffsyms.cc \
-    src/core/ext/transport/chttp2/transport/incoming_metadata.cc \
     src/core/ext/transport/chttp2/transport/parsing.cc \
     src/core/ext/transport/chttp2/transport/stream_lists.cc \
     src/core/ext/transport/chttp2/transport/stream_map.cc \
@@ -1235,20 +1233,22 @@ LIBGRPC_SRC = \
     src/core/ext/upb-generated/src/proto/grpc/gcp/transport_security_common.upb.c \
     src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.c \
     src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c \
+    src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls.upb.c \
     src/core/ext/upb-generated/udpa/annotations/migrate.upb.c \
     src/core/ext/upb-generated/udpa/annotations/security.upb.c \
     src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c \
     src/core/ext/upb-generated/udpa/annotations/status.upb.c \
     src/core/ext/upb-generated/udpa/annotations/versioning.upb.c \
-    src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c \
-    src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.c \
     src/core/ext/upb-generated/validate/validate.upb.c \
+    src/core/ext/upb-generated/xds/annotations/v3/status.upb.c \
     src/core/ext/upb-generated/xds/core/v3/authority.upb.c \
     src/core/ext/upb-generated/xds/core/v3/collection_entry.upb.c \
     src/core/ext/upb-generated/xds/core/v3/context_params.upb.c \
     src/core/ext/upb-generated/xds/core/v3/resource.upb.c \
     src/core/ext/upb-generated/xds/core/v3/resource_locator.upb.c \
     src/core/ext/upb-generated/xds/core/v3/resource_name.upb.c \
+    src/core/ext/upb-generated/xds/data/orca/v3/orca_load_report.upb.c \
+    src/core/ext/upb-generated/xds/type/v3/typed_struct.upb.c \
     src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.c \
     src/core/ext/upbdefs-generated/envoy/annotations/deprecation.upbdefs.c \
     src/core/ext/upbdefs-generated/envoy/annotations/resource.upbdefs.c \
@@ -1334,20 +1334,22 @@ LIBGRPC_SRC = \
     src/core/ext/upbdefs-generated/udpa/annotations/sensitive.upbdefs.c \
     src/core/ext/upbdefs-generated/udpa/annotations/status.upbdefs.c \
     src/core/ext/upbdefs-generated/udpa/annotations/versioning.upbdefs.c \
-    src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.c \
     src/core/ext/upbdefs-generated/validate/validate.upbdefs.c \
+    src/core/ext/upbdefs-generated/xds/annotations/v3/status.upbdefs.c \
     src/core/ext/upbdefs-generated/xds/core/v3/authority.upbdefs.c \
     src/core/ext/upbdefs-generated/xds/core/v3/collection_entry.upbdefs.c \
     src/core/ext/upbdefs-generated/xds/core/v3/context_params.upbdefs.c \
     src/core/ext/upbdefs-generated/xds/core/v3/resource.upbdefs.c \
     src/core/ext/upbdefs-generated/xds/core/v3/resource_locator.upbdefs.c \
     src/core/ext/upbdefs-generated/xds/core/v3/resource_name.upbdefs.c \
+    src/core/ext/upbdefs-generated/xds/type/v3/typed_struct.upbdefs.c \
     src/core/ext/xds/certificate_provider_registry.cc \
     src/core/ext/xds/certificate_provider_store.cc \
     src/core/ext/xds/file_watcher_certificate_provider_factory.cc \
     src/core/ext/xds/xds_api.cc \
     src/core/ext/xds/xds_bootstrap.cc \
     src/core/ext/xds/xds_certificate_provider.cc \
+    src/core/ext/xds/xds_channel_stack_modifier.cc \
     src/core/ext/xds/xds_client.cc \
     src/core/ext/xds/xds_client_stats.cc \
     src/core/ext/xds/xds_http_fault_filter.cc \
@@ -1473,7 +1475,6 @@ LIBGRPC_SRC = \
     src/core/lib/iomgr/timer_generic.cc \
     src/core/lib/iomgr/timer_heap.cc \
     src/core/lib/iomgr/timer_manager.cc \
-    src/core/lib/iomgr/udp_server.cc \
     src/core/lib/iomgr/unix_sockets_posix.cc \
     src/core/lib/iomgr/unix_sockets_posix_noop.cc \
     src/core/lib/iomgr/wakeup_fd_eventfd.cc \
@@ -1543,10 +1544,15 @@ LIBGRPC_SRC = \
     src/core/lib/slice/b64.cc \
     src/core/lib/slice/percent_encoding.cc \
     src/core/lib/slice/slice.cc \
+    src/core/lib/slice/slice_api.cc \
     src/core/lib/slice/slice_buffer.cc \
     src/core/lib/slice/slice_intern.cc \
+    src/core/lib/slice/slice_refcount.cc \
+    src/core/lib/slice/slice_split.cc \
     src/core/lib/slice/slice_string_helpers.cc \
+    src/core/lib/slice/static_slice.cc \
     src/core/lib/surface/api_trace.cc \
+    src/core/lib/surface/builtins.cc \
     src/core/lib/surface/byte_buffer.cc \
     src/core/lib/surface/byte_buffer_reader.cc \
     src/core/lib/surface/call.cc \
@@ -1566,7 +1572,6 @@ LIBGRPC_SRC = \
     src/core/lib/surface/server.cc \
     src/core/lib/surface/validate_metadata.cc \
     src/core/lib/surface/version.cc \
-    src/core/lib/transport/authority_override.cc \
     src/core/lib/transport/bdp_estimator.cc \
     src/core/lib/transport/byte_stream.cc \
     src/core/lib/transport/connectivity_state.cc \
@@ -1617,8 +1622,9 @@ PUBLIC_HEADERS_C += \
     include/grpc/compression.h \
     include/grpc/event_engine/endpoint_config.h \
     include/grpc/event_engine/event_engine.h \
+    include/grpc/event_engine/internal/memory_allocator_impl.h \
+    include/grpc/event_engine/memory_allocator.h \
     include/grpc/event_engine/port.h \
-    include/grpc/event_engine/slice_allocator.h \
     include/grpc/fork.h \
     include/grpc/grpc.h \
     include/grpc/grpc_posix.h \
@@ -1666,8 +1672,8 @@ $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGRPC_
 ifeq ($(SYSTEM),Darwin)
        $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS)
 else
-       $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc.so.19 -o $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS)
-       $(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).so.19
+       $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc.so.20 -o $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS)
+       $(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).so.20
        $(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).so
 endif
 endif
@@ -1714,8 +1720,8 @@ $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE):
 ifeq ($(SYSTEM),Darwin)
        $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_CSHARP_EXT_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS)
 else
-       $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc_csharp_ext.so.19 -o $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_CSHARP_EXT_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS)
-       $(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CORE).so.19
+       $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc_csharp_ext.so.20 -o $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_CSHARP_EXT_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS)
+       $(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CORE).so.20
        $(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CORE).so
 endif
 endif
@@ -1760,6 +1766,7 @@ LIBGRPC_UNSECURE_SRC = \
     src/core/ext/filters/client_channel/local_subchannel_pool.cc \
     src/core/ext/filters/client_channel/proxy_mapper_registry.cc \
     src/core/ext/filters/client_channel/resolver.cc \
+    src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc \
     src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc \
     src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_event_engine.cc \
     src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc \
@@ -1778,12 +1785,11 @@ LIBGRPC_UNSECURE_SRC = \
     src/core/ext/filters/client_channel/retry_service_config.cc \
     src/core/ext/filters/client_channel/retry_throttle.cc \
     src/core/ext/filters/client_channel/server_address.cc \
-    src/core/ext/filters/client_channel/service_config.cc \
     src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc \
-    src/core/ext/filters/client_channel/service_config_parser.cc \
     src/core/ext/filters/client_channel/subchannel.cc \
     src/core/ext/filters/client_channel/subchannel_pool_interface.cc \
     src/core/ext/filters/client_idle/client_idle_filter.cc \
+    src/core/ext/filters/client_idle/idle_filter_state.cc \
     src/core/ext/filters/deadline/deadline_filter.cc \
     src/core/ext/filters/fault_injection/fault_injection_filter.cc \
     src/core/ext/filters/fault_injection/service_config_parser.cc \
@@ -1795,10 +1801,9 @@ LIBGRPC_UNSECURE_SRC = \
     src/core/ext/filters/http/server/http_server_filter.cc \
     src/core/ext/filters/max_age/max_age_filter.cc \
     src/core/ext/filters/message_size/message_size_filter.cc \
-    src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc \
-    src/core/ext/filters/workarounds/workaround_utils.cc \
+    src/core/ext/service_config/service_config.cc \
+    src/core/ext/service_config/service_config_parser.cc \
     src/core/ext/transport/chttp2/alpn/alpn.cc \
-    src/core/ext/transport/chttp2/client/authority.cc \
     src/core/ext/transport/chttp2/client/chttp2_connector.cc \
     src/core/ext/transport/chttp2/client/insecure/channel_create.cc \
     src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc \
@@ -1808,7 +1813,6 @@ LIBGRPC_UNSECURE_SRC = \
     src/core/ext/transport/chttp2/transport/bin_decoder.cc \
     src/core/ext/transport/chttp2/transport/bin_encoder.cc \
     src/core/ext/transport/chttp2/transport/chttp2_plugin.cc \
-    src/core/ext/transport/chttp2/transport/chttp2_slice_allocator.cc \
     src/core/ext/transport/chttp2/transport/chttp2_transport.cc \
     src/core/ext/transport/chttp2/transport/context_list.cc \
     src/core/ext/transport/chttp2/transport/flow_control.cc \
@@ -1825,7 +1829,6 @@ LIBGRPC_UNSECURE_SRC = \
     src/core/ext/transport/chttp2/transport/hpack_utils.cc \
     src/core/ext/transport/chttp2/transport/http2_settings.cc \
     src/core/ext/transport/chttp2/transport/huffsyms.cc \
-    src/core/ext/transport/chttp2/transport/incoming_metadata.cc \
     src/core/ext/transport/chttp2/transport/parsing.cc \
     src/core/ext/transport/chttp2/transport/stream_lists.cc \
     src/core/ext/transport/chttp2/transport/stream_map.cc \
@@ -1835,8 +1838,8 @@ LIBGRPC_UNSECURE_SRC = \
     src/core/ext/transport/inproc/inproc_transport.cc \
     src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.c \
     src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c \
-    src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c \
     src/core/ext/upb-generated/validate/validate.upb.c \
+    src/core/ext/upb-generated/xds/data/orca/v3/orca_load_report.upb.c \
     src/core/lib/address_utils/parse_address.cc \
     src/core/lib/address_utils/sockaddr_utils.cc \
     src/core/lib/avl/avl.cc \
@@ -1956,7 +1959,6 @@ LIBGRPC_UNSECURE_SRC = \
     src/core/lib/iomgr/timer_generic.cc \
     src/core/lib/iomgr/timer_heap.cc \
     src/core/lib/iomgr/timer_manager.cc \
-    src/core/lib/iomgr/udp_server.cc \
     src/core/lib/iomgr/unix_sockets_posix.cc \
     src/core/lib/iomgr/unix_sockets_posix_noop.cc \
     src/core/lib/iomgr/wakeup_fd_eventfd.cc \
@@ -1971,10 +1973,15 @@ LIBGRPC_UNSECURE_SRC = \
     src/core/lib/slice/b64.cc \
     src/core/lib/slice/percent_encoding.cc \
     src/core/lib/slice/slice.cc \
+    src/core/lib/slice/slice_api.cc \
     src/core/lib/slice/slice_buffer.cc \
     src/core/lib/slice/slice_intern.cc \
+    src/core/lib/slice/slice_refcount.cc \
+    src/core/lib/slice/slice_split.cc \
     src/core/lib/slice/slice_string_helpers.cc \
+    src/core/lib/slice/static_slice.cc \
     src/core/lib/surface/api_trace.cc \
+    src/core/lib/surface/builtins.cc \
     src/core/lib/surface/byte_buffer.cc \
     src/core/lib/surface/byte_buffer_reader.cc \
     src/core/lib/surface/call.cc \
@@ -1994,7 +2001,6 @@ LIBGRPC_UNSECURE_SRC = \
     src/core/lib/surface/server.cc \
     src/core/lib/surface/validate_metadata.cc \
     src/core/lib/surface/version.cc \
-    src/core/lib/transport/authority_override.cc \
     src/core/lib/transport/bdp_estimator.cc \
     src/core/lib/transport/byte_stream.cc \
     src/core/lib/transport/connectivity_state.cc \
@@ -2018,8 +2024,9 @@ PUBLIC_HEADERS_C += \
     include/grpc/compression.h \
     include/grpc/event_engine/endpoint_config.h \
     include/grpc/event_engine/event_engine.h \
+    include/grpc/event_engine/internal/memory_allocator_impl.h \
+    include/grpc/event_engine/memory_allocator.h \
     include/grpc/event_engine/port.h \
-    include/grpc/event_engine/slice_allocator.h \
     include/grpc/fork.h \
     include/grpc/grpc.h \
     include/grpc/grpc_posix.h \
@@ -2056,8 +2063,8 @@ $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $
 ifeq ($(SYSTEM),Darwin)
        $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_UNSECURE_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS)
 else
-       $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc_unsecure.so.19 -o $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_UNSECURE_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS)
-       $(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).so.19
+       $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc_unsecure.so.20 -o $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_UNSECURE_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS)
+       $(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).so.20
        $(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).so
 endif
 endif
@@ -2453,8 +2460,8 @@ $(LIBDIR)/$(CONFIG)/libupb$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBUPB_OB
 ifeq ($(SYSTEM),Darwin)
        $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)upb$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libupb$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBUPB_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS)
 else
-       $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libupb.so.19 -o $(LIBDIR)/$(CONFIG)/libupb$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBUPB_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS)
-       $(Q) ln -sf $(SHARED_PREFIX)upb$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libupb$(SHARED_VERSION_CORE).so.19
+       $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libupb.so.20 -o $(LIBDIR)/$(CONFIG)/libupb$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBUPB_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS)
+       $(Q) ln -sf $(SHARED_PREFIX)upb$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libupb$(SHARED_VERSION_CORE).so.20
        $(Q) ln -sf $(SHARED_PREFIX)upb$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libupb$(SHARED_VERSION_CORE).so
 endif
 endif
@@ -2698,6 +2705,7 @@ ifneq ($(OPENSSL_DEP),)
 # installing headers to their final destination on the drive. We need this
 # otherwise parallel compilation will fail if a source is compiled first.
 src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.cc: $(OPENSSL_DEP)
+src/core/ext/filters/client_channel/lb_policy/rls/rls.cc: $(OPENSSL_DEP)
 src/core/ext/filters/client_channel/lb_policy/xds/cds.cc: $(OPENSSL_DEP)
 src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_impl.cc: $(OPENSSL_DEP)
 src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_manager.cc: $(OPENSSL_DEP)
@@ -2781,18 +2789,20 @@ src/core/ext/upb-generated/envoy/type/v3/semantic_version.upb.c: $(OPENSSL_DEP)
 src/core/ext/upb-generated/src/proto/grpc/gcp/altscontext.upb.c: $(OPENSSL_DEP)
 src/core/ext/upb-generated/src/proto/grpc/gcp/handshaker.upb.c: $(OPENSSL_DEP)
 src/core/ext/upb-generated/src/proto/grpc/gcp/transport_security_common.upb.c: $(OPENSSL_DEP)
+src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls.upb.c: $(OPENSSL_DEP)
 src/core/ext/upb-generated/udpa/annotations/migrate.upb.c: $(OPENSSL_DEP)
 src/core/ext/upb-generated/udpa/annotations/security.upb.c: $(OPENSSL_DEP)
 src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c: $(OPENSSL_DEP)
 src/core/ext/upb-generated/udpa/annotations/status.upb.c: $(OPENSSL_DEP)
 src/core/ext/upb-generated/udpa/annotations/versioning.upb.c: $(OPENSSL_DEP)
-src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.c: $(OPENSSL_DEP)
+src/core/ext/upb-generated/xds/annotations/v3/status.upb.c: $(OPENSSL_DEP)
 src/core/ext/upb-generated/xds/core/v3/authority.upb.c: $(OPENSSL_DEP)
 src/core/ext/upb-generated/xds/core/v3/collection_entry.upb.c: $(OPENSSL_DEP)
 src/core/ext/upb-generated/xds/core/v3/context_params.upb.c: $(OPENSSL_DEP)
 src/core/ext/upb-generated/xds/core/v3/resource.upb.c: $(OPENSSL_DEP)
 src/core/ext/upb-generated/xds/core/v3/resource_locator.upb.c: $(OPENSSL_DEP)
 src/core/ext/upb-generated/xds/core/v3/resource_name.upb.c: $(OPENSSL_DEP)
+src/core/ext/upb-generated/xds/type/v3/typed_struct.upb.c: $(OPENSSL_DEP)
 src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.c: $(OPENSSL_DEP)
 src/core/ext/upbdefs-generated/envoy/annotations/deprecation.upbdefs.c: $(OPENSSL_DEP)
 src/core/ext/upbdefs-generated/envoy/annotations/resource.upbdefs.c: $(OPENSSL_DEP)
@@ -2878,20 +2888,22 @@ src/core/ext/upbdefs-generated/udpa/annotations/security.upbdefs.c: $(OPENSSL_DE
 src/core/ext/upbdefs-generated/udpa/annotations/sensitive.upbdefs.c: $(OPENSSL_DEP)
 src/core/ext/upbdefs-generated/udpa/annotations/status.upbdefs.c: $(OPENSSL_DEP)
 src/core/ext/upbdefs-generated/udpa/annotations/versioning.upbdefs.c: $(OPENSSL_DEP)
-src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.c: $(OPENSSL_DEP)
 src/core/ext/upbdefs-generated/validate/validate.upbdefs.c: $(OPENSSL_DEP)
+src/core/ext/upbdefs-generated/xds/annotations/v3/status.upbdefs.c: $(OPENSSL_DEP)
 src/core/ext/upbdefs-generated/xds/core/v3/authority.upbdefs.c: $(OPENSSL_DEP)
 src/core/ext/upbdefs-generated/xds/core/v3/collection_entry.upbdefs.c: $(OPENSSL_DEP)
 src/core/ext/upbdefs-generated/xds/core/v3/context_params.upbdefs.c: $(OPENSSL_DEP)
 src/core/ext/upbdefs-generated/xds/core/v3/resource.upbdefs.c: $(OPENSSL_DEP)
 src/core/ext/upbdefs-generated/xds/core/v3/resource_locator.upbdefs.c: $(OPENSSL_DEP)
 src/core/ext/upbdefs-generated/xds/core/v3/resource_name.upbdefs.c: $(OPENSSL_DEP)
+src/core/ext/upbdefs-generated/xds/type/v3/typed_struct.upbdefs.c: $(OPENSSL_DEP)
 src/core/ext/xds/certificate_provider_registry.cc: $(OPENSSL_DEP)
 src/core/ext/xds/certificate_provider_store.cc: $(OPENSSL_DEP)
 src/core/ext/xds/file_watcher_certificate_provider_factory.cc: $(OPENSSL_DEP)
 src/core/ext/xds/xds_api.cc: $(OPENSSL_DEP)
 src/core/ext/xds/xds_bootstrap.cc: $(OPENSSL_DEP)
 src/core/ext/xds/xds_certificate_provider.cc: $(OPENSSL_DEP)
+src/core/ext/xds/xds_channel_stack_modifier.cc: $(OPENSSL_DEP)
 src/core/ext/xds/xds_client.cc: $(OPENSSL_DEP)
 src/core/ext/xds/xds_client_stats.cc: $(OPENSSL_DEP)
 src/core/ext/xds/xds_http_fault_filter.cc: $(OPENSSL_DEP)
index faae210..437942c 100755 (executable)
--- a/Rakefile
+++ b/Rakefile
@@ -23,12 +23,6 @@ end
 
 # Add the extension compiler task
 Rake::ExtensionTask.new('grpc_c', spec) do |ext|
-  unless RUBY_PLATFORM =~ /darwin/
-    # TODO: also set "no_native to true" for mac if possible. As is,
-    # "no_native" can only be set if the RUBY_PLATFORM doing
-    # cross-compilation is contained in the "ext.cross_platform" array.
-    ext.no_native = true
-  end
   ext.source_pattern = '**/*.{c,h}'
   ext.ext_dir = File.join('src', 'ruby', 'ext', 'grpc')
   ext.lib_dir = File.join('src', 'ruby', 'lib', 'grpc')
@@ -36,6 +30,7 @@ Rake::ExtensionTask.new('grpc_c', spec) do |ext|
   ext.cross_platform = [
     'x86-mingw32', 'x64-mingw32',
     'x86_64-linux', 'x86-linux',
+    'x86_64-darwin', 'arm64-darwin',
     'universal-darwin'
   ]
   ext.cross_compiling do |spec|
@@ -47,6 +42,8 @@ Rake::ExtensionTask.new('grpc_c', spec) do |ext|
   end
 end
 
+CLEAN.add "src/ruby/lib/grpc/[0-9].[0-9]", "src/ruby/lib/grpc/grpc_c.{bundle,so}"
+
 # Define the test suites
 SPEC_SUITES = [
   { id: :wrapper, title: 'wrapper layer', files: %w(src/ruby/spec/*.rb) },
@@ -106,14 +103,13 @@ task 'dlls' do
     env_comp += "CXX=#{opt[:cross]}-g++ "
     env_comp += "LD=#{opt[:cross]}-gcc "
     env_comp += "LDXX=#{opt[:cross]}-g++ "
-    run_rake_compiler opt[:platform], <<-EOT
+    run_rake_compiler(opt[:platform], <<~EOT)
       gem update --system --no-document && \
       #{env} #{env_comp} make -j`nproc` #{out} && \
       #{opt[:cross]}-strip -x -S #{out} && \
       cp #{out} #{opt[:out]}
     EOT
   end
-
 end
 
 desc 'Build the native gem file under rake_compiler_dock'
@@ -135,10 +131,11 @@ task 'gem:native' do
   else
     Rake::Task['dlls'].execute
     ['x86-mingw32', 'x64-mingw32'].each do |plat|
-      run_rake_compiler plat, <<-EOT
+      run_rake_compiler(plat, <<~EOT)
         gem update --system --no-document && \
         bundle && \
-        rake native:#{plat} pkg/#{spec.full_name}-#{plat}.gem pkg/#{spec.full_name}.gem \
+        bundle exec rake clean && \
+        bundle exec rake native:#{plat} pkg/#{spec.full_name}-#{plat}.gem pkg/#{spec.full_name}.gem \
           RUBY_CC_VERSION=#{ruby_cc_versions} \
           V=#{verbose} \
           GRPC_CONFIG=#{grpc_config}
@@ -147,11 +144,12 @@ task 'gem:native' do
     # Truncate grpc_c.*.ruby files because they're for Windows only.
     File.truncate('grpc_c.32.ruby', 0)
     File.truncate('grpc_c.64.ruby', 0)
-    ['x86_64-linux', 'x86-linux'].each do |plat|
-      run_rake_compiler plat, <<-EOT
+    ['x86_64-linux', 'x86-linux', 'x86_64-darwin', 'arm64-darwin'].each do |plat|
+      run_rake_compiler(plat, <<~EOT)
         gem update --system --no-document && \
         bundle && \
-        rake native:#{plat} pkg/#{spec.full_name}-#{plat}.gem pkg/#{spec.full_name}.gem \
+        bundle exec rake clean && \
+        bundle exec rake native:#{plat} pkg/#{spec.full_name}-#{plat}.gem pkg/#{spec.full_name}.gem \
           RUBY_CC_VERSION=#{ruby_cc_versions} \
           V=#{verbose} \
           GRPC_CONFIG=#{grpc_config}
index 2288b60..c528f35 100644 (file)
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -10,31 +10,15 @@ load("//bazel:grpc_extra_deps.bzl", "grpc_extra_deps")
 
 grpc_extra_deps()
 
-register_execution_platforms(
-    "//third_party/toolchains:rbe_windows",
-)
-
-register_toolchains(
-    "//third_party/toolchains/bazel_0.26.0_rbe_windows:cc-toolchain-x64_windows",
-)
-
-load("@bazel_toolchains//rules/exec_properties:exec_properties.bzl", "create_exec_properties_dict", "custom_exec_properties", "merge_dicts")
+load("@bazel_toolchains//rules/exec_properties:exec_properties.bzl", "create_rbe_exec_properties_dict", "custom_exec_properties")
 
 custom_exec_properties(
     name = "grpc_custom_exec_properties",
     constants = {
-        "LARGE_MACHINE": merge_dicts(
-            create_exec_properties_dict(),
-            # TODO(jtattermusch): specifying 'labels = {"abc": "xyz"}' in create_exec_properties_dict
-            # is not possible without https://github.com/bazelbuild/bazel-toolchains/pull/748
-            # and currently the toolchain we're using is too old for that. To be able to select worker
-            # pools through labels, we use a workaround and populate the corresponding label values
-            # manually (see create_exec_properties_dict logic for how labels get transformed)
-            # Remove this workaround once we transition to a new-enough bazel toolchain.
-            # The next line corresponds to 'labels = {"os": "ubuntu", "machine_size": "large"}'
-            {
-                "label:os": "ubuntu",
-                "label:machine_size": "large",
+        "LARGE_MACHINE": create_rbe_exec_properties_dict(
+            labels = {
+                "os": "ubuntu",
+                "machine_size": "large",
             },
         ),
     },
@@ -45,23 +29,14 @@ load("@bazel_toolchains//rules:rbe_repo.bzl", "rbe_autoconfig")
 # Create toolchain configuration for remote execution.
 rbe_autoconfig(
     name = "rbe_default",
-    exec_properties = merge_dicts(
-        create_exec_properties_dict(
-            docker_add_capabilities = "SYS_PTRACE",
-            docker_privileged = True,
-            os_family = "Linux",
-        ),
-        # TODO(jtattermusch): specifying 'labels = {"abc": "xyz"}' in create_exec_properties_dict
-        # is not possible without https://github.com/bazelbuild/bazel-toolchains/pull/748
-        # and currently the toolchain we're using is too old for that. To be able to select worker
-        # pools through labels, we use a workaround and populate the corresponding label values
-        # manually (see create_exec_properties_dict logic for how labels get transformed)
-        # Remove this workaround once we transition to a new-enough bazel toolchain.
-        # The next line corresponds to 'labels = {"os": "ubuntu", "machine_size": "small"}'
-        {
-            "label:os": "ubuntu",
-            "label:machine_size": "small",
+    exec_properties = create_rbe_exec_properties_dict(
+        docker_add_capabilities = "SYS_PTRACE",
+        docker_privileged = True,
+        labels = {
+            "os": "ubuntu",
+            "machine_size": "small",
         },
+        os_family = "Linux",
     ),
     # use exec_properties instead of deprecated remote_execution_properties
     use_legacy_platform_definition = False,
@@ -112,15 +87,9 @@ rbe_autoconfig(
     ),
 )
 
-load("@io_bazel_rules_python//python:pip.bzl", "pip_import", "pip_repositories")
+load("@io_bazel_rules_python//python:pip.bzl", "pip_install")
 
-pip_import(
+pip_install(
     name = "grpc_python_dependencies",
     requirements = "@com_github_grpc_grpc//:requirements.bazel.txt",
 )
-
-load("@grpc_python_dependencies//:requirements.bzl", "pip_install")
-
-pip_repositories()
-
-pip_install()
index 7f4d749..699054b 100644 (file)
@@ -14,4 +14,4 @@
 
 # AUTO-GENERATED FROM `$REPO_ROOT/templates/_metadata.py.template`!!!
 
-__version__ = """1.41.1"""
+__version__ = """1.42.0"""
index c3c82c9..aa6cb34 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 package(default_visibility = ["//:__subpackages__"])
 
 load(":cc_grpc_library.bzl", "cc_grpc_library")
+
+filegroup(
+    name = "_gevent_test_main",
+    srcs = ["_gevent_test_main.py"],
+)
diff --git a/bazel/_gevent_test_main.py b/bazel/_gevent_test_main.py
new file mode 100644 (file)
index 0000000..52629c6
--- /dev/null
@@ -0,0 +1,60 @@
+# Copyright 2021 The gRPC Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import grpc
+import unittest
+import sys
+import os
+import pkgutil
+
+from typing import Sequence
+
+class SingleLoader(object):
+    def __init__(self, pattern: str):
+        loader = unittest.TestLoader()
+        self.suite = unittest.TestSuite()
+        tests = []
+        for importer, module_name, is_package in pkgutil.walk_packages([os.path.dirname(os.path.relpath(__file__))]):
+            if pattern in module_name:
+                module = importer.find_module(module_name).load_module(module_name)
+                tests.append(loader.loadTestsFromModule(module))
+        if len(tests) != 1:
+            raise AssertionError("Expected only 1 test module. Found {}".format(tests))
+        self.suite.addTest(tests[0])
+
+
+    def loadTestsFromNames(self, names: Sequence[str], module: str = None) -> unittest.TestSuite:
+        return self.suite
+
+if __name__ == "__main__":
+    from gevent import monkey
+
+    monkey.patch_all()
+
+    import grpc.experimental.gevent
+    grpc.experimental.gevent.init_gevent()
+    import gevent
+
+    if len(sys.argv) != 2:
+        print(f"USAGE: {sys.argv[0]} TARGET_MODULE", file=sys.stderr)
+
+    target_module = sys.argv[1]
+
+    loader = SingleLoader(target_module)
+    runner = unittest.TextTestRunner()
+
+    result = gevent.spawn(runner.run, loader.suite)
+    result.join()
+    if not result.value.wasSuccessful():
+        sys.exit("Test failure.")
diff --git a/bazel/gevent_test.bzl b/bazel/gevent_test.bzl
new file mode 100644 (file)
index 0000000..55444d3
--- /dev/null
@@ -0,0 +1,71 @@
+# Copyright 2021 The gRPC Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+load("@grpc_python_dependencies//:requirements.bzl", "requirement")
+
+_GRPC_LIB = "//src/python/grpcio/grpc:grpcio"
+
+_COPIED_MAIN_SUFFIX = ".gevent.main"
+
+def py_grpc_gevent_test(
+        name,
+        srcs,
+        main = None,
+        deps = None,
+        data = None,
+        **kwargs):
+    if main == None:
+        if len(srcs) != 1:
+            fail("When main is not provided, srcs must be of size 1.")
+        main = srcs[0]
+    deps = [] if deps == None else deps
+    data = [] if data == None else data
+    lib_name = name + ".gevent.lib"
+    supplied_python_version = kwargs.pop("python_version", "")
+    if supplied_python_version and supplied_python_version != "PY3":
+        fail("py_grpc_gevent_test only supports python_version=PY3")
+    native.py_library(
+        name = lib_name,
+        srcs = srcs,
+    )
+    augmented_deps = deps + [
+        ":{}".format(lib_name),
+        requirement("gevent"),
+    ]
+    if _GRPC_LIB not in augmented_deps:
+        augmented_deps.append(_GRPC_LIB)
+
+    # The main file needs to be in the same package as the test file.
+    copied_main_name = name + _COPIED_MAIN_SUFFIX
+    copied_main_filename = copied_main_name + ".py"
+    native.genrule(
+        name = copied_main_name,
+        srcs = ["//bazel:_gevent_test_main.py"],
+        outs = [copied_main_filename],
+        cmd = "cp $< $@",
+    )
+
+    # TODO(https://github.com/grpc/grpc/issues/27542): Remove once gevent is deemed non-flaky.
+    if "flaky" in kwargs:
+        kwargs.pop("flaky")
+
+    native.py_test(
+        name = name + ".gevent",
+        args = [name],
+        deps = augmented_deps,
+        srcs = [copied_main_filename],
+        main = copied_main_filename,
+        python_version = "PY3",
+        flaky = True,
+        **kwargs
+    )
index ddfb8e3..bd40426 100644 (file)
@@ -25,7 +25,7 @@
 
 load("//bazel:cc_grpc_library.bzl", "cc_grpc_library")
 load("//bazel:copts.bzl", "GRPC_DEFAULT_COPTS")
-load("@upb//bazel:upb_proto_library.bzl", "upb_proto_library")
+load("@upb//bazel:upb_proto_library.bzl", "upb_proto_library", "upb_proto_reflection_library")
 load("@build_bazel_rules_apple//apple:ios.bzl", "ios_unit_test")
 
 # The set of pollers to test against if a test exercises polling
@@ -131,7 +131,8 @@ def grpc_cc_library(
         linkopts = linkopts + if_mac(["-framework CoreFoundation"])
 
     if select_deps:
-        deps += select(select_deps)
+        for select_deps_entry in select_deps:
+            deps += select(select_deps_entry)
 
     native.cc_library(
         name = name,
@@ -398,6 +399,9 @@ def grpc_objc_library(
 def grpc_upb_proto_library(name, deps):
     upb_proto_library(name = name, deps = deps)
 
+def grpc_upb_proto_reflection_library(name, deps):
+    upb_proto_reflection_library(name = name, deps = deps)
+
 def python_config_settings():
     native.config_setting(
         name = "python3",
index dc9dacb..b089c85 100644 (file)
@@ -189,11 +189,11 @@ def grpc_deps():
             name = "boringssl",
             # Use github mirror instead of https://boringssl.googlesource.com/boringssl
             # to obtain a boringssl archive with consistent sha256
-            sha256 = "87a2efd493bd84c0c26afc607ce6c99d2cb05046d0ebbbefe8ba5b71bdeeda1c",
-            strip_prefix = "boringssl-340faef0ad19283e985ce7fff0dec73ba4022c8d",
+            sha256 = "bf070ffab0ea1a2d0c3d024d8ab8c813c96a5d07a890a9e7e9a979e9ad427b47",
+            strip_prefix = "boringssl-95b3ed1b01f2ef1d72fed290ed79fe1b0e7dafc0",
             urls = [
-                "https://storage.googleapis.com/grpc-bazel-mirror/github.com/google/boringssl/archive/340faef0ad19283e985ce7fff0dec73ba4022c8d.tar.gz",
-                "https://github.com/google/boringssl/archive/340faef0ad19283e985ce7fff0dec73ba4022c8d.tar.gz",
+                "https://storage.googleapis.com/grpc-bazel-mirror/github.com/google/boringssl/archive/95b3ed1b01f2ef1d72fed290ed79fe1b0e7dafc0.tar.gz",
+                "https://github.com/google/boringssl/archive/95b3ed1b01f2ef1d72fed290ed79fe1b0e7dafc0.tar.gz",
             ],
         )
 
@@ -212,11 +212,11 @@ def grpc_deps():
     if "com_google_protobuf" not in native.existing_rules():
         http_archive(
             name = "com_google_protobuf",
-            sha256 = "dd53cb731b1b6b515d3d679644344bf33bb9f5b88c98187ae5c7be734a665c57",
-            strip_prefix = "protobuf-909a0f36a10075c4b4bc70fdee2c7e32dd612a72",
+            sha256 = "74b5c6f7ca553a8d7c365ff0b5008ef5a44bc1aaeca6f964ad7557c2fa430691",
+            strip_prefix = "protobuf-0dab03ba7bc438d7ba3eac2b2c1eb39ed520f928",
             urls = [
-                "https://storage.googleapis.com/grpc-bazel-mirror/github.com/protocolbuffers/protobuf/archive/909a0f36a10075c4b4bc70fdee2c7e32dd612a72.tar.gz",
-                "https://github.com/protocolbuffers/protobuf/archive/909a0f36a10075c4b4bc70fdee2c7e32dd612a72.tar.gz",
+                "https://storage.googleapis.com/grpc-bazel-mirror/github.com/protocolbuffers/protobuf/archive/0dab03ba7bc438d7ba3eac2b2c1eb39ed520f928.tar.gz",
+                "https://github.com/protocolbuffers/protobuf/archive/0dab03ba7bc438d7ba3eac2b2c1eb39ed520f928.tar.gz",
             ],
             patches = ["@com_github_grpc_grpc//third_party:protobuf.patch"],
             patch_args = ["-p1"],
@@ -249,22 +249,23 @@ def grpc_deps():
     if "com_github_google_benchmark" not in native.existing_rules():
         http_archive(
             name = "com_github_google_benchmark",
-            sha256 = "daa4a97e0547d76de300e325a49177b199f3689ce5a35e25d47696f7cb050f86",
-            strip_prefix = "benchmark-73d4d5e8d6d449fc8663765a42aa8aeeee844489",
+            sha256 = "0b921a3bc39e35f4275c8dcc658af2391c150fb966102341287b0401ff2e6f21",
+            strip_prefix = "benchmark-0baacde3618ca617da95375e0af13ce1baadea47",
             urls = [
-                "https://storage.googleapis.com/grpc-bazel-mirror/github.com/google/benchmark/archive/73d4d5e8d6d449fc8663765a42aa8aeeee844489.tar.gz",
-                "https://github.com/google/benchmark/archive/73d4d5e8d6d449fc8663765a42aa8aeeee844489.tar.gz",
+                "https://storage.googleapis.com/grpc-bazel-mirror/github.com/google/benchmark/archive/0baacde3618ca617da95375e0af13ce1baadea47.tar.gz",
+                "https://github.com/google/benchmark/archive/0baacde3618ca617da95375e0af13ce1baadea47.tar.gz",
             ],
         )
 
     if "com_googlesource_code_re2" not in native.existing_rules():
         http_archive(
             name = "com_googlesource_code_re2",
-            sha256 = "9f385e146410a8150b6f4cb1a57eab7ec806ced48d427554b1e754877ff26c3e",
-            strip_prefix = "re2-aecba11114cf1fac5497aeb844b6966106de3eb6",
+            sha256 = "319a58a58d8af295db97dfeecc4e250179c5966beaa2d842a82f0a013b6a239b",
+            # Release 2021-09-01
+            strip_prefix = "re2-8e08f47b11b413302749c0d8b17a1c94777495d5",
             urls = [
-                "https://storage.googleapis.com/grpc-bazel-mirror/github.com/google/re2/archive/aecba11114cf1fac5497aeb844b6966106de3eb6.tar.gz",
-                "https://github.com/google/re2/archive/aecba11114cf1fac5497aeb844b6966106de3eb6.tar.gz",
+                "https://storage.googleapis.com/grpc-bazel-mirror/github.com/google/re2/archive/8e08f47b11b413302749c0d8b17a1c94777495d5.tar.gz",
+                "https://github.com/google/re2/archive/8e08f47b11b413302749c0d8b17a1c94777495d5.tar.gz",
             ],
         )
 
@@ -283,11 +284,11 @@ def grpc_deps():
     if "com_google_absl" not in native.existing_rules():
         http_archive(
             name = "com_google_absl",
-            sha256 = "35f22ef5cb286f09954b7cc4c85b5a3f6221c9d4df6b8c4a1e9d399555b366ee",
-            strip_prefix = "abseil-cpp-997aaf3a28308eba1b9156aa35ab7bca9688e9f6",
+            sha256 = "1764491a199eb9325b177126547f03d244f86b4ff28f16f206c7b3e7e4f777ec",
+            strip_prefix = "abseil-cpp-278e0a071885a22dcd2fd1b5576cc44757299343",
             urls = [
-                "https://storage.googleapis.com/grpc-bazel-mirror/github.com/abseil/abseil-cpp/archive/997aaf3a28308eba1b9156aa35ab7bca9688e9f6.tar.gz",
-                "https://github.com/abseil/abseil-cpp/archive/997aaf3a28308eba1b9156aa35ab7bca9688e9f6.tar.gz",
+                "https://storage.googleapis.com/grpc-bazel-mirror/github.com/abseil/abseil-cpp/archive/278e0a071885a22dcd2fd1b5576cc44757299343.tar.gz",
+                "https://github.com/abseil/abseil-cpp/archive/278e0a071885a22dcd2fd1b5576cc44757299343.tar.gz",
             ],
         )
 
@@ -295,11 +296,11 @@ def grpc_deps():
         # list of releases is at https://releases.bazel.build/bazel-toolchains.html
         http_archive(
             name = "bazel_toolchains",
-            sha256 = "0b36eef8a66f39c8dbae88e522d5bbbef49d5e66e834a982402c79962281be10",
-            strip_prefix = "bazel-toolchains-1.0.1",
+            sha256 = "179ec02f809e86abf56356d8898c8bd74069f1bd7c56044050c2cd3d79d0e024",
+            strip_prefix = "bazel-toolchains-4.1.0",
             urls = [
-                "https://mirror.bazel.build/github.com/bazelbuild/bazel-toolchains/archive/1.0.1.tar.gz",
-                "https://github.com/bazelbuild/bazel-toolchains/releases/download/1.0.1/bazel-toolchains-1.0.1.tar.gz",
+                "https://mirror.bazel.build/github.com/bazelbuild/bazel-toolchains/archive/4.1.0.tar.gz",
+                "https://github.com/bazelbuild/bazel-toolchains/releases/download/4.1.0/bazel-toolchains-4.1.0.tar.gz",
             ],
         )
 
@@ -349,11 +350,11 @@ def grpc_deps():
     if "envoy_api" not in native.existing_rules():
         http_archive(
             name = "envoy_api",
-            sha256 = "330f2f9c938fc038b7ab438919b692d30cdfba3cf596e7824410f88da16c30b5",
-            strip_prefix = "data-plane-api-2f0d081fab0b0823f088c6e368f40e1992f46fcd",
+            sha256 = "e89d4dddbadf797dd2700ce45ee8abc82557a934a15fcad82673e7d13213b868",
+            strip_prefix = "data-plane-api-20b1b5fcee88a20a08b71051a961181839ec7268",
             urls = [
-                "https://storage.googleapis.com/grpc-bazel-mirror/github.com/envoyproxy/data-plane-api/archive/2f0d081fab0b0823f088c6e368f40e1992f46fcd.tar.gz",
-                "https://github.com/envoyproxy/data-plane-api/archive/2f0d081fab0b0823f088c6e368f40e1992f46fcd.tar.gz",
+                "https://storage.googleapis.com/grpc-bazel-mirror/github.com/envoyproxy/data-plane-api/archive/20b1b5fcee88a20a08b71051a961181839ec7268.tar.gz",
+                "https://github.com/envoyproxy/data-plane-api/archive/20b1b5fcee88a20a08b71051a961181839ec7268.tar.gz",
             ],
         )
 
@@ -370,33 +371,32 @@ def grpc_deps():
     if "build_bazel_rules_apple" not in native.existing_rules():
         http_archive(
             name = "build_bazel_rules_apple",
-            strip_prefix = "rules_apple-b869b0d3868d78a1d4ffd866ccb304fb68aa12c3",
-            sha256 = "bdc8e66e70b8a75da23b79f1f8c6207356df07d041d96d2189add7ee0780cf4e",
+            sha256 = "0052d452af7742c8f3a4e0929763388a66403de363775db7e90adecb2ba4944b",
             urls = [
-                "https://storage.googleapis.com/grpc-bazel-mirror/github.com/bazelbuild/rules_apple/archive/b869b0d3868d78a1d4ffd866ccb304fb68aa12c3.tar.gz",
-                "https://github.com/bazelbuild/rules_apple/archive/b869b0d3868d78a1d4ffd866ccb304fb68aa12c3.tar.gz",
+                "https://storage.googleapis.com/grpc-bazel-mirror/github.com/bazelbuild/rules_apple/releases/download/0.31.3/rules_apple.0.31.3.tar.gz",
+                "https://github.com/bazelbuild/rules_apple/releases/download/0.31.3/rules_apple.0.31.3.tar.gz",
             ],
         )
 
     if "build_bazel_apple_support" not in native.existing_rules():
         http_archive(
             name = "build_bazel_apple_support",
+            sha256 = "76df040ade90836ff5543888d64616e7ba6c3a7b33b916aa3a4b68f342d1b447",
             urls = [
-                "https://storage.googleapis.com/grpc-bazel-mirror/github.com/bazelbuild/apple_support/releases/download/0.7.1/apple_support.0.7.1.tar.gz",
-                "https://github.com/bazelbuild/apple_support/releases/download/0.7.1/apple_support.0.7.1.tar.gz",
+                "https://storage.googleapis.com/grpc-bazel-mirror/github.com/bazelbuild/apple_support/releases/download/0.11.0/apple_support.0.11.0.tar.gz",
+                "https://github.com/bazelbuild/apple_support/releases/download/0.11.0/apple_support.0.11.0.tar.gz",
             ],
-            sha256 = "122ebf7fe7d1c8e938af6aeaee0efe788a3a2449ece5a8d6a428cb18d6f88033",
         )
 
     if "libuv" not in native.existing_rules():
         http_archive(
             name = "libuv",
             build_file = "@com_github_grpc_grpc//third_party:libuv.BUILD",
-            sha256 = "dfb4fe1ff0b47340978490a14bf253475159ecfcbad46ab2a350c78f9ce3360f",
-            strip_prefix = "libuv-15ae750151ac9341e5945eb38f8982d59fb99201",
+            sha256 = "5ca4e9091f3231d8ad8801862dc4e851c23af89c69141d27723157776f7291e7",
+            strip_prefix = "libuv-02a9e1be252b623ee032a3137c0b0c94afbe6809",
             urls = [
-                "https://storage.googleapis.com/grpc-bazel-mirror/github.com/libuv/libuv/archive/15ae750151ac9341e5945eb38f8982d59fb99201.tar.gz",
-                "https://github.com/libuv/libuv/archive/15ae750151ac9341e5945eb38f8982d59fb99201.tar.gz",
+                "https://storage.googleapis.com/grpc-bazel-mirror/github.com/libuv/libuv/archive/02a9e1be252b623ee032a3137c0b0c94afbe6809.tar.gz",
+                "https://github.com/libuv/libuv/archive/02a9e1be252b623ee032a3137c0b0c94afbe6809.tar.gz",
             ],
         )
 
@@ -519,3 +519,15 @@ def grpc_test_only_deps():
             ],
             build_file = "@com_github_grpc_grpc//third_party:constantly.BUILD",
         )
+
+    if "com_google_libprotobuf_mutator" not in native.existing_rules():
+        http_archive(
+            name = "com_google_libprotobuf_mutator",
+            sha256 = "b847c71723d8ce0b747aa661d7f3a07f1d16c595bf9c0202f30febc2f9a24a06",
+            urls = [
+                "https://github.com/google/libprotobuf-mutator/archive/ffd86a32874e5c08a143019aad1aaf0907294c9f.tar.gz",
+                "https://storage.googleapis.com/grpc-bazel-mirror/github.com/google/libprotobuf-mutator/archive/ffd86a32874e5c08a143019aad1aaf0907294c9f.tar.gz",
+            ],
+            strip_prefix = "libprotobuf-mutator-ffd86a32874e5c08a143019aad1aaf0907294c9f",
+            build_file = "@com_github_grpc_grpc//third_party:libprotobuf_mutator.BUILD",
+        )
index 4c47c5c..bbbaa2a 100644 (file)
@@ -49,8 +49,10 @@ def grpc_python_deps():
     if "io_bazel_rules_python" not in native.existing_rules():
         http_archive(
             name = "io_bazel_rules_python",
-            url = "https://github.com/bazelbuild/rules_python/releases/download/0.0.1/rules_python-0.0.1.tar.gz",
-            sha256 = "aa96a691d3a8177f3215b14b0edc9641787abaaa30363a080165d06ab65e1161",
+            url = "https://github.com/bazelbuild/rules_python/releases/download/0.4.0/rules_python-0.4.0.tar.gz",
+            sha256 = "954aa89b491be4a083304a2cb838019c8b8c3720a7abb9c4cb81ac7a24230cea",
+            patches = ["//third_party:rules_python.patch"],
+            patch_args = ["-p1"],
         )
 
     python_configure(name = "local_config_python")
diff --git a/bazel/internal_python_rules.bzl b/bazel/internal_python_rules.bzl
new file mode 100644 (file)
index 0000000..6f3c875
--- /dev/null
@@ -0,0 +1,35 @@
+# Copyright 2021 The gRPC Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Python-related rules intended only for use internal to the repo."""
+
+load("//bazel:gevent_test.bzl", "py_grpc_gevent_test")
+load("//bazel:python_rules.bzl", "py2and3_test")
+
+def internal_py_grpc_test(name, **kwargs):
+    """Runs a test under all supported environments."""
+    py2and3_test(name, **kwargs)
+    py_grpc_gevent_test(name, **kwargs)
+
+    suite_kwargs = {}
+    if "visibility" in kwargs:
+        suite_kwargs["visibility"] = kwargs["visibility"]
+
+    native.test_suite(
+        name = name,
+        tests = [
+            name + ".both_pythons",
+            name + ".gevent",
+        ],
+        **suite_kwargs
+    )
index ad304f4..d8d18ea 100644 (file)
@@ -34,6 +34,9 @@ def well_known_proto_libs():
         "@com_google_protobuf//:wrappers_proto",
     ]
 
+def is_well_known(label):
+    return label in well_known_proto_libs()
+
 def get_proto_root(workspace_root):
     """Gets the root protobuf directory.
 
@@ -141,8 +144,18 @@ def get_plugin_args(
         ),
     ]
 
-def _get_staged_proto_file(context, source_file):
-    if source_file.dirname == context.label.package or \
+def get_staged_proto_file(label, context, source_file):
+    """Copies a proto file to the appropriate location if necessary.
+
+    Args:
+      label: The label of the rule using the .proto file.
+      context: The ctx object for the rule or aspect.
+      source_file: The original .proto file.
+
+    Returns:
+      The original proto file OR a new file in the staged location.
+    """
+    if source_file.dirname == label.package or \
        is_in_virtual_imports(source_file):
         # Current target and source_file are in same package
         return source_file
@@ -170,7 +183,7 @@ def protos_from_context(context):
     protos = []
     for src in context.attr.deps:
         for file in src[ProtoInfo].direct_sources:
-            protos.append(_get_staged_proto_file(context, file))
+            protos.append(get_staged_proto_file(context.label, context, file))
     return protos
 
 def includes_from_deps(deps):
index df067d3..b38672e 100644 (file)
@@ -21,42 +21,61 @@ load(
     "get_out_dir",
     "get_plugin_args",
     "get_proto_arguments",
+    "get_staged_proto_file",
     "includes_from_deps",
+    "is_well_known",
     "protos_from_context",
 )
 
 _GENERATED_PROTO_FORMAT = "{}_pb2.py"
 _GENERATED_GRPC_PROTO_FORMAT = "{}_pb2_grpc.py"
 
-def _generate_py_impl(context):
-    protos = protos_from_context(context)
-    includes = includes_from_deps(context.attr.deps)
+PyProtoInfo = provider(
+    "The Python outputs from the Protobuf compiler.",
+    fields = {
+        "py_info": "A PyInfo provider for the generated code.",
+        "generated_py_srcs": "The direct (not transitive) generated Python source files.",
+    },
+)
+
+def _merge_pyinfos(pyinfos):
+    return PyInfo(
+        transitive_sources = depset(transitive = [p.transitive_sources for p in pyinfos]),
+        imports = depset(transitive = [p.imports for p in pyinfos]),
+    )
+
+def _gen_py_aspect_impl(target, context):
+    # Early return for well-known protos.
+    if is_well_known(str(context.label)):
+        return [
+            PyProtoInfo(py_info = context.attr._protobuf_library[PyInfo]),
+        ]
+
+    protos = []
+    for p in target[ProtoInfo].direct_sources:
+        protos.append(get_staged_proto_file(target.label, context, p))
+
+    includes = depset(direct = protos, transitive = [target[ProtoInfo].transitive_imports])
     out_files = declare_out_files(protos, context, _GENERATED_PROTO_FORMAT)
+    generated_py_srcs = out_files
+
     tools = [context.executable._protoc]
 
     out_dir = get_out_dir(protos, context)
+
     arguments = ([
         "--python_out={}".format(out_dir.path),
     ] + [
         "--proto_path={}".format(get_include_directory(i))
-        for i in includes
+        for i in includes.to_list()
     ] + [
         "--proto_path={}".format(context.genfiles_dir.path),
     ])
-    if context.attr.plugin:
-        arguments += get_plugin_args(
-            context.executable.plugin,
-            [],
-            out_dir.path,
-            False,
-            context.attr.plugin.label.name,
-        )
-        tools.append(context.executable.plugin)
 
     arguments += get_proto_arguments(protos, context.genfiles_dir.path)
 
     context.actions.run(
-        inputs = protos + includes,
+        inputs = protos + includes.to_list(),
         tools = tools,
         outputs = out_files,
         executable = context.executable._protoc,
@@ -68,26 +87,77 @@ def _generate_py_impl(context):
     if out_dir.import_path:
         imports.append("%s/%s/%s" % (context.workspace_name, context.label.package, out_dir.import_path))
 
+    py_info = PyInfo(transitive_sources = depset(direct = out_files), imports = depset(direct = imports))
+    return PyProtoInfo(
+        py_info = _merge_pyinfos(
+            [
+                py_info,
+                context.attr._protobuf_library[PyInfo],
+            ] + [dep[PyProtoInfo].py_info for dep in context.rule.attr.deps],
+        ),
+        generated_py_srcs = generated_py_srcs,
+    )
+
+_gen_py_aspect = aspect(
+    implementation = _gen_py_aspect_impl,
+    attr_aspects = ["deps"],
+    fragments = ["py"],
+    attrs = {
+        "_protoc": attr.label(
+            default = Label("//external:protocol_compiler"),
+            providers = ["files_to_run"],
+            executable = True,
+            cfg = "host",
+        ),
+        "_protobuf_library": attr.label(
+            default = Label("@com_google_protobuf//:protobuf_python"),
+            providers = [PyInfo],
+        ),
+    },
+)
+
+def _generate_py_impl(context):
+    if (len(context.attr.deps) != 1):
+        fail("Can only compile a single proto at a time.")
+
+    py_sources = []
+
+    # If the proto_library this rule *directly* depends on is in another
+    # package, then we generate .py files to import them in this package. This
+    # behavior is needed to allow rearranging of import paths to make Bazel
+    # outputs align with native python workflows.
+    #
+    # Note that this approach is vulnerable to protoc defining __all__ or other
+    # symbols with __ prefixes that need to be directly imported. Since these
+    # names are likely to be reserved for private APIs, the risk is minimal.
+    if context.label.package != context.attr.deps[0].label.package:
+        for py_src in context.attr.deps[0][PyProtoInfo].generated_py_srcs:
+            reimport_py_file = context.actions.declare_file(py_src.basename)
+            py_sources.append(reimport_py_file)
+            import_line = "from %s import *" % py_src.short_path.replace("/", ".")[:-len(".py")]
+            context.actions.write(reimport_py_file, import_line)
+
+    # Collect output PyInfo provider.
+    imports = [context.label.package + "/" + i for i in context.attr.imports]
+    py_info = PyInfo(transitive_sources = depset(direct = py_sources), imports = depset(direct = imports))
+    out_pyinfo = _merge_pyinfos([py_info, context.attr.deps[0][PyProtoInfo].py_info])
+
+    runfiles = context.runfiles(files = out_pyinfo.transitive_sources.to_list()).merge(context.attr._protobuf_library[DefaultInfo].data_runfiles)
     return [
-        DefaultInfo(files = depset(direct = out_files)),
-        PyInfo(
-            transitive_sources = depset(),
-            imports = depset(direct = imports),
+        DefaultInfo(
+            files = out_pyinfo.transitive_sources,
+            runfiles = runfiles,
         ),
+        out_pyinfo,
     ]
 
-_generate_pb2_src = rule(
+py_proto_library = rule(
     attrs = {
         "deps": attr.label_list(
             mandatory = True,
             allow_empty = False,
             providers = [ProtoInfo],
-        ),
-        "plugin": attr.label(
-            mandatory = False,
-            executable = True,
-            providers = ["files_to_run"],
-            cfg = "host",
+            aspects = [_gen_py_aspect],
         ),
         "_protoc": attr.label(
             default = Label("//external:protocol_compiler"),
@@ -95,46 +165,15 @@ _generate_pb2_src = rule(
             executable = True,
             cfg = "host",
         ),
+        "_protobuf_library": attr.label(
+            default = Label("@com_google_protobuf//:protobuf_python"),
+            providers = [PyInfo],
+        ),
+        "imports": attr.string_list(),
     },
     implementation = _generate_py_impl,
 )
 
-def py_proto_library(
-        name,
-        deps,
-        plugin = None,
-        **kwargs):
-    """Generate python code for a protobuf.
-
-    Args:
-      name: The name of the target.
-      deps: A list of proto_library dependencies. Must contain a single element.
-      plugin: An optional custom protoc plugin to execute together with
-        generating the protobuf code.
-      **kwargs: Additional arguments to be supplied to the invocation of
-        py_library.
-    """
-    codegen_target = "_{}_codegen".format(name)
-    if len(deps) != 1:
-        fail("Can only compile a single proto at a time.")
-
-    _generate_pb2_src(
-        name = codegen_target,
-        deps = deps,
-        plugin = plugin,
-        **kwargs
-    )
-
-    native.py_library(
-        name = name,
-        srcs = [":{}".format(codegen_target)],
-        deps = [
-            "@com_google_protobuf//:protobuf_python",
-            ":{}".format(codegen_target),
-        ],
-        **kwargs
-    )
-
 def _generate_pb2_grpc_src_impl(context):
     protos = protos_from_context(context)
     includes = includes_from_deps(context.attr.deps)
@@ -151,15 +190,6 @@ def _generate_pb2_grpc_src_impl(context):
         out_dir.path,
         False,
     )
-    if context.attr.plugin:
-        arguments += get_plugin_args(
-            context.executable.plugin,
-            [],
-            out_dir.path,
-            False,
-            context.attr.plugin.label.name,
-        )
-        tools.append(context.executable.plugin)
 
     arguments += [
         "--proto_path={}".format(get_include_directory(i))
@@ -177,13 +207,22 @@ def _generate_pb2_grpc_src_impl(context):
         mnemonic = "ProtocInvocation",
     )
 
+    p = PyInfo(transitive_sources = depset(direct = out_files))
+    py_info = _merge_pyinfos(
+        [
+            p,
+            context.attr._grpc_library[PyInfo],
+        ] + [dep[PyInfo] for dep in context.attr.py_deps],
+    )
+
+    runfiles = context.runfiles(files = out_files, transitive_files = py_info.transitive_sources).merge(context.attr._grpc_library[DefaultInfo].data_runfiles)
+
     return [
-        DefaultInfo(files = depset(direct = out_files)),
-        PyInfo(
-            transitive_sources = depset(),
-            # Imports are already configured by the generated py impl
-            imports = depset(),
+        DefaultInfo(
+            files = depset(direct = out_files),
+            runfiles = runfiles,
         ),
+        py_info,
     ]
 
 _generate_pb2_grpc_src = rule(
@@ -193,13 +232,12 @@ _generate_pb2_grpc_src = rule(
             allow_empty = False,
             providers = [ProtoInfo],
         ),
-        "strip_prefixes": attr.string_list(),
-        "plugin": attr.label(
-            mandatory = False,
-            executable = True,
-            providers = ["files_to_run"],
-            cfg = "host",
+        "py_deps": attr.label_list(
+            mandatory = True,
+            allow_empty = False,
+            providers = [PyInfo],
         ),
+        "strip_prefixes": attr.string_list(),
         "_grpc_plugin": attr.label(
             executable = True,
             providers = ["files_to_run"],
@@ -212,6 +250,10 @@ _generate_pb2_grpc_src = rule(
             cfg = "host",
             default = Label("//external:protocol_compiler"),
         ),
+        "_grpc_library": attr.label(
+            default = Label("//src/python/grpcio/grpc:grpcio"),
+            providers = [PyInfo],
+        ),
     },
     implementation = _generate_pb2_grpc_src_impl,
 )
@@ -220,7 +262,6 @@ def py_grpc_library(
         name,
         srcs,
         deps,
-        plugin = None,
         strip_prefixes = [],
         **kwargs):
     """Generate python code for gRPC services defined in a protobuf.
@@ -235,12 +276,9 @@ def py_grpc_library(
         stripped from the beginning of foo_pb2 modules imported by the
         generated stubs. This is useful in combination with the `imports`
         attribute of the `py_library` rule.
-      plugin: An optional custom protoc plugin to execute together with
-        generating the gRPC code.
       **kwargs: Additional arguments to be supplied to the invocation of
         py_library.
     """
-    codegen_grpc_target = "_{}_grpc_codegen".format(name)
     if len(srcs) != 1:
         fail("Can only compile a single proto at a time.")
 
@@ -248,26 +286,14 @@ def py_grpc_library(
         fail("Deps must have length 1.")
 
     _generate_pb2_grpc_src(
-        name = codegen_grpc_target,
+        name = name,
         deps = srcs,
+        py_deps = deps,
         strip_prefixes = strip_prefixes,
-        plugin = plugin,
-        **kwargs
-    )
-
-    native.py_library(
-        name = name,
-        srcs = [
-            ":{}".format(codegen_grpc_target),
-        ],
-        deps = [
-            Label("//src/python/grpcio/grpc:grpcio"),
-        ] + deps + [
-            ":{}".format(codegen_grpc_target),
-        ],
         **kwargs
     )
 
+# TODO(https://github.com/grpc/grpc/issues/27543): Remove once Python 2 is no longer supported.
 def py2and3_test(
         name,
         py_test = native.py_test,
@@ -297,7 +323,7 @@ def py2and3_test(
         suite_kwargs["visibility"] = kwargs["visibility"]
 
     native.test_suite(
-        name = name,
+        name = name + ".both_pythons",
         tests = names,
         **suite_kwargs
     )
index e7d359c..b0f0e53 100644 (file)
 load("@rules_proto//proto:defs.bzl", "proto_library")
 load(
     "@com_github_grpc_grpc//bazel:python_rules.bzl",
-    "py2and3_test",
     "py_grpc_library",
     "py_proto_library",
 )
 
-package(default_testonly = 1)
+package(
+    default_testonly = 1,
+)
 
 proto_library(
     name = "helloworld_proto",
@@ -54,10 +55,11 @@ py_proto_library(
     deps = ["@com_google_protobuf//:timestamp_proto"],
 )
 
-py2and3_test(
+py_test(
     name = "import_test",
     srcs = ["helloworld.py"],
     main = "helloworld.py",
+    python_version = "PY3",
     deps = [
         ":duration_py_pb2",
         ":helloworld_py_pb2",
@@ -82,10 +84,8 @@ proto_library(
     ],
 )
 
-# Also test the custom plugin execution parameter
 py_proto_library(
     name = "helloworld_moved_py_pb2",
-    plugin = ":dummy_plugin",
     deps = [":helloworld_moved_proto"],
 )
 
@@ -95,10 +95,11 @@ py_grpc_library(
     deps = [":helloworld_moved_py_pb2"],
 )
 
-py2and3_test(
+py_test(
     name = "import_moved_test",
     srcs = ["helloworld_moved.py"],
     main = "helloworld_moved.py",
+    python_version = "PY3",
     deps = [
         ":duration_py_pb2",
         ":helloworld_moved_py_pb2",
@@ -107,10 +108,42 @@ py2and3_test(
     ],
 )
 
-py_binary(
-    name = "dummy_plugin",
-    srcs = [":dummy_plugin.py"],
+# Test that a py_proto_library wrapping a proto_library in another package can
+# be imported from the package that contains the py_proto_library *AND* from
+# the package that contains the proto_library.
+py_proto_library(
+    name = "subpackage_py_pb2",
+    deps = ["//in_subpackage:subpackage_proto"],
+)
+
+py_test(
+    name = "import_from_this_package_subpackage_test",
+    srcs = ["import_from_this_package.py"],
+    main = "import_from_this_package.py",
+    python_version = "PY3",
     deps = [
-        "@com_google_protobuf//:protobuf_python",
+        ":subpackage_py_pb2",
+    ],
+)
+
+py_test(
+    name = "import_from_proto_library_package_test",
+    srcs = ["import_from_proto_library_package.py"],
+    main = "import_from_proto_library_package.py",
+    python_version = "PY3",
+    deps = [
+        ":subpackage_py_pb2",
+    ],
+)
+
+# Test that a py_proto_library can be successfully imported without requiring
+# explicit dependencies on unused dependencies of the generated code.
+py_test(
+    name = "transitive_proto_dep_test",
+    srcs = ["transitive_proto_dep.py"],
+    main = "transitive_proto_dep.py",
+    python_version = "PY3",
+    deps = [
+        ":helloworld_py_pb2",
     ],
 )
diff --git a/bazel/test/python_test_repo/dummy_plugin.py b/bazel/test/python_test_repo/dummy_plugin.py
deleted file mode 100644 (file)
index a7e3a01..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-# Copyright 2019 the gRPC authors.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""A dummy plugin for testing"""
-
-import sys
-
-from google.protobuf.compiler.plugin_pb2 import CodeGeneratorRequest
-from google.protobuf.compiler.plugin_pb2 import CodeGeneratorResponse
-
-
-def main(input_file=sys.stdin, output_file=sys.stdout):
-    request = CodeGeneratorRequest.FromString(input_file.buffer.read())
-    answer = []
-    for fname in request.file_to_generate:
-        answer.append(CodeGeneratorResponse.File(
-            name=fname.replace('.proto', '_pb2.py'),
-            insertion_point='module_scope',
-            content="# Hello {}, I'm a dummy plugin!".format(fname),
-        ))
-
-    cgr = CodeGeneratorResponse(file=answer)
-    output_file.buffer.write(cgr.SerializeToString())
-
-
-if __name__ == '__main__':
-    main()
diff --git a/bazel/test/python_test_repo/import_from_proto_library_package.py b/bazel/test/python_test_repo/import_from_proto_library_package.py
new file mode 100644 (file)
index 0000000..9a7e085
--- /dev/null
@@ -0,0 +1,18 @@
+# Copyright 2021 the gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""A trivial executable that imports Protobuf generated code where the
+proto_library and py_proto_library are in different Bazel packages.
+"""
+
+import in_subpackage.subpackage_pb2
diff --git a/bazel/test/python_test_repo/import_from_this_package.py b/bazel/test/python_test_repo/import_from_this_package.py
new file mode 100644 (file)
index 0000000..1191ff2
--- /dev/null
@@ -0,0 +1,18 @@
+# Copyright 2021 the gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""A trivial executable that imports Protobuf generated code where the
+proto_library and py_proto_library are in different Bazel packages.
+"""
+
+import subpackage_pb2
diff --git a/bazel/test/python_test_repo/in_subpackage/BUILD b/bazel/test/python_test_repo/in_subpackage/BUILD
new file mode 100644 (file)
index 0000000..d656bda
--- /dev/null
@@ -0,0 +1,27 @@
+# gRPC Bazel BUILD file.
+#
+# Copyright 2021 The gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+load("@rules_proto//proto:defs.bzl", "proto_library")
+
+package(
+    default_testonly = 1,
+    default_visibility = ["//:__subpackages__"],
+)
+
+proto_library(
+    name = "subpackage_proto",
+    srcs = ["subpackage.proto"],
+)
diff --git a/bazel/test/python_test_repo/in_subpackage/subpackage.proto b/bazel/test/python_test_repo/in_subpackage/subpackage.proto
new file mode 100644 (file)
index 0000000..a3325b0
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2021 The gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+syntax = "proto3";
+
+option java_multiple_files = true;
+option java_package = "io.grpc.examples.subpackage";
+option java_outer_classname = "SubpackageProto";
+option objc_class_prefix = "SP";
+
+package subpackage;
+
+message Subpackaged {
+  string name = 1;
+}
+
index 8995a73..2d61033 100644 (file)
@@ -17,7 +17,6 @@
 load("@rules_proto//proto:defs.bzl", "proto_library")
 load(
     "@com_github_grpc_grpc//bazel:python_rules.bzl",
-    "py2and3_test",
     "py_grpc_library",
     "py_proto_library",
 )
@@ -124,40 +123,44 @@ py_grpc_library(
 # Both Import and Strip
 # bazel-out/darwin-fastbuild/bin/namespaced/upper/example/_virtual_imports/namespaced_example_proto/upper/example/namespaced_example_pb2.py
 
-py2and3_test(
-    "import_no_strip_test",
+py_test(
+    name = "import_no_strip_test",
     srcs = ["import_no_strip_test.py"],
     main = "import_no_strip_test.py",
+    python_version = "PY3",
     deps = [
         ":import_no_strip_py_pb2",
         ":import_no_strip_py_pb2_grpc",
     ],
 )
 
-py2and3_test(
-    "import_strip_test",
+py_test(
+    name = "import_strip_test",
     srcs = ["import_strip_test.py"],
     main = "import_strip_test.py",
+    python_version = "PY3",
     deps = [
         ":import_strip_py_pb2",
         ":import_strip_py_pb2_grpc",
     ],
 )
 
-py2and3_test(
-    "no_import_no_strip_test",
+py_test(
+    name = "no_import_no_strip_test",
     srcs = ["no_import_no_strip_test.py"],
     main = "no_import_no_strip_test.py",
+    python_version = "PY3",
     deps = [
         ":no_import_no_strip_py_pb2",
         ":no_import_no_strip_py_pb2_grpc",
     ],
 )
 
-py2and3_test(
-    "no_import_strip_test",
+py_test(
+    name = "no_import_strip_test",
     srcs = ["no_import_strip_test.py"],
     main = "no_import_strip_test.py",
+    python_version = "PY3",
     deps = [
         ":no_import_strip_py_pb2",
         ":no_import_strip_py_pb2_grpc",
diff --git a/bazel/test/python_test_repo/transitive_proto_dep.py b/bazel/test/python_test_repo/transitive_proto_dep.py
new file mode 100644 (file)
index 0000000..23d9b0c
--- /dev/null
@@ -0,0 +1,17 @@
+# Copyright 2021 the gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""A trivial executable that imports helloworld_pb2, but NOT its transitive
+dependencies."""
+
+import helloworld_pb2
index 274fe51..a4805db 100755 (executable)
@@ -69,6 +69,10 @@ upload github.com/bazelbuild/bazel/releases/download/3.7.1/bazel-3.7.1-linux-x86
 upload github.com/bazelbuild/bazel/releases/download/3.7.1/bazel-3.7.1-darwin-x86_64
 upload github.com/bazelbuild/bazel/releases/download/3.7.1/bazel-3.7.1-windows-x86_64.exe
 
+upload github.com/bazelbuild/bazel/releases/download/4.2.1/bazel-4.2.1-linux-x86_64
+upload github.com/bazelbuild/bazel/releases/download/4.2.1/bazel-4.2.1-darwin-x86_64
+upload github.com/bazelbuild/bazel/releases/download/4.2.1/bazel-4.2.1-windows-x86_64.exe
+
 # Collect the github archives to mirror from grpc_deps.bzl
 grep -o '"https://github.com/[^"]*"' bazel/grpc_deps.bzl | sed 's/^"https:\/\///' | sed 's/"$//' | while read -r line ; do
     echo "Updating mirror for ${line}"
index e09b30b..9881310 100644 (file)
@@ -122,7 +122,6 @@ libs:
   - test/core/end2end/tests/stream_compression_ping_pong_streaming.cc
   - test/core/end2end/tests/streaming_error_response.cc
   - test/core/end2end/tests/trailing_metadata.cc
-  - test/core/end2end/tests/workaround_cronet_compression.cc
   - test/core/end2end/tests/write_buffering.cc
   - test/core/end2end/tests/write_buffering_at_end.cc
   - test/core/util/test_lb_policies.cc
@@ -250,7 +249,6 @@ libs:
   - test/core/end2end/tests/stream_compression_ping_pong_streaming.cc
   - test/core/end2end/tests/streaming_error_response.cc
   - test/core/end2end/tests/trailing_metadata.cc
-  - test/core/end2end/tests/workaround_cronet_compression.cc
   - test/core/end2end/tests/write_buffering.cc
   - test/core/end2end/tests/write_buffering_at_end.cc
   - test/core/util/test_lb_policies.cc
@@ -421,8 +419,9 @@ libs:
   - include/grpc/compression.h
   - include/grpc/event_engine/endpoint_config.h
   - include/grpc/event_engine/event_engine.h
+  - include/grpc/event_engine/internal/memory_allocator_impl.h
+  - include/grpc/event_engine/memory_allocator.h
   - include/grpc/event_engine/port.h
-  - include/grpc/event_engine/slice_allocator.h
   - include/grpc/fork.h
   - include/grpc/grpc.h
   - include/grpc/grpc_posix.h
@@ -477,12 +476,10 @@ libs:
   - src/core/ext/filters/client_channel/retry_service_config.h
   - src/core/ext/filters/client_channel/retry_throttle.h
   - src/core/ext/filters/client_channel/server_address.h
-  - src/core/ext/filters/client_channel/service_config.h
-  - src/core/ext/filters/client_channel/service_config_call_data.h
-  - src/core/ext/filters/client_channel/service_config_parser.h
   - src/core/ext/filters/client_channel/subchannel.h
   - src/core/ext/filters/client_channel/subchannel_interface.h
   - src/core/ext/filters/client_channel/subchannel_pool_interface.h
+  - src/core/ext/filters/client_idle/idle_filter_state.h
   - src/core/ext/filters/deadline/deadline_filter.h
   - src/core/ext/filters/fault_injection/fault_injection_filter.h
   - src/core/ext/filters/fault_injection/service_config_parser.h
@@ -493,15 +490,14 @@ libs:
   - src/core/ext/filters/http/server/http_server_filter.h
   - src/core/ext/filters/max_age/max_age_filter.h
   - src/core/ext/filters/message_size/message_size_filter.h
-  - src/core/ext/filters/workarounds/workaround_cronet_compression_filter.h
-  - src/core/ext/filters/workarounds/workaround_utils.h
+  - src/core/ext/service_config/service_config.h
+  - src/core/ext/service_config/service_config_call_data.h
+  - src/core/ext/service_config/service_config_parser.h
   - src/core/ext/transport/chttp2/alpn/alpn.h
-  - src/core/ext/transport/chttp2/client/authority.h
   - src/core/ext/transport/chttp2/client/chttp2_connector.h
   - src/core/ext/transport/chttp2/server/chttp2_server.h
   - src/core/ext/transport/chttp2/transport/bin_decoder.h
   - src/core/ext/transport/chttp2/transport/bin_encoder.h
-  - src/core/ext/transport/chttp2/transport/chttp2_slice_allocator.h
   - src/core/ext/transport/chttp2/transport/chttp2_transport.h
   - src/core/ext/transport/chttp2/transport/context_list.h
   - src/core/ext/transport/chttp2/transport/flow_control.h
@@ -521,7 +517,6 @@ libs:
   - src/core/ext/transport/chttp2/transport/hpack_utils.h
   - src/core/ext/transport/chttp2/transport/http2_settings.h
   - src/core/ext/transport/chttp2/transport/huffsyms.h
-  - src/core/ext/transport/chttp2/transport/incoming_metadata.h
   - src/core/ext/transport/chttp2/transport/internal.h
   - src/core/ext/transport/chttp2/transport/popularity_count.h
   - src/core/ext/transport/chttp2/transport/stream_map.h
@@ -604,20 +599,22 @@ libs:
   - src/core/ext/upb-generated/src/proto/grpc/gcp/transport_security_common.upb.h
   - src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.h
   - src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.h
+  - src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls.upb.h
   - src/core/ext/upb-generated/udpa/annotations/migrate.upb.h
   - src/core/ext/upb-generated/udpa/annotations/security.upb.h
   - src/core/ext/upb-generated/udpa/annotations/sensitive.upb.h
   - src/core/ext/upb-generated/udpa/annotations/status.upb.h
   - src/core/ext/upb-generated/udpa/annotations/versioning.upb.h
-  - src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h
-  - src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.h
   - src/core/ext/upb-generated/validate/validate.upb.h
+  - src/core/ext/upb-generated/xds/annotations/v3/status.upb.h
   - src/core/ext/upb-generated/xds/core/v3/authority.upb.h
   - src/core/ext/upb-generated/xds/core/v3/collection_entry.upb.h
   - src/core/ext/upb-generated/xds/core/v3/context_params.upb.h
   - src/core/ext/upb-generated/xds/core/v3/resource.upb.h
   - src/core/ext/upb-generated/xds/core/v3/resource_locator.upb.h
   - src/core/ext/upb-generated/xds/core/v3/resource_name.upb.h
+  - src/core/ext/upb-generated/xds/data/orca/v3/orca_load_report.upb.h
+  - src/core/ext/upb-generated/xds/type/v3/typed_struct.upb.h
   - src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.h
   - src/core/ext/upbdefs-generated/envoy/annotations/deprecation.upbdefs.h
   - src/core/ext/upbdefs-generated/envoy/annotations/resource.upbdefs.h
@@ -703,14 +700,15 @@ libs:
   - src/core/ext/upbdefs-generated/udpa/annotations/sensitive.upbdefs.h
   - src/core/ext/upbdefs-generated/udpa/annotations/status.upbdefs.h
   - src/core/ext/upbdefs-generated/udpa/annotations/versioning.upbdefs.h
-  - src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.h
   - src/core/ext/upbdefs-generated/validate/validate.upbdefs.h
+  - src/core/ext/upbdefs-generated/xds/annotations/v3/status.upbdefs.h
   - src/core/ext/upbdefs-generated/xds/core/v3/authority.upbdefs.h
   - src/core/ext/upbdefs-generated/xds/core/v3/collection_entry.upbdefs.h
   - src/core/ext/upbdefs-generated/xds/core/v3/context_params.upbdefs.h
   - src/core/ext/upbdefs-generated/xds/core/v3/resource.upbdefs.h
   - src/core/ext/upbdefs-generated/xds/core/v3/resource_locator.upbdefs.h
   - src/core/ext/upbdefs-generated/xds/core/v3/resource_name.upbdefs.h
+  - src/core/ext/upbdefs-generated/xds/type/v3/typed_struct.upbdefs.h
   - src/core/ext/xds/certificate_provider_factory.h
   - src/core/ext/xds/certificate_provider_registry.h
   - src/core/ext/xds/certificate_provider_store.h
@@ -719,6 +717,7 @@ libs:
   - src/core/ext/xds/xds_bootstrap.h
   - src/core/ext/xds/xds_certificate_provider.h
   - src/core/ext/xds/xds_channel_args.h
+  - src/core/ext/xds/xds_channel_stack_modifier.h
   - src/core/ext/xds/xds_client.h
   - src/core/ext/xds/xds_client_stats.h
   - src/core/ext/xds/xds_http_fault_filter.h
@@ -755,12 +754,14 @@ libs:
   - src/core/lib/event_engine/sockaddr.h
   - src/core/lib/gprpp/atomic_utils.h
   - src/core/lib/gprpp/bitset.h
+  - src/core/lib/gprpp/chunked_vector.h
   - src/core/lib/gprpp/dual_ref_counted.h
   - src/core/lib/gprpp/match.h
   - src/core/lib/gprpp/orphanable.h
   - src/core/lib/gprpp/overload.h
   - src/core/lib/gprpp/ref_counted.h
   - src/core/lib/gprpp/ref_counted_ptr.h
+  - src/core/lib/gprpp/table.h
   - src/core/lib/http/format_request.h
   - src/core/lib/http/httpcli.h
   - src/core/lib/http/parser.h
@@ -837,7 +838,6 @@ libs:
   - src/core/lib/iomgr/timer_generic.h
   - src/core/lib/iomgr/timer_heap.h
   - src/core/lib/iomgr/timer_manager.h
-  - src/core/lib/iomgr/udp_server.h
   - src/core/lib/iomgr/unix_sockets_posix.h
   - src/core/lib/iomgr/wakeup_fd_pipe.h
   - src/core/lib/iomgr/wakeup_fd_posix.h
@@ -895,9 +895,14 @@ libs:
   - src/core/lib/slice/b64.h
   - src/core/lib/slice/percent_encoding.h
   - src/core/lib/slice/slice_internal.h
+  - src/core/lib/slice/slice_refcount.h
+  - src/core/lib/slice/slice_refcount_base.h
+  - src/core/lib/slice/slice_split.h
   - src/core/lib/slice/slice_string_helpers.h
   - src/core/lib/slice/slice_utils.h
+  - src/core/lib/slice/static_slice.h
   - src/core/lib/surface/api_trace.h
+  - src/core/lib/surface/builtins.h
   - src/core/lib/surface/call.h
   - src/core/lib/surface/call_test_only.h
   - src/core/lib/surface/channel.h
@@ -910,7 +915,6 @@ libs:
   - src/core/lib/surface/lame_client.h
   - src/core/lib/surface/server.h
   - src/core/lib/surface/validate_metadata.h
-  - src/core/lib/transport/authority_override.h
   - src/core/lib/transport/bdp_estimator.h
   - src/core/lib/transport/byte_stream.h
   - src/core/lib/transport/connectivity_state.h
@@ -918,6 +922,7 @@ libs:
   - src/core/lib/transport/http2_errors.h
   - src/core/lib/transport/metadata.h
   - src/core/lib/transport/metadata_batch.h
+  - src/core/lib/transport/parsed_metadata.h
   - src/core/lib/transport/pid_controller.h
   - src/core/lib/transport/static_metadata.h
   - src/core/lib/transport/status_conversion.h
@@ -981,6 +986,7 @@ libs:
   - src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc
   - src/core/ext/filters/client_channel/lb_policy/priority/priority.cc
   - src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc
+  - src/core/ext/filters/client_channel/lb_policy/rls/rls.cc
   - src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc
   - src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc
   - src/core/ext/filters/client_channel/lb_policy/xds/cds.cc
@@ -991,6 +997,7 @@ libs:
   - src/core/ext/filters/client_channel/local_subchannel_pool.cc
   - src/core/ext/filters/client_channel/proxy_mapper_registry.cc
   - src/core/ext/filters/client_channel/resolver.cc
+  - src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc
   - src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc
   - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_event_engine.cc
   - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc
@@ -1011,12 +1018,11 @@ libs:
   - src/core/ext/filters/client_channel/retry_service_config.cc
   - src/core/ext/filters/client_channel/retry_throttle.cc
   - src/core/ext/filters/client_channel/server_address.cc
-  - src/core/ext/filters/client_channel/service_config.cc
   - src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc
-  - src/core/ext/filters/client_channel/service_config_parser.cc
   - src/core/ext/filters/client_channel/subchannel.cc
   - src/core/ext/filters/client_channel/subchannel_pool_interface.cc
   - src/core/ext/filters/client_idle/client_idle_filter.cc
+  - src/core/ext/filters/client_idle/idle_filter_state.cc
   - src/core/ext/filters/deadline/deadline_filter.cc
   - src/core/ext/filters/fault_injection/fault_injection_filter.cc
   - src/core/ext/filters/fault_injection/service_config_parser.cc
@@ -1028,10 +1034,9 @@ libs:
   - src/core/ext/filters/http/server/http_server_filter.cc
   - src/core/ext/filters/max_age/max_age_filter.cc
   - src/core/ext/filters/message_size/message_size_filter.cc
-  - src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc
-  - src/core/ext/filters/workarounds/workaround_utils.cc
+  - src/core/ext/service_config/service_config.cc
+  - src/core/ext/service_config/service_config_parser.cc
   - src/core/ext/transport/chttp2/alpn/alpn.cc
-  - src/core/ext/transport/chttp2/client/authority.cc
   - src/core/ext/transport/chttp2/client/chttp2_connector.cc
   - src/core/ext/transport/chttp2/client/insecure/channel_create.cc
   - src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc
@@ -1043,7 +1048,6 @@ libs:
   - src/core/ext/transport/chttp2/transport/bin_decoder.cc
   - src/core/ext/transport/chttp2/transport/bin_encoder.cc
   - src/core/ext/transport/chttp2/transport/chttp2_plugin.cc
-  - src/core/ext/transport/chttp2/transport/chttp2_slice_allocator.cc
   - src/core/ext/transport/chttp2/transport/chttp2_transport.cc
   - src/core/ext/transport/chttp2/transport/context_list.cc
   - src/core/ext/transport/chttp2/transport/flow_control.cc
@@ -1060,7 +1064,6 @@ libs:
   - src/core/ext/transport/chttp2/transport/hpack_utils.cc
   - src/core/ext/transport/chttp2/transport/http2_settings.cc
   - src/core/ext/transport/chttp2/transport/huffsyms.cc
-  - src/core/ext/transport/chttp2/transport/incoming_metadata.cc
   - src/core/ext/transport/chttp2/transport/parsing.cc
   - src/core/ext/transport/chttp2/transport/stream_lists.cc
   - src/core/ext/transport/chttp2/transport/stream_map.cc
@@ -1145,20 +1148,22 @@ libs:
   - src/core/ext/upb-generated/src/proto/grpc/gcp/transport_security_common.upb.c
   - src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.c
   - src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c
+  - src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls.upb.c
   - src/core/ext/upb-generated/udpa/annotations/migrate.upb.c
   - src/core/ext/upb-generated/udpa/annotations/security.upb.c
   - src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c
   - src/core/ext/upb-generated/udpa/annotations/status.upb.c
   - src/core/ext/upb-generated/udpa/annotations/versioning.upb.c
-  - src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c
-  - src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.c
   - src/core/ext/upb-generated/validate/validate.upb.c
+  - src/core/ext/upb-generated/xds/annotations/v3/status.upb.c
   - src/core/ext/upb-generated/xds/core/v3/authority.upb.c
   - src/core/ext/upb-generated/xds/core/v3/collection_entry.upb.c
   - src/core/ext/upb-generated/xds/core/v3/context_params.upb.c
   - src/core/ext/upb-generated/xds/core/v3/resource.upb.c
   - src/core/ext/upb-generated/xds/core/v3/resource_locator.upb.c
   - src/core/ext/upb-generated/xds/core/v3/resource_name.upb.c
+  - src/core/ext/upb-generated/xds/data/orca/v3/orca_load_report.upb.c
+  - src/core/ext/upb-generated/xds/type/v3/typed_struct.upb.c
   - src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.c
   - src/core/ext/upbdefs-generated/envoy/annotations/deprecation.upbdefs.c
   - src/core/ext/upbdefs-generated/envoy/annotations/resource.upbdefs.c
@@ -1244,20 +1249,22 @@ libs:
   - src/core/ext/upbdefs-generated/udpa/annotations/sensitive.upbdefs.c
   - src/core/ext/upbdefs-generated/udpa/annotations/status.upbdefs.c
   - src/core/ext/upbdefs-generated/udpa/annotations/versioning.upbdefs.c
-  - src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.c
   - src/core/ext/upbdefs-generated/validate/validate.upbdefs.c
+  - src/core/ext/upbdefs-generated/xds/annotations/v3/status.upbdefs.c
   - src/core/ext/upbdefs-generated/xds/core/v3/authority.upbdefs.c
   - src/core/ext/upbdefs-generated/xds/core/v3/collection_entry.upbdefs.c
   - src/core/ext/upbdefs-generated/xds/core/v3/context_params.upbdefs.c
   - src/core/ext/upbdefs-generated/xds/core/v3/resource.upbdefs.c
   - src/core/ext/upbdefs-generated/xds/core/v3/resource_locator.upbdefs.c
   - src/core/ext/upbdefs-generated/xds/core/v3/resource_name.upbdefs.c
+  - src/core/ext/upbdefs-generated/xds/type/v3/typed_struct.upbdefs.c
   - src/core/ext/xds/certificate_provider_registry.cc
   - src/core/ext/xds/certificate_provider_store.cc
   - src/core/ext/xds/file_watcher_certificate_provider_factory.cc
   - src/core/ext/xds/xds_api.cc
   - src/core/ext/xds/xds_bootstrap.cc
   - src/core/ext/xds/xds_certificate_provider.cc
+  - src/core/ext/xds/xds_channel_stack_modifier.cc
   - src/core/ext/xds/xds_client.cc
   - src/core/ext/xds/xds_client_stats.cc
   - src/core/ext/xds/xds_http_fault_filter.cc
@@ -1383,7 +1390,6 @@ libs:
   - src/core/lib/iomgr/timer_generic.cc
   - src/core/lib/iomgr/timer_heap.cc
   - src/core/lib/iomgr/timer_manager.cc
-  - src/core/lib/iomgr/udp_server.cc
   - src/core/lib/iomgr/unix_sockets_posix.cc
   - src/core/lib/iomgr/unix_sockets_posix_noop.cc
   - src/core/lib/iomgr/wakeup_fd_eventfd.cc
@@ -1453,10 +1459,15 @@ libs:
   - src/core/lib/slice/b64.cc
   - src/core/lib/slice/percent_encoding.cc
   - src/core/lib/slice/slice.cc
+  - src/core/lib/slice/slice_api.cc
   - src/core/lib/slice/slice_buffer.cc
   - src/core/lib/slice/slice_intern.cc
+  - src/core/lib/slice/slice_refcount.cc
+  - src/core/lib/slice/slice_split.cc
   - src/core/lib/slice/slice_string_helpers.cc
+  - src/core/lib/slice/static_slice.cc
   - src/core/lib/surface/api_trace.cc
+  - src/core/lib/surface/builtins.cc
   - src/core/lib/surface/byte_buffer.cc
   - src/core/lib/surface/byte_buffer_reader.cc
   - src/core/lib/surface/call.cc
@@ -1476,7 +1487,6 @@ libs:
   - src/core/lib/surface/server.cc
   - src/core/lib/surface/validate_metadata.cc
   - src/core/lib/surface/version.cc
-  - src/core/lib/transport/authority_override.cc
   - src/core/lib/transport/bdp_estimator.cc
   - src/core/lib/transport/byte_stream.cc
   - src/core/lib/transport/connectivity_state.cc
@@ -1523,8 +1533,10 @@ libs:
   - absl/container:flat_hash_map
   - absl/container:inlined_vector
   - absl/functional:bind_front
+  - absl/hash:hash
   - absl/status:statusor
   - absl/types:variant
+  - absl/utility:utility
   - gpr
   - libssl
   - address_sorting
@@ -1661,8 +1673,9 @@ libs:
   - include/grpc/compression.h
   - include/grpc/event_engine/endpoint_config.h
   - include/grpc/event_engine/event_engine.h
+  - include/grpc/event_engine/internal/memory_allocator_impl.h
+  - include/grpc/event_engine/memory_allocator.h
   - include/grpc/event_engine/port.h
-  - include/grpc/event_engine/slice_allocator.h
   - include/grpc/fork.h
   - include/grpc/grpc.h
   - include/grpc/grpc_posix.h
@@ -1713,12 +1726,10 @@ libs:
   - src/core/ext/filters/client_channel/retry_service_config.h
   - src/core/ext/filters/client_channel/retry_throttle.h
   - src/core/ext/filters/client_channel/server_address.h
-  - src/core/ext/filters/client_channel/service_config.h
-  - src/core/ext/filters/client_channel/service_config_call_data.h
-  - src/core/ext/filters/client_channel/service_config_parser.h
   - src/core/ext/filters/client_channel/subchannel.h
   - src/core/ext/filters/client_channel/subchannel_interface.h
   - src/core/ext/filters/client_channel/subchannel_pool_interface.h
+  - src/core/ext/filters/client_idle/idle_filter_state.h
   - src/core/ext/filters/deadline/deadline_filter.h
   - src/core/ext/filters/fault_injection/fault_injection_filter.h
   - src/core/ext/filters/fault_injection/service_config_parser.h
@@ -1729,15 +1740,14 @@ libs:
   - src/core/ext/filters/http/server/http_server_filter.h
   - src/core/ext/filters/max_age/max_age_filter.h
   - src/core/ext/filters/message_size/message_size_filter.h
-  - src/core/ext/filters/workarounds/workaround_cronet_compression_filter.h
-  - src/core/ext/filters/workarounds/workaround_utils.h
+  - src/core/ext/service_config/service_config.h
+  - src/core/ext/service_config/service_config_call_data.h
+  - src/core/ext/service_config/service_config_parser.h
   - src/core/ext/transport/chttp2/alpn/alpn.h
-  - src/core/ext/transport/chttp2/client/authority.h
   - src/core/ext/transport/chttp2/client/chttp2_connector.h
   - src/core/ext/transport/chttp2/server/chttp2_server.h
   - src/core/ext/transport/chttp2/transport/bin_decoder.h
   - src/core/ext/transport/chttp2/transport/bin_encoder.h
-  - src/core/ext/transport/chttp2/transport/chttp2_slice_allocator.h
   - src/core/ext/transport/chttp2/transport/chttp2_transport.h
   - src/core/ext/transport/chttp2/transport/context_list.h
   - src/core/ext/transport/chttp2/transport/flow_control.h
@@ -1757,7 +1767,6 @@ libs:
   - src/core/ext/transport/chttp2/transport/hpack_utils.h
   - src/core/ext/transport/chttp2/transport/http2_settings.h
   - src/core/ext/transport/chttp2/transport/huffsyms.h
-  - src/core/ext/transport/chttp2/transport/incoming_metadata.h
   - src/core/ext/transport/chttp2/transport/internal.h
   - src/core/ext/transport/chttp2/transport/popularity_count.h
   - src/core/ext/transport/chttp2/transport/stream_map.h
@@ -1765,8 +1774,8 @@ libs:
   - src/core/ext/transport/inproc/inproc_transport.h
   - src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.h
   - src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.h
-  - src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h
   - src/core/ext/upb-generated/validate/validate.upb.h
+  - src/core/ext/upb-generated/xds/data/orca/v3/orca_load_report.upb.h
   - src/core/lib/address_utils/parse_address.h
   - src/core/lib/address_utils/sockaddr_utils.h
   - src/core/lib/avl/avl.h
@@ -1799,12 +1808,14 @@ libs:
   - src/core/lib/event_engine/sockaddr.h
   - src/core/lib/gprpp/atomic_utils.h
   - src/core/lib/gprpp/bitset.h
+  - src/core/lib/gprpp/chunked_vector.h
   - src/core/lib/gprpp/dual_ref_counted.h
   - src/core/lib/gprpp/match.h
   - src/core/lib/gprpp/orphanable.h
   - src/core/lib/gprpp/overload.h
   - src/core/lib/gprpp/ref_counted.h
   - src/core/lib/gprpp/ref_counted_ptr.h
+  - src/core/lib/gprpp/table.h
   - src/core/lib/http/format_request.h
   - src/core/lib/http/httpcli.h
   - src/core/lib/http/parser.h
@@ -1881,7 +1892,6 @@ libs:
   - src/core/lib/iomgr/timer_generic.h
   - src/core/lib/iomgr/timer_heap.h
   - src/core/lib/iomgr/timer_manager.h
-  - src/core/lib/iomgr/udp_server.h
   - src/core/lib/iomgr/unix_sockets_posix.h
   - src/core/lib/iomgr/wakeup_fd_pipe.h
   - src/core/lib/iomgr/wakeup_fd_posix.h
@@ -1891,9 +1901,14 @@ libs:
   - src/core/lib/slice/b64.h
   - src/core/lib/slice/percent_encoding.h
   - src/core/lib/slice/slice_internal.h
+  - src/core/lib/slice/slice_refcount.h
+  - src/core/lib/slice/slice_refcount_base.h
+  - src/core/lib/slice/slice_split.h
   - src/core/lib/slice/slice_string_helpers.h
   - src/core/lib/slice/slice_utils.h
+  - src/core/lib/slice/static_slice.h
   - src/core/lib/surface/api_trace.h
+  - src/core/lib/surface/builtins.h
   - src/core/lib/surface/call.h
   - src/core/lib/surface/call_test_only.h
   - src/core/lib/surface/channel.h
@@ -1906,7 +1921,6 @@ libs:
   - src/core/lib/surface/lame_client.h
   - src/core/lib/surface/server.h
   - src/core/lib/surface/validate_metadata.h
-  - src/core/lib/transport/authority_override.h
   - src/core/lib/transport/bdp_estimator.h
   - src/core/lib/transport/byte_stream.h
   - src/core/lib/transport/connectivity_state.h
@@ -1914,6 +1928,7 @@ libs:
   - src/core/lib/transport/http2_errors.h
   - src/core/lib/transport/metadata.h
   - src/core/lib/transport/metadata_batch.h
+  - src/core/lib/transport/parsed_metadata.h
   - src/core/lib/transport/pid_controller.h
   - src/core/lib/transport/static_metadata.h
   - src/core/lib/transport/status_conversion.h
@@ -1956,6 +1971,7 @@ libs:
   - src/core/ext/filters/client_channel/local_subchannel_pool.cc
   - src/core/ext/filters/client_channel/proxy_mapper_registry.cc
   - src/core/ext/filters/client_channel/resolver.cc
+  - src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc
   - src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc
   - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_event_engine.cc
   - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc
@@ -1974,12 +1990,11 @@ libs:
   - src/core/ext/filters/client_channel/retry_service_config.cc
   - src/core/ext/filters/client_channel/retry_throttle.cc
   - src/core/ext/filters/client_channel/server_address.cc
-  - src/core/ext/filters/client_channel/service_config.cc
   - src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc
-  - src/core/ext/filters/client_channel/service_config_parser.cc
   - src/core/ext/filters/client_channel/subchannel.cc
   - src/core/ext/filters/client_channel/subchannel_pool_interface.cc
   - src/core/ext/filters/client_idle/client_idle_filter.cc
+  - src/core/ext/filters/client_idle/idle_filter_state.cc
   - src/core/ext/filters/deadline/deadline_filter.cc
   - src/core/ext/filters/fault_injection/fault_injection_filter.cc
   - src/core/ext/filters/fault_injection/service_config_parser.cc
@@ -1991,10 +2006,9 @@ libs:
   - src/core/ext/filters/http/server/http_server_filter.cc
   - src/core/ext/filters/max_age/max_age_filter.cc
   - src/core/ext/filters/message_size/message_size_filter.cc
-  - src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc
-  - src/core/ext/filters/workarounds/workaround_utils.cc
+  - src/core/ext/service_config/service_config.cc
+  - src/core/ext/service_config/service_config_parser.cc
   - src/core/ext/transport/chttp2/alpn/alpn.cc
-  - src/core/ext/transport/chttp2/client/authority.cc
   - src/core/ext/transport/chttp2/client/chttp2_connector.cc
   - src/core/ext/transport/chttp2/client/insecure/channel_create.cc
   - src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc
@@ -2004,7 +2018,6 @@ libs:
   - src/core/ext/transport/chttp2/transport/bin_decoder.cc
   - src/core/ext/transport/chttp2/transport/bin_encoder.cc
   - src/core/ext/transport/chttp2/transport/chttp2_plugin.cc
-  - src/core/ext/transport/chttp2/transport/chttp2_slice_allocator.cc
   - src/core/ext/transport/chttp2/transport/chttp2_transport.cc
   - src/core/ext/transport/chttp2/transport/context_list.cc
   - src/core/ext/transport/chttp2/transport/flow_control.cc
@@ -2021,7 +2034,6 @@ libs:
   - src/core/ext/transport/chttp2/transport/hpack_utils.cc
   - src/core/ext/transport/chttp2/transport/http2_settings.cc
   - src/core/ext/transport/chttp2/transport/huffsyms.cc
-  - src/core/ext/transport/chttp2/transport/incoming_metadata.cc
   - src/core/ext/transport/chttp2/transport/parsing.cc
   - src/core/ext/transport/chttp2/transport/stream_lists.cc
   - src/core/ext/transport/chttp2/transport/stream_map.cc
@@ -2031,8 +2043,8 @@ libs:
   - src/core/ext/transport/inproc/inproc_transport.cc
   - src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.c
   - src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c
-  - src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c
   - src/core/ext/upb-generated/validate/validate.upb.c
+  - src/core/ext/upb-generated/xds/data/orca/v3/orca_load_report.upb.c
   - src/core/lib/address_utils/parse_address.cc
   - src/core/lib/address_utils/sockaddr_utils.cc
   - src/core/lib/avl/avl.cc
@@ -2152,7 +2164,6 @@ libs:
   - src/core/lib/iomgr/timer_generic.cc
   - src/core/lib/iomgr/timer_heap.cc
   - src/core/lib/iomgr/timer_manager.cc
-  - src/core/lib/iomgr/udp_server.cc
   - src/core/lib/iomgr/unix_sockets_posix.cc
   - src/core/lib/iomgr/unix_sockets_posix_noop.cc
   - src/core/lib/iomgr/wakeup_fd_eventfd.cc
@@ -2167,10 +2178,15 @@ libs:
   - src/core/lib/slice/b64.cc
   - src/core/lib/slice/percent_encoding.cc
   - src/core/lib/slice/slice.cc
+  - src/core/lib/slice/slice_api.cc
   - src/core/lib/slice/slice_buffer.cc
   - src/core/lib/slice/slice_intern.cc
+  - src/core/lib/slice/slice_refcount.cc
+  - src/core/lib/slice/slice_split.cc
   - src/core/lib/slice/slice_string_helpers.cc
+  - src/core/lib/slice/static_slice.cc
   - src/core/lib/surface/api_trace.cc
+  - src/core/lib/surface/builtins.cc
   - src/core/lib/surface/byte_buffer.cc
   - src/core/lib/surface/byte_buffer_reader.cc
   - src/core/lib/surface/call.cc
@@ -2190,7 +2206,6 @@ libs:
   - src/core/lib/surface/server.cc
   - src/core/lib/surface/validate_metadata.cc
   - src/core/lib/surface/version.cc
-  - src/core/lib/transport/authority_override.cc
   - src/core/lib/transport/bdp_estimator.cc
   - src/core/lib/transport/byte_stream.cc
   - src/core/lib/transport/connectivity_state.cc
@@ -2212,6 +2227,7 @@ libs:
   - absl/functional:bind_front
   - absl/status:statusor
   - absl/types:variant
+  - absl/utility:utility
   - gpr
   - address_sorting
   baselib: true
@@ -2321,6 +2337,7 @@ libs:
   - include/grpcpp/client_context.h
   - include/grpcpp/completion_queue.h
   - include/grpcpp/create_channel.h
+  - include/grpcpp/create_channel_binder.h
   - include/grpcpp/create_channel_posix.h
   - include/grpcpp/ext/health_check_service_server_builder_option.h
   - include/grpcpp/generic/async_generic_service.h
@@ -2394,6 +2411,8 @@ libs:
   - include/grpcpp/security/auth_context.h
   - include/grpcpp/security/auth_metadata_processor.h
   - include/grpcpp/security/authorization_policy_provider.h
+  - include/grpcpp/security/binder_credentials.h
+  - include/grpcpp/security/binder_security_policy.h
   - include/grpcpp/security/credentials.h
   - include/grpcpp/security/server_credentials.h
   - include/grpcpp/security/tls_certificate_provider.h
@@ -2426,6 +2445,24 @@ libs:
   - include/grpcpp/support/validate_service_config.h
   - include/grpcpp/xds_server_builder.h
   headers:
+  - src/core/ext/transport/binder/client/binder_connector.h
+  - src/core/ext/transport/binder/client/channel_create_impl.h
+  - src/core/ext/transport/binder/client/connection_id_generator.h
+  - src/core/ext/transport/binder/client/endpoint_binder_pool.h
+  - src/core/ext/transport/binder/client/jni_utils.h
+  - src/core/ext/transport/binder/client/security_policy_setting.h
+  - src/core/ext/transport/binder/server/binder_server.h
+  - src/core/ext/transport/binder/transport/binder_stream.h
+  - src/core/ext/transport/binder/transport/binder_transport.h
+  - src/core/ext/transport/binder/utils/transport_stream_receiver.h
+  - src/core/ext/transport/binder/utils/transport_stream_receiver_impl.h
+  - src/core/ext/transport/binder/wire_format/binder.h
+  - src/core/ext/transport/binder/wire_format/binder_android.h
+  - src/core/ext/transport/binder/wire_format/binder_constants.h
+  - src/core/ext/transport/binder/wire_format/transaction.h
+  - src/core/ext/transport/binder/wire_format/wire_reader.h
+  - src/core/ext/transport/binder/wire_format/wire_reader_impl.h
+  - src/core/ext/transport/binder/wire_format/wire_writer.h
   - src/cpp/client/create_channel_internal.h
   - src/cpp/client/secure_credentials.h
   - src/cpp/common/channel_filter.h
@@ -2438,6 +2475,23 @@ libs:
   - src/cpp/server/thread_pool_interface.h
   - src/cpp/thread_manager/thread_manager.h
   src:
+  - src/core/ext/transport/binder/client/binder_connector.cc
+  - src/core/ext/transport/binder/client/channel_create.cc
+  - src/core/ext/transport/binder/client/channel_create_impl.cc
+  - src/core/ext/transport/binder/client/connection_id_generator.cc
+  - src/core/ext/transport/binder/client/endpoint_binder_pool.cc
+  - src/core/ext/transport/binder/client/jni_utils.cc
+  - src/core/ext/transport/binder/client/security_policy_setting.cc
+  - src/core/ext/transport/binder/security_policy/binder_security_policy.cc
+  - src/core/ext/transport/binder/server/binder_server.cc
+  - src/core/ext/transport/binder/server/binder_server_credentials.cc
+  - src/core/ext/transport/binder/transport/binder_transport.cc
+  - src/core/ext/transport/binder/utils/transport_stream_receiver_impl.cc
+  - src/core/ext/transport/binder/wire_format/binder_android.cc
+  - src/core/ext/transport/binder/wire_format/binder_constants.cc
+  - src/core/ext/transport/binder/wire_format/transaction.cc
+  - src/core/ext/transport/binder/wire_format/wire_reader_impl.cc
+  - src/core/ext/transport/binder/wire_format/wire_writer.cc
   - src/cpp/client/channel_cc.cc
   - src/cpp/client/client_callback.cc
   - src/cpp/client/client_context.cc
@@ -3128,14 +3182,6 @@ targets:
   - test/core/surface/channel_create_test.cc
   deps:
   - grpc_test_util
-- name: channel_stack_builder_test
-  build: test
-  language: c
-  headers: []
-  src:
-  - test/core/channel/channel_stack_builder_test.cc
-  deps:
-  - grpc_test_util
 - name: channel_stack_test
   build: test
   language: c
@@ -3308,17 +3354,6 @@ targets:
   deps:
   - grpc_test_util
   uses_polling: false
-- name: error_test
-  build: test
-  language: c
-  headers:
-  - test/core/iomgr/endpoint_tests.h
-  src:
-  - test/core/iomgr/endpoint_tests.cc
-  - test/core/iomgr/error_test.cc
-  deps:
-  - grpc_test_util
-  uses_polling: false
 - name: ev_epollex_linux_test
   build: test
   language: c
@@ -3527,24 +3562,6 @@ targets:
   deps:
   - grpc_test_util
   uses_polling: false
-- name: hpack_parser_table_test
-  build: test
-  language: c
-  headers: []
-  src:
-  - test/core/transport/chttp2/hpack_parser_table_test.cc
-  deps:
-  - grpc_test_util
-  uses_polling: false
-- name: hpack_parser_test
-  build: test
-  language: c
-  headers: []
-  src:
-  - test/core/transport/chttp2/hpack_parser_test.cc
-  deps:
-  - grpc_test_util
-  uses_polling: false
 - name: httpcli_test
   build: test
   language: c
@@ -3644,6 +3661,65 @@ targets:
   deps:
   - grpc_test_util
   uses_polling: false
+- name: memory_quota_stress_test
+  build: test
+  language: c
+  headers:
+  - src/core/lib/debug/trace.h
+  - src/core/lib/gprpp/atomic_utils.h
+  - src/core/lib/gprpp/dual_ref_counted.h
+  - src/core/lib/gprpp/orphanable.h
+  - src/core/lib/gprpp/ref_counted.h
+  - src/core/lib/gprpp/ref_counted_ptr.h
+  - src/core/lib/iomgr/closure.h
+  - src/core/lib/iomgr/combiner.h
+  - src/core/lib/iomgr/error.h
+  - src/core/lib/iomgr/error_internal.h
+  - src/core/lib/iomgr/exec_ctx.h
+  - src/core/lib/iomgr/executor.h
+  - src/core/lib/iomgr/iomgr_internal.h
+  - src/core/lib/promise/activity.h
+  - src/core/lib/promise/context.h
+  - src/core/lib/promise/detail/basic_seq.h
+  - src/core/lib/promise/detail/promise_factory.h
+  - src/core/lib/promise/detail/promise_like.h
+  - src/core/lib/promise/detail/status.h
+  - src/core/lib/promise/detail/switch.h
+  - src/core/lib/promise/exec_ctx_wakeup_scheduler.h
+  - src/core/lib/promise/loop.h
+  - src/core/lib/promise/poll.h
+  - src/core/lib/promise/race.h
+  - src/core/lib/promise/seq.h
+  - src/core/lib/resource_quota/memory_quota.h
+  - src/core/lib/slice/slice_internal.h
+  - src/core/lib/slice/slice_refcount.h
+  - src/core/lib/slice/slice_refcount_base.h
+  - src/core/lib/slice/slice_string_helpers.h
+  - src/core/lib/slice/slice_utils.h
+  - src/core/lib/slice/static_slice.h
+  src:
+  - src/core/lib/debug/trace.cc
+  - src/core/lib/event_engine/memory_allocator.cc
+  - src/core/lib/iomgr/combiner.cc
+  - src/core/lib/iomgr/error.cc
+  - src/core/lib/iomgr/exec_ctx.cc
+  - src/core/lib/iomgr/executor.cc
+  - src/core/lib/iomgr/iomgr_internal.cc
+  - src/core/lib/promise/activity.cc
+  - src/core/lib/resource_quota/memory_quota.cc
+  - src/core/lib/slice/slice.cc
+  - src/core/lib/slice/slice_refcount.cc
+  - src/core/lib/slice/slice_string_helpers.cc
+  - src/core/lib/slice/static_slice.cc
+  - test/core/resource_quota/memory_quota_stress_test.cc
+  deps:
+  - absl/status:statusor
+  - absl/types:variant
+  - gpr
+  platforms:
+  - linux
+  - posix
+  uses_polling: false
 - name: message_compress_test
   build: test
   language: c
@@ -3839,14 +3915,6 @@ targets:
   - grpc_test_util
   args:
   - --resolver=native
-- name: resource_quota_test
-  build: test
-  language: c
-  headers: []
-  src:
-  - test/core/iomgr/resource_quota_test.cc
-  deps:
-  - grpc_test_util
 - name: secure_channel_create_test
   build: test
   language: c
@@ -3913,15 +3981,48 @@ targets:
   deps:
   - grpc_test_util
   uses_polling: false
-- name: slice_string_helpers_test
+- name: slice_intern_test
   build: test
   language: c
   headers: []
   src:
-  - test/core/slice/slice_string_helpers_test.cc
+  - test/core/slice/slice_intern_test.cc
+  deps:
+  - grpc_test_util
+  uses_polling: false
+- name: slice_split_test
+  build: test
+  language: c
+  headers: []
+  src:
+  - test/core/slice/slice_split_test.cc
   deps:
   - grpc_test_util
   uses_polling: false
+- name: slice_string_helpers_test
+  build: test
+  language: c
+  headers:
+  - src/core/lib/debug/trace.h
+  - src/core/lib/gprpp/atomic_utils.h
+  - src/core/lib/gprpp/ref_counted.h
+  - src/core/lib/gprpp/ref_counted_ptr.h
+  - src/core/lib/slice/slice_internal.h
+  - src/core/lib/slice/slice_refcount.h
+  - src/core/lib/slice/slice_refcount_base.h
+  - src/core/lib/slice/slice_string_helpers.h
+  - src/core/lib/slice/slice_utils.h
+  - src/core/lib/slice/static_slice.h
+  src:
+  - src/core/lib/debug/trace.cc
+  - src/core/lib/slice/slice.cc
+  - src/core/lib/slice/slice_refcount.cc
+  - src/core/lib/slice/slice_string_helpers.cc
+  - src/core/lib/slice/static_slice.cc
+  - test/core/slice/slice_string_helpers_test.cc
+  deps:
+  - gpr
+  uses_polling: false
 - name: sockaddr_resolver_test
   build: test
   language: c
@@ -4072,6 +4173,14 @@ targets:
   deps:
   - grpc_test_util
   uses_polling: false
+- name: test_core_iomgr_resource_quota_test
+  build: test
+  language: c
+  headers: []
+  src:
+  - test/core/iomgr/resource_quota_test.cc
+  deps:
+  - grpc_test_util
 - name: test_core_security_credentials_test
   build: test
   language: c
@@ -4083,11 +4192,26 @@ targets:
 - name: test_core_slice_slice_test
   build: test
   language: c
-  headers: []
+  headers:
+  - src/core/lib/debug/trace.h
+  - src/core/lib/gprpp/atomic_utils.h
+  - src/core/lib/gprpp/ref_counted.h
+  - src/core/lib/gprpp/ref_counted_ptr.h
+  - src/core/lib/slice/slice_internal.h
+  - src/core/lib/slice/slice_refcount.h
+  - src/core/lib/slice/slice_refcount_base.h
+  - src/core/lib/slice/slice_string_helpers.h
+  - src/core/lib/slice/slice_utils.h
+  - src/core/lib/slice/static_slice.h
   src:
+  - src/core/lib/debug/trace.cc
+  - src/core/lib/slice/slice.cc
+  - src/core/lib/slice/slice_refcount.cc
+  - src/core/lib/slice/slice_string_helpers.cc
+  - src/core/lib/slice/static_slice.cc
   - test/core/slice/slice_test.cc
   deps:
-  - grpc_test_util
+  - gpr
   uses_polling: false
 - name: thd_test
   build: test
@@ -4159,27 +4283,6 @@ targets:
   - test/core/tsi/transport_security_test.cc
   deps:
   - grpc_test_util
-- name: udp_server_test
-  build: test
-  language: c
-  headers: []
-  src:
-  - test/core/iomgr/udp_server_test.cc
-  deps:
-  - grpc_test_util
-  platforms:
-  - linux
-  - posix
-  - mac
-- name: useful_test
-  build: test
-  language: c
-  headers: []
-  src:
-  - test/core/gpr/useful_test.cc
-  deps:
-  - grpc_test_util
-  uses_polling: false
 - name: varint_test
   build: test
   language: c
@@ -4249,6 +4352,7 @@ targets:
   - src/core/lib/promise/promise.h
   - src/core/lib/promise/seq.h
   - src/core/lib/promise/wait_set.h
+  - test/core/promise/test_wakeup_schedulers.h
   src:
   - src/core/ext/upb-generated/google/api/annotations.upb.c
   - src/core/ext/upb-generated/google/api/expr/v1alpha1/checked.upb.c
@@ -4410,20 +4514,6 @@ targets:
   platforms:
   - linux
   - posix
-- name: alts_credentials_fuzzer
-  build: fuzzer
-  language: c++
-  headers: []
-  src:
-  - test/core/security/alts_credentials_fuzzer.cc
-  - test/core/util/fuzzer_corpus_test.cc
-  deps:
-  - absl/flags:flag
-  - grpc_test_util
-  - grpc++_test_config
-  corpus_dirs:
-  - test/core/security/corpus/alts_credentials_corpus
-  maxlen: 2048
 - name: alts_util_test
   gtest: true
   build: test
@@ -4553,45 +4643,27 @@ targets:
   - posix
   - mac
   uses_polling: false
+- name: binder_resolver_test
+  gtest: true
+  build: test
+  language: c++
+  headers: []
+  src:
+  - test/core/client_channel/resolvers/binder_resolver_test.cc
+  deps:
+  - grpc_test_util
 - name: binder_server_test
   gtest: true
   build: test
   language: c++
   headers:
-  - src/core/ext/transport/binder/client/channel_create_impl.h
-  - src/core/ext/transport/binder/server/binder_server.h
-  - src/core/ext/transport/binder/server/binder_server_credentials.h
-  - src/core/ext/transport/binder/transport/binder_stream.h
-  - src/core/ext/transport/binder/transport/binder_transport.h
-  - src/core/ext/transport/binder/utils/transport_stream_receiver.h
-  - src/core/ext/transport/binder/utils/transport_stream_receiver_impl.h
-  - src/core/ext/transport/binder/wire_format/binder.h
-  - src/core/ext/transport/binder/wire_format/binder_android.h
-  - src/core/ext/transport/binder/wire_format/binder_constants.h
-  - src/core/ext/transport/binder/wire_format/transaction.h
-  - src/core/ext/transport/binder/wire_format/wire_reader.h
-  - src/core/ext/transport/binder/wire_format/wire_reader_impl.h
-  - src/core/ext/transport/binder/wire_format/wire_writer.h
-  - test/core/transport/binder/end2end/echo_service.h
   - test/core/transport/binder/end2end/fake_binder.h
   - test/cpp/end2end/test_service_impl.h
   src:
   - src/proto/grpc/testing/echo.proto
   - src/proto/grpc/testing/echo_messages.proto
   - src/proto/grpc/testing/simple_messages.proto
-  - test/core/transport/binder/end2end/echo.proto
-  - src/core/ext/transport/binder/client/channel_create_impl.cc
-  - src/core/ext/transport/binder/server/binder_server.cc
-  - src/core/ext/transport/binder/server/binder_server_credentials.cc
-  - src/core/ext/transport/binder/transport/binder_transport.cc
-  - src/core/ext/transport/binder/utils/transport_stream_receiver_impl.cc
-  - src/core/ext/transport/binder/wire_format/binder_android.cc
-  - src/core/ext/transport/binder/wire_format/binder_constants.cc
-  - src/core/ext/transport/binder/wire_format/transaction.cc
-  - src/core/ext/transport/binder/wire_format/wire_reader_impl.cc
-  - src/core/ext/transport/binder/wire_format/wire_writer.cc
   - test/core/transport/binder/end2end/binder_server_test.cc
-  - test/core/transport/binder/end2end/echo_service.cc
   - test/core/transport/binder/end2end/fake_binder.cc
   - test/cpp/end2end/test_service_impl.cc
   deps:
@@ -4602,349 +4674,102 @@ targets:
   build: test
   language: c++
   headers:
+  - src/core/ext/transport/binder/client/binder_connector.h
+  - src/core/ext/transport/binder/client/channel_create_impl.h
+  - src/core/ext/transport/binder/client/connection_id_generator.h
+  - src/core/ext/transport/binder/client/endpoint_binder_pool.h
+  - src/core/ext/transport/binder/client/jni_utils.h
+  - src/core/ext/transport/binder/client/security_policy_setting.h
+  - src/core/ext/transport/binder/server/binder_server.h
   - src/core/ext/transport/binder/transport/binder_stream.h
   - src/core/ext/transport/binder/transport/binder_transport.h
   - src/core/ext/transport/binder/utils/transport_stream_receiver.h
   - src/core/ext/transport/binder/utils/transport_stream_receiver_impl.h
   - src/core/ext/transport/binder/wire_format/binder.h
+  - src/core/ext/transport/binder/wire_format/binder_android.h
   - src/core/ext/transport/binder/wire_format/binder_constants.h
   - src/core/ext/transport/binder/wire_format/transaction.h
   - src/core/ext/transport/binder/wire_format/wire_reader.h
   - src/core/ext/transport/binder/wire_format/wire_reader_impl.h
   - src/core/ext/transport/binder/wire_format/wire_writer.h
+  - src/cpp/client/create_channel_internal.h
+  - src/cpp/common/channel_filter.h
+  - src/cpp/server/dynamic_thread_pool.h
+  - src/cpp/server/external_connection_acceptor_impl.h
+  - src/cpp/server/health/default_health_check_service.h
+  - src/cpp/server/thread_pool_interface.h
+  - src/cpp/thread_manager/thread_manager.h
   - test/core/transport/binder/mock_objects.h
   src:
+  - src/core/ext/transport/binder/client/binder_connector.cc
+  - src/core/ext/transport/binder/client/channel_create.cc
+  - src/core/ext/transport/binder/client/channel_create_impl.cc
+  - src/core/ext/transport/binder/client/connection_id_generator.cc
+  - src/core/ext/transport/binder/client/endpoint_binder_pool.cc
+  - src/core/ext/transport/binder/client/jni_utils.cc
+  - src/core/ext/transport/binder/client/security_policy_setting.cc
+  - src/core/ext/transport/binder/security_policy/binder_security_policy.cc
+  - src/core/ext/transport/binder/server/binder_server.cc
+  - src/core/ext/transport/binder/server/binder_server_credentials.cc
   - src/core/ext/transport/binder/transport/binder_transport.cc
   - src/core/ext/transport/binder/utils/transport_stream_receiver_impl.cc
+  - src/core/ext/transport/binder/wire_format/binder_android.cc
   - src/core/ext/transport/binder/wire_format/binder_constants.cc
   - src/core/ext/transport/binder/wire_format/transaction.cc
   - src/core/ext/transport/binder/wire_format/wire_reader_impl.cc
   - src/core/ext/transport/binder/wire_format/wire_writer.cc
-  - test/core/transport/binder/binder_transport_test.cc
-  - test/core/transport/binder/mock_objects.cc
-  deps:
-  - grpc_test_util
-  uses_polling: false
-- name: bitset_test
-  gtest: true
-  build: test
-  language: c++
-  headers:
-  - src/core/lib/gprpp/bitset.h
-  src:
-  - test/core/gprpp/bitset_test.cc
-  deps: []
-  uses_polling: false
-- name: bm_alarm
-  build: test
-  language: c++
-  headers: []
-  src:
-  - test/cpp/microbenchmarks/bm_alarm.cc
-  deps:
-  - benchmark_helpers
-  benchmark: true
-  defaults: benchmark
-  platforms:
-  - linux
-  - posix
-- name: bm_arena
-  build: test
-  language: c++
-  headers: []
-  src:
-  - test/cpp/microbenchmarks/bm_arena.cc
-  deps:
-  - benchmark_helpers
-  benchmark: true
-  defaults: benchmark
-  platforms:
-  - linux
-  - posix
-  uses_polling: false
-- name: bm_byte_buffer
-  build: test
-  language: c++
-  headers: []
-  src:
-  - test/cpp/microbenchmarks/bm_byte_buffer.cc
-  deps:
-  - benchmark_helpers
-  benchmark: true
-  defaults: benchmark
-  platforms:
-  - linux
-  - posix
-  uses_polling: false
-- name: bm_call_create
-  build: test
-  language: c++
-  headers: []
-  src:
-  - test/cpp/microbenchmarks/bm_call_create.cc
-  deps:
-  - benchmark_helpers
-  benchmark: true
-  defaults: benchmark
-  platforms:
-  - linux
-  - posix
-  uses_polling: false
-- name: bm_callback_streaming_ping_pong
-  build: test
-  run: false
-  language: c++
-  headers:
-  - test/cpp/microbenchmarks/callback_streaming_ping_pong.h
-  - test/cpp/microbenchmarks/callback_test_service.h
-  - test/cpp/util/byte_buffer_proto_helper.h
-  - test/cpp/util/string_ref_helper.h
-  - test/cpp/util/subprocess.h
-  src:
-  - test/cpp/microbenchmarks/bm_callback_streaming_ping_pong.cc
-  - test/cpp/microbenchmarks/callback_test_service.cc
-  - test/cpp/util/byte_buffer_proto_helper.cc
-  - test/cpp/util/string_ref_helper.cc
-  - test/cpp/util/subprocess.cc
-  deps:
-  - benchmark_helpers
-  benchmark: true
-  defaults: benchmark
-  platforms:
-  - linux
-  - posix
-- name: bm_callback_unary_ping_pong
-  build: test
-  run: false
-  language: c++
-  headers:
-  - test/cpp/microbenchmarks/callback_test_service.h
-  - test/cpp/microbenchmarks/callback_unary_ping_pong.h
-  - test/cpp/util/byte_buffer_proto_helper.h
-  - test/cpp/util/string_ref_helper.h
-  - test/cpp/util/subprocess.h
-  src:
-  - test/cpp/microbenchmarks/bm_callback_unary_ping_pong.cc
-  - test/cpp/microbenchmarks/callback_test_service.cc
-  - test/cpp/util/byte_buffer_proto_helper.cc
-  - test/cpp/util/string_ref_helper.cc
-  - test/cpp/util/subprocess.cc
-  deps:
-  - benchmark_helpers
-  benchmark: true
-  defaults: benchmark
-  platforms:
-  - linux
-  - posix
-- name: bm_channel
-  build: test
-  language: c++
-  headers: []
-  src:
-  - test/cpp/microbenchmarks/bm_channel.cc
-  deps:
-  - benchmark_helpers
-  benchmark: true
-  defaults: benchmark
-  platforms:
-  - linux
-  - posix
-  uses_polling: false
-- name: bm_chttp2_hpack
-  build: test
-  language: c++
-  headers: []
-  src:
-  - test/cpp/microbenchmarks/bm_chttp2_hpack.cc
-  deps:
-  - benchmark_helpers
-  benchmark: true
-  defaults: benchmark
-  platforms:
-  - linux
-  - posix
-  uses_polling: false
-- name: bm_chttp2_transport
-  build: test
-  language: c++
-  headers: []
-  src:
-  - test/cpp/microbenchmarks/bm_chttp2_transport.cc
-  deps:
-  - benchmark_helpers
-  benchmark: true
-  defaults: benchmark
-  platforms:
-  - linux
-  - posix
-- name: bm_closure
-  build: test
-  language: c++
-  headers: []
-  src:
-  - test/cpp/microbenchmarks/bm_closure.cc
-  deps:
-  - benchmark_helpers
-  benchmark: true
-  defaults: benchmark
-  platforms:
-  - linux
-  - posix
-- name: bm_cq
-  build: test
-  language: c++
-  headers: []
-  src:
-  - test/cpp/microbenchmarks/bm_cq.cc
-  deps:
-  - benchmark_helpers
-  benchmark: true
-  defaults: benchmark
-  platforms:
-  - linux
-  - posix
-- name: bm_cq_multiple_threads
-  build: test
-  language: c++
-  headers: []
-  src:
-  - test/cpp/microbenchmarks/bm_cq_multiple_threads.cc
-  deps:
-  - benchmark_helpers
-  benchmark: true
-  defaults: benchmark
-  platforms:
-  - linux
-  - posix
-  uses_polling: false
-- name: bm_error
-  build: test
-  language: c++
-  headers: []
-  src:
-  - test/cpp/microbenchmarks/bm_error.cc
+  - src/cpp/client/channel_cc.cc
+  - src/cpp/client/client_callback.cc
+  - src/cpp/client/client_context.cc
+  - src/cpp/client/client_interceptor.cc
+  - src/cpp/client/create_channel.cc
+  - src/cpp/client/create_channel_internal.cc
+  - src/cpp/client/create_channel_posix.cc
+  - src/cpp/client/credentials_cc.cc
+  - src/cpp/codegen/codegen_init.cc
+  - src/cpp/common/alarm.cc
+  - src/cpp/common/channel_arguments.cc
+  - src/cpp/common/channel_filter.cc
+  - src/cpp/common/completion_queue_cc.cc
+  - src/cpp/common/core_codegen.cc
+  - src/cpp/common/resource_quota_cc.cc
+  - src/cpp/common/rpc_method.cc
+  - src/cpp/common/validate_service_config.cc
+  - src/cpp/common/version_cc.cc
+  - src/cpp/server/async_generic_service.cc
+  - src/cpp/server/channel_argument_option.cc
+  - src/cpp/server/create_default_thread_pool.cc
+  - src/cpp/server/dynamic_thread_pool.cc
+  - src/cpp/server/external_connection_acceptor_impl.cc
+  - src/cpp/server/health/default_health_check_service.cc
+  - src/cpp/server/health/health_check_service.cc
+  - src/cpp/server/health/health_check_service_server_builder_option.cc
+  - src/cpp/server/server_builder.cc
+  - src/cpp/server/server_callback.cc
+  - src/cpp/server/server_cc.cc
+  - src/cpp/server/server_context.cc
+  - src/cpp/server/server_credentials.cc
+  - src/cpp/server/server_posix.cc
+  - src/cpp/thread_manager/thread_manager.cc
+  - src/cpp/util/byte_buffer_cc.cc
+  - src/cpp/util/status.cc
+  - src/cpp/util/string_ref.cc
+  - src/cpp/util/time_cc.cc
+  - test/core/transport/binder/binder_transport_test.cc
+  - test/core/transport/binder/mock_objects.cc
   deps:
-  - benchmark_helpers
-  benchmark: true
-  defaults: benchmark
-  platforms:
-  - linux
-  - posix
+  - grpc_test_util
   uses_polling: false
-- name: bm_fullstack_streaming_ping_pong
-  build: test
-  language: c++
-  headers:
-  - test/cpp/microbenchmarks/fullstack_streaming_ping_pong.h
-  src:
-  - test/cpp/microbenchmarks/bm_fullstack_streaming_ping_pong.cc
-  deps:
-  - benchmark_helpers
-  benchmark: true
-  defaults: benchmark
-  platforms:
-  - linux
-  - posix
-- name: bm_fullstack_streaming_pump
-  build: test
-  language: c++
-  headers:
-  - test/cpp/microbenchmarks/fullstack_streaming_pump.h
-  src:
-  - test/cpp/microbenchmarks/bm_fullstack_streaming_pump.cc
-  deps:
-  - benchmark_helpers
-  benchmark: true
-  defaults: benchmark
-  platforms:
-  - linux
-  - posix
-- name: bm_fullstack_trickle
-  build: test
-  run: false
-  language: c++
-  headers: []
-  src:
-  - test/cpp/microbenchmarks/bm_fullstack_trickle.cc
-  deps:
-  - absl/flags:flag
-  - benchmark_helpers
-  benchmark: true
-  defaults: benchmark
-  platforms:
-  - linux
-  - posix
-  - mac
-- name: bm_fullstack_unary_ping_pong
+- name: bitset_test
+  gtest: true
   build: test
   language: c++
   headers:
-  - test/cpp/microbenchmarks/fullstack_unary_ping_pong.h
-  src:
-  - test/cpp/microbenchmarks/bm_fullstack_unary_ping_pong.cc
-  deps:
-  - benchmark_helpers
-  benchmark: true
-  defaults: benchmark
-  platforms:
-  - linux
-  - posix
-- name: bm_metadata
-  build: test
-  language: c++
-  headers: []
-  src:
-  - test/cpp/microbenchmarks/bm_metadata.cc
-  deps:
-  - benchmark_helpers
-  benchmark: true
-  defaults: benchmark
-  platforms:
-  - linux
-  - posix
-  uses_polling: false
-- name: bm_pollset
-  build: test
-  language: c++
-  headers: []
-  src:
-  - test/cpp/microbenchmarks/bm_pollset.cc
-  deps:
-  - benchmark_helpers
-  benchmark: true
-  defaults: benchmark
-  platforms:
-  - linux
-  - posix
-- name: bm_threadpool
-  build: test
-  run: false
-  language: c++
-  headers: []
-  src:
-  - test/cpp/microbenchmarks/bm_threadpool.cc
-  deps:
-  - benchmark_helpers
-  benchmark: true
-  defaults: benchmark
-  platforms:
-  - linux
-  - posix
-  - mac
-  uses_polling: false
-- name: bm_timer
-  build: test
-  language: c++
-  headers: []
+  - src/core/lib/gpr/useful.h
+  - src/core/lib/gprpp/bitset.h
   src:
-  - test/cpp/microbenchmarks/bm_timer.cc
-  deps:
-  - benchmark_helpers
-  benchmark: true
-  defaults: benchmark
-  platforms:
-  - linux
-  - posix
+  - test/core/gprpp/bitset_test.cc
+  deps: []
   uses_polling: false
 - name: byte_buffer_test
   gtest: true
@@ -5070,6 +4895,15 @@ targets:
   - grpc++
   - grpc_test_util
   uses_polling: false
+- name: channel_stack_builder_test
+  gtest: true
+  build: test
+  language: c++
+  headers: []
+  src:
+  - test/core/channel/channel_stack_builder_test.cc
+  deps:
+  - grpc_test_util
 - name: channel_trace_test
   gtest: true
   build: test
@@ -5122,6 +4956,124 @@ targets:
   deps:
   - grpc++
   - grpc_test_util
+- name: chunked_vector_test
+  gtest: true
+  build: test
+  language: c++
+  headers:
+  - src/core/ext/upb-generated/google/api/annotations.upb.h
+  - src/core/ext/upb-generated/google/api/expr/v1alpha1/checked.upb.h
+  - src/core/ext/upb-generated/google/api/expr/v1alpha1/syntax.upb.h
+  - src/core/ext/upb-generated/google/api/http.upb.h
+  - src/core/ext/upb-generated/google/protobuf/any.upb.h
+  - src/core/ext/upb-generated/google/protobuf/duration.upb.h
+  - src/core/ext/upb-generated/google/protobuf/empty.upb.h
+  - src/core/ext/upb-generated/google/protobuf/struct.upb.h
+  - src/core/ext/upb-generated/google/protobuf/timestamp.upb.h
+  - src/core/ext/upb-generated/google/protobuf/wrappers.upb.h
+  - src/core/ext/upb-generated/google/rpc/status.upb.h
+  - src/core/lib/gpr/alloc.h
+  - src/core/lib/gpr/env.h
+  - src/core/lib/gpr/murmur_hash.h
+  - src/core/lib/gpr/spinlock.h
+  - src/core/lib/gpr/string.h
+  - src/core/lib/gpr/string_windows.h
+  - src/core/lib/gpr/time_precise.h
+  - src/core/lib/gpr/tls.h
+  - src/core/lib/gpr/tmpfile.h
+  - src/core/lib/gpr/useful.h
+  - src/core/lib/gprpp/arena.h
+  - src/core/lib/gprpp/chunked_vector.h
+  - src/core/lib/gprpp/construct_destruct.h
+  - src/core/lib/gprpp/debug_location.h
+  - src/core/lib/gprpp/examine_stack.h
+  - src/core/lib/gprpp/fork.h
+  - src/core/lib/gprpp/global_config.h
+  - src/core/lib/gprpp/global_config_custom.h
+  - src/core/lib/gprpp/global_config_env.h
+  - src/core/lib/gprpp/global_config_generic.h
+  - src/core/lib/gprpp/host_port.h
+  - src/core/lib/gprpp/manual_constructor.h
+  - src/core/lib/gprpp/memory.h
+  - src/core/lib/gprpp/mpscq.h
+  - src/core/lib/gprpp/stat.h
+  - src/core/lib/gprpp/status_helper.h
+  - src/core/lib/gprpp/sync.h
+  - src/core/lib/gprpp/thd.h
+  - src/core/lib/gprpp/time_util.h
+  - src/core/lib/profiling/timers.h
+  src:
+  - src/core/ext/upb-generated/google/api/annotations.upb.c
+  - src/core/ext/upb-generated/google/api/expr/v1alpha1/checked.upb.c
+  - src/core/ext/upb-generated/google/api/expr/v1alpha1/syntax.upb.c
+  - src/core/ext/upb-generated/google/api/http.upb.c
+  - src/core/ext/upb-generated/google/protobuf/any.upb.c
+  - src/core/ext/upb-generated/google/protobuf/duration.upb.c
+  - src/core/ext/upb-generated/google/protobuf/empty.upb.c
+  - src/core/ext/upb-generated/google/protobuf/struct.upb.c
+  - src/core/ext/upb-generated/google/protobuf/timestamp.upb.c
+  - src/core/ext/upb-generated/google/protobuf/wrappers.upb.c
+  - src/core/ext/upb-generated/google/rpc/status.upb.c
+  - src/core/lib/gpr/alloc.cc
+  - src/core/lib/gpr/atm.cc
+  - src/core/lib/gpr/cpu_iphone.cc
+  - src/core/lib/gpr/cpu_linux.cc
+  - src/core/lib/gpr/cpu_posix.cc
+  - src/core/lib/gpr/cpu_windows.cc
+  - src/core/lib/gpr/env_linux.cc
+  - src/core/lib/gpr/env_posix.cc
+  - src/core/lib/gpr/env_windows.cc
+  - src/core/lib/gpr/log.cc
+  - src/core/lib/gpr/log_android.cc
+  - src/core/lib/gpr/log_linux.cc
+  - src/core/lib/gpr/log_posix.cc
+  - src/core/lib/gpr/log_windows.cc
+  - src/core/lib/gpr/murmur_hash.cc
+  - src/core/lib/gpr/string.cc
+  - src/core/lib/gpr/string_posix.cc
+  - src/core/lib/gpr/string_util_windows.cc
+  - src/core/lib/gpr/string_windows.cc
+  - src/core/lib/gpr/sync.cc
+  - src/core/lib/gpr/sync_abseil.cc
+  - src/core/lib/gpr/sync_posix.cc
+  - src/core/lib/gpr/sync_windows.cc
+  - src/core/lib/gpr/time.cc
+  - src/core/lib/gpr/time_posix.cc
+  - src/core/lib/gpr/time_precise.cc
+  - src/core/lib/gpr/time_windows.cc
+  - src/core/lib/gpr/tmpfile_msys.cc
+  - src/core/lib/gpr/tmpfile_posix.cc
+  - src/core/lib/gpr/tmpfile_windows.cc
+  - src/core/lib/gpr/wrap_memcpy.cc
+  - src/core/lib/gprpp/arena.cc
+  - src/core/lib/gprpp/examine_stack.cc
+  - src/core/lib/gprpp/fork.cc
+  - src/core/lib/gprpp/global_config_env.cc
+  - src/core/lib/gprpp/host_port.cc
+  - src/core/lib/gprpp/mpscq.cc
+  - src/core/lib/gprpp/stat_posix.cc
+  - src/core/lib/gprpp/stat_windows.cc
+  - src/core/lib/gprpp/status_helper.cc
+  - src/core/lib/gprpp/thd_posix.cc
+  - src/core/lib/gprpp/thd_windows.cc
+  - src/core/lib/gprpp/time_util.cc
+  - src/core/lib/profiling/basic_timers.cc
+  - src/core/lib/profiling/stap_timers.cc
+  - test/core/gprpp/chunked_vector_test.cc
+  deps:
+  - absl/base:base
+  - absl/base:core_headers
+  - absl/memory:memory
+  - absl/status:status
+  - absl/strings:cord
+  - absl/strings:str_format
+  - absl/strings:strings
+  - absl/synchronization:synchronization
+  - absl/time:time
+  - absl/types:optional
+  - absl/utility:utility
+  - upb
+  uses_polling: false
 - name: cli_call_test
   gtest: true
   build: test
@@ -5195,21 +5147,6 @@ targets:
   deps:
   - grpc++_test
   - grpc++_test_util
-- name: client_fuzzer
-  build: fuzzer
-  language: c++
-  headers: []
-  src:
-  - test/core/end2end/fuzzers/client_fuzzer.cc
-  - test/core/util/fuzzer_corpus_test.cc
-  deps:
-  - absl/flags:flag
-  - grpc_test_util
-  - grpc++_test_config
-  corpus_dirs:
-  - test/core/end2end/fuzzers/client_fuzzer_corpus
-  dict: test/core/end2end/fuzzers/hpack.dictionary
-  maxlen: 2048
 - name: client_interceptors_end2end_test
   gtest: true
   build: test
@@ -5239,7 +5176,7 @@ targets:
   - src/proto/grpc/testing/echo.proto
   - src/proto/grpc/testing/echo_messages.proto
   - src/proto/grpc/testing/simple_messages.proto
-  - src/proto/grpc/testing/xds/orca_load_report_for_test.proto
+  - src/proto/grpc/testing/xds/v3/orca_load_report.proto
   - test/core/util/test_lb_policies.cc
   - test/cpp/end2end/client_lb_end2end_test.cc
   - test/cpp/end2end/test_service_impl.cc
@@ -5376,6 +5313,8 @@ targets:
   - src/core/lib/gprpp/thd.h
   - src/core/lib/gprpp/time_util.h
   - src/core/lib/profiling/timers.h
+  - src/core/lib/surface/channel_init.h
+  - src/core/lib/surface/channel_stack_type.h
   src:
   - src/core/ext/upb-generated/google/api/annotations.upb.c
   - src/core/ext/upb-generated/google/api/expr/v1alpha1/checked.upb.c
@@ -5435,6 +5374,8 @@ targets:
   - src/core/lib/gprpp/time_util.cc
   - src/core/lib/profiling/basic_timers.cc
   - src/core/lib/profiling/stap_timers.cc
+  - src/core/lib/surface/channel_init.cc
+  - src/core/lib/surface/channel_stack_type.cc
   - test/core/config/core_configuration_test.cc
   deps:
   - absl/base:base
@@ -5499,11 +5440,57 @@ targets:
   build: test
   language: c++
   headers:
+  - test/core/transport/binder/end2end/fake_binder.h
+  - test/core/transport/binder/end2end/testing_channel_create.h
+  - test/cpp/end2end/test_service_impl.h
+  src:
+  - src/proto/grpc/testing/echo.proto
+  - src/proto/grpc/testing/echo_messages.proto
+  - src/proto/grpc/testing/simple_messages.proto
+  - test/core/transport/binder/end2end/end2end_binder_transport_test.cc
+  - test/core/transport/binder/end2end/fake_binder.cc
+  - test/core/transport/binder/end2end/testing_channel_create.cc
+  - test/cpp/end2end/test_service_impl.cc
+  deps:
+  - absl/random:random
+  - grpc++_test_util
+- name: end2end_test
+  gtest: true
+  build: test
+  run: false
+  language: c++
+  headers:
+  - test/cpp/end2end/interceptors_util.h
+  - test/cpp/end2end/test_service_impl.h
+  src:
+  - src/proto/grpc/testing/duplicate/echo_duplicate.proto
+  - src/proto/grpc/testing/echo.proto
+  - src/proto/grpc/testing/echo_messages.proto
+  - src/proto/grpc/testing/simple_messages.proto
+  - test/cpp/end2end/end2end_test.cc
+  - test/cpp/end2end/interceptors_util.cc
+  - test/cpp/end2end/test_service_impl.cc
+  deps:
+  - grpc++_test
+  - grpc++_test_util
+- name: endpoint_binder_pool_test
+  gtest: true
+  build: test
+  language: c++
+  headers:
+  - src/core/ext/transport/binder/client/binder_connector.h
+  - src/core/ext/transport/binder/client/channel_create_impl.h
+  - src/core/ext/transport/binder/client/connection_id_generator.h
+  - src/core/ext/transport/binder/client/endpoint_binder_pool.h
+  - src/core/ext/transport/binder/client/jni_utils.h
+  - src/core/ext/transport/binder/client/security_policy_setting.h
+  - src/core/ext/transport/binder/server/binder_server.h
   - src/core/ext/transport/binder/transport/binder_stream.h
   - src/core/ext/transport/binder/transport/binder_transport.h
   - src/core/ext/transport/binder/utils/transport_stream_receiver.h
   - src/core/ext/transport/binder/utils/transport_stream_receiver_impl.h
   - src/core/ext/transport/binder/wire_format/binder.h
+  - src/core/ext/transport/binder/wire_format/binder_android.h
   - src/core/ext/transport/binder/wire_format/binder_constants.h
   - src/core/ext/transport/binder/wire_format/transaction.h
   - src/core/ext/transport/binder/wire_format/wire_reader.h
@@ -5516,13 +5503,21 @@ targets:
   - src/cpp/server/health/default_health_check_service.h
   - src/cpp/server/thread_pool_interface.h
   - src/cpp/thread_manager/thread_manager.h
-  - test/core/transport/binder/end2end/echo_service.h
-  - test/core/transport/binder/end2end/fake_binder.h
-  - test/core/transport/binder/end2end/testing_channel_create.h
+  - test/core/transport/binder/mock_objects.h
   src:
-  - test/core/transport/binder/end2end/echo.proto
+  - src/core/ext/transport/binder/client/binder_connector.cc
+  - src/core/ext/transport/binder/client/channel_create.cc
+  - src/core/ext/transport/binder/client/channel_create_impl.cc
+  - src/core/ext/transport/binder/client/connection_id_generator.cc
+  - src/core/ext/transport/binder/client/endpoint_binder_pool.cc
+  - src/core/ext/transport/binder/client/jni_utils.cc
+  - src/core/ext/transport/binder/client/security_policy_setting.cc
+  - src/core/ext/transport/binder/security_policy/binder_security_policy.cc
+  - src/core/ext/transport/binder/server/binder_server.cc
+  - src/core/ext/transport/binder/server/binder_server_credentials.cc
   - src/core/ext/transport/binder/transport/binder_transport.cc
   - src/core/ext/transport/binder/utils/transport_stream_receiver_impl.cc
+  - src/core/ext/transport/binder/wire_format/binder_android.cc
   - src/core/ext/transport/binder/wire_format/binder_constants.cc
   - src/core/ext/transport/binder/wire_format/transaction.cc
   - src/core/ext/transport/binder/wire_format/wire_reader_impl.cc
@@ -5564,32 +5559,11 @@ targets:
   - src/cpp/util/status.cc
   - src/cpp/util/string_ref.cc
   - src/cpp/util/time_cc.cc
-  - test/core/transport/binder/end2end/echo_service.cc
-  - test/core/transport/binder/end2end/end2end_binder_transport_test.cc
-  - test/core/transport/binder/end2end/fake_binder.cc
-  - test/core/transport/binder/end2end/testing_channel_create.cc
+  - test/core/transport/binder/endpoint_binder_pool_test.cc
+  - test/core/transport/binder/mock_objects.cc
   deps:
-  - absl/random:random
   - grpc_test_util
-- name: end2end_test
-  gtest: true
-  build: test
-  run: false
-  language: c++
-  headers:
-  - test/cpp/end2end/interceptors_util.h
-  - test/cpp/end2end/test_service_impl.h
-  src:
-  - src/proto/grpc/testing/duplicate/echo_duplicate.proto
-  - src/proto/grpc/testing/echo.proto
-  - src/proto/grpc/testing/echo_messages.proto
-  - src/proto/grpc/testing/simple_messages.proto
-  - test/cpp/end2end/end2end_test.cc
-  - test/cpp/end2end/interceptors_util.cc
-  - test/cpp/end2end/test_service_impl.cc
-  deps:
-  - grpc++_test
-  - grpc++_test_util
+  uses_polling: false
 - name: endpoint_config_test
   gtest: true
   build: test
@@ -5611,6 +5585,18 @@ targets:
   deps:
   - grpc++_error_details
   - grpc_test_util
+- name: error_test
+  gtest: true
+  build: test
+  language: c++
+  headers:
+  - test/core/iomgr/endpoint_tests.h
+  src:
+  - test/core/iomgr/endpoint_tests.cc
+  - test/core/iomgr/error_test.cc
+  deps:
+  - grpc_test_util
+  uses_polling: false
 - name: error_utils_test
   gtest: true
   build: test
@@ -5649,32 +5635,145 @@ targets:
   language: c++
   headers: []
   src:
-  - src/proto/grpc/testing/echo.proto
-  - src/proto/grpc/testing/echo_messages.proto
-  - src/proto/grpc/testing/simple_messages.proto
-  - test/cpp/end2end/exception_test.cc
+  - src/proto/grpc/testing/echo.proto
+  - src/proto/grpc/testing/echo_messages.proto
+  - src/proto/grpc/testing/simple_messages.proto
+  - test/cpp/end2end/exception_test.cc
+  deps:
+  - grpc++_test_util
+- name: exec_ctx_wakeup_scheduler_test
+  gtest: true
+  build: test
+  language: c++
+  headers:
+  - src/core/lib/debug/trace.h
+  - src/core/lib/gprpp/atomic_utils.h
+  - src/core/lib/gprpp/ref_counted.h
+  - src/core/lib/gprpp/ref_counted_ptr.h
+  - src/core/lib/iomgr/closure.h
+  - src/core/lib/iomgr/combiner.h
+  - src/core/lib/iomgr/error.h
+  - src/core/lib/iomgr/error_internal.h
+  - src/core/lib/iomgr/exec_ctx.h
+  - src/core/lib/iomgr/executor.h
+  - src/core/lib/iomgr/iomgr_internal.h
+  - src/core/lib/promise/activity.h
+  - src/core/lib/promise/context.h
+  - src/core/lib/promise/detail/promise_factory.h
+  - src/core/lib/promise/detail/promise_like.h
+  - src/core/lib/promise/detail/status.h
+  - src/core/lib/promise/exec_ctx_wakeup_scheduler.h
+  - src/core/lib/promise/poll.h
+  - src/core/lib/slice/slice_internal.h
+  - src/core/lib/slice/slice_refcount.h
+  - src/core/lib/slice/slice_refcount_base.h
+  - src/core/lib/slice/slice_string_helpers.h
+  - src/core/lib/slice/slice_utils.h
+  - src/core/lib/slice/static_slice.h
+  src:
+  - src/core/lib/debug/trace.cc
+  - src/core/lib/iomgr/combiner.cc
+  - src/core/lib/iomgr/error.cc
+  - src/core/lib/iomgr/exec_ctx.cc
+  - src/core/lib/iomgr/executor.cc
+  - src/core/lib/iomgr/iomgr_internal.cc
+  - src/core/lib/promise/activity.cc
+  - src/core/lib/slice/slice.cc
+  - src/core/lib/slice/slice_refcount.cc
+  - src/core/lib/slice/slice_string_helpers.cc
+  - src/core/lib/slice/static_slice.cc
+  - test/core/promise/exec_ctx_wakeup_scheduler_test.cc
   deps:
-  - grpc++_test_util
+  - absl/status:statusor
+  - absl/types:variant
+  - gpr
+  uses_polling: false
 - name: fake_binder_test
   gtest: true
   build: test
   language: c++
   headers:
+  - src/core/ext/transport/binder/client/binder_connector.h
+  - src/core/ext/transport/binder/client/channel_create_impl.h
+  - src/core/ext/transport/binder/client/connection_id_generator.h
+  - src/core/ext/transport/binder/client/endpoint_binder_pool.h
+  - src/core/ext/transport/binder/client/jni_utils.h
+  - src/core/ext/transport/binder/client/security_policy_setting.h
+  - src/core/ext/transport/binder/server/binder_server.h
+  - src/core/ext/transport/binder/transport/binder_stream.h
+  - src/core/ext/transport/binder/transport/binder_transport.h
   - src/core/ext/transport/binder/utils/transport_stream_receiver.h
   - src/core/ext/transport/binder/utils/transport_stream_receiver_impl.h
   - src/core/ext/transport/binder/wire_format/binder.h
+  - src/core/ext/transport/binder/wire_format/binder_android.h
   - src/core/ext/transport/binder/wire_format/binder_constants.h
   - src/core/ext/transport/binder/wire_format/transaction.h
   - src/core/ext/transport/binder/wire_format/wire_reader.h
   - src/core/ext/transport/binder/wire_format/wire_reader_impl.h
   - src/core/ext/transport/binder/wire_format/wire_writer.h
+  - src/cpp/client/create_channel_internal.h
+  - src/cpp/common/channel_filter.h
+  - src/cpp/server/dynamic_thread_pool.h
+  - src/cpp/server/external_connection_acceptor_impl.h
+  - src/cpp/server/health/default_health_check_service.h
+  - src/cpp/server/thread_pool_interface.h
+  - src/cpp/thread_manager/thread_manager.h
   - test/core/transport/binder/end2end/fake_binder.h
   src:
+  - src/core/ext/transport/binder/client/binder_connector.cc
+  - src/core/ext/transport/binder/client/channel_create.cc
+  - src/core/ext/transport/binder/client/channel_create_impl.cc
+  - src/core/ext/transport/binder/client/connection_id_generator.cc
+  - src/core/ext/transport/binder/client/endpoint_binder_pool.cc
+  - src/core/ext/transport/binder/client/jni_utils.cc
+  - src/core/ext/transport/binder/client/security_policy_setting.cc
+  - src/core/ext/transport/binder/security_policy/binder_security_policy.cc
+  - src/core/ext/transport/binder/server/binder_server.cc
+  - src/core/ext/transport/binder/server/binder_server_credentials.cc
+  - src/core/ext/transport/binder/transport/binder_transport.cc
   - src/core/ext/transport/binder/utils/transport_stream_receiver_impl.cc
+  - src/core/ext/transport/binder/wire_format/binder_android.cc
   - src/core/ext/transport/binder/wire_format/binder_constants.cc
   - src/core/ext/transport/binder/wire_format/transaction.cc
   - src/core/ext/transport/binder/wire_format/wire_reader_impl.cc
   - src/core/ext/transport/binder/wire_format/wire_writer.cc
+  - src/cpp/client/channel_cc.cc
+  - src/cpp/client/client_callback.cc
+  - src/cpp/client/client_context.cc
+  - src/cpp/client/client_interceptor.cc
+  - src/cpp/client/create_channel.cc
+  - src/cpp/client/create_channel_internal.cc
+  - src/cpp/client/create_channel_posix.cc
+  - src/cpp/client/credentials_cc.cc
+  - src/cpp/codegen/codegen_init.cc
+  - src/cpp/common/alarm.cc
+  - src/cpp/common/channel_arguments.cc
+  - src/cpp/common/channel_filter.cc
+  - src/cpp/common/completion_queue_cc.cc
+  - src/cpp/common/core_codegen.cc
+  - src/cpp/common/resource_quota_cc.cc
+  - src/cpp/common/rpc_method.cc
+  - src/cpp/common/validate_service_config.cc
+  - src/cpp/common/version_cc.cc
+  - src/cpp/server/async_generic_service.cc
+  - src/cpp/server/channel_argument_option.cc
+  - src/cpp/server/create_default_thread_pool.cc
+  - src/cpp/server/dynamic_thread_pool.cc
+  - src/cpp/server/external_connection_acceptor_impl.cc
+  - src/cpp/server/health/default_health_check_service.cc
+  - src/cpp/server/health/health_check_service.cc
+  - src/cpp/server/health/health_check_service_server_builder_option.cc
+  - src/cpp/server/server_builder.cc
+  - src/cpp/server/server_callback.cc
+  - src/cpp/server/server_cc.cc
+  - src/cpp/server/server_context.cc
+  - src/cpp/server/server_credentials.cc
+  - src/cpp/server/server_posix.cc
+  - src/cpp/thread_manager/thread_manager.cc
+  - src/cpp/util/byte_buffer_cc.cc
+  - src/cpp/util/status.cc
+  - src/cpp/util/string_ref.cc
+  - src/cpp/util/time_cc.cc
   - test/core/transport/binder/end2end/fake_binder.cc
   - test/core/transport/binder/end2end/fake_binder_test.cc
   deps:
@@ -5793,6 +5892,7 @@ targets:
   - src/core/lib/promise/poll.h
   - src/core/lib/promise/seq.h
   - src/core/lib/promise/wait_set.h
+  - test/core/promise/test_wakeup_schedulers.h
   src:
   - src/core/ext/upb-generated/google/api/annotations.upb.c
   - src/core/ext/upb-generated/google/api/expr/v1alpha1/checked.upb.c
@@ -6105,6 +6205,7 @@ targets:
   run: false
   language: c++
   headers:
+  - test/cpp/end2end/counted_service.h
   - test/cpp/end2end/test_service_impl.h
   src:
   - src/proto/grpc/lb/v1/load_balancer.proto
@@ -6184,21 +6285,26 @@ targets:
   - test/core/transport/chttp2/hpack_encoder_index_test.cc
   deps:
   - absl/types:optional
-- name: hpack_parser_fuzzer_test
-  build: fuzzer
+- name: hpack_parser_table_test
+  gtest: true
+  build: test
   language: c++
   headers: []
   src:
-  - test/core/transport/chttp2/hpack_parser_fuzzer_test.cc
-  - test/core/util/fuzzer_corpus_test.cc
+  - test/core/transport/chttp2/hpack_parser_table_test.cc
   deps:
-  - absl/flags:flag
   - grpc_test_util
-  - grpc++_test_config
-  corpus_dirs:
-  - test/core/transport/chttp2/hpack_parser_corpus
-  dict: test/core/end2end/fuzzers/hpack.dictionary
-  maxlen: 512
+  uses_polling: false
+- name: hpack_parser_test
+  gtest: true
+  build: test
+  language: c++
+  headers: []
+  src:
+  - test/core/transport/chttp2/hpack_parser_test.cc
+  deps:
+  - grpc_test_util
+  uses_polling: false
 - name: http2_client
   build: test
   run: false
@@ -6212,34 +6318,6 @@ targets:
   deps:
   - grpc++_test_config
   - grpc++_test_util
-- name: http_request_fuzzer_test
-  build: fuzzer
-  language: c++
-  headers: []
-  src:
-  - test/core/http/request_fuzzer.cc
-  - test/core/util/fuzzer_corpus_test.cc
-  deps:
-  - absl/flags:flag
-  - grpc_test_util
-  - grpc++_test_config
-  corpus_dirs:
-  - test/core/http/request_corpus
-  maxlen: 2048
-- name: http_response_fuzzer_test
-  build: fuzzer
-  language: c++
-  headers: []
-  src:
-  - test/core/http/response_fuzzer.cc
-  - test/core/util/fuzzer_corpus_test.cc
-  deps:
-  - absl/flags:flag
-  - grpc_test_util
-  - grpc++_test_config
-  corpus_dirs:
-  - test/core/http/response_corpus
-  maxlen: 2048
 - name: hybrid_end2end_test
   gtest: true
   build: test
@@ -6255,6 +6333,17 @@ targets:
   - test/cpp/end2end/test_service_impl.cc
   deps:
   - grpc++_test_util
+- name: idle_filter_state_test
+  gtest: true
+  build: test
+  language: c++
+  headers:
+  - src/core/ext/filters/client_idle/idle_filter_state.h
+  src:
+  - src/core/ext/filters/client_idle/idle_filter_state.cc
+  - test/core/client_idle/idle_filter_state_test.cc
+  deps: []
+  uses_polling: false
 - name: if_test
   gtest: true
   build: test
@@ -6355,6 +6444,7 @@ targets:
   build: test
   language: c++
   headers:
+  - src/core/lib/gpr/useful.h
   - src/core/lib/gprpp/bitset.h
   - src/core/lib/gprpp/construct_destruct.h
   - src/core/lib/promise/detail/basic_join.h
@@ -6367,20 +6457,6 @@ targets:
   deps:
   - absl/types:variant
   uses_polling: false
-- name: json_fuzzer_test
-  build: fuzzer
-  language: c++
-  headers: []
-  src:
-  - test/core/json/fuzzer.cc
-  - test/core/util/fuzzer_corpus_test.cc
-  deps:
-  - absl/flags:flag
-  - grpc_test_util
-  - grpc++_test_config
-  corpus_dirs:
-  - test/core/json/corpus
-  maxlen: 512
 - name: json_test
   gtest: true
   build: test
@@ -6464,6 +6540,7 @@ targets:
   - src/core/lib/promise/latch.h
   - src/core/lib/promise/poll.h
   - src/core/lib/promise/seq.h
+  - test/core/promise/test_wakeup_schedulers.h
   src:
   - src/core/ext/upb-generated/google/api/annotations.upb.c
   - src/core/ext/upb-generated/google/api/expr/v1alpha1/checked.upb.c
@@ -6590,10 +6667,14 @@ targets:
   build: test
   language: c++
   headers:
+  - src/core/lib/gprpp/construct_destruct.h
+  - src/core/lib/promise/detail/basic_seq.h
   - src/core/lib/promise/detail/promise_factory.h
   - src/core/lib/promise/detail/promise_like.h
+  - src/core/lib/promise/detail/switch.h
   - src/core/lib/promise/loop.h
   - src/core/lib/promise/poll.h
+  - src/core/lib/promise/seq.h
   src:
   - test/core/promise/loop_test.cc
   deps:
@@ -6620,6 +6701,64 @@ targets:
   - test/core/security/matchers_test.cc
   deps:
   - grpc_test_util
+- name: memory_quota_test
+  gtest: true
+  build: test
+  language: c++
+  headers:
+  - src/core/lib/debug/trace.h
+  - src/core/lib/gprpp/atomic_utils.h
+  - src/core/lib/gprpp/dual_ref_counted.h
+  - src/core/lib/gprpp/orphanable.h
+  - src/core/lib/gprpp/ref_counted.h
+  - src/core/lib/gprpp/ref_counted_ptr.h
+  - src/core/lib/iomgr/closure.h
+  - src/core/lib/iomgr/combiner.h
+  - src/core/lib/iomgr/error.h
+  - src/core/lib/iomgr/error_internal.h
+  - src/core/lib/iomgr/exec_ctx.h
+  - src/core/lib/iomgr/executor.h
+  - src/core/lib/iomgr/iomgr_internal.h
+  - src/core/lib/promise/activity.h
+  - src/core/lib/promise/context.h
+  - src/core/lib/promise/detail/basic_seq.h
+  - src/core/lib/promise/detail/promise_factory.h
+  - src/core/lib/promise/detail/promise_like.h
+  - src/core/lib/promise/detail/status.h
+  - src/core/lib/promise/detail/switch.h
+  - src/core/lib/promise/exec_ctx_wakeup_scheduler.h
+  - src/core/lib/promise/loop.h
+  - src/core/lib/promise/poll.h
+  - src/core/lib/promise/race.h
+  - src/core/lib/promise/seq.h
+  - src/core/lib/resource_quota/memory_quota.h
+  - src/core/lib/slice/slice_internal.h
+  - src/core/lib/slice/slice_refcount.h
+  - src/core/lib/slice/slice_refcount_base.h
+  - src/core/lib/slice/slice_string_helpers.h
+  - src/core/lib/slice/slice_utils.h
+  - src/core/lib/slice/static_slice.h
+  - test/core/resource_quota/call_checker.h
+  src:
+  - src/core/lib/debug/trace.cc
+  - src/core/lib/event_engine/memory_allocator.cc
+  - src/core/lib/iomgr/combiner.cc
+  - src/core/lib/iomgr/error.cc
+  - src/core/lib/iomgr/exec_ctx.cc
+  - src/core/lib/iomgr/executor.cc
+  - src/core/lib/iomgr/iomgr_internal.cc
+  - src/core/lib/promise/activity.cc
+  - src/core/lib/resource_quota/memory_quota.cc
+  - src/core/lib/slice/slice.cc
+  - src/core/lib/slice/slice_refcount.cc
+  - src/core/lib/slice/slice_string_helpers.cc
+  - src/core/lib/slice/static_slice.cc
+  - test/core/resource_quota/memory_quota_test.cc
+  deps:
+  - absl/status:statusor
+  - absl/types:variant
+  - gpr
+  uses_polling: false
 - name: message_allocator_end2end_test
   gtest: true
   build: test
@@ -6634,6 +6773,15 @@ targets:
   - test/cpp/end2end/test_service_impl.cc
   deps:
   - grpc++_test_util
+- name: metadata_map_test
+  gtest: true
+  build: test
+  language: c++
+  headers: []
+  src:
+  - test/core/transport/metadata_map_test.cc
+  deps:
+  - grpc_test_util
 - name: miscompile_with_no_unique_address_test
   gtest: true
   build: test
@@ -6670,34 +6818,6 @@ targets:
   deps:
   - grpc++_test
   - grpc++_test_util
-- name: nanopb_fuzzer_response_test
-  build: fuzzer
-  language: c++
-  headers: []
-  src:
-  - test/core/nanopb/fuzzer_response.cc
-  - test/core/util/fuzzer_corpus_test.cc
-  deps:
-  - absl/flags:flag
-  - grpc_test_util
-  - grpc++_test_config
-  corpus_dirs:
-  - test/core/nanopb/corpus_response
-  maxlen: 128
-- name: nanopb_fuzzer_serverlist_test
-  build: fuzzer
-  language: c++
-  headers: []
-  src:
-  - test/core/nanopb/fuzzer_serverlist.cc
-  - test/core/util/fuzzer_corpus_test.cc
-  deps:
-  - absl/flags:flag
-  - grpc_test_util
-  - grpc++_test_config
-  corpus_dirs:
-  - test/core/nanopb/corpus_serverlist
-  maxlen: 128
 - name: nonblocking_test
   gtest: true
   build: test
@@ -6710,17 +6830,6 @@ targets:
   - test/cpp/end2end/nonblocking_test.cc
   deps:
   - grpc++_test_util
-- name: noop-benchmark
-  build: test
-  language: c++
-  headers: []
-  src:
-  - test/cpp/microbenchmarks/noop-benchmark.cc
-  deps:
-  - benchmark
-  - grpc_test_util
-  benchmark: true
-  defaults: benchmark
 - name: observable_test
   gtest: true
   build: test
@@ -6779,6 +6888,7 @@ targets:
   - src/core/lib/promise/promise.h
   - src/core/lib/promise/seq.h
   - src/core/lib/promise/wait_set.h
+  - test/core/promise/test_wakeup_schedulers.h
   src:
   - src/core/ext/upb-generated/google/api/annotations.upb.c
   - src/core/ext/upb-generated/google/api/expr/v1alpha1/checked.upb.c
@@ -6886,34 +6996,15 @@ targets:
   - test/core/gprpp/overload_test.cc
   deps: []
   uses_polling: false
-- name: percent_decode_fuzzer
-  build: fuzzer
-  language: c++
-  headers: []
-  src:
-  - test/core/slice/percent_decode_fuzzer.cc
-  - test/core/util/fuzzer_corpus_test.cc
-  deps:
-  - absl/flags:flag
-  - grpc_test_util
-  - grpc++_test_config
-  corpus_dirs:
-  - test/core/slice/percent_decode_corpus
-  maxlen: 32
-- name: percent_encode_fuzzer
-  build: fuzzer
+- name: parsed_metadata_test
+  gtest: true
+  build: test
   language: c++
   headers: []
   src:
-  - test/core/slice/percent_encode_fuzzer.cc
-  - test/core/util/fuzzer_corpus_test.cc
+  - test/core/transport/parsed_metadata_test.cc
   deps:
-  - absl/flags:flag
   - grpc_test_util
-  - grpc++_test_config
-  corpus_dirs:
-  - test/core/slice/percent_encode_corpus
-  maxlen: 32
 - name: pid_controller_test
   gtest: true
   build: test
@@ -6984,6 +7075,7 @@ targets:
   - src/core/lib/promise/poll.h
   - src/core/lib/promise/promise.h
   - src/core/lib/promise/seq.h
+  - test/core/promise/test_wakeup_schedulers.h
   src:
   - src/core/ext/upb-generated/google/api/annotations.upb.c
   - src/core/ext/upb-generated/google/api/expr/v1alpha1/checked.upb.c
@@ -7336,6 +7428,35 @@ targets:
   deps:
   - grpc_test_util
   uses_polling: false
+- name: rls_end2end_test
+  gtest: true
+  build: test
+  language: c++
+  headers:
+  - test/core/util/test_lb_policies.h
+  - test/cpp/end2end/counted_service.h
+  - test/cpp/end2end/test_service_impl.h
+  src:
+  - src/proto/grpc/lookup/v1/rls.proto
+  - src/proto/grpc/testing/duplicate/echo_duplicate.proto
+  - src/proto/grpc/testing/echo.proto
+  - src/proto/grpc/testing/echo_messages.proto
+  - src/proto/grpc/testing/simple_messages.proto
+  - test/core/util/test_lb_policies.cc
+  - test/cpp/end2end/rls_end2end_test.cc
+  - test/cpp/end2end/test_service_impl.cc
+  deps:
+  - grpc++_test_config
+  - grpc++_test_util
+- name: rls_lb_config_parser_test
+  gtest: true
+  build: test
+  language: c++
+  headers: []
+  src:
+  - test/core/client_channel/rls_lb_config_parser_test.cc
+  deps:
+  - grpc_test_util
 - name: sdk_authz_end2end_test
   gtest: true
   build: test
@@ -7445,6 +7566,18 @@ targets:
   - test/core/surface/server_chttp2_test.cc
   deps:
   - grpc_test_util
+- name: server_config_selector_test
+  gtest: true
+  build: test
+  language: c++
+  headers:
+  - src/core/ext/filters/server_config_selector/server_config_selector.h
+  src:
+  - src/core/ext/filters/server_config_selector/server_config_selector.cc
+  - test/core/server_config_selector/server_config_selector_test.cc
+  deps:
+  - grpc_test_util
+  uses_polling: false
 - name: server_context_test_spouse_test
   gtest: true
   build: test
@@ -7466,22 +7599,7 @@ targets:
   - src/proto/grpc/testing/simple_messages.proto
   - test/cpp/end2end/server_early_return_test.cc
   deps:
-  - grpc++_test_util
-- name: server_fuzzer
-  build: fuzzer
-  language: c++
-  headers: []
-  src:
-  - test/core/end2end/fuzzers/server_fuzzer.cc
-  - test/core/util/fuzzer_corpus_test.cc
-  deps:
-  - absl/flags:flag
-  - grpc_test_util
-  - grpc++_test_config
-  corpus_dirs:
-  - test/core/end2end/fuzzers/server_fuzzer_corpus
-  dict: test/core/end2end/fuzzers/hpack.dictionary
-  maxlen: 2048
+  - grpc++_test_util
 - name: server_interceptors_end2end_test
   gtest: true
   build: test
@@ -7597,20 +7715,6 @@ targets:
   - test/core/address_utils/sockaddr_utils_test.cc
   deps:
   - grpc_test_util
-- name: ssl_server_fuzzer
-  build: fuzzer
-  language: c++
-  headers: []
-  src:
-  - test/core/security/ssl_server_fuzzer.cc
-  - test/core/util/fuzzer_corpus_test.cc
-  deps:
-  - absl/flags:flag
-  - grpc_test_util
-  - grpc++_test_config
-  corpus_dirs:
-  - test/core/security/corpus/ssl_server_corpus
-  maxlen: 2048
 - name: stack_tracer_test
   gtest: true
   build: test
@@ -7732,6 +7836,7 @@ targets:
   build: test
   language: c++
   headers:
+  - src/core/lib/gpr/useful.h
   - src/core/lib/gprpp/bitset.h
   - src/core/lib/gprpp/table.h
   src:
@@ -7740,6 +7845,67 @@ targets:
   - absl/types:optional
   - absl/utility:utility
   uses_polling: false
+- name: test_core_resource_quota_resource_quota_test
+  gtest: true
+  build: test
+  language: c++
+  headers:
+  - src/core/lib/debug/trace.h
+  - src/core/lib/gprpp/atomic_utils.h
+  - src/core/lib/gprpp/dual_ref_counted.h
+  - src/core/lib/gprpp/orphanable.h
+  - src/core/lib/gprpp/ref_counted.h
+  - src/core/lib/gprpp/ref_counted_ptr.h
+  - src/core/lib/iomgr/closure.h
+  - src/core/lib/iomgr/combiner.h
+  - src/core/lib/iomgr/error.h
+  - src/core/lib/iomgr/error_internal.h
+  - src/core/lib/iomgr/exec_ctx.h
+  - src/core/lib/iomgr/executor.h
+  - src/core/lib/iomgr/iomgr_internal.h
+  - src/core/lib/promise/activity.h
+  - src/core/lib/promise/context.h
+  - src/core/lib/promise/detail/basic_seq.h
+  - src/core/lib/promise/detail/promise_factory.h
+  - src/core/lib/promise/detail/promise_like.h
+  - src/core/lib/promise/detail/status.h
+  - src/core/lib/promise/detail/switch.h
+  - src/core/lib/promise/exec_ctx_wakeup_scheduler.h
+  - src/core/lib/promise/loop.h
+  - src/core/lib/promise/poll.h
+  - src/core/lib/promise/race.h
+  - src/core/lib/promise/seq.h
+  - src/core/lib/resource_quota/memory_quota.h
+  - src/core/lib/resource_quota/resource_quota.h
+  - src/core/lib/resource_quota/thread_quota.h
+  - src/core/lib/slice/slice_internal.h
+  - src/core/lib/slice/slice_refcount.h
+  - src/core/lib/slice/slice_refcount_base.h
+  - src/core/lib/slice/slice_string_helpers.h
+  - src/core/lib/slice/slice_utils.h
+  - src/core/lib/slice/static_slice.h
+  src:
+  - src/core/lib/debug/trace.cc
+  - src/core/lib/event_engine/memory_allocator.cc
+  - src/core/lib/iomgr/combiner.cc
+  - src/core/lib/iomgr/error.cc
+  - src/core/lib/iomgr/exec_ctx.cc
+  - src/core/lib/iomgr/executor.cc
+  - src/core/lib/iomgr/iomgr_internal.cc
+  - src/core/lib/promise/activity.cc
+  - src/core/lib/resource_quota/memory_quota.cc
+  - src/core/lib/resource_quota/resource_quota.cc
+  - src/core/lib/resource_quota/thread_quota.cc
+  - src/core/lib/slice/slice.cc
+  - src/core/lib/slice/slice_refcount.cc
+  - src/core/lib/slice/slice_string_helpers.cc
+  - src/core/lib/slice/static_slice.cc
+  - test/core/resource_quota/resource_quota_test.cc
+  deps:
+  - absl/status:statusor
+  - absl/types:variant
+  - gpr
+  uses_polling: false
 - name: test_cpp_client_credentials_test
   gtest: true
   build: test
@@ -7790,6 +7956,23 @@ targets:
   deps:
   - grpc++_test_config
   - grpc++_test_util
+- name: thread_quota_test
+  gtest: true
+  build: test
+  language: c++
+  headers:
+  - src/core/lib/debug/trace.h
+  - src/core/lib/gprpp/atomic_utils.h
+  - src/core/lib/gprpp/ref_counted.h
+  - src/core/lib/gprpp/ref_counted_ptr.h
+  - src/core/lib/resource_quota/thread_quota.h
+  src:
+  - src/core/lib/debug/trace.cc
+  - src/core/lib/resource_quota/thread_quota.cc
+  - test/core/resource_quota/thread_quota_test.cc
+  deps:
+  - gpr
+  uses_polling: false
 - name: thread_stress_test
   gtest: true
   build: test
@@ -7878,12 +8061,86 @@ targets:
   build: test
   language: c++
   headers:
+  - src/core/ext/transport/binder/client/binder_connector.h
+  - src/core/ext/transport/binder/client/channel_create_impl.h
+  - src/core/ext/transport/binder/client/connection_id_generator.h
+  - src/core/ext/transport/binder/client/endpoint_binder_pool.h
+  - src/core/ext/transport/binder/client/jni_utils.h
+  - src/core/ext/transport/binder/client/security_policy_setting.h
+  - src/core/ext/transport/binder/server/binder_server.h
+  - src/core/ext/transport/binder/transport/binder_stream.h
+  - src/core/ext/transport/binder/transport/binder_transport.h
   - src/core/ext/transport/binder/utils/transport_stream_receiver.h
   - src/core/ext/transport/binder/utils/transport_stream_receiver_impl.h
+  - src/core/ext/transport/binder/wire_format/binder.h
+  - src/core/ext/transport/binder/wire_format/binder_android.h
+  - src/core/ext/transport/binder/wire_format/binder_constants.h
   - src/core/ext/transport/binder/wire_format/transaction.h
+  - src/core/ext/transport/binder/wire_format/wire_reader.h
+  - src/core/ext/transport/binder/wire_format/wire_reader_impl.h
+  - src/core/ext/transport/binder/wire_format/wire_writer.h
+  - src/cpp/client/create_channel_internal.h
+  - src/cpp/common/channel_filter.h
+  - src/cpp/server/dynamic_thread_pool.h
+  - src/cpp/server/external_connection_acceptor_impl.h
+  - src/cpp/server/health/default_health_check_service.h
+  - src/cpp/server/thread_pool_interface.h
+  - src/cpp/thread_manager/thread_manager.h
   src:
+  - src/core/ext/transport/binder/client/binder_connector.cc
+  - src/core/ext/transport/binder/client/channel_create.cc
+  - src/core/ext/transport/binder/client/channel_create_impl.cc
+  - src/core/ext/transport/binder/client/connection_id_generator.cc
+  - src/core/ext/transport/binder/client/endpoint_binder_pool.cc
+  - src/core/ext/transport/binder/client/jni_utils.cc
+  - src/core/ext/transport/binder/client/security_policy_setting.cc
+  - src/core/ext/transport/binder/security_policy/binder_security_policy.cc
+  - src/core/ext/transport/binder/server/binder_server.cc
+  - src/core/ext/transport/binder/server/binder_server_credentials.cc
+  - src/core/ext/transport/binder/transport/binder_transport.cc
   - src/core/ext/transport/binder/utils/transport_stream_receiver_impl.cc
+  - src/core/ext/transport/binder/wire_format/binder_android.cc
+  - src/core/ext/transport/binder/wire_format/binder_constants.cc
   - src/core/ext/transport/binder/wire_format/transaction.cc
+  - src/core/ext/transport/binder/wire_format/wire_reader_impl.cc
+  - src/core/ext/transport/binder/wire_format/wire_writer.cc
+  - src/cpp/client/channel_cc.cc
+  - src/cpp/client/client_callback.cc
+  - src/cpp/client/client_context.cc
+  - src/cpp/client/client_interceptor.cc
+  - src/cpp/client/create_channel.cc
+  - src/cpp/client/create_channel_internal.cc
+  - src/cpp/client/create_channel_posix.cc
+  - src/cpp/client/credentials_cc.cc
+  - src/cpp/codegen/codegen_init.cc
+  - src/cpp/common/alarm.cc
+  - src/cpp/common/channel_arguments.cc
+  - src/cpp/common/channel_filter.cc
+  - src/cpp/common/completion_queue_cc.cc
+  - src/cpp/common/core_codegen.cc
+  - src/cpp/common/resource_quota_cc.cc
+  - src/cpp/common/rpc_method.cc
+  - src/cpp/common/validate_service_config.cc
+  - src/cpp/common/version_cc.cc
+  - src/cpp/server/async_generic_service.cc
+  - src/cpp/server/channel_argument_option.cc
+  - src/cpp/server/create_default_thread_pool.cc
+  - src/cpp/server/dynamic_thread_pool.cc
+  - src/cpp/server/external_connection_acceptor_impl.cc
+  - src/cpp/server/health/default_health_check_service.cc
+  - src/cpp/server/health/health_check_service.cc
+  - src/cpp/server/health/health_check_service_server_builder_option.cc
+  - src/cpp/server/server_builder.cc
+  - src/cpp/server/server_callback.cc
+  - src/cpp/server/server_cc.cc
+  - src/cpp/server/server_context.cc
+  - src/cpp/server/server_credentials.cc
+  - src/cpp/server/server_posix.cc
+  - src/cpp/thread_manager/thread_manager.cc
+  - src/cpp/util/byte_buffer_cc.cc
+  - src/cpp/util/status.cc
+  - src/cpp/util/string_ref.cc
+  - src/cpp/util/time_cc.cc
   - test/core/transport/binder/transport_stream_receiver_test.cc
   deps:
   - grpc_test_util
@@ -7893,6 +8150,7 @@ targets:
   build: test
   language: c++
   headers:
+  - src/core/lib/gpr/useful.h
   - src/core/lib/gprpp/bitset.h
   - src/core/lib/gprpp/construct_destruct.h
   - src/core/lib/promise/detail/basic_join.h
@@ -7941,20 +8199,6 @@ targets:
   - test/core/end2end/cq_verifier.cc
   deps:
   - grpc_test_util
-- name: uri_fuzzer_test
-  build: fuzzer
-  language: c++
-  headers: []
-  src:
-  - test/core/uri/uri_fuzzer_test.cc
-  - test/core/util/fuzzer_corpus_test.cc
-  deps:
-  - absl/flags:flag
-  - grpc_test_util
-  - grpc++_test_config
-  corpus_dirs:
-  - test/core/uri/uri_corpus
-  maxlen: 128
 - name: uri_parser_test
   gtest: true
   build: test
@@ -7964,6 +8208,16 @@ targets:
   - test/core/uri/uri_parser_test.cc
   deps:
   - grpc_test_util
+- name: useful_test
+  gtest: true
+  build: test
+  language: c++
+  headers:
+  - src/core/lib/gpr/useful.h
+  src:
+  - test/core/gpr/useful_test.cc
+  deps: []
+  uses_polling: false
 - name: window_overflow_bad_client_test
   gtest: true
   build: test
@@ -7982,21 +8236,87 @@ targets:
   build: test
   language: c++
   headers:
+  - src/core/ext/transport/binder/client/binder_connector.h
+  - src/core/ext/transport/binder/client/channel_create_impl.h
+  - src/core/ext/transport/binder/client/connection_id_generator.h
+  - src/core/ext/transport/binder/client/endpoint_binder_pool.h
+  - src/core/ext/transport/binder/client/jni_utils.h
+  - src/core/ext/transport/binder/client/security_policy_setting.h
+  - src/core/ext/transport/binder/server/binder_server.h
+  - src/core/ext/transport/binder/transport/binder_stream.h
+  - src/core/ext/transport/binder/transport/binder_transport.h
   - src/core/ext/transport/binder/utils/transport_stream_receiver.h
   - src/core/ext/transport/binder/utils/transport_stream_receiver_impl.h
   - src/core/ext/transport/binder/wire_format/binder.h
+  - src/core/ext/transport/binder/wire_format/binder_android.h
   - src/core/ext/transport/binder/wire_format/binder_constants.h
   - src/core/ext/transport/binder/wire_format/transaction.h
   - src/core/ext/transport/binder/wire_format/wire_reader.h
   - src/core/ext/transport/binder/wire_format/wire_reader_impl.h
   - src/core/ext/transport/binder/wire_format/wire_writer.h
+  - src/cpp/client/create_channel_internal.h
+  - src/cpp/common/channel_filter.h
+  - src/cpp/server/dynamic_thread_pool.h
+  - src/cpp/server/external_connection_acceptor_impl.h
+  - src/cpp/server/health/default_health_check_service.h
+  - src/cpp/server/thread_pool_interface.h
+  - src/cpp/thread_manager/thread_manager.h
   - test/core/transport/binder/mock_objects.h
   src:
+  - src/core/ext/transport/binder/client/binder_connector.cc
+  - src/core/ext/transport/binder/client/channel_create.cc
+  - src/core/ext/transport/binder/client/channel_create_impl.cc
+  - src/core/ext/transport/binder/client/connection_id_generator.cc
+  - src/core/ext/transport/binder/client/endpoint_binder_pool.cc
+  - src/core/ext/transport/binder/client/jni_utils.cc
+  - src/core/ext/transport/binder/client/security_policy_setting.cc
+  - src/core/ext/transport/binder/security_policy/binder_security_policy.cc
+  - src/core/ext/transport/binder/server/binder_server.cc
+  - src/core/ext/transport/binder/server/binder_server_credentials.cc
+  - src/core/ext/transport/binder/transport/binder_transport.cc
   - src/core/ext/transport/binder/utils/transport_stream_receiver_impl.cc
+  - src/core/ext/transport/binder/wire_format/binder_android.cc
   - src/core/ext/transport/binder/wire_format/binder_constants.cc
   - src/core/ext/transport/binder/wire_format/transaction.cc
   - src/core/ext/transport/binder/wire_format/wire_reader_impl.cc
   - src/core/ext/transport/binder/wire_format/wire_writer.cc
+  - src/cpp/client/channel_cc.cc
+  - src/cpp/client/client_callback.cc
+  - src/cpp/client/client_context.cc
+  - src/cpp/client/client_interceptor.cc
+  - src/cpp/client/create_channel.cc
+  - src/cpp/client/create_channel_internal.cc
+  - src/cpp/client/create_channel_posix.cc
+  - src/cpp/client/credentials_cc.cc
+  - src/cpp/codegen/codegen_init.cc
+  - src/cpp/common/alarm.cc
+  - src/cpp/common/channel_arguments.cc
+  - src/cpp/common/channel_filter.cc
+  - src/cpp/common/completion_queue_cc.cc
+  - src/cpp/common/core_codegen.cc
+  - src/cpp/common/resource_quota_cc.cc
+  - src/cpp/common/rpc_method.cc
+  - src/cpp/common/validate_service_config.cc
+  - src/cpp/common/version_cc.cc
+  - src/cpp/server/async_generic_service.cc
+  - src/cpp/server/channel_argument_option.cc
+  - src/cpp/server/create_default_thread_pool.cc
+  - src/cpp/server/dynamic_thread_pool.cc
+  - src/cpp/server/external_connection_acceptor_impl.cc
+  - src/cpp/server/health/default_health_check_service.cc
+  - src/cpp/server/health/health_check_service.cc
+  - src/cpp/server/health/health_check_service_server_builder_option.cc
+  - src/cpp/server/server_builder.cc
+  - src/cpp/server/server_callback.cc
+  - src/cpp/server/server_cc.cc
+  - src/cpp/server/server_context.cc
+  - src/cpp/server/server_credentials.cc
+  - src/cpp/server/server_posix.cc
+  - src/cpp/thread_manager/thread_manager.cc
+  - src/cpp/util/byte_buffer_cc.cc
+  - src/cpp/util/status.cc
+  - src/cpp/util/string_ref.cc
+  - src/cpp/util/time_cc.cc
   - test/core/transport/binder/mock_objects.cc
   - test/core/transport/binder/wire_reader_test.cc
   deps:
@@ -8007,21 +8327,87 @@ targets:
   build: test
   language: c++
   headers:
+  - src/core/ext/transport/binder/client/binder_connector.h
+  - src/core/ext/transport/binder/client/channel_create_impl.h
+  - src/core/ext/transport/binder/client/connection_id_generator.h
+  - src/core/ext/transport/binder/client/endpoint_binder_pool.h
+  - src/core/ext/transport/binder/client/jni_utils.h
+  - src/core/ext/transport/binder/client/security_policy_setting.h
+  - src/core/ext/transport/binder/server/binder_server.h
+  - src/core/ext/transport/binder/transport/binder_stream.h
+  - src/core/ext/transport/binder/transport/binder_transport.h
   - src/core/ext/transport/binder/utils/transport_stream_receiver.h
   - src/core/ext/transport/binder/utils/transport_stream_receiver_impl.h
   - src/core/ext/transport/binder/wire_format/binder.h
+  - src/core/ext/transport/binder/wire_format/binder_android.h
   - src/core/ext/transport/binder/wire_format/binder_constants.h
   - src/core/ext/transport/binder/wire_format/transaction.h
   - src/core/ext/transport/binder/wire_format/wire_reader.h
   - src/core/ext/transport/binder/wire_format/wire_reader_impl.h
   - src/core/ext/transport/binder/wire_format/wire_writer.h
+  - src/cpp/client/create_channel_internal.h
+  - src/cpp/common/channel_filter.h
+  - src/cpp/server/dynamic_thread_pool.h
+  - src/cpp/server/external_connection_acceptor_impl.h
+  - src/cpp/server/health/default_health_check_service.h
+  - src/cpp/server/thread_pool_interface.h
+  - src/cpp/thread_manager/thread_manager.h
   - test/core/transport/binder/mock_objects.h
   src:
+  - src/core/ext/transport/binder/client/binder_connector.cc
+  - src/core/ext/transport/binder/client/channel_create.cc
+  - src/core/ext/transport/binder/client/channel_create_impl.cc
+  - src/core/ext/transport/binder/client/connection_id_generator.cc
+  - src/core/ext/transport/binder/client/endpoint_binder_pool.cc
+  - src/core/ext/transport/binder/client/jni_utils.cc
+  - src/core/ext/transport/binder/client/security_policy_setting.cc
+  - src/core/ext/transport/binder/security_policy/binder_security_policy.cc
+  - src/core/ext/transport/binder/server/binder_server.cc
+  - src/core/ext/transport/binder/server/binder_server_credentials.cc
+  - src/core/ext/transport/binder/transport/binder_transport.cc
   - src/core/ext/transport/binder/utils/transport_stream_receiver_impl.cc
+  - src/core/ext/transport/binder/wire_format/binder_android.cc
   - src/core/ext/transport/binder/wire_format/binder_constants.cc
   - src/core/ext/transport/binder/wire_format/transaction.cc
   - src/core/ext/transport/binder/wire_format/wire_reader_impl.cc
   - src/core/ext/transport/binder/wire_format/wire_writer.cc
+  - src/cpp/client/channel_cc.cc
+  - src/cpp/client/client_callback.cc
+  - src/cpp/client/client_context.cc
+  - src/cpp/client/client_interceptor.cc
+  - src/cpp/client/create_channel.cc
+  - src/cpp/client/create_channel_internal.cc
+  - src/cpp/client/create_channel_posix.cc
+  - src/cpp/client/credentials_cc.cc
+  - src/cpp/codegen/codegen_init.cc
+  - src/cpp/common/alarm.cc
+  - src/cpp/common/channel_arguments.cc
+  - src/cpp/common/channel_filter.cc
+  - src/cpp/common/completion_queue_cc.cc
+  - src/cpp/common/core_codegen.cc
+  - src/cpp/common/resource_quota_cc.cc
+  - src/cpp/common/rpc_method.cc
+  - src/cpp/common/validate_service_config.cc
+  - src/cpp/common/version_cc.cc
+  - src/cpp/server/async_generic_service.cc
+  - src/cpp/server/channel_argument_option.cc
+  - src/cpp/server/create_default_thread_pool.cc
+  - src/cpp/server/dynamic_thread_pool.cc
+  - src/cpp/server/external_connection_acceptor_impl.cc
+  - src/cpp/server/health/default_health_check_service.cc
+  - src/cpp/server/health/health_check_service.cc
+  - src/cpp/server/health/health_check_service_server_builder_option.cc
+  - src/cpp/server/server_builder.cc
+  - src/cpp/server/server_callback.cc
+  - src/cpp/server/server_cc.cc
+  - src/cpp/server/server_context.cc
+  - src/cpp/server/server_credentials.cc
+  - src/cpp/server/server_posix.cc
+  - src/cpp/thread_manager/thread_manager.cc
+  - src/cpp/util/byte_buffer_cc.cc
+  - src/cpp/util/status.cc
+  - src/cpp/util/string_ref.cc
+  - src/cpp/util/time_cc.cc
   - test/core/transport/binder/mock_objects.cc
   - test/core/transport/binder/wire_writer_test.cc
   deps:
@@ -8132,7 +8518,7 @@ targets:
   - src/proto/grpc/testing/echo_messages.proto
   - src/proto/grpc/testing/simple_messages.proto
   - test/cpp/end2end/test_service_impl.cc
-  - test/cpp/end2end/xds_credentials_end2end_test.cc
+  - test/cpp/end2end/xds/xds_credentials_end2end_test.cc
   deps:
   - grpc++_test_util
 - name: xds_credentials_test
@@ -8151,7 +8537,9 @@ targets:
   language: c++
   headers:
   - src/cpp/server/csds/csds.h
+  - test/cpp/end2end/counted_service.h
   - test/cpp/end2end/test_service_impl.h
+  - test/cpp/end2end/xds/xds_server.h
   src:
   - src/proto/grpc/testing/duplicate/echo_duplicate.proto
   - src/proto/grpc/testing/echo.proto
@@ -8189,7 +8577,8 @@ targets:
   - src/proto/grpc/testing/xds/v3/tls.proto
   - src/cpp/server/csds/csds.cc
   - test/cpp/end2end/test_service_impl.cc
-  - test/cpp/end2end/xds_end2end_test.cc
+  - test/cpp/end2end/xds/xds_end2end_test.cc
+  - test/cpp/end2end/xds/xds_server.cc
   deps:
   - grpc++_test_config
   - grpc++_test_util
index 7b89bc5..17abefa 100644 (file)
@@ -13,5 +13,5 @@
 # limitations under the License.
 
 module GrpcBuildConfig
-  CORE_WINDOWS_DLL = '/tmp/libs/opt/grpc-19.dll'
+  CORE_WINDOWS_DLL = '/tmp/libs/opt/grpc-20.dll'
 end
index d6f7c3e..3a1a2c8 100644 (file)
@@ -12,11 +12,11 @@ settings:
   '#08': Use "-preN" suffixes to identify pre-release versions
   '#09': Per-language overrides are possible with (eg) ruby_version tag here
   '#10': See the expand_version.py for all the quirks here
-  core_version: 19.0.0
+  core_version: 20.0.0
   csharp_major_version: 2
-  g_stands_for: goat
-  protobuf_version: 3.17.3
-  version: 1.41.1
+  g_stands_for: granola
+  protobuf_version: 3.18.1
+  version: 1.42.0
 targets:
 - name: check_epollexclusive
   build: tool
index 9467e7e..fc45fa0 100644 (file)
--- a/config.m4
+++ b/config.m4
@@ -66,6 +66,7 @@ if test "$PHP_GRPC" != "no"; then
     src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc \
     src/core/ext/filters/client_channel/lb_policy/priority/priority.cc \
     src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc \
+    src/core/ext/filters/client_channel/lb_policy/rls/rls.cc \
     src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc \
     src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc \
     src/core/ext/filters/client_channel/lb_policy/xds/cds.cc \
@@ -76,6 +77,7 @@ if test "$PHP_GRPC" != "no"; then
     src/core/ext/filters/client_channel/local_subchannel_pool.cc \
     src/core/ext/filters/client_channel/proxy_mapper_registry.cc \
     src/core/ext/filters/client_channel/resolver.cc \
+    src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc \
     src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc \
     src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_event_engine.cc \
     src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc \
@@ -96,12 +98,11 @@ if test "$PHP_GRPC" != "no"; then
     src/core/ext/filters/client_channel/retry_service_config.cc \
     src/core/ext/filters/client_channel/retry_throttle.cc \
     src/core/ext/filters/client_channel/server_address.cc \
-    src/core/ext/filters/client_channel/service_config.cc \
     src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc \
-    src/core/ext/filters/client_channel/service_config_parser.cc \
     src/core/ext/filters/client_channel/subchannel.cc \
     src/core/ext/filters/client_channel/subchannel_pool_interface.cc \
     src/core/ext/filters/client_idle/client_idle_filter.cc \
+    src/core/ext/filters/client_idle/idle_filter_state.cc \
     src/core/ext/filters/deadline/deadline_filter.cc \
     src/core/ext/filters/fault_injection/fault_injection_filter.cc \
     src/core/ext/filters/fault_injection/service_config_parser.cc \
@@ -113,10 +114,9 @@ if test "$PHP_GRPC" != "no"; then
     src/core/ext/filters/http/server/http_server_filter.cc \
     src/core/ext/filters/max_age/max_age_filter.cc \
     src/core/ext/filters/message_size/message_size_filter.cc \
-    src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc \
-    src/core/ext/filters/workarounds/workaround_utils.cc \
+    src/core/ext/service_config/service_config.cc \
+    src/core/ext/service_config/service_config_parser.cc \
     src/core/ext/transport/chttp2/alpn/alpn.cc \
-    src/core/ext/transport/chttp2/client/authority.cc \
     src/core/ext/transport/chttp2/client/chttp2_connector.cc \
     src/core/ext/transport/chttp2/client/insecure/channel_create.cc \
     src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc \
@@ -128,7 +128,6 @@ if test "$PHP_GRPC" != "no"; then
     src/core/ext/transport/chttp2/transport/bin_decoder.cc \
     src/core/ext/transport/chttp2/transport/bin_encoder.cc \
     src/core/ext/transport/chttp2/transport/chttp2_plugin.cc \
-    src/core/ext/transport/chttp2/transport/chttp2_slice_allocator.cc \
     src/core/ext/transport/chttp2/transport/chttp2_transport.cc \
     src/core/ext/transport/chttp2/transport/context_list.cc \
     src/core/ext/transport/chttp2/transport/flow_control.cc \
@@ -145,7 +144,6 @@ if test "$PHP_GRPC" != "no"; then
     src/core/ext/transport/chttp2/transport/hpack_utils.cc \
     src/core/ext/transport/chttp2/transport/http2_settings.cc \
     src/core/ext/transport/chttp2/transport/huffsyms.cc \
-    src/core/ext/transport/chttp2/transport/incoming_metadata.cc \
     src/core/ext/transport/chttp2/transport/parsing.cc \
     src/core/ext/transport/chttp2/transport/stream_lists.cc \
     src/core/ext/transport/chttp2/transport/stream_map.cc \
@@ -242,20 +240,22 @@ if test "$PHP_GRPC" != "no"; then
     src/core/ext/upb-generated/src/proto/grpc/gcp/transport_security_common.upb.c \
     src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.c \
     src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c \
+    src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls.upb.c \
     src/core/ext/upb-generated/udpa/annotations/migrate.upb.c \
     src/core/ext/upb-generated/udpa/annotations/security.upb.c \
     src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c \
     src/core/ext/upb-generated/udpa/annotations/status.upb.c \
     src/core/ext/upb-generated/udpa/annotations/versioning.upb.c \
-    src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c \
-    src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.c \
     src/core/ext/upb-generated/validate/validate.upb.c \
+    src/core/ext/upb-generated/xds/annotations/v3/status.upb.c \
     src/core/ext/upb-generated/xds/core/v3/authority.upb.c \
     src/core/ext/upb-generated/xds/core/v3/collection_entry.upb.c \
     src/core/ext/upb-generated/xds/core/v3/context_params.upb.c \
     src/core/ext/upb-generated/xds/core/v3/resource.upb.c \
     src/core/ext/upb-generated/xds/core/v3/resource_locator.upb.c \
     src/core/ext/upb-generated/xds/core/v3/resource_name.upb.c \
+    src/core/ext/upb-generated/xds/data/orca/v3/orca_load_report.upb.c \
+    src/core/ext/upb-generated/xds/type/v3/typed_struct.upb.c \
     src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.c \
     src/core/ext/upbdefs-generated/envoy/annotations/deprecation.upbdefs.c \
     src/core/ext/upbdefs-generated/envoy/annotations/resource.upbdefs.c \
@@ -342,20 +342,22 @@ if test "$PHP_GRPC" != "no"; then
     src/core/ext/upbdefs-generated/udpa/annotations/sensitive.upbdefs.c \
     src/core/ext/upbdefs-generated/udpa/annotations/status.upbdefs.c \
     src/core/ext/upbdefs-generated/udpa/annotations/versioning.upbdefs.c \
-    src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.c \
     src/core/ext/upbdefs-generated/validate/validate.upbdefs.c \
+    src/core/ext/upbdefs-generated/xds/annotations/v3/status.upbdefs.c \
     src/core/ext/upbdefs-generated/xds/core/v3/authority.upbdefs.c \
     src/core/ext/upbdefs-generated/xds/core/v3/collection_entry.upbdefs.c \
     src/core/ext/upbdefs-generated/xds/core/v3/context_params.upbdefs.c \
     src/core/ext/upbdefs-generated/xds/core/v3/resource.upbdefs.c \
     src/core/ext/upbdefs-generated/xds/core/v3/resource_locator.upbdefs.c \
     src/core/ext/upbdefs-generated/xds/core/v3/resource_name.upbdefs.c \
+    src/core/ext/upbdefs-generated/xds/type/v3/typed_struct.upbdefs.c \
     src/core/ext/xds/certificate_provider_registry.cc \
     src/core/ext/xds/certificate_provider_store.cc \
     src/core/ext/xds/file_watcher_certificate_provider_factory.cc \
     src/core/ext/xds/xds_api.cc \
     src/core/ext/xds/xds_bootstrap.cc \
     src/core/ext/xds/xds_certificate_provider.cc \
+    src/core/ext/xds/xds_channel_stack_modifier.cc \
     src/core/ext/xds/xds_client.cc \
     src/core/ext/xds/xds_client_stats.cc \
     src/core/ext/xds/xds_http_fault_filter.cc \
@@ -524,7 +526,6 @@ if test "$PHP_GRPC" != "no"; then
     src/core/lib/iomgr/timer_generic.cc \
     src/core/lib/iomgr/timer_heap.cc \
     src/core/lib/iomgr/timer_manager.cc \
-    src/core/lib/iomgr/udp_server.cc \
     src/core/lib/iomgr/unix_sockets_posix.cc \
     src/core/lib/iomgr/unix_sockets_posix_noop.cc \
     src/core/lib/iomgr/wakeup_fd_eventfd.cc \
@@ -596,10 +597,15 @@ if test "$PHP_GRPC" != "no"; then
     src/core/lib/slice/b64.cc \
     src/core/lib/slice/percent_encoding.cc \
     src/core/lib/slice/slice.cc \
+    src/core/lib/slice/slice_api.cc \
     src/core/lib/slice/slice_buffer.cc \
     src/core/lib/slice/slice_intern.cc \
+    src/core/lib/slice/slice_refcount.cc \
+    src/core/lib/slice/slice_split.cc \
     src/core/lib/slice/slice_string_helpers.cc \
+    src/core/lib/slice/static_slice.cc \
     src/core/lib/surface/api_trace.cc \
+    src/core/lib/surface/builtins.cc \
     src/core/lib/surface/byte_buffer.cc \
     src/core/lib/surface/byte_buffer_reader.cc \
     src/core/lib/surface/call.cc \
@@ -619,7 +625,6 @@ if test "$PHP_GRPC" != "no"; then
     src/core/lib/surface/server.cc \
     src/core/lib/surface/validate_metadata.cc \
     src/core/lib/surface/version.cc \
-    src/core/lib/transport/authority_override.cc \
     src/core/lib/transport/bdp_estimator.cc \
     src/core/lib/transport/byte_stream.cc \
     src/core/lib/transport/connectivity_state.cc \
@@ -1057,7 +1062,7 @@ if test "$PHP_GRPC" != "no"; then
     -D_HAS_EXCEPTIONS=0 -DNOMINMAX -DGRPC_ARES=0 \
     -DGRPC_POSIX_FORK_ALLOW_PTHREAD_ATFORK=1 \
     -DGRPC_XDS_USER_AGENT_NAME_SUFFIX='"\"PHP\""' \
-    -DGRPC_XDS_USER_AGENT_VERSION_SUFFIX='"\"1.41.1\""')
+    -DGRPC_XDS_USER_AGENT_VERSION_SUFFIX='"\"1.42.0\""')
 
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/census)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel)
@@ -1067,9 +1072,11 @@ if test "$PHP_GRPC" != "no"; then
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/lb_policy/pick_first)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/lb_policy/priority)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/lb_policy/ring_hash)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/lb_policy/rls)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/lb_policy/round_robin)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/lb_policy/weighted_target)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/lb_policy/xds)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/resolver/binder)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/resolver/dns)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/resolver/dns/c_ares)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/resolver/dns/native)
@@ -1086,7 +1093,7 @@ if test "$PHP_GRPC" != "no"; then
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/http/server)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/max_age)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/message_size)
-  PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/workarounds)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/service_config)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/alpn)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/client)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/client/insecure)
@@ -1134,11 +1141,13 @@ if test "$PHP_GRPC" != "no"; then
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/src/proto/grpc/gcp)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/src/proto/grpc/health/v1)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/src/proto/grpc/lb/v1)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/src/proto/grpc/lookup/v1)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/udpa/annotations)
-  PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/udpa/data/orca/v1)
-  PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/udpa/type/v1)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/validate)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/xds/annotations/v3)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/xds/core/v3)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/xds/data/orca/v3)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/xds/type/v3)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/admin/v3)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/annotations)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/config/accesslog/v3)
@@ -1173,9 +1182,10 @@ if test "$PHP_GRPC" != "no"; then
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/google/protobuf)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/google/rpc)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/udpa/annotations)
-  PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/udpa/type/v1)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/validate)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/xds/annotations/v3)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/xds/core/v3)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/xds/type/v3)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/xds)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/address_utils)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/avl)
index 3e46c07..07270cf 100644 (file)
@@ -32,6 +32,7 @@ if (PHP_GRPC != "no") {
     "src\\core\\ext\\filters\\client_channel\\lb_policy\\pick_first\\pick_first.cc " +
     "src\\core\\ext\\filters\\client_channel\\lb_policy\\priority\\priority.cc " +
     "src\\core\\ext\\filters\\client_channel\\lb_policy\\ring_hash\\ring_hash.cc " +
+    "src\\core\\ext\\filters\\client_channel\\lb_policy\\rls\\rls.cc " +
     "src\\core\\ext\\filters\\client_channel\\lb_policy\\round_robin\\round_robin.cc " +
     "src\\core\\ext\\filters\\client_channel\\lb_policy\\weighted_target\\weighted_target.cc " +
     "src\\core\\ext\\filters\\client_channel\\lb_policy\\xds\\cds.cc " +
@@ -42,6 +43,7 @@ if (PHP_GRPC != "no") {
     "src\\core\\ext\\filters\\client_channel\\local_subchannel_pool.cc " +
     "src\\core\\ext\\filters\\client_channel\\proxy_mapper_registry.cc " +
     "src\\core\\ext\\filters\\client_channel\\resolver.cc " +
+    "src\\core\\ext\\filters\\client_channel\\resolver\\binder\\binder_resolver.cc " +
     "src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares\\dns_resolver_ares.cc " +
     "src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares\\grpc_ares_ev_driver_event_engine.cc " +
     "src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares\\grpc_ares_ev_driver_posix.cc " +
@@ -62,12 +64,11 @@ if (PHP_GRPC != "no") {
     "src\\core\\ext\\filters\\client_channel\\retry_service_config.cc " +
     "src\\core\\ext\\filters\\client_channel\\retry_throttle.cc " +
     "src\\core\\ext\\filters\\client_channel\\server_address.cc " +
-    "src\\core\\ext\\filters\\client_channel\\service_config.cc " +
     "src\\core\\ext\\filters\\client_channel\\service_config_channel_arg_filter.cc " +
-    "src\\core\\ext\\filters\\client_channel\\service_config_parser.cc " +
     "src\\core\\ext\\filters\\client_channel\\subchannel.cc " +
     "src\\core\\ext\\filters\\client_channel\\subchannel_pool_interface.cc " +
     "src\\core\\ext\\filters\\client_idle\\client_idle_filter.cc " +
+    "src\\core\\ext\\filters\\client_idle\\idle_filter_state.cc " +
     "src\\core\\ext\\filters\\deadline\\deadline_filter.cc " +
     "src\\core\\ext\\filters\\fault_injection\\fault_injection_filter.cc " +
     "src\\core\\ext\\filters\\fault_injection\\service_config_parser.cc " +
@@ -79,10 +80,9 @@ if (PHP_GRPC != "no") {
     "src\\core\\ext\\filters\\http\\server\\http_server_filter.cc " +
     "src\\core\\ext\\filters\\max_age\\max_age_filter.cc " +
     "src\\core\\ext\\filters\\message_size\\message_size_filter.cc " +
-    "src\\core\\ext\\filters\\workarounds\\workaround_cronet_compression_filter.cc " +
-    "src\\core\\ext\\filters\\workarounds\\workaround_utils.cc " +
+    "src\\core\\ext\\service_config\\service_config.cc " +
+    "src\\core\\ext\\service_config\\service_config_parser.cc " +
     "src\\core\\ext\\transport\\chttp2\\alpn\\alpn.cc " +
-    "src\\core\\ext\\transport\\chttp2\\client\\authority.cc " +
     "src\\core\\ext\\transport\\chttp2\\client\\chttp2_connector.cc " +
     "src\\core\\ext\\transport\\chttp2\\client\\insecure\\channel_create.cc " +
     "src\\core\\ext\\transport\\chttp2\\client\\insecure\\channel_create_posix.cc " +
@@ -94,7 +94,6 @@ if (PHP_GRPC != "no") {
     "src\\core\\ext\\transport\\chttp2\\transport\\bin_decoder.cc " +
     "src\\core\\ext\\transport\\chttp2\\transport\\bin_encoder.cc " +
     "src\\core\\ext\\transport\\chttp2\\transport\\chttp2_plugin.cc " +
-    "src\\core\\ext\\transport\\chttp2\\transport\\chttp2_slice_allocator.cc " +
     "src\\core\\ext\\transport\\chttp2\\transport\\chttp2_transport.cc " +
     "src\\core\\ext\\transport\\chttp2\\transport\\context_list.cc " +
     "src\\core\\ext\\transport\\chttp2\\transport\\flow_control.cc " +
@@ -111,7 +110,6 @@ if (PHP_GRPC != "no") {
     "src\\core\\ext\\transport\\chttp2\\transport\\hpack_utils.cc " +
     "src\\core\\ext\\transport\\chttp2\\transport\\http2_settings.cc " +
     "src\\core\\ext\\transport\\chttp2\\transport\\huffsyms.cc " +
-    "src\\core\\ext\\transport\\chttp2\\transport\\incoming_metadata.cc " +
     "src\\core\\ext\\transport\\chttp2\\transport\\parsing.cc " +
     "src\\core\\ext\\transport\\chttp2\\transport\\stream_lists.cc " +
     "src\\core\\ext\\transport\\chttp2\\transport\\stream_map.cc " +
@@ -208,20 +206,22 @@ if (PHP_GRPC != "no") {
     "src\\core\\ext\\upb-generated\\src\\proto\\grpc\\gcp\\transport_security_common.upb.c " +
     "src\\core\\ext\\upb-generated\\src\\proto\\grpc\\health\\v1\\health.upb.c " +
     "src\\core\\ext\\upb-generated\\src\\proto\\grpc\\lb\\v1\\load_balancer.upb.c " +
+    "src\\core\\ext\\upb-generated\\src\\proto\\grpc\\lookup\\v1\\rls.upb.c " +
     "src\\core\\ext\\upb-generated\\udpa\\annotations\\migrate.upb.c " +
     "src\\core\\ext\\upb-generated\\udpa\\annotations\\security.upb.c " +
     "src\\core\\ext\\upb-generated\\udpa\\annotations\\sensitive.upb.c " +
     "src\\core\\ext\\upb-generated\\udpa\\annotations\\status.upb.c " +
     "src\\core\\ext\\upb-generated\\udpa\\annotations\\versioning.upb.c " +
-    "src\\core\\ext\\upb-generated\\udpa\\data\\orca\\v1\\orca_load_report.upb.c " +
-    "src\\core\\ext\\upb-generated\\udpa\\type\\v1\\typed_struct.upb.c " +
     "src\\core\\ext\\upb-generated\\validate\\validate.upb.c " +
+    "src\\core\\ext\\upb-generated\\xds\\annotations\\v3\\status.upb.c " +
     "src\\core\\ext\\upb-generated\\xds\\core\\v3\\authority.upb.c " +
     "src\\core\\ext\\upb-generated\\xds\\core\\v3\\collection_entry.upb.c " +
     "src\\core\\ext\\upb-generated\\xds\\core\\v3\\context_params.upb.c " +
     "src\\core\\ext\\upb-generated\\xds\\core\\v3\\resource.upb.c " +
     "src\\core\\ext\\upb-generated\\xds\\core\\v3\\resource_locator.upb.c " +
     "src\\core\\ext\\upb-generated\\xds\\core\\v3\\resource_name.upb.c " +
+    "src\\core\\ext\\upb-generated\\xds\\data\\orca\\v3\\orca_load_report.upb.c " +
+    "src\\core\\ext\\upb-generated\\xds\\type\\v3\\typed_struct.upb.c " +
     "src\\core\\ext\\upbdefs-generated\\envoy\\admin\\v3\\config_dump.upbdefs.c " +
     "src\\core\\ext\\upbdefs-generated\\envoy\\annotations\\deprecation.upbdefs.c " +
     "src\\core\\ext\\upbdefs-generated\\envoy\\annotations\\resource.upbdefs.c " +
@@ -308,20 +308,22 @@ if (PHP_GRPC != "no") {
     "src\\core\\ext\\upbdefs-generated\\udpa\\annotations\\sensitive.upbdefs.c " +
     "src\\core\\ext\\upbdefs-generated\\udpa\\annotations\\status.upbdefs.c " +
     "src\\core\\ext\\upbdefs-generated\\udpa\\annotations\\versioning.upbdefs.c " +
-    "src\\core\\ext\\upbdefs-generated\\udpa\\type\\v1\\typed_struct.upbdefs.c " +
     "src\\core\\ext\\upbdefs-generated\\validate\\validate.upbdefs.c " +
+    "src\\core\\ext\\upbdefs-generated\\xds\\annotations\\v3\\status.upbdefs.c " +
     "src\\core\\ext\\upbdefs-generated\\xds\\core\\v3\\authority.upbdefs.c " +
     "src\\core\\ext\\upbdefs-generated\\xds\\core\\v3\\collection_entry.upbdefs.c " +
     "src\\core\\ext\\upbdefs-generated\\xds\\core\\v3\\context_params.upbdefs.c " +
     "src\\core\\ext\\upbdefs-generated\\xds\\core\\v3\\resource.upbdefs.c " +
     "src\\core\\ext\\upbdefs-generated\\xds\\core\\v3\\resource_locator.upbdefs.c " +
     "src\\core\\ext\\upbdefs-generated\\xds\\core\\v3\\resource_name.upbdefs.c " +
+    "src\\core\\ext\\upbdefs-generated\\xds\\type\\v3\\typed_struct.upbdefs.c " +
     "src\\core\\ext\\xds\\certificate_provider_registry.cc " +
     "src\\core\\ext\\xds\\certificate_provider_store.cc " +
     "src\\core\\ext\\xds\\file_watcher_certificate_provider_factory.cc " +
     "src\\core\\ext\\xds\\xds_api.cc " +
     "src\\core\\ext\\xds\\xds_bootstrap.cc " +
     "src\\core\\ext\\xds\\xds_certificate_provider.cc " +
+    "src\\core\\ext\\xds\\xds_channel_stack_modifier.cc " +
     "src\\core\\ext\\xds\\xds_client.cc " +
     "src\\core\\ext\\xds\\xds_client_stats.cc " +
     "src\\core\\ext\\xds\\xds_http_fault_filter.cc " +
@@ -490,7 +492,6 @@ if (PHP_GRPC != "no") {
     "src\\core\\lib\\iomgr\\timer_generic.cc " +
     "src\\core\\lib\\iomgr\\timer_heap.cc " +
     "src\\core\\lib\\iomgr\\timer_manager.cc " +
-    "src\\core\\lib\\iomgr\\udp_server.cc " +
     "src\\core\\lib\\iomgr\\unix_sockets_posix.cc " +
     "src\\core\\lib\\iomgr\\unix_sockets_posix_noop.cc " +
     "src\\core\\lib\\iomgr\\wakeup_fd_eventfd.cc " +
@@ -562,10 +563,15 @@ if (PHP_GRPC != "no") {
     "src\\core\\lib\\slice\\b64.cc " +
     "src\\core\\lib\\slice\\percent_encoding.cc " +
     "src\\core\\lib\\slice\\slice.cc " +
+    "src\\core\\lib\\slice\\slice_api.cc " +
     "src\\core\\lib\\slice\\slice_buffer.cc " +
     "src\\core\\lib\\slice\\slice_intern.cc " +
+    "src\\core\\lib\\slice\\slice_refcount.cc " +
+    "src\\core\\lib\\slice\\slice_split.cc " +
     "src\\core\\lib\\slice\\slice_string_helpers.cc " +
+    "src\\core\\lib\\slice\\static_slice.cc " +
     "src\\core\\lib\\surface\\api_trace.cc " +
+    "src\\core\\lib\\surface\\builtins.cc " +
     "src\\core\\lib\\surface\\byte_buffer.cc " +
     "src\\core\\lib\\surface\\byte_buffer_reader.cc " +
     "src\\core\\lib\\surface\\call.cc " +
@@ -585,7 +591,6 @@ if (PHP_GRPC != "no") {
     "src\\core\\lib\\surface\\server.cc " +
     "src\\core\\lib\\surface\\validate_metadata.cc " +
     "src\\core\\lib\\surface\\version.cc " +
-    "src\\core\\lib\\transport\\authority_override.cc " +
     "src\\core\\lib\\transport\\bdp_estimator.cc " +
     "src\\core\\lib\\transport\\byte_stream.cc " +
     "src\\core\\lib\\transport\\connectivity_state.cc " +
@@ -1065,10 +1070,12 @@ if (PHP_GRPC != "no") {
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\lb_policy\\pick_first");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\lb_policy\\priority");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\lb_policy\\ring_hash");
+  FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\lb_policy\\rls");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\lb_policy\\round_robin");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\lb_policy\\weighted_target");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\lb_policy\\xds");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\resolver");
+  FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\resolver\\binder");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\resolver\\dns");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\resolver\\dns\\native");
@@ -1085,7 +1092,7 @@ if (PHP_GRPC != "no") {
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\http\\server");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\max_age");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\message_size");
-  FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\workarounds");
+  FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\service_config");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\transport");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\transport\\chttp2");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\transport\\chttp2\\alpn");
@@ -1183,17 +1190,21 @@ if (PHP_GRPC != "no") {
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\src\\proto\\grpc\\health\\v1");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\src\\proto\\grpc\\lb");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\src\\proto\\grpc\\lb\\v1");
+  FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\src\\proto\\grpc\\lookup");
+  FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\src\\proto\\grpc\\lookup\\v1");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\udpa");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\udpa\\annotations");
-  FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\udpa\\data");
-  FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\udpa\\data\\orca");
-  FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\udpa\\data\\orca\\v1");
-  FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\udpa\\type");
-  FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\udpa\\type\\v1");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\validate");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\xds");
+  FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\xds\\annotations");
+  FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\xds\\annotations\\v3");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\xds\\core");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\xds\\core\\v3");
+  FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\xds\\data");
+  FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\xds\\data\\orca");
+  FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\xds\\data\\orca\\v3");
+  FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\xds\\type");
+  FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\xds\\type\\v3");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\admin");
@@ -1270,12 +1281,14 @@ if (PHP_GRPC != "no") {
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\google\\rpc");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\udpa");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\udpa\\annotations");
-  FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\udpa\\type");
-  FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\udpa\\type\\v1");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\validate");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\xds");
+  FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\xds\\annotations");
+  FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\xds\\annotations\\v3");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\xds\\core");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\xds\\core\\v3");
+  FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\xds\\type");
+  FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\xds\\type\\v3");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\xds");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\address_utils");
index 48c2292..8a19eca 100644 (file)
@@ -76,6 +76,7 @@ some configuration as environment variables that can be set.
   - priority_lb - traces priority LB policy
   - resource_quota - trace resource quota objects internals
   - ring_hash_lb - traces the ring hash load balancing policy
+  - rls_lb - traces the RLS load balancing policy
   - round_robin - traces the round_robin load balancing policy
   - queue_pluck
   - sdk_authz - traces sdk authorization
index 35b477a..29ce903 100644 (file)
@@ -41,3 +41,4 @@
 - 1.39 'g' stands for ['goofy'](https://github.com/grpc/grpc/tree/v1.39.x)
 - 1.40 'g' stands for ['guileless'](https://github.com/grpc/grpc/tree/v1.40.x)
 - 1.41 'g' stands for ['goat'](https://github.com/grpc/grpc/tree/v1.41.x)
+- 1.42 'g' stands for ['granola'](https://github.com/grpc/grpc/tree/v1.42.x)
index 1e8124e..44ebfc0 100644 (file)
@@ -57,10 +57,10 @@ Features | gRFCs  | [C++, Python,<br> Ruby, PHP](https://github.com/grpc/grpc/re
 **Load Balancing:**<ul><li>[Virtual host](https://www.envoyproxy.io/docs/envoy/latest/api-v2/api/v2/route/route_components.proto#route-virtualhost) domains matching</li><li>Only default path ("" or "/") matching</li><li>Priority-based weighted round-robin locality picking</li><li>Round-robin endpoint picking within locality</li><li>[Cluster](https://www.envoyproxy.io/docs/envoy/latest/api-v2/api/v2/route/route_components.proto#envoy-api-msg-route-routeaction) route action</li><li>Client-side Load reporting via [LRS](https://github.com/envoyproxy/data-plane-api/blob/master/envoy/service/load_stats/v2/lrs.proto)</li></ul> | [A27](https://github.com/grpc/proposal/blob/master/A27-xds-global-load-balancing.md) | v1.30.0  | v1.30.0 | v1.30.0 | v1.2.0 |
 Request matching based on:<ul><li>[Path](https://www.envoyproxy.io/docs/envoy/latest/api-v2/api/v2/route/route_components.proto#route-routematch) (prefix, full path and safe regex)</li><ul><li>[case_sensitive](https://www.envoyproxy.io/docs/envoy/latest/api-v2/api/v2/route/route_components.proto#route-routematch) must be true else config is NACKed</li></ul><li>[Headers](https://www.envoyproxy.io/docs/envoy/latest/api-v2/api/v2/route/route_components.proto#route-headermatcher)</li></ul>Request routing to multiple clusters based on [weights](https://www.envoyproxy.io/docs/envoy/latest/api-v2/api/v2/route/route_components.proto#route-weightedcluster) | [A28](https://github.com/grpc/proposal/blob/master/A28-xds-traffic-splitting-and-routing.md) | v1.31.0 | v1.31.0 | v1.31.0 | v1.3.0 |
 Case insensitive prefix/full path matching:<ul><li>[case_sensitive](https://www.envoyproxy.io/docs/envoy/latest/api-v2/api/v2/route/route_components.proto#route-routematch) can be true or false</li></ul> | | v1.34.0 | v1.34.0 | v1.34.0 | v1.3.0 |
-Support for [xDS v3 APIs](https://www.envoyproxy.io/docs/envoy/latest/api-v3/api) | [A30](https://github.com/grpc/proposal/blob/master/A30-xds-v3.md) | v1.36.0 | v1.36.0 | v1.36.0 | |
-[Maximum Stream Duration](https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto#config-route-v3-routeaction-maxstreamduration):<ul><li>Only max_stream_duration is supported.</li></ul> | [A31](https://github.com/grpc/proposal/blob/master/A31-xds-timeout-support-and-config-selector.md) | v1.37.1  | v1.37.1 | v1.37.0 | |
-[Circuit Breaking](https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/cluster/v3/circuit_breaker.proto):<ul><li>Only max_requests is supported.</li></ul> | [A32](https://github.com/grpc/proposal/blob/master/A32-xds-circuit-breaking.md) | v1.37.1 (N/A for PHP) | v1.37.1 | v1.37.0 | |
-[Fault Injection](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/fault/v3/fault.proto):<br> Only the following fields are supported:<ul><li>delay</li><li>abort</li><li>max_active_faults</li><li>headers</li></ul> | [A33](https://github.com/grpc/proposal/blob/master/A33-Fault-Injection.md) | v1.37.1  | v1.37.1 | v1.37.0 | |
+Support for [xDS v3 APIs](https://www.envoyproxy.io/docs/envoy/latest/api-v3/api) | [A30](https://github.com/grpc/proposal/blob/master/A30-xds-v3.md) | v1.36.0 | v1.36.0 | v1.36.0 | v1.4.0 |
+[Maximum Stream Duration](https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto#config-route-v3-routeaction-maxstreamduration):<ul><li>Only max_stream_duration is supported.</li></ul> | [A31](https://github.com/grpc/proposal/blob/master/A31-xds-timeout-support-and-config-selector.md) | v1.37.1  | v1.37.1 | v1.37.0 | v1.4.0 |
+[Circuit Breaking](https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/cluster/v3/circuit_breaker.proto):<ul><li>Only max_requests is supported.</li></ul> | [A32](https://github.com/grpc/proposal/blob/master/A32-xds-circuit-breaking.md) | v1.37.1 (N/A for PHP) | v1.37.1 | v1.37.0 | v1.4.0 |
+[Fault Injection](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/fault/v3/fault.proto):<br> Only the following fields are supported:<ul><li>delay</li><li>abort</li><li>max_active_faults</li><li>headers</li></ul> | [A33](https://github.com/grpc/proposal/blob/master/A33-Fault-Injection.md) | v1.37.1  | v1.37.1 | v1.37.0 | v1.4.0 |
 [Client Status Discovery Service](https://github.com/envoyproxy/envoy/blob/main/api/envoy/service/status/v3/csds.proto) | [A40](https://github.com/grpc/proposal/blob/master/A40-csds-support.md) | v1.37.1 (C++)<br>v1.38.0 (Python)  | v1.37.1 | v1.37.0 | |
-[Ring hash](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/load_balancing/load_balancers#ring-hash) load balancing policy:<br> Only the following [policy specifiers](https://github.com/envoyproxy/envoy/blob/2443032526cf6e50d63d35770df9473dd0460fc0/api/envoy/config/route/v3/route_components.proto#L706) are supported:<ul><li>header</li><li>filter_state with key `io.grpc.channel_id`</li></ul>Only [`XX_HASH`](https://github.com/envoyproxy/envoy/blob/2443032526cf6e50d63d35770df9473dd0460fc0/api/envoy/config/cluster/v3/cluster.proto#L383) function is supported. | [A42](https://github.com/grpc/proposal/blob/master/A42-xds-ring-hash-lb-policy.md) | v1.40.0 | v1.40.1 | |
-[Retry](https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto#envoy-v3-api-msg-config-route-v3-retrypolicy):<br>Only the following fields are supported:<ul><li>retry_on for the following conditions: cancelled, deadline-exceeded, internal, resource-exhausted, and unavailable.</li><li>num_retries</li><li>retry_back_off</li></ul> | [A44](https://github.com/grpc/proposal/blob/master/A44-xds-retry.md) | v1.40.0 | v1.40.1 | | |
+[Ring hash](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/load_balancing/load_balancers#ring-hash) load balancing policy:<br> Only the following [policy specifiers](https://github.com/envoyproxy/envoy/blob/2443032526cf6e50d63d35770df9473dd0460fc0/api/envoy/config/route/v3/route_components.proto#L706) are supported:<ul><li>header</li><li>filter_state with key `io.grpc.channel_id`</li></ul>Only [`XX_HASH`](https://github.com/envoyproxy/envoy/blob/2443032526cf6e50d63d35770df9473dd0460fc0/api/envoy/config/cluster/v3/cluster.proto#L383) function is supported. | [A42](https://github.com/grpc/proposal/blob/master/A42-xds-ring-hash-lb-policy.md) | v1.40.0<br>(C++ and Python) | v1.40.1 | 1.41.0 | |
+[Retry](https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto#envoy-v3-api-msg-config-route-v3-retrypolicy):<br>Only the following fields are supported:<ul><li>retry_on for the following conditions: cancelled, deadline-exceeded, internal, resource-exhausted, and unavailable.</li><li>num_retries</li><li>retry_back_off</li></ul> | [A44](https://github.com/grpc/proposal/blob/master/A44-xds-retry.md) | v1.40.0<br>(C++ and Python) | v1.40.1 | 1.41.0 | |
index 8ff9407..743b779 100644 (file)
@@ -7,96 +7,31 @@ This document explains the design for load balancing within gRPC.
 
 # Background
 
-## Per-Call Load Balancing
-
-It is worth noting that load-balancing within gRPC happens on a per-call
-basis, not a per-connection basis.  In other words, even if all requests
-come from a single client, we still want them to be load-balanced across
-all servers.
-
-## Approaches to Load Balancing
-
-Prior to any gRPC specifics, we explore some usual ways to approach load
-balancing.
-
-### Proxy Model
-
-Using a proxy provides a solid trustable client that can report load to the load
-balancing system. Proxies typically require more resources to operate since they
-have temporary copies of the RPC request and response. This model also increases
-latency to the RPCs.
-
-The proxy model was deemed inefficient when considering request heavy services
-like storage.
-
-### Balancing-aware Client
-
-This thicker client places more of the load balancing logic in the client. For
-example, the client could contain many load balancing policies (Round Robin,
-Random, etc) used to select servers from a list. In this model, a list of
-servers would be either statically configured in the client, provided by the
-name resolution system, an external load balancer, etc. In any case, the client
-is responsible for choosing the preferred server from the list.
-
-One of the drawbacks of this approach is writing and maintaining the load
-balancing policies in multiple languages and/or versions of the clients. These
-policies can be fairly complicated. Some of the algorithms also require client
-to server communication so the client would need to get thicker to support
-additional RPCs to get health or load information in addition to sending RPCs
-for user requests.
-
-It would also significantly complicate the client's code: the new design hides
-the load balancing complexity of multiple layers and presents it as a simple
-list of servers to the client.
-
-### External Load Balancing Service
-
-The client load balancing code is kept simple and portable, implementing
-well-known algorithms (e.g., Round Robin) for server selection.
-Complex load balancing algorithms are instead provided by the load
-balancer. The client relies on the load balancer to provide _load
-balancing configuration_ and _the list of servers_ to which the client
-should send requests. The balancer updates the server list as needed
-to balance the load as well as handle server unavailability or health
-issues. The load balancer will make any necessary complex decisions and
-inform the client. The load balancer may communicate with the backend
-servers to collect load and health information.
-
-# Requirements
-
-## Simple API and client
-
-The gRPC client load balancing code must be simple and portable. The
-client should only contain simple algorithms (e.g., Round Robin) for
-server selection.  For complex algorithms, the client should rely on
-a load balancer to provide load balancing configuration and the list of
-servers to which the client should send requests. The balancer will update
-the server list as needed to balance the load as well as handle server
-unavailability or health issues. The load balancer will make any necessary
-complex decisions and inform the client. The load balancer may communicate
-with the backend servers to collect load and health information.
-
-## Security
-
-The load balancer may be separate from the actual server backends and a
-compromise of the load balancer should only lead to a compromise of the
-loadbalancing functionality. In other words, a compromised load balancer should
-not be able to cause a client to trust a (potentially malicious) backend server
-any more than in a comparable situation without loadbalancing.
+Load-balancing within gRPC happens on a per-call basis, not a
+per-connection basis.  In other words, even if all requests come from a
+single client, we still want them to be load-balanced across all servers.
 
 # Architecture
 
 ## Overview
 
-The primary mechanism for load-balancing in gRPC is external
-load-balancing, where an external load balancer provides simple clients
-with an up-to-date list of servers.
-
-The gRPC client does support an API for built-in load balancing policies.
-However, there are only a small number of these (one of which is the
-`grpclb` policy, which implements external load balancing), and users
-are discouraged from trying to extend gRPC by adding more.  Instead, new
-load balancing policies should be implemented in external load balancers.
+The gRPC client supports an API that allows load balancing policies to
+be implemented and plugged into gRPC.  An LB policy is responsible for:
+- receiving updated configuration and list of server addresses from the
+  resolver
+- creating subchannels for the server addresses and managing their
+  connectivity behavior
+- setting the overall [connectivity state](connectivity-semantics-and-api.md)
+  (usually computed by aggregating the connectivity states of its subchannels)
+  of the channel
+- for each RPC sent on the channel, determining which subchannel to send
+  the RPC on
+
+There are a number of LB policies provided with gRPC.  The most
+notable ones are `pick_first` (the default), `round_robin`, and
+`grpclb`.  There are also a number of additional LB policies to support
+[xDS](grpc_xds_features.md), although they are not currently configurable
+directly.
 
 ## Workflow
 
@@ -107,40 +42,99 @@ works:
 ![image](images/load-balancing.png)
 
 1. On startup, the gRPC client issues a [name resolution](naming.md) request
-   for the server name.  The name will resolve to one or more IP addresses,
-   each of which will indicate whether it is a server address or
-   a load balancer address, and a [service config](service_config.md)
-   that indicates which client-side load-balancing policy to use (e.g.,
-   `round_robin` or `grpclb`).
-2. The client instantiates the load balancing policy.
-   - Note: If any one of the addresses returned by the resolver is a balancer
-     address, then the client will use the `grpclb` policy, regardless
-     of what load-balancing policy was requested by the service config.
-     Otherwise, the client will use the load-balancing policy requested
-     by the service config.  If no load-balancing policy is requested
-     by the service config, then the client will default to a policy
-     that picks the first available server address.
-3. The load balancing policy creates a subchannel to each server address.
-   - For all policies *except* `grpclb`, this means one subchannel for each
-     address returned by the resolver. Note that these policies
-     ignore any balancer addresses returned by the resolver.
-   - In the case of the `grpclb` policy, the workflow is as follows:
-     1. The policy opens a stream to one of the balancer addresses returned
-        by the resolver. It asks the balancer for the server addresses to
-        use for the server name originally requested by the client (i.e.,
-        the same one originally passed to the name resolver).
-        - Note: In the `grpclb` policy, the non-balancer addresses returned
-          by the resolver are used as a fallback in case no balancers can be
-          contacted when the LB policy is started.
-     2. The gRPC servers to which the load balancer is directing the client
-        may report load to the load balancers, if that information is needed
-        by the load balancer's configuration.
-     3. The load balancer returns a server list to the gRPC client's `grpclb`
-        policy. The `grpclb` policy will then create a subchannel to each of
-        server in the list.
+   for the server name.  The name will resolve to a list of IP addresses,
+   a [service config](service_config.md) that indicates which client-side
+   load-balancing policy to use (e.g., `round_robin` or `grpclb`) and
+   provides a configuration for that policy, and a set of attributes
+   (channel args in C-core).
+2. The client instantiates the load balancing policy and passes it its
+   configuration from the service config, the list of IP addresses, and
+   the attributes.
+3. The load balancing policy creates a set of subchannels for the IP
+   addresses of the servers (which might be different from the IP
+   addresses returned by the resolver; see below).  It also watches the
+   subchannels' connectivity states and decides when each subchannel
+   should attempt to connect.
 4. For each RPC sent, the load balancing policy decides which
    subchannel (i.e., which server) the RPC should be sent to.
-   - In the case of the `grpclb` policy, the client will send requests
-     to the servers in the order in which they were returned by the load
-     balancer.  If the server list is empty, the call will block until a
-     non-empty one is received.
+
+See below for more information on `grpclb`.
+
+## Load Balancing Policies
+
+### `pick_first`
+
+This is the default LB policy if the service config does not specify any
+LB policy.  It does not require any configuration.
+
+The `pick_first` policy takes a list of addresses from the resolver.  It
+attempts to connect to those addresses one at a time, in order, until it
+finds one that is reachable.  If none of the addresses are reachable, it
+sets the channel's state to TRANSIENT_FAILURE while it attempts to
+reconnect.  Appropriate [backoff](connection-backoff.md) is applied for
+repeated connection attempts.
+
+If it is able to connect to one of the addresses, it sets the channel's
+state to READY, and then all RPCs sent on the channel will be sent to
+that address.  If the connection to that address is later broken,
+the `pick_first` policy will put the channel into state IDLE, and it
+will not attempt to reconnect until the application requests that it
+does so (either via the channel's connectivity state API or by sending
+an RPC).
+
+### `round_robin`
+
+This LB policy is selected via the service config.  It does not require
+any configuration.
+
+This policy takes a list of addresses from the resolver.  It creates a
+subchannel for each of those addresses and constantly monitors the
+connectivity state of the subchannels.  Whenever a subchannel becomes
+disconnected, the `round_robin` policy will ask it to reconnect, with
+appropriate connection [backoff](connection-backoff.md).
+
+The policy sets the channel's connectivity state by aggregating the
+states of the subchannels:
+- If any one subchannel is in READY state, the channel's state is READY.
+- Otherwise, if there is any subchannel in state CONNECTING, the channel's
+  state is CONNECTING.
+- Otherwise, if there is any subchannel in state IDLE, the channel's state is
+  IDLE.
+- Otherwise, if all subchannels are in state TRANSIENT_FAILURE, the channel's
+  state is TRANSIENT_FAILURE.
+
+Note that when a given subchannel reports TRANSIENT_FAILURE, it is
+considered to still be in TRANSIENT_FAILURE until it successfully
+reconnects and reports READY.  In particular, we ignore the transition
+from TRANSIENT_FAILURE to CONNECTING.
+
+When an RPC is sent on the channel, the `round_robin` policy will
+iterate over all subchannels that are currently in READY state, sending
+each successive RPC to the next successive subchannel in the list,
+wrapping around to the start of the list when needed.
+
+### `grpclb`
+
+(This policy is deprecated.  We recommend using [xDS](grpc_xds_features.md)
+instead.)
+
+This LB policy was originally intended as gRPC's primary extensibility
+mechanism for load balancing.  The intent was that instead of adding new
+LB policies directly in the client, the client could implement only
+simple algorithms like `round_robin`, and any more complex algorithms
+would be provided by a look-aside load balancer.
+
+The client relies on the load balancer to provide _load balancing
+configuration_ and _the list of server addresses_ to which the client should
+send requests. The balancer updates the server list as needed to balance
+the load as well as handle server unavailability or health issues. The
+load balancer will make any necessary complex decisions and inform the
+client. The load balancer may communicate with the backend servers to
+collect load and health information.
+
+The `grpclb` policy uses the addresses returned by the resolver (if any)
+as fallback addresses, which are used when it loses contact with the
+balancers.
+
+The `grpclb` policy gets the list of addresses of the balancers to talk to
+via an attribute returned by the resolver.
diff --git a/examples/android/binder/java/io/grpc/binder/cpp/README.md b/examples/android/binder/java/io/grpc/binder/cpp/README.md
new file mode 100644 (file)
index 0000000..d0817c0
--- /dev/null
@@ -0,0 +1,21 @@
+# gRPC-core BinderTransport example apps
+
+WIP.
+
+## Build Instruction
+
+1. Install Android SDK and NDK. Currently we only support SDK version 30.0.3 and
+   NDK version 21.4.7075529 . Make sure you get these exact versions otherwise
+   Bazel might complain.
+
+2. Point environment variables to install locations of SDK and NDK
+    ```
+    export ANDROID_HOME=$HOME/Android/Sdk/
+    export ANDROID_NDK_HOME=$HOME/Android/Sdk/ndk/21.4.7075529
+    ```
+3. `bazel build //examples/android/binder/java/io/grpc/binder/cpp/exampleclient:app`
+4. `bazel build //examples/android/binder/java/io/grpc/binder/cpp/exampleserver:app`
+5. `adb install
+   bazel-bin/examples/android/binder/java/io/grpc/binder/cpp/exampleclient/app.apk`
+6. `adb install
+   bazel-bin/examples/android/binder/java/io/grpc/binder/cpp/exampleserver/app.apk`
diff --git a/examples/android/binder/java/io/grpc/binder/cpp/example/AndroidManifest.xml b/examples/android/binder/java/io/grpc/binder/cpp/example/AndroidManifest.xml
deleted file mode 100644 (file)
index 7a60e90..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-<!-- TODO(mingcl): Rename this app to exampleclient -->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="io.grpc.binder.cpp.example"
-    android:versionCode="1"
-    android:versionName="1.0" >
-
-  <uses-sdk
-      android:minSdkVersion="29"
-      android:targetSdkVersion="30" />
-
-   <queries>
-      <package android:name="io.grpc.binder.cpp.exampleserver" />
-   </queries>
-
-  <application
-      android:label="gRPC BinderTransport Cpp">
-    <activity
-        android:name=".MainActivity"
-        android:label="gRPC BinderTransport Cpp" >
-      <intent-filter>
-        <action android:name="android.intent.action.MAIN" />
-        <category android:name="android.intent.category.LAUNCHER" />
-      </intent-filter>
-    </activity>
-  </application>
-</manifest>
diff --git a/examples/android/binder/java/io/grpc/binder/cpp/example/BUILD b/examples/android/binder/java/io/grpc/binder/cpp/example/BUILD
deleted file mode 100644 (file)
index 9ef5041..0000000
+++ /dev/null
@@ -1,55 +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.
-
-load("@build_bazel_rules_android//android:rules.bzl", "android_binary", "android_library")
-
-cc_library(
-    name = "jni_lib",
-    srcs = ["native.cc"],
-    linkopts = [
-        "-ldl",
-        "-llog",
-        "-lm",
-        "-lbinder_ndk",
-        "-Wl,--no-undefined",
-    ],
-    deps = [
-        # Temporarily directly depend on this target before we expose a public API
-        "//src/core/ext/transport/binder/client:grpc_transport_binder_client",
-        "//examples/protos:helloworld_cc_grpc",
-    ],
-    alwayslink = True,
-)
-
-android_library(
-    name = "activity",
-    srcs = [
-        "ButtonPressHandler.java",
-        "MainActivity.java",
-    ],
-    manifest = "AndroidManifest.xml",
-    resource_files = glob(["res/**"]),
-    deps = [
-        ":jni_lib",
-        "@binder_transport_android_helper//io/grpc/binder/cpp:connection_helper",
-    ],
-)
-
-android_binary(
-    name = "app",
-    manifest = "AndroidManifest.xml",
-    deps = [
-        ":activity",
-    ],
-)
diff --git a/examples/android/binder/java/io/grpc/binder/cpp/example/ButtonPressHandler.java b/examples/android/binder/java/io/grpc/binder/cpp/example/ButtonPressHandler.java
deleted file mode 100644 (file)
index 44e1e08..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-package io.grpc.binder.cpp.example;
-
-import android.app.Application;
-
-public class ButtonPressHandler {
-  static {
-    System.loadLibrary("app");
-  }
-
-  public native String native_entry(Application application);
-
-  public String onPressed(Application application) {
-    return native_entry(application);
-  }
-}
diff --git a/examples/android/binder/java/io/grpc/binder/cpp/example/MainActivity.java b/examples/android/binder/java/io/grpc/binder/cpp/example/MainActivity.java
deleted file mode 100644 (file)
index 0c87b2b..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-package io.grpc.binder.cpp.example;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.util.Log;
-import android.widget.Button;
-import android.widget.TextView;
-
-/** Main class for the example app. */
-public class MainActivity extends Activity {
-  @Override
-  public void onCreate(Bundle savedInstanceState) {
-    super.onCreate(savedInstanceState);
-    Log.v("Example", "hello, world");
-
-    setContentView(R.layout.activity_main);
-
-    Button clickMeButton = findViewById(R.id.clickMeButton);
-    TextView exampleTextView = findViewById(R.id.exampleTextView);
-
-    ButtonPressHandler h = new ButtonPressHandler();
-
-    clickMeButton.setOnClickListener(
-        v -> exampleTextView.setText(h.onPressed(getApplication())));
-  }
-}
diff --git a/examples/android/binder/java/io/grpc/binder/cpp/example/README.md b/examples/android/binder/java/io/grpc/binder/cpp/example/README.md
deleted file mode 100644 (file)
index bbc1545..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-# gRPC-core BinderTransport example app
-
-WIP.
-
-## Build Instruction
-
-1. Install Android SDK and NDK. Currently we only support SDK version 30.0.3 and
-   NDK version 21.4.7075529 . Make sure you get these exact versions otherwise
-   Bazel might complain.
-
-2. Point environment variables to install locations of SDK and NDK
-    ```
-    export ANDROID_HOME=$HOME/Android/Sdk/
-    export ANDROID_NDK_HOME=$HOME/Android/Sdk/ndk/21.4.7075529
-    ```
-3. `bazel build //examples/android/binder/java/io/grpc/binder/cpp/example:app`
-4. `adb install
-   bazel-bin/examples/android/binder/java/io/grpc/binder/cpp/example/app.apk`
diff --git a/examples/android/binder/java/io/grpc/binder/cpp/example/native.cc b/examples/android/binder/java/io/grpc/binder/cpp/example/native.cc
deleted file mode 100644 (file)
index 99f4941..0000000
+++ /dev/null
@@ -1,48 +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 <android/log.h>
-#include <jni.h>
-
-#include "examples/protos/helloworld.grpc.pb.h"
-#include "examples/protos/helloworld.pb.h"
-
-#include "src/core/ext/transport/binder/client/channel_create.h"
-
-extern "C" JNIEXPORT jstring JNICALL
-Java_io_grpc_binder_cpp_example_ButtonPressHandler_native_1entry(
-    JNIEnv* env, jobject /*this*/, jobject application) {
-  static bool first = true;
-  __android_log_print(ANDROID_LOG_INFO, "Demo", "Line number %d", __LINE__);
-  if (first) {
-    first = false;
-    grpc::experimental::BindToOnDeviceServerService(
-        env, application, "io.grpc.binder.cpp.exampleserver",
-        "io.grpc.binder.cpp.exampleserver.ExportedEndpointService");
-    return env->NewStringUTF("Clicked 1 time");
-  } else {
-    auto channel =
-        grpc::experimental::CreateBinderChannel(env, application, "", "");
-    auto stub = helloworld::Greeter::NewStub(channel);
-    grpc::ClientContext context;
-    helloworld::HelloRequest request;
-    helloworld::HelloReply response;
-    request.set_name("BinderTransportClient");
-    grpc::Status status = stub->SayHello(&context, request, &response);
-    if (status.ok()) {
-      return env->NewStringUTF(response.message().c_str());
-    }
-    return env->NewStringUTF("Clicked more than 1 time. Status not ok");
-  }
-}
diff --git a/examples/android/binder/java/io/grpc/binder/cpp/exampleclient/AndroidManifest.xml b/examples/android/binder/java/io/grpc/binder/cpp/exampleclient/AndroidManifest.xml
new file mode 100644 (file)
index 0000000..8dea155
--- /dev/null
@@ -0,0 +1,25 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="io.grpc.binder.cpp.exampleclient"
+    android:versionCode="1"
+    android:versionName="1.0" >
+
+  <uses-sdk
+      android:minSdkVersion="29"
+      android:targetSdkVersion="30" />
+
+   <queries>
+      <package android:name="io.grpc.binder.cpp.exampleserver" />
+   </queries>
+
+  <application
+      android:label="gRPC BinderTransport Client Cpp">
+    <activity
+        android:name=".MainActivity"
+        android:label="gRPC BinderTransport Client Cpp" >
+      <intent-filter>
+        <action android:name="android.intent.action.MAIN" />
+        <category android:name="android.intent.category.LAUNCHER" />
+      </intent-filter>
+    </activity>
+  </application>
+</manifest>
diff --git a/examples/android/binder/java/io/grpc/binder/cpp/exampleclient/BUILD b/examples/android/binder/java/io/grpc/binder/cpp/exampleclient/BUILD
new file mode 100644 (file)
index 0000000..3efffcd
--- /dev/null
@@ -0,0 +1,54 @@
+# 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.
+
+load("@build_bazel_rules_android//android:rules.bzl", "android_binary", "android_library")
+
+cc_library(
+    name = "jni_lib",
+    srcs = ["native.cc"],
+    linkopts = [
+        "-ldl",
+        "-llog",
+        "-lm",
+        "-lbinder_ndk",
+        "-Wl,--no-undefined",
+    ],
+    deps = [
+        "//:grpc++",
+        "//examples/protos:helloworld_cc_grpc",
+    ],
+    alwayslink = True,
+)
+
+android_library(
+    name = "activity",
+    srcs = [
+        "ButtonPressHandler.java",
+        "MainActivity.java",
+    ],
+    manifest = "AndroidManifest.xml",
+    resource_files = glob(["res/**"]),
+    deps = [
+        ":jni_lib",
+        "@binder_transport_android_helper//io/grpc/binder/cpp:connection_helper",
+    ],
+)
+
+android_binary(
+    name = "app",
+    manifest = "AndroidManifest.xml",
+    deps = [
+        ":activity",
+    ],
+)
diff --git a/examples/android/binder/java/io/grpc/binder/cpp/exampleclient/ButtonPressHandler.java b/examples/android/binder/java/io/grpc/binder/cpp/exampleclient/ButtonPressHandler.java
new file mode 100644 (file)
index 0000000..ed9d11a
--- /dev/null
@@ -0,0 +1,15 @@
+package io.grpc.binder.cpp.exampleclient;
+
+import android.app.Application;
+
+public class ButtonPressHandler {
+  static {
+    System.loadLibrary("app");
+  }
+
+  public native String native_entry(Application application);
+
+  public String onPressed(Application application) {
+    return native_entry(application);
+  }
+}
diff --git a/examples/android/binder/java/io/grpc/binder/cpp/exampleclient/MainActivity.java b/examples/android/binder/java/io/grpc/binder/cpp/exampleclient/MainActivity.java
new file mode 100644 (file)
index 0000000..3cbf70d
--- /dev/null
@@ -0,0 +1,26 @@
+package io.grpc.binder.cpp.exampleclient;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.util.Log;
+import android.widget.Button;
+import android.widget.TextView;
+
+/** Main class for the example app. */
+public class MainActivity extends Activity {
+  @Override
+  public void onCreate(Bundle savedInstanceState) {
+    super.onCreate(savedInstanceState);
+    Log.v("Example", "hello, world");
+
+    setContentView(R.layout.activity_main);
+
+    Button clickMeButton = findViewById(R.id.clickMeButton);
+    TextView exampleTextView = findViewById(R.id.exampleTextView);
+
+    ButtonPressHandler h = new ButtonPressHandler();
+
+    clickMeButton.setOnClickListener(
+        v -> exampleTextView.setText(h.onPressed(getApplication())));
+  }
+}
diff --git a/examples/android/binder/java/io/grpc/binder/cpp/exampleclient/native.cc b/examples/android/binder/java/io/grpc/binder/cpp/exampleclient/native.cc
new file mode 100644 (file)
index 0000000..2f0e7b9
--- /dev/null
@@ -0,0 +1,50 @@
+// 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 <android/log.h>
+#include <jni.h>
+
+#include "examples/protos/helloworld.grpc.pb.h"
+#include "examples/protos/helloworld.pb.h"
+
+#include <grpcpp/create_channel_binder.h>
+#include <grpcpp/security/binder_security_policy.h>
+
+extern "C" JNIEXPORT jstring JNICALL
+Java_io_grpc_binder_cpp_exampleclient_ButtonPressHandler_native_1entry(
+    JNIEnv* env, jobject /*this*/, jobject application) {
+  static bool first = true;
+  static std::shared_ptr<grpc::Channel> channel;
+  if (first) {
+    first = false;
+    // TODO(mingcl): Use same signature security after it become available
+    channel = grpc::experimental::CreateBinderChannel(
+        env, application, "io.grpc.binder.cpp.exampleserver",
+        "io.grpc.binder.cpp.exampleserver.ExportedEndpointService",
+        std::make_shared<
+            grpc::experimental::binder::UntrustedSecurityPolicy>());
+    return env->NewStringUTF("Clicked 1 time");
+  } else {
+    auto stub = helloworld::Greeter::NewStub(channel);
+    grpc::ClientContext context;
+    helloworld::HelloRequest request;
+    helloworld::HelloReply response;
+    request.set_name("BinderTransportClient");
+    grpc::Status status = stub->SayHello(&context, request, &response);
+    if (status.ok()) {
+      return env->NewStringUTF(response.message().c_str());
+    }
+    return env->NewStringUTF("Clicked more than 1 time. Status not ok");
+  }
+}
index 5bc44c4..df302fe 100644 (file)
@@ -25,8 +25,6 @@ cc_library(
         "-Wl,--no-undefined",
     ],
     deps = [
-        # Temporarily directly depend on this target before we expose a public API
-        "//src/core/ext/transport/binder/server:grpc_transport_binder_server",
         "//:grpc++",
         "//examples/protos:helloworld_cc_grpc",
     ],
@@ -52,7 +50,9 @@ android_library(
     srcs = ["ExportedEndpointService.java"],
     exports_manifest = True,
     manifest = "AndroidManifest_endpoint.xml",
-    deps = [],
+    deps = [
+        "@binder_transport_android_helper//io/grpc/binder/cpp:connection_helper",
+    ],
 )
 
 android_binary(
index 287b066..78412e6 100644 (file)
@@ -1,28 +1,25 @@
 package io.grpc.binder.cpp.exampleserver;
 
 import android.app.Service;
-import android.os.IBinder;
 import android.content.Intent;
+import android.os.IBinder;
+import io.grpc.binder.cpp.GrpcCppServerBuilder;
 
 /** Exposes gRPC services running in the main process */
 public final class ExportedEndpointService extends Service {
-  private final IBinder binder;
-
   static {
     System.loadLibrary("app");
   }
 
   public ExportedEndpointService() {
     init_grpc_server();
-    binder = get_endpoint_binder();
   }
 
   @Override
   public IBinder onBind(Intent intent) {
-    return binder;
+    // The argument should match the URI passed into grpc::ServerBuilder::AddListeningPort
+    return GrpcCppServerBuilder.GetEndpointBinder("binder:example.service");
   }
 
   public native void init_grpc_server();
-
-  public native IBinder get_endpoint_binder();
 }
index be79380..ef77d60 100644 (file)
@@ -23,9 +23,8 @@
 #include "examples/protos/helloworld.pb.h"
 
 #include <grpcpp/grpcpp.h>
-
-#include "src/core/ext/transport/binder/server/binder_server.h"
-#include "src/core/ext/transport/binder/server/binder_server_credentials.h"
+#include <grpcpp/security/binder_credentials.h>
+#include <grpcpp/security/binder_security_policy.h>
 
 namespace {
 class GreeterService : public helloworld::Greeter::Service {
@@ -60,23 +59,12 @@ Java_io_grpc_binder_cpp_exampleserver_ExportedEndpointService_init_1grpc_1server
   grpc::ServerBuilder server_builder;
   server_builder.RegisterService(&service);
 
+  // TODO(mingcl): Use same signature security after it become available
   server_builder.AddListeningPort(
-      "binder://example.service",
-      grpc::experimental::BinderServerCredentials());
+      "binder:example.service",
+      grpc::experimental::BinderServerCredentials(
+          std::make_shared<
+              grpc::experimental::binder::UntrustedSecurityPolicy>()));
 
   server = server_builder.BuildAndStart();
 }
-
-extern "C" JNIEXPORT jobject JNICALL
-Java_io_grpc_binder_cpp_exampleserver_ExportedEndpointService_get_1endpoint_1binder(
-    JNIEnv* env, jobject /*this*/) {
-  __android_log_print(ANDROID_LOG_INFO, "DemoServer", "Line number %d",
-                      __LINE__);
-
-  auto ai_binder = static_cast<AIBinder*>(
-      grpc::experimental::binder::GetEndpointBinder("example.service"));
-
-  __android_log_print(ANDROID_LOG_INFO, "DemoServer", "ai_binder = %p",
-                      ai_binder);
-  return AIBinder_toJavaBinder(env, ai_binder);
-}
index 8df2ecb..15485ed 100644 (file)
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-licenses(["notice"])  # 3-clause BSD
+licenses(["notice"])
 
 cc_binary(
     name = "compression_client",
index c9a0cc2..eb0d57e 100644 (file)
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-licenses(["notice"])  # 3-clause BSD
+licenses(["notice"])
 
 cc_binary(
     name = "greeter_client",
index ac1fec2..b6c7839 100644 (file)
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-licenses(["notice"])  # 3-clause BSD
+licenses(["notice"])
 
 cc_binary(
     name = "keyvaluestore_client",
index 52c07fd..b254eb9 100644 (file)
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-licenses(["notice"])  # 3-clause BSD
+licenses(["notice"])
 
 cc_binary(
     name = "lb_server",
index 90cb90c..d1848a9 100644 (file)
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-licenses(["notice"])  # 3-clause BSD
+licenses(["notice"])
 
 cc_binary(
     name = "metadata_client",
index 6f93549..3f04558 100644 (file)
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-licenses(["notice"])  # 3-clause BSD
+licenses(["notice"])
 
 cc_library(
     name = "route_guide_helper",
index 965da49..2d9861b 100644 (file)
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-licenses(["notice"])  # 3-clause BSD
+licenses(["notice"])
 
 package(default_visibility = ["//visibility:public"])
 
index 5418b88..911c868 100644 (file)
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-licenses(["notice"])  # 3-clause BSD
+licenses(["notice"])
 
 package(default_visibility = ["//visibility:public"])
 
index 28b7f57..cb6eaf4 100644 (file)
@@ -66,9 +66,9 @@ class CallMaker:
         logging.info("Call toward [%s] enters [%s] state", self._phone_number,
                      phone_pb2.CallState.State.Name(call_state))
         self._call_state = call_state
-        if call_state is phone_pb2.CallState.State.ACTIVE:
+        if call_state == phone_pb2.CallState.State.ACTIVE:
             self._peer_responded.set()
-        if call_state is phone_pb2.CallState.State.ENDED:
+        if call_state == phone_pb2.CallState.State.ENDED:
             self._peer_responded.set()
             self._call_finished.set()
 
@@ -80,13 +80,13 @@ class CallMaker:
         self._consumer_future = self._executor.submit(self._response_watcher,
                                                       response_iterator)
 
-    def wait_peer(self) -> None:
+    def wait_peer(self) -> bool:
         logging.info("Waiting for peer to connect [%s]...", self._phone_number)
         self._peer_responded.wait(timeout=None)
         if self._consumer_future.done():
             # If the future raises, forwards the exception here
             self._consumer_future.result()
-        return self._call_state is phone_pb2.CallState.State.ACTIVE
+        return self._call_state == phone_pb2.CallState.State.ACTIVE
 
     def audio_session(self) -> None:
         assert self._audio_session_link is not None
index 2eefb7a..eaf2c10 100644 (file)
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-licenses(["notice"])  # 3-clause BSD
+licenses(["notice"])
 
 load("@grpc_python_dependencies//:requirements.bzl", "requirement")
 
index 5869d24..70136ad 100644 (file)
@@ -22,7 +22,7 @@
 Pod::Spec.new do |s|
   s.name     = 'gRPC-C++'
   # TODO (mxyan): use version that match gRPC version when pod is stabilized
-  version = '1.41.1'
+  version = '1.42.0'
   s.version  = version
   s.summary  = 'gRPC C++ library'
   s.homepage = 'https://grpc.io'
@@ -51,7 +51,10 @@ Pod::Spec.new do |s|
 
   s.pod_target_xcconfig = {
     'HEADER_SEARCH_PATHS' => '"$(inherited)" "$(PODS_TARGET_SRCROOT)/include"',
-    'USER_HEADER_SEARCH_PATHS' => '"$(PODS_TARGET_SRCROOT)"',
+    'USER_HEADER_SEARCH_PATHS' => '"$(PODS_TARGET_SRCROOT)"'\
+        ' "$(PODS_TARGET_SRCROOT)/src/core/ext/upb-generated"'\
+        ' "$(PODS_TARGET_SRCROOT)/src/core/ext/upbdefs-generated"'\
+        ' "$(PODS_TARGET_SRCROOT)/third_party/**"',
     'GCC_PREPROCESSOR_DEFINITIONS' => '"$(inherited)" "COCOAPODS=1"',
     'CLANG_WARN_STRICT_PROTOTYPES' => 'NO',
     'CLANG_WARN_DOCUMENTATION_COMMENTS' => 'NO',
@@ -81,6 +84,7 @@ Pod::Spec.new do |s|
                       'include/grpcpp/client_context.h',
                       'include/grpcpp/completion_queue.h',
                       'include/grpcpp/create_channel.h',
+                      'include/grpcpp/create_channel_binder.h',
                       'include/grpcpp/create_channel_posix.h',
                       'include/grpcpp/ext/health_check_service_server_builder_option.h',
                       'include/grpcpp/generic/async_generic_service.h',
@@ -150,6 +154,8 @@ Pod::Spec.new do |s|
                       'include/grpcpp/security/auth_context.h',
                       'include/grpcpp/security/auth_metadata_processor.h',
                       'include/grpcpp/security/authorization_policy_provider.h',
+                      'include/grpcpp/security/binder_credentials.h',
+                      'include/grpcpp/security/binder_security_policy.h',
                       'include/grpcpp/security/credentials.h',
                       'include/grpcpp/security/server_credentials.h',
                       'include/grpcpp/security/tls_certificate_provider.h',
@@ -187,12 +193,13 @@ Pod::Spec.new do |s|
     ss.header_mappings_dir = '.'
     ss.dependency "#{s.name}/Interface", version
     ss.dependency 'gRPC-Core', version
-    abseil_version = '1.20210324.0'
+    abseil_version = '1.20210324.2'
     ss.dependency 'abseil/base/base', abseil_version
     ss.dependency 'abseil/base/core_headers', abseil_version
     ss.dependency 'abseil/container/flat_hash_map', abseil_version
     ss.dependency 'abseil/container/inlined_vector', abseil_version
     ss.dependency 'abseil/functional/bind_front', abseil_version
+    ss.dependency 'abseil/hash/hash', abseil_version
     ss.dependency 'abseil/memory/memory', abseil_version
     ss.dependency 'abseil/status/status', abseil_version
     ss.dependency 'abseil/status/statusor', abseil_version
@@ -203,6 +210,7 @@ Pod::Spec.new do |s|
     ss.dependency 'abseil/time/time', abseil_version
     ss.dependency 'abseil/types/optional', abseil_version
     ss.dependency 'abseil/types/variant', abseil_version
+    ss.dependency 'abseil/utility/utility', abseil_version
 
     ss.source_files = 'src/core/ext/filters/client_channel/backend_metric.h',
                       'src/core/ext/filters/client_channel/backup_poller.h',
@@ -247,12 +255,10 @@ Pod::Spec.new do |s|
                       'src/core/ext/filters/client_channel/retry_service_config.h',
                       'src/core/ext/filters/client_channel/retry_throttle.h',
                       'src/core/ext/filters/client_channel/server_address.h',
-                      'src/core/ext/filters/client_channel/service_config.h',
-                      'src/core/ext/filters/client_channel/service_config_call_data.h',
-                      'src/core/ext/filters/client_channel/service_config_parser.h',
                       'src/core/ext/filters/client_channel/subchannel.h',
                       'src/core/ext/filters/client_channel/subchannel_interface.h',
                       'src/core/ext/filters/client_channel/subchannel_pool_interface.h',
+                      'src/core/ext/filters/client_idle/idle_filter_state.h',
                       'src/core/ext/filters/deadline/deadline_filter.h',
                       'src/core/ext/filters/fault_injection/fault_injection_filter.h',
                       'src/core/ext/filters/fault_injection/service_config_parser.h',
@@ -263,15 +269,49 @@ Pod::Spec.new do |s|
                       'src/core/ext/filters/http/server/http_server_filter.h',
                       'src/core/ext/filters/max_age/max_age_filter.h',
                       'src/core/ext/filters/message_size/message_size_filter.h',
-                      'src/core/ext/filters/workarounds/workaround_cronet_compression_filter.h',
-                      'src/core/ext/filters/workarounds/workaround_utils.h',
+                      'src/core/ext/service_config/service_config.h',
+                      'src/core/ext/service_config/service_config_call_data.h',
+                      'src/core/ext/service_config/service_config_parser.h',
+                      'src/core/ext/transport/binder/client/binder_connector.cc',
+                      'src/core/ext/transport/binder/client/binder_connector.h',
+                      'src/core/ext/transport/binder/client/channel_create.cc',
+                      'src/core/ext/transport/binder/client/channel_create_impl.cc',
+                      'src/core/ext/transport/binder/client/channel_create_impl.h',
+                      'src/core/ext/transport/binder/client/connection_id_generator.cc',
+                      'src/core/ext/transport/binder/client/connection_id_generator.h',
+                      'src/core/ext/transport/binder/client/endpoint_binder_pool.cc',
+                      'src/core/ext/transport/binder/client/endpoint_binder_pool.h',
+                      'src/core/ext/transport/binder/client/jni_utils.cc',
+                      'src/core/ext/transport/binder/client/jni_utils.h',
+                      'src/core/ext/transport/binder/client/security_policy_setting.cc',
+                      'src/core/ext/transport/binder/client/security_policy_setting.h',
+                      'src/core/ext/transport/binder/security_policy/binder_security_policy.cc',
+                      'src/core/ext/transport/binder/server/binder_server.cc',
+                      'src/core/ext/transport/binder/server/binder_server.h',
+                      'src/core/ext/transport/binder/server/binder_server_credentials.cc',
+                      'src/core/ext/transport/binder/transport/binder_stream.h',
+                      'src/core/ext/transport/binder/transport/binder_transport.cc',
+                      'src/core/ext/transport/binder/transport/binder_transport.h',
+                      'src/core/ext/transport/binder/utils/transport_stream_receiver.h',
+                      'src/core/ext/transport/binder/utils/transport_stream_receiver_impl.cc',
+                      'src/core/ext/transport/binder/utils/transport_stream_receiver_impl.h',
+                      'src/core/ext/transport/binder/wire_format/binder.h',
+                      'src/core/ext/transport/binder/wire_format/binder_android.cc',
+                      'src/core/ext/transport/binder/wire_format/binder_android.h',
+                      'src/core/ext/transport/binder/wire_format/binder_constants.cc',
+                      'src/core/ext/transport/binder/wire_format/binder_constants.h',
+                      'src/core/ext/transport/binder/wire_format/transaction.cc',
+                      'src/core/ext/transport/binder/wire_format/transaction.h',
+                      'src/core/ext/transport/binder/wire_format/wire_reader.h',
+                      'src/core/ext/transport/binder/wire_format/wire_reader_impl.cc',
+                      'src/core/ext/transport/binder/wire_format/wire_reader_impl.h',
+                      'src/core/ext/transport/binder/wire_format/wire_writer.cc',
+                      'src/core/ext/transport/binder/wire_format/wire_writer.h',
                       'src/core/ext/transport/chttp2/alpn/alpn.h',
-                      'src/core/ext/transport/chttp2/client/authority.h',
                       'src/core/ext/transport/chttp2/client/chttp2_connector.h',
                       'src/core/ext/transport/chttp2/server/chttp2_server.h',
                       'src/core/ext/transport/chttp2/transport/bin_decoder.h',
                       'src/core/ext/transport/chttp2/transport/bin_encoder.h',
-                      'src/core/ext/transport/chttp2/transport/chttp2_slice_allocator.h',
                       'src/core/ext/transport/chttp2/transport/chttp2_transport.h',
                       'src/core/ext/transport/chttp2/transport/context_list.h',
                       'src/core/ext/transport/chttp2/transport/flow_control.h',
@@ -291,7 +331,6 @@ Pod::Spec.new do |s|
                       'src/core/ext/transport/chttp2/transport/hpack_utils.h',
                       'src/core/ext/transport/chttp2/transport/http2_settings.h',
                       'src/core/ext/transport/chttp2/transport/huffsyms.h',
-                      'src/core/ext/transport/chttp2/transport/incoming_metadata.h',
                       'src/core/ext/transport/chttp2/transport/internal.h',
                       'src/core/ext/transport/chttp2/transport/popularity_count.h',
                       'src/core/ext/transport/chttp2/transport/stream_map.h',
@@ -386,20 +425,22 @@ Pod::Spec.new do |s|
                       'src/core/ext/upb-generated/src/proto/grpc/gcp/transport_security_common.upb.h',
                       'src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.h',
                       'src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.h',
+                      'src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls.upb.h',
                       'src/core/ext/upb-generated/udpa/annotations/migrate.upb.h',
                       'src/core/ext/upb-generated/udpa/annotations/security.upb.h',
                       'src/core/ext/upb-generated/udpa/annotations/sensitive.upb.h',
                       'src/core/ext/upb-generated/udpa/annotations/status.upb.h',
                       'src/core/ext/upb-generated/udpa/annotations/versioning.upb.h',
-                      'src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h',
-                      'src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.h',
                       'src/core/ext/upb-generated/validate/validate.upb.h',
+                      'src/core/ext/upb-generated/xds/annotations/v3/status.upb.h',
                       'src/core/ext/upb-generated/xds/core/v3/authority.upb.h',
                       'src/core/ext/upb-generated/xds/core/v3/collection_entry.upb.h',
                       'src/core/ext/upb-generated/xds/core/v3/context_params.upb.h',
                       'src/core/ext/upb-generated/xds/core/v3/resource.upb.h',
                       'src/core/ext/upb-generated/xds/core/v3/resource_locator.upb.h',
                       'src/core/ext/upb-generated/xds/core/v3/resource_name.upb.h',
+                      'src/core/ext/upb-generated/xds/data/orca/v3/orca_load_report.upb.h',
+                      'src/core/ext/upb-generated/xds/type/v3/typed_struct.upb.h',
                       'src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.h',
                       'src/core/ext/upbdefs-generated/envoy/annotations/deprecation.upbdefs.h',
                       'src/core/ext/upbdefs-generated/envoy/annotations/resource.upbdefs.h',
@@ -486,14 +527,15 @@ Pod::Spec.new do |s|
                       'src/core/ext/upbdefs-generated/udpa/annotations/sensitive.upbdefs.h',
                       'src/core/ext/upbdefs-generated/udpa/annotations/status.upbdefs.h',
                       'src/core/ext/upbdefs-generated/udpa/annotations/versioning.upbdefs.h',
-                      'src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.h',
                       'src/core/ext/upbdefs-generated/validate/validate.upbdefs.h',
+                      'src/core/ext/upbdefs-generated/xds/annotations/v3/status.upbdefs.h',
                       'src/core/ext/upbdefs-generated/xds/core/v3/authority.upbdefs.h',
                       'src/core/ext/upbdefs-generated/xds/core/v3/collection_entry.upbdefs.h',
                       'src/core/ext/upbdefs-generated/xds/core/v3/context_params.upbdefs.h',
                       'src/core/ext/upbdefs-generated/xds/core/v3/resource.upbdefs.h',
                       'src/core/ext/upbdefs-generated/xds/core/v3/resource_locator.upbdefs.h',
                       'src/core/ext/upbdefs-generated/xds/core/v3/resource_name.upbdefs.h',
+                      'src/core/ext/upbdefs-generated/xds/type/v3/typed_struct.upbdefs.h',
                       'src/core/ext/xds/certificate_provider_factory.h',
                       'src/core/ext/xds/certificate_provider_registry.h',
                       'src/core/ext/xds/certificate_provider_store.h',
@@ -502,6 +544,7 @@ Pod::Spec.new do |s|
                       'src/core/ext/xds/xds_bootstrap.h',
                       'src/core/ext/xds/xds_certificate_provider.h',
                       'src/core/ext/xds/xds_channel_args.h',
+                      'src/core/ext/xds/xds_channel_stack_modifier.h',
                       'src/core/ext/xds/xds_client.h',
                       'src/core/ext/xds/xds_client_stats.h',
                       'src/core/ext/xds/xds_http_fault_filter.h',
@@ -549,6 +592,7 @@ Pod::Spec.new do |s|
                       'src/core/lib/gprpp/arena.h',
                       'src/core/lib/gprpp/atomic_utils.h',
                       'src/core/lib/gprpp/bitset.h',
+                      'src/core/lib/gprpp/chunked_vector.h',
                       'src/core/lib/gprpp/construct_destruct.h',
                       'src/core/lib/gprpp/debug_location.h',
                       'src/core/lib/gprpp/dual_ref_counted.h',
@@ -570,6 +614,7 @@ Pod::Spec.new do |s|
                       'src/core/lib/gprpp/stat.h',
                       'src/core/lib/gprpp/status_helper.h',
                       'src/core/lib/gprpp/sync.h',
+                      'src/core/lib/gprpp/table.h',
                       'src/core/lib/gprpp/thd.h',
                       'src/core/lib/gprpp/time_util.h',
                       'src/core/lib/http/format_request.h',
@@ -648,7 +693,6 @@ Pod::Spec.new do |s|
                       'src/core/lib/iomgr/timer_generic.h',
                       'src/core/lib/iomgr/timer_heap.h',
                       'src/core/lib/iomgr/timer_manager.h',
-                      'src/core/lib/iomgr/udp_server.h',
                       'src/core/lib/iomgr/unix_sockets_posix.h',
                       'src/core/lib/iomgr/wakeup_fd_pipe.h',
                       'src/core/lib/iomgr/wakeup_fd_posix.h',
@@ -707,9 +751,14 @@ Pod::Spec.new do |s|
                       'src/core/lib/slice/b64.h',
                       'src/core/lib/slice/percent_encoding.h',
                       'src/core/lib/slice/slice_internal.h',
+                      'src/core/lib/slice/slice_refcount.h',
+                      'src/core/lib/slice/slice_refcount_base.h',
+                      'src/core/lib/slice/slice_split.h',
                       'src/core/lib/slice/slice_string_helpers.h',
                       'src/core/lib/slice/slice_utils.h',
+                      'src/core/lib/slice/static_slice.h',
                       'src/core/lib/surface/api_trace.h',
+                      'src/core/lib/surface/builtins.h',
                       'src/core/lib/surface/call.h',
                       'src/core/lib/surface/call_test_only.h',
                       'src/core/lib/surface/channel.h',
@@ -722,7 +771,6 @@ Pod::Spec.new do |s|
                       'src/core/lib/surface/lame_client.h',
                       'src/core/lib/surface/server.h',
                       'src/core/lib/surface/validate_metadata.h',
-                      'src/core/lib/transport/authority_override.h',
                       'src/core/lib/transport/bdp_estimator.h',
                       'src/core/lib/transport/byte_stream.h',
                       'src/core/lib/transport/connectivity_state.h',
@@ -730,6 +778,7 @@ Pod::Spec.new do |s|
                       'src/core/lib/transport/http2_errors.h',
                       'src/core/lib/transport/metadata.h',
                       'src/core/lib/transport/metadata_batch.h',
+                      'src/core/lib/transport/parsed_metadata.h',
                       'src/core/lib/transport/pid_controller.h',
                       'src/core/lib/transport/static_metadata.h',
                       'src/core/lib/transport/status_conversion.h',
@@ -914,12 +963,10 @@ Pod::Spec.new do |s|
                               'src/core/ext/filters/client_channel/retry_service_config.h',
                               'src/core/ext/filters/client_channel/retry_throttle.h',
                               'src/core/ext/filters/client_channel/server_address.h',
-                              'src/core/ext/filters/client_channel/service_config.h',
-                              'src/core/ext/filters/client_channel/service_config_call_data.h',
-                              'src/core/ext/filters/client_channel/service_config_parser.h',
                               'src/core/ext/filters/client_channel/subchannel.h',
                               'src/core/ext/filters/client_channel/subchannel_interface.h',
                               'src/core/ext/filters/client_channel/subchannel_pool_interface.h',
+                              'src/core/ext/filters/client_idle/idle_filter_state.h',
                               'src/core/ext/filters/deadline/deadline_filter.h',
                               'src/core/ext/filters/fault_injection/fault_injection_filter.h',
                               'src/core/ext/filters/fault_injection/service_config_parser.h',
@@ -930,15 +977,32 @@ Pod::Spec.new do |s|
                               'src/core/ext/filters/http/server/http_server_filter.h',
                               'src/core/ext/filters/max_age/max_age_filter.h',
                               'src/core/ext/filters/message_size/message_size_filter.h',
-                              'src/core/ext/filters/workarounds/workaround_cronet_compression_filter.h',
-                              'src/core/ext/filters/workarounds/workaround_utils.h',
+                              'src/core/ext/service_config/service_config.h',
+                              'src/core/ext/service_config/service_config_call_data.h',
+                              'src/core/ext/service_config/service_config_parser.h',
+                              'src/core/ext/transport/binder/client/binder_connector.h',
+                              'src/core/ext/transport/binder/client/channel_create_impl.h',
+                              'src/core/ext/transport/binder/client/connection_id_generator.h',
+                              'src/core/ext/transport/binder/client/endpoint_binder_pool.h',
+                              'src/core/ext/transport/binder/client/jni_utils.h',
+                              'src/core/ext/transport/binder/client/security_policy_setting.h',
+                              'src/core/ext/transport/binder/server/binder_server.h',
+                              'src/core/ext/transport/binder/transport/binder_stream.h',
+                              'src/core/ext/transport/binder/transport/binder_transport.h',
+                              'src/core/ext/transport/binder/utils/transport_stream_receiver.h',
+                              'src/core/ext/transport/binder/utils/transport_stream_receiver_impl.h',
+                              'src/core/ext/transport/binder/wire_format/binder.h',
+                              'src/core/ext/transport/binder/wire_format/binder_android.h',
+                              'src/core/ext/transport/binder/wire_format/binder_constants.h',
+                              'src/core/ext/transport/binder/wire_format/transaction.h',
+                              'src/core/ext/transport/binder/wire_format/wire_reader.h',
+                              'src/core/ext/transport/binder/wire_format/wire_reader_impl.h',
+                              'src/core/ext/transport/binder/wire_format/wire_writer.h',
                               'src/core/ext/transport/chttp2/alpn/alpn.h',
-                              'src/core/ext/transport/chttp2/client/authority.h',
                               'src/core/ext/transport/chttp2/client/chttp2_connector.h',
                               'src/core/ext/transport/chttp2/server/chttp2_server.h',
                               'src/core/ext/transport/chttp2/transport/bin_decoder.h',
                               'src/core/ext/transport/chttp2/transport/bin_encoder.h',
-                              'src/core/ext/transport/chttp2/transport/chttp2_slice_allocator.h',
                               'src/core/ext/transport/chttp2/transport/chttp2_transport.h',
                               'src/core/ext/transport/chttp2/transport/context_list.h',
                               'src/core/ext/transport/chttp2/transport/flow_control.h',
@@ -958,7 +1022,6 @@ Pod::Spec.new do |s|
                               'src/core/ext/transport/chttp2/transport/hpack_utils.h',
                               'src/core/ext/transport/chttp2/transport/http2_settings.h',
                               'src/core/ext/transport/chttp2/transport/huffsyms.h',
-                              'src/core/ext/transport/chttp2/transport/incoming_metadata.h',
                               'src/core/ext/transport/chttp2/transport/internal.h',
                               'src/core/ext/transport/chttp2/transport/popularity_count.h',
                               'src/core/ext/transport/chttp2/transport/stream_map.h',
@@ -1053,20 +1116,22 @@ Pod::Spec.new do |s|
                               'src/core/ext/upb-generated/src/proto/grpc/gcp/transport_security_common.upb.h',
                               'src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.h',
                               'src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.h',
+                              'src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls.upb.h',
                               'src/core/ext/upb-generated/udpa/annotations/migrate.upb.h',
                               'src/core/ext/upb-generated/udpa/annotations/security.upb.h',
                               'src/core/ext/upb-generated/udpa/annotations/sensitive.upb.h',
                               'src/core/ext/upb-generated/udpa/annotations/status.upb.h',
                               'src/core/ext/upb-generated/udpa/annotations/versioning.upb.h',
-                              'src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h',
-                              'src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.h',
                               'src/core/ext/upb-generated/validate/validate.upb.h',
+                              'src/core/ext/upb-generated/xds/annotations/v3/status.upb.h',
                               'src/core/ext/upb-generated/xds/core/v3/authority.upb.h',
                               'src/core/ext/upb-generated/xds/core/v3/collection_entry.upb.h',
                               'src/core/ext/upb-generated/xds/core/v3/context_params.upb.h',
                               'src/core/ext/upb-generated/xds/core/v3/resource.upb.h',
                               'src/core/ext/upb-generated/xds/core/v3/resource_locator.upb.h',
                               'src/core/ext/upb-generated/xds/core/v3/resource_name.upb.h',
+                              'src/core/ext/upb-generated/xds/data/orca/v3/orca_load_report.upb.h',
+                              'src/core/ext/upb-generated/xds/type/v3/typed_struct.upb.h',
                               'src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.h',
                               'src/core/ext/upbdefs-generated/envoy/annotations/deprecation.upbdefs.h',
                               'src/core/ext/upbdefs-generated/envoy/annotations/resource.upbdefs.h',
@@ -1153,14 +1218,15 @@ Pod::Spec.new do |s|
                               'src/core/ext/upbdefs-generated/udpa/annotations/sensitive.upbdefs.h',
                               'src/core/ext/upbdefs-generated/udpa/annotations/status.upbdefs.h',
                               'src/core/ext/upbdefs-generated/udpa/annotations/versioning.upbdefs.h',
-                              'src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.h',
                               'src/core/ext/upbdefs-generated/validate/validate.upbdefs.h',
+                              'src/core/ext/upbdefs-generated/xds/annotations/v3/status.upbdefs.h',
                               'src/core/ext/upbdefs-generated/xds/core/v3/authority.upbdefs.h',
                               'src/core/ext/upbdefs-generated/xds/core/v3/collection_entry.upbdefs.h',
                               'src/core/ext/upbdefs-generated/xds/core/v3/context_params.upbdefs.h',
                               'src/core/ext/upbdefs-generated/xds/core/v3/resource.upbdefs.h',
                               'src/core/ext/upbdefs-generated/xds/core/v3/resource_locator.upbdefs.h',
                               'src/core/ext/upbdefs-generated/xds/core/v3/resource_name.upbdefs.h',
+                              'src/core/ext/upbdefs-generated/xds/type/v3/typed_struct.upbdefs.h',
                               'src/core/ext/xds/certificate_provider_factory.h',
                               'src/core/ext/xds/certificate_provider_registry.h',
                               'src/core/ext/xds/certificate_provider_store.h',
@@ -1169,6 +1235,7 @@ Pod::Spec.new do |s|
                               'src/core/ext/xds/xds_bootstrap.h',
                               'src/core/ext/xds/xds_certificate_provider.h',
                               'src/core/ext/xds/xds_channel_args.h',
+                              'src/core/ext/xds/xds_channel_stack_modifier.h',
                               'src/core/ext/xds/xds_client.h',
                               'src/core/ext/xds/xds_client_stats.h',
                               'src/core/ext/xds/xds_http_fault_filter.h',
@@ -1216,6 +1283,7 @@ Pod::Spec.new do |s|
                               'src/core/lib/gprpp/arena.h',
                               'src/core/lib/gprpp/atomic_utils.h',
                               'src/core/lib/gprpp/bitset.h',
+                              'src/core/lib/gprpp/chunked_vector.h',
                               'src/core/lib/gprpp/construct_destruct.h',
                               'src/core/lib/gprpp/debug_location.h',
                               'src/core/lib/gprpp/dual_ref_counted.h',
@@ -1237,6 +1305,7 @@ Pod::Spec.new do |s|
                               'src/core/lib/gprpp/stat.h',
                               'src/core/lib/gprpp/status_helper.h',
                               'src/core/lib/gprpp/sync.h',
+                              'src/core/lib/gprpp/table.h',
                               'src/core/lib/gprpp/thd.h',
                               'src/core/lib/gprpp/time_util.h',
                               'src/core/lib/http/format_request.h',
@@ -1315,7 +1384,6 @@ Pod::Spec.new do |s|
                               'src/core/lib/iomgr/timer_generic.h',
                               'src/core/lib/iomgr/timer_heap.h',
                               'src/core/lib/iomgr/timer_manager.h',
-                              'src/core/lib/iomgr/udp_server.h',
                               'src/core/lib/iomgr/unix_sockets_posix.h',
                               'src/core/lib/iomgr/wakeup_fd_pipe.h',
                               'src/core/lib/iomgr/wakeup_fd_posix.h',
@@ -1374,9 +1442,14 @@ Pod::Spec.new do |s|
                               'src/core/lib/slice/b64.h',
                               'src/core/lib/slice/percent_encoding.h',
                               'src/core/lib/slice/slice_internal.h',
+                              'src/core/lib/slice/slice_refcount.h',
+                              'src/core/lib/slice/slice_refcount_base.h',
+                              'src/core/lib/slice/slice_split.h',
                               'src/core/lib/slice/slice_string_helpers.h',
                               'src/core/lib/slice/slice_utils.h',
+                              'src/core/lib/slice/static_slice.h',
                               'src/core/lib/surface/api_trace.h',
+                              'src/core/lib/surface/builtins.h',
                               'src/core/lib/surface/call.h',
                               'src/core/lib/surface/call_test_only.h',
                               'src/core/lib/surface/channel.h',
@@ -1389,7 +1462,6 @@ Pod::Spec.new do |s|
                               'src/core/lib/surface/lame_client.h',
                               'src/core/lib/surface/server.h',
                               'src/core/lib/surface/validate_metadata.h',
-                              'src/core/lib/transport/authority_override.h',
                               'src/core/lib/transport/bdp_estimator.h',
                               'src/core/lib/transport/byte_stream.h',
                               'src/core/lib/transport/connectivity_state.h',
@@ -1397,6 +1469,7 @@ Pod::Spec.new do |s|
                               'src/core/lib/transport/http2_errors.h',
                               'src/core/lib/transport/metadata.h',
                               'src/core/lib/transport/metadata_batch.h',
+                              'src/core/lib/transport/parsed_metadata.h',
                               'src/core/lib/transport/pid_controller.h',
                               'src/core/lib/transport/static_metadata.h',
                               'src/core/lib/transport/status_conversion.h',
@@ -1517,18 +1590,11 @@ Pod::Spec.new do |s|
     ss.source_files = "src/cpp/client/cronet_credentials.cc"
   end
 
+  # patch include of openssl to openssl_grpc
+  # patch xxhash.h to silent the -Wdocumentation error
   s.prepare_command = <<-END_OF_COMMAND
+    set -e
     find src/core -type f \\( -path '*.h' -or -path '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include <openssl/(.*)>;#if COCOAPODS==1\\\n  #include <openssl_grpc/\\1>\\\n#else\\\n  #include <openssl/\\1>\\\n#endif;g'
-    find third_party/upb/ -type f \\( -name '*.h' -or -name '*.hpp' -or -name '*.c' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "third_party/(.*)";#if COCOAPODS==1\\\n  #include  "third_party/upb/third_party/\\1"\\\n#else\\\n  #include  "third_party/\\1"\\\n#endif;g'
-    find src/core/ src/cpp/ third_party/upb/ -type f \\( -name '*.h' -or -name '*.hpp' -or -name '*.c' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "upb/(.*)";#if COCOAPODS==1\\\n  #include  "third_party/upb/upb/\\1"\\\n#else\\\n  #include  "upb/\\1"\\\n#endif;g'
-    find src/core/ src/cpp/ third_party/upb/ -type f -name '*.grpc_back' -print0 | xargs -0 rm
-    find src/core/ src/cpp/ third_party/upb/ -type f \\( -name '*.h' -or -name '*.c' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "(.*).upb.h";#if COCOAPODS==1\\\n  #include  "src/core/ext/upb-generated/\\1.upb.h"\\\n#else\\\n  #include  "\\1.upb.h"\\\n#endif;g'
-    find src/core/ src/cpp/ third_party/upb/ -type f \\( -name '*.h' -or -name '*.c' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "(.*).upbdefs.h";#if COCOAPODS==1\\\n  #include  "src/core/ext/upbdefs-generated/\\1.upbdefs.h"\\\n#else\\\n  #include  "\\1.upbdefs.h"\\\n#endif;g'
-    find src/core/ src/cpp/ -type f -name '*.grpc_back' -print0 | xargs -0 rm
-    find third_party/re2/re2/ third_party/re2/util/ -type f \\( -name '*.h' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "re2/(.*)";#if COCOAPODS==1\\\n  #include  "third_party/re2/re2/\\1"\\\n#else\\\n  #include  "re2/\\1"\\\n#endif;g;s;#include "util/(.*)";#if COCOAPODS==1\\\n  #include  "third_party/re2/util/\\1"\\\n#else\\\n  #include  "util/\\1"\\\n#endif;g'
-    find src/core/ -type f \\( -name '*.h' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "re2/(.*)";#if COCOAPODS==1\\\n  #include  "third_party/re2/re2/\\1"\\\n#else\\\n  #include  "re2/\\1"\\\n#endif;g'
-    find src/core/ third_party/re2/ -type f -name '*.grpc_back' -print0 | xargs -0 rm
-    find src/core/ -type f \\( -name '*.h' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "xxhash.h";#if COCOAPODS==1\\\n #include "third_party/xxhash/xxhash.h"\\\n#else\\\n #include "xxhash.h"\\\n#endif;g'
     find third_party/xxhash  -type f -name xxhash.h -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;@param([^,]*),;@param\\1 ,;g'
     find src/core/ third_party/xxhash/ -type f -name '*.grpc_back' -print0 | xargs -0 rm
   END_OF_COMMAND
index efee0db..d3910f4 100644 (file)
@@ -21,7 +21,7 @@
 
 Pod::Spec.new do |s|
   s.name     = 'gRPC-Core'
-  version = '1.41.1'
+  version = '1.42.0'
   s.version  = version
   s.summary  = 'Core cross-platform gRPC library, written in C'
   s.homepage = 'https://grpc.io'
@@ -46,7 +46,7 @@ Pod::Spec.new do |s|
   s.requires_arc = false
 
   name = 'grpc'
-  abseil_version = '1.20210324.0'
+  abseil_version = '1.20210324.2'
 
   # When creating a dynamic framework, name it grpc.framework instead of gRPC-Core.framework.
   # This lets users write their includes like `#include <grpc/grpc.h>` as opposed to `#include
@@ -69,24 +69,14 @@ Pod::Spec.new do |s|
   s.module_map = 'include/grpc/module.modulemap'
 
   # To compile the library, we need the user headers search path (quoted includes) to point to the
-  # root of the repo, and the system headers search path (angled includes) to point to `include/`.
-  # Cocoapods effectively clones the repo under `<Podfile dir>/Pods/gRPC-Core/`, and sets a build
-  # variable called `$(PODS_ROOT)` to `<Podfile dir>/Pods/`, so we use that.
-  #
-  # Relying on the file structure under $(PODS_ROOT) isn't officially supported in Cocoapods, as it
-  # is taken as an implementation detail. We've asked for an alternative, and have been told that
-  # what we're doing should keep working: https://github.com/CocoaPods/CocoaPods/issues/4386
-  #
-  # The `src_root` value of `$(PODS_ROOT)/gRPC-Core` assumes Cocoapods is installing this pod from
-  # its remote repo. For local development of this library, enabled by using `:path` in the Podfile,
-  # that assumption is wrong. In such case, the following settings need to be reset with the
-  # appropriate value of `src_root`. This can be accomplished in the `pre_install` hook of the
-  # Podfile; see `src/objective-c/tests/Podfile` for an example.
-  src_root = '$(PODS_ROOT)/gRPC-Core'
+  # root of the repo, third_party/** and two upb generated directories, and the system headers
+  # search path (angled includes) to point to `include/`.
   s.pod_target_xcconfig = {
-    'GRPC_SRC_ROOT' => src_root,
-    'HEADER_SEARCH_PATHS' => '"$(inherited)" "$(GRPC_SRC_ROOT)/include"',
-    'USER_HEADER_SEARCH_PATHS' => '"$(GRPC_SRC_ROOT)"',
+    'HEADER_SEARCH_PATHS' => '"$(inherited)" "$(PODS_TARGET_SRCROOT)/include"',
+    'USER_HEADER_SEARCH_PATHS' => '"$(PODS_TARGET_SRCROOT)"'\
+        ' "$(PODS_TARGET_SRCROOT)/src/core/ext/upb-generated"'\
+        ' "$(PODS_TARGET_SRCROOT)/src/core/ext/upbdefs-generated"'\
+        ' "$(PODS_TARGET_SRCROOT)/third_party/**"',
     # If we don't set these two settings, `include/grpc/support/time.h` and
     # `src/core/lib/gpr/string.h` shadow the system `<time.h>` and `<string.h>`, breaking the
     # build.
@@ -119,8 +109,9 @@ Pod::Spec.new do |s|
                       'include/grpc/compression.h',
                       'include/grpc/event_engine/endpoint_config.h',
                       'include/grpc/event_engine/event_engine.h',
+                      'include/grpc/event_engine/internal/memory_allocator_impl.h',
+                      'include/grpc/event_engine/memory_allocator.h',
                       'include/grpc/event_engine/port.h',
-                      'include/grpc/event_engine/slice_allocator.h',
                       'include/grpc/fork.h',
                       'include/grpc/grpc.h',
                       'include/grpc/grpc_posix.h',
@@ -177,12 +168,14 @@ Pod::Spec.new do |s|
     ss.header_mappings_dir = '.'
     ss.libraries = 'z'
     ss.dependency "#{s.name}/Interface", version
-    ss.dependency 'BoringSSL-GRPC', '0.0.21'
+    ss.dependency 'BoringSSL-GRPC', '0.0.22'
+    ss.dependency 'Libuv-gRPC', '0.0.10'
     ss.dependency 'abseil/base/base', abseil_version
     ss.dependency 'abseil/base/core_headers', abseil_version
     ss.dependency 'abseil/container/flat_hash_map', abseil_version
     ss.dependency 'abseil/container/inlined_vector', abseil_version
     ss.dependency 'abseil/functional/bind_front', abseil_version
+    ss.dependency 'abseil/hash/hash', abseil_version
     ss.dependency 'abseil/memory/memory', abseil_version
     ss.dependency 'abseil/status/status', abseil_version
     ss.dependency 'abseil/status/statusor', abseil_version
@@ -193,6 +186,7 @@ Pod::Spec.new do |s|
     ss.dependency 'abseil/time/time', abseil_version
     ss.dependency 'abseil/types/optional', abseil_version
     ss.dependency 'abseil/types/variant', abseil_version
+    ss.dependency 'abseil/utility/utility', abseil_version
     ss.compiler_flags = '-DBORINGSSL_PREFIX=GRPC -Wno-unreachable-code -Wno-shorten-64-to-32'
 
     ss.source_files = 'src/core/ext/filters/census/grpc_context.cc',
@@ -243,6 +237,7 @@ Pod::Spec.new do |s|
                       'src/core/ext/filters/client_channel/lb_policy/priority/priority.cc',
                       'src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc',
                       'src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.h',
+                      'src/core/ext/filters/client_channel/lb_policy/rls/rls.cc',
                       'src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc',
                       'src/core/ext/filters/client_channel/lb_policy/subchannel_list.h',
                       'src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc',
@@ -262,6 +257,7 @@ Pod::Spec.new do |s|
                       'src/core/ext/filters/client_channel/proxy_mapper_registry.h',
                       'src/core/ext/filters/client_channel/resolver.cc',
                       'src/core/ext/filters/client_channel/resolver.h',
+                      'src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc',
                       'src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc',
                       'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h',
                       'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_event_engine.cc',
@@ -294,18 +290,15 @@ Pod::Spec.new do |s|
                       'src/core/ext/filters/client_channel/retry_throttle.h',
                       'src/core/ext/filters/client_channel/server_address.cc',
                       'src/core/ext/filters/client_channel/server_address.h',
-                      'src/core/ext/filters/client_channel/service_config.cc',
-                      'src/core/ext/filters/client_channel/service_config.h',
-                      'src/core/ext/filters/client_channel/service_config_call_data.h',
                       'src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc',
-                      'src/core/ext/filters/client_channel/service_config_parser.cc',
-                      'src/core/ext/filters/client_channel/service_config_parser.h',
                       'src/core/ext/filters/client_channel/subchannel.cc',
                       'src/core/ext/filters/client_channel/subchannel.h',
                       'src/core/ext/filters/client_channel/subchannel_interface.h',
                       'src/core/ext/filters/client_channel/subchannel_pool_interface.cc',
                       'src/core/ext/filters/client_channel/subchannel_pool_interface.h',
                       'src/core/ext/filters/client_idle/client_idle_filter.cc',
+                      'src/core/ext/filters/client_idle/idle_filter_state.cc',
+                      'src/core/ext/filters/client_idle/idle_filter_state.h',
                       'src/core/ext/filters/deadline/deadline_filter.cc',
                       'src/core/ext/filters/deadline/deadline_filter.h',
                       'src/core/ext/filters/fault_injection/fault_injection_filter.cc',
@@ -327,14 +320,13 @@ Pod::Spec.new do |s|
                       'src/core/ext/filters/max_age/max_age_filter.h',
                       'src/core/ext/filters/message_size/message_size_filter.cc',
                       'src/core/ext/filters/message_size/message_size_filter.h',
-                      'src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc',
-                      'src/core/ext/filters/workarounds/workaround_cronet_compression_filter.h',
-                      'src/core/ext/filters/workarounds/workaround_utils.cc',
-                      'src/core/ext/filters/workarounds/workaround_utils.h',
+                      'src/core/ext/service_config/service_config.cc',
+                      'src/core/ext/service_config/service_config.h',
+                      'src/core/ext/service_config/service_config_call_data.h',
+                      'src/core/ext/service_config/service_config_parser.cc',
+                      'src/core/ext/service_config/service_config_parser.h',
                       'src/core/ext/transport/chttp2/alpn/alpn.cc',
                       'src/core/ext/transport/chttp2/alpn/alpn.h',
-                      'src/core/ext/transport/chttp2/client/authority.cc',
-                      'src/core/ext/transport/chttp2/client/authority.h',
                       'src/core/ext/transport/chttp2/client/chttp2_connector.cc',
                       'src/core/ext/transport/chttp2/client/chttp2_connector.h',
                       'src/core/ext/transport/chttp2/client/insecure/channel_create.cc',
@@ -350,8 +342,6 @@ Pod::Spec.new do |s|
                       'src/core/ext/transport/chttp2/transport/bin_encoder.cc',
                       'src/core/ext/transport/chttp2/transport/bin_encoder.h',
                       'src/core/ext/transport/chttp2/transport/chttp2_plugin.cc',
-                      'src/core/ext/transport/chttp2/transport/chttp2_slice_allocator.cc',
-                      'src/core/ext/transport/chttp2/transport/chttp2_slice_allocator.h',
                       'src/core/ext/transport/chttp2/transport/chttp2_transport.cc',
                       'src/core/ext/transport/chttp2/transport/chttp2_transport.h',
                       'src/core/ext/transport/chttp2/transport/context_list.cc',
@@ -387,8 +377,6 @@ Pod::Spec.new do |s|
                       'src/core/ext/transport/chttp2/transport/http2_settings.h',
                       'src/core/ext/transport/chttp2/transport/huffsyms.cc',
                       'src/core/ext/transport/chttp2/transport/huffsyms.h',
-                      'src/core/ext/transport/chttp2/transport/incoming_metadata.cc',
-                      'src/core/ext/transport/chttp2/transport/incoming_metadata.h',
                       'src/core/ext/transport/chttp2/transport/internal.h',
                       'src/core/ext/transport/chttp2/transport/parsing.cc',
                       'src/core/ext/transport/chttp2/transport/popularity_count.h',
@@ -579,6 +567,8 @@ Pod::Spec.new do |s|
                       'src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.h',
                       'src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c',
                       'src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.h',
+                      'src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls.upb.c',
+                      'src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls.upb.h',
                       'src/core/ext/upb-generated/udpa/annotations/migrate.upb.c',
                       'src/core/ext/upb-generated/udpa/annotations/migrate.upb.h',
                       'src/core/ext/upb-generated/udpa/annotations/security.upb.c',
@@ -589,12 +579,10 @@ Pod::Spec.new do |s|
                       'src/core/ext/upb-generated/udpa/annotations/status.upb.h',
                       'src/core/ext/upb-generated/udpa/annotations/versioning.upb.c',
                       'src/core/ext/upb-generated/udpa/annotations/versioning.upb.h',
-                      'src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c',
-                      'src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h',
-                      'src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.c',
-                      'src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.h',
                       'src/core/ext/upb-generated/validate/validate.upb.c',
                       'src/core/ext/upb-generated/validate/validate.upb.h',
+                      'src/core/ext/upb-generated/xds/annotations/v3/status.upb.c',
+                      'src/core/ext/upb-generated/xds/annotations/v3/status.upb.h',
                       'src/core/ext/upb-generated/xds/core/v3/authority.upb.c',
                       'src/core/ext/upb-generated/xds/core/v3/authority.upb.h',
                       'src/core/ext/upb-generated/xds/core/v3/collection_entry.upb.c',
@@ -607,6 +595,10 @@ Pod::Spec.new do |s|
                       'src/core/ext/upb-generated/xds/core/v3/resource_locator.upb.h',
                       'src/core/ext/upb-generated/xds/core/v3/resource_name.upb.c',
                       'src/core/ext/upb-generated/xds/core/v3/resource_name.upb.h',
+                      'src/core/ext/upb-generated/xds/data/orca/v3/orca_load_report.upb.c',
+                      'src/core/ext/upb-generated/xds/data/orca/v3/orca_load_report.upb.h',
+                      'src/core/ext/upb-generated/xds/type/v3/typed_struct.upb.c',
+                      'src/core/ext/upb-generated/xds/type/v3/typed_struct.upb.h',
                       'src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.c',
                       'src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.h',
                       'src/core/ext/upbdefs-generated/envoy/annotations/deprecation.upbdefs.c',
@@ -779,10 +771,10 @@ Pod::Spec.new do |s|
                       'src/core/ext/upbdefs-generated/udpa/annotations/status.upbdefs.h',
                       'src/core/ext/upbdefs-generated/udpa/annotations/versioning.upbdefs.c',
                       'src/core/ext/upbdefs-generated/udpa/annotations/versioning.upbdefs.h',
-                      'src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.c',
-                      'src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.h',
                       'src/core/ext/upbdefs-generated/validate/validate.upbdefs.c',
                       'src/core/ext/upbdefs-generated/validate/validate.upbdefs.h',
+                      'src/core/ext/upbdefs-generated/xds/annotations/v3/status.upbdefs.c',
+                      'src/core/ext/upbdefs-generated/xds/annotations/v3/status.upbdefs.h',
                       'src/core/ext/upbdefs-generated/xds/core/v3/authority.upbdefs.c',
                       'src/core/ext/upbdefs-generated/xds/core/v3/authority.upbdefs.h',
                       'src/core/ext/upbdefs-generated/xds/core/v3/collection_entry.upbdefs.c',
@@ -795,6 +787,8 @@ Pod::Spec.new do |s|
                       'src/core/ext/upbdefs-generated/xds/core/v3/resource_locator.upbdefs.h',
                       'src/core/ext/upbdefs-generated/xds/core/v3/resource_name.upbdefs.c',
                       'src/core/ext/upbdefs-generated/xds/core/v3/resource_name.upbdefs.h',
+                      'src/core/ext/upbdefs-generated/xds/type/v3/typed_struct.upbdefs.c',
+                      'src/core/ext/upbdefs-generated/xds/type/v3/typed_struct.upbdefs.h',
                       'src/core/ext/xds/certificate_provider_factory.h',
                       'src/core/ext/xds/certificate_provider_registry.cc',
                       'src/core/ext/xds/certificate_provider_registry.h',
@@ -809,6 +803,8 @@ Pod::Spec.new do |s|
                       'src/core/ext/xds/xds_certificate_provider.cc',
                       'src/core/ext/xds/xds_certificate_provider.h',
                       'src/core/ext/xds/xds_channel_args.h',
+                      'src/core/ext/xds/xds_channel_stack_modifier.cc',
+                      'src/core/ext/xds/xds_channel_stack_modifier.h',
                       'src/core/ext/xds/xds_client.cc',
                       'src/core/ext/xds/xds_client.h',
                       'src/core/ext/xds/xds_client_stats.cc',
@@ -921,6 +917,7 @@ Pod::Spec.new do |s|
                       'src/core/lib/gprpp/arena.h',
                       'src/core/lib/gprpp/atomic_utils.h',
                       'src/core/lib/gprpp/bitset.h',
+                      'src/core/lib/gprpp/chunked_vector.h',
                       'src/core/lib/gprpp/construct_destruct.h',
                       'src/core/lib/gprpp/debug_location.h',
                       'src/core/lib/gprpp/dual_ref_counted.h',
@@ -950,6 +947,7 @@ Pod::Spec.new do |s|
                       'src/core/lib/gprpp/status_helper.cc',
                       'src/core/lib/gprpp/status_helper.h',
                       'src/core/lib/gprpp/sync.h',
+                      'src/core/lib/gprpp/table.h',
                       'src/core/lib/gprpp/thd.h',
                       'src/core/lib/gprpp/thd_posix.cc',
                       'src/core/lib/gprpp/thd_windows.cc',
@@ -1123,8 +1121,6 @@ Pod::Spec.new do |s|
                       'src/core/lib/iomgr/timer_heap.h',
                       'src/core/lib/iomgr/timer_manager.cc',
                       'src/core/lib/iomgr/timer_manager.h',
-                      'src/core/lib/iomgr/udp_server.cc',
-                      'src/core/lib/iomgr/udp_server.h',
                       'src/core/lib/iomgr/unix_sockets_posix.cc',
                       'src/core/lib/iomgr/unix_sockets_posix.h',
                       'src/core/lib/iomgr/unix_sockets_posix_noop.cc',
@@ -1253,14 +1249,24 @@ Pod::Spec.new do |s|
                       'src/core/lib/slice/percent_encoding.cc',
                       'src/core/lib/slice/percent_encoding.h',
                       'src/core/lib/slice/slice.cc',
+                      'src/core/lib/slice/slice_api.cc',
                       'src/core/lib/slice/slice_buffer.cc',
                       'src/core/lib/slice/slice_intern.cc',
                       'src/core/lib/slice/slice_internal.h',
+                      'src/core/lib/slice/slice_refcount.cc',
+                      'src/core/lib/slice/slice_refcount.h',
+                      'src/core/lib/slice/slice_refcount_base.h',
+                      'src/core/lib/slice/slice_split.cc',
+                      'src/core/lib/slice/slice_split.h',
                       'src/core/lib/slice/slice_string_helpers.cc',
                       'src/core/lib/slice/slice_string_helpers.h',
                       'src/core/lib/slice/slice_utils.h',
+                      'src/core/lib/slice/static_slice.cc',
+                      'src/core/lib/slice/static_slice.h',
                       'src/core/lib/surface/api_trace.cc',
                       'src/core/lib/surface/api_trace.h',
+                      'src/core/lib/surface/builtins.cc',
+                      'src/core/lib/surface/builtins.h',
                       'src/core/lib/surface/byte_buffer.cc',
                       'src/core/lib/surface/byte_buffer_reader.cc',
                       'src/core/lib/surface/call.cc',
@@ -1292,8 +1298,6 @@ Pod::Spec.new do |s|
                       'src/core/lib/surface/validate_metadata.cc',
                       'src/core/lib/surface/validate_metadata.h',
                       'src/core/lib/surface/version.cc',
-                      'src/core/lib/transport/authority_override.cc',
-                      'src/core/lib/transport/authority_override.h',
                       'src/core/lib/transport/bdp_estimator.cc',
                       'src/core/lib/transport/bdp_estimator.h',
                       'src/core/lib/transport/byte_stream.cc',
@@ -1307,6 +1311,7 @@ Pod::Spec.new do |s|
                       'src/core/lib/transport/metadata.h',
                       'src/core/lib/transport/metadata_batch.cc',
                       'src/core/lib/transport/metadata_batch.h',
+                      'src/core/lib/transport/parsed_metadata.h',
                       'src/core/lib/transport/pid_controller.cc',
                       'src/core/lib/transport/pid_controller.h',
                       'src/core/lib/transport/static_metadata.cc',
@@ -1497,12 +1502,10 @@ Pod::Spec.new do |s|
                               'src/core/ext/filters/client_channel/retry_service_config.h',
                               'src/core/ext/filters/client_channel/retry_throttle.h',
                               'src/core/ext/filters/client_channel/server_address.h',
-                              'src/core/ext/filters/client_channel/service_config.h',
-                              'src/core/ext/filters/client_channel/service_config_call_data.h',
-                              'src/core/ext/filters/client_channel/service_config_parser.h',
                               'src/core/ext/filters/client_channel/subchannel.h',
                               'src/core/ext/filters/client_channel/subchannel_interface.h',
                               'src/core/ext/filters/client_channel/subchannel_pool_interface.h',
+                              'src/core/ext/filters/client_idle/idle_filter_state.h',
                               'src/core/ext/filters/deadline/deadline_filter.h',
                               'src/core/ext/filters/fault_injection/fault_injection_filter.h',
                               'src/core/ext/filters/fault_injection/service_config_parser.h',
@@ -1513,15 +1516,14 @@ Pod::Spec.new do |s|
                               'src/core/ext/filters/http/server/http_server_filter.h',
                               'src/core/ext/filters/max_age/max_age_filter.h',
                               'src/core/ext/filters/message_size/message_size_filter.h',
-                              'src/core/ext/filters/workarounds/workaround_cronet_compression_filter.h',
-                              'src/core/ext/filters/workarounds/workaround_utils.h',
+                              'src/core/ext/service_config/service_config.h',
+                              'src/core/ext/service_config/service_config_call_data.h',
+                              'src/core/ext/service_config/service_config_parser.h',
                               'src/core/ext/transport/chttp2/alpn/alpn.h',
-                              'src/core/ext/transport/chttp2/client/authority.h',
                               'src/core/ext/transport/chttp2/client/chttp2_connector.h',
                               'src/core/ext/transport/chttp2/server/chttp2_server.h',
                               'src/core/ext/transport/chttp2/transport/bin_decoder.h',
                               'src/core/ext/transport/chttp2/transport/bin_encoder.h',
-                              'src/core/ext/transport/chttp2/transport/chttp2_slice_allocator.h',
                               'src/core/ext/transport/chttp2/transport/chttp2_transport.h',
                               'src/core/ext/transport/chttp2/transport/context_list.h',
                               'src/core/ext/transport/chttp2/transport/flow_control.h',
@@ -1541,7 +1543,6 @@ Pod::Spec.new do |s|
                               'src/core/ext/transport/chttp2/transport/hpack_utils.h',
                               'src/core/ext/transport/chttp2/transport/http2_settings.h',
                               'src/core/ext/transport/chttp2/transport/huffsyms.h',
-                              'src/core/ext/transport/chttp2/transport/incoming_metadata.h',
                               'src/core/ext/transport/chttp2/transport/internal.h',
                               'src/core/ext/transport/chttp2/transport/popularity_count.h',
                               'src/core/ext/transport/chttp2/transport/stream_map.h',
@@ -1636,20 +1637,22 @@ Pod::Spec.new do |s|
                               'src/core/ext/upb-generated/src/proto/grpc/gcp/transport_security_common.upb.h',
                               'src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.h',
                               'src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.h',
+                              'src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls.upb.h',
                               'src/core/ext/upb-generated/udpa/annotations/migrate.upb.h',
                               'src/core/ext/upb-generated/udpa/annotations/security.upb.h',
                               'src/core/ext/upb-generated/udpa/annotations/sensitive.upb.h',
                               'src/core/ext/upb-generated/udpa/annotations/status.upb.h',
                               'src/core/ext/upb-generated/udpa/annotations/versioning.upb.h',
-                              'src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h',
-                              'src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.h',
                               'src/core/ext/upb-generated/validate/validate.upb.h',
+                              'src/core/ext/upb-generated/xds/annotations/v3/status.upb.h',
                               'src/core/ext/upb-generated/xds/core/v3/authority.upb.h',
                               'src/core/ext/upb-generated/xds/core/v3/collection_entry.upb.h',
                               'src/core/ext/upb-generated/xds/core/v3/context_params.upb.h',
                               'src/core/ext/upb-generated/xds/core/v3/resource.upb.h',
                               'src/core/ext/upb-generated/xds/core/v3/resource_locator.upb.h',
                               'src/core/ext/upb-generated/xds/core/v3/resource_name.upb.h',
+                              'src/core/ext/upb-generated/xds/data/orca/v3/orca_load_report.upb.h',
+                              'src/core/ext/upb-generated/xds/type/v3/typed_struct.upb.h',
                               'src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.h',
                               'src/core/ext/upbdefs-generated/envoy/annotations/deprecation.upbdefs.h',
                               'src/core/ext/upbdefs-generated/envoy/annotations/resource.upbdefs.h',
@@ -1736,14 +1739,15 @@ Pod::Spec.new do |s|
                               'src/core/ext/upbdefs-generated/udpa/annotations/sensitive.upbdefs.h',
                               'src/core/ext/upbdefs-generated/udpa/annotations/status.upbdefs.h',
                               'src/core/ext/upbdefs-generated/udpa/annotations/versioning.upbdefs.h',
-                              'src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.h',
                               'src/core/ext/upbdefs-generated/validate/validate.upbdefs.h',
+                              'src/core/ext/upbdefs-generated/xds/annotations/v3/status.upbdefs.h',
                               'src/core/ext/upbdefs-generated/xds/core/v3/authority.upbdefs.h',
                               'src/core/ext/upbdefs-generated/xds/core/v3/collection_entry.upbdefs.h',
                               'src/core/ext/upbdefs-generated/xds/core/v3/context_params.upbdefs.h',
                               'src/core/ext/upbdefs-generated/xds/core/v3/resource.upbdefs.h',
                               'src/core/ext/upbdefs-generated/xds/core/v3/resource_locator.upbdefs.h',
                               'src/core/ext/upbdefs-generated/xds/core/v3/resource_name.upbdefs.h',
+                              'src/core/ext/upbdefs-generated/xds/type/v3/typed_struct.upbdefs.h',
                               'src/core/ext/xds/certificate_provider_factory.h',
                               'src/core/ext/xds/certificate_provider_registry.h',
                               'src/core/ext/xds/certificate_provider_store.h',
@@ -1752,6 +1756,7 @@ Pod::Spec.new do |s|
                               'src/core/ext/xds/xds_bootstrap.h',
                               'src/core/ext/xds/xds_certificate_provider.h',
                               'src/core/ext/xds/xds_channel_args.h',
+                              'src/core/ext/xds/xds_channel_stack_modifier.h',
                               'src/core/ext/xds/xds_client.h',
                               'src/core/ext/xds/xds_client_stats.h',
                               'src/core/ext/xds/xds_http_fault_filter.h',
@@ -1799,6 +1804,7 @@ Pod::Spec.new do |s|
                               'src/core/lib/gprpp/arena.h',
                               'src/core/lib/gprpp/atomic_utils.h',
                               'src/core/lib/gprpp/bitset.h',
+                              'src/core/lib/gprpp/chunked_vector.h',
                               'src/core/lib/gprpp/construct_destruct.h',
                               'src/core/lib/gprpp/debug_location.h',
                               'src/core/lib/gprpp/dual_ref_counted.h',
@@ -1820,6 +1826,7 @@ Pod::Spec.new do |s|
                               'src/core/lib/gprpp/stat.h',
                               'src/core/lib/gprpp/status_helper.h',
                               'src/core/lib/gprpp/sync.h',
+                              'src/core/lib/gprpp/table.h',
                               'src/core/lib/gprpp/thd.h',
                               'src/core/lib/gprpp/time_util.h',
                               'src/core/lib/http/format_request.h',
@@ -1898,7 +1905,6 @@ Pod::Spec.new do |s|
                               'src/core/lib/iomgr/timer_generic.h',
                               'src/core/lib/iomgr/timer_heap.h',
                               'src/core/lib/iomgr/timer_manager.h',
-                              'src/core/lib/iomgr/udp_server.h',
                               'src/core/lib/iomgr/unix_sockets_posix.h',
                               'src/core/lib/iomgr/wakeup_fd_pipe.h',
                               'src/core/lib/iomgr/wakeup_fd_posix.h',
@@ -1957,9 +1963,14 @@ Pod::Spec.new do |s|
                               'src/core/lib/slice/b64.h',
                               'src/core/lib/slice/percent_encoding.h',
                               'src/core/lib/slice/slice_internal.h',
+                              'src/core/lib/slice/slice_refcount.h',
+                              'src/core/lib/slice/slice_refcount_base.h',
+                              'src/core/lib/slice/slice_split.h',
                               'src/core/lib/slice/slice_string_helpers.h',
                               'src/core/lib/slice/slice_utils.h',
+                              'src/core/lib/slice/static_slice.h',
                               'src/core/lib/surface/api_trace.h',
+                              'src/core/lib/surface/builtins.h',
                               'src/core/lib/surface/call.h',
                               'src/core/lib/surface/call_test_only.h',
                               'src/core/lib/surface/channel.h',
@@ -1972,7 +1983,6 @@ Pod::Spec.new do |s|
                               'src/core/lib/surface/lame_client.h',
                               'src/core/lib/surface/server.h',
                               'src/core/lib/surface/validate_metadata.h',
-                              'src/core/lib/transport/authority_override.h',
                               'src/core/lib/transport/bdp_estimator.h',
                               'src/core/lib/transport/byte_stream.h',
                               'src/core/lib/transport/connectivity_state.h',
@@ -1980,6 +1990,7 @@ Pod::Spec.new do |s|
                               'src/core/lib/transport/http2_errors.h',
                               'src/core/lib/transport/metadata.h',
                               'src/core/lib/transport/metadata_batch.h',
+                              'src/core/lib/transport/parsed_metadata.h',
                               'src/core/lib/transport/pid_controller.h',
                               'src/core/lib/transport/static_metadata.h',
                               'src/core/lib/transport/status_conversion.h',
@@ -2211,7 +2222,6 @@ Pod::Spec.new do |s|
                       'test/core/end2end/tests/stream_compression_ping_pong_streaming.cc',
                       'test/core/end2end/tests/streaming_error_response.cc',
                       'test/core/end2end/tests/trailing_metadata.cc',
-                      'test/core/end2end/tests/workaround_cronet_compression.cc',
                       'test/core/end2end/tests/write_buffering.cc',
                       'test/core/end2end/tests/write_buffering_at_end.cc',
                       'test/core/util/cmdline.cc',
@@ -2263,20 +2273,13 @@ Pod::Spec.new do |s|
                       'test/core/util/trickle_endpoint.h'
   end
 
-  # TODO (mxyan): Instead of this hack, add include path "third_party" to C core's include path?
+  # patch include of openssl to openssl_grpc
+  # patch xxhash.h to silent the -Wdocumentation error
   s.prepare_command = <<-END_OF_COMMAND
+    set -e
     find src/core -type f \\( -path '*.h' -or -path '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include <openssl/(.*)>;#if COCOAPODS==1\\\n  #include <openssl_grpc/\\1>\\\n#else\\\n  #include <openssl/\\1>\\\n#endif;g'
-    find third_party/upb/ -type f \\( -name '*.h' -or -name '*.hpp' -or -name '*.c' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "third_party/(.*)";#if COCOAPODS==1\\\n  #include  "third_party/upb/third_party/\\1"\\\n#else\\\n  #include  "third_party/\\1"\\\n#endif;g'
-    find src/core/ src/cpp/ third_party/upb/ -type f \\( -name '*.h' -or -name '*.hpp' -or -name '*.c' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "upb/(.*)";#if COCOAPODS==1\\\n  #include  "third_party/upb/upb/\\1"\\\n#else\\\n  #include  "upb/\\1"\\\n#endif;g'
-    find src/core/ src/cpp/ third_party/upb/ -type f -name '*.grpc_back' -print0 | xargs -0 rm
-    find src/core/ src/cpp/ third_party/upb/ -type f \\( -name '*.h' -or -name '*.c' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "(.*).upb.h";#if COCOAPODS==1\\\n  #include  "src/core/ext/upb-generated/\\1.upb.h"\\\n#else\\\n  #include  "\\1.upb.h"\\\n#endif;g'
-    find src/core/ src/cpp/ third_party/upb/ -type f \\( -name '*.h' -or -name '*.c' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "(.*).upbdefs.h";#if COCOAPODS==1\\\n  #include  "src/core/ext/upbdefs-generated/\\1.upbdefs.h"\\\n#else\\\n  #include  "\\1.upbdefs.h"\\\n#endif;g'
-    find src/core/ src/cpp/ third_party/upb/ -type f -name '*.grpc_back' -print0 | xargs -0 rm
-    find third_party/re2/re2/ third_party/re2/util/ -type f \\( -name '*.h' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "re2/(.*)";#if COCOAPODS==1\\\n  #include  "third_party/re2/re2/\\1"\\\n#else\\\n  #include  "re2/\\1"\\\n#endif;g;s;#include "util/(.*)";#if COCOAPODS==1\\\n  #include  "third_party/re2/util/\\1"\\\n#else\\\n  #include  "util/\\1"\\\n#endif;g'
-    find src/core/ -type f \\( -name '*.h' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "re2/(.*)";#if COCOAPODS==1\\\n  #include  "third_party/re2/re2/\\1"\\\n#else\\\n  #include  "re2/\\1"\\\n#endif;g'
-    find src/core/ third_party/re2/ -type f -name '*.grpc_back' -print0 | xargs -0 rm
-    find src/core/ -type f \\( -name '*.h' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "xxhash.h";#if COCOAPODS==1\\\n  #include  "third_party/xxhash/xxhash.h"\\\n#else\\\n  #include  "xxhash.h"\\\n#endif;g'
+    find src/core -type f \\( -path '*.h' -or -path '*.cc' -or -path '*.c' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include <uv.h>;#if COCOAPODS==1\\\n  #include <uv/uv.h>\\\n#else\\\n  #include  <uv.h>\\\n#endif;g'
     find third_party/xxhash  -type f -name xxhash.h -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;@param([^,]*),;@param\\1 ,;g'
-    find src/core/ third_party/xxhash/ -type f -name '*.grpc_back' -print0 | xargs -0 rm
+    find src/core/ third_party/xxhash/ third_party/uv/ -type f -name '*.grpc_back' -print0 | xargs -0 rm
   END_OF_COMMAND
 end
index 82511f5..76c62a0 100644 (file)
@@ -21,7 +21,7 @@
 
 Pod::Spec.new do |s|
   s.name     = 'gRPC-ProtoRPC'
-  version = '1.41.1'
+  version = '1.42.0'
   s.version  = version
   s.summary  = 'RPC library for Protocol Buffers, based on gRPC'
   s.homepage = 'https://grpc.io'
index 5f95124..0231345 100644 (file)
@@ -21,7 +21,7 @@
 
 Pod::Spec.new do |s|
   s.name     = 'gRPC-RxLibrary'
-  version = '1.41.1'
+  version = '1.42.0'
   s.version  = version
   s.summary  = 'Reactive Extensions library for iOS/OSX.'
   s.homepage = 'https://grpc.io'
index 9fd8f18..024f216 100644 (file)
@@ -20,7 +20,7 @@
 
 Pod::Spec.new do |s|
   s.name     = 'gRPC'
-  version = '1.41.1'
+  version = '1.42.0'
   s.version  = version
   s.summary  = 'gRPC client library for iOS/OSX'
   s.homepage = 'https://grpc.io'
index 827aaf9..8c5d3d1 100644 (file)
--- a/grpc.def
+++ b/grpc.def
@@ -50,6 +50,7 @@ EXPORTS
     grpc_channel_destroy
     grpc_call_cancel
     grpc_call_cancel_with_status
+    grpc_call_failed_before_recv_message
     grpc_call_ref
     grpc_call_unref
     grpc_server_request_call
@@ -161,6 +162,7 @@ EXPORTS
     grpc_xds_credentials_create
     grpc_xds_server_credentials_create
     grpc_authorization_policy_provider_static_data_create
+    grpc_authorization_policy_provider_file_watcher_create
     grpc_authorization_policy_provider_release
     grpc_raw_byte_buffer_create
     grpc_raw_compressed_byte_buffer_create
index 511fa50..57ff8b9 100644 (file)
@@ -32,7 +32,7 @@ Gem::Specification.new do |s|
   s.require_paths = %w( src/ruby/lib src/ruby/bin src/ruby/pb )
   s.platform      = Gem::Platform::RUBY
 
-  s.add_dependency 'google-protobuf', '~> 3.17'
+  s.add_dependency 'google-protobuf', '~> 3.18'
   s.add_dependency 'googleapis-common-protos-types', '~> 1.0'
 
   s.add_development_dependency 'bundler',            '>= 1.9'
@@ -41,7 +41,7 @@ Gem::Specification.new do |s|
   s.add_development_dependency 'simplecov',          '~> 0.14.1'
   s.add_development_dependency 'rake',               '~> 13.0'
   s.add_development_dependency 'rake-compiler',      '~> 1.1'
-  s.add_development_dependency 'rake-compiler-dock', '~> 1.0'
+  s.add_development_dependency 'rake-compiler-dock', '~> 1.1'
   s.add_development_dependency 'rspec',              '~> 3.6'
   s.add_development_dependency 'rubocop',            '~> 0.49.1'
   s.add_development_dependency 'signet',             '~> 0.7'
@@ -55,8 +55,9 @@ Gem::Specification.new do |s|
   s.files += %w( include/grpc/compression.h )
   s.files += %w( include/grpc/event_engine/endpoint_config.h )
   s.files += %w( include/grpc/event_engine/event_engine.h )
+  s.files += %w( include/grpc/event_engine/internal/memory_allocator_impl.h )
+  s.files += %w( include/grpc/event_engine/memory_allocator.h )
   s.files += %w( include/grpc/event_engine/port.h )
-  s.files += %w( include/grpc/event_engine/slice_allocator.h )
   s.files += %w( include/grpc/fork.h )
   s.files += %w( include/grpc/grpc.h )
   s.files += %w( include/grpc/grpc_posix.h )
@@ -156,6 +157,7 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/ext/filters/client_channel/lb_policy/priority/priority.cc )
   s.files += %w( src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc )
   s.files += %w( src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.h )
+  s.files += %w( src/core/ext/filters/client_channel/lb_policy/rls/rls.cc )
   s.files += %w( src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc )
   s.files += %w( src/core/ext/filters/client_channel/lb_policy/subchannel_list.h )
   s.files += %w( src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc )
@@ -175,6 +177,7 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/ext/filters/client_channel/proxy_mapper_registry.h )
   s.files += %w( src/core/ext/filters/client_channel/resolver.cc )
   s.files += %w( src/core/ext/filters/client_channel/resolver.h )
+  s.files += %w( src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc )
   s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc )
   s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h )
   s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_event_engine.cc )
@@ -207,18 +210,15 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/ext/filters/client_channel/retry_throttle.h )
   s.files += %w( src/core/ext/filters/client_channel/server_address.cc )
   s.files += %w( src/core/ext/filters/client_channel/server_address.h )
-  s.files += %w( src/core/ext/filters/client_channel/service_config.cc )
-  s.files += %w( src/core/ext/filters/client_channel/service_config.h )
-  s.files += %w( src/core/ext/filters/client_channel/service_config_call_data.h )
   s.files += %w( src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc )
-  s.files += %w( src/core/ext/filters/client_channel/service_config_parser.cc )
-  s.files += %w( src/core/ext/filters/client_channel/service_config_parser.h )
   s.files += %w( src/core/ext/filters/client_channel/subchannel.cc )
   s.files += %w( src/core/ext/filters/client_channel/subchannel.h )
   s.files += %w( src/core/ext/filters/client_channel/subchannel_interface.h )
   s.files += %w( src/core/ext/filters/client_channel/subchannel_pool_interface.cc )
   s.files += %w( src/core/ext/filters/client_channel/subchannel_pool_interface.h )
   s.files += %w( src/core/ext/filters/client_idle/client_idle_filter.cc )
+  s.files += %w( src/core/ext/filters/client_idle/idle_filter_state.cc )
+  s.files += %w( src/core/ext/filters/client_idle/idle_filter_state.h )
   s.files += %w( src/core/ext/filters/deadline/deadline_filter.cc )
   s.files += %w( src/core/ext/filters/deadline/deadline_filter.h )
   s.files += %w( src/core/ext/filters/fault_injection/fault_injection_filter.cc )
@@ -240,14 +240,13 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/ext/filters/max_age/max_age_filter.h )
   s.files += %w( src/core/ext/filters/message_size/message_size_filter.cc )
   s.files += %w( src/core/ext/filters/message_size/message_size_filter.h )
-  s.files += %w( src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc )
-  s.files += %w( src/core/ext/filters/workarounds/workaround_cronet_compression_filter.h )
-  s.files += %w( src/core/ext/filters/workarounds/workaround_utils.cc )
-  s.files += %w( src/core/ext/filters/workarounds/workaround_utils.h )
+  s.files += %w( src/core/ext/service_config/service_config.cc )
+  s.files += %w( src/core/ext/service_config/service_config.h )
+  s.files += %w( src/core/ext/service_config/service_config_call_data.h )
+  s.files += %w( src/core/ext/service_config/service_config_parser.cc )
+  s.files += %w( src/core/ext/service_config/service_config_parser.h )
   s.files += %w( src/core/ext/transport/chttp2/alpn/alpn.cc )
   s.files += %w( src/core/ext/transport/chttp2/alpn/alpn.h )
-  s.files += %w( src/core/ext/transport/chttp2/client/authority.cc )
-  s.files += %w( src/core/ext/transport/chttp2/client/authority.h )
   s.files += %w( src/core/ext/transport/chttp2/client/chttp2_connector.cc )
   s.files += %w( src/core/ext/transport/chttp2/client/chttp2_connector.h )
   s.files += %w( src/core/ext/transport/chttp2/client/insecure/channel_create.cc )
@@ -263,8 +262,6 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/ext/transport/chttp2/transport/bin_encoder.cc )
   s.files += %w( src/core/ext/transport/chttp2/transport/bin_encoder.h )
   s.files += %w( src/core/ext/transport/chttp2/transport/chttp2_plugin.cc )
-  s.files += %w( src/core/ext/transport/chttp2/transport/chttp2_slice_allocator.cc )
-  s.files += %w( src/core/ext/transport/chttp2/transport/chttp2_slice_allocator.h )
   s.files += %w( src/core/ext/transport/chttp2/transport/chttp2_transport.cc )
   s.files += %w( src/core/ext/transport/chttp2/transport/chttp2_transport.h )
   s.files += %w( src/core/ext/transport/chttp2/transport/context_list.cc )
@@ -300,8 +297,6 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/ext/transport/chttp2/transport/http2_settings.h )
   s.files += %w( src/core/ext/transport/chttp2/transport/huffsyms.cc )
   s.files += %w( src/core/ext/transport/chttp2/transport/huffsyms.h )
-  s.files += %w( src/core/ext/transport/chttp2/transport/incoming_metadata.cc )
-  s.files += %w( src/core/ext/transport/chttp2/transport/incoming_metadata.h )
   s.files += %w( src/core/ext/transport/chttp2/transport/internal.h )
   s.files += %w( src/core/ext/transport/chttp2/transport/parsing.cc )
   s.files += %w( src/core/ext/transport/chttp2/transport/popularity_count.h )
@@ -492,6 +487,8 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.h )
   s.files += %w( src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c )
   s.files += %w( src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.h )
+  s.files += %w( src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls.upb.c )
+  s.files += %w( src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls.upb.h )
   s.files += %w( src/core/ext/upb-generated/udpa/annotations/migrate.upb.c )
   s.files += %w( src/core/ext/upb-generated/udpa/annotations/migrate.upb.h )
   s.files += %w( src/core/ext/upb-generated/udpa/annotations/security.upb.c )
@@ -502,12 +499,10 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/ext/upb-generated/udpa/annotations/status.upb.h )
   s.files += %w( src/core/ext/upb-generated/udpa/annotations/versioning.upb.c )
   s.files += %w( src/core/ext/upb-generated/udpa/annotations/versioning.upb.h )
-  s.files += %w( src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c )
-  s.files += %w( src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h )
-  s.files += %w( src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.c )
-  s.files += %w( src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.h )
   s.files += %w( src/core/ext/upb-generated/validate/validate.upb.c )
   s.files += %w( src/core/ext/upb-generated/validate/validate.upb.h )
+  s.files += %w( src/core/ext/upb-generated/xds/annotations/v3/status.upb.c )
+  s.files += %w( src/core/ext/upb-generated/xds/annotations/v3/status.upb.h )
   s.files += %w( src/core/ext/upb-generated/xds/core/v3/authority.upb.c )
   s.files += %w( src/core/ext/upb-generated/xds/core/v3/authority.upb.h )
   s.files += %w( src/core/ext/upb-generated/xds/core/v3/collection_entry.upb.c )
@@ -520,6 +515,10 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/ext/upb-generated/xds/core/v3/resource_locator.upb.h )
   s.files += %w( src/core/ext/upb-generated/xds/core/v3/resource_name.upb.c )
   s.files += %w( src/core/ext/upb-generated/xds/core/v3/resource_name.upb.h )
+  s.files += %w( src/core/ext/upb-generated/xds/data/orca/v3/orca_load_report.upb.c )
+  s.files += %w( src/core/ext/upb-generated/xds/data/orca/v3/orca_load_report.upb.h )
+  s.files += %w( src/core/ext/upb-generated/xds/type/v3/typed_struct.upb.c )
+  s.files += %w( src/core/ext/upb-generated/xds/type/v3/typed_struct.upb.h )
   s.files += %w( src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.c )
   s.files += %w( src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.h )
   s.files += %w( src/core/ext/upbdefs-generated/envoy/annotations/deprecation.upbdefs.c )
@@ -692,10 +691,10 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/ext/upbdefs-generated/udpa/annotations/status.upbdefs.h )
   s.files += %w( src/core/ext/upbdefs-generated/udpa/annotations/versioning.upbdefs.c )
   s.files += %w( src/core/ext/upbdefs-generated/udpa/annotations/versioning.upbdefs.h )
-  s.files += %w( src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.c )
-  s.files += %w( src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.h )
   s.files += %w( src/core/ext/upbdefs-generated/validate/validate.upbdefs.c )
   s.files += %w( src/core/ext/upbdefs-generated/validate/validate.upbdefs.h )
+  s.files += %w( src/core/ext/upbdefs-generated/xds/annotations/v3/status.upbdefs.c )
+  s.files += %w( src/core/ext/upbdefs-generated/xds/annotations/v3/status.upbdefs.h )
   s.files += %w( src/core/ext/upbdefs-generated/xds/core/v3/authority.upbdefs.c )
   s.files += %w( src/core/ext/upbdefs-generated/xds/core/v3/authority.upbdefs.h )
   s.files += %w( src/core/ext/upbdefs-generated/xds/core/v3/collection_entry.upbdefs.c )
@@ -708,6 +707,8 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/ext/upbdefs-generated/xds/core/v3/resource_locator.upbdefs.h )
   s.files += %w( src/core/ext/upbdefs-generated/xds/core/v3/resource_name.upbdefs.c )
   s.files += %w( src/core/ext/upbdefs-generated/xds/core/v3/resource_name.upbdefs.h )
+  s.files += %w( src/core/ext/upbdefs-generated/xds/type/v3/typed_struct.upbdefs.c )
+  s.files += %w( src/core/ext/upbdefs-generated/xds/type/v3/typed_struct.upbdefs.h )
   s.files += %w( src/core/ext/xds/certificate_provider_factory.h )
   s.files += %w( src/core/ext/xds/certificate_provider_registry.cc )
   s.files += %w( src/core/ext/xds/certificate_provider_registry.h )
@@ -722,6 +723,8 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/ext/xds/xds_certificate_provider.cc )
   s.files += %w( src/core/ext/xds/xds_certificate_provider.h )
   s.files += %w( src/core/ext/xds/xds_channel_args.h )
+  s.files += %w( src/core/ext/xds/xds_channel_stack_modifier.cc )
+  s.files += %w( src/core/ext/xds/xds_channel_stack_modifier.h )
   s.files += %w( src/core/ext/xds/xds_client.cc )
   s.files += %w( src/core/ext/xds/xds_client.h )
   s.files += %w( src/core/ext/xds/xds_client_stats.cc )
@@ -834,6 +837,7 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/lib/gprpp/arena.h )
   s.files += %w( src/core/lib/gprpp/atomic_utils.h )
   s.files += %w( src/core/lib/gprpp/bitset.h )
+  s.files += %w( src/core/lib/gprpp/chunked_vector.h )
   s.files += %w( src/core/lib/gprpp/construct_destruct.h )
   s.files += %w( src/core/lib/gprpp/debug_location.h )
   s.files += %w( src/core/lib/gprpp/dual_ref_counted.h )
@@ -863,6 +867,7 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/lib/gprpp/status_helper.cc )
   s.files += %w( src/core/lib/gprpp/status_helper.h )
   s.files += %w( src/core/lib/gprpp/sync.h )
+  s.files += %w( src/core/lib/gprpp/table.h )
   s.files += %w( src/core/lib/gprpp/thd.h )
   s.files += %w( src/core/lib/gprpp/thd_posix.cc )
   s.files += %w( src/core/lib/gprpp/thd_windows.cc )
@@ -1036,8 +1041,6 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/lib/iomgr/timer_heap.h )
   s.files += %w( src/core/lib/iomgr/timer_manager.cc )
   s.files += %w( src/core/lib/iomgr/timer_manager.h )
-  s.files += %w( src/core/lib/iomgr/udp_server.cc )
-  s.files += %w( src/core/lib/iomgr/udp_server.h )
   s.files += %w( src/core/lib/iomgr/unix_sockets_posix.cc )
   s.files += %w( src/core/lib/iomgr/unix_sockets_posix.h )
   s.files += %w( src/core/lib/iomgr/unix_sockets_posix_noop.cc )
@@ -1166,14 +1169,24 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/lib/slice/percent_encoding.cc )
   s.files += %w( src/core/lib/slice/percent_encoding.h )
   s.files += %w( src/core/lib/slice/slice.cc )
+  s.files += %w( src/core/lib/slice/slice_api.cc )
   s.files += %w( src/core/lib/slice/slice_buffer.cc )
   s.files += %w( src/core/lib/slice/slice_intern.cc )
   s.files += %w( src/core/lib/slice/slice_internal.h )
+  s.files += %w( src/core/lib/slice/slice_refcount.cc )
+  s.files += %w( src/core/lib/slice/slice_refcount.h )
+  s.files += %w( src/core/lib/slice/slice_refcount_base.h )
+  s.files += %w( src/core/lib/slice/slice_split.cc )
+  s.files += %w( src/core/lib/slice/slice_split.h )
   s.files += %w( src/core/lib/slice/slice_string_helpers.cc )
   s.files += %w( src/core/lib/slice/slice_string_helpers.h )
   s.files += %w( src/core/lib/slice/slice_utils.h )
+  s.files += %w( src/core/lib/slice/static_slice.cc )
+  s.files += %w( src/core/lib/slice/static_slice.h )
   s.files += %w( src/core/lib/surface/api_trace.cc )
   s.files += %w( src/core/lib/surface/api_trace.h )
+  s.files += %w( src/core/lib/surface/builtins.cc )
+  s.files += %w( src/core/lib/surface/builtins.h )
   s.files += %w( src/core/lib/surface/byte_buffer.cc )
   s.files += %w( src/core/lib/surface/byte_buffer_reader.cc )
   s.files += %w( src/core/lib/surface/call.cc )
@@ -1205,8 +1218,6 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/lib/surface/validate_metadata.cc )
   s.files += %w( src/core/lib/surface/validate_metadata.h )
   s.files += %w( src/core/lib/surface/version.cc )
-  s.files += %w( src/core/lib/transport/authority_override.cc )
-  s.files += %w( src/core/lib/transport/authority_override.h )
   s.files += %w( src/core/lib/transport/bdp_estimator.cc )
   s.files += %w( src/core/lib/transport/bdp_estimator.h )
   s.files += %w( src/core/lib/transport/byte_stream.cc )
@@ -1220,6 +1231,7 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/lib/transport/metadata.h )
   s.files += %w( src/core/lib/transport/metadata_batch.cc )
   s.files += %w( src/core/lib/transport/metadata_batch.h )
+  s.files += %w( src/core/lib/transport/parsed_metadata.h )
   s.files += %w( src/core/lib/transport/pid_controller.cc )
   s.files += %w( src/core/lib/transport/pid_controller.h )
   s.files += %w( src/core/lib/transport/static_metadata.cc )
index ed67482..8dd6cd0 100644 (file)
--- a/grpc.gyp
+++ b/grpc.gyp
         'test/core/end2end/tests/stream_compression_ping_pong_streaming.cc',
         'test/core/end2end/tests/streaming_error_response.cc',
         'test/core/end2end/tests/trailing_metadata.cc',
-        'test/core/end2end/tests/workaround_cronet_compression.cc',
         'test/core/end2end/tests/write_buffering.cc',
         'test/core/end2end/tests/write_buffering_at_end.cc',
         'test/core/util/test_lb_policies.cc',
         'test/core/end2end/tests/stream_compression_ping_pong_streaming.cc',
         'test/core/end2end/tests/streaming_error_response.cc',
         'test/core/end2end/tests/trailing_metadata.cc',
-        'test/core/end2end/tests/workaround_cronet_compression.cc',
         'test/core/end2end/tests/write_buffering.cc',
         'test/core/end2end/tests/write_buffering_at_end.cc',
         'test/core/util/test_lb_policies.cc',
         'absl/container:flat_hash_map',
         'absl/container:inlined_vector',
         'absl/functional:bind_front',
+        'absl/hash:hash',
         'absl/status:statusor',
         'absl/types:variant',
+        'absl/utility:utility',
         'gpr',
         'address_sorting',
       ],
         'src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc',
         'src/core/ext/filters/client_channel/lb_policy/priority/priority.cc',
         'src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc',
+        'src/core/ext/filters/client_channel/lb_policy/rls/rls.cc',
         'src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc',
         'src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc',
         'src/core/ext/filters/client_channel/lb_policy/xds/cds.cc',
         'src/core/ext/filters/client_channel/local_subchannel_pool.cc',
         'src/core/ext/filters/client_channel/proxy_mapper_registry.cc',
         'src/core/ext/filters/client_channel/resolver.cc',
+        'src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc',
         'src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc',
         'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_event_engine.cc',
         'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc',
         'src/core/ext/filters/client_channel/retry_service_config.cc',
         'src/core/ext/filters/client_channel/retry_throttle.cc',
         'src/core/ext/filters/client_channel/server_address.cc',
-        'src/core/ext/filters/client_channel/service_config.cc',
         'src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc',
-        'src/core/ext/filters/client_channel/service_config_parser.cc',
         'src/core/ext/filters/client_channel/subchannel.cc',
         'src/core/ext/filters/client_channel/subchannel_pool_interface.cc',
         'src/core/ext/filters/client_idle/client_idle_filter.cc',
+        'src/core/ext/filters/client_idle/idle_filter_state.cc',
         'src/core/ext/filters/deadline/deadline_filter.cc',
         'src/core/ext/filters/fault_injection/fault_injection_filter.cc',
         'src/core/ext/filters/fault_injection/service_config_parser.cc',
         'src/core/ext/filters/http/server/http_server_filter.cc',
         'src/core/ext/filters/max_age/max_age_filter.cc',
         'src/core/ext/filters/message_size/message_size_filter.cc',
-        'src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc',
-        'src/core/ext/filters/workarounds/workaround_utils.cc',
+        'src/core/ext/service_config/service_config.cc',
+        'src/core/ext/service_config/service_config_parser.cc',
         'src/core/ext/transport/chttp2/alpn/alpn.cc',
-        'src/core/ext/transport/chttp2/client/authority.cc',
         'src/core/ext/transport/chttp2/client/chttp2_connector.cc',
         'src/core/ext/transport/chttp2/client/insecure/channel_create.cc',
         'src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc',
         'src/core/ext/transport/chttp2/transport/bin_decoder.cc',
         'src/core/ext/transport/chttp2/transport/bin_encoder.cc',
         'src/core/ext/transport/chttp2/transport/chttp2_plugin.cc',
-        'src/core/ext/transport/chttp2/transport/chttp2_slice_allocator.cc',
         'src/core/ext/transport/chttp2/transport/chttp2_transport.cc',
         'src/core/ext/transport/chttp2/transport/context_list.cc',
         'src/core/ext/transport/chttp2/transport/flow_control.cc',
         'src/core/ext/transport/chttp2/transport/hpack_utils.cc',
         'src/core/ext/transport/chttp2/transport/http2_settings.cc',
         'src/core/ext/transport/chttp2/transport/huffsyms.cc',
-        'src/core/ext/transport/chttp2/transport/incoming_metadata.cc',
         'src/core/ext/transport/chttp2/transport/parsing.cc',
         'src/core/ext/transport/chttp2/transport/stream_lists.cc',
         'src/core/ext/transport/chttp2/transport/stream_map.cc',
         'src/core/ext/upb-generated/src/proto/grpc/gcp/transport_security_common.upb.c',
         'src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.c',
         'src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c',
+        'src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls.upb.c',
         'src/core/ext/upb-generated/udpa/annotations/migrate.upb.c',
         'src/core/ext/upb-generated/udpa/annotations/security.upb.c',
         'src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c',
         'src/core/ext/upb-generated/udpa/annotations/status.upb.c',
         'src/core/ext/upb-generated/udpa/annotations/versioning.upb.c',
-        'src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c',
-        'src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.c',
         'src/core/ext/upb-generated/validate/validate.upb.c',
+        'src/core/ext/upb-generated/xds/annotations/v3/status.upb.c',
         'src/core/ext/upb-generated/xds/core/v3/authority.upb.c',
         'src/core/ext/upb-generated/xds/core/v3/collection_entry.upb.c',
         'src/core/ext/upb-generated/xds/core/v3/context_params.upb.c',
         'src/core/ext/upb-generated/xds/core/v3/resource.upb.c',
         'src/core/ext/upb-generated/xds/core/v3/resource_locator.upb.c',
         'src/core/ext/upb-generated/xds/core/v3/resource_name.upb.c',
+        'src/core/ext/upb-generated/xds/data/orca/v3/orca_load_report.upb.c',
+        'src/core/ext/upb-generated/xds/type/v3/typed_struct.upb.c',
         'src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.c',
         'src/core/ext/upbdefs-generated/envoy/annotations/deprecation.upbdefs.c',
         'src/core/ext/upbdefs-generated/envoy/annotations/resource.upbdefs.c',
         'src/core/ext/upbdefs-generated/udpa/annotations/sensitive.upbdefs.c',
         'src/core/ext/upbdefs-generated/udpa/annotations/status.upbdefs.c',
         'src/core/ext/upbdefs-generated/udpa/annotations/versioning.upbdefs.c',
-        'src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.c',
         'src/core/ext/upbdefs-generated/validate/validate.upbdefs.c',
+        'src/core/ext/upbdefs-generated/xds/annotations/v3/status.upbdefs.c',
         'src/core/ext/upbdefs-generated/xds/core/v3/authority.upbdefs.c',
         'src/core/ext/upbdefs-generated/xds/core/v3/collection_entry.upbdefs.c',
         'src/core/ext/upbdefs-generated/xds/core/v3/context_params.upbdefs.c',
         'src/core/ext/upbdefs-generated/xds/core/v3/resource.upbdefs.c',
         'src/core/ext/upbdefs-generated/xds/core/v3/resource_locator.upbdefs.c',
         'src/core/ext/upbdefs-generated/xds/core/v3/resource_name.upbdefs.c',
+        'src/core/ext/upbdefs-generated/xds/type/v3/typed_struct.upbdefs.c',
         'src/core/ext/xds/certificate_provider_registry.cc',
         'src/core/ext/xds/certificate_provider_store.cc',
         'src/core/ext/xds/file_watcher_certificate_provider_factory.cc',
         'src/core/ext/xds/xds_api.cc',
         'src/core/ext/xds/xds_bootstrap.cc',
         'src/core/ext/xds/xds_certificate_provider.cc',
+        'src/core/ext/xds/xds_channel_stack_modifier.cc',
         'src/core/ext/xds/xds_client.cc',
         'src/core/ext/xds/xds_client_stats.cc',
         'src/core/ext/xds/xds_http_fault_filter.cc',
         'src/core/lib/iomgr/timer_generic.cc',
         'src/core/lib/iomgr/timer_heap.cc',
         'src/core/lib/iomgr/timer_manager.cc',
-        'src/core/lib/iomgr/udp_server.cc',
         'src/core/lib/iomgr/unix_sockets_posix.cc',
         'src/core/lib/iomgr/unix_sockets_posix_noop.cc',
         'src/core/lib/iomgr/wakeup_fd_eventfd.cc',
         'src/core/lib/slice/b64.cc',
         'src/core/lib/slice/percent_encoding.cc',
         'src/core/lib/slice/slice.cc',
+        'src/core/lib/slice/slice_api.cc',
         'src/core/lib/slice/slice_buffer.cc',
         'src/core/lib/slice/slice_intern.cc',
+        'src/core/lib/slice/slice_refcount.cc',
+        'src/core/lib/slice/slice_split.cc',
         'src/core/lib/slice/slice_string_helpers.cc',
+        'src/core/lib/slice/static_slice.cc',
         'src/core/lib/surface/api_trace.cc',
+        'src/core/lib/surface/builtins.cc',
         'src/core/lib/surface/byte_buffer.cc',
         'src/core/lib/surface/byte_buffer_reader.cc',
         'src/core/lib/surface/call.cc',
         'src/core/lib/surface/server.cc',
         'src/core/lib/surface/validate_metadata.cc',
         'src/core/lib/surface/version.cc',
-        'src/core/lib/transport/authority_override.cc',
         'src/core/lib/transport/bdp_estimator.cc',
         'src/core/lib/transport/byte_stream.cc',
         'src/core/lib/transport/connectivity_state.cc',
         'absl/functional:bind_front',
         'absl/status:statusor',
         'absl/types:variant',
+        'absl/utility:utility',
         'gpr',
         'address_sorting',
       ],
         'src/core/ext/filters/client_channel/local_subchannel_pool.cc',
         'src/core/ext/filters/client_channel/proxy_mapper_registry.cc',
         'src/core/ext/filters/client_channel/resolver.cc',
+        'src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc',
         'src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc',
         'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_event_engine.cc',
         'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc',
         'src/core/ext/filters/client_channel/retry_service_config.cc',
         'src/core/ext/filters/client_channel/retry_throttle.cc',
         'src/core/ext/filters/client_channel/server_address.cc',
-        'src/core/ext/filters/client_channel/service_config.cc',
         'src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc',
-        'src/core/ext/filters/client_channel/service_config_parser.cc',
         'src/core/ext/filters/client_channel/subchannel.cc',
         'src/core/ext/filters/client_channel/subchannel_pool_interface.cc',
         'src/core/ext/filters/client_idle/client_idle_filter.cc',
+        'src/core/ext/filters/client_idle/idle_filter_state.cc',
         'src/core/ext/filters/deadline/deadline_filter.cc',
         'src/core/ext/filters/fault_injection/fault_injection_filter.cc',
         'src/core/ext/filters/fault_injection/service_config_parser.cc',
         'src/core/ext/filters/http/server/http_server_filter.cc',
         'src/core/ext/filters/max_age/max_age_filter.cc',
         'src/core/ext/filters/message_size/message_size_filter.cc',
-        'src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc',
-        'src/core/ext/filters/workarounds/workaround_utils.cc',
+        'src/core/ext/service_config/service_config.cc',
+        'src/core/ext/service_config/service_config_parser.cc',
         'src/core/ext/transport/chttp2/alpn/alpn.cc',
-        'src/core/ext/transport/chttp2/client/authority.cc',
         'src/core/ext/transport/chttp2/client/chttp2_connector.cc',
         'src/core/ext/transport/chttp2/client/insecure/channel_create.cc',
         'src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc',
         'src/core/ext/transport/chttp2/transport/bin_decoder.cc',
         'src/core/ext/transport/chttp2/transport/bin_encoder.cc',
         'src/core/ext/transport/chttp2/transport/chttp2_plugin.cc',
-        'src/core/ext/transport/chttp2/transport/chttp2_slice_allocator.cc',
         'src/core/ext/transport/chttp2/transport/chttp2_transport.cc',
         'src/core/ext/transport/chttp2/transport/context_list.cc',
         'src/core/ext/transport/chttp2/transport/flow_control.cc',
         'src/core/ext/transport/chttp2/transport/hpack_utils.cc',
         'src/core/ext/transport/chttp2/transport/http2_settings.cc',
         'src/core/ext/transport/chttp2/transport/huffsyms.cc',
-        'src/core/ext/transport/chttp2/transport/incoming_metadata.cc',
         'src/core/ext/transport/chttp2/transport/parsing.cc',
         'src/core/ext/transport/chttp2/transport/stream_lists.cc',
         'src/core/ext/transport/chttp2/transport/stream_map.cc',
         'src/core/ext/transport/inproc/inproc_transport.cc',
         'src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.c',
         'src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c',
-        'src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c',
         'src/core/ext/upb-generated/validate/validate.upb.c',
+        'src/core/ext/upb-generated/xds/data/orca/v3/orca_load_report.upb.c',
         'src/core/lib/address_utils/parse_address.cc',
         'src/core/lib/address_utils/sockaddr_utils.cc',
         'src/core/lib/avl/avl.cc',
         'src/core/lib/iomgr/timer_generic.cc',
         'src/core/lib/iomgr/timer_heap.cc',
         'src/core/lib/iomgr/timer_manager.cc',
-        'src/core/lib/iomgr/udp_server.cc',
         'src/core/lib/iomgr/unix_sockets_posix.cc',
         'src/core/lib/iomgr/unix_sockets_posix_noop.cc',
         'src/core/lib/iomgr/wakeup_fd_eventfd.cc',
         'src/core/lib/slice/b64.cc',
         'src/core/lib/slice/percent_encoding.cc',
         'src/core/lib/slice/slice.cc',
+        'src/core/lib/slice/slice_api.cc',
         'src/core/lib/slice/slice_buffer.cc',
         'src/core/lib/slice/slice_intern.cc',
+        'src/core/lib/slice/slice_refcount.cc',
+        'src/core/lib/slice/slice_split.cc',
         'src/core/lib/slice/slice_string_helpers.cc',
+        'src/core/lib/slice/static_slice.cc',
         'src/core/lib/surface/api_trace.cc',
+        'src/core/lib/surface/builtins.cc',
         'src/core/lib/surface/byte_buffer.cc',
         'src/core/lib/surface/byte_buffer_reader.cc',
         'src/core/lib/surface/call.cc',
         'src/core/lib/surface/server.cc',
         'src/core/lib/surface/validate_metadata.cc',
         'src/core/lib/surface/version.cc',
-        'src/core/lib/transport/authority_override.cc',
         'src/core/lib/transport/bdp_estimator.cc',
         'src/core/lib/transport/byte_stream.cc',
         'src/core/lib/transport/connectivity_state.cc',
         'grpc',
       ],
       'sources': [
+        'src/core/ext/transport/binder/client/binder_connector.cc',
+        'src/core/ext/transport/binder/client/channel_create.cc',
+        'src/core/ext/transport/binder/client/channel_create_impl.cc',
+        'src/core/ext/transport/binder/client/connection_id_generator.cc',
+        'src/core/ext/transport/binder/client/endpoint_binder_pool.cc',
+        'src/core/ext/transport/binder/client/jni_utils.cc',
+        'src/core/ext/transport/binder/client/security_policy_setting.cc',
+        'src/core/ext/transport/binder/security_policy/binder_security_policy.cc',
+        'src/core/ext/transport/binder/server/binder_server.cc',
+        'src/core/ext/transport/binder/server/binder_server_credentials.cc',
+        'src/core/ext/transport/binder/transport/binder_transport.cc',
+        'src/core/ext/transport/binder/utils/transport_stream_receiver_impl.cc',
+        'src/core/ext/transport/binder/wire_format/binder_android.cc',
+        'src/core/ext/transport/binder/wire_format/binder_constants.cc',
+        'src/core/ext/transport/binder/wire_format/transaction.cc',
+        'src/core/ext/transport/binder/wire_format/wire_reader_impl.cc',
+        'src/core/ext/transport/binder/wire_format/wire_writer.cc',
         'src/cpp/client/channel_cc.cc',
         'src/cpp/client/client_callback.cc',
         'src/cpp/client/client_context.cc',
         'third_party/benchmark/src/counter.cc',
         'third_party/benchmark/src/csv_reporter.cc',
         'third_party/benchmark/src/json_reporter.cc',
+        'third_party/benchmark/src/perf_counters.cc',
         'third_party/benchmark/src/reporter.cc',
         'third_party/benchmark/src/sleep.cc',
         'third_party/benchmark/src/statistics.cc',
index 61e3ecb..ec6b913 100644 (file)
@@ -24,8 +24,8 @@
 #include "absl/time/time.h"
 
 #include <grpc/event_engine/endpoint_config.h>
+#include <grpc/event_engine/memory_allocator.h>
 #include <grpc/event_engine/port.h>
-#include <grpc/event_engine/slice_allocator.h>
 
 // TODO(hork): Define the Endpoint::Write metrics collection system
 namespace grpc_event_engine {
@@ -73,12 +73,27 @@ namespace experimental {
 ////////////////////////////////////////////////////////////////////////////////
 class EventEngine {
  public:
-  /// Basic callable function. The first argument to all callbacks is an
-  /// absl::Status indicating the status of the operation associated with this
-  /// callback. Each EventEngine method that takes a callback parameter, defines
-  /// the expected sets and meanings of statuses for that use case.
-  using Callback = std::function<void(absl::Status)>;
-  /// Callback handle, used to cancel a callback.
+  /// A custom closure type for EventEngine task execution.
+  ///
+  /// Throughout the EventEngine API, \a Closure ownership is retained by the
+  /// caller - the EventEngine will never delete a Closure, and upon
+  /// cancellation, the EventEngine will simply forget the Closure exists. The
+  /// caller is responsible for all necessary cleanup.
+  class Closure {
+   public:
+    Closure() = default;
+    // Closure's are an interface, and thus non-copyable.
+    Closure(const Closure&) = delete;
+    Closure& operator=(const Closure&) = delete;
+    // Polymorphic type => virtual destructor
+    virtual ~Closure() = default;
+    // Run the contained code.
+    virtual void Run() = 0;
+  };
+  /// Represents a scheduled task.
+  ///
+  /// \a TaskHandles are returned by \a Run* methods, and can be given to the
+  /// \a Cancel method.
   struct TaskHandle {
     intptr_t keys[2];
   };
@@ -108,7 +123,7 @@ class EventEngine {
   /// created when connections are established, and Endpoint operations are
   /// gRPC's primary means of communication.
   ///
-  /// Endpoints must use the provided SliceAllocator for all data buffer memory
+  /// Endpoints must use the provided MemoryAllocator for all data buffer memory
   /// allocations. gRPC allows applications to set memory constraints per
   /// Channel or Server, and the implementation depends on all dynamic memory
   /// allocation being handled by the quota system.
@@ -134,7 +149,8 @@ class EventEngine {
     /// For failed read operations, implementations should pass the appropriate
     /// statuses to \a on_read. For example, callbacks might expect to receive
     /// CANCELLED on endpoint shutdown.
-    virtual void Read(Callback on_read, SliceBuffer* buffer) = 0;
+    virtual void Read(std::function<void(absl::Status)> on_read,
+                      SliceBuffer* buffer) = 0;
     /// Writes data out on the connection.
     ///
     /// \a on_writable is called when the connection is ready for more data. The
@@ -153,7 +169,8 @@ class EventEngine {
     /// For failed write operations, implementations should pass the appropriate
     /// statuses to \a on_writable. For example, callbacks might expect to
     /// receive CANCELLED on endpoint shutdown.
-    virtual void Write(Callback on_writable, SliceBuffer* data) = 0;
+    virtual void Write(std::function<void(absl::Status)> on_writable,
+                       SliceBuffer* data) = 0;
     /// Returns an address in the format described in DNSResolver. The returned
     /// values are expected to remain valid for the life of the Endpoint.
     virtual const ResolvedAddress& GetPeerAddress() const = 0;
@@ -175,7 +192,7 @@ class EventEngine {
    public:
     /// Called when the listener has accepted a new client connection.
     using AcceptCallback = std::function<void(
-        std::unique_ptr<Endpoint>, const SliceAllocator& slice_allocator)>;
+        std::unique_ptr<Endpoint>, MemoryAllocator memory_allocator)>;
     virtual ~Listener() = default;
     /// Bind an address/port to this Listener.
     ///
@@ -198,12 +215,13 @@ class EventEngine {
   /// exactly once, when the Listener is shut down. The status passed to it will
   /// indicate if there was a problem during shutdown.
   ///
-  /// The provided \a SliceAllocatorFactory is used to create \a SliceAllocators
-  /// for Endpoint construction.
+  /// The provided \a MemoryAllocatorFactory is used to create \a
+  /// MemoryAllocators for Endpoint construction.
   virtual absl::StatusOr<std::unique_ptr<Listener>> CreateListener(
-      Listener::AcceptCallback on_accept, Callback on_shutdown,
+      Listener::AcceptCallback on_accept,
+      std::function<void(absl::Status)> on_shutdown,
       const EndpointConfig& config,
-      std::unique_ptr<SliceAllocatorFactory> slice_allocator_factory) = 0;
+      std::unique_ptr<MemoryAllocatorFactory> memory_allocator_factory) = 0;
   /// Creates a client network connection to a remote network listener.
   ///
   /// May return an error status immediately if there was a failure in the
@@ -212,15 +230,15 @@ class EventEngine {
   /// expected that the \a on_connect callback will be asynchronously executed
   /// exactly once by the EventEngine.
   ///
-  /// Implementation Note: it is important that the \a slice_allocator be used
+  /// Implementation Note: it is important that the \a memory_allocator be used
   /// for all read/write buffer allocations in the EventEngine implementation.
   /// This allows gRPC's \a ResourceQuota system to monitor and control memory
   /// usage with graceful degradation mechanisms. Please see the \a
-  /// SliceAllocator API for more information.
+  /// MemoryAllocator API for more information.
   virtual absl::Status Connect(OnConnectCallback on_connect,
                                const ResolvedAddress& addr,
                                const EndpointConfig& args,
-                               std::unique_ptr<SliceAllocator> slice_allocator,
+                               MemoryAllocator memory_allocator,
                                absl::Time deadline) = 0;
 
   /// Provides asynchronous resolution.
@@ -257,8 +275,10 @@ class EventEngine {
     /// When the lookup is complete, the \a on_resolve callback will be invoked
     /// with a status indicating the success or failure of the lookup.
     /// Implementations should pass the appropriate statuses to the callback.
-    /// For example, callbacks might expect to receive DEADLINE_EXCEEDED when
-    /// the deadline is exceeded or CANCELLED if the lookup was cancelled.
+    /// For example, callbacks might expect to receive DEADLINE_EXCEEDED or
+    /// NOT_FOUND.
+    ///
+    /// If cancelled, \a on_resolve will not be executed.
     virtual LookupTaskHandle LookupHostname(LookupHostnameCallback on_resolve,
                                             absl::string_view address,
                                             absl::string_view default_port,
@@ -278,7 +298,11 @@ class EventEngine {
                                        absl::string_view name,
                                        absl::Time deadline) = 0;
     /// Cancel an asynchronous lookup operation.
-    virtual void TryCancelLookup(LookupTaskHandle handle) = 0;
+    ///
+    /// This shares the same semantics with \a EventEngine::Cancel: successfully
+    /// cancelled lookups will not have their callbacks executed, and this
+    /// method returns true.
+    virtual bool CancelLookup(LookupTaskHandle handle) = 0;
   };
 
   /// At time of destruction, the EventEngine must have no active
@@ -297,32 +321,48 @@ class EventEngine {
   /// Creates and returns an instance of a DNSResolver.
   virtual std::unique_ptr<DNSResolver> GetDNSResolver() = 0;
 
-  /// Executes a callback as soon as possible.
+  /// Asynchronously executes a task as soon as possible.
   ///
-  /// The \a fn callback's \a status argument is used to indicate whether it was
-  /// executed normally. For example, the status may be CANCELLED if the
-  /// EventEngine is being shut down. \a fn is guaranteed to be called exactly
-  /// once.
-  virtual void Run(Callback fn) = 0;
+  /// \a Closures scheduled with \a Run cannot be cancelled. The \a closure will
+  /// not be deleted after it has been run, ownership remains with the caller.
+  virtual void Run(Closure* closure) = 0;
+  /// Asynchronously executes a task as soon as possible.
+  ///
+  /// \a Closures scheduled with \a Run cannot be cancelled. Unlike the
+  /// overloaded \a Closure alternative, the std::function version's \a closure
+  /// will be deleted by the EventEngine after the closure has been run.
+  ///
+  /// This version of \a Run may be less performant than the \a Closure version
+  /// in some scenarios. This overload is useful in situations where performance
+  /// is not a critical concern.
+  virtual void Run(std::function<void()> closure) = 0;
   /// Synonymous with scheduling an alarm to run at time \a when.
   ///
-  /// The callback \a fn will execute when either when time \a when arrives
-  /// (receiving status OK), or when the \a fn is cancelled (receiving status
-  /// CANCELLED). The callback is guaranteed to be called exactly once.
-  virtual TaskHandle RunAt(absl::Time when, Callback fn) = 0;
-  /// Attempts to cancel a callback.
-  /// Note that this is a "best effort" cancellation. No guarantee is made that
-  /// the callback will be cancelled, the call could be in any stage.
+  /// The \a closure will execute when time \a when arrives unless it has been
+  /// cancelled via the \a Cancel method. If cancelled, the closure will not be
+  /// run, nor will it be deleted. Ownership remains with the caller.
+  virtual TaskHandle RunAt(absl::Time when, Closure* closure) = 0;
+  /// Synonymous with scheduling an alarm to run at time \a when.
+  ///
+  /// The \a closure will execute when time \a when arrives unless it has been
+  /// cancelled via the \a Cancel method. If cancelled, the closure will not be
+  /// run. Unilke the overloaded \a Closure alternative, the std::function
+  /// version's \a closure will be deleted by the EventEngine after the closure
+  /// has been run, or upon cancellation.
+  ///
+  /// This version of \a RunAt may be less performant than the \a Closure
+  /// version in some scenarios. This overload is useful in situations where
+  /// performance is not a critical concern.
+  virtual TaskHandle RunAt(absl::Time when, std::function<void()> closure) = 0;
+  /// Request cancellation of a task.
   ///
-  /// There are three scenarios in which we may cancel a scheduled task:
-  ///   1. We cancel the execution before it has run.
-  ///   2. The callback has already run.
-  ///   3. We can't cancel it because it is "in flight".
+  /// If the associated closure has already been scheduled to run, it will not
+  /// be cancelled, and this function will return false.
   ///
-  /// In all cases, the cancellation is still considered successful, the
-  /// callback will be run exactly once from either cancellation or from its
-  /// activation.
-  virtual void TryCancel(TaskHandle handle) = 0;
+  /// If the associated callback has not been scheduled to run, it will be
+  /// cancelled, and the associated std::function or \a Closure* will not be
+  /// executed. In this case, Cancel will return true.
+  virtual bool Cancel(TaskHandle handle) = 0;
 };
 
 // TODO(hork): finalize the API and document it. We need to firm up the story
diff --git a/include/grpc/event_engine/internal/memory_allocator_impl.h b/include/grpc/event_engine/internal/memory_allocator_impl.h
new file mode 100644 (file)
index 0000000..a790057
--- /dev/null
@@ -0,0 +1,98 @@
+// Copyright 2021 The gRPC Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#ifndef GRPC_EVENT_ENGINE_INTERNAL_MEMORY_ALLOCATOR_IMPL_H
+#define GRPC_EVENT_ENGINE_INTERNAL_MEMORY_ALLOCATOR_IMPL_H
+
+#include <grpc/impl/codegen/port_platform.h>
+
+#include <algorithm>
+#include <memory>
+#include <type_traits>
+#include <vector>
+
+#include <grpc/slice.h>
+
+// forward-declaring an internal struct, not used publicly.
+struct grpc_slice_buffer;
+
+namespace grpc_event_engine {
+namespace experimental {
+
+/// Reservation request - how much memory do we want to allocate?
+class MemoryRequest {
+ public:
+  /// Request a fixed amount of memory.
+  // NOLINTNEXTLINE(google-explicit-constructor)
+  MemoryRequest(size_t n) : min_(n), max_(n) {}
+  /// Request a range of memory.
+  /// Requires: \a min <= \a max.
+  /// Requires: \a max <= max_size()
+  MemoryRequest(size_t min, size_t max) : min_(min), max_(max) {}
+
+  /// Maximum allowable request size - hard coded to 1GB.
+  static constexpr size_t max_allowed_size() { return 1024 * 1024 * 1024; }
+
+  /// Increase the size by \a amount.
+  /// Undefined behavior if min() + amount or max() + amount overflows.
+  MemoryRequest Increase(size_t amount) const {
+    return MemoryRequest(min_ + amount, max_ + amount);
+  }
+
+  size_t min() const { return min_; }
+  size_t max() const { return max_; }
+
+ private:
+  size_t min_;
+  size_t max_;
+};
+
+namespace internal {
+
+/// Underlying memory allocation interface.
+/// This is an internal interface, not intended to be used by users.
+/// Its interface is subject to change at any time.
+class MemoryAllocatorImpl
+    : public std::enable_shared_from_this<MemoryAllocatorImpl> {
+ public:
+  MemoryAllocatorImpl() {}
+  virtual ~MemoryAllocatorImpl() {}
+
+  MemoryAllocatorImpl(const MemoryAllocatorImpl&) = delete;
+  MemoryAllocatorImpl& operator=(const MemoryAllocatorImpl&) = delete;
+
+  /// Reserve bytes from the quota.
+  /// If we enter overcommit, reclamation will begin concurrently.
+  /// Returns the number of bytes reserved.
+  /// If MemoryRequest is invalid, this function will abort.
+  /// If MemoryRequest is valid, this function is infallible, and will always
+  /// succeed at reserving the some number of bytes between request.min() and
+  /// request.max() inclusively.
+  virtual size_t Reserve(MemoryRequest request) = 0;
+
+  /// Release some bytes that were previously reserved.
+  /// If more bytes are released than were reserved, we will have undefined
+  /// behavior.
+  virtual void Release(size_t n) = 0;
+
+  /// Shutdown this allocator.
+  /// Further usage of Reserve() is undefined behavior.
+  virtual void Shutdown() = 0;
+};
+
+}  // namespace internal
+
+}  // namespace experimental
+}  // namespace grpc_event_engine
+
+#endif  // GRPC_EVENT_ENGINE_INTERNAL_MEMORY_ALLOCATOR_IMPL_H
diff --git a/include/grpc/event_engine/memory_allocator.h b/include/grpc/event_engine/memory_allocator.h
new file mode 100644 (file)
index 0000000..fb200da
--- /dev/null
@@ -0,0 +1,210 @@
+// Copyright 2021 The gRPC Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#ifndef GRPC_EVENT_ENGINE_MEMORY_ALLOCATOR_H
+#define GRPC_EVENT_ENGINE_MEMORY_ALLOCATOR_H
+
+#include <grpc/impl/codegen/port_platform.h>
+
+#include <algorithm>
+#include <memory>
+#include <type_traits>
+#include <vector>
+
+#include <grpc/event_engine/internal/memory_allocator_impl.h>
+#include <grpc/slice.h>
+
+// forward-declaring an internal struct, not used publicly.
+struct grpc_slice_buffer;
+
+namespace grpc_event_engine {
+namespace experimental {
+
+// TODO(nnoble): needs implementation
+class SliceBuffer {
+ public:
+  SliceBuffer() { abort(); }
+  explicit SliceBuffer(grpc_slice_buffer*) { abort(); }
+
+  grpc_slice_buffer* RawSliceBuffer() { return slice_buffer_; }
+
+ private:
+  grpc_slice_buffer* slice_buffer_;
+};
+
+class MemoryAllocator {
+ public:
+  /// Construct a MemoryAllocator given an internal::MemoryAllocatorImpl
+  /// implementation. The constructed MemoryAllocator will call
+  /// MemoryAllocatorImpl::Shutdown() upon destruction.
+  explicit MemoryAllocator(
+      std::shared_ptr<internal::MemoryAllocatorImpl> allocator)
+      : allocator_(std::move(allocator)) {}
+  ~MemoryAllocator() {
+    if (allocator_ != nullptr) allocator_->Shutdown();
+  }
+
+  MemoryAllocator(const MemoryAllocator&) = delete;
+  MemoryAllocator& operator=(const MemoryAllocator&) = delete;
+
+  MemoryAllocator(MemoryAllocator&&) = default;
+  MemoryAllocator& operator=(MemoryAllocator&&) = default;
+
+  /// Reserve bytes from the quota.
+  /// If we enter overcommit, reclamation will begin concurrently.
+  /// Returns the number of bytes reserved.
+  size_t Reserve(MemoryRequest request) { return allocator_->Reserve(request); }
+
+  /// Release some bytes that were previously reserved.
+  void Release(size_t n) { return allocator_->Release(n); }
+
+  /// Return a pointer to the underlying implementation.
+  /// Note that the interface of said implementatoin is unstable and likely to
+  /// change at any time.
+  internal::MemoryAllocatorImpl* get_internal_impl_ptr() {
+    return allocator_.get();
+  }
+
+  //
+  // The remainder of this type are helper functions implemented in terms of
+  // Reserve/Release.
+  //
+
+  /// An automatic releasing reservation of memory.
+  class Reservation {
+   public:
+    Reservation() = default;
+    Reservation(const Reservation&) = delete;
+    Reservation& operator=(const Reservation&) = delete;
+    Reservation(Reservation&&) = default;
+    Reservation& operator=(Reservation&&) = default;
+    ~Reservation() {
+      if (allocator_ != nullptr) allocator_->Release(size_);
+    }
+
+   private:
+    friend class MemoryAllocator;
+    Reservation(std::shared_ptr<internal::MemoryAllocatorImpl> allocator,
+                size_t size)
+        : allocator_(std::move(allocator)), size_(size) {}
+
+    std::shared_ptr<internal::MemoryAllocatorImpl> allocator_;
+    size_t size_ = 0;
+  };
+
+  /// Reserve bytes from the quota and automatically release them when
+  /// Reservation is destroyed.
+  Reservation MakeReservation(MemoryRequest request) {
+    return Reservation(allocator_, Reserve(request));
+  }
+
+  /// Allocate a new object of type T, with constructor arguments.
+  /// The returned type is wrapped, and upon destruction the reserved memory
+  /// will be released to the allocator automatically. As such, T must have a
+  /// virtual destructor so we can insert the necessary hook.
+  template <typename T, typename... Args>
+  typename std::enable_if<std::has_virtual_destructor<T>::value, T*>::type New(
+      Args&&... args) {
+    // Wrap T such that when it's destroyed, we can release memory back to the
+    // allocator.
+    class Wrapper final : public T {
+     public:
+      explicit Wrapper(std::shared_ptr<internal::MemoryAllocatorImpl> allocator,
+                       Args&&... args)
+          : T(std::forward<Args>(args)...), allocator_(std::move(allocator)) {}
+      ~Wrapper() override { allocator_->Release(sizeof(*this)); }
+
+     private:
+      const std::shared_ptr<internal::MemoryAllocatorImpl> allocator_;
+    };
+    Reserve(sizeof(Wrapper));
+    return new Wrapper(allocator_, std::forward<Args>(args)...);
+  }
+
+  /// Construct a unique_ptr immediately.
+  template <typename T, typename... Args>
+  std::unique_ptr<T> MakeUnique(Args&&... args) {
+    return std::unique_ptr<T>(New<T>(std::forward<Args>(args)...));
+  }
+
+  /// Allocate a slice, using MemoryRequest to size the number of returned
+  /// bytes. For a variable length request, check the returned slice length to
+  /// verify how much memory was allocated. Takes care of reserving memory for
+  /// any relevant control structures also.
+  grpc_slice MakeSlice(MemoryRequest request);
+
+  /// A C++ allocator for containers of T.
+  template <typename T>
+  class Container {
+   public:
+    using value_type = T;
+
+    /// Construct the allocator: \a underlying_allocator is borrowed, and must
+    /// outlive this object.
+    explicit Container(MemoryAllocator* underlying_allocator)
+        : underlying_allocator_(underlying_allocator) {}
+    template <typename U>
+    explicit Container(const Container<U>& other)
+        : underlying_allocator_(other.underlying_allocator()) {}
+
+    MemoryAllocator* underlying_allocator() const {
+      return underlying_allocator_;
+    }
+
+    T* allocate(size_t n) {
+      underlying_allocator_->Reserve(n * sizeof(T));
+      return static_cast<T*>(::operator new(n * sizeof(T)));
+    }
+    void deallocate(T* p, size_t n) {
+      ::operator delete(p);
+      underlying_allocator_->Release(n * sizeof(T));
+    }
+
+   private:
+    MemoryAllocator* underlying_allocator_;
+  };
+
+ protected:
+  const std::shared_ptr<internal::MemoryAllocatorImpl>& allocator() {
+    return allocator_;
+  }
+
+ private:
+  std::shared_ptr<internal::MemoryAllocatorImpl> allocator_;
+};
+
+// Wrapper type around std::vector to make initialization against a
+// MemoryAllocator based container allocator easy.
+template <typename T>
+class Vector : public std::vector<T, MemoryAllocator::Container<T>> {
+ public:
+  explicit Vector(MemoryAllocator* allocator)
+      : std::vector<T, MemoryAllocator::Container<T>>(
+            MemoryAllocator::Container<T>(allocator)) {}
+};
+
+class MemoryAllocatorFactory {
+ public:
+  virtual ~MemoryAllocatorFactory() = default;
+  /// On Endpoint creation, call \a CreateMemoryAllocator to create a new
+  /// allocator for the endpoint.
+  /// Typically we'll want to:
+  ///    auto allocator = factory->CreateMemoryAllocator();
+  ///    auto* endpoint = allocator->New<MyEndpoint>(std::move(allocator), ...);
+  virtual MemoryAllocator CreateMemoryAllocator() = 0;
+};
+
+}  // namespace experimental
+}  // namespace grpc_event_engine
+
+#endif  // GRPC_EVENT_ENGINE_MEMORY_ALLOCATOR_H
diff --git a/include/grpc/event_engine/slice_allocator.h b/include/grpc/event_engine/slice_allocator.h
deleted file mode 100644 (file)
index beccfd6..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright 2021 The gRPC Authors
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-#ifndef GRPC_EVENT_ENGINE_SLICE_ALLOCATOR_H
-#define GRPC_EVENT_ENGINE_SLICE_ALLOCATOR_H
-
-#include <grpc/support/port_platform.h>
-
-#include <functional>
-
-#include "absl/status/status.h"
-
-// forward-declaring an internal struct, not used publicly.
-struct grpc_resource_quota;
-struct grpc_resource_user;
-struct grpc_slice_buffer;
-
-namespace grpc_event_engine {
-namespace experimental {
-
-// TODO(nnoble): needs implementation
-class SliceBuffer {
- public:
-  SliceBuffer() { abort(); }
-  explicit SliceBuffer(grpc_slice_buffer*) { abort(); }
-
-  grpc_slice_buffer* RawSliceBuffer() { return slice_buffer_; }
-
- private:
-  grpc_slice_buffer* slice_buffer_;
-};
-
-class SliceAllocator {
- public:
-  using AllocateCallback = std::function<void(absl::Status)>;
-  virtual ~SliceAllocator() = default;
-  /// Requests \a size bytes from gRPC, and populates \a dest with the allocated
-  /// slices. Ownership of the \a SliceBuffer is not transferred.
-  ///
-  /// gRPC provides a ResourceQuota system to cap the amount of memory used by
-  /// the library. When a memory limit has been reached, slice allocation is
-  /// interrupted to attempt to reclaim memory from participating gRPC
-  /// internals. When there is sufficient memory available, slice allocation
-  /// proceeds as normal.
-  virtual absl::Status Allocate(size_t size, SliceBuffer* dest,
-                                SliceAllocator::AllocateCallback cb) = 0;
-};
-
-class SliceAllocatorFactory {
- public:
-  virtual ~SliceAllocatorFactory() = default;
-  /// On Endpoint creation, call \a CreateSliceAllocator with the name of the
-  /// endpoint peer (a URI string, most likely).
-  virtual std::unique_ptr<SliceAllocator> CreateSliceAllocator(
-      absl::string_view peer_name) = 0;
-};
-
-}  // namespace experimental
-}  // namespace grpc_event_engine
-
-#endif  // GRPC_EVENT_ENGINE_SLICE_ALLOCATOR_H
index ee30ae1..136a4e5 100644 (file)
@@ -340,6 +340,10 @@ GRPCAPI grpc_call_error grpc_call_cancel_with_status(grpc_call* call,
                                                      const char* description,
                                                      void* reserved);
 
+/* Returns whether or not the call's receive message operation failed because of
+ * an error (as opposed to a graceful end-of-stream) */
+GRPCAPI int grpc_call_failed_before_recv_message(const grpc_call* c);
+
 /** Ref a call.
     THREAD SAFETY: grpc_call_ref is thread-compatible */
 GRPCAPI void grpc_call_ref(grpc_call* call);
index 9edd70f..2902100 100644 (file)
@@ -1111,6 +1111,24 @@ grpc_authorization_policy_provider_static_data_create(
 
 /**
  * EXPERIMENTAL - Subject to change.
+ * Creates a grpc_authorization_policy_provider by watching for SDK
+ * authorization policy changes in filesystem.
+ * - authz_policy is the file path of SDK authorization policy.
+ * - refresh_interval_sec is the amount of time the internal thread would wait
+ *   before checking for file updates.
+ * - code is the error status code on failure. On success, it equals
+ *   GRPC_STATUS_OK.
+ * - error_details contains details about the error if any. If the
+ *   initialization is successful, it will be null. Caller must use gpr_free to
+ *   destroy this string.
+ */
+GRPCAPI grpc_authorization_policy_provider*
+grpc_authorization_policy_provider_file_watcher_create(
+    const char* authz_policy_path, unsigned int refresh_interval_sec,
+    grpc_status_code* code, const char** error_details);
+
+/**
+ * EXPERIMENTAL - Subject to change.
  * Releases grpc_authorization_policy_provider object. The creator of
  * grpc_authorization_policy_provider is responsible for its release.
  */
index 3b2d45a..1c3cbc7 100644 (file)
@@ -25,6 +25,7 @@ extern "C" {
 
 #define GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME "transport_security_type"
 #define GRPC_SSL_TRANSPORT_SECURITY_TYPE "ssl"
+#define GRPC_TLS_TRANSPORT_SECURITY_TYPE "tls"
 
 #define GRPC_X509_CN_PROPERTY_NAME "x509_common_name"
 #define GRPC_X509_SAN_PROPERTY_NAME "x509_subject_alternative_name"
index 8b9831b..d9fdeed 100644 (file)
 #endif /* _LP64 */
 #ifdef __GLIBC__
 #define GPR_POSIX_CRASH_HANDLER 1
+#ifdef __GLIBC_PREREQ
+#if __GLIBC_PREREQ(2, 12)
 #define GPR_LINUX_PTHREAD_NAME 1
+#endif
+#else
+// musl libc & others
+#define GPR_LINUX_PTHREAD_NAME 1
+#endif
 #include <linux/version.h>
 #else /* musl libc */
 #define GPR_MUSL_LIBC_COMPAT 1
diff --git a/include/grpcpp/create_channel_binder.h b/include/grpcpp/create_channel_binder.h
new file mode 100644 (file)
index 0000000..a724e87
--- /dev/null
@@ -0,0 +1,77 @@
+// 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.
+
+#ifndef GRPCPP_CREATE_CHANNEL_BINDER_H
+#define GRPCPP_CREATE_CHANNEL_BINDER_H
+
+#include <grpc/support/port_platform.h>
+
+#ifdef GPR_ANDROID
+
+#include <jni.h>
+
+#include <memory>
+
+#include "absl/strings/string_view.h"
+
+#include <grpcpp/channel.h>
+#include <grpcpp/security/binder_security_policy.h>
+#include <grpcpp/support/channel_arguments.h>
+
+namespace grpc {
+namespace experimental {
+
+/// EXPERIMENTAL Create a new \a Channel based on binder transport. The package
+/// name and class name will be used identify the specific application component
+/// to connect to.
+///
+/// \param jni_env Pointer to a JNIEnv structure
+/// \param context The context that we will use to invoke \a bindService See
+/// https://developer.android.com/reference/android/content/Context#bindService(android.content.Intent,%20android.content.ServiceConnection,%20int)
+/// for detail.
+/// \param package_name Package name of the component to be connected to
+/// \param class_name Class name of the component to be connected to
+/// \param security_policy Used for checking if remote component is allowed to
+/// connect
+std::shared_ptr<grpc::Channel> CreateBinderChannel(
+    void* jni_env, jobject context, absl::string_view package_name,
+    absl::string_view class_name,
+    std::shared_ptr<grpc::experimental::binder::SecurityPolicy>
+        security_policy);
+
+/// EXPERIMENTAL Create a new \a Channel based on binder transport. The package
+/// name and class name will be used identify the specific application component
+/// to connect to.
+///
+/// \param jni_env Pointer to a JNIEnv structure
+/// \param context The context that we will use to invoke \a bindService See
+/// https://developer.android.com/reference/android/content/Context#bindService(android.content.Intent,%20android.content.ServiceConnection,%20int)
+/// for detail.
+/// \param package_name Package name of the component to be connected to
+/// \param class_name Class name of the component to be connected to
+/// \param security_policy Used for checking if remote component is allowed to
+/// connect
+/// \param args Options for channel creation.
+std::shared_ptr<grpc::Channel> CreateCustomBinderChannel(
+    void* jni_env_void, jobject application, absl::string_view package_name,
+    absl::string_view class_name,
+    std::shared_ptr<grpc::experimental::binder::SecurityPolicy> security_policy,
+    const ChannelArguments& args);
+
+}  // namespace experimental
+}  // namespace grpc
+
+#endif
+
+#endif  // GRPCPP_CREATE_CHANNEL_BINDER_H
index 0cefdb5..e0440ff 100644 (file)
@@ -72,6 +72,7 @@ class CoreCodegen final : public CoreCodegenInterface {
                                                grpc_status_code status,
                                                const char* description,
                                                void* reserved) override;
+  int grpc_call_failed_before_recv_message(const grpc_call* c) override;
   void grpc_call_ref(grpc_call* call) override;
   void grpc_call_unref(grpc_call* call) override;
   void* grpc_call_arena_alloc(grpc_call* call, size_t length) override;
index edbeee2..0b23bf4 100644 (file)
@@ -113,6 +113,7 @@ class CoreCodegenInterface {
                                                        grpc_status_code status,
                                                        const char* description,
                                                        void* reserved) = 0;
+  virtual int grpc_call_failed_before_recv_message(const grpc_call* c) = 0;
   virtual void grpc_call_ref(grpc_call* call) = 0;
   virtual void grpc_call_unref(grpc_call* call) = 0;
   virtual void* grpc_call_arena_alloc(grpc_call* call, size_t length) = 0;
index a0cd181..f74fa97 100644 (file)
@@ -65,6 +65,8 @@ class ServerReader;
 template <class W>
 class ServerWriter;
 
+extern CoreCodegenInterface* g_core_codegen_interface;
+
 namespace internal {
 template <class ServiceType, class RequestType, class ResponseType>
 class BidiStreamingHandler;
@@ -420,7 +422,12 @@ class ServerContextBase {
     message_allocator_state_ = allocator_state;
   }
 
-  void MaybeMarkCancelledOnRead();
+  void MaybeMarkCancelledOnRead() {
+    if (g_core_codegen_interface->grpc_call_failed_before_recv_message(
+            call_.call)) {
+      marked_cancelled_.store(true, std::memory_order_release);
+    }
+  }
 
   struct CallWrapper {
     ~CallWrapper();
index 17faeb5..1ce3acd 100644 (file)
@@ -609,7 +609,11 @@ class ServerReader final : public ServerReaderInterface<R> {
     ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvMessage<R>> ops;
     ops.RecvMessage(msg);
     call_->PerformOps(&ops);
-    return call_->cq()->Pluck(&ops) && ops.got_message;
+    bool ok = call_->cq()->Pluck(&ops) && ops.got_message;
+    if (!ok) {
+      ctx_->MaybeMarkCancelledOnRead();
+    }
+    return ok;
   }
 
  private:
@@ -736,7 +740,11 @@ class ServerReaderWriterBody final {
     ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvMessage<R>> ops;
     ops.RecvMessage(msg);
     call_->PerformOps(&ops);
-    return call_->cq()->Pluck(&ops) && ops.got_message;
+    bool ok = call_->cq()->Pluck(&ops) && ops.got_message;
+    if (!ok) {
+      ctx_->MaybeMarkCancelledOnRead();
+    }
+    return ok;
   }
 
   bool Write(const W& msg, ::grpc::WriteOptions options) {
index b3258b2..883dc1a 100644 (file)
@@ -20,7 +20,7 @@
 #include <grpc/status.h>
 #include <grpcpp/impl/codegen/grpc_library.h>
 
-// TODO(yihuazhang): remove the forward declaration here and include
+// TODO(yihuazhang): remove the forward declarations here and include
 // <grpc/grpc_security.h> directly once the insecure builds are cleaned up.
 typedef struct grpc_authorization_policy_provider
     grpc_authorization_policy_provider;
@@ -61,6 +61,31 @@ class StaticDataAuthorizationPolicyProvider
   grpc_authorization_policy_provider* c_provider_ = nullptr;
 };
 
+// Implementation obtains authorization policy by watching for changes in
+// filesystem.
+class FileWatcherAuthorizationPolicyProvider
+    : public AuthorizationPolicyProviderInterface {
+ public:
+  static std::shared_ptr<FileWatcherAuthorizationPolicyProvider> Create(
+      const std::string& authz_policy_path, unsigned int refresh_interval_sec,
+      grpc::Status* status);
+
+  // Use factory method "Create" to create an instance of
+  // FileWatcherAuthorizationPolicyProvider.
+  explicit FileWatcherAuthorizationPolicyProvider(
+      grpc_authorization_policy_provider* provider)
+      : c_provider_(provider) {}
+
+  ~FileWatcherAuthorizationPolicyProvider() override;
+
+  grpc_authorization_policy_provider* c_provider() override {
+    return c_provider_;
+  }
+
+ private:
+  grpc_authorization_policy_provider* c_provider_ = nullptr;
+};
+
 }  // namespace experimental
 }  // namespace grpc
 
diff --git a/include/grpcpp/security/binder_credentials.h b/include/grpcpp/security/binder_credentials.h
new file mode 100644 (file)
index 0000000..f511837
--- /dev/null
@@ -0,0 +1,43 @@
+// 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.
+
+#ifndef GRPCPP_SECURITY_BINDER_CREDENTIALS_H
+#define GRPCPP_SECURITY_BINDER_CREDENTIALS_H
+
+#include <memory>
+
+#include <grpcpp/security/binder_security_policy.h>
+#include <grpcpp/security/server_credentials.h>
+
+namespace grpc {
+
+class ChannelCredentials;
+
+namespace experimental {
+
+/// EXPERIMENTAL Builds Binder ServerCredentials.
+///
+/// This should be used along with `binder:` URI scheme. The path in the URI can
+/// later be used to access the server's endpoint binder.
+/// Note that calling \a ServerBuilder::AddListeningPort() with Binder
+/// ServerCredentials in a non-supported environment will make the subsequent
+/// call to \a ServerBuilder::BuildAndStart() return a null pointer.
+std::shared_ptr<grpc::ServerCredentials> BinderServerCredentials(
+    std::shared_ptr<grpc::experimental::binder::SecurityPolicy>
+        security_policy);
+
+}  // namespace experimental
+}  // namespace grpc
+
+#endif  // GRPCPP_SECURITY_BINDER_CREDENTIALS_H
diff --git a/include/grpcpp/security/binder_security_policy.h b/include/grpcpp/security/binder_security_policy.h
new file mode 100644 (file)
index 0000000..9b825e7
--- /dev/null
@@ -0,0 +1,58 @@
+// 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.
+
+#ifndef GRPCPP_SECURITY_BINDER_SECURITY_POLICY_H
+#define GRPCPP_SECURITY_BINDER_SECURITY_POLICY_H
+
+#include <memory>
+
+namespace grpc {
+namespace experimental {
+namespace binder {
+
+// EXPERIMENTAL Determinines if a connection is allowed to be
+// established on Android. See https://source.android.com/security/app-sandbox
+// for more info about UID.
+class SecurityPolicy {
+ public:
+  virtual ~SecurityPolicy() = default;
+  // Returns true if the UID is authorized to connect.
+  // Must return the same value for the same inputs so callers can safely cache
+  // the result.
+  virtual bool IsAuthorized(int uid) = 0;
+};
+
+// EXPERIMENTAL Allows all connection. Anything on the Android device will be
+// able to connect, use with caution!
+class UntrustedSecurityPolicy : public SecurityPolicy {
+ public:
+  UntrustedSecurityPolicy();
+  ~UntrustedSecurityPolicy() override;
+  bool IsAuthorized(int uid) override;
+};
+
+// EXPERIMENTAL Only allows the connections from processes with the same UID. In
+// most cases this means "from the same APK".
+class InternalOnlySecurityPolicy : public SecurityPolicy {
+ public:
+  InternalOnlySecurityPolicy();
+  ~InternalOnlySecurityPolicy() override;
+  bool IsAuthorized(int uid) override;
+};
+
+}  // namespace binder
+}  // namespace experimental
+}  // namespace grpc
+
+#endif  // GRPCPP_SECURITY_BINDER_SECURITY_POLICY_H
index 745c8d5..03e1e02 100644 (file)
@@ -13,8 +13,8 @@
  <date>2019-09-24</date>
  <time>16:06:07</time>
  <version>
-  <release>1.41.1</release>
-  <api>1.41.1</api>
+  <release>1.42.0</release>
+  <api>1.42.0</api>
  </version>
  <stability>
   <release>stable</release>
@@ -22,7 +22,7 @@
  </stability>
  <license>Apache 2.0</license>
  <notes>
-- gRPC Core 1.41.1 update
+- gRPC Core 1.42.0 update
  </notes>
  <contents>
   <dir baseinstalldir="/" name="/">
@@ -35,8 +35,9 @@
     <file baseinstalldir="/" name="include/grpc/compression.h" role="src" />
     <file baseinstalldir="/" name="include/grpc/event_engine/endpoint_config.h" role="src" />
     <file baseinstalldir="/" name="include/grpc/event_engine/event_engine.h" role="src" />
+    <file baseinstalldir="/" name="include/grpc/event_engine/internal/memory_allocator_impl.h" role="src" />
+    <file baseinstalldir="/" name="include/grpc/event_engine/memory_allocator.h" role="src" />
     <file baseinstalldir="/" name="include/grpc/event_engine/port.h" role="src" />
-    <file baseinstalldir="/" name="include/grpc/event_engine/slice_allocator.h" role="src" />
     <file baseinstalldir="/" name="include/grpc/fork.h" role="src" />
     <file baseinstalldir="/" name="include/grpc/grpc.h" role="src" />
     <file baseinstalldir="/" name="include/grpc/grpc_posix.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/priority/priority.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/rls/rls.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/subchannel_list.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/proxy_mapper_registry.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_event_engine.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/retry_throttle.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/server_address.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/server_address.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/service_config.cc" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/service_config.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/service_config_call_data.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/service_config_parser.cc" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/service_config_parser.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/subchannel.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/subchannel.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/subchannel_interface.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/subchannel_pool_interface.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/subchannel_pool_interface.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_idle/client_idle_filter.cc" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/filters/client_idle/idle_filter_state.cc" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/filters/client_idle/idle_filter_state.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/deadline/deadline_filter.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/deadline/deadline_filter.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/fault_injection/fault_injection_filter.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/max_age/max_age_filter.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/message_size/message_size_filter.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/message_size/message_size_filter.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/filters/workarounds/workaround_cronet_compression_filter.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/filters/workarounds/workaround_utils.cc" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/filters/workarounds/workaround_utils.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/service_config/service_config.cc" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/service_config/service_config.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/service_config/service_config_call_data.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/service_config/service_config_parser.cc" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/service_config/service_config_parser.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/alpn/alpn.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/alpn/alpn.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/authority.cc" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/authority.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/chttp2_connector.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/chttp2_connector.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/insecure/channel_create.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/bin_encoder.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/bin_encoder.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/chttp2_plugin.cc" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/chttp2_slice_allocator.cc" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/chttp2_slice_allocator.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/chttp2_transport.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/chttp2_transport.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/context_list.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/http2_settings.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/huffsyms.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/huffsyms.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/incoming_metadata.cc" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/incoming_metadata.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/internal.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/parsing.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/popularity_count.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls.upb.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls.upb.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/udpa/annotations/migrate.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/udpa/annotations/migrate.upb.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/udpa/annotations/security.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/udpa/annotations/status.upb.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/udpa/annotations/versioning.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/udpa/annotations/versioning.upb.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.c" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/validate/validate.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/validate/validate.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/xds/annotations/v3/status.upb.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/xds/annotations/v3/status.upb.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/xds/core/v3/authority.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/xds/core/v3/authority.upb.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/xds/core/v3/collection_entry.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/xds/core/v3/resource_locator.upb.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/xds/core/v3/resource_name.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/xds/core/v3/resource_name.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/xds/data/orca/v3/orca_load_report.upb.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/xds/data/orca/v3/orca_load_report.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/xds/type/v3/typed_struct.upb.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/xds/type/v3/typed_struct.upb.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upbdefs-generated/envoy/annotations/deprecation.upbdefs.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upbdefs-generated/udpa/annotations/status.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upbdefs-generated/udpa/annotations/versioning.upbdefs.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upbdefs-generated/udpa/annotations/versioning.upbdefs.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.c" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upbdefs-generated/validate/validate.upbdefs.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upbdefs-generated/validate/validate.upbdefs.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upbdefs-generated/xds/annotations/v3/status.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upbdefs-generated/xds/annotations/v3/status.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upbdefs-generated/xds/core/v3/authority.upbdefs.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upbdefs-generated/xds/core/v3/authority.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upbdefs-generated/xds/core/v3/collection_entry.upbdefs.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upbdefs-generated/xds/core/v3/resource_locator.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upbdefs-generated/xds/core/v3/resource_name.upbdefs.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upbdefs-generated/xds/core/v3/resource_name.upbdefs.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upbdefs-generated/xds/type/v3/typed_struct.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upbdefs-generated/xds/type/v3/typed_struct.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/xds/certificate_provider_factory.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/xds/certificate_provider_registry.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/xds/certificate_provider_registry.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/xds/xds_certificate_provider.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/xds/xds_certificate_provider.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/xds/xds_channel_args.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/xds/xds_channel_stack_modifier.cc" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/xds/xds_channel_stack_modifier.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/xds/xds_client.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/xds/xds_client.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/xds/xds_client_stats.cc" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gprpp/arena.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gprpp/atomic_utils.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gprpp/bitset.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/gprpp/chunked_vector.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gprpp/construct_destruct.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gprpp/debug_location.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gprpp/dual_ref_counted.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gprpp/status_helper.cc" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gprpp/status_helper.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gprpp/sync.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/gprpp/table.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gprpp/thd.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gprpp/thd_posix.cc" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gprpp/thd_windows.cc" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/timer_heap.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/timer_manager.cc" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/timer_manager.h" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/iomgr/udp_server.cc" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/iomgr/udp_server.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/unix_sockets_posix.cc" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/unix_sockets_posix.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/unix_sockets_posix_noop.cc" role="src" />
     <file baseinstalldir="/" name="src/core/lib/slice/percent_encoding.cc" role="src" />
     <file baseinstalldir="/" name="src/core/lib/slice/percent_encoding.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/slice/slice.cc" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/slice/slice_api.cc" role="src" />
     <file baseinstalldir="/" name="src/core/lib/slice/slice_buffer.cc" role="src" />
     <file baseinstalldir="/" name="src/core/lib/slice/slice_intern.cc" role="src" />
     <file baseinstalldir="/" name="src/core/lib/slice/slice_internal.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/slice/slice_refcount.cc" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/slice/slice_refcount.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/slice/slice_refcount_base.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/slice/slice_split.cc" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/slice/slice_split.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/slice/slice_string_helpers.cc" role="src" />
     <file baseinstalldir="/" name="src/core/lib/slice/slice_string_helpers.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/slice/slice_utils.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/slice/static_slice.cc" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/slice/static_slice.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/surface/api_trace.cc" role="src" />
     <file baseinstalldir="/" name="src/core/lib/surface/api_trace.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/surface/builtins.cc" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/surface/builtins.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/surface/byte_buffer.cc" role="src" />
     <file baseinstalldir="/" name="src/core/lib/surface/byte_buffer_reader.cc" role="src" />
     <file baseinstalldir="/" name="src/core/lib/surface/call.cc" role="src" />
     <file baseinstalldir="/" name="src/core/lib/surface/validate_metadata.cc" role="src" />
     <file baseinstalldir="/" name="src/core/lib/surface/validate_metadata.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/surface/version.cc" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/transport/authority_override.cc" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/transport/authority_override.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/transport/bdp_estimator.cc" role="src" />
     <file baseinstalldir="/" name="src/core/lib/transport/bdp_estimator.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/transport/byte_stream.cc" role="src" />
     <file baseinstalldir="/" name="src/core/lib/transport/metadata.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/transport/metadata_batch.cc" role="src" />
     <file baseinstalldir="/" name="src/core/lib/transport/metadata_batch.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/transport/parsed_metadata.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/transport/pid_controller.cc" role="src" />
     <file baseinstalldir="/" name="src/core/lib/transport/pid_controller.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/transport/static_metadata.cc" role="src" />
index 57deb95..e24eca1 100644 (file)
@@ -14,3 +14,6 @@ chardet==3.0.4
 certifi==2017.4.17
 idna==2.7
 googleapis-common-protos==1.5.5
+gevent==21.1.2
+zope.event==4.5.0
+setuptools==44.1.1
index 4d34c43..1a72c5c 100644 (file)
--- a/setup.py
+++ b/setup.py
@@ -536,6 +536,7 @@ setuptools.setup(
     packages=list(PACKAGES),
     package_dir=PACKAGE_DIRECTORIES,
     package_data=PACKAGE_DATA,
+    python_requires='>=3.6',
     install_requires=INSTALL_REQUIRES,
     extras_require=EXTRAS_REQUIRES,
     setup_requires=SETUP_REQUIRES,
index 296724a..2d5e5d0 100644 (file)
@@ -1,4 +1,4 @@
-// generated by generate_boringssl_prefix_header.sh on BoringSSL commit: 340faef0ad19283e985ce7fff0dec73ba4022c8d
+// generated by generate_boringssl_prefix_header.sh on BoringSSL commit: 95b3ed1b01f2ef1d72fed290ed79fe1b0e7dafc0
 
 // Copyright (c) 2018, Google Inc.
 //
 #define ASN1_SET_ANY_it BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ASN1_SET_ANY_it)
 #define ASN1_STRING_TABLE_add BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ASN1_STRING_TABLE_add)
 #define ASN1_STRING_TABLE_cleanup BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ASN1_STRING_TABLE_cleanup)
-#define ASN1_STRING_TABLE_get BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ASN1_STRING_TABLE_get)
 #define ASN1_STRING_cmp BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ASN1_STRING_cmp)
 #define ASN1_STRING_copy BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ASN1_STRING_copy)
 #define ASN1_STRING_data BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ASN1_STRING_data)
 #define asn1_generalizedtime_to_tm BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, asn1_generalizedtime_to_tm)
 #define asn1_get_choice_selector BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, asn1_get_choice_selector)
 #define asn1_get_field_ptr BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, asn1_get_field_ptr)
+#define asn1_get_string_table_for_testing BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, asn1_get_string_table_for_testing)
 #define asn1_is_printable BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, asn1_is_printable)
 #define asn1_item_combine_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, asn1_item_combine_free)
 #define asn1_refcount_dec_and_test_zero BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, asn1_refcount_dec_and_test_zero)
index 964339e..235916a 100644 (file)
@@ -19,8 +19,8 @@
 #include "src/core/ext/filters/client_channel/backend_metric.h"
 
 #include "absl/strings/string_view.h"
-#include "udpa/data/orca/v1/orca_load_report.upb.h"
 #include "upb/upb.hpp"
+#include "xds/data/orca/v3/orca_load_report.upb.h"
 
 namespace grpc_core {
 
@@ -28,8 +28,8 @@ namespace {
 
 template <typename EntryType>
 std::map<absl::string_view, double> ParseMap(
-    udpa_data_orca_v1_OrcaLoadReport* msg,
-    const EntryType* (*entry_func)(const udpa_data_orca_v1_OrcaLoadReport*,
+    xds_data_orca_v3_OrcaLoadReport* msg,
+    const EntryType* (*entry_func)(const xds_data_orca_v3_OrcaLoadReport*,
                                    size_t*),
     upb_strview (*key_func)(const EntryType*),
     double (*value_func)(const EntryType*), Arena* arena) {
@@ -51,30 +51,29 @@ std::map<absl::string_view, double> ParseMap(
 const LoadBalancingPolicy::BackendMetricData* ParseBackendMetricData(
     const grpc_slice& serialized_load_report, Arena* arena) {
   upb::Arena upb_arena;
-  udpa_data_orca_v1_OrcaLoadReport* msg =
-      udpa_data_orca_v1_OrcaLoadReport_parse(
-          reinterpret_cast<const char*>(
-              GRPC_SLICE_START_PTR(serialized_load_report)),
-          GRPC_SLICE_LENGTH(serialized_load_report), upb_arena.ptr());
+  xds_data_orca_v3_OrcaLoadReport* msg = xds_data_orca_v3_OrcaLoadReport_parse(
+      reinterpret_cast<const char*>(
+          GRPC_SLICE_START_PTR(serialized_load_report)),
+      GRPC_SLICE_LENGTH(serialized_load_report), upb_arena.ptr());
   if (msg == nullptr) return nullptr;
   LoadBalancingPolicy::BackendMetricData* backend_metric_data =
       arena->New<LoadBalancingPolicy::BackendMetricData>();
   backend_metric_data->cpu_utilization =
-      udpa_data_orca_v1_OrcaLoadReport_cpu_utilization(msg);
+      xds_data_orca_v3_OrcaLoadReport_cpu_utilization(msg);
   backend_metric_data->mem_utilization =
-      udpa_data_orca_v1_OrcaLoadReport_mem_utilization(msg);
+      xds_data_orca_v3_OrcaLoadReport_mem_utilization(msg);
   backend_metric_data->requests_per_second =
-      udpa_data_orca_v1_OrcaLoadReport_rps(msg);
+      xds_data_orca_v3_OrcaLoadReport_rps(msg);
   backend_metric_data->request_cost =
-      ParseMap<udpa_data_orca_v1_OrcaLoadReport_RequestCostEntry>(
-          msg, udpa_data_orca_v1_OrcaLoadReport_request_cost_next,
-          udpa_data_orca_v1_OrcaLoadReport_RequestCostEntry_key,
-          udpa_data_orca_v1_OrcaLoadReport_RequestCostEntry_value, arena);
+      ParseMap<xds_data_orca_v3_OrcaLoadReport_RequestCostEntry>(
+          msg, xds_data_orca_v3_OrcaLoadReport_request_cost_next,
+          xds_data_orca_v3_OrcaLoadReport_RequestCostEntry_key,
+          xds_data_orca_v3_OrcaLoadReport_RequestCostEntry_value, arena);
   backend_metric_data->utilization =
-      ParseMap<udpa_data_orca_v1_OrcaLoadReport_UtilizationEntry>(
-          msg, udpa_data_orca_v1_OrcaLoadReport_utilization_next,
-          udpa_data_orca_v1_OrcaLoadReport_UtilizationEntry_key,
-          udpa_data_orca_v1_OrcaLoadReport_UtilizationEntry_value, arena);
+      ParseMap<xds_data_orca_v3_OrcaLoadReport_UtilizationEntry>(
+          msg, xds_data_orca_v3_OrcaLoadReport_utilization_next,
+          xds_data_orca_v3_OrcaLoadReport_UtilizationEntry_key,
+          xds_data_orca_v3_OrcaLoadReport_UtilizationEntry_value, arena);
   return backend_metric_data;
 }
 
index ad7f892..1332e87 100644 (file)
@@ -28,6 +28,7 @@
 #include "src/core/ext/filters/client_channel/client_channel.h"
 #include "src/core/lib/gpr/string.h"
 #include "src/core/lib/gprpp/global_config.h"
+#include "src/core/lib/gprpp/memory.h"
 #include "src/core/lib/iomgr/error.h"
 #include "src/core/lib/iomgr/iomgr.h"
 #include "src/core/lib/iomgr/pollset.h"
@@ -138,7 +139,7 @@ static void run_poller(void* arg, grpc_error_handle error) {
 
 static void g_poller_init_locked() {
   if (g_poller == nullptr) {
-    g_poller = static_cast<backup_poller*>(gpr_zalloc(sizeof(backup_poller)));
+    g_poller = grpc_core::Zalloc<backup_poller>();
     g_poller->pollset =
         static_cast<grpc_pollset*>(gpr_zalloc(grpc_pollset_size()));
     g_poller->shutting_down = false;
index a656294..a75b974 100644 (file)
 #include "src/core/lib/surface/api_trace.h"
 #include "src/core/lib/surface/channel.h"
 #include "src/core/lib/surface/completion_queue.h"
+#include "src/core/lib/surface/lame_client.h"
+
+namespace {
+
+bool IsLameChannel(grpc_channel* channel) {
+  grpc_channel_element* elem =
+      grpc_channel_stack_last_element(grpc_channel_get_channel_stack(channel));
+  return elem->filter == &grpc_lame_filter;
+}
+
+}  // namespace
 
 grpc_connectivity_state grpc_channel_check_connectivity_state(
     grpc_channel* channel, int try_to_connect) {
@@ -35,6 +46,7 @@ grpc_connectivity_state grpc_channel_check_connectivity_state(
   grpc_core::ClientChannel* client_channel =
       grpc_core::ClientChannel::GetFromChannel(channel);
   if (GPR_UNLIKELY(client_channel == nullptr)) {
+    if (IsLameChannel(channel)) return GRPC_CHANNEL_TRANSIENT_FAILURE;
     gpr_log(GPR_ERROR,
             "grpc_channel_check_connectivity_state called on something that is "
             "not a client channel");
@@ -47,9 +59,11 @@ int grpc_channel_num_external_connectivity_watchers(grpc_channel* channel) {
   grpc_core::ClientChannel* client_channel =
       grpc_core::ClientChannel::GetFromChannel(channel);
   if (client_channel == nullptr) {
-    gpr_log(GPR_ERROR,
-            "grpc_channel_num_external_connectivity_watchers called on "
-            "something that is not a client channel");
+    if (!IsLameChannel(channel)) {
+      gpr_log(GPR_ERROR,
+              "grpc_channel_num_external_connectivity_watchers called on "
+              "something that is not a client channel");
+    }
     return 0;
   }
   return client_channel->NumExternalConnectivityWatchers();
@@ -62,7 +76,7 @@ int grpc_channel_support_connectivity_watcher(grpc_channel* channel) {
 namespace grpc_core {
 namespace {
 
-class StateWatcher {
+class StateWatcher : public DualRefCounted<StateWatcher> {
  public:
   StateWatcher(grpc_channel* channel, grpc_completion_queue* cq, void* tag,
                grpc_connectivity_state last_observed_state,
@@ -72,16 +86,35 @@ class StateWatcher {
     GRPC_CHANNEL_INTERNAL_REF(channel, "watch_channel_connectivity");
     GRPC_CLOSURE_INIT(&on_complete_, WatchComplete, this, nullptr);
     GRPC_CLOSURE_INIT(&on_timeout_, TimeoutComplete, this, nullptr);
+    ClientChannel* client_channel = ClientChannel::GetFromChannel(channel);
+    if (client_channel == nullptr) {
+      // If the target URI used to create the channel was invalid, channel
+      // stack initialization failed, and that caused us to create a lame
+      // channel.  In that case, connectivity state will never change (it
+      // will always be TRANSIENT_FAILURE), so we don't actually start a
+      // watch, but we are hiding that fact from the application.
+      if (IsLameChannel(channel)) {
+        // Ref from object creation is held by timer callback.
+        StartTimer(grpc_timespec_to_millis_round_up(deadline));
+        return;
+      }
+      gpr_log(GPR_ERROR,
+              "grpc_channel_watch_connectivity_state called on "
+              "something that is not a client channel");
+      GPR_ASSERT(false);
+    }
+    // Take an addition ref, so we have two (the first one is from the
+    // creation of this object).  One will be held by the timer callback,
+    // the other by the watcher callback.
+    Ref().release();
     auto* watcher_timer_init_state = new WatcherTimerInitState(
         this, grpc_timespec_to_millis_round_up(deadline));
-    ClientChannel* client_channel = ClientChannel::GetFromChannel(channel);
-    GPR_ASSERT(client_channel != nullptr);
     client_channel->AddExternalConnectivityWatcher(
         grpc_polling_entity_create_from_pollset(grpc_cq_pollset(cq)), &state_,
         &on_complete_, watcher_timer_init_state->closure());
   }
 
-  ~StateWatcher() {
+  ~StateWatcher() override {
     GRPC_CHANNEL_INTERNAL_UNREF(channel_, "watch_channel_connectivity");
   }
 
@@ -100,8 +133,7 @@ class StateWatcher {
    private:
     static void WatcherTimerInit(void* arg, grpc_error_handle /*error*/) {
       auto* self = static_cast<WatcherTimerInitState*>(arg);
-      grpc_timer_init(&self->state_watcher_->timer_, self->deadline_,
-                      &self->state_watcher_->on_timeout_);
+      self->state_watcher_->StartTimer(self->deadline_);
       delete self;
     }
 
@@ -110,94 +142,46 @@ class StateWatcher {
     grpc_closure closure_;
   };
 
-  enum CallbackPhase { kWaiting, kReadyToCallBack, kCallingBackAndFinished };
+  void StartTimer(grpc_millis deadline) {
+    grpc_timer_init(&timer_, deadline, &on_timeout_);
+  }
 
-  // Called when the completion is returned to the CQ.
-  static void FinishedCompletion(void* arg, grpc_cq_completion* /*ignored*/) {
+  static void WatchComplete(void* arg, grpc_error_handle error) {
     auto* self = static_cast<StateWatcher*>(arg);
-    bool should_delete = false;
-    {
-      MutexLock lock(&self->mu_);
-      switch (self->phase_) {
-        case kWaiting:
-        case kReadyToCallBack:
-          GPR_UNREACHABLE_CODE(return );
-        case kCallingBackAndFinished:
-          should_delete = true;
-      }
+    if (GRPC_TRACE_FLAG_ENABLED(grpc_trace_operation_failures)) {
+      GRPC_LOG_IF_ERROR("watch_completion_error", GRPC_ERROR_REF(error));
     }
-    if (should_delete) delete self;
+    grpc_timer_cancel(&self->timer_);
+    self->Unref();
   }
 
-  void PartlyDone(bool due_to_completion, grpc_error_handle error) {
-    bool end_op = false;
-    void* end_op_tag = nullptr;
-    grpc_error_handle end_op_error = GRPC_ERROR_NONE;
-    grpc_completion_queue* end_op_cq = nullptr;
-    grpc_cq_completion* end_op_completion_storage = nullptr;
-    if (due_to_completion) {
-      grpc_timer_cancel(&timer_);
-    } else {
-      grpc_core::ClientChannel* client_channel =
-          grpc_core::ClientChannel::GetFromChannel(channel_);
-      GPR_ASSERT(client_channel != nullptr);
-      client_channel->CancelExternalConnectivityWatcher(&on_complete_);
-    }
-    {
-      MutexLock lock(&mu_);
-      if (due_to_completion) {
-        if (GRPC_TRACE_FLAG_ENABLED(grpc_trace_operation_failures)) {
-          GRPC_LOG_IF_ERROR("watch_completion_error", GRPC_ERROR_REF(error));
-        }
-        GRPC_ERROR_UNREF(error);
-        error = GRPC_ERROR_NONE;
-      } else {
-        if (error == GRPC_ERROR_NONE) {
-          error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
-              "Timed out waiting for connection state change");
-        } else if (error == GRPC_ERROR_CANCELLED) {
-          error = GRPC_ERROR_NONE;
-        }
-      }
-      switch (phase_) {
-        case kWaiting:
-          GRPC_ERROR_REF(error);
-          error_ = error;
-          phase_ = kReadyToCallBack;
-          break;
-        case kReadyToCallBack:
-          if (error != GRPC_ERROR_NONE) {
-            GPR_ASSERT(!due_to_completion);
-            GRPC_ERROR_UNREF(error_);
-            GRPC_ERROR_REF(error);
-            error_ = error;
-          }
-          phase_ = kCallingBackAndFinished;
-          end_op = true;
-          end_op_cq = cq_;
-          end_op_tag = tag_;
-          end_op_error = error_;
-          end_op_completion_storage = &completion_storage_;
-          break;
-        case kCallingBackAndFinished:
-          GPR_UNREACHABLE_CODE(return );
-      }
-    }
-    if (end_op) {
-      grpc_cq_end_op(end_op_cq, end_op_tag, end_op_error, FinishedCompletion,
-                     this, end_op_completion_storage);
+  static void TimeoutComplete(void* arg, grpc_error_handle error) {
+    auto* self = static_cast<StateWatcher*>(arg);
+    self->timer_fired_ = error == GRPC_ERROR_NONE;
+    // If this is a client channel (not a lame channel), cancel the watch.
+    ClientChannel* client_channel =
+        ClientChannel::GetFromChannel(self->channel_);
+    if (client_channel != nullptr) {
+      client_channel->CancelExternalConnectivityWatcher(&self->on_complete_);
     }
-    GRPC_ERROR_UNREF(error);
+    self->Unref();
   }
 
-  static void WatchComplete(void* arg, grpc_error_handle error) {
-    auto* self = static_cast<StateWatcher*>(arg);
-    self->PartlyDone(/*due_to_completion=*/true, GRPC_ERROR_REF(error));
+  // Invoked when both strong refs are released.
+  void Orphan() override {
+    WeakRef().release();  // Take a weak ref until completion is finished.
+    grpc_error_handle error =
+        timer_fired_ ? GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+                           "Timed out waiting for connection state change")
+                     : GRPC_ERROR_NONE;
+    grpc_cq_end_op(cq_, tag_, error, FinishedCompletion, this,
+                   &completion_storage_);
   }
 
-  static void TimeoutComplete(void* arg, grpc_error_handle error) {
+  // Called when the completion is returned to the CQ.
+  static void FinishedCompletion(void* arg, grpc_cq_completion* /*ignored*/) {
     auto* self = static_cast<StateWatcher*>(arg);
-    self->PartlyDone(/*due_to_completion=*/false, GRPC_ERROR_REF(error));
+    self->WeakUnref();
   }
 
   grpc_channel* channel_;
@@ -212,9 +196,7 @@ class StateWatcher {
   grpc_timer timer_;
   grpc_closure on_timeout_;
 
-  Mutex mu_;
-  CallbackPhase phase_ ABSL_GUARDED_BY(mu_) = kWaiting;
-  grpc_error_handle error_ ABSL_GUARDED_BY(mu_) = GRPC_ERROR_NONE;
+  bool timer_fired_ = false;
 };
 
 }  // namespace
index da04ec0..94c2514 100644 (file)
 #include "src/core/ext/filters/client_channel/resolver_registry.h"
 #include "src/core/ext/filters/client_channel/resolver_result_parsing.h"
 #include "src/core/ext/filters/client_channel/retry_filter.h"
-#include "src/core/ext/filters/client_channel/service_config.h"
-#include "src/core/ext/filters/client_channel/service_config_call_data.h"
 #include "src/core/ext/filters/client_channel/subchannel.h"
 #include "src/core/ext/filters/deadline/deadline_filter.h"
+#include "src/core/ext/service_config/service_config.h"
+#include "src/core/ext/service_config/service_config_call_data.h"
 #include "src/core/lib/backoff/backoff.h"
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/channel/connected_channel.h"
@@ -79,6 +79,9 @@
 // Client channel filter
 //
 
+#define GRPC_ARG_HEALTH_CHECK_SERVICE_NAME \
+  "grpc.internal.health_check_service_name"
+
 namespace grpc_core {
 
 using internal::ClientChannelGlobalParsedConfig;
@@ -254,7 +257,7 @@ namespace {
 // Channel arg pointer vtable for GRPC_ARG_CLIENT_CHANNEL.
 void* ClientChannelArgCopy(void* p) { return p; }
 void ClientChannelArgDestroy(void* /*p*/) {}
-int ClientChannelArgCmp(void* p, void* q) { return GPR_ICMP(p, q); }
+int ClientChannelArgCmp(void* p, void* q) { return QsortCompare(p, q); }
 const grpc_arg_pointer_vtable kClientChannelArgPointerVtable = {
     ClientChannelArgCopy, ClientChannelArgDestroy, ClientChannelArgCmp};
 
@@ -268,7 +271,7 @@ void ServiceConfigObjArgDestroy(void* p) {
   auto* service_config = static_cast<ServiceConfig*>(p);
   service_config->Unref();
 }
-int ServiceConfigObjArgCmp(void* p, void* q) { return GPR_ICMP(p, q); }
+int ServiceConfigObjArgCmp(void* p, void* q) { return QsortCompare(p, q); }
 const grpc_arg_pointer_vtable kServiceConfigObjArgPointerVtable = {
     ServiceConfigObjArgCopy, ServiceConfigObjArgDestroy,
     ServiceConfigObjArgCmp};
@@ -346,8 +349,9 @@ class DynamicTerminationFilter::CallData {
                                    calld->call_context_, calld->path_,
                                    /*start_time=*/0,     calld->deadline_,
                                    calld->arena_,        calld->call_combiner_};
-    auto* service_config_call_data = static_cast<ServiceConfigCallData*>(
-        calld->call_context_[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].value);
+    auto* service_config_call_data =
+        static_cast<ClientChannelServiceConfigCallData*>(
+            calld->call_context_[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].value);
     calld->lb_call_ = client_channel->CreateLoadBalancedCall(
         args, pollent, nullptr,
         service_config_call_data->call_dispatch_controller(),
@@ -456,15 +460,17 @@ class ClientChannel::SubchannelWrapper : public SubchannelInterface {
               chand, this, subchannel_.get());
     }
     GRPC_CHANNEL_STACK_REF(chand_->owning_stack_, "SubchannelWrapper");
-    auto* subchannel_node = subchannel_->channelz_node();
-    if (subchannel_node != nullptr) {
-      auto it = chand_->subchannel_refcount_map_.find(subchannel_.get());
-      if (it == chand_->subchannel_refcount_map_.end()) {
-        chand_->channelz_node_->AddChildSubchannel(subchannel_node->uuid());
-        it = chand_->subchannel_refcount_map_.emplace(subchannel_.get(), 0)
-                 .first;
+    if (chand_->channelz_node_ != nullptr) {
+      auto* subchannel_node = subchannel_->channelz_node();
+      if (subchannel_node != nullptr) {
+        auto it = chand_->subchannel_refcount_map_.find(subchannel_.get());
+        if (it == chand_->subchannel_refcount_map_.end()) {
+          chand_->channelz_node_->AddChildSubchannel(subchannel_node->uuid());
+          it = chand_->subchannel_refcount_map_.emplace(subchannel_.get(), 0)
+                   .first;
+        }
+        ++it->second;
       }
-      ++it->second;
     }
     chand_->subchannel_wrappers_.insert(this);
   }
@@ -476,32 +482,30 @@ class ClientChannel::SubchannelWrapper : public SubchannelInterface {
               chand_, this, subchannel_.get());
     }
     chand_->subchannel_wrappers_.erase(this);
-    auto* subchannel_node = subchannel_->channelz_node();
-    if (subchannel_node != nullptr) {
-      auto it = chand_->subchannel_refcount_map_.find(subchannel_.get());
-      GPR_ASSERT(it != chand_->subchannel_refcount_map_.end());
-      --it->second;
-      if (it->second == 0) {
-        chand_->channelz_node_->RemoveChildSubchannel(subchannel_node->uuid());
-        chand_->subchannel_refcount_map_.erase(it);
+    if (chand_->channelz_node_ != nullptr) {
+      auto* subchannel_node = subchannel_->channelz_node();
+      if (subchannel_node != nullptr) {
+        auto it = chand_->subchannel_refcount_map_.find(subchannel_.get());
+        GPR_ASSERT(it != chand_->subchannel_refcount_map_.end());
+        --it->second;
+        if (it->second == 0) {
+          chand_->channelz_node_->RemoveChildSubchannel(
+              subchannel_node->uuid());
+          chand_->subchannel_refcount_map_.erase(it);
+        }
       }
     }
     GRPC_CHANNEL_STACK_UNREF(chand_->owning_stack_, "SubchannelWrapper");
   }
 
-  grpc_connectivity_state CheckConnectivityState() override
-      ABSL_EXCLUSIVE_LOCKS_REQUIRED(chand_->work_serializer_) {
-    RefCountedPtr<ConnectedSubchannel> connected_subchannel;
-    grpc_connectivity_state connectivity_state =
-        subchannel_->CheckConnectivityState(health_check_service_name_,
-                                            &connected_subchannel);
-    MaybeUpdateConnectedSubchannel(std::move(connected_subchannel));
-    return connectivity_state;
+  grpc_connectivity_state CheckConnectivityState() override {
+    return subchannel_->CheckConnectivityState(health_check_service_name_);
   }
 
   void WatchConnectivityState(
       grpc_connectivity_state initial_state,
-      std::unique_ptr<ConnectivityStateWatcherInterface> watcher) override {
+      std::unique_ptr<ConnectivityStateWatcherInterface> watcher) override
+      ABSL_EXCLUSIVE_LOCKS_REQUIRED(chand_->work_serializer_) {
     auto& watcher_wrapper = watcher_map_[watcher.get()];
     GPR_ASSERT(watcher_wrapper == nullptr);
     watcher_wrapper = new WatcherWrapper(std::move(watcher),
@@ -513,8 +517,8 @@ class ClientChannel::SubchannelWrapper : public SubchannelInterface {
             watcher_wrapper));
   }
 
-  void CancelConnectivityStateWatch(
-      ConnectivityStateWatcherInterface* watcher) override {
+  void CancelConnectivityStateWatch(ConnectivityStateWatcherInterface* watcher)
+      override ABSL_EXCLUSIVE_LOCKS_REQUIRED(chand_->work_serializer_) {
     auto it = watcher_map_.find(watcher);
     GPR_ASSERT(it != watcher_map_.end());
     subchannel_->CancelConnectivityStateWatch(health_check_service_name_,
@@ -522,6 +526,10 @@ class ClientChannel::SubchannelWrapper : public SubchannelInterface {
     watcher_map_.erase(it);
   }
 
+  RefCountedPtr<ConnectedSubchannel> connected_subchannel() const {
+    return subchannel_->connected_subchannel();
+  }
+
   void AttemptToConnect() override { subchannel_->AttemptToConnect(); }
 
   void ResetBackoff() override { subchannel_->ResetBackoff(); }
@@ -534,57 +542,6 @@ class ClientChannel::SubchannelWrapper : public SubchannelInterface {
     subchannel_->ThrottleKeepaliveTime(new_keepalive_time);
   }
 
-  void UpdateHealthCheckServiceName(
-      absl::optional<std::string> health_check_service_name) {
-    if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
-      gpr_log(GPR_INFO,
-              "chand=%p: subchannel wrapper %p: updating health check service "
-              "name from \"%s\" to \"%s\"",
-              chand_, this, health_check_service_name_->c_str(),
-              health_check_service_name->c_str());
-    }
-    for (auto& p : watcher_map_) {
-      WatcherWrapper*& watcher_wrapper = p.second;
-      // Cancel the current watcher and create a new one using the new
-      // health check service name.
-      // TODO(roth): If there is not already an existing health watch
-      // call for the new name, then the watcher will initially report
-      // state CONNECTING.  If the LB policy is currently reporting
-      // state READY, this may cause it to switch to CONNECTING before
-      // switching back to READY.  This could cause a small delay for
-      // RPCs being started on the channel.  If/when this becomes a
-      // problem, we may be able to handle it by waiting for the new
-      // watcher to report READY before we use it to replace the old one.
-      WatcherWrapper* replacement = watcher_wrapper->MakeReplacement();
-      subchannel_->CancelConnectivityStateWatch(health_check_service_name_,
-                                                watcher_wrapper);
-      watcher_wrapper = replacement;
-      subchannel_->WatchConnectivityState(
-          replacement->last_seen_state(), health_check_service_name,
-          RefCountedPtr<Subchannel::ConnectivityStateWatcherInterface>(
-              replacement));
-    }
-    // Save the new health check service name.
-    health_check_service_name_ = std::move(health_check_service_name);
-  }
-
-  // Caller must be holding the control-plane work_serializer.
-  ConnectedSubchannel* connected_subchannel() const
-      ABSL_EXCLUSIVE_LOCKS_REQUIRED(&ClientChannel::work_serializer_) {
-    return connected_subchannel_.get();
-  }
-
-  // Caller must be holding the data-plane mutex.
-  ConnectedSubchannel* connected_subchannel_in_data_plane() const
-      ABSL_EXCLUSIVE_LOCKS_REQUIRED(&ClientChannel::data_plane_mu_) {
-    return connected_subchannel_in_data_plane_.get();
-  }
-  void set_connected_subchannel_in_data_plane(
-      RefCountedPtr<ConnectedSubchannel> connected_subchannel)
-      ABSL_EXCLUSIVE_LOCKS_REQUIRED(&ClientChannel::data_plane_mu_) {
-    connected_subchannel_in_data_plane_ = std::move(connected_subchannel);
-  }
-
  private:
   // Subchannel and SubchannelInterface have different interfaces for
   // their respective ConnectivityStateWatcherInterface classes.
@@ -696,8 +653,6 @@ class ClientChannel::SubchannelWrapper : public SubchannelInterface {
       // since this callback was scheduled.
       if (watcher_ != nullptr) {
         last_seen_state_ = state_change.state;
-        parent_->MaybeUpdateConnectedSubchannel(
-            std::move(state_change.connected_subchannel));
         watcher_->OnConnectivityStateChange(state_change.state);
       }
     }
@@ -709,28 +664,6 @@ class ClientChannel::SubchannelWrapper : public SubchannelInterface {
     WatcherWrapper* replacement_ = nullptr;
   };
 
-  void MaybeUpdateConnectedSubchannel(
-      RefCountedPtr<ConnectedSubchannel> connected_subchannel)
-      ABSL_EXCLUSIVE_LOCKS_REQUIRED(&ClientChannel::work_serializer_) {
-    // Update the connected subchannel only if the channel is not shutting
-    // down.  This is because once the channel is shutting down, we
-    // ignore picker updates from the LB policy, which means that
-    // UpdateStateAndPickerLocked() will never process the entries
-    // in chand_->pending_subchannel_updates_.  So we don't want to add
-    // entries there that will never be processed, since that would
-    // leave dangling refs to the channel and prevent its destruction.
-    grpc_error_handle disconnect_error = chand_->disconnect_error();
-    if (disconnect_error != GRPC_ERROR_NONE) return;
-    // Not shutting down, so do the update.
-    if (connected_subchannel_ != connected_subchannel) {
-      connected_subchannel_ = std::move(connected_subchannel);
-      // Record the new connected subchannel so that it can be updated
-      // in the data plane mutex the next time the picker is updated.
-      chand_->pending_subchannel_updates_[Ref(
-          DEBUG_LOCATION, "ConnectedSubchannelUpdate")] = connected_subchannel_;
-    }
-  }
-
   ClientChannel* chand_;
   RefCountedPtr<Subchannel> subchannel_;
   absl::optional<std::string> health_check_service_name_;
@@ -739,13 +672,8 @@ class ClientChannel::SubchannelWrapper : public SubchannelInterface {
   // subchannel.  This is needed so that when the LB policy calls
   // CancelConnectivityStateWatch() with its watcher, we know the
   // corresponding WrapperWatcher to cancel on the underlying subchannel.
-  std::map<ConnectivityStateWatcherInterface*, WatcherWrapper*> watcher_map_;
-  // To be accessed only in the control plane work_serializer.
-  RefCountedPtr<ConnectedSubchannel> connected_subchannel_
+  std::map<ConnectivityStateWatcherInterface*, WatcherWrapper*> watcher_map_
       ABSL_GUARDED_BY(&ClientChannel::work_serializer_);
-  // To be accessed only in the data plane mutex.
-  RefCountedPtr<ConnectedSubchannel> connected_subchannel_in_data_plane_
-      ABSL_GUARDED_BY(&ClientChannel::data_plane_mu_);
 };
 
 //
@@ -942,35 +870,62 @@ class ClientChannel::ClientChannelControlHelper
       ABSL_EXCLUSIVE_LOCKS_REQUIRED(chand_->work_serializer_) {
     if (chand_->resolver_ == nullptr) return nullptr;  // Shutting down.
     // Determine health check service name.
-    bool inhibit_health_checking = grpc_channel_args_find_bool(
-        &args, GRPC_ARG_INHIBIT_HEALTH_CHECKING, false);
     absl::optional<std::string> health_check_service_name;
-    if (!inhibit_health_checking) {
-      health_check_service_name = chand_->health_check_service_name_;
+    const char* health_check_service_name_arg = grpc_channel_args_find_string(
+        &args, GRPC_ARG_HEALTH_CHECK_SERVICE_NAME);
+    if (health_check_service_name_arg != nullptr) {
+      bool inhibit_health_checking = grpc_channel_args_find_bool(
+          &args, GRPC_ARG_INHIBIT_HEALTH_CHECKING, false);
+      if (!inhibit_health_checking) {
+        health_check_service_name = health_check_service_name_arg;
+      }
     }
+    // Construct channel args for subchannel.
     // Remove channel args that should not affect subchannel uniqueness.
-    static const char* args_to_remove[] = {
+    absl::InlinedVector<const char*, 4> args_to_remove = {
+        GRPC_ARG_HEALTH_CHECK_SERVICE_NAME,
         GRPC_ARG_INHIBIT_HEALTH_CHECKING,
         GRPC_ARG_CHANNELZ_CHANNEL_NODE,
     };
     // Add channel args needed for the subchannel.
-    absl::InlinedVector<grpc_arg, 3> args_to_add = {
-        Subchannel::CreateSubchannelAddressArg(&address.address()),
+    absl::InlinedVector<grpc_arg, 2> args_to_add = {
         SubchannelPoolInterface::CreateChannelArg(
             chand_->subchannel_pool_.get()),
     };
+    // Check if default authority arg is already set.
+    const char* default_authority =
+        grpc_channel_args_find_string(&args, GRPC_ARG_DEFAULT_AUTHORITY);
+    // Add args from subchannel address.
     if (address.args() != nullptr) {
       for (size_t j = 0; j < address.args()->num_args; ++j) {
-        args_to_add.emplace_back(address.args()->args[j]);
+        grpc_arg& arg = address.args()->args[j];
+        if (strcmp(arg.key, GRPC_ARG_DEFAULT_AUTHORITY) == 0) {
+          // Don't add default authority arg from subchannel address if
+          // it's already set at the channel level -- the value from the
+          // application should take precedence over what is set by the
+          // resolver.
+          if (default_authority != nullptr) continue;
+          default_authority = arg.value.string;
+        }
+        args_to_add.emplace_back(arg);
       }
     }
+    // If we haven't already set the default authority arg, add it from
+    // the channel.
+    if (default_authority == nullptr) {
+      // Remove it, just in case it's actually present but is the wrong type.
+      args_to_remove.push_back(GRPC_ARG_DEFAULT_AUTHORITY);
+      args_to_add.push_back(grpc_channel_arg_string_create(
+          const_cast<char*>(GRPC_ARG_DEFAULT_AUTHORITY),
+          const_cast<char*>(chand_->default_authority_.c_str())));
+    }
     grpc_channel_args* new_args = grpc_channel_args_copy_and_add_and_remove(
-        &args, args_to_remove, GPR_ARRAY_SIZE(args_to_remove),
-        args_to_add.data(), args_to_add.size());
-    gpr_free(args_to_add[0].value.string);
+        &args, args_to_remove.data(), args_to_remove.size(), args_to_add.data(),
+        args_to_add.size());
     // Create subchannel.
     RefCountedPtr<Subchannel> subchannel =
-        chand_->client_channel_factory_->CreateSubchannel(new_args);
+        chand_->client_channel_factory_->CreateSubchannel(address.address(),
+                                                          new_args);
     grpc_channel_args_destroy(new_args);
     if (subchannel == nullptr) return nullptr;
     // Make sure the subchannel has updated keepalive time.
@@ -985,9 +940,8 @@ class ClientChannel::ClientChannelControlHelper
       std::unique_ptr<LoadBalancingPolicy::SubchannelPicker> picker) override
       ABSL_EXCLUSIVE_LOCKS_REQUIRED(chand_->work_serializer_) {
     if (chand_->resolver_ == nullptr) return;  // Shutting down.
-    grpc_error_handle disconnect_error = chand_->disconnect_error();
     if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
-      const char* extra = disconnect_error == GRPC_ERROR_NONE
+      const char* extra = chand_->disconnect_error_ == GRPC_ERROR_NONE
                               ? ""
                               : " (ignoring -- channel shutting down)";
       gpr_log(GPR_INFO, "chand=%p: update: state=%s status=(%s) picker=%p%s",
@@ -995,7 +949,7 @@ class ClientChannel::ClientChannelControlHelper
               picker.get(), extra);
     }
     // Do update only if not shutting down.
-    if (disconnect_error == GRPC_ERROR_NONE) {
+    if (chand_->disconnect_error_ == GRPC_ERROR_NONE) {
       chand_->UpdateStateAndPickerLocked(state, status, "helper",
                                          std::move(picker));
     }
@@ -1010,6 +964,10 @@ class ClientChannel::ClientChannelControlHelper
     chand_->resolver_->RequestReresolutionLocked();
   }
 
+  absl::string_view GetAuthority() override {
+    return chand_->default_authority_;
+  }
+
   void AddTraceEvent(TraceSeverity severity, absl::string_view message) override
       ABSL_EXCLUSIVE_LOCKS_REQUIRED(chand_->work_serializer_) {
     if (chand_->resolver_ == nullptr) return;  // Shutting down.
@@ -1086,8 +1044,7 @@ ClientChannel::ClientChannel(grpc_channel_element_args* args,
       interested_parties_(grpc_pollset_set_create()),
       work_serializer_(std::make_shared<WorkSerializer>()),
       state_tracker_("client_channel", GRPC_CHANNEL_IDLE),
-      subchannel_pool_(GetSubchannelPool(args->channel_args)),
-      disconnect_error_(GRPC_ERROR_NONE) {
+      subchannel_pool_(GetSubchannelPool(args->channel_args)) {
   if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
     gpr_log(GPR_INFO, "chand=%p: creating client_channel for channel stack %p",
             this, owning_stack_);
@@ -1100,15 +1057,6 @@ ClientChannel::ClientChannel(grpc_channel_element_args* args,
         "Missing client channel factory in args for client channel filter");
     return;
   }
-  // Get server name to resolve, using proxy mapper if needed.
-  const char* server_uri =
-      grpc_channel_args_find_string(args->channel_args, GRPC_ARG_SERVER_URI);
-  if (server_uri == nullptr) {
-    *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
-        "server URI channel arg missing or wrong type in client channel "
-        "filter");
-    return;
-  }
   // Get default service config.  If none is specified via the client API,
   // we use an empty config.
   const char* service_config_json = grpc_channel_args_find_string(
@@ -1121,30 +1069,50 @@ ClientChannel::ClientChannel(grpc_channel_element_args* args,
     default_service_config_.reset();
     return;
   }
-  absl::StatusOr<URI> uri = URI::Parse(server_uri);
-  if (uri.ok() && !uri->path().empty()) {
-    server_name_ = std::string(absl::StripPrefix(uri->path(), "/"));
+  // Get URI to resolve, using proxy mapper if needed.
+  const char* server_uri =
+      grpc_channel_args_find_string(args->channel_args, GRPC_ARG_SERVER_URI);
+  if (server_uri == nullptr) {
+    *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+        "target URI channel arg missing or wrong type in client channel "
+        "filter");
+    return;
   }
+  uri_to_resolve_ = server_uri;
   char* proxy_name = nullptr;
   grpc_channel_args* new_args = nullptr;
   ProxyMapperRegistry::MapName(server_uri, args->channel_args, &proxy_name,
                                &new_args);
-  target_uri_.reset(proxy_name != nullptr ? proxy_name
-                                          : gpr_strdup(server_uri));
+  if (proxy_name != nullptr) {
+    uri_to_resolve_ = proxy_name;
+    gpr_free(proxy_name);
+  }
+  // Make sure the URI to resolve is valid, so that we know that
+  // resolver creation will succeed later.
+  if (!ResolverRegistry::IsValidTarget(uri_to_resolve_)) {
+    *error = GRPC_ERROR_CREATE_FROM_CPP_STRING(
+        absl::StrCat("the target uri is not valid: ", uri_to_resolve_.c_str()));
+    return;
+  }
   // Strip out service config channel arg, so that it doesn't affect
   // subchannel uniqueness when the args flow down to that layer.
   const char* arg_to_remove = GRPC_ARG_SERVICE_CONFIG;
   channel_args_ = grpc_channel_args_copy_and_remove(
       new_args != nullptr ? new_args : args->channel_args, &arg_to_remove, 1);
   grpc_channel_args_destroy(new_args);
+  // Set initial keepalive time.
   keepalive_time_ = grpc_channel_args_find_integer(
       channel_args_, GRPC_ARG_KEEPALIVE_TIME_MS,
       {-1 /* default value, unset */, 1, INT_MAX});
-  if (!ResolverRegistry::IsValidTarget(target_uri_.get())) {
-    *error = GRPC_ERROR_CREATE_FROM_CPP_STRING(
-        absl::StrCat("the target uri is not valid: ", target_uri_.get()));
-    return;
+  // Set default authority.
+  const char* default_authority =
+      grpc_channel_args_find_string(channel_args_, GRPC_ARG_DEFAULT_AUTHORITY);
+  if (default_authority == nullptr) {
+    default_authority_ = ResolverRegistry::GetDefaultAuthority(server_uri);
+  } else {
+    default_authority_ = default_authority;
   }
+  // Success.
   *error = GRPC_ERROR_NONE;
 }
 
@@ -1158,7 +1126,7 @@ ClientChannel::~ClientChannel() {
   // Stop backup polling.
   grpc_client_channel_stop_backup_polling(interested_parties_);
   grpc_pollset_set_destroy(interested_parties_);
-  GRPC_ERROR_UNREF(disconnect_error_.load(std::memory_order_relaxed));
+  GRPC_ERROR_UNREF(disconnect_error_);
 }
 
 OrphanablePtr<ClientChannel::LoadBalancedCall>
@@ -1307,15 +1275,16 @@ void ClientChannel::OnResolverResultChangedLocked(Resolver::Result result) {
     // If either has changed, apply the global parameters now.
     if (service_config_changed || config_selector_changed) {
       // Update service config in control plane.
-      UpdateServiceConfigInControlPlaneLocked(
-          std::move(service_config), std::move(config_selector),
-          parsed_service_config, lb_policy_config->name());
+      UpdateServiceConfigInControlPlaneLocked(std::move(service_config),
+                                              std::move(config_selector),
+                                              lb_policy_config->name());
     } else if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
       gpr_log(GPR_INFO, "chand=%p: service config not changed", this);
     }
     // Create or update LB policy, as needed.
-    CreateOrUpdateLbPolicyLocked(std::move(lb_policy_config),
-                                 std::move(result));
+    CreateOrUpdateLbPolicyLocked(
+        std::move(lb_policy_config),
+        parsed_service_config->health_check_service_name(), std::move(result));
     if (service_config_changed || config_selector_changed) {
       // Start using new service config for calls.
       // This needs to happen after the LB policy has been updated, since
@@ -1381,17 +1350,25 @@ void ClientChannel::OnResolverErrorLocked(grpc_error_handle error) {
 
 void ClientChannel::CreateOrUpdateLbPolicyLocked(
     RefCountedPtr<LoadBalancingPolicy::Config> lb_policy_config,
+    const absl::optional<std::string>& health_check_service_name,
     Resolver::Result result) {
   // Construct update.
   LoadBalancingPolicy::UpdateArgs update_args;
   update_args.addresses = std::move(result.addresses);
   update_args.config = std::move(lb_policy_config);
+  // Add health check service name to channel args.
+  absl::InlinedVector<grpc_arg, 1> args_to_add;
+  if (health_check_service_name.has_value()) {
+    args_to_add.push_back(grpc_channel_arg_string_create(
+        const_cast<char*>(GRPC_ARG_HEALTH_CHECK_SERVICE_NAME),
+        const_cast<char*>(health_check_service_name->c_str())));
+  }
   // Remove the config selector from channel args so that we're not holding
   // unnecessary refs that cause it to be destroyed somewhere other than in the
   // WorkSerializer.
-  const char* arg_name = GRPC_ARG_CONFIG_SELECTOR;
-  update_args.args =
-      grpc_channel_args_copy_and_remove(result.args, &arg_name, 1);
+  const char* arg_to_remove = GRPC_ARG_CONFIG_SELECTOR;
+  update_args.args = grpc_channel_args_copy_and_add_and_remove(
+      result.args, &arg_to_remove, 1, args_to_add.data(), args_to_add.size());
   // Create policy if needed.
   if (lb_policy_ == nullptr) {
     lb_policy_ = CreateLbPolicyLocked(*update_args.args);
@@ -1450,9 +1427,7 @@ void ClientChannel::RemoveResolverQueuedCall(ResolverQueuedCall* to_remove,
 
 void ClientChannel::UpdateServiceConfigInControlPlaneLocked(
     RefCountedPtr<ServiceConfig> service_config,
-    RefCountedPtr<ConfigSelector> config_selector,
-    const internal::ClientChannelGlobalParsedConfig* parsed_service_config,
-    const char* lb_policy_name) {
+    RefCountedPtr<ConfigSelector> config_selector, const char* lb_policy_name) {
   UniquePtr<char> service_config_json(
       gpr_strdup(service_config->json_string().c_str()));
   if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
@@ -1462,17 +1437,6 @@ void ClientChannel::UpdateServiceConfigInControlPlaneLocked(
   }
   // Save service config.
   saved_service_config_ = std::move(service_config);
-  // Update health check service name if needed.
-  if (health_check_service_name_ !=
-      parsed_service_config->health_check_service_name()) {
-    health_check_service_name_ =
-        parsed_service_config->health_check_service_name();
-    // Update health check service name used by existing subchannel wrappers.
-    for (auto* subchannel_wrapper : subchannel_wrappers_) {
-      subchannel_wrapper->UpdateHealthCheckServiceName(
-          health_check_service_name_);
-    }
-  }
   // Swap out the data used by GetChannelInfo().
   UniquePtr<char> lb_policy_name_owned(gpr_strdup(lb_policy_name));
   {
@@ -1530,7 +1494,6 @@ void ClientChannel::UpdateServiceConfigInDataPlaneLocked() {
   //
   // We defer unreffing the old values (and deallocating memory) until
   // after releasing the lock to keep the critical section small.
-  std::set<grpc_call_element*> calls_pending_resolver_result;
   {
     MutexLock lock(&resolution_mu_);
     GRPC_ERROR_UNREF(resolver_transient_failure_error_);
@@ -1570,8 +1533,8 @@ void ClientChannel::CreateResolverLocked() {
     gpr_log(GPR_INFO, "chand=%p: starting name resolution", this);
   }
   resolver_ = ResolverRegistry::CreateResolver(
-      target_uri_.get(), channel_args_, interested_parties_, work_serializer_,
-      absl::make_unique<ResolverResultHandler>(this));
+      uri_to_resolve_.c_str(), channel_args_, interested_parties_,
+      work_serializer_, absl::make_unique<ResolverResultHandler>(this));
   // Since the validity of the args was checked when the channel was created,
   // CreateResolver() must return a non-null result.
   GPR_ASSERT(resolver_ != nullptr);
@@ -1635,30 +1598,9 @@ void ClientChannel::UpdateStateAndPickerLocked(
             channelz::ChannelNode::GetChannelConnectivityStateChangeString(
                 state)));
   }
-  // Grab data plane lock to do subchannel updates and update the picker.
-  //
-  // Note that we want to minimize the work done while holding the data
-  // plane lock, to keep the critical section small.  So, for all of the
-  // objects that we might wind up unreffing here, we actually hold onto
-  // the refs until after we release the lock, and then unref them at
-  // that point.  This includes the following:
-  // - refs to subchannel wrappers in the keys of pending_subchannel_updates_
-  // - ownership of the existing picker in picker_
+  // Grab data plane lock to update the picker.
   {
     MutexLock lock(&data_plane_mu_);
-    // Handle subchannel updates.
-    for (auto& p : pending_subchannel_updates_) {
-      if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
-        gpr_log(GPR_INFO,
-                "chand=%p: updating subchannel wrapper %p data plane "
-                "connected_subchannel to %p",
-                this, p.first.get(), p.second.get());
-      }
-      // Note: We do not remove the entry from pending_subchannel_updates_
-      // here, since this would unref the subchannel wrapper; instead,
-      // we wait until we've released the lock to clear the map.
-      p.first->set_connected_subchannel_in_data_plane(std::move(p.second));
-    }
     // Swap out the picker.
     // Note: Original value will be destroyed after the lock is released.
     picker_.swap(picker);
@@ -1680,9 +1622,6 @@ void ClientChannel::UpdateStateAndPickerLocked(
       }
     }
   }
-  // Clear the pending update map after releasing the lock, to keep the
-  // critical section small.
-  pending_subchannel_updates_.clear();
 }
 
 namespace {
@@ -1735,7 +1674,7 @@ grpc_error_handle ClientChannel::DoPingLocked(grpc_transport_op* op) {
           ABSL_EXCLUSIVE_LOCKS_REQUIRED(&ClientChannel::work_serializer_) {
             SubchannelWrapper* subchannel = static_cast<SubchannelWrapper*>(
                 complete_pick->subchannel.get());
-            ConnectedSubchannel* connected_subchannel =
+            RefCountedPtr<ConnectedSubchannel> connected_subchannel =
                 subchannel->connected_subchannel();
             connected_subchannel->Ping(op->send_ping.on_initiate,
                                        op->send_ping.on_ack);
@@ -1793,7 +1732,7 @@ void ClientChannel::StartTransportOpLocked(grpc_transport_op* op) {
     if (grpc_error_get_int(op->disconnect_with_error,
                            GRPC_ERROR_INT_CHANNEL_CONNECTIVITY_STATE, &value) &&
         static_cast<grpc_connectivity_state>(value) == GRPC_CHANNEL_IDLE) {
-      if (disconnect_error() == GRPC_ERROR_NONE) {
+      if (disconnect_error_ == GRPC_ERROR_NONE) {
         // Enter IDLE state.
         UpdateStateAndPickerLocked(GRPC_CHANNEL_IDLE, absl::Status(),
                                    "channel entering IDLE", nullptr);
@@ -1801,10 +1740,8 @@ void ClientChannel::StartTransportOpLocked(grpc_transport_op* op) {
       GRPC_ERROR_UNREF(op->disconnect_with_error);
     } else {
       // Disconnect.
-      GPR_ASSERT(disconnect_error_.load(std::memory_order_relaxed) ==
-                 GRPC_ERROR_NONE);
-      disconnect_error_.store(op->disconnect_with_error,
-                              std::memory_order_release);
+      GPR_ASSERT(disconnect_error_ == GRPC_ERROR_NONE);
+      disconnect_error_ = op->disconnect_with_error;
       UpdateStateAndPickerLocked(
           GRPC_CHANNEL_SHUTDOWN, absl::Status(), "shutdown from API",
           absl::make_unique<LoadBalancingPolicy::TransientFailurePicker>(
@@ -1869,17 +1806,6 @@ void ClientChannel::RemoveLbQueuedCall(LbQueuedCall* to_remove,
   }
 }
 
-RefCountedPtr<ConnectedSubchannel>
-ClientChannel::GetConnectedSubchannelInDataPlane(
-    SubchannelInterface* subchannel) const {
-  SubchannelWrapper* subchannel_wrapper =
-      static_cast<SubchannelWrapper*>(subchannel);
-  ConnectedSubchannel* connected_subchannel =
-      subchannel_wrapper->connected_subchannel_in_data_plane();
-  if (connected_subchannel == nullptr) return nullptr;
-  return connected_subchannel->Ref();
-}
-
 void ClientChannel::TryToConnectLocked() {
   if (lb_policy_ != nullptr) {
     lb_policy_->ExitIdleLocked();
@@ -2274,15 +2200,16 @@ grpc_error_handle ClientChannel::CallData::ApplyServiceConfigToCallLocked(
     ConfigSelector::CallConfig call_config =
         config_selector->GetCallConfig({&path_, initial_metadata, arena_});
     if (call_config.error != GRPC_ERROR_NONE) return call_config.error;
-    // Create a ServiceConfigCallData for the call.  This stores a ref to the
-    // ServiceConfig and caches the right set of parsed configs to use for
-    // the call.  The MethodConfig will store itself in the call context,
-    // so that it can be accessed by filters in the subchannel, and it
-    // will be cleaned up when the call ends.
-    auto* service_config_call_data = arena_->New<ServiceConfigCallData>(
-        std::move(call_config.service_config), call_config.method_configs,
-        std::move(call_config.call_attributes),
-        call_config.call_dispatch_controller, call_context_);
+    // Create a ClientChannelServiceConfigCallData for the call.  This stores
+    // a ref to the ServiceConfig and caches the right set of parsed configs
+    // to use for the call.  The ClientChannelServiceConfigCallData will store
+    // itself in the call context, so that it can be accessed by filters
+    // below us in the stack, and it will be cleaned up when the call ends.
+    auto* service_config_call_data =
+        arena_->New<ClientChannelServiceConfigCallData>(
+            std::move(call_config.service_config), call_config.method_configs,
+            std::move(call_config.call_attributes),
+            call_config.call_dispatch_controller, call_context_);
     // Apply our own method params to the call.
     auto* method_params = static_cast<ClientChannelMethodParsedConfig*>(
         service_config_call_data->GetMethodParsedConfig(
@@ -2324,8 +2251,9 @@ void ClientChannel::CallData::
     RecvTrailingMetadataReadyForConfigSelectorCommitCallback(
         void* arg, grpc_error_handle error) {
   auto* self = static_cast<CallData*>(arg);
-  auto* service_config_call_data = static_cast<ServiceConfigCallData*>(
-      self->call_context_[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].value);
+  auto* service_config_call_data =
+      static_cast<ClientChannelServiceConfigCallData*>(
+          self->call_context_[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].value);
   if (service_config_call_data != nullptr) {
     service_config_call_data->call_dispatch_controller()->Commit();
   }
@@ -2495,24 +2423,28 @@ class ClientChannel::LoadBalancedCall::Metadata
     linked_mdelem->md = grpc_mdelem_from_slices(
         ExternallyManagedSlice(key.data(), key.size()),
         ExternallyManagedSlice(value.data(), value.size()));
-    GPR_ASSERT(grpc_metadata_batch_link_tail(batch_, linked_mdelem) ==
-               GRPC_ERROR_NONE);
+    GPR_ASSERT(batch_->LinkTail(linked_mdelem) == GRPC_ERROR_NONE);
   }
 
   std::vector<std::pair<std::string, std::string>> TestOnlyCopyToVector()
       override {
     std::vector<std::pair<std::string, std::string>> result;
-    for (grpc_linked_mdelem* entry = batch_->list.head; entry != nullptr;
-         entry = entry->next) {
-      if (batch_->idx.named.path != entry) {
-        result.push_back(std::make_pair(
-            std::string(StringViewFromSlice(GRPC_MDKEY(entry->md))),
-            std::string(StringViewFromSlice(GRPC_MDVALUE(entry->md)))));
+    batch_->ForEach([&](grpc_mdelem md) {
+      auto key = std::string(StringViewFromSlice(GRPC_MDKEY(md)));
+      if (key != ":path") {
+        result.push_back(
+            std::make_pair(std::move(key),
+                           std::string(StringViewFromSlice(GRPC_MDVALUE(md)))));
       }
-    }
+    });
     return result;
   }
 
+  absl::optional<absl::string_view> Lookup(absl::string_view key,
+                                           std::string* buffer) const override {
+    return batch_->GetValue(key, buffer);
+  }
+
  private:
   LoadBalancedCall* lb_call_;
   grpc_metadata_batch* batch_;
@@ -2532,8 +2464,8 @@ class ClientChannel::LoadBalancedCall::LbCallState
   const LoadBalancingPolicy::BackendMetricData* GetBackendMetricData()
       override {
     if (lb_call_->backend_metric_data_ == nullptr) {
-      grpc_linked_mdelem* md = lb_call_->recv_trailing_metadata_->idx.named
-                                   .x_endpoint_load_metrics_bin;
+      grpc_linked_mdelem* md = lb_call_->recv_trailing_metadata_->legacy_index()
+                                   ->named.x_endpoint_load_metrics_bin;
       if (md != nullptr) {
         lb_call_->backend_metric_data_ =
             ParseBackendMetricData(GRPC_MDVALUE(md->md), lb_call_->arena_);
@@ -2906,14 +2838,13 @@ void ClientChannel::LoadBalancedCall::RecvTrailingMetadataReady(
     if (error != GRPC_ERROR_NONE) {
       // Get status from error.
       grpc_status_code code;
-      grpc_slice message = grpc_empty_slice();
+      std::string message;
       grpc_error_get_status(error, self->deadline_, &code, &message,
                             /*http_error=*/nullptr, /*error_string=*/nullptr);
-      status = absl::Status(static_cast<absl::StatusCode>(code),
-                            StringViewFromSlice(message));
+      status = absl::Status(static_cast<absl::StatusCode>(code), message);
     } else {
       // Get status from headers.
-      const auto& fields = self->recv_trailing_metadata_->idx.named;
+      const auto& fields = self->recv_trailing_metadata_->legacy_index()->named;
       GPR_ASSERT(fields.grpc_status != nullptr);
       grpc_status_code code =
           grpc_get_status_code_from_metadata(fields.grpc_status->md);
@@ -3116,9 +3047,20 @@ bool ClientChannel::LoadBalancedCall::PickSubchannelLocked(
             GPR_ASSERT(complete_pick->subchannel != nullptr);
             // Grab a ref to the connected subchannel while we're still
             // holding the data plane mutex.
-            connected_subchannel_ = chand_->GetConnectedSubchannelInDataPlane(
+            SubchannelWrapper* subchannel = static_cast<SubchannelWrapper*>(
                 complete_pick->subchannel.get());
-            GPR_ASSERT(connected_subchannel_ != nullptr);
+            connected_subchannel_ = subchannel->connected_subchannel();
+            // If the subchannel has no connected subchannel (e.g., if the
+            // subchannel has moved out of state READY but the LB policy hasn't
+            // yet seen that change and given us a new picker), then just
+            // queue the pick.  We'll try again as soon as we get a new picker.
+            // TODO(roth): In this case, we need to invoke the LB
+            // policy's recv_trailing_metadata_ready callback to tell it
+            // that the pick has been abandoned.
+            if (connected_subchannel_ == nullptr) {
+              MaybeAddCallToLbQueuedCallsLocked();
+              return false;
+            }
             lb_recv_trailing_metadata_ready_ =
                 std::move(complete_pick->recv_trailing_metadata_ready);
             MaybeRemoveCallFromLbQueuedCallsLocked();
@@ -3142,13 +3084,6 @@ bool ClientChannel::LoadBalancedCall::PickSubchannelLocked(
               gpr_log(GPR_INFO, "chand=%p lb_call=%p: LB pick failed: %s",
                       chand_, this, fail_pick->status.ToString().c_str());
             }
-            // If we're shutting down, fail all RPCs.
-            grpc_error_handle disconnect_error = chand_->disconnect_error();
-            if (disconnect_error != GRPC_ERROR_NONE) {
-              MaybeRemoveCallFromLbQueuedCallsLocked();
-              *error = GRPC_ERROR_REF(disconnect_error);
-              return true;
-            }
             // If wait_for_ready is false, then the error indicates the RPC
             // attempt's final status.
             if ((send_initial_metadata_flags &
index 7ff217e..e273839 100644 (file)
 #include "src/core/ext/filters/client_channel/resolver.h"
 #include "src/core/ext/filters/client_channel/resolver_result_parsing.h"
 #include "src/core/ext/filters/client_channel/retry_throttle.h"
-#include "src/core/ext/filters/client_channel/service_config.h"
 #include "src/core/ext/filters/client_channel/subchannel.h"
 #include "src/core/ext/filters/client_channel/subchannel_pool_interface.h"
+#include "src/core/ext/service_config/service_config.h"
+#include "src/core/ext/service_config/service_config_call_data.h"
+#include "src/core/ext/service_config/service_config_parser.h"
 #include "src/core/lib/channel/call_tracer.h"
+#include "src/core/lib/channel/context.h"
+#include "src/core/lib/gprpp/ref_counted_ptr.h"
 #include "src/core/lib/gprpp/sync.h"
 #include "src/core/lib/iomgr/error.h"
 #include "src/core/lib/iomgr/polling_entity.h"
@@ -207,11 +211,6 @@ class ClientChannel {
   static void GetChannelInfo(grpc_channel_element* elem,
                              const grpc_channel_info* info);
 
-  // Note: Does NOT return a new ref.
-  grpc_error_handle disconnect_error() const {
-    return disconnect_error_.load(std::memory_order_acquire);
-  }
-
   // Note: All methods with "Locked" suffix must be invoked from within
   // work_serializer_.
 
@@ -222,6 +221,7 @@ class ClientChannel {
 
   void CreateOrUpdateLbPolicyLocked(
       RefCountedPtr<LoadBalancingPolicy::Config> lb_policy_config,
+      const absl::optional<std::string>& health_check_service_name,
       Resolver::Result result) ABSL_EXCLUSIVE_LOCKS_REQUIRED(work_serializer_);
   OrphanablePtr<LoadBalancingPolicy> CreateLbPolicyLocked(
       const grpc_channel_args& args)
@@ -235,9 +235,7 @@ class ClientChannel {
 
   void UpdateServiceConfigInControlPlaneLocked(
       RefCountedPtr<ServiceConfig> service_config,
-      RefCountedPtr<ConfigSelector> config_selector,
-      const internal::ClientChannelGlobalParsedConfig* parsed_service_config,
-      const char* lb_policy_name)
+      RefCountedPtr<ConfigSelector> config_selector, const char* lb_policy_name)
       ABSL_EXCLUSIVE_LOCKS_REQUIRED(work_serializer_);
 
   void UpdateServiceConfigInDataPlaneLocked()
@@ -268,9 +266,6 @@ class ClientChannel {
       ABSL_EXCLUSIVE_LOCKS_REQUIRED(data_plane_mu_);
   void RemoveLbQueuedCall(LbQueuedCall* to_remove, grpc_polling_entity* pollent)
       ABSL_EXCLUSIVE_LOCKS_REQUIRED(data_plane_mu_);
-  RefCountedPtr<ConnectedSubchannel> GetConnectedSubchannelInDataPlane(
-      SubchannelInterface* subchannel) const
-      ABSL_EXCLUSIVE_LOCKS_REQUIRED(data_plane_mu_);
 
   //
   // Fields set at construction and never modified.
@@ -280,8 +275,8 @@ class ClientChannel {
   ClientChannelFactory* client_channel_factory_;
   const grpc_channel_args* channel_args_;
   RefCountedPtr<ServiceConfig> default_service_config_;
-  std::string server_name_;
-  UniquePtr<char> target_uri_;
+  std::string uri_to_resolve_;
+  std::string default_authority_;
   channelz::ChannelNode* channelz_node_;
   grpc_pollset_set* interested_parties_;
 
@@ -323,8 +318,6 @@ class ClientChannel {
       ABSL_GUARDED_BY(work_serializer_);
   RefCountedPtr<ConfigSelector> saved_config_selector_
       ABSL_GUARDED_BY(work_serializer_);
-  absl::optional<std::string> health_check_service_name_
-      ABSL_GUARDED_BY(work_serializer_);
   OrphanablePtr<LoadBalancingPolicy> lb_policy_
       ABSL_GUARDED_BY(work_serializer_);
   RefCountedPtr<SubchannelPoolInterface> subchannel_pool_
@@ -337,18 +330,9 @@ class ClientChannel {
   // work_serializer when the SubchannelWrappers are created and destroyed.
   std::set<SubchannelWrapper*> subchannel_wrappers_
       ABSL_GUARDED_BY(work_serializer_);
-  // Pending ConnectedSubchannel updates for each SubchannelWrapper.
-  // Updates are queued here in the control plane work_serializer and then
-  // applied in the data plane mutex when the picker is updated.
-  std::map<RefCountedPtr<SubchannelWrapper>, RefCountedPtr<ConnectedSubchannel>>
-      pending_subchannel_updates_ ABSL_GUARDED_BY(work_serializer_);
   int keepalive_time_ ABSL_GUARDED_BY(work_serializer_) = -1;
-
-  //
-  // Fields accessed from both data plane mutex and control plane
-  // work_serializer.
-  //
-  std::atomic<grpc_error_handle> disconnect_error_{GRPC_ERROR_NONE};
+  grpc_error_handle disconnect_error_ ABSL_GUARDED_BY(work_serializer_) =
+      GRPC_ERROR_NONE;
 
   //
   // Fields guarded by a mutex, since they need to be accessed
@@ -529,6 +513,69 @@ class ClientChannel::LoadBalancedCall
   grpc_transport_stream_op_batch* pending_batches_[MAX_PENDING_BATCHES] = {};
 };
 
+// A sub-class of ServiceConfigCallData used to access the
+// CallDispatchController.  Allocated on the arena, stored in the call
+// context, and destroyed when the call is destroyed.
+class ClientChannelServiceConfigCallData : public ServiceConfigCallData {
+ public:
+  ClientChannelServiceConfigCallData(
+      RefCountedPtr<ServiceConfig> service_config,
+      const ServiceConfigParser::ParsedConfigVector* method_configs,
+      ServiceConfigCallData::CallAttributes call_attributes,
+      ConfigSelector::CallDispatchController* call_dispatch_controller,
+      grpc_call_context_element* call_context)
+      : ServiceConfigCallData(std::move(service_config), method_configs,
+                              std::move(call_attributes)),
+        call_dispatch_controller_(call_dispatch_controller) {
+    call_context[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].value = this;
+    call_context[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].destroy = Destroy;
+  }
+
+  ConfigSelector::CallDispatchController* call_dispatch_controller() {
+    return &call_dispatch_controller_;
+  }
+
+ private:
+  // A wrapper for the CallDispatchController returned by the ConfigSelector.
+  // Handles the case where the ConfigSelector doees not return any
+  // CallDispatchController.
+  // Also ensures that we call Commit() at most once, which allows the
+  // client channel code to call Commit() when the call is complete in case
+  // it wasn't called earlier, without needing to know whether or not it was.
+  class CallDispatchControllerWrapper
+      : public ConfigSelector::CallDispatchController {
+   public:
+    explicit CallDispatchControllerWrapper(
+        ConfigSelector::CallDispatchController* call_dispatch_controller)
+        : call_dispatch_controller_(call_dispatch_controller) {}
+
+    bool ShouldRetry() override {
+      if (call_dispatch_controller_ != nullptr) {
+        return call_dispatch_controller_->ShouldRetry();
+      }
+      return true;
+    }
+
+    void Commit() override {
+      if (call_dispatch_controller_ != nullptr && !commit_called_) {
+        call_dispatch_controller_->Commit();
+        commit_called_ = true;
+      }
+    }
+
+   private:
+    ConfigSelector::CallDispatchController* call_dispatch_controller_;
+    bool commit_called_ = false;
+  };
+
+  static void Destroy(void* ptr) {
+    auto* self = static_cast<ClientChannelServiceConfigCallData*>(ptr);
+    self->~ClientChannelServiceConfigCallData();
+  }
+
+  CallDispatchControllerWrapper call_dispatch_controller_;
+};
+
 }  // namespace grpc_core
 
 #endif  // GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_CLIENT_CHANNEL_H
index caaf963..7e234a3 100644 (file)
@@ -32,7 +32,7 @@ namespace {
 void* factory_arg_copy(void* f) { return f; }
 void factory_arg_destroy(void* /*f*/) {}
 int factory_arg_cmp(void* factory1, void* factory2) {
-  return GPR_ICMP(factory1, factory2);
+  return QsortCompare(factory1, factory2);
 }
 const grpc_arg_pointer_vtable factory_arg_vtable = {
     factory_arg_copy, factory_arg_destroy, factory_arg_cmp};
index 75d74d6..0e00edc 100644 (file)
@@ -1,20 +1,18 @@
-/*
- *
- * 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.
- *
- */
+//
+// 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.
+//
 
 #ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_CLIENT_CHANNEL_FACTORY_H
 #define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_CLIENT_CHANNEL_FACTORY_H
@@ -33,7 +31,7 @@ class ClientChannelFactory {
 
   // Creates a subchannel with the specified args.
   virtual RefCountedPtr<Subchannel> CreateSubchannel(
-      const grpc_channel_args* args) = 0;
+      const grpc_resolved_address& address, const grpc_channel_args* args) = 0;
 
   // Returns a channel arg containing the specified factory.
   static grpc_arg CreateChannelArg(ClientChannelFactory* factory);
@@ -45,4 +43,4 @@ class ClientChannelFactory {
 
 }  // namespace grpc_core
 
-#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_CLIENT_CHANNEL_FACTORY_H */
+#endif  // GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_CLIENT_CHANNEL_FACTORY_H
index 8bd41f2..8220518 100644 (file)
 #include "src/core/ext/filters/client_channel/resolver_result_parsing.h"
 #include "src/core/ext/filters/client_channel/retry_service_config.h"
 #include "src/core/ext/filters/client_channel/retry_throttle.h"
-#include "src/core/ext/filters/client_channel/service_config_parser.h"
-#include "src/core/lib/surface/channel_init.h"
-
-static bool append_filter(grpc_channel_stack_builder* builder, void* arg) {
-  return grpc_channel_stack_builder_append_filter(
-      builder, static_cast<const grpc_channel_filter*>(arg), nullptr, nullptr);
-}
+#include "src/core/lib/config/core_configuration.h"
 
 void grpc_client_channel_init(void) {
-  grpc_core::ServiceConfigParser::Init();
   grpc_core::internal::ClientChannelServiceConfigParser::Register();
   grpc_core::internal::RetryServiceConfigParser::Register();
   grpc_core::LoadBalancingPolicyRegistry::Builder::InitRegistry();
@@ -54,27 +47,28 @@ void grpc_client_channel_init(void) {
   grpc_core::ProxyMapperRegistry::Init();
   grpc_core::RegisterHttpProxyMapper();
   grpc_core::GlobalSubchannelPool::Init();
-  grpc_channel_init_register_stage(
-      GRPC_CLIENT_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, append_filter,
-      const_cast<grpc_channel_filter*>(
-          &grpc_core::ClientChannel::kFilterVtable));
   grpc_client_channel_global_init_backup_polling();
 }
 
 void grpc_client_channel_shutdown(void) {
   grpc_core::GlobalSubchannelPool::Shutdown();
-  grpc_channel_init_shutdown();
   grpc_core::ProxyMapperRegistry::Shutdown();
   grpc_core::internal::ServerRetryThrottleMap::Shutdown();
   grpc_core::ResolverRegistry::Builder::ShutdownRegistry();
   grpc_core::LoadBalancingPolicyRegistry::Builder::ShutdownRegistry();
-  grpc_core::ServiceConfigParser::Shutdown();
 }
 
 namespace grpc_core {
 
 void BuildClientChannelConfiguration(CoreConfiguration::Builder* builder) {
   RegisterHttpConnectHandshaker(builder);
+  builder->channel_init()->RegisterStage(
+      GRPC_CLIENT_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
+      [](grpc_channel_stack_builder* builder) {
+        return grpc_channel_stack_builder_append_filter(
+            builder, &grpc_core::ClientChannel::kFilterVtable, nullptr,
+            nullptr);
+      });
 }
 
 }  // namespace grpc_core
index c631adb..e741a3e 100644 (file)
@@ -35,7 +35,7 @@ void ConfigSelectorArgDestroy(void* p) {
   config_selector->Unref();
 }
 
-int ConfigSelectorArgCmp(void* p, void* q) { return GPR_ICMP(p, q); }
+int ConfigSelectorArgCmp(void* p, void* q) { return QsortCompare(p, q); }
 
 const grpc_arg_pointer_vtable kChannelArgVtable = {
     ConfigSelectorArgCopy, ConfigSelectorArgDestroy, ConfigSelectorArgCmp};
index 6c7e750..5feb331 100644 (file)
@@ -27,8 +27,9 @@
 
 #include <grpc/grpc.h>
 
-#include "src/core/ext/filters/client_channel/service_config.h"
-#include "src/core/ext/filters/client_channel/service_config_parser.h"
+#include "src/core/ext/service_config/service_config.h"
+#include "src/core/ext/service_config/service_config_call_data.h"
+#include "src/core/ext/service_config/service_config_parser.h"
 #include "src/core/lib/channel/channel_stack.h"
 #include "src/core/lib/gprpp/arena.h"
 #include "src/core/lib/gprpp/ref_counted.h"
@@ -44,8 +45,6 @@ namespace grpc_core {
 // MethodConfig and provide input to LB policies on a per-call basis.
 class ConfigSelector : public RefCounted<ConfigSelector> {
  public:
-  using CallAttributes = std::map<const char*, absl::string_view>;
-
   // An interface to be used by the channel when dispatching calls.
   class CallDispatchController {
    public:
@@ -76,7 +75,7 @@ class ConfigSelector : public RefCounted<ConfigSelector> {
     // the call to ensure that method_configs lives long enough.
     RefCountedPtr<ServiceConfig> service_config;
     // Call attributes that will be accessible to LB policy implementations.
-    CallAttributes call_attributes;
+    ServiceConfigCallData::CallAttributes call_attributes;
     // Call dispatch controller.
     CallDispatchController* call_dispatch_controller = nullptr;
   };
index 20e25b5..3e193be 100644 (file)
@@ -1,20 +1,18 @@
-/*
- *
- * 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.
- *
- */
+//
+// 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.
+//
 
 #ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_CONNECTOR_H
 #define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_CONNECTOR_H
@@ -35,6 +33,8 @@ namespace grpc_core {
 class SubchannelConnector : public InternallyRefCounted<SubchannelConnector> {
  public:
   struct Args {
+    // Address to connect to.
+    grpc_resolved_address* address;
     // Set of pollsets interested in this connection.
     grpc_pollset_set* interested_parties;
     // Deadline for connection.
@@ -76,4 +76,4 @@ class SubchannelConnector : public InternallyRefCounted<SubchannelConnector> {
 
 }  // namespace grpc_core
 
-#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_CONNECTOR_H */
+#endif  // GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_CONNECTOR_H
index 47c05a3..8e7f5db 100644 (file)
@@ -163,7 +163,7 @@ RefCountedPtr<DynamicFilters> DynamicFilters::Create(
     // Channel stack creation failed with requested filters.
     // Create with lame filter instead.
     grpc_error_handle error = p.second;
-    grpc_arg error_arg = MakeLameClientErrorArg(error);
+    grpc_arg error_arg = MakeLameClientErrorArg(&error);
     grpc_channel_args* new_args =
         grpc_channel_args_copy_and_add(args, &error_arg, 1);
     GRPC_ERROR_UNREF(error);
index 7ff9b07..5b29a89 100644 (file)
@@ -32,7 +32,6 @@ namespace grpc_core {
 // should be only one instance of this class. Init() should be called once at
 // the filter initialization time; Shutdown() should be called once at the
 // filter shutdown time.
-// TODO(juanlishen): Enable subchannel retention.
 class GlobalSubchannelPool final : public SubchannelPoolInterface {
  public:
   // The ctor and dtor are not intended to use directly.
index d8f4455..53d13a4 100644 (file)
@@ -254,7 +254,11 @@ HealthCheckClient::CallState::CallState(
       pollent_(grpc_polling_entity_create_from_pollset_set(interested_parties)),
       arena_(Arena::Create(health_check_client_->connected_subchannel_
                                ->GetInitialCallSizeEstimate())),
-      payload_(context_) {}
+      payload_(context_),
+      send_initial_metadata_(arena_),
+      send_trailing_metadata_(arena_),
+      recv_initial_metadata_(arena_),
+      recv_trailing_metadata_(arena_) {}
 
 HealthCheckClient::CallState::~CallState() {
   if (GRPC_TRACE_FLAG_ENABLED(grpc_health_check_client_trace)) {
@@ -315,7 +319,6 @@ void HealthCheckClient::CallState::StartCall() {
   batch_.on_complete = GRPC_CLOSURE_INIT(&on_complete_, OnComplete, this,
                                          grpc_schedule_on_exec_ctx);
   // Add send_initial_metadata op.
-  grpc_metadata_batch_init(&send_initial_metadata_);
   error = grpc_metadata_batch_add_head(
       &send_initial_metadata_, &path_metadata_storage_,
       grpc_mdelem_from_slices(
@@ -333,12 +336,10 @@ void HealthCheckClient::CallState::StartCall() {
   payload_.send_message.send_message.reset(send_message_.get());
   batch_.send_message = true;
   // Add send_trailing_metadata op.
-  grpc_metadata_batch_init(&send_trailing_metadata_);
   payload_.send_trailing_metadata.send_trailing_metadata =
       &send_trailing_metadata_;
   batch_.send_trailing_metadata = true;
   // Add recv_initial_metadata op.
-  grpc_metadata_batch_init(&recv_initial_metadata_);
   payload_.recv_initial_metadata.recv_initial_metadata =
       &recv_initial_metadata_;
   payload_.recv_initial_metadata.recv_flags = nullptr;
@@ -363,7 +364,6 @@ void HealthCheckClient::CallState::StartCall() {
   // Initialize recv_trailing_metadata batch.
   recv_trailing_metadata_batch_.payload = &payload_;
   // Add recv_trailing_metadata op.
-  grpc_metadata_batch_init(&recv_trailing_metadata_);
   payload_.recv_trailing_metadata.recv_trailing_metadata =
       &recv_trailing_metadata_;
   payload_.recv_trailing_metadata.collect_stats = &collect_stats_;
@@ -441,8 +441,8 @@ void HealthCheckClient::CallState::OnComplete(void* arg,
   HealthCheckClient::CallState* self =
       static_cast<HealthCheckClient::CallState*>(arg);
   GRPC_CALL_COMBINER_STOP(&self->call_combiner_, "on_complete");
-  grpc_metadata_batch_destroy(&self->send_initial_metadata_);
-  grpc_metadata_batch_destroy(&self->send_trailing_metadata_);
+  self->send_initial_metadata_.Clear();
+  self->send_trailing_metadata_.Clear();
   self->call_->Unref(DEBUG_LOCATION, "on_complete");
 }
 
@@ -451,7 +451,7 @@ void HealthCheckClient::CallState::RecvInitialMetadataReady(
   HealthCheckClient::CallState* self =
       static_cast<HealthCheckClient::CallState*>(arg);
   GRPC_CALL_COMBINER_STOP(&self->call_combiner_, "recv_initial_metadata_ready");
-  grpc_metadata_batch_destroy(&self->recv_initial_metadata_);
+  self->recv_initial_metadata_.Clear();
   self->call_->Unref(DEBUG_LOCATION, "recv_initial_metadata_ready");
 }
 
@@ -558,9 +558,10 @@ void HealthCheckClient::CallState::RecvTrailingMetadataReady(
     grpc_error_get_status(error, GRPC_MILLIS_INF_FUTURE, &status,
                           nullptr /* slice */, nullptr /* http_error */,
                           nullptr /* error_string */);
-  } else if (self->recv_trailing_metadata_.idx.named.grpc_status != nullptr) {
+  } else if (self->recv_trailing_metadata_.legacy_index()->named.grpc_status !=
+             nullptr) {
     status = grpc_get_status_code_from_metadata(
-        self->recv_trailing_metadata_.idx.named.grpc_status->md);
+        self->recv_trailing_metadata_.legacy_index()->named.grpc_status->md);
   }
   if (GRPC_TRACE_FLAG_ENABLED(grpc_health_check_client_trace)) {
     gpr_log(GPR_INFO,
@@ -569,7 +570,7 @@ void HealthCheckClient::CallState::RecvTrailingMetadataReady(
             self->health_check_client_.get(), self, status);
   }
   // Clean up.
-  grpc_metadata_batch_destroy(&self->recv_trailing_metadata_);
+  self->recv_trailing_metadata_.Clear();
   // For status UNIMPLEMENTED, give up and assume always healthy.
   bool retry = true;
   if (status == GRPC_STATUS_UNIMPLEMENTED) {
index 31d25c2..d23ce91 100644 (file)
@@ -19,7 +19,7 @@
 #ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_HTTP_CONNECT_HANDSHAKER_H
 #define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_HTTP_CONNECT_HANDSHAKER_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include "src/core/lib/config/core_configuration.h"
 
index c7a78c1..5066875 100644 (file)
@@ -29,7 +29,6 @@
 #include "absl/types/variant.h"
 
 #include "src/core/ext/filters/client_channel/server_address.h"
-#include "src/core/ext/filters/client_channel/service_config.h"
 #include "src/core/ext/filters/client_channel/subchannel_interface.h"
 #include "src/core/lib/gprpp/orphanable.h"
 #include "src/core/lib/gprpp/ref_counted_ptr.h"
@@ -154,6 +153,9 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
     /// Produce a vector of metadata key/value strings for tests.
     virtual std::vector<std::pair<std::string, std::string>>
     TestOnlyCopyToVector() = 0;
+
+    virtual absl::optional<absl::string_view> Lookup(
+        absl::string_view key, std::string* buffer) const = 0;
   };
 
   /// Arguments used when picking a subchannel for a call.
@@ -261,6 +263,11 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
 
   /// A proxy object implemented by the client channel and used by the
   /// LB policy to communicate with the channel.
+  // TODO(roth): Once insecure builds go away, add methods for accessing
+  // channel creds.  By default, that should strip off the call creds
+  // attached to the channel creds, but there should also be a "use at
+  // your own risk" option to get the channel creds without stripping
+  // off the attached call creds.
   class ChannelControlHelper {
    public:
     ChannelControlHelper() = default;
@@ -279,6 +286,9 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
     /// Requests that the resolver re-resolve.
     virtual void RequestReresolution() = 0;
 
+    /// Returns the channel authority.
+    virtual absl::string_view GetAuthority() = 0;
+
     /// Adds a trace message associated with the channel.
     enum TraceSeverity { TRACE_INFO, TRACE_WARNING, TRACE_ERROR };
     virtual void AddTraceEvent(TraceSeverity severity,
index a307ce6..1d0b1ef 100644 (file)
@@ -90,6 +90,10 @@ class ChildPolicyHandler::Helper
     parent_->channel_control_helper()->RequestReresolution();
   }
 
+  absl::string_view GetAuthority() override {
+    return parent_->channel_control_helper()->GetAuthority();
+  }
+
   void AddTraceEvent(TraceSeverity severity,
                      absl::string_view message) override {
     if (parent_->shutting_down_) return;
index 5f7d75c..a3cf12a 100644 (file)
@@ -101,20 +101,15 @@ static void clr_start_transport_stream_op_batch(
   // Handle send_initial_metadata.
   if (batch->send_initial_metadata) {
     // Grab client stats object from metadata.
-    grpc_linked_mdelem* client_stats_md =
-        batch->payload->send_initial_metadata.send_initial_metadata->list.head;
-    for (; client_stats_md != nullptr;
-         client_stats_md = client_stats_md->next) {
-      if (GRPC_SLICE_START_PTR(GRPC_MDKEY(client_stats_md->md)) ==
-          static_cast<const void*>(grpc_core::kGrpcLbClientStatsMetadataKey)) {
-        break;
-      }
-    }
-    if (client_stats_md != nullptr) {
+    auto client_stats_md =
+        batch->payload->send_initial_metadata.send_initial_metadata->Remove(
+            grpc_slice_from_static_string(
+                grpc_core::kGrpcLbClientStatsMetadataKey));
+    if (client_stats_md.has_value()) {
       grpc_core::GrpcLbClientStats* client_stats =
           const_cast<grpc_core::GrpcLbClientStats*>(
               reinterpret_cast<const grpc_core::GrpcLbClientStats*>(
-                  GRPC_SLICE_START_PTR(GRPC_MDVALUE(client_stats_md->md))));
+                  GRPC_SLICE_START_PTR(*client_stats_md)));
       if (client_stats != nullptr) {
         calld->client_stats.reset(client_stats);
         // Intercept completion.
@@ -123,10 +118,6 @@ static void clr_start_transport_stream_op_batch(
                           calld, grpc_schedule_on_exec_ctx);
         batch->on_complete = &calld->on_complete_for_send;
       }
-      // Remove metadata so it doesn't go out on the wire.
-      grpc_metadata_batch_remove(
-          batch->payload->send_initial_metadata.send_initial_metadata,
-          client_stats_md);
     }
   }
   // Intercept completion of recv_initial_metadata.
index 95ec208..489d153 100644 (file)
@@ -1,20 +1,18 @@
-/*
- *
- * 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.
- *
- */
+//
+// 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.
+//
 
 /// Implementation of the gRPC LB policy.
 ///
@@ -88,6 +86,8 @@
 #include "src/core/lib/backoff/backoff.h"
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/channel/channel_stack.h"
+#include "src/core/lib/channel/channel_stack_builder.h"
+#include "src/core/lib/config/core_configuration.h"
 #include "src/core/lib/gpr/string.h"
 #include "src/core/lib/gprpp/manual_constructor.h"
 #include "src/core/lib/gprpp/memory.h"
 #include "src/core/lib/slice/slice_string_helpers.h"
 #include "src/core/lib/surface/call.h"
 #include "src/core/lib/surface/channel.h"
-#include "src/core/lib/surface/channel_init.h"
 #include "src/core/lib/transport/static_metadata.h"
 
 #define GRPC_GRPCLB_INITIAL_CONNECT_BACKOFF_SECONDS 1
 #define GRPC_GRPCLB_RECONNECT_MAX_BACKOFF_SECONDS 120
 #define GRPC_GRPCLB_RECONNECT_JITTER 0.2
 #define GRPC_GRPCLB_DEFAULT_FALLBACK_TIMEOUT_MS 10000
-
-#define GRPC_ARG_GRPCLB_ADDRESS_LB_TOKEN "grpc.grpclb_address_lb_token"
-#define GRPC_ARG_GRPCLB_ADDRESS_CLIENT_STATS "grpc.grpclb_address_client_stats"
+#define GRPC_GRPCLB_DEFAULT_SUBCHANNEL_DELETION_DELAY_MS 10000
 
 namespace grpc_core {
 
@@ -233,16 +230,24 @@ class GrpcLb : public LoadBalancingPolicy {
   class SubchannelWrapper : public DelegatingSubchannel {
    public:
     SubchannelWrapper(RefCountedPtr<SubchannelInterface> subchannel,
-                      std::string lb_token,
+                      RefCountedPtr<GrpcLb> lb_policy, std::string lb_token,
                       RefCountedPtr<GrpcLbClientStats> client_stats)
         : DelegatingSubchannel(std::move(subchannel)),
+          lb_policy_(std::move(lb_policy)),
           lb_token_(std::move(lb_token)),
           client_stats_(std::move(client_stats)) {}
 
+    ~SubchannelWrapper() override {
+      if (!lb_policy_->shutting_down_) {
+        lb_policy_->CacheDeletedSubchannelLocked(wrapped_subchannel());
+      }
+    }
+
     const std::string& lb_token() const { return lb_token_; }
     GrpcLbClientStats* client_stats() const { return client_stats_.get(); }
 
    private:
+    RefCountedPtr<GrpcLb> lb_policy_;
     std::string lb_token_;
     RefCountedPtr<GrpcLbClientStats> client_stats_;
   };
@@ -265,7 +270,7 @@ class GrpcLb : public LoadBalancingPolicy {
           static_cast<const TokenAndClientStatsAttribute*>(other_base);
       int r = lb_token_.compare(other->lb_token_);
       if (r != 0) return r;
-      return GPR_ICMP(client_stats_.get(), other->client_stats_.get());
+      return QsortCompare(client_stats_.get(), other->client_stats_.get());
     }
 
     std::string ToString() const override {
@@ -351,6 +356,7 @@ class GrpcLb : public LoadBalancingPolicy {
     void UpdateState(grpc_connectivity_state state, const absl::Status& status,
                      std::unique_ptr<SubchannelPicker> picker) override;
     void RequestReresolution() override;
+    absl::string_view GetAuthority() override;
     void AddTraceEvent(TraceSeverity severity,
                        absl::string_view message) override;
 
@@ -420,6 +426,13 @@ class GrpcLb : public LoadBalancingPolicy {
       const grpc_channel_args* args);
   void CreateOrUpdateChildPolicyLocked();
 
+  // Subchannel caching.
+  void CacheDeletedSubchannelLocked(
+      RefCountedPtr<SubchannelInterface> subchannel);
+  void StartSubchannelCacheTimerLocked();
+  static void OnSubchannelCacheTimer(void* arg, grpc_error_handle error);
+  void OnSubchannelCacheTimerLocked(grpc_error_handle error);
+
   // Who the client is trying to communicate with.
   std::string server_name_;
   // Configurations for the policy.
@@ -446,7 +459,7 @@ class GrpcLb : public LoadBalancingPolicy {
   // contains a non-NULL lb_call_.
   OrphanablePtr<BalancerCallState> lb_calld_;
   // Timeout in milliseconds for the LB call. 0 means no deadline.
-  int lb_call_timeout_ms_ = 0;
+  const int lb_call_timeout_ms_ = 0;
   // Balancer call retry state.
   BackOff lb_call_backoff_;
   bool retry_timer_callback_pending_ = false;
@@ -464,7 +477,7 @@ class GrpcLb : public LoadBalancingPolicy {
   // State for fallback-at-startup checks.
   // Timeout after startup after which we will go into fallback mode if
   // we have not received a serverlist from the balancer.
-  int fallback_at_startup_timeout_ = 0;
+  const int fallback_at_startup_timeout_ = 0;
   bool fallback_at_startup_checks_pending_ = false;
   grpc_timer lb_fallback_timer_;
   grpc_closure lb_on_fallback_;
@@ -473,6 +486,15 @@ class GrpcLb : public LoadBalancingPolicy {
   OrphanablePtr<LoadBalancingPolicy> child_policy_;
   // Child policy in state READY.
   bool child_policy_ready_ = false;
+
+  // Deleted subchannel caching.
+  const grpc_millis subchannel_cache_interval_ms_;
+  std::map<grpc_millis /*deletion time*/,
+           std::vector<RefCountedPtr<SubchannelInterface>>>
+      cached_subchannels_;
+  grpc_timer subchannel_cache_timer_;
+  grpc_closure on_subchannel_cache_timer_;
+  bool subchannel_cache_timer_pending_ = false;
 };
 
 //
@@ -673,7 +695,8 @@ RefCountedPtr<SubchannelInterface> GrpcLb::Helper::CreateSubchannel(
   return MakeRefCounted<SubchannelWrapper>(
       parent_->channel_control_helper()->CreateSubchannel(std::move(address),
                                                           args),
-      std::move(lb_token), std::move(client_stats));
+      parent_->Ref(DEBUG_LOCATION, "SubchannelWrapper"), std::move(lb_token),
+      std::move(client_stats));
 }
 
 void GrpcLb::Helper::UpdateState(grpc_connectivity_state state,
@@ -729,6 +752,10 @@ void GrpcLb::Helper::RequestReresolution() {
   }
 }
 
+absl::string_view GrpcLb::Helper::GetAuthority() {
+  return parent_->channel_control_helper()->GetAuthority();
+}
+
 void GrpcLb::Helper::AddTraceEvent(TraceSeverity severity,
                                    absl::string_view message) {
   if (parent_->shutting_down_) return;
@@ -902,7 +929,7 @@ void GrpcLb::BalancerCallState::ScheduleNextClientLoadReportLocked() {
 void GrpcLb::BalancerCallState::MaybeSendClientLoadReport(
     void* arg, grpc_error_handle error) {
   BalancerCallState* lb_calld = static_cast<BalancerCallState*>(arg);
-  GRPC_ERROR_REF(error);  // ref owned by lambda
+  (void)GRPC_ERROR_REF(error);  // ref owned by lambda
   lb_calld->grpclb_policy()->work_serializer()->Run(
       [lb_calld, error]() { lb_calld->MaybeSendClientLoadReportLocked(error); },
       DEBUG_LOCATION);
@@ -981,7 +1008,7 @@ void GrpcLb::BalancerCallState::SendClientLoadReportLocked() {
 void GrpcLb::BalancerCallState::ClientLoadReportDone(void* arg,
                                                      grpc_error_handle error) {
   BalancerCallState* lb_calld = static_cast<BalancerCallState*>(arg);
-  GRPC_ERROR_REF(error);  // ref owned by lambda
+  (void)GRPC_ERROR_REF(error);  // ref owned by lambda
   lb_calld->grpclb_policy()->work_serializer()->Run(
       [lb_calld, error]() { lb_calld->ClientLoadReportDoneLocked(error); },
       DEBUG_LOCATION);
@@ -1054,8 +1081,8 @@ void GrpcLb::BalancerCallState::OnBalancerMessageReceivedLocked() {
     switch (response.type) {
       case response.INITIAL: {
         if (response.client_stats_report_interval != 0) {
-          client_stats_report_interval_ =
-              GPR_MAX(GPR_MS_PER_SEC, response.client_stats_report_interval);
+          client_stats_report_interval_ = std::max(
+              int64_t(GPR_MS_PER_SEC), response.client_stats_report_interval);
           if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
             gpr_log(GPR_INFO,
                     "[grpclb %p] lb_calld=%p: Received initial LB response "
@@ -1184,7 +1211,7 @@ void GrpcLb::BalancerCallState::OnBalancerMessageReceivedLocked() {
 void GrpcLb::BalancerCallState::OnBalancerStatusReceived(
     void* arg, grpc_error_handle error) {
   BalancerCallState* lb_calld = static_cast<BalancerCallState*>(arg);
-  GRPC_ERROR_REF(error);  // owned by lambda
+  (void)GRPC_ERROR_REF(error);  // owned by lambda
   lb_calld->grpclb_policy()->work_serializer()->Run(
       [lb_calld, error]() { lb_calld->OnBalancerStatusReceivedLocked(error); },
       DEBUG_LOCATION);
@@ -1316,9 +1343,21 @@ grpc_channel_args* BuildBalancerChannelArgs(
 // ctor and dtor
 //
 
+std::string GetServerNameFromChannelArgs(const grpc_channel_args* args) {
+  const char* server_uri =
+      grpc_channel_args_find_string(args, GRPC_ARG_SERVER_URI);
+  GPR_ASSERT(server_uri != nullptr);
+  absl::StatusOr<URI> uri = URI::Parse(server_uri);
+  GPR_ASSERT(uri.ok() && !uri->path().empty());
+  return std::string(absl::StripPrefix(uri->path(), "/"));
+}
+
 GrpcLb::GrpcLb(Args args)
     : LoadBalancingPolicy(std::move(args)),
+      server_name_(GetServerNameFromChannelArgs(args.args)),
       response_generator_(MakeRefCounted<FakeResolverResponseGenerator>()),
+      lb_call_timeout_ms_(grpc_channel_args_find_integer(
+          args.args, GRPC_ARG_GRPCLB_CALL_TIMEOUT_MS, {0, 0, INT_MAX})),
       lb_call_backoff_(
           BackOff::Options()
               .set_initial_backoff(GRPC_GRPCLB_INITIAL_CONNECT_BACKOFF_SECONDS *
@@ -1326,31 +1365,25 @@ GrpcLb::GrpcLb(Args args)
               .set_multiplier(GRPC_GRPCLB_RECONNECT_BACKOFF_MULTIPLIER)
               .set_jitter(GRPC_GRPCLB_RECONNECT_JITTER)
               .set_max_backoff(GRPC_GRPCLB_RECONNECT_MAX_BACKOFF_SECONDS *
-                               1000)) {
-  // Closure Initialization
-  GRPC_CLOSURE_INIT(&lb_on_fallback_, &GrpcLb::OnFallbackTimer, this,
-                    grpc_schedule_on_exec_ctx);
-  GRPC_CLOSURE_INIT(&lb_on_call_retry_, &GrpcLb::OnBalancerCallRetryTimer, this,
-                    grpc_schedule_on_exec_ctx);
-  // Record server name.
-  const grpc_arg* arg = grpc_channel_args_find(args.args, GRPC_ARG_SERVER_URI);
-  const char* server_uri = grpc_channel_arg_get_string(arg);
-  GPR_ASSERT(server_uri != nullptr);
-  absl::StatusOr<URI> uri = URI::Parse(server_uri);
-  GPR_ASSERT(uri.ok() && !uri->path().empty());
-  server_name_ = std::string(absl::StripPrefix(uri->path(), "/"));
+                               1000)),
+      fallback_at_startup_timeout_(grpc_channel_args_find_integer(
+          args.args, GRPC_ARG_GRPCLB_FALLBACK_TIMEOUT_MS,
+          {GRPC_GRPCLB_DEFAULT_FALLBACK_TIMEOUT_MS, 0, INT_MAX})),
+      subchannel_cache_interval_ms_(grpc_channel_args_find_integer(
+          args.args, GRPC_ARG_GRPCLB_SUBCHANNEL_CACHE_INTERVAL_MS,
+          {GRPC_GRPCLB_DEFAULT_SUBCHANNEL_DELETION_DELAY_MS, 0, INT_MAX})) {
   if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
     gpr_log(GPR_INFO,
             "[grpclb %p] Will use '%s' as the server name for LB request.",
             this, server_name_.c_str());
   }
-  // Record LB call timeout.
-  arg = grpc_channel_args_find(args.args, GRPC_ARG_GRPCLB_CALL_TIMEOUT_MS);
-  lb_call_timeout_ms_ = grpc_channel_arg_get_integer(arg, {0, 0, INT_MAX});
-  // Record fallback-at-startup timeout.
-  arg = grpc_channel_args_find(args.args, GRPC_ARG_GRPCLB_FALLBACK_TIMEOUT_MS);
-  fallback_at_startup_timeout_ = grpc_channel_arg_get_integer(
-      arg, {GRPC_GRPCLB_DEFAULT_FALLBACK_TIMEOUT_MS, 0, INT_MAX});
+  // Closure Initialization
+  GRPC_CLOSURE_INIT(&lb_on_fallback_, &GrpcLb::OnFallbackTimer, this,
+                    grpc_schedule_on_exec_ctx);
+  GRPC_CLOSURE_INIT(&lb_on_call_retry_, &GrpcLb::OnBalancerCallRetryTimer, this,
+                    grpc_schedule_on_exec_ctx);
+  GRPC_CLOSURE_INIT(&on_subchannel_cache_timer_, &OnSubchannelCacheTimer, this,
+                    nullptr);
 }
 
 GrpcLb::~GrpcLb() { grpc_channel_args_destroy(args_); }
@@ -1358,6 +1391,11 @@ GrpcLb::~GrpcLb() { grpc_channel_args_destroy(args_); }
 void GrpcLb::ShutdownLocked() {
   shutting_down_ = true;
   lb_calld_.reset();
+  if (subchannel_cache_timer_pending_) {
+    subchannel_cache_timer_pending_ = false;
+    grpc_timer_cancel(&subchannel_cache_timer_);
+  }
+  cached_subchannels_.clear();
   if (retry_timer_callback_pending_) {
     grpc_timer_cancel(&lb_call_retry_timer_);
   }
@@ -1534,7 +1572,7 @@ void GrpcLb::StartBalancerCallRetryTimerLocked() {
 
 void GrpcLb::OnBalancerCallRetryTimer(void* arg, grpc_error_handle error) {
   GrpcLb* grpclb_policy = static_cast<GrpcLb*>(arg);
-  GRPC_ERROR_REF(error);  // ref owned by lambda
+  (void)GRPC_ERROR_REF(error);  // ref owned by lambda
   grpclb_policy->work_serializer()->Run(
       [grpclb_policy, error]() {
         grpclb_policy->OnBalancerCallRetryTimerLocked(error);
@@ -1578,7 +1616,7 @@ void GrpcLb::MaybeEnterFallbackModeAfterStartup() {
 
 void GrpcLb::OnFallbackTimer(void* arg, grpc_error_handle error) {
   GrpcLb* grpclb_policy = static_cast<GrpcLb*>(arg);
-  GRPC_ERROR_REF(error);  // ref owned by lambda
+  (void)GRPC_ERROR_REF(error);  // ref owned by lambda
   grpclb_policy->work_serializer()->Run(
       [grpclb_policy, error]() { grpclb_policy->OnFallbackTimerLocked(error); },
       DEBUG_LOCATION);
@@ -1675,6 +1713,57 @@ void GrpcLb::CreateOrUpdateChildPolicyLocked() {
 }
 
 //
+// subchannel caching
+//
+
+void GrpcLb::CacheDeletedSubchannelLocked(
+    RefCountedPtr<SubchannelInterface> subchannel) {
+  grpc_millis deletion_time =
+      ExecCtx::Get()->Now() + subchannel_cache_interval_ms_;
+  cached_subchannels_[deletion_time].push_back(std::move(subchannel));
+  if (!subchannel_cache_timer_pending_) {
+    Ref(DEBUG_LOCATION, "OnSubchannelCacheTimer").release();
+    subchannel_cache_timer_pending_ = true;
+    StartSubchannelCacheTimerLocked();
+  }
+}
+
+void GrpcLb::StartSubchannelCacheTimerLocked() {
+  GPR_ASSERT(!cached_subchannels_.empty());
+  grpc_timer_init(&subchannel_cache_timer_, cached_subchannels_.begin()->first,
+                  &on_subchannel_cache_timer_);
+}
+
+void GrpcLb::OnSubchannelCacheTimer(void* arg, grpc_error_handle error) {
+  auto* self = static_cast<GrpcLb*>(arg);
+  (void)GRPC_ERROR_REF(error);
+  self->work_serializer()->Run(
+      [self, error]() { self->GrpcLb::OnSubchannelCacheTimerLocked(error); },
+      DEBUG_LOCATION);
+}
+
+void GrpcLb::OnSubchannelCacheTimerLocked(grpc_error_handle error) {
+  if (subchannel_cache_timer_pending_ && error == GRPC_ERROR_NONE) {
+    auto it = cached_subchannels_.begin();
+    if (it != cached_subchannels_.end()) {
+      if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
+        gpr_log(GPR_INFO,
+                "[grpclb %p] removing %" PRIuPTR " subchannels from cache",
+                this, it->second.size());
+      }
+      cached_subchannels_.erase(it);
+    }
+    if (!cached_subchannels_.empty()) {
+      StartSubchannelCacheTimerLocked();
+      return;
+    }
+    subchannel_cache_timer_pending_ = false;
+  }
+  Unref(DEBUG_LOCATION, "OnSubchannelCacheTimer");
+  GRPC_ERROR_UNREF(error);
+}
+
+//
 // factory
 //
 
@@ -1744,39 +1833,34 @@ class GrpcLbFactory : public LoadBalancingPolicyFactory {
 // Plugin registration
 //
 
-namespace {
-
-// Only add client_load_reporting filter if the grpclb LB policy is used.
-bool maybe_add_client_load_reporting_filter(grpc_channel_stack_builder* builder,
-                                            void* arg) {
-  const grpc_channel_args* args =
-      grpc_channel_stack_builder_get_channel_arguments(builder);
-  const grpc_arg* channel_arg =
-      grpc_channel_args_find(args, GRPC_ARG_LB_POLICY_NAME);
-  if (channel_arg != nullptr && channel_arg->type == GRPC_ARG_STRING &&
-      strcmp(channel_arg->value.string, "grpclb") == 0) {
-    // TODO(roth): When we get around to re-attempting
-    // https://github.com/grpc/grpc/pull/16214, we should try to keep
-    // this filter at the very top of the subchannel stack, since that
-    // will minimize the number of metadata elements that the filter
-    // needs to iterate through to find the ClientStats object.
-    return grpc_channel_stack_builder_prepend_filter(
-        builder, static_cast<const grpc_channel_filter*>(arg), nullptr,
-        nullptr);
-  }
-  return true;
-}
-
-}  // namespace
-
 void grpc_lb_policy_grpclb_init() {
   grpc_core::LoadBalancingPolicyRegistry::Builder::
       RegisterLoadBalancingPolicyFactory(
           absl::make_unique<grpc_core::GrpcLbFactory>());
-  grpc_channel_init_register_stage(
-      GRPC_CLIENT_SUBCHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
-      maybe_add_client_load_reporting_filter,
-      const_cast<grpc_channel_filter*>(&grpc_client_load_reporting_filter));
 }
 
 void grpc_lb_policy_grpclb_shutdown() {}
+
+namespace grpc_core {
+void RegisterGrpcLbLoadReportingFilter(CoreConfiguration::Builder* builder) {
+  builder->channel_init()->RegisterStage(
+      GRPC_CLIENT_SUBCHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
+      [](grpc_channel_stack_builder* builder) {
+        const grpc_channel_args* args =
+            grpc_channel_stack_builder_get_channel_arguments(builder);
+        const grpc_arg* channel_arg =
+            grpc_channel_args_find(args, GRPC_ARG_LB_POLICY_NAME);
+        if (channel_arg != nullptr && channel_arg->type == GRPC_ARG_STRING &&
+            strcmp(channel_arg->value.string, "grpclb") == 0) {
+          // TODO(roth): When we get around to re-attempting
+          // https://github.com/grpc/grpc/pull/16214, we should try to keep
+          // this filter at the very top of the subchannel stack, since that
+          // will minimize the number of metadata elements that the filter
+          // needs to iterate through to find the ClientStats object.
+          return grpc_channel_stack_builder_prepend_filter(
+              builder, &grpc_client_load_reporting_filter, nullptr, nullptr);
+        }
+        return true;
+      });
+}
+}  // namespace grpc_core
index a032b5d..27e7a3a 100644 (file)
 #define GRPC_ARG_ADDRESS_IS_BACKEND_FROM_GRPCLB_LOAD_BALANCER \
   "grpc.address_is_backend_from_grpclb_load_balancer"
 
+// For use in tests.
+#define GRPC_ARG_GRPCLB_SUBCHANNEL_CACHE_INTERVAL_MS \
+  "grpc.internal.grpclb_subchannel_cache_interval_ms"
+
 namespace grpc_core {
 
 extern const char kGrpcLbClientStatsMetadataKey[];
index 0bd587a..8168d15 100644 (file)
@@ -42,7 +42,7 @@ int BalancerAddressesArgCmp(void* p, void* q) {
   ServerAddressList* address_list1 = static_cast<ServerAddressList*>(p);
   ServerAddressList* address_list2 = static_cast<ServerAddressList*>(q);
   if (address_list1 == nullptr || address_list2 == nullptr) {
-    return GPR_ICMP(address_list1, address_list2);
+    return QsortCompare(address_list1, address_list2);
   }
   if (address_list1->size() > address_list2->size()) return 1;
   if (address_list1->size() < address_list2->size()) return -1;
index 6213a5b..1d39768 100644 (file)
@@ -25,8 +25,6 @@
 
 #include <grpc/support/alloc.h>
 
-#include "src/core/lib/gpr/useful.h"
-
 namespace grpc_core {
 
 bool GrpcLbServer::operator==(const GrpcLbServer& other) const {
@@ -56,8 +54,8 @@ grpc_slice GrpcLbRequestCreate(const char* lb_service_name, upb_arena* arena) {
   grpc_lb_v1_LoadBalanceRequest* req = grpc_lb_v1_LoadBalanceRequest_new(arena);
   grpc_lb_v1_InitialLoadBalanceRequest* initial_request =
       grpc_lb_v1_LoadBalanceRequest_mutable_initial_request(req, arena);
-  size_t name_len =
-      GPR_MIN(strlen(lb_service_name), GRPC_GRPCLB_SERVICE_NAME_MAX_LENGTH);
+  size_t name_len = std::min(strlen(lb_service_name),
+                             size_t(GRPC_GRPCLB_SERVICE_NAME_MAX_LENGTH));
   grpc_lb_v1_InitialLoadBalanceRequest_set_name(
       initial_request, upb_strview_make(lb_service_name, name_len));
   return grpc_grpclb_request_encode(req, arena);
index ba38a9f..ad03e6c 100644 (file)
@@ -267,7 +267,7 @@ void PickFirst::UpdateLocked(UpdateArgs args) {
       const_cast<char*>(GRPC_ARG_INHIBIT_HEALTH_CHECKING), 1);
   const grpc_channel_args* new_args =
       grpc_channel_args_copy_and_add(args.args, &new_arg, 1);
-  GPR_SWAP(const grpc_channel_args*, new_args, args.args);
+  std::swap(new_args, args.args);
   grpc_channel_args_destroy(new_args);
   latest_update_args_ = std::move(args);
   // If we are not in idle, start connection attempt immediately.
@@ -377,15 +377,31 @@ void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked(
       sd = subchannel_list()->subchannel(next_index);
       // If we're tried all subchannels, set state to TRANSIENT_FAILURE.
       if (sd->Index() == 0) {
-        // Re-resolve if this is the most recent subchannel list.
-        if (subchannel_list() == (p->latest_pending_subchannel_list_ != nullptr
-                                      ? p->latest_pending_subchannel_list_.get()
-                                      : p->subchannel_list_.get())) {
-          p->channel_control_helper()->RequestReresolution();
+        if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_pick_first_trace)) {
+          gpr_log(GPR_INFO,
+                  "Pick First %p subchannel list %p failed to connect to "
+                  "all subchannels",
+                  p, subchannel_list());
         }
         subchannel_list()->set_in_transient_failure(true);
-        // Only report new state in case 1.
+        // In case 2, swap to the new subchannel list.  This means reporting
+        // TRANSIENT_FAILURE and dropping the existing (working) connection,
+        // but we can't ignore what the control plane has told us.
+        if (subchannel_list() == p->latest_pending_subchannel_list_.get()) {
+          if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_pick_first_trace)) {
+            gpr_log(GPR_INFO,
+                    "Pick First %p promoting pending subchannel list %p to "
+                    "replace %p",
+                    p, p->latest_pending_subchannel_list_.get(),
+                    p->subchannel_list_.get());
+          }
+          p->subchannel_list_ = std::move(p->latest_pending_subchannel_list_);
+        }
+        // If this is the current subchannel list (either because we were
+        // in case 1 or because we were in case 2 and just promoted it to
+        // be the current list), re-resolve and report new state.
         if (subchannel_list() == p->subchannel_list_.get()) {
+          p->channel_control_helper()->RequestReresolution();
           absl::Status status =
               absl::UnavailableError("failed to connect to all addresses");
           p->channel_control_helper()->UpdateState(
index a35ae2e..cb9fc3a 100644 (file)
@@ -162,6 +162,7 @@ class PriorityLb : public LoadBalancingPolicy {
                        const absl::Status& status,
                        std::unique_ptr<SubchannelPicker> picker) override;
       void RequestReresolution() override;
+      absl::string_view GetAuthority() override;
       void AddTraceEvent(TraceSeverity severity,
                          absl::string_view message) override;
 
@@ -656,7 +657,7 @@ void PriorityLb::ChildPriority::MaybeCancelFailoverTimerLocked() {
 void PriorityLb::ChildPriority::OnFailoverTimer(void* arg,
                                                 grpc_error_handle error) {
   ChildPriority* self = static_cast<ChildPriority*>(arg);
-  GRPC_ERROR_REF(error);  // ref owned by lambda
+  (void)GRPC_ERROR_REF(error);  // ref owned by lambda
   self->priority_policy_->work_serializer()->Run(
       [self, error]() { self->OnFailoverTimerLocked(error); }, DEBUG_LOCATION);
 }
@@ -713,7 +714,7 @@ void PriorityLb::ChildPriority::MaybeReactivateLocked() {
 void PriorityLb::ChildPriority::OnDeactivationTimer(void* arg,
                                                     grpc_error_handle error) {
   ChildPriority* self = static_cast<ChildPriority*>(arg);
-  GRPC_ERROR_REF(error);  // ref owned by lambda
+  (void)GRPC_ERROR_REF(error);  // ref owned by lambda
   self->priority_policy_->work_serializer()->Run(
       [self, error]() { self->OnDeactivationTimerLocked(error); },
       DEBUG_LOCATION);
@@ -740,14 +741,6 @@ void PriorityLb::ChildPriority::OnDeactivationTimerLocked(
 // PriorityLb::ChildPriority::Helper
 //
 
-void PriorityLb::ChildPriority::Helper::RequestReresolution() {
-  if (priority_->priority_policy_->shutting_down_) return;
-  if (priority_->ignore_reresolution_requests_) {
-    return;
-  }
-  priority_->priority_policy_->channel_control_helper()->RequestReresolution();
-}
-
 RefCountedPtr<SubchannelInterface>
 PriorityLb::ChildPriority::Helper::CreateSubchannel(
     ServerAddress address, const grpc_channel_args& args) {
@@ -764,6 +757,18 @@ void PriorityLb::ChildPriority::Helper::UpdateState(
   priority_->OnConnectivityStateUpdateLocked(state, status, std::move(picker));
 }
 
+void PriorityLb::ChildPriority::Helper::RequestReresolution() {
+  if (priority_->priority_policy_->shutting_down_) return;
+  if (priority_->ignore_reresolution_requests_) {
+    return;
+  }
+  priority_->priority_policy_->channel_control_helper()->RequestReresolution();
+}
+
+absl::string_view PriorityLb::ChildPriority::Helper::GetAuthority() {
+  return priority_->priority_policy_->channel_control_helper()->GetAuthority();
+}
+
 void PriorityLb::ChildPriority::Helper::AddTraceEvent(
     TraceSeverity severity, absl::string_view message) {
   if (priority_->priority_policy_->shutting_down_) return;
index cb291a3..3f954f2 100644 (file)
@@ -33,7 +33,6 @@
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/debug/trace.h"
 #include "src/core/lib/gpr/string.h"
-#include "src/core/lib/gpr/useful.h"
 #include "src/core/lib/gprpp/ref_counted_ptr.h"
 #include "src/core/lib/gprpp/sync.h"
 #include "src/core/lib/transport/connectivity_state.h"
@@ -236,7 +235,7 @@ class RingHash : public LoadBalancingPolicy {
       }
 
      private:
-      static void RunInExecCtx(void* arg, grpc_error* /*error*/) {
+      static void RunInExecCtx(void* arg, grpc_error_handle /*error*/) {
         auto* self = static_cast<SubchannelConnectionAttempter*>(arg);
         self->ring_hash_lb_->work_serializer()->Run(
             [self]() {
@@ -730,7 +729,7 @@ class RingHashFactory : public LoadBalancingPolicyFactory {
   const char* name() const override { return kRingHash; }
 
   RefCountedPtr<LoadBalancingPolicy::Config> ParseLoadBalancingConfig(
-      const Json& json, grpc_error** error) const override {
+      const Json& json, grpc_error_handle* error) const override {
     size_t min_ring_size;
     size_t max_ring_size;
     std::vector<grpc_error_handle> error_list;
diff --git a/src/core/ext/filters/client_channel/lb_policy/rls/rls.cc b/src/core/ext/filters/client_channel/lb_policy/rls/rls.cc
new file mode 100644 (file)
index 0000000..2b0483a
--- /dev/null
@@ -0,0 +1,2502 @@
+//
+// 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.
+//
+
+// Implementation of the Route Lookup Service (RLS) LB policy
+//
+// The policy queries a route lookup service for the name of the actual service
+// to use. A child policy that recognizes the name as a field of its
+// configuration will take further load balancing action on the request.
+
+#include <grpc/support/port_platform.h>
+
+#include <stdlib.h>
+
+#include <algorithm>
+#include <deque>
+#include <functional>
+#include <list>
+#include <map>
+#include <string>
+#include <unordered_map>
+#include <utility>
+
+#include "absl/container/inlined_vector.h"
+#include "absl/hash/hash.h"
+#include "absl/memory/memory.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_join.h"
+#include "absl/strings/string_view.h"
+#include "absl/strings/strip.h"
+#include "upb/upb.hpp"
+
+#include <grpc/grpc_security.h>
+#include <grpc/impl/codegen/byte_buffer_reader.h>
+#include <grpc/impl/codegen/grpc_types.h>
+#include <grpc/support/time.h>
+
+#include "src/core/ext/filters/client_channel/client_channel.h"
+#include "src/core/ext/filters/client_channel/lb_policy.h"
+#include "src/core/ext/filters/client_channel/lb_policy/child_policy_handler.h"
+#include "src/core/ext/filters/client_channel/lb_policy_factory.h"
+#include "src/core/ext/filters/client_channel/lb_policy_registry.h"
+#include "src/core/ext/filters/client_channel/resolver_registry.h"
+#include "src/core/lib/backoff/backoff.h"
+#include "src/core/lib/gpr/env.h"
+#include "src/core/lib/gpr/string.h"
+#include "src/core/lib/gprpp/dual_ref_counted.h"
+#include "src/core/lib/gprpp/orphanable.h"
+#include "src/core/lib/gprpp/ref_counted.h"
+#include "src/core/lib/gprpp/sync.h"
+#include "src/core/lib/iomgr/exec_ctx.h"
+#include "src/core/lib/iomgr/timer.h"
+#include "src/core/lib/json/json.h"
+#include "src/core/lib/json/json_util.h"
+#include "src/core/lib/security/credentials/credentials.h"
+#include "src/core/lib/security/credentials/fake/fake_credentials.h"
+#include "src/core/lib/surface/call.h"
+#include "src/core/lib/surface/channel.h"
+#include "src/core/lib/transport/connectivity_state.h"
+#include "src/core/lib/transport/error_utils.h"
+#include "src/core/lib/transport/static_metadata.h"
+#include "src/core/lib/uri/uri_parser.h"
+#include "src/proto/grpc/lookup/v1/rls.upb.h"
+
+namespace grpc_core {
+
+TraceFlag grpc_lb_rls_trace(false, "rls_lb");
+
+namespace {
+
+const char* kRls = "rls";
+const char kGrpc[] = "grpc";
+const char* kRlsRequestPath = "/grpc.lookup.v1.RouteLookupService/RouteLookup";
+const char* kFakeTargetFieldValue = "fake_target_field_value";
+const char* kRlsHeaderKey = "X-Google-RLS-Data";
+
+const grpc_millis kDefaultLookupServiceTimeout = 10000;
+const grpc_millis kMaxMaxAge = 5 * 60 * GPR_MS_PER_SEC;
+const grpc_millis kMinExpirationTime = 5 * GPR_MS_PER_SEC;
+const grpc_millis kCacheBackoffInitial = 1 * GPR_MS_PER_SEC;
+const double kCacheBackoffMultiplier = 1.6;
+const double kCacheBackoffJitter = 0.2;
+const grpc_millis kCacheBackoffMax = 120 * GPR_MS_PER_SEC;
+const grpc_millis kDefaultThrottleWindowSize = 30 * GPR_MS_PER_SEC;
+const double kDefaultThrottleRatioForSuccesses = 2.0;
+const int kDefaultThrottlePaddings = 8;
+const grpc_millis kCacheCleanupTimerInterval = 60 * GPR_MS_PER_SEC;
+const int64_t kMaxCacheSizeBytes = 5 * 1024 * 1024;
+
+// Parsed RLS LB policy configuration.
+class RlsLbConfig : public LoadBalancingPolicy::Config {
+ public:
+  struct KeyBuilder {
+    std::map<std::string /*key*/, std::vector<std::string /*header*/>>
+        header_keys;
+    std::string host_key;
+    std::string service_key;
+    std::string method_key;
+    std::map<std::string /*key*/, std::string /*value*/> constant_keys;
+  };
+  using KeyBuilderMap = std::unordered_map<std::string /*path*/, KeyBuilder>;
+
+  struct RouteLookupConfig {
+    KeyBuilderMap key_builder_map;
+    std::string lookup_service;
+    grpc_millis lookup_service_timeout = 0;
+    grpc_millis max_age = 0;
+    grpc_millis stale_age = 0;
+    int64_t cache_size_bytes = 0;
+    std::string default_target;
+  };
+
+  RlsLbConfig(RouteLookupConfig route_lookup_config, Json child_policy_config,
+              std::string child_policy_config_target_field_name,
+              RefCountedPtr<LoadBalancingPolicy::Config>
+                  default_child_policy_parsed_config)
+      : route_lookup_config_(std::move(route_lookup_config)),
+        child_policy_config_(std::move(child_policy_config)),
+        child_policy_config_target_field_name_(
+            std::move(child_policy_config_target_field_name)),
+        default_child_policy_parsed_config_(
+            std::move(default_child_policy_parsed_config)) {}
+
+  const char* name() const override { return kRls; }
+
+  const KeyBuilderMap& key_builder_map() const {
+    return route_lookup_config_.key_builder_map;
+  }
+  const std::string& lookup_service() const {
+    return route_lookup_config_.lookup_service;
+  }
+  grpc_millis lookup_service_timeout() const {
+    return route_lookup_config_.lookup_service_timeout;
+  }
+  grpc_millis max_age() const { return route_lookup_config_.max_age; }
+  grpc_millis stale_age() const { return route_lookup_config_.stale_age; }
+  int64_t cache_size_bytes() const {
+    return route_lookup_config_.cache_size_bytes;
+  }
+  const std::string& default_target() const {
+    return route_lookup_config_.default_target;
+  }
+  const Json& child_policy_config() const { return child_policy_config_; }
+  const std::string& child_policy_config_target_field_name() const {
+    return child_policy_config_target_field_name_;
+  }
+  RefCountedPtr<LoadBalancingPolicy::Config>
+  default_child_policy_parsed_config() const {
+    return default_child_policy_parsed_config_;
+  }
+
+ private:
+  RouteLookupConfig route_lookup_config_;
+  Json child_policy_config_;
+  std::string child_policy_config_target_field_name_;
+  RefCountedPtr<LoadBalancingPolicy::Config>
+      default_child_policy_parsed_config_;
+};
+
+// RLS LB policy.
+class RlsLb : public LoadBalancingPolicy {
+ public:
+  explicit RlsLb(Args args);
+
+  const char* name() const override { return kRls; }
+  void UpdateLocked(UpdateArgs args) override;
+  void ExitIdleLocked() override;
+  void ResetBackoffLocked() override;
+
+ private:
+  // Key to access entries in the cache and the request map.
+  struct RequestKey {
+    std::map<std::string, std::string> key_map;
+
+    bool operator==(const RequestKey& rhs) const {
+      return key_map == rhs.key_map;
+    }
+
+    template <typename H>
+    friend H AbslHashValue(H h, const RequestKey& key) {
+      std::hash<std::string> string_hasher;
+      for (auto& kv : key.key_map) {
+        h = H::combine(std::move(h), string_hasher(kv.first),
+                       string_hasher(kv.second));
+      }
+      return h;
+    }
+
+    size_t Size() const {
+      size_t size = sizeof(RequestKey);
+      for (auto& kv : key_map) {
+        size += kv.first.length() + kv.second.length();
+      }
+      return size;
+    }
+
+    std::string ToString() const {
+      return absl::StrCat(
+          "{", absl::StrJoin(key_map, ",", absl::PairFormatter("=")), "}");
+    }
+  };
+
+  // Data from an RLS response.
+  struct ResponseInfo {
+    absl::Status status;
+    std::vector<std::string> targets;
+    std::string header_data;
+
+    std::string ToString() const {
+      return absl::StrFormat("{status=%s, targets=[%s], header_data=\"%s\"}",
+                             status.ToString(), absl::StrJoin(targets, ","),
+                             header_data);
+    }
+  };
+
+  // Wraps a child policy for a given RLS target.
+  class ChildPolicyWrapper : public DualRefCounted<ChildPolicyWrapper> {
+   public:
+    ChildPolicyWrapper(RefCountedPtr<RlsLb> lb_policy, std::string target);
+
+    // Note: We are forced to disable lock analysis here because
+    // Orphan() is called by OrphanablePtr<>, which cannot have lock
+    // annotations for this particular caller.
+    void Orphan() override ABSL_NO_THREAD_SAFETY_ANALYSIS;
+
+    const std::string& target() const { return target_; }
+
+    PickResult Pick(PickArgs args) ABSL_EXCLUSIVE_LOCKS_REQUIRED(&RlsLb::mu_) {
+      return picker_->Pick(args);
+    }
+
+    // Updates for the child policy are handled in two phases:
+    // 1. In StartUpdate(), we parse and validate the new child policy
+    //    config and store the parsed config.
+    // 2. In MaybeFinishUpdate(), we actually pass the parsed config to the
+    //    child policy's UpdateLocked() method.
+    //
+    // The reason we do this is to avoid deadlocks.  In StartUpdate(),
+    // if the new config fails to validate, then we need to set
+    // picker_ to an instance that will fail all requests, which
+    // requires holding the lock.  However, we cannot call the child
+    // policy's UpdateLocked() method from MaybeFinishUpdate() while
+    // holding the lock, since that would cause a deadlock: the child's
+    // UpdateLocked() will call the helper's UpdateState() method, which
+    // will try to acquire the lock to set picker_.  So StartUpdate() is
+    // called while we are still holding the lock, but MaybeFinishUpdate()
+    // is called after releasing it.
+    //
+    // Both methods grab the data they need from the parent object.
+    void StartUpdate() ABSL_EXCLUSIVE_LOCKS_REQUIRED(&RlsLb::mu_);
+    // Does not take ownership of channel_args.
+    void MaybeFinishUpdate() ABSL_LOCKS_EXCLUDED(&RlsLb::mu_);
+
+    void ExitIdleLocked() {
+      if (child_policy_ != nullptr) child_policy_->ExitIdleLocked();
+    }
+
+    void ResetBackoffLocked() {
+      if (child_policy_ != nullptr) child_policy_->ResetBackoffLocked();
+    }
+
+    // Gets the connectivity state of the child policy. Once the child policy
+    // reports TRANSIENT_FAILURE, the function will always return
+    // TRANSIENT_FAILURE state instead of the actual state of the child policy
+    // until the child policy reports another READY state.
+    grpc_connectivity_state connectivity_state() const
+        ABSL_EXCLUSIVE_LOCKS_REQUIRED(&RlsLb::mu_) {
+      return connectivity_state_;
+    }
+
+   private:
+    // ChannelControlHelper object that allows the child policy to update state
+    // with the wrapper.
+    class ChildPolicyHelper : public LoadBalancingPolicy::ChannelControlHelper {
+     public:
+      explicit ChildPolicyHelper(WeakRefCountedPtr<ChildPolicyWrapper> wrapper)
+          : wrapper_(std::move(wrapper)) {}
+      ~ChildPolicyHelper() override {
+        wrapper_.reset(DEBUG_LOCATION, "ChildPolicyHelper");
+      }
+
+      RefCountedPtr<SubchannelInterface> CreateSubchannel(
+          ServerAddress address, const grpc_channel_args& args) override;
+      void UpdateState(grpc_connectivity_state state,
+                       const absl::Status& status,
+                       std::unique_ptr<SubchannelPicker> picker) override;
+      void RequestReresolution() override;
+      absl::string_view GetAuthority() override;
+      void AddTraceEvent(TraceSeverity severity,
+                         absl::string_view message) override;
+
+     private:
+      WeakRefCountedPtr<ChildPolicyWrapper> wrapper_;
+    };
+
+    RefCountedPtr<RlsLb> lb_policy_;
+    std::string target_;
+
+    bool is_shutdown_ = false;
+
+    OrphanablePtr<ChildPolicyHandler> child_policy_;
+    RefCountedPtr<LoadBalancingPolicy::Config> pending_config_;
+
+    grpc_connectivity_state connectivity_state_ ABSL_GUARDED_BY(&RlsLb::mu_) =
+        GRPC_CHANNEL_IDLE;
+    std::unique_ptr<LoadBalancingPolicy::SubchannelPicker> picker_
+        ABSL_GUARDED_BY(&RlsLb::mu_);
+  };
+
+  // A picker that uses the cache and the request map in the LB policy
+  // (synchronized via a mutex) to determine how to route requests.
+  class Picker : public LoadBalancingPolicy::SubchannelPicker {
+   public:
+    explicit Picker(RefCountedPtr<RlsLb> lb_policy);
+    ~Picker() override;
+
+    PickResult Pick(PickArgs args) override;
+
+   private:
+    RefCountedPtr<RlsLb> lb_policy_;
+    RefCountedPtr<RlsLbConfig> config_;
+    RefCountedPtr<ChildPolicyWrapper> default_child_policy_;
+  };
+
+  // An LRU cache with adjustable size.
+  class Cache {
+   public:
+    using Iterator = std::list<RequestKey>::iterator;
+
+    class Entry : public InternallyRefCounted<Entry> {
+     public:
+      Entry(RefCountedPtr<RlsLb> lb_policy, const RequestKey& key);
+
+      // Notify the entry when it's evicted from the cache. Performs shut down.
+      // Note: We are forced to disable lock analysis here because
+      // Orphan() is called by OrphanablePtr<>, which cannot have lock
+      // annotations for this particular caller.
+      void Orphan() override ABSL_NO_THREAD_SAFETY_ANALYSIS;
+
+      const absl::Status& status() const
+          ABSL_EXCLUSIVE_LOCKS_REQUIRED(&RlsLb::mu_) {
+        return status_;
+      }
+      grpc_millis backoff_time() const
+          ABSL_EXCLUSIVE_LOCKS_REQUIRED(&RlsLb::mu_) {
+        return backoff_time_;
+      }
+      grpc_millis backoff_expiration_time() const
+          ABSL_EXCLUSIVE_LOCKS_REQUIRED(&RlsLb::mu_) {
+        return backoff_expiration_time_;
+      }
+      grpc_millis data_expiration_time() const
+          ABSL_EXCLUSIVE_LOCKS_REQUIRED(&RlsLb::mu_) {
+        return data_expiration_time_;
+      }
+      const std::string& header_data() const
+          ABSL_EXCLUSIVE_LOCKS_REQUIRED(&RlsLb::mu_) {
+        return header_data_;
+      }
+      grpc_millis stale_time() const
+          ABSL_EXCLUSIVE_LOCKS_REQUIRED(&RlsLb::mu_) {
+        return stale_time_;
+      }
+      grpc_millis min_expiration_time() const
+          ABSL_EXCLUSIVE_LOCKS_REQUIRED(&RlsLb::mu_) {
+        return min_expiration_time_;
+      }
+
+      std::unique_ptr<BackOff> TakeBackoffState()
+          ABSL_EXCLUSIVE_LOCKS_REQUIRED(&RlsLb::mu_) {
+        return std::move(backoff_state_);
+      }
+
+      // Cache size of entry.
+      size_t Size() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(&RlsLb::mu_);
+
+      // Pick subchannel for request based on the entry's state.
+      PickResult Pick(PickArgs args) ABSL_EXCLUSIVE_LOCKS_REQUIRED(&RlsLb::mu_);
+
+      // If the cache entry is in backoff state, resets the backoff and, if
+      // applicable, its backoff timer. The method does not update the LB
+      // policy's picker; the caller is responsible for that if necessary.
+      void ResetBackoff() ABSL_EXCLUSIVE_LOCKS_REQUIRED(&RlsLb::mu_);
+
+      // Check if the entry should be removed by the clean-up timer.
+      bool ShouldRemove() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(&RlsLb::mu_);
+
+      // Check if the entry can be evicted from the cache, i.e. the
+      // min_expiration_time_ has passed.
+      bool CanEvict() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(&RlsLb::mu_);
+
+      // Updates the entry upon reception of a new RLS response.
+      // Returns a list of child policy wrappers on which FinishUpdate()
+      // needs to be called after releasing the lock.
+      std::vector<ChildPolicyWrapper*> OnRlsResponseLocked(
+          ResponseInfo response, std::unique_ptr<BackOff> backoff_state)
+          ABSL_EXCLUSIVE_LOCKS_REQUIRED(&RlsLb::mu_);
+
+      // Moves entry to the end of the LRU list.
+      void MarkUsed() ABSL_EXCLUSIVE_LOCKS_REQUIRED(&RlsLb::mu_);
+
+     private:
+      class BackoffTimer : public InternallyRefCounted<BackoffTimer> {
+       public:
+        BackoffTimer(RefCountedPtr<Entry> entry, grpc_millis backoff_time);
+
+        // Note: We are forced to disable lock analysis here because
+        // Orphan() is called by OrphanablePtr<>, which cannot have lock
+        // annotations for this particular caller.
+        void Orphan() override ABSL_NO_THREAD_SAFETY_ANALYSIS;
+
+       private:
+        static void OnBackoffTimer(void* args, grpc_error_handle error);
+
+        RefCountedPtr<Entry> entry_;
+        bool armed_ ABSL_GUARDED_BY(&RlsLb::mu_) = true;
+        grpc_timer backoff_timer_;
+        grpc_closure backoff_timer_callback_;
+      };
+
+      RefCountedPtr<RlsLb> lb_policy_;
+
+      bool is_shutdown_ ABSL_GUARDED_BY(&RlsLb::mu_) = false;
+
+      // Backoff states
+      absl::Status status_ ABSL_GUARDED_BY(&RlsLb::mu_);
+      std::unique_ptr<BackOff> backoff_state_ ABSL_GUARDED_BY(&RlsLb::mu_);
+      grpc_millis backoff_time_ ABSL_GUARDED_BY(&RlsLb::mu_) =
+          GRPC_MILLIS_INF_PAST;
+      grpc_millis backoff_expiration_time_ ABSL_GUARDED_BY(&RlsLb::mu_) =
+          GRPC_MILLIS_INF_PAST;
+      OrphanablePtr<BackoffTimer> backoff_timer_;
+
+      // RLS response states
+      std::vector<RefCountedPtr<ChildPolicyWrapper>> child_policy_wrappers_
+          ABSL_GUARDED_BY(&RlsLb::mu_);
+      std::string header_data_ ABSL_GUARDED_BY(&RlsLb::mu_);
+      grpc_millis data_expiration_time_ ABSL_GUARDED_BY(&RlsLb::mu_) =
+          GRPC_MILLIS_INF_PAST;
+      grpc_millis stale_time_ ABSL_GUARDED_BY(&RlsLb::mu_) =
+          GRPC_MILLIS_INF_PAST;
+
+      grpc_millis min_expiration_time_ ABSL_GUARDED_BY(&RlsLb::mu_);
+      Cache::Iterator lru_iterator_ ABSL_GUARDED_BY(&RlsLb::mu_);
+    };
+
+    explicit Cache(RlsLb* lb_policy);
+
+    // Finds an entry from the cache that corresponds to a key. If an entry is
+    // not found, nullptr is returned. Otherwise, the entry is considered
+    // recently used and its order in the LRU list of the cache is updated.
+    Entry* Find(const RequestKey& key)
+        ABSL_EXCLUSIVE_LOCKS_REQUIRED(&RlsLb::mu_);
+
+    // Finds an entry from the cache that corresponds to a key. If an entry is
+    // not found, an entry is created, inserted in the cache, and returned to
+    // the caller. Otherwise, the entry found is returned to the caller. The
+    // entry returned to the user is considered recently used and its order in
+    // the LRU list of the cache is updated.
+    Entry* FindOrInsert(const RequestKey& key)
+        ABSL_EXCLUSIVE_LOCKS_REQUIRED(&RlsLb::mu_);
+
+    // Resizes the cache. If the new cache size is greater than the current size
+    // of the cache, do nothing. Otherwise, evict the oldest entries that
+    // exceed the new size limit of the cache.
+    void Resize(size_t bytes) ABSL_EXCLUSIVE_LOCKS_REQUIRED(&RlsLb::mu_);
+
+    // Resets backoff of all the cache entries.
+    void ResetAllBackoff() ABSL_EXCLUSIVE_LOCKS_REQUIRED(&RlsLb::mu_);
+
+    // Shutdown the cache; clean-up and orphan all the stored cache entries.
+    void Shutdown() ABSL_EXCLUSIVE_LOCKS_REQUIRED(&RlsLb::mu_);
+
+   private:
+    static void OnCleanupTimer(void* arg, grpc_error_handle error);
+
+    // Returns the entry size for a given key.
+    static size_t EntrySizeForKey(const RequestKey& key);
+
+    // Evicts oversized cache elements when the current size is greater than
+    // the specified limit.
+    void MaybeShrinkSize(size_t bytes)
+        ABSL_EXCLUSIVE_LOCKS_REQUIRED(&RlsLb::mu_);
+
+    RlsLb* lb_policy_;
+
+    size_t size_limit_ ABSL_GUARDED_BY(&RlsLb::mu_) = 0;
+    size_t size_ ABSL_GUARDED_BY(&RlsLb::mu_) = 0;
+
+    std::list<RequestKey> lru_list_ ABSL_GUARDED_BY(&RlsLb::mu_);
+    std::unordered_map<RequestKey, OrphanablePtr<Entry>, absl::Hash<RequestKey>>
+        map_ ABSL_GUARDED_BY(&RlsLb::mu_);
+    grpc_timer cleanup_timer_;
+    grpc_closure timer_callback_;
+  };
+
+  // Channel for communicating with the RLS server.
+  // Contains throttling logic for RLS requests.
+  class RlsChannel : public InternallyRefCounted<RlsChannel> {
+   public:
+    RlsChannel(RefCountedPtr<RlsLb> lb_policy, const std::string& target,
+               const grpc_channel_args* parent_channel_args);
+
+    // Shuts down the channel.
+    void Orphan() override;
+
+    // Starts an RLS call.
+    // If stale_entry is non-null, it points to the entry containing
+    // stale data for the key.
+    void StartRlsCall(const RequestKey& key, Cache::Entry* stale_entry)
+        ABSL_EXCLUSIVE_LOCKS_REQUIRED(&RlsLb::mu_);
+
+    // Reports the result of an RLS call to the throttle.
+    void ReportResponseLocked(bool response_succeeded)
+        ABSL_EXCLUSIVE_LOCKS_REQUIRED(&RlsLb::mu_);
+
+    // Checks if a proposed RLS call should be throttled.
+    bool ShouldThrottle() ABSL_EXCLUSIVE_LOCKS_REQUIRED(&RlsLb::mu_) {
+      return throttle_.ShouldThrottle();
+    }
+
+    // Resets the channel's backoff.
+    void ResetBackoff();
+
+    grpc_channel* channel() const { return channel_; }
+
+   private:
+    // Watches the state of the RLS channel. Notifies the LB policy when
+    // the channel was previously in TRANSIENT_FAILURE and then becomes READY.
+    class StateWatcher : public AsyncConnectivityStateWatcherInterface {
+     public:
+      explicit StateWatcher(RefCountedPtr<RlsChannel> rls_channel)
+          : AsyncConnectivityStateWatcherInterface(
+                rls_channel->lb_policy_->work_serializer()),
+            rls_channel_(std::move(rls_channel)) {}
+
+     private:
+      void OnConnectivityStateChange(grpc_connectivity_state new_state,
+                                     const absl::Status& status) override;
+
+      RefCountedPtr<RlsChannel> rls_channel_;
+      bool was_transient_failure_ = false;
+    };
+
+    // Throttle state for RLS requests.
+    class Throttle {
+     public:
+      explicit Throttle(int window_size_seconds = 0,
+                        double ratio_for_successes = 0, int paddings = 0);
+
+      bool ShouldThrottle() ABSL_EXCLUSIVE_LOCKS_REQUIRED(&RlsLb::mu_);
+
+      void RegisterResponse(bool success)
+          ABSL_EXCLUSIVE_LOCKS_REQUIRED(&RlsLb::mu_);
+
+     private:
+      grpc_millis window_size_;
+      double ratio_for_successes_;
+      int paddings_;
+
+      // Logged timestamp of requests.
+      std::deque<grpc_millis> requests_ ABSL_GUARDED_BY(&RlsLb::mu_);
+
+      // Logged timestamp of responses that were successful.
+      std::deque<grpc_millis> successes_ ABSL_GUARDED_BY(&RlsLb::mu_);
+    };
+
+    RefCountedPtr<RlsLb> lb_policy_;
+    bool is_shutdown_ = false;
+
+    grpc_channel* channel_ = nullptr;
+    RefCountedPtr<channelz::ChannelNode> parent_channelz_node_;
+    StateWatcher* watcher_ = nullptr;
+    Throttle throttle_ ABSL_GUARDED_BY(&RlsLb::mu_);
+  };
+
+  // A pending RLS request.  Instances will be tracked in request_map_.
+  class RlsRequest : public InternallyRefCounted<RlsRequest> {
+   public:
+    // Asynchronously starts a call on rls_channel for key.
+    // Stores backoff_state, which will be transferred to the data cache
+    // if the RLS request fails.
+    RlsRequest(RefCountedPtr<RlsLb> lb_policy, RlsLb::RequestKey key,
+               RefCountedPtr<RlsChannel> rls_channel,
+               std::unique_ptr<BackOff> backoff_state,
+               grpc_lookup_v1_RouteLookupRequest_Reason reason,
+               std::string stale_header_data);
+    ~RlsRequest() override;
+
+    // Shuts down the request.  If the request is still in flight, it is
+    // cancelled, in which case no response will be added to the cache.
+    void Orphan() override;
+
+   private:
+    // Callback to be invoked to start the call.
+    static void StartCall(void* arg, grpc_error_handle error);
+
+    // Helper for StartCall() that runs within the WorkSerializer.
+    void StartCallLocked();
+
+    // Callback to be invoked when the call is completed.
+    static void OnRlsCallComplete(void* arg, grpc_error_handle error);
+
+    // Call completion callback running on LB policy WorkSerializer.
+    void OnRlsCallCompleteLocked(grpc_error_handle error);
+
+    grpc_byte_buffer* MakeRequestProto();
+    ResponseInfo ParseResponseProto();
+
+    RefCountedPtr<RlsLb> lb_policy_;
+    RlsLb::RequestKey key_;
+    RefCountedPtr<RlsChannel> rls_channel_;
+    std::unique_ptr<BackOff> backoff_state_;
+    grpc_lookup_v1_RouteLookupRequest_Reason reason_;
+    std::string stale_header_data_;
+
+    // RLS call state.
+    grpc_millis deadline_;
+    grpc_closure call_start_cb_;
+    grpc_closure call_complete_cb_;
+    grpc_call* call_ = nullptr;
+    grpc_byte_buffer* send_message_ = nullptr;
+    grpc_metadata_array recv_initial_metadata_;
+    grpc_byte_buffer* recv_message_ = nullptr;
+    grpc_metadata_array recv_trailing_metadata_;
+    grpc_status_code status_recv_;
+    grpc_slice status_details_recv_;
+  };
+
+  void ShutdownLocked() override;
+
+  // Returns a new picker to the channel to trigger reprocessing of
+  // pending picks.  Schedules the actual picker update on the ExecCtx
+  // to be run later, so it's safe to invoke this while holding the lock.
+  void UpdatePickerAsync();
+  // Hops into work serializer and calls UpdatePickerLocked().
+  static void UpdatePickerCallback(void* arg, grpc_error_handle error);
+  // Updates the picker in the work serializer.
+  void UpdatePickerLocked() ABSL_LOCKS_EXCLUDED(&mu_);
+
+  // The name of the server for the channel.
+  std::string server_name_;
+
+  // Mutex to guard LB policy state that is accessed by the picker.
+  Mutex mu_;
+  bool is_shutdown_ ABSL_GUARDED_BY(mu_) = false;
+  Cache cache_ ABSL_GUARDED_BY(mu_);
+  // Maps an RLS request key to an RlsRequest object that represents a pending
+  // RLS request.
+  std::unordered_map<RequestKey, OrphanablePtr<RlsRequest>,
+                     absl::Hash<RequestKey>>
+      request_map_ ABSL_GUARDED_BY(mu_);
+  // The channel on which RLS requests are sent.
+  // Note that this channel may be swapped out when the RLS policy gets
+  // an update.  However, when that happens, any existing entries in
+  // request_map_ will continue to use the previous channel.
+  OrphanablePtr<RlsChannel> rls_channel_ ABSL_GUARDED_BY(mu_);
+
+  // Accessed only from within WorkSerializer.
+  ServerAddressList addresses_;
+  const grpc_channel_args* channel_args_ = nullptr;
+  RefCountedPtr<RlsLbConfig> config_;
+  RefCountedPtr<ChildPolicyWrapper> default_child_policy_;
+  std::map<std::string /*target*/, ChildPolicyWrapper*> child_policy_map_;
+};
+
+//
+// RlsLb::ChildPolicyWrapper
+//
+
+RlsLb::ChildPolicyWrapper::ChildPolicyWrapper(RefCountedPtr<RlsLb> lb_policy,
+                                              std::string target)
+    : DualRefCounted<ChildPolicyWrapper>(
+          GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace) ? "ChildPolicyWrapper"
+                                                     : nullptr),
+      lb_policy_(lb_policy),
+      target_(std::move(target)),
+      picker_(absl::make_unique<QueuePicker>(std::move(lb_policy))) {
+  lb_policy_->child_policy_map_.emplace(target_, this);
+}
+
+void RlsLb::ChildPolicyWrapper::Orphan() {
+  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
+    gpr_log(GPR_INFO, "[rlslb %p] ChildPolicyWrapper=%p [%s]: shutdown",
+            lb_policy_.get(), this, target_.c_str());
+  }
+  is_shutdown_ = true;
+  lb_policy_->child_policy_map_.erase(target_);
+  if (child_policy_ != nullptr) {
+    grpc_pollset_set_del_pollset_set(child_policy_->interested_parties(),
+                                     lb_policy_->interested_parties());
+    child_policy_.reset();
+  }
+  picker_.reset();
+}
+
+grpc_error_handle InsertOrUpdateChildPolicyField(const std::string& field,
+                                                 const std::string& value,
+                                                 Json* config) {
+  if (config->type() != Json::Type::ARRAY) {
+    return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+        "child policy configuration is not an array");
+  }
+  std::vector<grpc_error_handle> error_list;
+  for (Json& child_json : *config->mutable_array()) {
+    if (child_json.type() != Json::Type::OBJECT) {
+      error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+          "child policy item is not an object"));
+    } else {
+      Json::Object& child = *child_json.mutable_object();
+      if (child.size() != 1) {
+        error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+            "child policy item contains more than one field"));
+      } else {
+        Json& child_config_json = child.begin()->second;
+        if (child_config_json.type() != Json::Type::OBJECT) {
+          error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+              "child policy item config is not an object"));
+        } else {
+          Json::Object& child_config = *child_config_json.mutable_object();
+          child_config[field] = Json(value);
+        }
+      }
+    }
+  }
+  return GRPC_ERROR_CREATE_FROM_VECTOR_AND_CPP_STRING(
+      absl::StrCat("errors when inserting field \"", field,
+                   "\" for child policy"),
+      &error_list);
+}
+
+void RlsLb::ChildPolicyWrapper::StartUpdate() {
+  Json child_policy_config = lb_policy_->config_->child_policy_config();
+  grpc_error_handle error = InsertOrUpdateChildPolicyField(
+      lb_policy_->config_->child_policy_config_target_field_name(), target_,
+      &child_policy_config);
+  GPR_ASSERT(error == GRPC_ERROR_NONE);
+  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
+    gpr_log(
+        GPR_INFO,
+        "[rlslb %p] ChildPolicyWrapper=%p [%s]: validating update, config: %s",
+        lb_policy_.get(), this, target_.c_str(),
+        child_policy_config.Dump().c_str());
+  }
+  pending_config_ = LoadBalancingPolicyRegistry::ParseLoadBalancingConfig(
+      child_policy_config, &error);
+  // Returned RLS target fails the validation.
+  if (error != GRPC_ERROR_NONE) {
+    if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
+      gpr_log(GPR_INFO,
+              "[rlslb %p] ChildPolicyWrapper=%p [%s]: config failed to parse: "
+              "%s; config: %s",
+              lb_policy_.get(), this, target_.c_str(),
+              grpc_error_std_string(error).c_str(),
+              child_policy_config.Dump().c_str());
+    }
+    pending_config_.reset();
+    picker_ = absl::make_unique<TransientFailurePicker>(
+        grpc_error_to_absl_status(error));
+    GRPC_ERROR_UNREF(error);
+    child_policy_.reset();
+  }
+}
+
+void RlsLb::ChildPolicyWrapper::MaybeFinishUpdate() {
+  // If pending_config_ is not set, that means StartUpdate() failed, so
+  // there's nothing to do here.
+  if (pending_config_ == nullptr) return;
+  // If child policy doesn't yet exist, create it.
+  if (child_policy_ == nullptr) {
+    Args create_args;
+    create_args.work_serializer = lb_policy_->work_serializer();
+    create_args.channel_control_helper = absl::make_unique<ChildPolicyHelper>(
+        WeakRef(DEBUG_LOCATION, "ChildPolicyHelper"));
+    create_args.args = lb_policy_->channel_args_;
+    child_policy_ = MakeOrphanable<ChildPolicyHandler>(std::move(create_args),
+                                                       &grpc_lb_rls_trace);
+    if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
+      gpr_log(GPR_INFO,
+              "[rlslb %p] ChildPolicyWrapper=%p [%s], created new child policy "
+              "handler %p",
+              lb_policy_.get(), this, target_.c_str(), child_policy_.get());
+    }
+    grpc_pollset_set_add_pollset_set(child_policy_->interested_parties(),
+                                     lb_policy_->interested_parties());
+  }
+  // Send the child the updated config.
+  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
+    gpr_log(GPR_INFO,
+            "[rlslb %p] ChildPolicyWrapper=%p [%s], updating child policy "
+            "handler %p",
+            lb_policy_.get(), this, target_.c_str(), child_policy_.get());
+  }
+  UpdateArgs update_args;
+  update_args.config = std::move(pending_config_);
+  update_args.addresses = lb_policy_->addresses_;
+  update_args.args = grpc_channel_args_copy(lb_policy_->channel_args_);
+  child_policy_->UpdateLocked(std::move(update_args));
+}
+
+//
+// RlsLb::ChildPolicyWrapper::ChildPolicyHelper
+//
+
+RefCountedPtr<SubchannelInterface>
+RlsLb::ChildPolicyWrapper::ChildPolicyHelper::CreateSubchannel(
+    ServerAddress address, const grpc_channel_args& args) {
+  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
+    gpr_log(GPR_INFO,
+            "[rlslb %p] ChildPolicyWrapper=%p [%s] ChildPolicyHelper=%p: "
+            "CreateSubchannel() for %s",
+            wrapper_->lb_policy_.get(), wrapper_.get(),
+            wrapper_->target_.c_str(), this, address.ToString().c_str());
+  }
+  if (wrapper_->is_shutdown_) return nullptr;
+  return wrapper_->lb_policy_->channel_control_helper()->CreateSubchannel(
+      std::move(address), args);
+}
+
+void RlsLb::ChildPolicyWrapper::ChildPolicyHelper::UpdateState(
+    grpc_connectivity_state state, const absl::Status& status,
+    std::unique_ptr<SubchannelPicker> picker) {
+  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
+    gpr_log(GPR_INFO,
+            "[rlslb %p] ChildPolicyWrapper=%p [%s] ChildPolicyHelper=%p: "
+            "UpdateState(state=%s, status=%s, picker=%p)",
+            wrapper_->lb_policy_.get(), wrapper_.get(),
+            wrapper_->target_.c_str(), this, ConnectivityStateName(state),
+            status.ToString().c_str(), picker.get());
+  }
+  {
+    MutexLock lock(&wrapper_->lb_policy_->mu_);
+    if (wrapper_->is_shutdown_) return;
+    if (wrapper_->connectivity_state_ == GRPC_CHANNEL_TRANSIENT_FAILURE &&
+        state != GRPC_CHANNEL_READY) {
+      return;
+    }
+    wrapper_->connectivity_state_ = state;
+    GPR_DEBUG_ASSERT(picker != nullptr);
+    if (picker != nullptr) {
+      wrapper_->picker_ = std::move(picker);
+    }
+  }
+  wrapper_->lb_policy_->UpdatePickerLocked();
+}
+
+void RlsLb::ChildPolicyWrapper::ChildPolicyHelper::RequestReresolution() {
+  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
+    gpr_log(GPR_INFO,
+            "[rlslb %p] ChildPolicyWrapper=%p [%s] ChildPolicyHelper=%p: "
+            "RequestReresolution",
+            wrapper_->lb_policy_.get(), wrapper_.get(),
+            wrapper_->target_.c_str(), this);
+  }
+  if (wrapper_->is_shutdown_) return;
+  wrapper_->lb_policy_->channel_control_helper()->RequestReresolution();
+}
+
+absl::string_view RlsLb::ChildPolicyWrapper::ChildPolicyHelper::GetAuthority() {
+  return wrapper_->lb_policy_->channel_control_helper()->GetAuthority();
+}
+
+void RlsLb::ChildPolicyWrapper::ChildPolicyHelper::AddTraceEvent(
+    TraceSeverity severity, absl::string_view message) {
+  if (wrapper_->is_shutdown_) return;
+  wrapper_->lb_policy_->channel_control_helper()->AddTraceEvent(severity,
+                                                                message);
+}
+
+//
+// RlsLb::Picker
+//
+
+// Builds the key to be used for a request based on path and initial_metadata.
+std::map<std::string, std::string> BuildKeyMap(
+    const RlsLbConfig::KeyBuilderMap& key_builder_map, absl::string_view path,
+    const std::string& host,
+    const LoadBalancingPolicy::MetadataInterface* initial_metadata) {
+  size_t last_slash_pos = path.npos;  // May need this a few times, so cache it.
+  // Find key builder for this path.
+  auto it = key_builder_map.find(std::string(path));
+  if (it == key_builder_map.end()) {
+    // Didn't find exact match, try method wildcard.
+    last_slash_pos = path.rfind("/");
+    GPR_DEBUG_ASSERT(last_slash_pos != path.npos);
+    if (GPR_UNLIKELY(last_slash_pos == path.npos)) return {};
+    std::string service(path.substr(0, last_slash_pos + 1));
+    it = key_builder_map.find(service);
+    if (it == key_builder_map.end()) return {};
+  }
+  const RlsLbConfig::KeyBuilder* key_builder = &it->second;
+  // Construct key map using key builder.
+  std::map<std::string, std::string> key_map;
+  // Add header keys.
+  for (const auto& p : key_builder->header_keys) {
+    const std::string& key = p.first;
+    const std::vector<std::string>& header_names = p.second;
+    for (const std::string& header_name : header_names) {
+      std::string buffer;
+      absl::optional<absl::string_view> value =
+          initial_metadata->Lookup(header_name, &buffer);
+      if (value.has_value()) {
+        key_map[key] = std::string(*value);
+        break;
+      }
+    }
+  }
+  // Add constant keys.
+  key_map.insert(key_builder->constant_keys.begin(),
+                 key_builder->constant_keys.end());
+  // Add host key.
+  if (!key_builder->host_key.empty()) {
+    key_map[key_builder->host_key] = host;
+  }
+  // Add service key.
+  if (!key_builder->service_key.empty()) {
+    if (last_slash_pos == path.npos) {
+      last_slash_pos = path.rfind("/");
+      GPR_DEBUG_ASSERT(last_slash_pos != path.npos);
+      if (GPR_UNLIKELY(last_slash_pos == path.npos)) return {};
+    }
+    key_map[key_builder->service_key] =
+        std::string(path.substr(1, last_slash_pos - 1));
+  }
+  // Add method key.
+  if (!key_builder->method_key.empty()) {
+    if (last_slash_pos == path.npos) {
+      last_slash_pos = path.rfind("/");
+      GPR_DEBUG_ASSERT(last_slash_pos != path.npos);
+      if (GPR_UNLIKELY(last_slash_pos == path.npos)) return {};
+    }
+    key_map[key_builder->method_key] =
+        std::string(path.substr(last_slash_pos + 1));
+  }
+  return key_map;
+}
+
+RlsLb::Picker::Picker(RefCountedPtr<RlsLb> lb_policy)
+    : lb_policy_(std::move(lb_policy)), config_(lb_policy_->config_) {
+  if (lb_policy_->default_child_policy_ != nullptr) {
+    default_child_policy_ =
+        lb_policy_->default_child_policy_->Ref(DEBUG_LOCATION, "Picker");
+  }
+}
+
+RlsLb::Picker::~Picker() {
+  // It's not safe to unref the default child policy in the picker,
+  // since that needs to be done in the WorkSerializer.
+  if (default_child_policy_ != nullptr) {
+    auto* default_child_policy = default_child_policy_.release();
+    lb_policy_->work_serializer()->Run(
+        [default_child_policy]() {
+          default_child_policy->Unref(DEBUG_LOCATION, "Picker");
+        },
+        DEBUG_LOCATION);
+  }
+}
+
+LoadBalancingPolicy::PickResult RlsLb::Picker::Pick(PickArgs args) {
+  // Construct key for request.
+  RequestKey key = {BuildKeyMap(config_->key_builder_map(), args.path,
+                                lb_policy_->server_name_,
+                                args.initial_metadata)};
+  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
+    gpr_log(GPR_INFO, "[rlslb %p] picker=%p: request keys: %s",
+            lb_policy_.get(), this, key.ToString().c_str());
+  }
+  grpc_millis now = ExecCtx::Get()->Now();
+  MutexLock lock(&lb_policy_->mu_);
+  if (lb_policy_->is_shutdown_) {
+    return PickResult::Fail(
+        absl::UnavailableError("LB policy already shut down"));
+  }
+  // Check if there's a cache entry.
+  Cache::Entry* entry = lb_policy_->cache_.Find(key);
+  // If there is no cache entry, or if the cache entry is not in backoff
+  // and has a stale time in the past, and there is not already a
+  // pending RLS request for this key, then try to start a new RLS request.
+  if ((entry == nullptr ||
+       (entry->stale_time() < now && entry->backoff_time() < now)) &&
+      lb_policy_->request_map_.find(key) == lb_policy_->request_map_.end()) {
+    // Check if requests are being throttled.
+    if (lb_policy_->rls_channel_->ShouldThrottle()) {
+      // Request is throttled.
+      // If there is no non-expired data in the cache, then we use the
+      // default target if set, or else we fail the pick.
+      if (entry == nullptr || entry->data_expiration_time() < now) {
+        if (default_child_policy_ != nullptr) {
+          if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
+            gpr_log(GPR_INFO,
+                    "[rlslb %p] picker=%p: RLS call throttled; "
+                    "using default target",
+                    lb_policy_.get(), this);
+          }
+          return default_child_policy_->Pick(args);
+        }
+        if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
+          gpr_log(GPR_INFO,
+                  "[rlslb %p] picker=%p: RLS call throttled; failing pick",
+                  lb_policy_.get(), this);
+        }
+        return PickResult::Fail(
+            absl::UnavailableError("RLS request throttled"));
+      }
+    }
+    // Start the RLS call.
+    lb_policy_->rls_channel_->StartRlsCall(
+        key, (entry == nullptr || entry->data_expiration_time() < now) ? nullptr
+                                                                       : entry);
+  }
+  // If the cache entry exists, see if it has usable data.
+  if (entry != nullptr) {
+    // If the entry has non-expired data, use it.
+    if (entry->data_expiration_time() >= now) {
+      if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
+        gpr_log(GPR_INFO, "[rlslb %p] picker=%p: using cache entry %p",
+                lb_policy_.get(), this, entry);
+      }
+      return entry->Pick(args);
+    }
+    // If the entry is in backoff, then use the default target if set,
+    // or else fail the pick.
+    if (entry->backoff_time() >= now) {
+      if (default_child_policy_ != nullptr) {
+        if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
+          gpr_log(
+              GPR_INFO,
+              "[rlslb %p] picker=%p: RLS call in backoff; using default target",
+              lb_policy_.get(), this);
+        }
+        return default_child_policy_->Pick(args);
+      }
+      if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
+        gpr_log(GPR_INFO,
+                "[rlslb %p] picker=%p: RLS call in backoff; failing pick",
+                lb_policy_.get(), this);
+      }
+      return PickResult::Fail(entry->status());
+    }
+  }
+  // RLS call pending.  Queue the pick.
+  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
+    gpr_log(GPR_INFO, "[rlslb %p] picker=%p: RLS request pending; queuing pick",
+            lb_policy_.get(), this);
+  }
+  return PickResult::Queue();
+}
+
+//
+// RlsLb::Cache::Entry::BackoffTimer
+//
+
+RlsLb::Cache::Entry::BackoffTimer::BackoffTimer(RefCountedPtr<Entry> entry,
+                                                grpc_millis backoff_time)
+    : entry_(std::move(entry)) {
+  GRPC_CLOSURE_INIT(&backoff_timer_callback_, OnBackoffTimer, this, nullptr);
+  Ref(DEBUG_LOCATION, "BackoffTimer").release();
+  grpc_timer_init(&backoff_timer_, backoff_time, &backoff_timer_callback_);
+}
+
+void RlsLb::Cache::Entry::BackoffTimer::Orphan() {
+  if (armed_) {
+    armed_ = false;
+    grpc_timer_cancel(&backoff_timer_);
+  }
+  Unref(DEBUG_LOCATION, "Orphan");
+}
+
+void RlsLb::Cache::Entry::BackoffTimer::OnBackoffTimer(
+    void* arg, grpc_error_handle /*error*/) {
+  auto* self = static_cast<BackoffTimer*>(arg);
+  self->entry_->lb_policy_->work_serializer()->Run(
+      [self]() {
+        RefCountedPtr<BackoffTimer> backoff_timer(self);
+        {
+          MutexLock lock(&self->entry_->lb_policy_->mu_);
+          if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
+            gpr_log(GPR_INFO,
+                    "[rlslb %p] cache entry=%p %s, armed_=%d: "
+                    "backoff timer fired",
+                    self->entry_->lb_policy_.get(), self->entry_.get(),
+                    self->entry_->is_shutdown_
+                        ? "(shut down)"
+                        : self->entry_->lru_iterator_->ToString().c_str(),
+                    self->armed_);
+          }
+          bool cancelled = !self->armed_;
+          self->armed_ = false;
+          if (cancelled) return;
+        }
+        // The pick was in backoff state and there could be a pick queued if
+        // wait_for_ready is true. We'll update the picker for that case.
+        self->entry_->lb_policy_->UpdatePickerLocked();
+      },
+      DEBUG_LOCATION);
+}
+
+//
+// RlsLb::Cache::Entry
+//
+
+std::unique_ptr<BackOff> MakeCacheEntryBackoff() {
+  return absl::make_unique<BackOff>(
+      BackOff::Options()
+          .set_initial_backoff(kCacheBackoffInitial)
+          .set_multiplier(kCacheBackoffMultiplier)
+          .set_jitter(kCacheBackoffJitter)
+          .set_max_backoff(kCacheBackoffMax));
+}
+
+RlsLb::Cache::Entry::Entry(RefCountedPtr<RlsLb> lb_policy,
+                           const RequestKey& key)
+    : InternallyRefCounted<Entry>(
+          GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace) ? "CacheEntry" : nullptr),
+      lb_policy_(std::move(lb_policy)),
+      backoff_state_(MakeCacheEntryBackoff()),
+      min_expiration_time_(ExecCtx::Get()->Now() + kMinExpirationTime),
+      lru_iterator_(lb_policy_->cache_.lru_list_.insert(
+          lb_policy_->cache_.lru_list_.end(), key)) {}
+
+void RlsLb::Cache::Entry::Orphan() {
+  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
+    gpr_log(GPR_INFO, "[rlslb %p] cache entry=%p %s: cache entry evicted",
+            lb_policy_.get(), this, lru_iterator_->ToString().c_str());
+  }
+  is_shutdown_ = true;
+  lb_policy_->cache_.lru_list_.erase(lru_iterator_);
+  lru_iterator_ = lb_policy_->cache_.lru_list_.end();  // Just in case.
+  backoff_state_.reset();
+  if (backoff_timer_ != nullptr) {
+    backoff_timer_.reset();
+    lb_policy_->UpdatePickerAsync();
+  }
+  child_policy_wrappers_.clear();
+  Unref(DEBUG_LOCATION, "Orphan");
+}
+
+size_t RlsLb::Cache::Entry::Size() const {
+  // lru_iterator_ is not valid once we're shut down.
+  GPR_ASSERT(!is_shutdown_);
+  return lb_policy_->cache_.EntrySizeForKey(*lru_iterator_);
+}
+
+LoadBalancingPolicy::PickResult RlsLb::Cache::Entry::Pick(PickArgs args) {
+  for (const auto& child_policy_wrapper : child_policy_wrappers_) {
+    if (child_policy_wrapper->connectivity_state() ==
+        GRPC_CHANNEL_TRANSIENT_FAILURE) {
+      if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
+        gpr_log(GPR_INFO,
+                "[rlslb %p] cache entry=%p %s: target %s in state "
+                "TRANSIENT_FAILURE; skipping",
+                lb_policy_.get(), this, lru_iterator_->ToString().c_str(),
+                child_policy_wrapper->target().c_str());
+      }
+      continue;
+    }
+    // Child policy not in TRANSIENT_FAILURE, so delegate.
+    if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
+      gpr_log(
+          GPR_INFO,
+          "[rlslb %p] cache entry=%p %s: target %s in state %s; "
+          "delegating",
+          lb_policy_.get(), this, lru_iterator_->ToString().c_str(),
+          child_policy_wrapper->target().c_str(),
+          ConnectivityStateName(child_policy_wrapper->connectivity_state()));
+    }
+    // Add header data.
+    if (!header_data_.empty()) {
+      char* copied_header_data =
+          static_cast<char*>(args.call_state->Alloc(header_data_.length() + 1));
+      strcpy(copied_header_data, header_data_.c_str());
+      args.initial_metadata->Add(kRlsHeaderKey, copied_header_data);
+    }
+    return child_policy_wrapper->Pick(args);
+  }
+  // No child policy found.
+  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
+    gpr_log(GPR_INFO,
+            "[rlslb %p] cache entry=%p %s: no healthy target found; "
+            "failing pick",
+            lb_policy_.get(), this, lru_iterator_->ToString().c_str());
+  }
+  return PickResult::Fail(
+      absl::UnavailableError("all RLS targets unreachable"));
+}
+
+void RlsLb::Cache::Entry::ResetBackoff() {
+  backoff_time_ = GRPC_MILLIS_INF_PAST;
+  backoff_timer_.reset();
+}
+
+bool RlsLb::Cache::Entry::ShouldRemove() const {
+  grpc_millis now = ExecCtx::Get()->Now();
+  return data_expiration_time_ < now && backoff_expiration_time_ < now;
+}
+
+bool RlsLb::Cache::Entry::CanEvict() const {
+  grpc_millis now = ExecCtx::Get()->Now();
+  return min_expiration_time_ < now;
+}
+
+void RlsLb::Cache::Entry::MarkUsed() {
+  auto& lru_list = lb_policy_->cache_.lru_list_;
+  auto new_it = lru_list.insert(lru_list.end(), *lru_iterator_);
+  lru_list.erase(lru_iterator_);
+  lru_iterator_ = new_it;
+}
+
+std::vector<RlsLb::ChildPolicyWrapper*>
+RlsLb::Cache::Entry::OnRlsResponseLocked(
+    ResponseInfo response, std::unique_ptr<BackOff> backoff_state) {
+  // Move the entry to the end of the LRU list.
+  MarkUsed();
+  // If the request failed, store the failed status and update the
+  // backoff state.
+  if (!response.status.ok()) {
+    status_ = response.status;
+    if (backoff_state != nullptr) {
+      backoff_state_ = std::move(backoff_state);
+    } else {
+      backoff_state_ = MakeCacheEntryBackoff();
+    }
+    backoff_time_ = backoff_state_->NextAttemptTime();
+    grpc_millis now = ExecCtx::Get()->Now();
+    backoff_expiration_time_ = now + (backoff_time_ - now) * 2;
+    backoff_timer_ = MakeOrphanable<BackoffTimer>(
+        Ref(DEBUG_LOCATION, "BackoffTimer"), backoff_time_);
+    lb_policy_->UpdatePickerAsync();
+    return {};
+  }
+  // Request succeeded, so store the result.
+  header_data_ = std::move(response.header_data);
+  grpc_millis now = ExecCtx::Get()->Now();
+  data_expiration_time_ = now + lb_policy_->config_->max_age();
+  stale_time_ = now + lb_policy_->config_->stale_age();
+  status_ = absl::OkStatus();
+  backoff_state_.reset();
+  backoff_time_ = GRPC_MILLIS_INF_PAST;
+  backoff_expiration_time_ = GRPC_MILLIS_INF_PAST;
+  // Check if we need to update this list of targets.
+  bool targets_changed = [&]() ABSL_EXCLUSIVE_LOCKS_REQUIRED(&RlsLb::mu_) {
+    if (child_policy_wrappers_.size() != response.targets.size()) return true;
+    for (size_t i = 0; i < response.targets.size(); ++i) {
+      if (child_policy_wrappers_[i]->target() != response.targets[i]) {
+        return true;
+      }
+    }
+    return false;
+  }();
+  if (!targets_changed) {
+    // Targets didn't change, so we're not updating the list of child
+    // policies.  Return a new picker so that any queued requests can be
+    // re-processed.
+    lb_policy_->UpdatePickerAsync();
+    return {};
+  }
+  // Target list changed, so update it.
+  std::set<absl::string_view> old_targets;
+  for (RefCountedPtr<ChildPolicyWrapper>& child_policy_wrapper :
+       child_policy_wrappers_) {
+    old_targets.emplace(child_policy_wrapper->target());
+  }
+  bool update_picker = false;
+  std::vector<ChildPolicyWrapper*> child_policies_to_finish_update;
+  std::vector<RefCountedPtr<ChildPolicyWrapper>> new_child_policy_wrappers;
+  new_child_policy_wrappers.reserve(response.targets.size());
+  for (std::string& target : response.targets) {
+    auto it = lb_policy_->child_policy_map_.find(target);
+    if (it == lb_policy_->child_policy_map_.end()) {
+      auto new_child = MakeRefCounted<ChildPolicyWrapper>(
+          lb_policy_->Ref(DEBUG_LOCATION, "ChildPolicyWrapper"), target);
+      new_child->StartUpdate();
+      child_policies_to_finish_update.push_back(new_child.get());
+      new_child_policy_wrappers.emplace_back(std::move(new_child));
+    } else {
+      new_child_policy_wrappers.emplace_back(
+          it->second->Ref(DEBUG_LOCATION, "CacheEntry"));
+      // If the target already existed but was not previously used for
+      // this key, then we'll need to update the picker, since we
+      // didn't actually create a new child policy, which would have
+      // triggered an RLS picker update when it returned its first picker.
+      if (old_targets.find(target) == old_targets.end()) {
+        update_picker = true;
+      }
+    }
+  }
+  child_policy_wrappers_ = std::move(new_child_policy_wrappers);
+  if (update_picker) {
+    lb_policy_->UpdatePickerAsync();
+  }
+  return child_policies_to_finish_update;
+}
+
+//
+// RlsLb::Cache
+//
+
+RlsLb::Cache::Cache(RlsLb* lb_policy) : lb_policy_(lb_policy) {
+  grpc_millis now = ExecCtx::Get()->Now();
+  lb_policy_->Ref(DEBUG_LOCATION, "CacheCleanupTimer").release();
+  GRPC_CLOSURE_INIT(&timer_callback_, OnCleanupTimer, this, nullptr);
+  grpc_timer_init(&cleanup_timer_, now + kCacheCleanupTimerInterval,
+                  &timer_callback_);
+}
+
+RlsLb::Cache::Entry* RlsLb::Cache::Find(const RequestKey& key) {
+  auto it = map_.find(key);
+  if (it == map_.end()) return nullptr;
+  it->second->MarkUsed();
+  return it->second.get();
+}
+
+RlsLb::Cache::Entry* RlsLb::Cache::FindOrInsert(const RequestKey& key) {
+  auto it = map_.find(key);
+  // If not found, create new entry.
+  if (it == map_.end()) {
+    size_t entry_size = EntrySizeForKey(key);
+    MaybeShrinkSize(size_limit_ - std::min(size_limit_, entry_size));
+    Entry* entry =
+        new Entry(lb_policy_->Ref(DEBUG_LOCATION, "CacheEntry"), key);
+    map_.emplace(key, OrphanablePtr<Entry>(entry));
+    size_ += entry_size;
+    if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
+      gpr_log(GPR_INFO, "[rlslb %p] key=%s: cache entry added, entry=%p",
+              lb_policy_, key.ToString().c_str(), entry);
+    }
+    return entry;
+  }
+  // Entry found, so use it.
+  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
+    gpr_log(GPR_INFO, "[rlslb %p] key=%s: found cache entry %p", lb_policy_,
+            key.ToString().c_str(), it->second.get());
+  }
+  it->second->MarkUsed();
+  return it->second.get();
+}
+
+void RlsLb::Cache::Resize(size_t bytes) {
+  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
+    gpr_log(GPR_INFO, "[rlslb %p] resizing cache to %" PRIuPTR " bytes",
+            lb_policy_, bytes);
+  }
+  size_limit_ = bytes;
+  MaybeShrinkSize(size_limit_);
+}
+
+void RlsLb::Cache::ResetAllBackoff() {
+  for (auto& p : map_) {
+    p.second->ResetBackoff();
+  }
+  lb_policy_->UpdatePickerAsync();
+}
+
+void RlsLb::Cache::Shutdown() {
+  map_.clear();
+  lru_list_.clear();
+  grpc_timer_cancel(&cleanup_timer_);
+}
+
+void RlsLb::Cache::OnCleanupTimer(void* arg, grpc_error_handle error) {
+  Cache* cache = static_cast<Cache*>(arg);
+  GRPC_ERROR_REF(error);
+  cache->lb_policy_->work_serializer()->Run(
+      [cache, error]() {
+        RefCountedPtr<RlsLb> lb_policy(cache->lb_policy_);
+        if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
+          gpr_log(GPR_INFO, "[rlslb %p] cache cleanup timer fired (%s)",
+                  cache->lb_policy_, grpc_error_std_string(error).c_str());
+        }
+        if (error == GRPC_ERROR_CANCELLED) return;
+        MutexLock lock(&lb_policy->mu_);
+        if (lb_policy->is_shutdown_) return;
+        for (auto it = cache->map_.begin(); it != cache->map_.end();) {
+          if (GPR_UNLIKELY(it->second->ShouldRemove() &&
+                           it->second->CanEvict())) {
+            cache->size_ -= it->second->Size();
+            it = cache->map_.erase(it);
+          } else {
+            ++it;
+          }
+        }
+        grpc_millis now = ExecCtx::Get()->Now();
+        lb_policy.release();
+        grpc_timer_init(&cache->cleanup_timer_,
+                        now + kCacheCleanupTimerInterval,
+                        &cache->timer_callback_);
+      },
+      DEBUG_LOCATION);
+}
+
+size_t RlsLb::Cache::EntrySizeForKey(const RequestKey& key) {
+  // Key is stored twice, once in LRU list and again in the cache map.
+  return (key.Size() * 2) + sizeof(Entry);
+}
+
+void RlsLb::Cache::MaybeShrinkSize(size_t bytes) {
+  while (size_ > bytes) {
+    auto lru_it = lru_list_.begin();
+    if (GPR_UNLIKELY(lru_it == lru_list_.end())) break;
+    auto map_it = map_.find(*lru_it);
+    GPR_ASSERT(map_it != map_.end());
+    if (!map_it->second->CanEvict()) break;
+    if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
+      gpr_log(GPR_INFO, "[rlslb %p] LRU eviction: removing entry %p %s",
+              lb_policy_, map_it->second.get(), lru_it->ToString().c_str());
+    }
+    size_ -= map_it->second->Size();
+    map_.erase(map_it);
+  }
+  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
+    gpr_log(GPR_INFO,
+            "[rlslb %p] LRU pass complete: desired size=%" PRIuPTR
+            " size=%" PRIuPTR,
+            lb_policy_, bytes, size_);
+  }
+}
+
+//
+// RlsLb::RlsChannel::StateWatcher
+//
+
+void RlsLb::RlsChannel::StateWatcher::OnConnectivityStateChange(
+    grpc_connectivity_state new_state, const absl::Status& status) {
+  auto* lb_policy = rls_channel_->lb_policy_.get();
+  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
+    gpr_log(GPR_INFO,
+            "[rlslb %p] RlsChannel=%p StateWatcher=%p: "
+            "state changed to %s (%s)",
+            lb_policy, rls_channel_.get(), this,
+            ConnectivityStateName(new_state), status.ToString().c_str());
+  }
+  if (rls_channel_->is_shutdown_) return;
+  MutexLock lock(&lb_policy->mu_);
+  if (new_state == GRPC_CHANNEL_READY && was_transient_failure_) {
+    was_transient_failure_ = false;
+    // Reset the backoff of all cache entries, so that we don't
+    // double-penalize if an RLS request fails while the channel is
+    // down, since the throttling for the channel being down is handled
+    // at the channel level instead of in the individual cache entries.
+    lb_policy->cache_.ResetAllBackoff();
+  } else if (new_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
+    was_transient_failure_ = true;
+  }
+}
+
+//
+// RlsLb::RlsChannel::Throttle
+//
+
+RlsLb::RlsChannel::Throttle::Throttle(int window_size_seconds,
+                                      double ratio_for_successes,
+                                      int paddings) {
+  GPR_DEBUG_ASSERT(window_size_seconds >= 0);
+  GPR_DEBUG_ASSERT(ratio_for_successes >= 0);
+  GPR_DEBUG_ASSERT(paddings >= 0);
+  window_size_ = window_size_seconds == 0 ? window_size_seconds * GPR_MS_PER_SEC
+                                          : kDefaultThrottleWindowSize;
+  ratio_for_successes_ = ratio_for_successes == 0
+                             ? kDefaultThrottleRatioForSuccesses
+                             : ratio_for_successes;
+  paddings_ = paddings == 0 ? kDefaultThrottlePaddings : paddings;
+}
+
+bool RlsLb::RlsChannel::Throttle::ShouldThrottle() {
+  grpc_millis now = ExecCtx::Get()->Now();
+  while (!requests_.empty() && now - requests_.front() > window_size_) {
+    requests_.pop_front();
+  }
+  while (!successes_.empty() && now - successes_.front() > window_size_) {
+    successes_.pop_front();
+  }
+  int successes = successes_.size();
+  int requests = requests_.size();
+  bool result = ((rand() % (requests + paddings_)) <
+                 static_cast<double>(requests) -
+                     static_cast<double>(successes) * ratio_for_successes_);
+  requests_.push_back(now);
+  return result;
+}
+
+void RlsLb::RlsChannel::Throttle::RegisterResponse(bool success) {
+  if (success) {
+    successes_.push_back(ExecCtx::Get()->Now());
+  }
+}
+
+//
+// RlsLb::RlsChannel
+//
+
+RlsLb::RlsChannel::RlsChannel(RefCountedPtr<RlsLb> lb_policy,
+                              const std::string& target,
+                              const grpc_channel_args* parent_channel_args)
+    : InternallyRefCounted<RlsChannel>(
+          GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace) ? "RlsChannel" : nullptr),
+      lb_policy_(std::move(lb_policy)) {
+  // Get channel creds from parent channel.
+  // TODO(roth): Once we eliminate insecure builds, get this via a
+  // method on the helper instead of digging through channel args.
+  grpc_channel_credentials* creds =
+      grpc_channel_credentials_find_in_args(parent_channel_args);
+  // Use the parent channel's authority.
+  std::string authority(lb_policy_->channel_control_helper()->GetAuthority());
+  absl::InlinedVector<grpc_arg, 3> args = {
+      grpc_channel_arg_string_create(
+          const_cast<char*>(GRPC_ARG_DEFAULT_AUTHORITY),
+          const_cast<char*>(authority.c_str())),
+      grpc_channel_arg_integer_create(
+          const_cast<char*>(GRPC_ARG_CHANNELZ_IS_INTERNAL_CHANNEL), 1),
+  };
+  // Propagate fake security connector expected targets, if any.
+  // (This is ugly, but it seems better than propagating all channel args
+  // from the parent channel by default and then having a giant
+  // exclude list of args to strip out, like we do in grpclb.)
+  const char* fake_security_expected_targets = grpc_channel_args_find_string(
+      parent_channel_args, GRPC_ARG_FAKE_SECURITY_EXPECTED_TARGETS);
+  if (fake_security_expected_targets != nullptr) {
+    args.push_back(grpc_channel_arg_string_create(
+        const_cast<char*>(GRPC_ARG_FAKE_SECURITY_EXPECTED_TARGETS),
+        const_cast<char*>(fake_security_expected_targets)));
+  }
+  grpc_channel_args rls_channel_args = {args.size(), args.data()};
+  channel_ = grpc_secure_channel_create(creds, target.c_str(),
+                                        &rls_channel_args, nullptr);
+  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
+    gpr_log(GPR_INFO, "[rlslb %p] RlsChannel=%p: created channel %p for %s",
+            lb_policy_.get(), this, channel_, target.c_str());
+  }
+  if (channel_ != nullptr) {
+    // Set up channelz linkage.
+    channelz::ChannelNode* child_channelz_node =
+        grpc_channel_get_channelz_node(channel_);
+    channelz::ChannelNode* parent_channelz_node =
+        grpc_channel_args_find_pointer<channelz::ChannelNode>(
+            parent_channel_args, GRPC_ARG_CHANNELZ_CHANNEL_NODE);
+    if (child_channelz_node != nullptr && parent_channelz_node != nullptr) {
+      parent_channelz_node->AddChildChannel(child_channelz_node->uuid());
+      parent_channelz_node_ = parent_channelz_node->Ref();
+    }
+    // Start connectivity watch.
+    ClientChannel* client_channel = ClientChannel::GetFromChannel(channel_);
+    GPR_ASSERT(client_channel != nullptr);
+    watcher_ = new StateWatcher(Ref(DEBUG_LOCATION, "StateWatcher"));
+    client_channel->AddConnectivityWatcher(
+        GRPC_CHANNEL_IDLE,
+        OrphanablePtr<AsyncConnectivityStateWatcherInterface>(watcher_));
+  }
+}
+
+void RlsLb::RlsChannel::Orphan() {
+  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
+    gpr_log(GPR_INFO, "[rlslb %p] RlsChannel=%p, channel=%p: shutdown",
+            lb_policy_.get(), this, channel_);
+  }
+  is_shutdown_ = true;
+  if (channel_ != nullptr) {
+    // Remove channelz linkage.
+    if (parent_channelz_node_ != nullptr) {
+      channelz::ChannelNode* child_channelz_node =
+          grpc_channel_get_channelz_node(channel_);
+      GPR_ASSERT(child_channelz_node != nullptr);
+      parent_channelz_node_->RemoveChildChannel(child_channelz_node->uuid());
+    }
+    // Stop connectivity watch.
+    if (watcher_ != nullptr) {
+      ClientChannel* client_channel = ClientChannel::GetFromChannel(channel_);
+      GPR_ASSERT(client_channel != nullptr);
+      client_channel->RemoveConnectivityWatcher(watcher_);
+      watcher_ = nullptr;
+    }
+    grpc_channel_destroy(channel_);
+  }
+  Unref(DEBUG_LOCATION, "Orphan");
+}
+
+void RlsLb::RlsChannel::StartRlsCall(const RequestKey& key,
+                                     Cache::Entry* stale_entry) {
+  std::unique_ptr<BackOff> backoff_state;
+  grpc_lookup_v1_RouteLookupRequest_Reason reason =
+      grpc_lookup_v1_RouteLookupRequest_REASON_MISS;
+  std::string stale_header_data;
+  if (stale_entry != nullptr) {
+    backoff_state = stale_entry->TakeBackoffState();
+    reason = grpc_lookup_v1_RouteLookupRequest_REASON_STALE;
+    stale_header_data = stale_entry->header_data();
+  }
+  lb_policy_->request_map_.emplace(
+      key, MakeOrphanable<RlsRequest>(
+               lb_policy_->Ref(DEBUG_LOCATION, "RlsRequest"), key,
+               lb_policy_->rls_channel_->Ref(DEBUG_LOCATION, "RlsRequest"),
+               std::move(backoff_state), reason, std::move(stale_header_data)));
+}
+
+void RlsLb::RlsChannel::ReportResponseLocked(bool response_succeeded) {
+  throttle_.RegisterResponse(response_succeeded);
+}
+
+void RlsLb::RlsChannel::ResetBackoff() {
+  GPR_DEBUG_ASSERT(channel_ != nullptr);
+  grpc_channel_reset_connect_backoff(channel_);
+}
+
+//
+// RlsLb::RlsRequest
+//
+
+RlsLb::RlsRequest::RlsRequest(RefCountedPtr<RlsLb> lb_policy, RequestKey key,
+                              RefCountedPtr<RlsChannel> rls_channel,
+                              std::unique_ptr<BackOff> backoff_state,
+                              grpc_lookup_v1_RouteLookupRequest_Reason reason,
+                              std::string stale_header_data)
+    : InternallyRefCounted<RlsRequest>(
+          GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace) ? "RlsRequest" : nullptr),
+      lb_policy_(std::move(lb_policy)),
+      key_(std::move(key)),
+      rls_channel_(std::move(rls_channel)),
+      backoff_state_(std::move(backoff_state)),
+      reason_(reason),
+      stale_header_data_(std::move(stale_header_data)) {
+  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
+    gpr_log(GPR_INFO,
+            "[rlslb %p] rls_request=%p: RLS request created for key %s",
+            lb_policy_.get(), this, key_.ToString().c_str());
+  }
+  GRPC_CLOSURE_INIT(&call_complete_cb_, OnRlsCallComplete, this, nullptr);
+  ExecCtx::Run(
+      DEBUG_LOCATION,
+      GRPC_CLOSURE_INIT(&call_start_cb_, StartCall,
+                        Ref(DEBUG_LOCATION, "StartCall").release(), nullptr),
+      GRPC_ERROR_NONE);
+}
+
+RlsLb::RlsRequest::~RlsRequest() { GPR_ASSERT(call_ == nullptr); }
+
+void RlsLb::RlsRequest::Orphan() {
+  if (call_ != nullptr) {
+    if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
+      gpr_log(GPR_INFO, "[rlslb %p] rls_request=%p %s: cancelling RLS call",
+              lb_policy_.get(), this, key_.ToString().c_str());
+    }
+    grpc_call_cancel_internal(call_);
+  }
+  Unref(DEBUG_LOCATION, "Orphan");
+}
+
+void RlsLb::RlsRequest::StartCall(void* arg, grpc_error_handle /*error*/) {
+  auto* request = static_cast<RlsRequest*>(arg);
+  request->lb_policy_->work_serializer()->Run(
+      [request]() {
+        request->StartCallLocked();
+        request->Unref(DEBUG_LOCATION, "StartCall");
+      },
+      DEBUG_LOCATION);
+}
+
+void RlsLb::RlsRequest::StartCallLocked() {
+  {
+    MutexLock lock(&lb_policy_->mu_);
+    if (lb_policy_->is_shutdown_) return;
+  }
+  grpc_millis now = ExecCtx::Get()->Now();
+  deadline_ = now + lb_policy_->config_->lookup_service_timeout();
+  grpc_metadata_array_init(&recv_initial_metadata_);
+  grpc_metadata_array_init(&recv_trailing_metadata_);
+  call_ = grpc_channel_create_pollset_set_call(
+      rls_channel_->channel(), nullptr, GRPC_PROPAGATE_DEFAULTS,
+      lb_policy_->interested_parties(),
+      grpc_slice_from_static_string(kRlsRequestPath), nullptr, deadline_,
+      nullptr);
+  grpc_op ops[6];
+  memset(ops, 0, sizeof(ops));
+  grpc_op* op = ops;
+  op->op = GRPC_OP_SEND_INITIAL_METADATA;
+  ++op;
+  op->op = GRPC_OP_SEND_MESSAGE;
+  send_message_ = MakeRequestProto();
+  op->data.send_message.send_message = send_message_;
+  ++op;
+  op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
+  ++op;
+  op->op = GRPC_OP_RECV_INITIAL_METADATA;
+  op->data.recv_initial_metadata.recv_initial_metadata =
+      &recv_initial_metadata_;
+  ++op;
+  op->op = GRPC_OP_RECV_MESSAGE;
+  op->data.recv_message.recv_message = &recv_message_;
+  ++op;
+  op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
+  op->data.recv_status_on_client.trailing_metadata = &recv_trailing_metadata_;
+  op->data.recv_status_on_client.status = &status_recv_;
+  op->data.recv_status_on_client.status_details = &status_details_recv_;
+  ++op;
+  Ref(DEBUG_LOCATION, "OnRlsCallComplete").release();
+  auto call_error = grpc_call_start_batch_and_execute(
+      call_, ops, static_cast<size_t>(op - ops), &call_complete_cb_);
+  GPR_ASSERT(call_error == GRPC_CALL_OK);
+}
+
+void RlsLb::RlsRequest::OnRlsCallComplete(void* arg, grpc_error_handle error) {
+  auto* request = static_cast<RlsRequest*>(arg);
+  GRPC_ERROR_REF(error);
+  request->lb_policy_->work_serializer()->Run(
+      [request, error]() {
+        request->OnRlsCallCompleteLocked(error);
+        request->Unref(DEBUG_LOCATION, "OnRlsCallComplete");
+      },
+      DEBUG_LOCATION);
+}
+
+void RlsLb::RlsRequest::OnRlsCallCompleteLocked(grpc_error_handle error) {
+  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
+    std::string status_message(StringViewFromSlice(status_details_recv_));
+    gpr_log(GPR_INFO,
+            "[rlslb %p] rls_request=%p %s, error=%s, status={%d, %s} RLS call "
+            "response received",
+            lb_policy_.get(), this, key_.ToString().c_str(),
+            grpc_error_std_string(error).c_str(), status_recv_,
+            status_message.c_str());
+  }
+  // Parse response.
+  ResponseInfo response;
+  if (error != GRPC_ERROR_NONE) {
+    grpc_status_code code;
+    std::string message;
+    grpc_error_get_status(error, deadline_, &code, &message,
+                          /*http_error=*/nullptr, /*error_string=*/nullptr);
+    response.status =
+        absl::Status(static_cast<absl::StatusCode>(code), message);
+  } else if (status_recv_ != GRPC_STATUS_OK) {
+    response.status = absl::Status(static_cast<absl::StatusCode>(status_recv_),
+                                   StringViewFromSlice(status_details_recv_));
+  } else {
+    response = ParseResponseProto();
+  }
+  // Clean up call state.
+  grpc_byte_buffer_destroy(send_message_);
+  grpc_byte_buffer_destroy(recv_message_);
+  grpc_metadata_array_destroy(&recv_initial_metadata_);
+  grpc_metadata_array_destroy(&recv_trailing_metadata_);
+  grpc_slice_unref_internal(status_details_recv_);
+  grpc_call_unref(call_);
+  call_ = nullptr;
+  // Return result to cache.
+  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
+    gpr_log(GPR_INFO, "[rlslb %p] rls_request=%p %s: response info: %s",
+            lb_policy_.get(), this, key_.ToString().c_str(),
+            response.ToString().c_str());
+  }
+  std::vector<ChildPolicyWrapper*> child_policies_to_finish_update;
+  {
+    MutexLock lock(&lb_policy_->mu_);
+    if (lb_policy_->is_shutdown_) return;
+    rls_channel_->ReportResponseLocked(!response.status.ok());
+    Cache::Entry* cache_entry = lb_policy_->cache_.FindOrInsert(key_);
+    child_policies_to_finish_update = cache_entry->OnRlsResponseLocked(
+        std::move(response), std::move(backoff_state_));
+    lb_policy_->request_map_.erase(key_);
+  }
+  // Now that we've released the lock, finish the update on any newly
+  // created child policies.
+  for (ChildPolicyWrapper* child : child_policies_to_finish_update) {
+    child->MaybeFinishUpdate();
+  }
+}
+
+grpc_byte_buffer* RlsLb::RlsRequest::MakeRequestProto() {
+  upb::Arena arena;
+  grpc_lookup_v1_RouteLookupRequest* req =
+      grpc_lookup_v1_RouteLookupRequest_new(arena.ptr());
+  grpc_lookup_v1_RouteLookupRequest_set_target_type(
+      req, upb_strview_make(kGrpc, sizeof(kGrpc) - 1));
+  for (const auto& kv : key_.key_map) {
+    grpc_lookup_v1_RouteLookupRequest_key_map_set(
+        req, upb_strview_make(kv.first.data(), kv.first.size()),
+        upb_strview_make(kv.second.data(), kv.second.size()), arena.ptr());
+  }
+  grpc_lookup_v1_RouteLookupRequest_set_reason(req, reason_);
+  if (!stale_header_data_.empty()) {
+    grpc_lookup_v1_RouteLookupRequest_set_stale_header_data(
+        req,
+        upb_strview_make(stale_header_data_.data(), stale_header_data_.size()));
+  }
+  size_t len;
+  char* buf =
+      grpc_lookup_v1_RouteLookupRequest_serialize(req, arena.ptr(), &len);
+  grpc_slice send_slice = grpc_slice_from_copied_buffer(buf, len);
+  grpc_byte_buffer* byte_buffer = grpc_raw_byte_buffer_create(&send_slice, 1);
+  grpc_slice_unref_internal(send_slice);
+  return byte_buffer;
+}
+
+RlsLb::ResponseInfo RlsLb::RlsRequest::ParseResponseProto() {
+  ResponseInfo response_info;
+  upb::Arena arena;
+  grpc_byte_buffer_reader bbr;
+  grpc_byte_buffer_reader_init(&bbr, recv_message_);
+  grpc_slice recv_slice = grpc_byte_buffer_reader_readall(&bbr);
+  grpc_byte_buffer_reader_destroy(&bbr);
+  grpc_lookup_v1_RouteLookupResponse* response =
+      grpc_lookup_v1_RouteLookupResponse_parse(
+          reinterpret_cast<const char*>(GRPC_SLICE_START_PTR(recv_slice)),
+          GRPC_SLICE_LENGTH(recv_slice), arena.ptr());
+  grpc_slice_unref_internal(recv_slice);
+  if (response == nullptr) {
+    response_info.status = absl::InternalError("cannot parse RLS response");
+    return response_info;
+  }
+  size_t num_targets;
+  const upb_strview* targets_strview =
+      grpc_lookup_v1_RouteLookupResponse_targets(response, &num_targets);
+  if (num_targets == 0) {
+    response_info.status =
+        absl::InvalidArgumentError("RLS response has no target entry");
+    return response_info;
+  }
+  response_info.targets.reserve(num_targets);
+  for (size_t i = 0; i < num_targets; ++i) {
+    response_info.targets.emplace_back(targets_strview[i].data,
+                                       targets_strview[i].size);
+  }
+  upb_strview header_data_strview =
+      grpc_lookup_v1_RouteLookupResponse_header_data(response);
+  response_info.header_data =
+      std::string(header_data_strview.data, header_data_strview.size);
+  return response_info;
+}
+
+//
+// RlsLb
+//
+
+std::string GetServerUri(const grpc_channel_args* args) {
+  const char* server_uri_str =
+      grpc_channel_args_find_string(args, GRPC_ARG_SERVER_URI);
+  GPR_ASSERT(server_uri_str != nullptr);
+  absl::StatusOr<URI> uri = URI::Parse(server_uri_str);
+  GPR_ASSERT(uri.ok());
+  return std::string(absl::StripPrefix(uri->path(), "/"));
+}
+
+RlsLb::RlsLb(Args args)
+    : LoadBalancingPolicy(std::move(args)),
+      server_name_(GetServerUri(args.args)),
+      cache_(this) {
+  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
+    gpr_log(GPR_INFO, "[rlslb %p] policy created", this);
+  }
+}
+
+void RlsLb::UpdateLocked(UpdateArgs args) {
+  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
+    gpr_log(GPR_INFO, "[rlslb %p] policy updated", this);
+  }
+  // Swap out config, addresses, and channel args.
+  RefCountedPtr<RlsLbConfig> old_config = std::move(config_);
+  config_ = std::move(args.config);
+  ServerAddressList old_addresses = std::move(addresses_);
+  addresses_ = std::move(args.addresses);
+  grpc_channel_args_destroy(channel_args_);
+  channel_args_ = grpc_channel_args_copy(args.args);
+  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace) &&
+      (old_config == nullptr ||
+       old_config->child_policy_config() != config_->child_policy_config())) {
+    gpr_log(GPR_INFO, "[rlslb %p] updated child policy config: %s", this,
+            config_->child_policy_config().Dump().c_str());
+  }
+  // Determine whether we need to update all child policies.
+  bool update_child_policies =
+      old_config == nullptr ||
+      old_config->child_policy_config() != config_->child_policy_config() ||
+      old_addresses != addresses_ ||
+      grpc_channel_args_compare(args.args, channel_args_) != 0;
+  // If default target changes, swap out child policy.
+  bool created_default_child = false;
+  if (old_config == nullptr ||
+      config_->default_target() != old_config->default_target()) {
+    if (config_->default_target().empty()) {
+      if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
+        gpr_log(GPR_INFO, "[rlslb %p] unsetting default target", this);
+      }
+      default_child_policy_.reset();
+    } else {
+      auto it = child_policy_map_.find(config_->default_target());
+      if (it == child_policy_map_.end()) {
+        if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
+          gpr_log(GPR_INFO, "[rlslb %p] creating new default target", this);
+        }
+        default_child_policy_ = MakeRefCounted<ChildPolicyWrapper>(
+            Ref(DEBUG_LOCATION, "ChildPolicyWrapper"),
+            config_->default_target());
+        created_default_child = true;
+      } else {
+        if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
+          gpr_log(GPR_INFO,
+                  "[rlslb %p] using existing child for default target", this);
+        }
+        default_child_policy_ =
+            it->second->Ref(DEBUG_LOCATION, "DefaultChildPolicy");
+      }
+    }
+  }
+  // Now grab the lock to swap out the state it guards.
+  {
+    MutexLock lock(&mu_);
+    // Swap out RLS channel if needed.
+    if (old_config == nullptr ||
+        config_->lookup_service() != old_config->lookup_service()) {
+      rls_channel_ =
+          MakeOrphanable<RlsChannel>(Ref(DEBUG_LOCATION, "RlsChannel"),
+                                     config_->lookup_service(), channel_args_);
+    }
+    // Resize cache if needed.
+    if (old_config == nullptr ||
+        config_->cache_size_bytes() != old_config->cache_size_bytes()) {
+      cache_.Resize(config_->cache_size_bytes());
+    }
+    // Start update of child policies if needed.
+    if (update_child_policies) {
+      if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
+        gpr_log(GPR_INFO, "[rlslb %p] starting child policy updates", this);
+      }
+      for (auto& p : child_policy_map_) {
+        p.second->StartUpdate();
+      }
+    } else if (created_default_child) {
+      if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
+        gpr_log(GPR_INFO, "[rlslb %p] starting default child policy update",
+                this);
+      }
+      default_child_policy_->StartUpdate();
+    }
+  }
+  // Now that we've released the lock, finish update of child policies.
+  if (update_child_policies) {
+    if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
+      gpr_log(GPR_INFO, "[rlslb %p] finishing child policy updates", this);
+    }
+    for (auto& p : child_policy_map_) {
+      p.second->MaybeFinishUpdate();
+    }
+  } else if (created_default_child) {
+    if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
+      gpr_log(GPR_INFO, "[rlslb %p] finishing default child policy update",
+              this);
+    }
+    default_child_policy_->MaybeFinishUpdate();
+  }
+  // In principle, we need to update the picker here only if the config
+  // fields used by the picker have changed.  However, it seems fragile
+  // to check individual fields, since the picker logic could change in
+  // the future to use additional config fields, and we might not
+  // remember to update the code here.  So for now, we just unconditionally
+  // update the picker here, even though it's probably redundant.
+  UpdatePickerLocked();
+}
+
+void RlsLb::ExitIdleLocked() {
+  MutexLock lock(&mu_);
+  for (auto& child_entry : child_policy_map_) {
+    child_entry.second->ExitIdleLocked();
+  }
+}
+
+void RlsLb::ResetBackoffLocked() {
+  {
+    MutexLock lock(&mu_);
+    rls_channel_->ResetBackoff();
+    cache_.ResetAllBackoff();
+  }
+  for (auto& child : child_policy_map_) {
+    child.second->ResetBackoffLocked();
+  }
+}
+
+void RlsLb::ShutdownLocked() {
+  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
+    gpr_log(GPR_INFO, "[rlslb %p] policy shutdown", this);
+  }
+  MutexLock lock(&mu_);
+  is_shutdown_ = true;
+  config_.reset(DEBUG_LOCATION, "ShutdownLocked");
+  if (channel_args_ != nullptr) {
+    grpc_channel_args_destroy(channel_args_);
+  }
+  cache_.Shutdown();
+  request_map_.clear();
+  rls_channel_.reset();
+  default_child_policy_.reset();
+}
+
+void RlsLb::UpdatePickerAsync() {
+  // Run via the ExecCtx, since the caller may be holding the lock, and
+  // we don't want to be doing that when we hop into the WorkSerializer,
+  // in case the WorkSerializer callback happens to run inline.
+  ExecCtx::Run(
+      DEBUG_LOCATION,
+      GRPC_CLOSURE_CREATE(UpdatePickerCallback,
+                          Ref(DEBUG_LOCATION, "UpdatePickerCallback").release(),
+                          grpc_schedule_on_exec_ctx),
+      GRPC_ERROR_NONE);
+}
+
+void RlsLb::UpdatePickerCallback(void* arg, grpc_error_handle /*error*/) {
+  auto* rls_lb = static_cast<RlsLb*>(arg);
+  rls_lb->work_serializer()->Run(
+      [rls_lb]() {
+        RefCountedPtr<RlsLb> lb_policy(rls_lb);
+        lb_policy->UpdatePickerLocked();
+        lb_policy.reset(DEBUG_LOCATION, "UpdatePickerCallback");
+      },
+      DEBUG_LOCATION);
+}
+
+void RlsLb::UpdatePickerLocked() {
+  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
+    gpr_log(GPR_INFO, "[rlslb %p] updating picker", this);
+  }
+  grpc_connectivity_state state = GRPC_CHANNEL_IDLE;
+  if (!child_policy_map_.empty()) {
+    state = GRPC_CHANNEL_TRANSIENT_FAILURE;
+    int num_idle = 0;
+    int num_connecting = 0;
+    {
+      MutexLock lock(&mu_);
+      if (is_shutdown_) return;
+      for (auto& p : child_policy_map_) {
+        grpc_connectivity_state child_state = p.second->connectivity_state();
+        if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
+          gpr_log(GPR_INFO, "[rlslb %p] target %s in state %s", this,
+                  p.second->target().c_str(),
+                  ConnectivityStateName(child_state));
+        }
+        if (child_state == GRPC_CHANNEL_READY) {
+          state = GRPC_CHANNEL_READY;
+          break;
+        } else if (child_state == GRPC_CHANNEL_CONNECTING) {
+          ++num_connecting;
+        } else if (child_state == GRPC_CHANNEL_IDLE) {
+          ++num_idle;
+        }
+      }
+      if (state != GRPC_CHANNEL_READY) {
+        if (num_connecting > 0) {
+          state = GRPC_CHANNEL_CONNECTING;
+        } else if (num_idle > 0) {
+          state = GRPC_CHANNEL_IDLE;
+        }
+      }
+    }
+  }
+  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
+    gpr_log(GPR_INFO, "[rlslb %p] reporting state %s", this,
+            ConnectivityStateName(state));
+  }
+  absl::Status status;
+  if (state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
+    status = absl::UnavailableError("no children available");
+  }
+  channel_control_helper()->UpdateState(
+      state, status, absl::make_unique<Picker>(Ref(DEBUG_LOCATION, "Picker")));
+}
+
+//
+// RlsLbFactory
+//
+
+grpc_error_handle ParseJsonHeaders(size_t idx, const Json& json,
+                                   std::string* key,
+                                   std::vector<std::string>* headers) {
+  if (json.type() != Json::Type::OBJECT) {
+    return GRPC_ERROR_CREATE_FROM_CPP_STRING(absl::StrCat(
+        "field:headers index:", idx, " error:type should be OBJECT"));
+  }
+  std::vector<grpc_error_handle> error_list;
+  // requiredMatch must not be present.
+  if (json.object_value().find("requiredMatch") != json.object_value().end()) {
+    error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+        "field:requiredMatch error:must not be present"));
+  }
+  // Find key.
+  if (ParseJsonObjectField(json.object_value(), "key", key, &error_list) &&
+      key->empty()) {
+    error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+        "field:key error:must be non-empty"));
+  }
+  // Find headers.
+  const Json::Array* headers_json = nullptr;
+  ParseJsonObjectField(json.object_value(), "names", &headers_json,
+                       &error_list);
+  if (headers_json != nullptr) {
+    if (headers_json->empty()) {
+      error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+          "field:names error:list is empty"));
+    } else {
+      size_t name_idx = 0;
+      for (const Json& name_json : *headers_json) {
+        if (name_json.type() != Json::Type::STRING) {
+          error_list.push_back(GRPC_ERROR_CREATE_FROM_CPP_STRING(absl::StrCat(
+              "field:names index:", name_idx, " error:type should be STRING")));
+        } else if (name_json.string_value().empty()) {
+          error_list.push_back(GRPC_ERROR_CREATE_FROM_CPP_STRING(
+              absl::StrCat("field:names index:", name_idx,
+                           " error:header name must be non-empty")));
+        } else {
+          headers->push_back(name_json.string_value());
+        }
+        ++name_idx;
+      }
+    }
+  }
+  return GRPC_ERROR_CREATE_FROM_VECTOR_AND_CPP_STRING(
+      absl::StrCat("field:headers index:", idx), &error_list);
+}
+
+std::string ParseJsonMethodName(size_t idx, const Json& json,
+                                grpc_error_handle* error) {
+  if (json.type() != Json::Type::OBJECT) {
+    *error = GRPC_ERROR_CREATE_FROM_CPP_STRING(absl::StrCat(
+        "field:names index:", idx, " error:type should be OBJECT"));
+    return "";
+  }
+  std::vector<grpc_error_handle> error_list;
+  // Find service name.
+  absl::string_view service_name;
+  ParseJsonObjectField(json.object_value(), "service", &service_name,
+                       &error_list);
+  // Find method name.
+  absl::string_view method_name;
+  ParseJsonObjectField(json.object_value(), "method", &method_name, &error_list,
+                       /*required=*/false);
+  // Return error, if any.
+  *error = GRPC_ERROR_CREATE_FROM_VECTOR_AND_CPP_STRING(
+      absl::StrCat("field:names index:", idx), &error_list);
+  // Construct path.
+  return absl::StrCat("/", service_name, "/", method_name);
+}
+
+grpc_error_handle ParseGrpcKeybuilder(
+    size_t idx, const Json& json, RlsLbConfig::KeyBuilderMap* key_builder_map) {
+  if (json.type() != Json::Type::OBJECT) {
+    return GRPC_ERROR_CREATE_FROM_CPP_STRING(absl::StrCat(
+        "field:grpc_keybuilders index:", idx, " error:type should be OBJECT"));
+  }
+  std::vector<grpc_error_handle> error_list;
+  // Parse names.
+  std::set<std::string> names;
+  const Json::Array* names_array = nullptr;
+  if (ParseJsonObjectField(json.object_value(), "names", &names_array,
+                           &error_list)) {
+    if (names_array->empty()) {
+      error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+          "field:names error:list is empty"));
+    } else {
+      size_t name_idx = 0;
+      for (const Json& name_json : *names_array) {
+        grpc_error_handle child_error = GRPC_ERROR_NONE;
+        std::string name =
+            ParseJsonMethodName(name_idx++, name_json, &child_error);
+        if (child_error != GRPC_ERROR_NONE) {
+          error_list.push_back(child_error);
+        } else {
+          bool inserted = names.insert(name).second;
+          if (!inserted) {
+            error_list.push_back(GRPC_ERROR_CREATE_FROM_CPP_STRING(
+                absl::StrCat("field:names error:duplicate entry for ", name)));
+          }
+        }
+      }
+    }
+  }
+  // Helper function to check for duplicate keys.
+  std::set<std::string> all_keys;
+  auto duplicate_key_check_func = [&all_keys,
+                                   &error_list](const std::string& key) {
+    auto it = all_keys.find(key);
+    if (it != all_keys.end()) {
+      error_list.push_back(GRPC_ERROR_CREATE_FROM_CPP_STRING(
+          absl::StrCat("key \"", key, "\" listed multiple times")));
+    } else {
+      all_keys.insert(key);
+    }
+  };
+  // Parse headers.
+  RlsLbConfig::KeyBuilder key_builder;
+  const Json::Array* headers_array = nullptr;
+  ParseJsonObjectField(json.object_value(), "headers", &headers_array,
+                       &error_list, /*required=*/false);
+  if (headers_array != nullptr) {
+    size_t header_idx = 0;
+    for (const Json& header_json : *headers_array) {
+      std::string key;
+      std::vector<std::string> headers;
+      grpc_error_handle child_error =
+          ParseJsonHeaders(header_idx++, header_json, &key, &headers);
+      if (child_error != GRPC_ERROR_NONE) {
+        error_list.push_back(child_error);
+      } else {
+        duplicate_key_check_func(key);
+        key_builder.header_keys.emplace(key, std::move(headers));
+      }
+    }
+  }
+  // Parse extraKeys.
+  const Json::Object* extra_keys = nullptr;
+  ParseJsonObjectField(json.object_value(), "extraKeys", &extra_keys,
+                       &error_list, /*required=*/false);
+  if (extra_keys != nullptr) {
+    std::vector<grpc_error_handle> extra_keys_errors;
+    if (ParseJsonObjectField(*extra_keys, "host", &key_builder.host_key,
+                             &extra_keys_errors, /*required=*/false) &&
+        key_builder.host_key.empty()) {
+      extra_keys_errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+          "field:host error:must be non-empty"));
+    }
+    if (!key_builder.host_key.empty()) {
+      duplicate_key_check_func(key_builder.host_key);
+    }
+    if (ParseJsonObjectField(*extra_keys, "service", &key_builder.service_key,
+                             &extra_keys_errors, /*required=*/false) &&
+        key_builder.service_key.empty()) {
+      extra_keys_errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+          "field:service error:must be non-empty"));
+    }
+    if (!key_builder.service_key.empty()) {
+      duplicate_key_check_func(key_builder.service_key);
+    }
+    if (ParseJsonObjectField(*extra_keys, "method", &key_builder.method_key,
+                             &extra_keys_errors, /*required=*/false) &&
+        key_builder.method_key.empty()) {
+      extra_keys_errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+          "field:method error:must be non-empty"));
+    }
+    if (!key_builder.method_key.empty()) {
+      duplicate_key_check_func(key_builder.method_key);
+    }
+    if (!extra_keys_errors.empty()) {
+      error_list.push_back(
+          GRPC_ERROR_CREATE_FROM_VECTOR("field:extraKeys", &extra_keys_errors));
+    }
+  }
+  // Parse constantKeys.
+  const Json::Object* constant_keys = nullptr;
+  ParseJsonObjectField(json.object_value(), "constantKeys", &constant_keys,
+                       &error_list, /*required=*/false);
+  if (constant_keys != nullptr) {
+    std::vector<grpc_error_handle> constant_keys_errors;
+    for (const auto& p : *constant_keys) {
+      const std::string& key = p.first;
+      const Json& value = p.second;
+      if (key.empty()) {
+        constant_keys_errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+            "error:keys must be non-empty"));
+      }
+      duplicate_key_check_func(key);
+      ExtractJsonString(value, key, &key_builder.constant_keys[key],
+                        &constant_keys_errors);
+    }
+    if (!constant_keys_errors.empty()) {
+      error_list.push_back(GRPC_ERROR_CREATE_FROM_VECTOR(
+          "field:constantKeys", &constant_keys_errors));
+    }
+  }
+  // Insert key_builder into key_builder_map.
+  for (const std::string& name : names) {
+    bool inserted = key_builder_map->emplace(name, key_builder).second;
+    if (!inserted) {
+      error_list.push_back(GRPC_ERROR_CREATE_FROM_CPP_STRING(
+          absl::StrCat("field:names error:duplicate entry for ", name)));
+    }
+  }
+  return GRPC_ERROR_CREATE_FROM_VECTOR_AND_CPP_STRING(
+      absl::StrCat("index:", idx), &error_list);
+}
+
+RlsLbConfig::KeyBuilderMap ParseGrpcKeybuilders(
+    const Json::Array& key_builder_list, grpc_error_handle* error) {
+  RlsLbConfig::KeyBuilderMap key_builder_map;
+  if (key_builder_list.empty()) {
+    *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+        "field:grpcKeybuilders error:list is empty");
+    return key_builder_map;
+  }
+  std::vector<grpc_error_handle> error_list;
+  size_t idx = 0;
+  for (const Json& key_builder : key_builder_list) {
+    grpc_error_handle child_error =
+        ParseGrpcKeybuilder(idx++, key_builder, &key_builder_map);
+    if (child_error != GRPC_ERROR_NONE) error_list.push_back(child_error);
+  }
+  *error = GRPC_ERROR_CREATE_FROM_VECTOR("field:grpcKeybuilders", &error_list);
+  return key_builder_map;
+}
+
+RlsLbConfig::RouteLookupConfig ParseRouteLookupConfig(
+    const Json::Object& json, grpc_error_handle* error) {
+  std::vector<grpc_error_handle> error_list;
+  RlsLbConfig::RouteLookupConfig route_lookup_config;
+  // Parse grpcKeybuilders.
+  const Json::Array* keybuilder_list = nullptr;
+  ParseJsonObjectField(json, "grpcKeybuilders", &keybuilder_list, &error_list);
+  if (keybuilder_list != nullptr) {
+    grpc_error_handle child_error = GRPC_ERROR_NONE;
+    route_lookup_config.key_builder_map =
+        ParseGrpcKeybuilders(*keybuilder_list, &child_error);
+    if (child_error != GRPC_ERROR_NONE) error_list.push_back(child_error);
+  }
+  // Parse lookupService.
+  if (ParseJsonObjectField(json, "lookupService",
+                           &route_lookup_config.lookup_service, &error_list)) {
+    if (!ResolverRegistry::IsValidTarget(route_lookup_config.lookup_service)) {
+      error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+          "field:lookupService error:must be valid gRPC target URI"));
+    }
+  }
+  // Parse lookupServiceTimeout.
+  route_lookup_config.lookup_service_timeout = kDefaultLookupServiceTimeout;
+  ParseJsonObjectFieldAsDuration(json, "lookupServiceTimeout",
+                                 &route_lookup_config.lookup_service_timeout,
+                                 &error_list, /*required=*/false);
+  // Parse maxAge.
+  route_lookup_config.max_age = kMaxMaxAge;
+  bool max_age_set = ParseJsonObjectFieldAsDuration(
+      json, "maxAge", &route_lookup_config.max_age, &error_list,
+      /*required=*/false);
+  // Clamp maxAge to the max allowed value.
+  if (route_lookup_config.max_age > kMaxMaxAge) {
+    route_lookup_config.max_age = kMaxMaxAge;
+  }
+  // Parse staleAge.
+  route_lookup_config.stale_age = kMaxMaxAge;
+  bool stale_age_set = ParseJsonObjectFieldAsDuration(
+      json, "staleAge", &route_lookup_config.stale_age, &error_list,
+      /*required=*/false);
+  // If staleAge is set, then maxAge must also be set.
+  if (stale_age_set && !max_age_set) {
+    error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+        "field:maxAge error:must be set if staleAge is set"));
+  }
+  // Ignore staleAge if greater than or equal to maxAge.
+  if (route_lookup_config.stale_age >= route_lookup_config.max_age) {
+    route_lookup_config.stale_age = route_lookup_config.max_age;
+  }
+  // Parse cacheSizeBytes.
+  ParseJsonObjectField(json, "cacheSizeBytes",
+                       &route_lookup_config.cache_size_bytes, &error_list);
+  if (route_lookup_config.cache_size_bytes <= 0) {
+    error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+        "field:cacheSizeBytes error:must be greater than 0"));
+  }
+  // Clamp cacheSizeBytes to the max allowed value.
+  if (route_lookup_config.cache_size_bytes > kMaxCacheSizeBytes) {
+    route_lookup_config.cache_size_bytes = kMaxCacheSizeBytes;
+  }
+  // Parse defaultTarget.
+  if (ParseJsonObjectField(json, "defaultTarget",
+                           &route_lookup_config.default_target, &error_list,
+                           /*required=*/false)) {
+    if (route_lookup_config.default_target.empty()) {
+      error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+          "field:defaultTarget error:must be non-empty if set"));
+    }
+  }
+  *error =
+      GRPC_ERROR_CREATE_FROM_VECTOR("field:routeLookupConfig", &error_list);
+  return route_lookup_config;
+}
+
+grpc_error_handle ValidateChildPolicyList(
+    const Json& child_policy_list,
+    const std::string& child_policy_config_target_field_name,
+    const std::string& default_target, Json* child_policy_config,
+    RefCountedPtr<LoadBalancingPolicy::Config>*
+        default_child_policy_parsed_config) {
+  // Add target to each entry in the config proto.
+  *child_policy_config = child_policy_list;
+  std::string target =
+      default_target.empty() ? kFakeTargetFieldValue : default_target;
+  grpc_error_handle error = InsertOrUpdateChildPolicyField(
+      child_policy_config_target_field_name, target, child_policy_config);
+  if (error != GRPC_ERROR_NONE) return error;
+  // Parse the config.
+  RefCountedPtr<LoadBalancingPolicy::Config> parsed_config =
+      LoadBalancingPolicyRegistry::ParseLoadBalancingConfig(
+          *child_policy_config, &error);
+  if (error != GRPC_ERROR_NONE) return error;
+  // Find the chosen config and return it in JSON form.
+  // We remove all non-selected configs, and in the selected config, we leave
+  // the target field in place, set to the default value.  This slightly
+  // optimizes what we need to do later when we update a child policy for a
+  // given target.
+  if (parsed_config != nullptr) {
+    for (Json& config : *(child_policy_config->mutable_array())) {
+      if (config.object_value().begin()->first == parsed_config->name()) {
+        Json save_config = std::move(config);
+        child_policy_config->mutable_array()->clear();
+        child_policy_config->mutable_array()->push_back(std::move(save_config));
+        break;
+      }
+    }
+  }
+  // If default target is set, return the parsed config.
+  if (!default_target.empty()) {
+    *default_child_policy_parsed_config = std::move(parsed_config);
+  }
+  return GRPC_ERROR_NONE;
+}
+
+class RlsLbFactory : public LoadBalancingPolicyFactory {
+ public:
+  const char* name() const override { return kRls; }
+
+  OrphanablePtr<LoadBalancingPolicy> CreateLoadBalancingPolicy(
+      LoadBalancingPolicy::Args args) const override {
+    return MakeOrphanable<RlsLb>(std::move(args));
+  }
+
+  RefCountedPtr<LoadBalancingPolicy::Config> ParseLoadBalancingConfig(
+      const Json& config, grpc_error_handle* error) const override {
+    std::vector<grpc_error_handle> error_list;
+    // Parse routeLookupConfig.
+    RlsLbConfig::RouteLookupConfig route_lookup_config;
+    const Json::Object* route_lookup_config_json = nullptr;
+    if (ParseJsonObjectField(config.object_value(), "routeLookupConfig",
+                             &route_lookup_config_json, &error_list)) {
+      grpc_error_handle child_error = GRPC_ERROR_NONE;
+      route_lookup_config =
+          ParseRouteLookupConfig(*route_lookup_config_json, &child_error);
+      if (child_error != GRPC_ERROR_NONE) error_list.push_back(child_error);
+    }
+    // Parse childPolicyConfigTargetFieldName.
+    std::string child_policy_config_target_field_name;
+    if (ParseJsonObjectField(
+            config.object_value(), "childPolicyConfigTargetFieldName",
+            &child_policy_config_target_field_name, &error_list)) {
+      if (child_policy_config_target_field_name.empty()) {
+        error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+            "field:childPolicyConfigTargetFieldName error:must be non-empty"));
+      }
+    }
+    // Parse childPolicy.
+    Json child_policy_config;
+    RefCountedPtr<LoadBalancingPolicy::Config>
+        default_child_policy_parsed_config;
+    auto it = config.object_value().find("childPolicy");
+    if (it == config.object_value().end()) {
+      error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+          "field:childPolicy error:does not exist."));
+    } else if (it->second.type() != Json::Type::ARRAY) {
+      error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+          "field:childPolicy error:type should be ARRAY"));
+    } else {
+      grpc_error_handle child_error = ValidateChildPolicyList(
+          it->second, child_policy_config_target_field_name,
+          route_lookup_config.default_target, &child_policy_config,
+          &default_child_policy_parsed_config);
+      if (child_error != GRPC_ERROR_NONE) {
+        error_list.push_back(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
+            "field:childPolicy", &child_error, 1));
+        GRPC_ERROR_UNREF(child_error);
+      }
+    }
+    // Return result.
+    *error = GRPC_ERROR_CREATE_FROM_VECTOR(
+        "errors parsing RLS LB policy config", &error_list);
+    return MakeRefCounted<RlsLbConfig>(
+        std::move(route_lookup_config), std::move(child_policy_config),
+        std::move(child_policy_config_target_field_name),
+        std::move(default_child_policy_parsed_config));
+  }
+};
+
+bool RlsEnabled() {
+  char* value = gpr_getenv("GRPC_EXPERIMENTAL_ENABLE_RLS_LB_POLICY");
+  bool parsed_value;
+  bool parse_succeeded = gpr_parse_bool_value(value, &parsed_value);
+  gpr_free(value);
+  return parse_succeeded && parsed_value;
+}
+
+}  //  namespace
+
+void RlsLbPluginInit() {
+  if (!RlsEnabled()) return;
+  LoadBalancingPolicyRegistry::Builder::RegisterLoadBalancingPolicyFactory(
+      absl::make_unique<RlsLbFactory>());
+}
+
+void RlsLbPluginShutdown() {}
+
+}  // namespace grpc_core
index d8269fd..675ecf4 100644 (file)
@@ -339,7 +339,12 @@ void RoundRobin::RoundRobinSubchannelList::
 void RoundRobin::RoundRobinSubchannelList::
     UpdateRoundRobinStateFromSubchannelStateCountsLocked() {
   RoundRobin* p = static_cast<RoundRobin*>(policy());
-  if (num_ready_ > 0) {
+  // If we have at least one READY subchannel, then swap to the new list.
+  // Also, if all of the subchannels are in TRANSIENT_FAILURE, then we know
+  // we've tried all of them and failed, so we go ahead and swap over
+  // anyway; this may cause the channel to go from READY to TRANSIENT_FAILURE,
+  // but we are doing what the control plane told us to do.
+  if (num_ready_ > 0 || num_transient_failure_ == num_subchannels()) {
     if (p->subchannel_list_.get() != this) {
       // Promote this list to p->subchannel_list_.
       // This list must be p->latest_pending_subchannel_list_, because
index 8697870..785975d 100644 (file)
@@ -150,6 +150,7 @@ class WeightedTargetLb : public LoadBalancingPolicy {
                        const absl::Status& status,
                        std::unique_ptr<SubchannelPicker> picker) override;
       void RequestReresolution() override;
+      absl::string_view GetAuthority() override;
       void AddTraceEvent(TraceSeverity severity,
                          absl::string_view message) override;
 
@@ -564,7 +565,7 @@ void WeightedTargetLb::WeightedChild::DeactivateLocked() {
 void WeightedTargetLb::WeightedChild::OnDelayedRemovalTimer(
     void* arg, grpc_error_handle error) {
   WeightedChild* self = static_cast<WeightedChild*>(arg);
-  GRPC_ERROR_REF(error);  // ref owned by lambda
+  (void)GRPC_ERROR_REF(error);  // ref owned by lambda
   self->weighted_target_policy_->work_serializer()->Run(
       [self, error]() { self->OnDelayedRemovalTimerLocked(error); },
       DEBUG_LOCATION);
@@ -607,6 +608,11 @@ void WeightedTargetLb::WeightedChild::Helper::RequestReresolution() {
       ->RequestReresolution();
 }
 
+absl::string_view WeightedTargetLb::WeightedChild::Helper::GetAuthority() {
+  return weighted_child_->weighted_target_policy_->channel_control_helper()
+      ->GetAuthority();
+}
+
 void WeightedTargetLb::WeightedChild::Helper::AddTraceEvent(
     TraceSeverity severity, absl::string_view message) {
   if (weighted_child_->weighted_target_policy_->shutting_down_) return;
index 3bbc8fe..49a4496 100644 (file)
@@ -23,7 +23,6 @@
 #include "src/core/ext/filters/client_channel/lb_policy.h"
 #include "src/core/ext/filters/client_channel/lb_policy_factory.h"
 #include "src/core/ext/filters/client_channel/lb_policy_registry.h"
-#include "src/core/ext/filters/client_channel/service_config.h"
 #include "src/core/ext/xds/xds_certificate_provider.h"
 #include "src/core/ext/xds/xds_client.h"
 #include "src/core/lib/channel/channel_args.h"
@@ -123,6 +122,7 @@ class CdsLb : public LoadBalancingPolicy {
     void UpdateState(grpc_connectivity_state state, const absl::Status& status,
                      std::unique_ptr<SubchannelPicker> picker) override;
     void RequestReresolution() override;
+    absl::string_view GetAuthority() override;
     void AddTraceEvent(TraceSeverity severity,
                        absl::string_view message) override;
 
@@ -207,7 +207,7 @@ CdsLb::ClusterWatcher::Notifier::Notifier(RefCountedPtr<CdsLb> parent,
 void CdsLb::ClusterWatcher::Notifier::RunInExecCtx(void* arg,
                                                    grpc_error_handle error) {
   Notifier* self = static_cast<Notifier*>(arg);
-  GRPC_ERROR_REF(error);
+  (void)GRPC_ERROR_REF(error);
   self->parent_->work_serializer()->Run(
       [self, error]() { self->RunInWorkSerializer(error); }, DEBUG_LOCATION);
 }
@@ -261,6 +261,10 @@ void CdsLb::Helper::RequestReresolution() {
   parent_->channel_control_helper()->RequestReresolution();
 }
 
+absl::string_view CdsLb::Helper::GetAuthority() {
+  return parent_->channel_control_helper()->GetAuthority();
+}
+
 void CdsLb::Helper::AddTraceEvent(TraceSeverity severity,
                                   absl::string_view message) {
   if (parent_->shutting_down_) return;
index 2351502..430f88d 100644 (file)
@@ -24,6 +24,6 @@
 // For testing purpose, this channel arg indicating xds_cluster_resolver LB
 // policy should use the fake DNS resolver to resolve logical dns cluster.
 #define GRPC_ARG_XDS_LOGICAL_DNS_CLUSTER_FAKE_RESOLVER_RESPONSE_GENERATOR \
-  "grpc.internal.xds_logical_dns_cluster_fake_resolver_response_generator"
+  "grpc.TEST_ONLY.xds_logical_dns_cluster_fake_resolver_response_generator"
 
 #endif  // GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_XDS_XDS_CHANNEL_ARGS_H
index bce03ce..c65fa33 100644 (file)
@@ -222,6 +222,7 @@ class XdsClusterImplLb : public LoadBalancingPolicy {
     void UpdateState(grpc_connectivity_state state, const absl::Status& status,
                      std::unique_ptr<SubchannelPicker> picker) override;
     void RequestReresolution() override;
+    absl::string_view GetAuthority() override;
     void AddTraceEvent(TraceSeverity severity,
                        absl::string_view message) override;
 
@@ -576,6 +577,10 @@ void XdsClusterImplLb::Helper::RequestReresolution() {
   xds_cluster_impl_policy_->channel_control_helper()->RequestReresolution();
 }
 
+absl::string_view XdsClusterImplLb::Helper::GetAuthority() {
+  return xds_cluster_impl_policy_->channel_control_helper()->GetAuthority();
+}
+
 void XdsClusterImplLb::Helper::AddTraceEvent(TraceSeverity severity,
                                              absl::string_view message) {
   if (xds_cluster_impl_policy_->shutting_down_) return;
index 214d087..0455204 100644 (file)
@@ -151,6 +151,7 @@ class XdsClusterManagerLb : public LoadBalancingPolicy {
                        const absl::Status& status,
                        std::unique_ptr<SubchannelPicker> picker) override;
       void RequestReresolution() override;
+      absl::string_view GetAuthority() override;
       void AddTraceEvent(TraceSeverity severity,
                          absl::string_view message) override;
 
@@ -493,7 +494,7 @@ void XdsClusterManagerLb::ClusterChild::DeactivateLocked() {
 void XdsClusterManagerLb::ClusterChild::OnDelayedRemovalTimer(
     void* arg, grpc_error_handle error) {
   ClusterChild* self = static_cast<ClusterChild*>(arg);
-  GRPC_ERROR_REF(error);  // Ref owned by the lambda
+  (void)GRPC_ERROR_REF(error);  // Ref owned by the lambda
   self->xds_cluster_manager_policy_->work_serializer()->Run(
       [self, error]() { self->OnDelayedRemovalTimerLocked(error); },
       DEBUG_LOCATION);
@@ -570,6 +571,12 @@ void XdsClusterManagerLb::ClusterChild::Helper::RequestReresolution() {
       ->RequestReresolution();
 }
 
+absl::string_view XdsClusterManagerLb::ClusterChild::Helper::GetAuthority() {
+  return xds_cluster_manager_child_->xds_cluster_manager_policy_
+      ->channel_control_helper()
+      ->GetAuthority();
+}
+
 void XdsClusterManagerLb::ClusterChild::Helper::AddTraceEvent(
     TraceSeverity severity, absl::string_view message) {
   if (xds_cluster_manager_child_->xds_cluster_manager_policy_->shutting_down_) {
index ff936b9..8ca5f06 100644 (file)
@@ -299,6 +299,7 @@ class XdsClusterResolverLb : public LoadBalancingPolicy {
     // This is a no-op, because we get the addresses from the xds
     // client, which is a watch-based API.
     void RequestReresolution() override {}
+    absl::string_view GetAuthority() override;
     void AddTraceEvent(TraceSeverity severity,
                        absl::string_view message) override;
 
@@ -380,6 +381,10 @@ void XdsClusterResolverLb::Helper::UpdateState(
       state, status, std::move(picker));
 }
 
+absl::string_view XdsClusterResolverLb::Helper::GetAuthority() {
+  return xds_cluster_resolver_policy_->channel_control_helper()->GetAuthority();
+}
+
 void XdsClusterResolverLb::Helper::AddTraceEvent(TraceSeverity severity,
                                                  absl::string_view message) {
   if (xds_cluster_resolver_policy_->shutting_down_) return;
@@ -453,7 +458,7 @@ XdsClusterResolverLb::EdsDiscoveryMechanism::EndpointWatcher::Notifier::
 void XdsClusterResolverLb::EdsDiscoveryMechanism::EndpointWatcher::Notifier::
     RunInExecCtx(void* arg, grpc_error_handle error) {
   Notifier* self = static_cast<Notifier*>(arg);
-  GRPC_ERROR_REF(error);
+  (void)GRPC_ERROR_REF(error);
   self->discovery_mechanism_->parent()->work_serializer()->Run(
       [self, error]() { self->RunInWorkSerializer(error); }, DEBUG_LOCATION);
 }
@@ -572,13 +577,6 @@ XdsClusterResolverLb::XdsClusterResolverLb(RefCountedPtr<XdsClient> xds_client,
   }
   // EDS-only flow.
   if (!is_xds_uri_) {
-    // Setup channelz linkage.
-    channelz::ChannelNode* parent_channelz_node =
-        grpc_channel_args_find_pointer<channelz::ChannelNode>(
-            args.args, GRPC_ARG_CHANNELZ_CHANNEL_NODE);
-    if (parent_channelz_node != nullptr) {
-      xds_client_->AddChannelzLinkage(parent_channelz_node);
-    }
     // Couple polling.
     grpc_pollset_set_add_pollset_set(xds_client_->interested_parties(),
                                      interested_parties());
@@ -602,13 +600,6 @@ void XdsClusterResolverLb::ShutdownLocked() {
   MaybeDestroyChildPolicyLocked();
   discovery_mechanisms_.clear();
   if (!is_xds_uri_) {
-    // Remove channelz linkage.
-    channelz::ChannelNode* parent_channelz_node =
-        grpc_channel_args_find_pointer<channelz::ChannelNode>(
-            args_, GRPC_ARG_CHANNELZ_CHANNEL_NODE);
-    if (parent_channelz_node != nullptr) {
-      xds_client_->RemoveChannelzLinkage(parent_channelz_node);
-    }
     // Decouple polling.
     grpc_pollset_set_del_pollset_set(xds_client_->interested_parties(),
                                      interested_parties());
@@ -1171,7 +1162,7 @@ class XdsClusterResolverLbFactory : public LoadBalancingPolicyFactory {
         if (!discovery_mechanism_errors.empty()) {
           grpc_error_handle error = GRPC_ERROR_CREATE_FROM_CPP_STRING(
               absl::StrCat("field:discovery_mechanism element: ", i, " error"));
-          for (grpc_error_handle discovery_mechanism_error :
+          for (const grpc_error_handle& discovery_mechanism_error :
                discovery_mechanism_errors) {
             error = grpc_error_add_child(error, discovery_mechanism_error);
           }
index a595c27..d8163ce 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "src/core/ext/filters/client_channel/lb_policy.h"
 #include "src/core/lib/gprpp/orphanable.h"
+#include "src/core/lib/json/json.h"
 
 namespace grpc_core {
 
index 2ab7409..028baa9 100644 (file)
@@ -24,7 +24,7 @@
 #include <grpc/impl/codegen/grpc_types.h>
 
 #include "src/core/ext/filters/client_channel/server_address.h"
-#include "src/core/ext/filters/client_channel/service_config.h"
+#include "src/core/ext/service_config/service_config.h"
 #include "src/core/lib/gprpp/orphanable.h"
 #include "src/core/lib/gprpp/ref_counted_ptr.h"
 #include "src/core/lib/iomgr/iomgr.h"
diff --git a/src/core/ext/filters/client_channel/resolver/binder/README.md b/src/core/ext/filters/client_channel/resolver/binder/README.md
new file mode 100644 (file)
index 0000000..b602967
--- /dev/null
@@ -0,0 +1,9 @@
+Support for resolving the scheme used by binder transport implementation.
+
+The URI's authority is required to be empty.
+
+The path is used as the identifiers of endpoint binder objects and the length
+limit of the identifier is the same as unix socket length limit.
+
+The length limit of the path should at least be 100 characters long. This is
+guaranteed by `static_assert` in the implementation.
diff --git a/src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc b/src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc
new file mode 100644 (file)
index 0000000..68f21c8
--- /dev/null
@@ -0,0 +1,139 @@
+// 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 <grpc/support/port_platform.h>
+
+#include "src/core/lib/iomgr/port.h"
+
+#ifdef GRPC_HAVE_UNIX_SOCKET
+
+#include <sys/un.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/string_util.h>
+
+#include "src/core/ext/filters/client_channel/resolver_registry.h"
+#include "src/core/ext/filters/client_channel/server_address.h"
+#include "src/core/lib/address_utils/parse_address.h"
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/gpr/string.h"
+
+namespace grpc_core {
+namespace {
+
+class BinderResolver : public Resolver {
+ public:
+  BinderResolver(ServerAddressList addresses, ResolverArgs args)
+      : result_handler_(std::move(args.result_handler)),
+        addresses_(std::move(addresses)),
+        channel_args_(grpc_channel_args_copy(args.args)) {}
+
+  ~BinderResolver() override { grpc_channel_args_destroy(channel_args_); };
+
+  void StartLocked() override {
+    Result result;
+    result.addresses = std::move(addresses_);
+    result.args = channel_args_;
+    channel_args_ = nullptr;
+    result_handler_->ReturnResult(std::move(result));
+  }
+
+  void ShutdownLocked() override {}
+
+ private:
+  std::unique_ptr<ResultHandler> result_handler_;
+  ServerAddressList addresses_;
+  const grpc_channel_args* channel_args_ = nullptr;
+};
+
+class BinderResolverFactory : public ResolverFactory {
+ public:
+  bool IsValidUri(const URI& uri) const override {
+    return ParseUri(uri, nullptr);
+  }
+
+  OrphanablePtr<Resolver> CreateResolver(ResolverArgs args) const override {
+    ServerAddressList addresses;
+    if (!ParseUri(args.uri, &addresses)) return nullptr;
+    return MakeOrphanable<BinderResolver>(std::move(addresses),
+                                          std::move(args));
+  }
+
+  const char* scheme() const override { return "binder"; }
+
+ private:
+  static grpc_error_handle BinderAddrPopulate(
+      absl::string_view path, grpc_resolved_address* resolved_addr) {
+    path = absl::StripPrefix(path, "/");
+    if (path.empty()) {
+      return GRPC_ERROR_CREATE_FROM_CPP_STRING("path is empty");
+    }
+    // Store parsed path in a unix socket so it can be reinterpreted as
+    // sockaddr. An invalid address family (AF_MAX) is set to make sure it won't
+    // be accidentally used.
+    memset(resolved_addr, 0, sizeof(*resolved_addr));
+    struct sockaddr_un* un =
+        reinterpret_cast<struct sockaddr_un*>(resolved_addr->addr);
+    un->sun_family = AF_MAX;
+    static_assert(sizeof(un->sun_path) >= 101,
+                  "unix socket path size is unexpectedly short");
+    if (path.size() + 1 > sizeof(un->sun_path)) {
+      return GRPC_ERROR_CREATE_FROM_CPP_STRING(
+          absl::StrCat(path, " is too long to be handled"));
+    }
+    // `un` has already be set to zero, no need to append null after the string
+    memcpy(un->sun_path, path.data(), path.size());
+    resolved_addr->len =
+        static_cast<socklen_t>(sizeof(un->sun_family) + path.size() + 1);
+    return GRPC_ERROR_NONE;
+  }
+
+  static bool ParseUri(const URI& uri, ServerAddressList* addresses) {
+    grpc_resolved_address addr;
+    {
+      if (!uri.authority().empty()) {
+        gpr_log(GPR_ERROR, "authority is not supported in binder scheme");
+        return false;
+      }
+      grpc_error_handle error = BinderAddrPopulate(uri.path(), &addr);
+      if (error != GRPC_ERROR_NONE) {
+        gpr_log(GPR_ERROR, "%s", grpc_error_std_string(error).c_str());
+        GRPC_ERROR_UNREF(error);
+        return false;
+      }
+    }
+    if (addresses != nullptr) {
+      addresses->emplace_back(addr, nullptr /* args */);
+    }
+    return true;
+  }
+};
+
+}  // namespace
+}  // namespace grpc_core
+
+void grpc_resolver_binder_init() {
+  grpc_core::ResolverRegistry::Builder::RegisterResolverFactory(
+      absl::make_unique<grpc_core::BinderResolverFactory>());
+}
+
+void grpc_resolver_binder_shutdown() {}
+
+#else
+
+void grpc_resolver_binder_init() {}
+
+void grpc_resolver_binder_shutdown() {}
+
+#endif
index 2e0de37..68624cd 100644 (file)
@@ -39,7 +39,7 @@
 #include "src/core/ext/filters/client_channel/resolver/dns/dns_resolver_selection.h"
 #include "src/core/ext/filters/client_channel/resolver_registry.h"
 #include "src/core/ext/filters/client_channel/server_address.h"
-#include "src/core/ext/filters/client_channel/service_config.h"
+#include "src/core/ext/service_config/service_config.h"
 #include "src/core/lib/backoff/backoff.h"
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/gpr/string.h"
@@ -193,7 +193,7 @@ void AresDnsResolver::ShutdownLocked() {
 
 void AresDnsResolver::OnNextResolution(void* arg, grpc_error_handle error) {
   AresDnsResolver* r = static_cast<AresDnsResolver*>(arg);
-  GRPC_ERROR_REF(error);  // ref owned by lambda
+  (void)GRPC_ERROR_REF(error);  // ref owned by lambda
   r->work_serializer_->Run([r, error]() { r->OnNextResolutionLocked(error); },
                            DEBUG_LOCATION);
 }
@@ -305,7 +305,7 @@ std::string ChooseServiceConfig(char* service_config_choice_json,
 
 void AresDnsResolver::OnResolved(void* arg, grpc_error_handle error) {
   AresDnsResolver* r = static_cast<AresDnsResolver*>(arg);
-  GRPC_ERROR_REF(error);  // ref owned by lambda
+  (void)GRPC_ERROR_REF(error);  // ref owned by lambda
   r->work_serializer_->Run([r, error]() { r->OnResolvedLocked(error); },
                            DEBUG_LOCATION);
 }
@@ -313,7 +313,7 @@ void AresDnsResolver::OnResolved(void* arg, grpc_error_handle error) {
 void AresDnsResolver::OnResolvedLocked(grpc_error_handle error) {
   GPR_ASSERT(resolving_);
   resolving_ = false;
-  gpr_free(pending_request_);
+  delete pending_request_;
   pending_request_ = nullptr;
   if (shutdown_initiated_) {
     Unref(DEBUG_LOCATION, "OnResolvedLocked() shutdown");
@@ -445,7 +445,13 @@ void AresDnsResolver::StartResolvingLocked() {
 
 class AresDnsResolverFactory : public ResolverFactory {
  public:
-  bool IsValidUri(const URI& /*uri*/) const override { return true; }
+  bool IsValidUri(const URI& uri) const override {
+    if (absl::StripPrefix(uri.path(), "/").empty()) {
+      gpr_log(GPR_ERROR, "no server name supplied in dns URI");
+      return false;
+    }
+    return true;
+  }
 
   OrphanablePtr<Resolver> CreateResolver(ResolverArgs args) const override {
     return MakeOrphanable<AresDnsResolver>(std::move(args));
index 07a1b53..33b78b6 100644 (file)
@@ -424,7 +424,7 @@ class GrpcPolledFdWindows {
   static void OnTcpConnect(void* arg, grpc_error_handle error) {
     GrpcPolledFdWindows* grpc_polled_fd =
         static_cast<GrpcPolledFdWindows*>(arg);
-    GRPC_ERROR_REF(error);  // ref owned by lambda
+    (void)GRPC_ERROR_REF(error);  // ref owned by lambda
     grpc_polled_fd->work_serializer_->Run(
         [grpc_polled_fd, error]() {
           grpc_polled_fd->OnTcpConnectLocked(error);
@@ -579,7 +579,7 @@ class GrpcPolledFdWindows {
 
   static void OnIocpReadable(void* arg, grpc_error_handle error) {
     GrpcPolledFdWindows* polled_fd = static_cast<GrpcPolledFdWindows*>(arg);
-    GRPC_ERROR_REF(error);  // ref owned by lambda
+    (void)GRPC_ERROR_REF(error);  // ref owned by lambda
     polled_fd->work_serializer_->Run(
         [polled_fd, error]() { polled_fd->OnIocpReadableLocked(error); },
         DEBUG_LOCATION);
@@ -624,7 +624,7 @@ class GrpcPolledFdWindows {
 
   static void OnIocpWriteable(void* arg, grpc_error_handle error) {
     GrpcPolledFdWindows* polled_fd = static_cast<GrpcPolledFdWindows*>(arg);
-    GRPC_ERROR_REF(error);  // error owned by lambda
+    (void)GRPC_ERROR_REF(error);  // error owned by lambda
     polled_fd->work_serializer_->Run(
         [polled_fd, error]() { polled_fd->OnIocpWriteableLocked(error); },
         DEBUG_LOCATION);
index 045937e..fe5a42a 100644 (file)
@@ -47,7 +47,6 @@
 #include "src/core/lib/iomgr/nameser.h"
 #include "src/core/lib/iomgr/sockaddr.h"
 #include "src/core/lib/iomgr/timer.h"
-#include "src/core/lib/transport/authority_override.h"
 
 using grpc_core::ServerAddress;
 using grpc_core::ServerAddressList;
@@ -57,29 +56,6 @@ grpc_core::TraceFlag grpc_trace_cares_address_sorting(false,
 
 grpc_core::TraceFlag grpc_trace_cares_resolver(false, "cares_resolver");
 
-typedef struct grpc_ares_ev_driver grpc_ares_ev_driver;
-
-struct grpc_ares_request {
-  /** indicates the DNS server to use, if specified */
-  struct ares_addr_port_node dns_server_addr;
-  /** following members are set in grpc_resolve_address_ares_impl */
-  /** closure to call when the request completes */
-  grpc_closure* on_done;
-  /** the pointer to receive the resolved addresses */
-  std::unique_ptr<grpc_core::ServerAddressList>* addresses_out;
-  /** the pointer to receive the resolved balancer addresses */
-  std::unique_ptr<grpc_core::ServerAddressList>* balancer_addresses_out;
-  /** the pointer to receive the service config in JSON */
-  char** service_config_json_out;
-  /** the evernt driver used by this request */
-  grpc_ares_ev_driver* ev_driver;
-  /** number of ongoing queries */
-  size_t pending_queries;
-
-  /** the errors explaining query failures, appended to in query callbacks */
-  grpc_error_handle error;
-};
-
 typedef struct fd_node {
   /** the owner of this fd node */
   grpc_ares_ev_driver* ev_driver;
@@ -284,7 +260,7 @@ static void on_timeout_locked(grpc_ares_ev_driver* driver,
 
 static void on_timeout(void* arg, grpc_error_handle error) {
   grpc_ares_ev_driver* driver = static_cast<grpc_ares_ev_driver*>(arg);
-  GRPC_ERROR_REF(error);  // ref owned by lambda
+  (void)GRPC_ERROR_REF(error);  // ref owned by lambda
   driver->work_serializer->Run(
       [driver, error]() { on_timeout_locked(driver, error); }, DEBUG_LOCATION);
 }
@@ -296,7 +272,7 @@ static void on_ares_backup_poll_alarm_locked(grpc_ares_ev_driver* driver,
 
 static void on_ares_backup_poll_alarm(void* arg, grpc_error_handle error) {
   grpc_ares_ev_driver* driver = static_cast<grpc_ares_ev_driver*>(arg);
-  GRPC_ERROR_REF(error);
+  (void)GRPC_ERROR_REF(error);
   driver->work_serializer->Run(
       [driver, error]() { on_ares_backup_poll_alarm_locked(driver, error); },
       DEBUG_LOCATION);
@@ -379,7 +355,7 @@ static void on_readable_locked(fd_node* fdn, grpc_error_handle error) {
 
 static void on_readable(void* arg, grpc_error_handle error) {
   fd_node* fdn = static_cast<fd_node*>(arg);
-  GRPC_ERROR_REF(error); /* ref owned by lambda */
+  (void)GRPC_ERROR_REF(error); /* ref owned by lambda */
   fdn->ev_driver->work_serializer->Run(
       [fdn, error]() { on_readable_locked(fdn, error); }, DEBUG_LOCATION);
 }
@@ -409,7 +385,7 @@ static void on_writable_locked(fd_node* fdn, grpc_error_handle error) {
 
 static void on_writable(void* arg, grpc_error_handle error) {
   fd_node* fdn = static_cast<fd_node*>(arg);
-  GRPC_ERROR_REF(error); /* ref owned by lambda */
+  (void)GRPC_ERROR_REF(error); /* ref owned by lambda */
   fdn->ev_driver->work_serializer->Run(
       [fdn, error]() { on_writable_locked(fdn, error); }, DEBUG_LOCATION);
 }
@@ -670,8 +646,8 @@ static void on_hostbyname_done_locked(void* arg, int status, int /*timeouts*/,
     for (size_t i = 0; hostent->h_addr_list[i] != nullptr; ++i) {
       absl::InlinedVector<grpc_arg, 1> args_to_add;
       if (hr->is_balancer) {
-        args_to_add.emplace_back(
-            grpc_core::CreateAuthorityOverrideChannelArg(hr->host));
+        args_to_add.emplace_back(grpc_channel_arg_string_create(
+            const_cast<char*>(GRPC_ARG_DEFAULT_AUTHORITY), hr->host));
       }
       grpc_channel_args* args = grpc_channel_args_copy_and_add(
           nullptr, args_to_add.data(), args_to_add.size());
@@ -841,13 +817,13 @@ void grpc_dns_lookup_ares_continue_after_check_localhost_and_ip_literals_locked(
   if (host.empty()) {
     error = grpc_error_set_str(
         GRPC_ERROR_CREATE_FROM_STATIC_STRING("unparseable host:port"),
-        GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(name));
+        GRPC_ERROR_STR_TARGET_ADDRESS, name);
     goto error_cleanup;
   } else if (port.empty()) {
     if (default_port == nullptr) {
       error = grpc_error_set_str(
           GRPC_ERROR_CREATE_FROM_STATIC_STRING("no port in name"),
-          GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(name));
+          GRPC_ERROR_STR_TARGET_ADDRESS, name);
       goto error_cleanup;
     }
     port = default_port;
@@ -879,7 +855,7 @@ void grpc_dns_lookup_ares_continue_after_check_localhost_and_ip_literals_locked(
     } else {
       error = grpc_error_set_str(
           GRPC_ERROR_CREATE_FROM_STATIC_STRING("cannot parse authority"),
-          GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(name));
+          GRPC_ERROR_STR_TARGET_ADDRESS, name);
       goto error_cleanup;
     }
     int status =
@@ -1060,15 +1036,12 @@ static grpc_ares_request* grpc_dns_lookup_ares_locked_impl(
     std::unique_ptr<grpc_core::ServerAddressList>* balancer_addrs,
     char** service_config_json, int query_timeout_ms,
     std::shared_ptr<grpc_core::WorkSerializer> work_serializer) {
-  grpc_ares_request* r =
-      static_cast<grpc_ares_request*>(gpr_zalloc(sizeof(grpc_ares_request)));
+  grpc_ares_request* r = new grpc_ares_request();
   r->ev_driver = nullptr;
   r->on_done = on_done;
   r->addresses_out = addrs;
   r->balancer_addresses_out = balancer_addrs;
   r->service_config_json_out = service_config_json;
-  r->error = GRPC_ERROR_NONE;
-  r->pending_queries = 0;
   GRPC_CARES_TRACE_LOG(
       "request:%p c-ares grpc_dns_lookup_ares_locked_impl name=%s, "
       "default_port=%s",
@@ -1164,7 +1137,7 @@ typedef struct grpc_resolve_address_ares_request {
 
 static void on_dns_lookup_done_locked(grpc_resolve_address_ares_request* r,
                                       grpc_error_handle error) {
-  gpr_free(r->ares_request);
+  delete r->ares_request;
   grpc_resolved_addresses** resolved_addresses = r->addrs_out;
   if (r->addresses == nullptr || r->addresses->empty()) {
     *resolved_addresses = nullptr;
@@ -1187,7 +1160,7 @@ static void on_dns_lookup_done_locked(grpc_resolve_address_ares_request* r,
 static void on_dns_lookup_done(void* arg, grpc_error_handle error) {
   grpc_resolve_address_ares_request* r =
       static_cast<grpc_resolve_address_ares_request*>(arg);
-  GRPC_ERROR_REF(error);  // ref owned by lambda
+  (void)GRPC_ERROR_REF(error);  // ref owned by lambda
   r->work_serializer->Run([r, error]() { on_dns_lookup_done_locked(r, error); },
                           DEBUG_LOCATION);
 }
index 675dfc8..cfc0e2b 100644 (file)
@@ -42,7 +42,27 @@ extern grpc_core::TraceFlag grpc_trace_cares_resolver;
     }                                                               \
   } while (0)
 
-typedef struct grpc_ares_request grpc_ares_request;
+typedef struct grpc_ares_ev_driver grpc_ares_ev_driver;
+
+struct grpc_ares_request {
+  /** indicates the DNS server to use, if specified */
+  struct ares_addr_port_node dns_server_addr;
+  /** following members are set in grpc_resolve_address_ares_impl */
+  /** closure to call when the request completes */
+  grpc_closure* on_done = nullptr;
+  /** the pointer to receive the resolved addresses */
+  std::unique_ptr<grpc_core::ServerAddressList>* addresses_out;
+  /** the pointer to receive the resolved balancer addresses */
+  std::unique_ptr<grpc_core::ServerAddressList>* balancer_addresses_out;
+  /** the pointer to receive the service config in JSON */
+  char** service_config_json_out = nullptr;
+  /** the evernt driver used by this request */
+  grpc_ares_ev_driver* ev_driver = nullptr;
+  /** number of ongoing queries */
+  size_t pending_queries = 0;
+  /** the errors explaining query failures, appended to in query callbacks */
+  grpc_error_handle error = GRPC_ERROR_NONE;
+};
 
 /* Asynchronously resolve \a name. Use \a default_port if a port isn't
    designated in \a name, otherwise use the port in \a name. grpc_ares_init()
index b1ef207..3a8bc71 100644 (file)
@@ -149,7 +149,7 @@ void NativeDnsResolver::ShutdownLocked() {
 
 void NativeDnsResolver::OnNextResolution(void* arg, grpc_error_handle error) {
   NativeDnsResolver* r = static_cast<NativeDnsResolver*>(arg);
-  GRPC_ERROR_REF(error);  // ref owned by lambda
+  (void)GRPC_ERROR_REF(error);  // ref owned by lambda
   r->work_serializer_->Run([r, error]() { r->OnNextResolutionLocked(error); },
                            DEBUG_LOCATION);
 }
@@ -165,7 +165,7 @@ void NativeDnsResolver::OnNextResolutionLocked(grpc_error_handle error) {
 
 void NativeDnsResolver::OnResolved(void* arg, grpc_error_handle error) {
   NativeDnsResolver* r = static_cast<NativeDnsResolver*>(arg);
-  GRPC_ERROR_REF(error);  // owned by lambda
+  (void)GRPC_ERROR_REF(error);  // owned by lambda
   r->work_serializer_->Run([r, error]() { r->OnResolvedLocked(error); },
                            DEBUG_LOCATION);
 }
@@ -291,6 +291,10 @@ class NativeDnsResolverFactory : public ResolverFactory {
       gpr_log(GPR_ERROR, "authority based dns uri's not supported");
       return false;
     }
+    if (absl::StripPrefix(uri.path(), "/").empty()) {
+      gpr_log(GPR_ERROR, "no server name supplied in dns URI");
+      return false;
+    }
     return true;
   }
 
index be447c3..dceef6f 100644 (file)
@@ -324,7 +324,9 @@ void ResponseGeneratorChannelArgDestroy(void* p) {
   generator->Unref();
 }
 
-int ResponseGeneratorChannelArgCmp(void* a, void* b) { return GPR_ICMP(a, b); }
+int ResponseGeneratorChannelArgCmp(void* a, void* b) {
+  return QsortCompare(a, b);
+}
 
 }  // namespace
 
index c9a2974..fc2dac9 100644 (file)
@@ -235,7 +235,7 @@ class XdsResolver : public Resolver {
     void MaybeAddCluster(const std::string& name);
     grpc_error_handle CreateMethodConfig(
         const XdsApi::Route& route,
-        const XdsApi::Route::ClusterWeight* cluster_weight,
+        const XdsApi::Route::RouteAction::ClusterWeight* cluster_weight,
         RefCountedPtr<ServiceConfig>* method_config);
 
     RefCountedPtr<XdsResolver> resolver_;
@@ -311,7 +311,7 @@ XdsResolver::Notifier::Notifier(RefCountedPtr<XdsResolver> resolver)
 
 void XdsResolver::Notifier::RunInExecCtx(void* arg, grpc_error_handle error) {
   Notifier* self = static_cast<Notifier*>(arg);
-  GRPC_ERROR_REF(error);
+  (void)GRPC_ERROR_REF(error);
   self->resolver_->work_serializer_->Run(
       [self, error]() { self->RunInWorkSerializer(error); }, DEBUG_LOCATION);
 }
@@ -392,30 +392,34 @@ XdsResolver::XdsConfigSelector::XdsConfigSelector(
     route_table_.emplace_back();
     auto& route_entry = route_table_.back();
     route_entry.route = route;
-    // If the route doesn't specify a timeout, set its timeout to the global
-    // one.
-    if (!route.max_stream_duration.has_value()) {
-      route_entry.route.max_stream_duration =
-          resolver_->current_listener_.http_connection_manager
-              .http_max_stream_duration;
-    }
-    if (route.weighted_clusters.empty()) {
-      *error = CreateMethodConfig(route_entry.route, nullptr,
-                                  &route_entry.method_config);
-      MaybeAddCluster(route.cluster_name);
-    } else {
-      uint32_t end = 0;
-      for (const auto& weighted_cluster : route_entry.route.weighted_clusters) {
-        Route::ClusterWeightState cluster_weight_state;
-        *error = CreateMethodConfig(route_entry.route, &weighted_cluster,
-                                    &cluster_weight_state.method_config);
-        if (*error != GRPC_ERROR_NONE) return;
-        end += weighted_cluster.weight;
-        cluster_weight_state.range_end = end;
-        cluster_weight_state.cluster = weighted_cluster.name;
-        route_entry.weighted_cluster_state.push_back(
-            std::move(cluster_weight_state));
-        MaybeAddCluster(weighted_cluster.name);
+    auto* route_action =
+        absl::get_if<XdsApi::Route::RouteAction>(&route_entry.route.action);
+    if (route_action != nullptr) {
+      // If the route doesn't specify a timeout, set its timeout to the global
+      // one.
+      if (!route_action->max_stream_duration.has_value()) {
+        route_action->max_stream_duration =
+            resolver_->current_listener_.http_connection_manager
+                .http_max_stream_duration;
+      }
+      if (route_action->weighted_clusters.empty()) {
+        *error = CreateMethodConfig(route_entry.route, nullptr,
+                                    &route_entry.method_config);
+        MaybeAddCluster(route_action->cluster_name);
+      } else {
+        uint32_t end = 0;
+        for (const auto& weighted_cluster : route_action->weighted_clusters) {
+          Route::ClusterWeightState cluster_weight_state;
+          *error = CreateMethodConfig(route_entry.route, &weighted_cluster,
+                                      &cluster_weight_state.method_config);
+          if (*error != GRPC_ERROR_NONE) return;
+          end += weighted_cluster.weight;
+          cluster_weight_state.range_end = end;
+          cluster_weight_state.cluster = weighted_cluster.name;
+          route_entry.weighted_cluster_state.push_back(
+              std::move(cluster_weight_state));
+          MaybeAddCluster(weighted_cluster.name);
+        }
       }
     }
   }
@@ -447,7 +451,7 @@ XdsResolver::XdsConfigSelector::~XdsConfigSelector() {
 const XdsHttpFilterImpl::FilterConfig* FindFilterConfigOverride(
     const std::string& instance_name,
     const XdsApi::RdsUpdate::VirtualHost& vhost, const XdsApi::Route& route,
-    const XdsApi::Route::ClusterWeight* cluster_weight) {
+    const XdsApi::Route::RouteAction::ClusterWeight* cluster_weight) {
   // Check ClusterWeight, if any.
   if (cluster_weight != nullptr) {
     auto it = cluster_weight->typed_per_filter_config.find(instance_name);
@@ -465,11 +469,14 @@ const XdsHttpFilterImpl::FilterConfig* FindFilterConfigOverride(
 
 grpc_error_handle XdsResolver::XdsConfigSelector::CreateMethodConfig(
     const XdsApi::Route& route,
-    const XdsApi::Route::ClusterWeight* cluster_weight,
+    const XdsApi::Route::RouteAction::ClusterWeight* cluster_weight,
     RefCountedPtr<ServiceConfig>* method_config) {
   std::vector<std::string> fields;
+  const auto& route_action =
+      absl::get<XdsApi::Route::RouteAction>(route.action);
   // Set retry policy if any.
-  if (route.retry_policy.has_value()) {
+  if (route_action.retry_policy.has_value() &&
+      !route_action.retry_policy->retry_on.Empty()) {
     std::vector<std::string> retry_parts;
     retry_parts.push_back(absl::StrFormat(
         "\"retryPolicy\": {\n"
@@ -477,25 +484,27 @@ grpc_error_handle XdsResolver::XdsConfigSelector::CreateMethodConfig(
         "      \"initialBackoff\": \"%d.%09ds\",\n"
         "      \"maxBackoff\": \"%d.%09ds\",\n"
         "      \"backoffMultiplier\": 2,\n",
-        route.retry_policy->num_retries + 1,
-        route.retry_policy->retry_back_off.base_interval.seconds,
-        route.retry_policy->retry_back_off.base_interval.nanos,
-        route.retry_policy->retry_back_off.max_interval.seconds,
-        route.retry_policy->retry_back_off.max_interval.nanos));
+        route_action.retry_policy->num_retries + 1,
+        route_action.retry_policy->retry_back_off.base_interval.seconds,
+        route_action.retry_policy->retry_back_off.base_interval.nanos,
+        route_action.retry_policy->retry_back_off.max_interval.seconds,
+        route_action.retry_policy->retry_back_off.max_interval.nanos));
     std::vector<std::string> code_parts;
-    if (route.retry_policy->retry_on.Contains(GRPC_STATUS_CANCELLED)) {
+    if (route_action.retry_policy->retry_on.Contains(GRPC_STATUS_CANCELLED)) {
       code_parts.push_back("        \"CANCELLED\"");
     }
-    if (route.retry_policy->retry_on.Contains(GRPC_STATUS_DEADLINE_EXCEEDED)) {
+    if (route_action.retry_policy->retry_on.Contains(
+            GRPC_STATUS_DEADLINE_EXCEEDED)) {
       code_parts.push_back("        \"DEADLINE_EXCEEDED\"");
     }
-    if (route.retry_policy->retry_on.Contains(GRPC_STATUS_INTERNAL)) {
+    if (route_action.retry_policy->retry_on.Contains(GRPC_STATUS_INTERNAL)) {
       code_parts.push_back("        \"INTERNAL\"");
     }
-    if (route.retry_policy->retry_on.Contains(GRPC_STATUS_RESOURCE_EXHAUSTED)) {
+    if (route_action.retry_policy->retry_on.Contains(
+            GRPC_STATUS_RESOURCE_EXHAUSTED)) {
       code_parts.push_back("        \"RESOURCE_EXHAUSTED\"");
     }
-    if (route.retry_policy->retry_on.Contains(GRPC_STATUS_UNAVAILABLE)) {
+    if (route_action.retry_policy->retry_on.Contains(GRPC_STATUS_UNAVAILABLE)) {
       code_parts.push_back("        \"UNAVAILABLE\"");
     }
     retry_parts.push_back(
@@ -505,12 +514,13 @@ grpc_error_handle XdsResolver::XdsConfigSelector::CreateMethodConfig(
     fields.emplace_back(absl::StrJoin(retry_parts, ""));
   }
   // Set timeout.
-  if (route.max_stream_duration.has_value() &&
-      (route.max_stream_duration->seconds != 0 ||
-       route.max_stream_duration->nanos != 0)) {
-    fields.emplace_back(absl::StrFormat("    \"timeout\": \"%d.%09ds\"",
-                                        route.max_stream_duration->seconds,
-                                        route.max_stream_duration->nanos));
+  if (route_action.max_stream_duration.has_value() &&
+      (route_action.max_stream_duration->seconds != 0 ||
+       route_action.max_stream_duration->nanos != 0)) {
+    fields.emplace_back(
+        absl::StrFormat("    \"timeout\": \"%d.%09ds\"",
+                        route_action.max_stream_duration->seconds,
+                        route_action.max_stream_duration->nanos));
   }
   // Handle xDS HTTP filters.
   std::map<std::string, std::vector<std::string>> per_filter_configs;
@@ -597,8 +607,7 @@ absl::optional<absl::string_view> GetHeaderValue(
   } else if (header_name == "content-type") {
     return "application/grpc";
   }
-  return grpc_metadata_batch_get_value(initial_metadata, header_name,
-                                       concatenated_value);
+  return initial_metadata->GetValue(header_name, concatenated_value);
 }
 
 bool HeadersMatch(const std::vector<HeaderMatcher>& header_matchers,
@@ -614,9 +623,9 @@ bool HeadersMatch(const std::vector<HeaderMatcher>& header_matchers,
 }
 
 absl::optional<uint64_t> HeaderHashHelper(
-    const XdsApi::Route::HashPolicy& policy,
+    const XdsApi::Route::RouteAction::HashPolicy& policy,
     grpc_metadata_batch* initial_metadata) {
-  GPR_ASSERT(policy.type == XdsApi::Route::HashPolicy::HEADER);
+  GPR_ASSERT(policy.type == XdsApi::Route::RouteAction::HashPolicy::HEADER);
   std::string value_buffer;
   absl::optional<absl::string_view> header_value =
       GetHeaderValue(initial_metadata, policy.header_name, &value_buffer);
@@ -660,10 +669,20 @@ ConfigSelector::CallConfig XdsResolver::XdsConfigSelector::GetCallConfig(
       continue;
     }
     // Found a route match
+    const auto* route_action =
+        absl::get_if<XdsApi::Route::RouteAction>(&entry.route.action);
+    if (route_action == nullptr) {
+      CallConfig call_config;
+      call_config.error = grpc_error_set_int(
+          GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+              "Matching route has inappropriate action"),
+          GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
+      return call_config;
+    }
     absl::string_view cluster_name;
     RefCountedPtr<ServiceConfig> method_config;
-    if (entry.route.weighted_clusters.empty()) {
-      cluster_name = entry.route.cluster_name;
+    if (route_action->weighted_clusters.empty()) {
+      cluster_name = route_action->cluster_name;
       method_config = entry.method_config;
     } else {
       const uint32_t key =
@@ -695,13 +714,13 @@ ConfigSelector::CallConfig XdsResolver::XdsConfigSelector::GetCallConfig(
     GPR_ASSERT(it != clusters_.end());
     // Generate a hash.
     absl::optional<uint64_t> hash;
-    for (const auto& hash_policy : entry.route.hash_policies) {
+    for (const auto& hash_policy : route_action->hash_policies) {
       absl::optional<uint64_t> new_hash;
       switch (hash_policy.type) {
-        case XdsApi::Route::HashPolicy::HEADER:
+        case XdsApi::Route::RouteAction::HashPolicy::HEADER:
           new_hash = HeaderHashHelper(hash_policy, args.initial_metadata);
           break;
-        case XdsApi::Route::HashPolicy::CHANNEL_ID:
+        case XdsApi::Route::RouteAction::HashPolicy::CHANNEL_ID:
           new_hash = static_cast<uint64_t>(
               reinterpret_cast<uintptr_t>(resolver_.get()));
           break;
@@ -767,12 +786,6 @@ void XdsResolver::StartLocked() {
   }
   grpc_pollset_set_add_pollset_set(xds_client_->interested_parties(),
                                    interested_parties_);
-  channelz::ChannelNode* parent_channelz_node =
-      grpc_channel_args_find_pointer<channelz::ChannelNode>(
-          args_, GRPC_ARG_CHANNELZ_CHANNEL_NODE);
-  if (parent_channelz_node != nullptr) {
-    xds_client_->AddChannelzLinkage(parent_channelz_node);
-  }
   auto watcher = absl::make_unique<ListenerWatcher>(Ref());
   listener_watcher_ = watcher.get();
   xds_client_->WatchListenerData(server_name_, std::move(watcher));
@@ -791,12 +804,6 @@ void XdsResolver::ShutdownLocked() {
       xds_client_->CancelRouteConfigDataWatch(
           server_name_, route_config_watcher_, /*delay_unsubscription=*/false);
     }
-    channelz::ChannelNode* parent_channelz_node =
-        grpc_channel_args_find_pointer<channelz::ChannelNode>(
-            args_, GRPC_ARG_CHANNELZ_CHANNEL_NODE);
-    if (parent_channelz_node != nullptr) {
-      xds_client_->RemoveChannelzLinkage(parent_channelz_node);
-    }
     grpc_pollset_set_del_pollset_set(xds_client_->interested_parties(),
                                      interested_parties_);
     xds_client_.reset();
@@ -920,13 +927,15 @@ void XdsResolver::GenerateResult() {
   grpc_error_handle error = GRPC_ERROR_NONE;
   auto config_selector = MakeRefCounted<XdsConfigSelector>(Ref(), &error);
   if (error != GRPC_ERROR_NONE) {
-    OnError(error);
+    OnError(grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS,
+                               GRPC_STATUS_UNAVAILABLE));
     return;
   }
   Result result;
   error = CreateServiceConfig(&result.service_config);
   if (error != GRPC_ERROR_NONE) {
-    OnError(error);
+    OnError(grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS,
+                               GRPC_STATUS_UNAVAILABLE));
     return;
   }
   if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_resolver_trace)) {
index 7b96746..ef958ab 100644 (file)
@@ -36,6 +36,8 @@ namespace grpc_core {
 struct ResolverArgs {
   /// The parsed URI to resolve.
   URI uri;
+  /// The URI string.
+  std::string uri_string;
   /// Channel args to be included in resolver results.
   const grpc_channel_args* args = nullptr;
   /// Used to drive I/O in the name resolution process.
index 42b69bb..b1d0ee2 100644 (file)
@@ -73,7 +73,7 @@ class RegistryState {
     ResolverFactory* factory =
         tmp_uri.ok() ? LookupResolverFactory(tmp_uri->scheme()) : nullptr;
     if (factory != nullptr) {
-      *uri = *tmp_uri;
+      *uri = std::move(*tmp_uri);
       return factory;
     }
     *canonical_target = absl::StrCat(default_prefix_.get(), target);
@@ -81,7 +81,7 @@ class RegistryState {
     factory =
         tmp_uri2.ok() ? LookupResolverFactory(tmp_uri2->scheme()) : nullptr;
     if (factory != nullptr) {
-      *uri = *tmp_uri2;
+      *uri = std::move(*tmp_uri2);
       return factory;
     }
     if (!tmp_uri.ok() || !tmp_uri2.ok()) {
@@ -158,18 +158,16 @@ OrphanablePtr<Resolver> ResolverRegistry::CreateResolver(
     std::shared_ptr<WorkSerializer> work_serializer,
     std::unique_ptr<Resolver::ResultHandler> result_handler) {
   GPR_ASSERT(g_state != nullptr);
-  std::string canonical_target;
   ResolverArgs resolver_args;
   ResolverFactory* factory = g_state->FindResolverFactory(
-      target, &resolver_args.uri, &canonical_target);
+      target, &resolver_args.uri, &resolver_args.uri_string);
+  if (factory == nullptr) return nullptr;
+  if (resolver_args.uri_string.empty()) resolver_args.uri_string = target;
   resolver_args.args = args;
   resolver_args.pollset_set = pollset_set;
   resolver_args.work_serializer = std::move(work_serializer);
   resolver_args.result_handler = std::move(result_handler);
-  OrphanablePtr<Resolver> resolver =
-      factory == nullptr ? nullptr
-                         : factory->CreateResolver(std::move(resolver_args));
-  return resolver;
+  return factory->CreateResolver(std::move(resolver_args));
 }
 
 std::string ResolverRegistry::GetDefaultAuthority(absl::string_view target) {
index fe66c3f..4154ee7 100644 (file)
@@ -100,7 +100,7 @@ ClientChannelServiceConfigParser::ParseGlobalParams(
     grpc_error_handle parse_error = GRPC_ERROR_NONE;
     parsed_lb_config = LoadBalancingPolicyRegistry::ParseLoadBalancingConfig(
         it->second, &parse_error);
-    if (parsed_lb_config == nullptr) {
+    if (parse_error != GRPC_ERROR_NONE) {
       std::vector<grpc_error_handle> lb_errors;
       lb_errors.push_back(parse_error);
       error_list.push_back(GRPC_ERROR_CREATE_FROM_VECTOR(
index b70068e..21b619a 100644 (file)
@@ -24,7 +24,7 @@
 #include "src/core/ext/filters/client_channel/lb_policy.h"
 #include "src/core/ext/filters/client_channel/lb_policy_factory.h"
 #include "src/core/ext/filters/client_channel/resolver.h"
-#include "src/core/ext/filters/client_channel/service_config.h"
+#include "src/core/ext/service_config/service_config_parser.h"
 #include "src/core/lib/channel/status_util.h"
 #include "src/core/lib/gprpp/ref_counted.h"
 #include "src/core/lib/gprpp/ref_counted_ptr.h"
index 975001d..e8a6a46 100644 (file)
@@ -27,8 +27,8 @@
 #include "src/core/ext/filters/client_channel/client_channel.h"
 #include "src/core/ext/filters/client_channel/retry_service_config.h"
 #include "src/core/ext/filters/client_channel/retry_throttle.h"
-#include "src/core/ext/filters/client_channel/service_config.h"
-#include "src/core/ext/filters/client_channel/service_config_call_data.h"
+#include "src/core/ext/service_config/service_config.h"
+#include "src/core/ext/service_config/service_config_call_data.h"
 #include "src/core/lib/backoff/backoff.h"
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/channel/channel_stack.h"
@@ -335,9 +335,10 @@ class RetryFilter::CallData {
         call_attempt_->lb_call_committed_ = true;
         auto* calld = call_attempt_->calld_;
         if (calld->retry_committed_) {
-          auto* service_config_call_data = static_cast<ServiceConfigCallData*>(
-              calld->call_context_[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA]
-                  .value);
+          auto* service_config_call_data =
+              static_cast<ClientChannelServiceConfigCallData*>(
+                  calld->call_context_[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA]
+                      .value);
           service_config_call_data->call_dispatch_controller()->Commit();
         }
       }
@@ -419,27 +420,22 @@ class RetryFilter::CallData {
     // BatchData.batch.payload points to this.
     grpc_transport_stream_op_batch_payload batch_payload_;
     // For send_initial_metadata.
-    // Note that we need to make a copy of the initial metadata for each
-    // call attempt instead of just referring to the copy in call_data,
-    // because filters in the subchannel stack may modify the metadata,
-    // so we need to start in a pristine state for each attempt of the call.
-    grpc_linked_mdelem* send_initial_metadata_storage_;
-    grpc_metadata_batch send_initial_metadata_;
+    grpc_linked_mdelem retry_attempts_metadata_;
+    grpc_metadata_batch send_initial_metadata_{calld_->arena_};
     // For send_message.
     // TODO(roth): Restructure this to eliminate use of ManualConstructor.
     ManualConstructor<ByteStreamCache::CachingByteStream> send_message_;
     // For send_trailing_metadata.
-    grpc_linked_mdelem* send_trailing_metadata_storage_;
-    grpc_metadata_batch send_trailing_metadata_;
+    grpc_metadata_batch send_trailing_metadata_{calld_->arena_};
     // For intercepting recv_initial_metadata.
-    grpc_metadata_batch recv_initial_metadata_;
+    grpc_metadata_batch recv_initial_metadata_{calld_->arena_};
     grpc_closure recv_initial_metadata_ready_;
     bool trailing_metadata_available_ = false;
     // For intercepting recv_message.
     grpc_closure recv_message_ready_;
     OrphanablePtr<ByteStream> recv_message_;
     // For intercepting recv_trailing_metadata.
-    grpc_metadata_batch recv_trailing_metadata_;
+    grpc_metadata_batch recv_trailing_metadata_{calld_->arena_};
     grpc_transport_stream_stats collect_stats_;
     grpc_closure recv_trailing_metadata_ready_;
     // These fields indicate which ops have been started and completed on
@@ -572,8 +568,7 @@ class RetryFilter::CallData {
   // Cached data for retrying send ops.
   // send_initial_metadata
   bool seen_send_initial_metadata_ = false;
-  grpc_linked_mdelem* send_initial_metadata_storage_ = nullptr;
-  grpc_metadata_batch send_initial_metadata_;
+  grpc_metadata_batch send_initial_metadata_{arena_};
   uint32_t send_initial_metadata_flags_;
   // TODO(roth): As part of implementing hedging, we'll probably need to
   // have the LB call set a value in CallAttempt and then propagate it
@@ -598,8 +593,7 @@ class RetryFilter::CallData {
   absl::InlinedVector<ByteStreamCache*, 3> send_messages_;
   // send_trailing_metadata
   bool seen_send_trailing_metadata_ = false;
-  grpc_linked_mdelem* send_trailing_metadata_storage_ = nullptr;
-  grpc_metadata_batch send_trailing_metadata_;
+  grpc_metadata_batch send_trailing_metadata_{arena_};
 };
 
 //
@@ -1159,8 +1153,9 @@ bool RetryFilter::CallData::CallAttempt::ShouldRetry(
     }
   }
   // Check with call dispatch controller.
-  auto* service_config_call_data = static_cast<ServiceConfigCallData*>(
-      calld_->call_context_[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].value);
+  auto* service_config_call_data =
+      static_cast<ClientChannelServiceConfigCallData*>(
+          calld_->call_context_[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].value);
   if (!service_config_call_data->call_dispatch_controller()->ShouldRetry()) {
     if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) {
       gpr_log(
@@ -1308,18 +1303,6 @@ RetryFilter::CallData::CallAttempt::BatchData::~BatchData() {
             call_attempt_->calld_->chand_, call_attempt_->calld_,
             call_attempt_.get(), this);
   }
-  if (batch_.send_initial_metadata) {
-    grpc_metadata_batch_destroy(&call_attempt_->send_initial_metadata_);
-  }
-  if (batch_.send_trailing_metadata) {
-    grpc_metadata_batch_destroy(&call_attempt_->send_trailing_metadata_);
-  }
-  if (batch_.recv_initial_metadata) {
-    grpc_metadata_batch_destroy(&call_attempt_->recv_initial_metadata_);
-  }
-  if (batch_.recv_trailing_metadata) {
-    grpc_metadata_batch_destroy(&call_attempt_->recv_trailing_metadata_);
-  }
   GRPC_CALL_STACK_UNREF(call_attempt_->calld_->owning_call_, "Retry BatchData");
   call_attempt_.reset(DEBUG_LOCATION, "~BatchData");
 }
@@ -1363,9 +1346,8 @@ void RetryFilter::CallData::CallAttempt::BatchData::
     return;
   }
   // Return metadata.
-  grpc_metadata_batch_move(
-      &call_attempt_->recv_initial_metadata_,
-      pending->batch->payload->recv_initial_metadata.recv_initial_metadata);
+  *pending->batch->payload->recv_initial_metadata.recv_initial_metadata =
+      std::move(call_attempt_->recv_initial_metadata_);
   // Propagate trailing_metadata_available.
   *pending->batch->payload->recv_initial_metadata.trailing_metadata_available =
       call_attempt_->trailing_metadata_available_;
@@ -1565,11 +1547,12 @@ void GetCallStatus(grpc_millis deadline, grpc_metadata_batch* md_batch,
       *is_lb_drop = true;
     }
   } else {
-    GPR_ASSERT(md_batch->idx.named.grpc_status != nullptr);
-    *status =
-        grpc_get_status_code_from_metadata(md_batch->idx.named.grpc_status->md);
-    if (md_batch->idx.named.grpc_retry_pushback_ms != nullptr) {
-      *server_pushback_md = &md_batch->idx.named.grpc_retry_pushback_ms->md;
+    GPR_ASSERT(md_batch->legacy_index()->named.grpc_status != nullptr);
+    *status = grpc_get_status_code_from_metadata(
+        md_batch->legacy_index()->named.grpc_status->md);
+    if (md_batch->legacy_index()->named.grpc_retry_pushback_ms != nullptr) {
+      *server_pushback_md =
+          &md_batch->legacy_index()->named.grpc_retry_pushback_ms->md;
     }
   }
   GRPC_ERROR_UNREF(error);
@@ -1601,9 +1584,8 @@ void RetryFilter::CallData::CallAttempt::BatchData::
       &call_attempt_->collect_stats_,
       pending->batch->payload->recv_trailing_metadata.collect_stats);
   // Return metadata.
-  grpc_metadata_batch_move(
-      &call_attempt_->recv_trailing_metadata_,
-      pending->batch->payload->recv_trailing_metadata.recv_trailing_metadata);
+  *pending->batch->payload->recv_trailing_metadata.recv_trailing_metadata =
+      std::move(call_attempt_->recv_trailing_metadata_);
   // Add closure.
   closures->Add(pending->batch->payload->recv_trailing_metadata
                     .recv_trailing_metadata_ready,
@@ -1920,18 +1902,12 @@ void RetryFilter::CallData::CallAttempt::BatchData::
   //
   // If we've already completed one or more attempts, add the
   // grpc-retry-attempts header.
-  call_attempt_->send_initial_metadata_storage_ =
-      static_cast<grpc_linked_mdelem*>(
-          calld->arena_->Alloc(sizeof(grpc_linked_mdelem) *
-                               (calld->send_initial_metadata_.list.count +
-                                (calld->num_attempts_completed_ > 0))));
   grpc_metadata_batch_copy(&calld->send_initial_metadata_,
-                           &call_attempt_->send_initial_metadata_,
-                           call_attempt_->send_initial_metadata_storage_);
-  if (GPR_UNLIKELY(call_attempt_->send_initial_metadata_.idx.named
-                       .grpc_previous_rpc_attempts != nullptr)) {
-    grpc_metadata_batch_remove(&call_attempt_->send_initial_metadata_,
-                               GRPC_BATCH_GRPC_PREVIOUS_RPC_ATTEMPTS);
+                           &call_attempt_->send_initial_metadata_);
+  if (GPR_UNLIKELY(call_attempt_->send_initial_metadata_.legacy_index()
+                       ->named.grpc_previous_rpc_attempts != nullptr)) {
+    call_attempt_->send_initial_metadata_.Remove(
+        GRPC_BATCH_GRPC_PREVIOUS_RPC_ATTEMPTS);
   }
   if (GPR_UNLIKELY(calld->num_attempts_completed_ > 0)) {
     grpc_mdelem retry_md = grpc_mdelem_create(
@@ -1939,9 +1915,8 @@ void RetryFilter::CallData::CallAttempt::BatchData::
         *retry_count_strings[calld->num_attempts_completed_ - 1], nullptr);
     grpc_error_handle error = grpc_metadata_batch_add_tail(
         &call_attempt_->send_initial_metadata_,
-        &call_attempt_->send_initial_metadata_storage_
-             [calld->send_initial_metadata_.list.count],
-        retry_md, GRPC_BATCH_GRPC_PREVIOUS_RPC_ATTEMPTS);
+        &call_attempt_->retry_attempts_metadata_, retry_md,
+        GRPC_BATCH_GRPC_PREVIOUS_RPC_ATTEMPTS);
     if (GPR_UNLIKELY(error != GRPC_ERROR_NONE)) {
       gpr_log(GPR_ERROR, "error adding retry metadata: %s",
               grpc_error_std_string(error).c_str());
@@ -1983,13 +1958,8 @@ void RetryFilter::CallData::CallAttempt::BatchData::
   // We need to make a copy of the metadata batch for each attempt, since
   // the filters in the subchannel stack may modify this batch, and we don't
   // want those modifications to be passed forward to subsequent attempts.
-  call_attempt_->send_trailing_metadata_storage_ =
-      static_cast<grpc_linked_mdelem*>(
-          calld->arena_->Alloc(sizeof(grpc_linked_mdelem) *
-                               calld->send_trailing_metadata_.list.count));
   grpc_metadata_batch_copy(&calld->send_trailing_metadata_,
-                           &call_attempt_->send_trailing_metadata_,
-                           call_attempt_->send_trailing_metadata_storage_);
+                           &call_attempt_->send_trailing_metadata_);
   call_attempt_->started_send_trailing_metadata_ = true;
   batch_.send_trailing_metadata = true;
   batch_.payload->send_trailing_metadata.send_trailing_metadata =
@@ -2000,7 +1970,7 @@ void RetryFilter::CallData::CallAttempt::BatchData::
     AddRetriableRecvInitialMetadataOp() {
   call_attempt_->started_recv_initial_metadata_ = true;
   batch_.recv_initial_metadata = true;
-  grpc_metadata_batch_init(&call_attempt_->recv_initial_metadata_);
+  call_attempt_->recv_initial_metadata_.Clear();
   batch_.payload->recv_initial_metadata.recv_initial_metadata =
       &call_attempt_->recv_initial_metadata_;
   batch_.payload->recv_initial_metadata.trailing_metadata_available =
@@ -2027,7 +1997,7 @@ void RetryFilter::CallData::CallAttempt::BatchData::
     AddRetriableRecvTrailingMetadataOp() {
   call_attempt_->started_recv_trailing_metadata_ = true;
   batch_.recv_trailing_metadata = true;
-  grpc_metadata_batch_init(&call_attempt_->recv_trailing_metadata_);
+  call_attempt_->recv_trailing_metadata_.Clear();
   batch_.payload->recv_trailing_metadata.recv_trailing_metadata =
       &call_attempt_->recv_trailing_metadata_;
   batch_.payload->recv_trailing_metadata.collect_stats =
@@ -2244,8 +2214,9 @@ void RetryFilter::CallData::StartTransportStreamOpBatch(
                 chand_, this);
       }
       PendingBatchClear(pending);
-      auto* service_config_call_data = static_cast<ServiceConfigCallData*>(
-          call_context_[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].value);
+      auto* service_config_call_data =
+          static_cast<ClientChannelServiceConfigCallData*>(
+              call_context_[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].value);
       committed_call_ = CreateLoadBalancedCall(
           service_config_call_data->call_dispatch_controller());
       committed_call_->StartTransportStreamOpBatch(batch);
@@ -2301,14 +2272,9 @@ void RetryFilter::CallData::MaybeCacheSendOpsForBatch(PendingBatch* pending) {
   // Save a copy of metadata for send_initial_metadata ops.
   if (batch->send_initial_metadata) {
     seen_send_initial_metadata_ = true;
-    GPR_ASSERT(send_initial_metadata_storage_ == nullptr);
     grpc_metadata_batch* send_initial_metadata =
         batch->payload->send_initial_metadata.send_initial_metadata;
-    send_initial_metadata_storage_ =
-        static_cast<grpc_linked_mdelem*>(arena_->Alloc(
-            sizeof(grpc_linked_mdelem) * send_initial_metadata->list.count));
-    grpc_metadata_batch_copy(send_initial_metadata, &send_initial_metadata_,
-                             send_initial_metadata_storage_);
+    grpc_metadata_batch_copy(send_initial_metadata, &send_initial_metadata_);
     send_initial_metadata_flags_ =
         batch->payload->send_initial_metadata.send_initial_metadata_flags;
     peer_string_ = batch->payload->send_initial_metadata.peer_string;
@@ -2322,14 +2288,9 @@ void RetryFilter::CallData::MaybeCacheSendOpsForBatch(PendingBatch* pending) {
   // Save metadata batch for send_trailing_metadata ops.
   if (batch->send_trailing_metadata) {
     seen_send_trailing_metadata_ = true;
-    GPR_ASSERT(send_trailing_metadata_storage_ == nullptr);
     grpc_metadata_batch* send_trailing_metadata =
         batch->payload->send_trailing_metadata.send_trailing_metadata;
-    send_trailing_metadata_storage_ =
-        static_cast<grpc_linked_mdelem*>(arena_->Alloc(
-            sizeof(grpc_linked_mdelem) * send_trailing_metadata->list.count));
-    grpc_metadata_batch_copy(send_trailing_metadata, &send_trailing_metadata_,
-                             send_trailing_metadata_storage_);
+    grpc_metadata_batch_copy(send_trailing_metadata, &send_trailing_metadata_);
   }
 }
 
@@ -2338,7 +2299,7 @@ void RetryFilter::CallData::FreeCachedSendInitialMetadata() {
     gpr_log(GPR_INFO, "chand=%p calld=%p: destroying send_initial_metadata",
             chand_, this);
   }
-  grpc_metadata_batch_destroy(&send_initial_metadata_);
+  send_initial_metadata_.Clear();
 }
 
 void RetryFilter::CallData::FreeCachedSendMessage(size_t idx) {
@@ -2355,7 +2316,7 @@ void RetryFilter::CallData::FreeCachedSendTrailingMetadata() {
     gpr_log(GPR_INFO, "chand=%p calld=%p: destroying send_trailing_metadata",
             chand_, this);
   }
-  grpc_metadata_batch_destroy(&send_trailing_metadata_);
+  send_trailing_metadata_.Clear();
 }
 
 void RetryFilter::CallData::FreeAllCachedSendOpData() {
@@ -2404,8 +2365,8 @@ RetryFilter::CallData::PendingBatch* RetryFilter::CallData::PendingBatchesAdd(
   // gRPC clients do not send trailing metadata.
   if (batch->send_initial_metadata) {
     pending_send_initial_metadata_ = true;
-    bytes_buffered_for_retry_ += grpc_metadata_batch_size(
-        batch->payload->send_initial_metadata.send_initial_metadata);
+    bytes_buffered_for_retry_ += batch->payload->send_initial_metadata
+                                     .send_initial_metadata->TransportSize();
   }
   if (batch->send_message) {
     pending_send_message_ = true;
@@ -2541,8 +2502,9 @@ void RetryFilter::CallData::RetryCommit(CallAttempt* call_attempt) {
     // call dispatch controller down into the LB call, and it won't be
     // our problem anymore.
     if (call_attempt->lb_call_committed()) {
-      auto* service_config_call_data = static_cast<ServiceConfigCallData*>(
-          call_context_[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].value);
+      auto* service_config_call_data =
+          static_cast<ClientChannelServiceConfigCallData*>(
+              call_context_[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].value);
       service_config_call_data->call_dispatch_controller()->Commit();
     }
     // Free cached send ops.
index 86bda9c..8febc5e 100644 (file)
@@ -22,7 +22,7 @@
 #include <memory>
 
 #include "src/core/ext/filters/client_channel/retry_throttle.h"
-#include "src/core/ext/filters/client_channel/service_config_parser.h"
+#include "src/core/ext/service_config/service_config_parser.h"
 #include "src/core/lib/channel/status_util.h"
 #include "src/core/lib/iomgr/exec_ctx.h"  // for grpc_millis
 
index 03c7a67..ddeb13f 100644 (file)
@@ -23,6 +23,7 @@
 #include <limits.h>
 #include <string.h>
 
+#include <map>
 #include <string>
 
 #include <grpc/support/alloc.h>
@@ -30,7 +31,7 @@
 #include <grpc/support/string_util.h>
 #include <grpc/support/sync.h>
 
-#include "src/core/lib/avl/avl.h"
+#include "src/core/lib/gprpp/manual_constructor.h"
 
 namespace grpc_core {
 namespace internal {
@@ -115,54 +116,23 @@ void ServerRetryThrottleData::RecordSuccess() {
 }
 
 //
-// avl vtable for string -> server_retry_throttle_data map
-//
-
-namespace {
-
-void* copy_server_name(void* key, void* /*unused*/) {
-  return gpr_strdup(static_cast<const char*>(key));
-}
-
-long compare_server_name(void* key1, void* key2, void* /*unused*/) {
-  return strcmp(static_cast<const char*>(key1), static_cast<const char*>(key2));
-}
-
-void destroy_server_retry_throttle_data(void* value, void* /*unused*/) {
-  ServerRetryThrottleData* throttle_data =
-      static_cast<ServerRetryThrottleData*>(value);
-  throttle_data->Unref();
-}
-
-void* copy_server_retry_throttle_data(void* value, void* /*unused*/) {
-  ServerRetryThrottleData* throttle_data =
-      static_cast<ServerRetryThrottleData*>(value);
-  return throttle_data->Ref().release();
-}
-
-void destroy_server_name(void* key, void* /*unused*/) { gpr_free(key); }
-
-const grpc_avl_vtable avl_vtable = {
-    destroy_server_name, copy_server_name, compare_server_name,
-    destroy_server_retry_throttle_data, copy_server_retry_throttle_data};
-
-}  // namespace
-
-//
 // ServerRetryThrottleMap
 //
 
+using StringToDataMap =
+    std::map<std::string, RefCountedPtr<ServerRetryThrottleData>>;
 static gpr_mu g_mu;
-static grpc_avl g_avl;
+static StringToDataMap* g_map;
 
 void ServerRetryThrottleMap::Init() {
   gpr_mu_init(&g_mu);
-  g_avl = grpc_avl_create(&avl_vtable);
+  g_map = new StringToDataMap();
 }
 
 void ServerRetryThrottleMap::Shutdown() {
   gpr_mu_destroy(&g_mu);
-  grpc_avl_unref(g_avl, nullptr);
+  delete g_map;
+  g_map = nullptr;
 }
 
 RefCountedPtr<ServerRetryThrottleData> ServerRetryThrottleMap::GetDataForServer(
@@ -170,23 +140,22 @@ RefCountedPtr<ServerRetryThrottleData> ServerRetryThrottleMap::GetDataForServer(
     intptr_t milli_token_ratio) {
   RefCountedPtr<ServerRetryThrottleData> result;
   gpr_mu_lock(&g_mu);
+  auto it = g_map->find(server_name);
   ServerRetryThrottleData* throttle_data =
-      static_cast<ServerRetryThrottleData*>(
-          grpc_avl_get(g_avl, const_cast<char*>(server_name.c_str()), nullptr));
+      it == g_map->end() ? nullptr : it->second.get();
   if (throttle_data == nullptr ||
       throttle_data->max_milli_tokens() != max_milli_tokens ||
       throttle_data->milli_token_ratio() != milli_token_ratio) {
     // Entry not found, or found with old parameters.  Create a new one.
-    result = MakeRefCounted<ServerRetryThrottleData>(
-        max_milli_tokens, milli_token_ratio, throttle_data);
-    g_avl = grpc_avl_add(g_avl, gpr_strdup(server_name.c_str()),
-                         result->Ref().release(), nullptr);
-  } else {
-    // Entry found.  Return a new ref to it.
-    result = throttle_data->Ref();
+    it = g_map
+             ->emplace(server_name,
+                       MakeRefCounted<ServerRetryThrottleData>(
+                           max_milli_tokens, milli_token_ratio, throttle_data))
+             .first;
+    throttle_data = it->second.get();
   }
   gpr_mu_unlock(&g_mu);
-  return result;
+  return throttle_data->Ref();
 }
 
 }  // namespace internal
index 1e0eaa1..5869752 100644 (file)
@@ -128,7 +128,7 @@ class ServerAddressWeightAttribute : public ServerAddress::AttributeInterface {
   int Cmp(const AttributeInterface* other) const override {
     const auto* other_locality_attr =
         static_cast<const ServerAddressWeightAttribute*>(other);
-    return GPR_ICMP(weight_, other_locality_attr->weight_);
+    return QsortCompare(weight_, other_locality_attr->weight_);
   }
 
   std::string ToString() const override {
diff --git a/src/core/ext/filters/client_channel/service_config.cc b/src/core/ext/filters/client_channel/service_config.cc
deleted file mode 100644 (file)
index b87226c..0000000
+++ /dev/null
@@ -1,227 +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 "src/core/ext/filters/client_channel/service_config.h"
-
-#include <string>
-
-#include "absl/strings/str_cat.h"
-
-#include <grpc/support/log.h>
-
-#include "src/core/ext/filters/client_channel/service_config_parser.h"
-#include "src/core/lib/json/json.h"
-#include "src/core/lib/slice/slice_internal.h"
-
-namespace grpc_core {
-
-RefCountedPtr<ServiceConfig> ServiceConfig::Create(
-    const grpc_channel_args* args, absl::string_view json_string,
-    grpc_error_handle* error) {
-  GPR_DEBUG_ASSERT(error != nullptr);
-  Json json = Json::Parse(json_string, error);
-  if (*error != GRPC_ERROR_NONE) return nullptr;
-  return MakeRefCounted<ServiceConfig>(args, std::string(json_string),
-                                       std::move(json), error);
-}
-
-ServiceConfig::ServiceConfig(const grpc_channel_args* args,
-                             std::string json_string, Json json,
-                             grpc_error_handle* error)
-    : json_string_(std::move(json_string)), json_(std::move(json)) {
-  GPR_DEBUG_ASSERT(error != nullptr);
-  if (json_.type() != Json::Type::OBJECT) {
-    *error =
-        GRPC_ERROR_CREATE_FROM_STATIC_STRING("JSON value is not an object");
-    return;
-  }
-  std::vector<grpc_error_handle> error_list;
-  grpc_error_handle global_error = GRPC_ERROR_NONE;
-  parsed_global_configs_ =
-      ServiceConfigParser::ParseGlobalParameters(args, json_, &global_error);
-  if (global_error != GRPC_ERROR_NONE) error_list.push_back(global_error);
-  grpc_error_handle local_error = ParsePerMethodParams(args);
-  if (local_error != GRPC_ERROR_NONE) error_list.push_back(local_error);
-  if (!error_list.empty()) {
-    *error = GRPC_ERROR_CREATE_FROM_VECTOR("Service config parsing error",
-                                           &error_list);
-  }
-}
-
-ServiceConfig::~ServiceConfig() {
-  for (auto& p : parsed_method_configs_map_) {
-    grpc_slice_unref_internal(p.first);
-  }
-}
-
-grpc_error_handle ServiceConfig::ParseJsonMethodConfig(
-    const grpc_channel_args* args, const Json& json) {
-  std::vector<grpc_error_handle> error_list;
-  // Parse method config with each registered parser.
-  auto parsed_configs =
-      absl::make_unique<ServiceConfigParser::ParsedConfigVector>();
-  grpc_error_handle parser_error = GRPC_ERROR_NONE;
-  *parsed_configs =
-      ServiceConfigParser::ParsePerMethodParameters(args, json, &parser_error);
-  if (parser_error != GRPC_ERROR_NONE) {
-    error_list.push_back(parser_error);
-  }
-  parsed_method_config_vectors_storage_.push_back(std::move(parsed_configs));
-  const auto* vector_ptr = parsed_method_config_vectors_storage_.back().get();
-  // Add an entry for each path.
-  bool found_name = false;
-  auto it = json.object_value().find("name");
-  if (it != json.object_value().end()) {
-    if (it->second.type() != Json::Type::ARRAY) {
-      error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
-          "field:name error:not of type Array"));
-      return GRPC_ERROR_CREATE_FROM_VECTOR("methodConfig", &error_list);
-    }
-    const Json::Array& name_array = it->second.array_value();
-    for (const Json& name : name_array) {
-      grpc_error_handle parse_error = GRPC_ERROR_NONE;
-      std::string path = ParseJsonMethodName(name, &parse_error);
-      if (parse_error != GRPC_ERROR_NONE) {
-        error_list.push_back(parse_error);
-      } else {
-        found_name = true;
-        if (path.empty()) {
-          if (default_method_config_vector_ != nullptr) {
-            error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
-                "field:name error:multiple default method configs"));
-          }
-          default_method_config_vector_ = vector_ptr;
-        } else {
-          grpc_slice key = grpc_slice_from_copied_string(path.c_str());
-          // If the key is not already present in the map, this will
-          // store a ref to the key in the map.
-          auto& value = parsed_method_configs_map_[key];
-          if (value != nullptr) {
-            error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
-                "field:name error:multiple method configs with same name"));
-            // The map entry already existed, so we need to unref the
-            // key we just created.
-            grpc_slice_unref_internal(key);
-          } else {
-            value = vector_ptr;
-          }
-        }
-      }
-    }
-  }
-  if (!found_name) {
-    parsed_method_config_vectors_storage_.pop_back();
-  }
-  return GRPC_ERROR_CREATE_FROM_VECTOR("methodConfig", &error_list);
-}
-
-grpc_error_handle ServiceConfig::ParsePerMethodParams(
-    const grpc_channel_args* args) {
-  std::vector<grpc_error_handle> error_list;
-  auto it = json_.object_value().find("methodConfig");
-  if (it != json_.object_value().end()) {
-    if (it->second.type() != Json::Type::ARRAY) {
-      error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
-          "field:methodConfig error:not of type Array"));
-    }
-    for (const Json& method_config : it->second.array_value()) {
-      if (method_config.type() != Json::Type::OBJECT) {
-        error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
-            "field:methodConfig error:not of type Object"));
-        continue;
-      }
-      grpc_error_handle error = ParseJsonMethodConfig(args, method_config);
-      if (error != GRPC_ERROR_NONE) {
-        error_list.push_back(error);
-      }
-    }
-  }
-  return GRPC_ERROR_CREATE_FROM_VECTOR("Method Params", &error_list);
-}
-
-std::string ServiceConfig::ParseJsonMethodName(const Json& json,
-                                               grpc_error_handle* error) {
-  if (json.type() != Json::Type::OBJECT) {
-    *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
-        "field:name error:type is not object");
-    return "";
-  }
-  // Find service name.
-  const std::string* service_name = nullptr;
-  auto it = json.object_value().find("service");
-  if (it != json.object_value().end() &&
-      it->second.type() != Json::Type::JSON_NULL) {
-    if (it->second.type() != Json::Type::STRING) {
-      *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
-          "field:name error: field:service error:not of type string");
-      return "";
-    }
-    if (!it->second.string_value().empty()) {
-      service_name = &it->second.string_value();
-    }
-  }
-  const std::string* method_name = nullptr;
-  // Find method name.
-  it = json.object_value().find("method");
-  if (it != json.object_value().end() &&
-      it->second.type() != Json::Type::JSON_NULL) {
-    if (it->second.type() != Json::Type::STRING) {
-      *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
-          "field:name error: field:method error:not of type string");
-      return "";
-    }
-    if (!it->second.string_value().empty()) {
-      method_name = &it->second.string_value();
-    }
-  }
-  // If neither service nor method are specified, it's the default.
-  // Method name may not be specified without service name.
-  if (service_name == nullptr) {
-    if (method_name != nullptr) {
-      *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
-          "field:name error:method name populated without service name");
-    }
-    return "";
-  }
-  // Construct path.
-  return absl::StrCat("/", *service_name, "/",
-                      method_name == nullptr ? "" : *method_name);
-}
-
-const ServiceConfigParser::ParsedConfigVector*
-ServiceConfig::GetMethodParsedConfigVector(const grpc_slice& path) const {
-  if (parsed_method_configs_map_.empty()) {
-    return default_method_config_vector_;
-  }
-  // Try looking up the full path in the map.
-  auto it = parsed_method_configs_map_.find(path);
-  if (it != parsed_method_configs_map_.end()) return it->second;
-  // If we didn't find a match for the path, try looking for a wildcard
-  // entry (i.e., change "/service/method" to "/service/").
-  UniquePtr<char> path_str(grpc_slice_to_c_string(path));
-  char* sep = strrchr(path_str.get(), '/');
-  if (sep == nullptr) return nullptr;  // Shouldn't ever happen.
-  sep[1] = '\0';
-  grpc_slice wildcard_path = grpc_slice_from_static_string(path_str.get());
-  it = parsed_method_configs_map_.find(wildcard_path);
-  if (it != parsed_method_configs_map_.end()) return it->second;
-  // Try default method config, if set.
-  return default_method_config_vector_;
-}
-
-}  // namespace grpc_core
diff --git a/src/core/ext/filters/client_channel/service_config.h b/src/core/ext/filters/client_channel/service_config.h
deleted file mode 100644 (file)
index a06ae16..0000000
+++ /dev/null
@@ -1,127 +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.
-//
-
-#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SERVICE_CONFIG_H
-#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SERVICE_CONFIG_H
-
-#include <grpc/support/port_platform.h>
-
-#include <unordered_map>
-
-#include "absl/container/inlined_vector.h"
-
-#include <grpc/impl/codegen/grpc_types.h>
-#include <grpc/support/string_util.h>
-
-#include "src/core/ext/filters/client_channel/service_config_parser.h"
-#include "src/core/lib/gprpp/ref_counted.h"
-#include "src/core/lib/gprpp/ref_counted_ptr.h"
-#include "src/core/lib/iomgr/error.h"
-#include "src/core/lib/json/json.h"
-#include "src/core/lib/slice/slice_internal.h"
-
-// The main purpose of the code here is to parse the service config in
-// JSON form, which will look like this:
-//
-// {
-//   "loadBalancingPolicy": "string",  // optional
-//   "methodConfig": [  // array of one or more method_config objects
-//     {
-//       "name": [  // array of one or more name objects
-//         {
-//           "service": "string",  // required
-//           "method": "string",  // optional
-//         }
-//       ],
-//       // remaining fields are optional.
-//       // see https://developers.google.com/protocol-buffers/docs/proto3#json
-//       // for format details.
-//       "waitForReady": bool,
-//       "timeout": "duration_string",
-//       "maxRequestMessageBytes": "int64_string",
-//       "maxResponseMessageBytes": "int64_string",
-//     }
-//   ]
-// }
-
-namespace grpc_core {
-
-// TODO(roth): Consider stripping this down further to the completely minimal
-// interface requied to be exposed as part of the resolver API.
-class ServiceConfig : public RefCounted<ServiceConfig> {
- public:
-  /// Creates a new service config from parsing \a json_string.
-  /// Returns null on parse error.
-  static RefCountedPtr<ServiceConfig> Create(const grpc_channel_args* args,
-                                             absl::string_view json_string,
-                                             grpc_error_handle* error);
-
-  ServiceConfig(const grpc_channel_args* args, std::string json_string,
-                Json json, grpc_error_handle* error);
-  ~ServiceConfig() override;
-
-  const std::string& json_string() const { return json_string_; }
-
-  /// Retrieves the global parsed config at index \a index. The
-  /// lifetime of the returned object is tied to the lifetime of the
-  /// ServiceConfig object.
-  ServiceConfigParser::ParsedConfig* GetGlobalParsedConfig(size_t index) {
-    GPR_DEBUG_ASSERT(index < parsed_global_configs_.size());
-    return parsed_global_configs_[index].get();
-  }
-
-  /// Retrieves the vector of parsed configs for the method identified
-  /// by \a path.  The lifetime of the returned vector and contained objects
-  /// is tied to the lifetime of the ServiceConfig object.
-  const ServiceConfigParser::ParsedConfigVector* GetMethodParsedConfigVector(
-      const grpc_slice& path) const;
-
- private:
-  // Helper functions for parsing the method configs.
-  grpc_error_handle ParsePerMethodParams(const grpc_channel_args* args);
-  grpc_error_handle ParseJsonMethodConfig(const grpc_channel_args* args,
-                                          const Json& json);
-
-  // Returns a path string for the JSON name object specified by json.
-  // Sets *error on error.
-  static std::string ParseJsonMethodName(const Json& json,
-                                         grpc_error_handle* error);
-
-  std::string json_string_;
-  Json json_;
-
-  absl::InlinedVector<std::unique_ptr<ServiceConfigParser::ParsedConfig>,
-                      ServiceConfigParser::kNumPreallocatedParsers>
-      parsed_global_configs_;
-  // A map from the method name to the parsed config vector. Note that we are
-  // using a raw pointer and not a unique pointer so that we can use the same
-  // vector for multiple names.
-  std::unordered_map<grpc_slice, const ServiceConfigParser::ParsedConfigVector*,
-                     SliceHash>
-      parsed_method_configs_map_;
-  // Default method config.
-  const ServiceConfigParser::ParsedConfigVector* default_method_config_vector_ =
-      nullptr;
-  // Storage for all the vectors that are being used in
-  // parsed_method_configs_table_.
-  absl::InlinedVector<std::unique_ptr<ServiceConfigParser::ParsedConfigVector>,
-                      32>
-      parsed_method_config_vectors_storage_;
-};
-
-}  // namespace grpc_core
-
-#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SERVICE_CONFIG_H */
diff --git a/src/core/ext/filters/client_channel/service_config_call_data.h b/src/core/ext/filters/client_channel/service_config_call_data.h
deleted file mode 100644 (file)
index e634f6d..0000000
+++ /dev/null
@@ -1,126 +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.
-//
-
-#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SERVICE_CONFIG_CALL_DATA_H
-#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SERVICE_CONFIG_CALL_DATA_H
-
-#include <grpc/support/port_platform.h>
-
-#include <map>
-
-#include "absl/strings/string_view.h"
-
-#include "src/core/ext/filters/client_channel/config_selector.h"
-#include "src/core/ext/filters/client_channel/service_config.h"
-#include "src/core/ext/filters/client_channel/service_config_parser.h"
-#include "src/core/lib/channel/context.h"
-#include "src/core/lib/gprpp/ref_counted_ptr.h"
-
-namespace grpc_core {
-
-/// When a service config is applied to a call in the client_channel_filter,
-/// we create an instance of this object on the arena.  A pointer to this
-/// object is also stored in the call_context, so that future filters can
-/// easily access method and global parameters for the call.
-class ServiceConfigCallData {
- public:
-  ServiceConfigCallData(
-      RefCountedPtr<ServiceConfig> service_config,
-      const ServiceConfigParser::ParsedConfigVector* method_configs,
-      ConfigSelector::CallAttributes call_attributes,
-      ConfigSelector::CallDispatchController* call_dispatch_controller,
-      grpc_call_context_element* call_context)
-      : service_config_(std::move(service_config)),
-        method_configs_(method_configs),
-        call_attributes_(std::move(call_attributes)),
-        call_dispatch_controller_(call_dispatch_controller) {
-    call_context[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].value = this;
-    call_context[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].destroy = Destroy;
-  }
-
-  ServiceConfigCallData(
-      RefCountedPtr<ServiceConfig> service_config,
-      const ServiceConfigParser::ParsedConfigVector* method_configs,
-      grpc_call_context_element* call_context)
-      : ServiceConfigCallData(std::move(service_config), method_configs, {},
-                              nullptr, call_context) {}
-
-  ServiceConfig* service_config() { return service_config_.get(); }
-
-  ServiceConfigParser::ParsedConfig* GetMethodParsedConfig(size_t index) const {
-    return method_configs_ != nullptr ? (*method_configs_)[index].get()
-                                      : nullptr;
-  }
-
-  ServiceConfigParser::ParsedConfig* GetGlobalParsedConfig(size_t index) const {
-    return service_config_->GetGlobalParsedConfig(index);
-  }
-
-  const std::map<const char*, absl::string_view>& call_attributes() const {
-    return call_attributes_;
-  }
-
-  ConfigSelector::CallDispatchController* call_dispatch_controller() {
-    return &call_dispatch_controller_;
-  }
-
- private:
-  // A wrapper for the CallDispatchController returned by the ConfigSelector.
-  // Handles the case where the ConfigSelector doees not return any
-  // CallDispatchController.
-  // Also ensures that we call Commit() at most once, which allows the
-  // client channel code to call Commit() when the call is complete in case
-  // it wasn't called earlier, without needing to know whether or not it was.
-  class SingleCommitCallDispatchController
-      : public ConfigSelector::CallDispatchController {
-   public:
-    explicit SingleCommitCallDispatchController(
-        ConfigSelector::CallDispatchController* call_dispatch_controller)
-        : call_dispatch_controller_(call_dispatch_controller) {}
-
-    bool ShouldRetry() override {
-      if (call_dispatch_controller_ != nullptr) {
-        return call_dispatch_controller_->ShouldRetry();
-      }
-      return true;
-    }
-
-    void Commit() override {
-      if (call_dispatch_controller_ != nullptr && !commit_called_) {
-        call_dispatch_controller_->Commit();
-        commit_called_ = true;
-      }
-    }
-
-   private:
-    ConfigSelector::CallDispatchController* call_dispatch_controller_;
-    bool commit_called_ = false;
-  };
-
-  static void Destroy(void* ptr) {
-    ServiceConfigCallData* self = static_cast<ServiceConfigCallData*>(ptr);
-    self->~ServiceConfigCallData();
-  }
-
-  RefCountedPtr<ServiceConfig> service_config_;
-  const ServiceConfigParser::ParsedConfigVector* method_configs_;
-  ConfigSelector::CallAttributes call_attributes_;
-  SingleCommitCallDispatchController call_dispatch_controller_;
-};
-
-}  // namespace grpc_core
-
-#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SERVICE_CONFIG_CALL_DATA_H */
index 5763e17..1905429 100644 (file)
 
 #include <grpc/support/port_platform.h>
 
-#include "src/core/ext/filters/client_channel/service_config_call_data.h"
+#include "src/core/ext/service_config/service_config_call_data.h"
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/channel/channel_stack.h"
 #include "src/core/lib/channel/channel_stack_builder.h"
-#include "src/core/lib/surface/channel_init.h"
+#include "src/core/lib/config/core_configuration.h"
 
 namespace grpc_core {
 
@@ -59,26 +59,43 @@ class ServiceConfigChannelArgChannelData {
 
 class ServiceConfigChannelArgCallData {
  public:
-  ServiceConfigChannelArgCallData(grpc_call_element* elem,
-                                  const grpc_call_element_args* args) {
-    ServiceConfigChannelArgChannelData* chand =
-        static_cast<ServiceConfigChannelArgChannelData*>(elem->channel_data);
-    RefCountedPtr<ServiceConfig> service_config = chand->service_config();
-    if (service_config != nullptr) {
-      GPR_DEBUG_ASSERT(args->context != nullptr);
-      const auto* method_params_vector =
-          service_config->GetMethodParsedConfigVector(args->path);
-      args->arena->New<ServiceConfigCallData>(
-          std::move(service_config), method_params_vector, args->context);
-    }
+  ServiceConfigChannelArgCallData(
+      RefCountedPtr<ServiceConfig> service_config,
+      const ServiceConfigParser::ParsedConfigVector* method_config,
+      const grpc_call_element_args* args)
+      : call_context_(args->context),
+        service_config_call_data_(std::move(service_config), method_config,
+                                  /*call_attributes=*/{}) {
+    GPR_DEBUG_ASSERT(args->context != nullptr);
+    // No need to set the destroy function, since it will be cleaned up
+    // when this filter is destroyed in the filter stack.
+    args->context[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].value =
+        &service_config_call_data_;
+  }
+
+  ~ServiceConfigChannelArgCallData() {
+    // Remove the entry from call context, just in case anyone above us
+    // tries to look at it during call stack destruction.
+    call_context_[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].value = nullptr;
   }
+
+ private:
+  grpc_call_context_element* call_context_;
+  ServiceConfigCallData service_config_call_data_;
 };
 
 grpc_error_handle ServiceConfigChannelArgInitCallElem(
     grpc_call_element* elem, const grpc_call_element_args* args) {
-  ServiceConfigChannelArgCallData* calld =
-      static_cast<ServiceConfigChannelArgCallData*>(elem->call_data);
-  new (calld) ServiceConfigChannelArgCallData(elem, args);
+  auto* chand =
+      static_cast<ServiceConfigChannelArgChannelData*>(elem->channel_data);
+  auto* calld = static_cast<ServiceConfigChannelArgCallData*>(elem->call_data);
+  RefCountedPtr<ServiceConfig> service_config = chand->service_config();
+  const ServiceConfigParser::ParsedConfigVector* method_config = nullptr;
+  if (service_config != nullptr) {
+    method_config = service_config->GetMethodParsedConfigVector(args->path);
+  }
+  new (calld) ServiceConfigChannelArgCallData(std::move(service_config),
+                                              method_config, args);
   return GRPC_ERROR_NONE;
 }
 
@@ -117,27 +134,23 @@ const grpc_channel_filter ServiceConfigChannelArgFilter = {
     grpc_channel_next_get_info,
     "service_config_channel_arg"};
 
-bool maybe_add_service_config_channel_arg_filter(
-    grpc_channel_stack_builder* builder, void* /* arg */) {
-  const grpc_channel_args* channel_args =
-      grpc_channel_stack_builder_get_channel_arguments(builder);
-  if (grpc_channel_args_want_minimal_stack(channel_args) ||
-      grpc_channel_args_find_string(channel_args, GRPC_ARG_SERVICE_CONFIG) ==
-          nullptr) {
-    return true;
-  }
-  return grpc_channel_stack_builder_prepend_filter(
-      builder, &ServiceConfigChannelArgFilter, nullptr, nullptr);
-}
-
 }  // namespace
 
-}  // namespace grpc_core
-
-void grpc_service_config_channel_arg_filter_init(void) {
-  grpc_channel_init_register_stage(
+void RegisterServiceConfigChannelArgFilter(
+    CoreConfiguration::Builder* builder) {
+  builder->channel_init()->RegisterStage(
       GRPC_CLIENT_DIRECT_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
-      grpc_core::maybe_add_service_config_channel_arg_filter, nullptr);
+      [](grpc_channel_stack_builder* builder) {
+        const grpc_channel_args* channel_args =
+            grpc_channel_stack_builder_get_channel_arguments(builder);
+        if (grpc_channel_args_want_minimal_stack(channel_args) ||
+            grpc_channel_args_find_string(channel_args,
+                                          GRPC_ARG_SERVICE_CONFIG) == nullptr) {
+          return true;
+        }
+        return grpc_channel_stack_builder_prepend_filter(
+            builder, &ServiceConfigChannelArgFilter, nullptr, nullptr);
+      });
 }
 
-void grpc_service_config_channel_arg_filter_shutdown(void) {}
+}  // namespace grpc_core
diff --git a/src/core/ext/filters/client_channel/service_config_parser.cc b/src/core/ext/filters/client_channel/service_config_parser.cc
deleted file mode 100644 (file)
index fa8fbea..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-//
-// Copyright 2015 gRPC authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#include <grpc/support/port_platform.h>
-
-#include "src/core/ext/filters/client_channel/service_config_parser.h"
-
-#include <grpc/support/log.h>
-
-namespace grpc_core {
-
-namespace {
-typedef absl::InlinedVector<std::unique_ptr<ServiceConfigParser::Parser>,
-                            ServiceConfigParser::kNumPreallocatedParsers>
-    ServiceConfigParserList;
-ServiceConfigParserList* g_registered_parsers;
-}  // namespace
-
-void ServiceConfigParser::Init() {
-  GPR_ASSERT(g_registered_parsers == nullptr);
-  g_registered_parsers = new ServiceConfigParserList();
-}
-
-void ServiceConfigParser::Shutdown() {
-  delete g_registered_parsers;
-  g_registered_parsers = nullptr;
-}
-
-size_t ServiceConfigParser::RegisterParser(std::unique_ptr<Parser> parser) {
-  g_registered_parsers->push_back(std::move(parser));
-  return g_registered_parsers->size() - 1;
-}
-
-ServiceConfigParser::ParsedConfigVector
-ServiceConfigParser::ParseGlobalParameters(const grpc_channel_args* args,
-                                           const Json& json,
-                                           grpc_error_handle* error) {
-  ParsedConfigVector parsed_global_configs;
-  std::vector<grpc_error_handle> error_list;
-  for (size_t i = 0; i < g_registered_parsers->size(); i++) {
-    grpc_error_handle parser_error = GRPC_ERROR_NONE;
-    auto parsed_config = (*g_registered_parsers)[i]->ParseGlobalParams(
-        args, json, &parser_error);
-    if (parser_error != GRPC_ERROR_NONE) {
-      error_list.push_back(parser_error);
-    }
-    parsed_global_configs.push_back(std::move(parsed_config));
-  }
-  if (!error_list.empty()) {
-    *error = GRPC_ERROR_CREATE_FROM_VECTOR("Global Params", &error_list);
-  }
-  return parsed_global_configs;
-}
-
-ServiceConfigParser::ParsedConfigVector
-ServiceConfigParser::ParsePerMethodParameters(const grpc_channel_args* args,
-                                              const Json& json,
-                                              grpc_error_handle* error) {
-  ParsedConfigVector parsed_method_configs;
-  std::vector<grpc_error_handle> error_list;
-  for (size_t i = 0; i < g_registered_parsers->size(); i++) {
-    grpc_error_handle parser_error = GRPC_ERROR_NONE;
-    auto parsed_config = (*g_registered_parsers)[i]->ParsePerMethodParams(
-        args, json, &parser_error);
-    if (parser_error != GRPC_ERROR_NONE) {
-      error_list.push_back(parser_error);
-    }
-    parsed_method_configs.push_back(std::move(parsed_config));
-  }
-  if (!error_list.empty()) {
-    *error = GRPC_ERROR_CREATE_FROM_VECTOR("methodConfig", &error_list);
-  }
-  return parsed_method_configs;
-}
-
-}  // namespace grpc_core
diff --git a/src/core/ext/filters/client_channel/service_config_parser.h b/src/core/ext/filters/client_channel/service_config_parser.h
deleted file mode 100644 (file)
index ebd3166..0000000
+++ /dev/null
@@ -1,95 +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.
-//
-
-#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SERVICE_CONFIG_PARSER_H
-#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SERVICE_CONFIG_PARSER_H
-
-#include <grpc/support/port_platform.h>
-
-#include <memory>
-
-#include "absl/container/inlined_vector.h"
-
-#include <grpc/impl/codegen/grpc_types.h>
-
-#include "src/core/lib/iomgr/error.h"
-#include "src/core/lib/json/json.h"
-
-namespace grpc_core {
-
-// Service config parser registry.
-// See service_config.h for more information.
-class ServiceConfigParser {
- public:
-  /// This is the base class that all service config parsers MUST use to store
-  /// parsed service config data.
-  class ParsedConfig {
-   public:
-    virtual ~ParsedConfig() = default;
-  };
-
-  /// This is the base class that all service config parsers should derive from.
-  class Parser {
-   public:
-    virtual ~Parser() = default;
-
-    virtual std::unique_ptr<ParsedConfig> ParseGlobalParams(
-        const grpc_channel_args*, const Json& /* json */,
-        grpc_error_handle* error) {
-      // Avoid unused parameter warning on debug-only parameter
-      (void)error;
-      GPR_DEBUG_ASSERT(error != nullptr);
-      return nullptr;
-    }
-
-    virtual std::unique_ptr<ParsedConfig> ParsePerMethodParams(
-        const grpc_channel_args*, const Json& /* json */,
-        grpc_error_handle* error) {
-      // Avoid unused parameter warning on debug-only parameter
-      (void)error;
-      GPR_DEBUG_ASSERT(error != nullptr);
-      return nullptr;
-    }
-  };
-
-  static constexpr int kNumPreallocatedParsers = 4;
-  typedef absl::InlinedVector<std::unique_ptr<ParsedConfig>,
-                              kNumPreallocatedParsers>
-      ParsedConfigVector;
-
-  static void Init();
-  static void Shutdown();
-
-  /// Globally register a service config parser. On successful registration, it
-  /// returns the index at which the parser was registered. On failure, -1 is
-  /// returned. Each new service config update will go through all the
-  /// registered parser. Each parser is responsible for reading the service
-  /// config json and returning a parsed config. This parsed config can later be
-  /// retrieved using the same index that was returned at registration time.
-  static size_t RegisterParser(std::unique_ptr<Parser> parser);
-
-  static ParsedConfigVector ParseGlobalParameters(const grpc_channel_args* args,
-                                                  const Json& json,
-                                                  grpc_error_handle* error);
-
-  static ParsedConfigVector ParsePerMethodParameters(
-      const grpc_channel_args* args, const Json& json,
-      grpc_error_handle* error);
-};
-
-}  // namespace grpc_core
-
-#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SERVICE_CONFIG_PARSER_H */
index a3db609..39ded50 100644 (file)
@@ -1,20 +1,18 @@
-/*
- *
- * 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.
- *
- */
+//
+// 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 "src/core/ext/filters/client_channel/client_channel.h"
 #include "src/core/ext/filters/client_channel/health/health_check_client.h"
 #include "src/core/ext/filters/client_channel/proxy_mapper_registry.h"
-#include "src/core/ext/filters/client_channel/service_config.h"
 #include "src/core/ext/filters/client_channel/subchannel_pool_interface.h"
 #include "src/core/lib/address_utils/parse_address.h"
 #include "src/core/lib/address_utils/sockaddr_utils.h"
 #include "src/core/lib/backoff/backoff.h"
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/channel/connected_channel.h"
+#include "src/core/lib/config/core_configuration.h"
 #include "src/core/lib/debug/stats.h"
 #include "src/core/lib/gpr/alloc.h"
 #include "src/core/lib/gprpp/debug_location.h"
@@ -50,7 +48,6 @@
 #include "src/core/lib/profiling/timers.h"
 #include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/surface/channel.h"
-#include "src/core/lib/surface/channel_init.h"
 #include "src/core/lib/transport/connectivity_state.h"
 #include "src/core/lib/transport/error_utils.h"
 #include "src/core/lib/transport/status_metadata.h"
@@ -255,9 +252,9 @@ void GetCallStatus(grpc_status_code* status, grpc_millis deadline,
   if (error != GRPC_ERROR_NONE) {
     grpc_error_get_status(error, deadline, status, nullptr, nullptr, nullptr);
   } else {
-    if (md_batch->idx.named.grpc_status != nullptr) {
+    if (md_batch->legacy_index()->named.grpc_status != nullptr) {
       *status = grpc_get_status_code_from_metadata(
-          md_batch->idx.named.grpc_status->md);
+          md_batch->legacy_index()->named.grpc_status->md);
     } else {
       *status = GRPC_STATUS_UNKNOWN;
     }
@@ -319,11 +316,12 @@ class Subchannel::ConnectedSubchannelStateWatcher
       case GRPC_CHANNEL_TRANSIENT_FAILURE:
       case GRPC_CHANNEL_SHUTDOWN: {
         if (!c->disconnected_ && c->connected_subchannel_ != nullptr) {
-          if (grpc_trace_subchannel.enabled()) {
+          if (GRPC_TRACE_FLAG_ENABLED(grpc_trace_subchannel)) {
             gpr_log(GPR_INFO,
-                    "Connected subchannel %p of subchannel %p has gone into "
+                    "subchannel %p %s: Connected subchannel %p has gone into "
                     "%s. Attempting to reconnect.",
-                    c->connected_subchannel_.get(), c,
+                    c, c->key_.ToString().c_str(),
+                    c->connected_subchannel_.get(),
                     ConnectivityStateName(new_state));
           }
           c->connected_subchannel_.reset();
@@ -363,15 +361,9 @@ class Subchannel::AsyncWatcherNotifierLocked {
  public:
   AsyncWatcherNotifierLocked(
       RefCountedPtr<Subchannel::ConnectivityStateWatcherInterface> watcher,
-      Subchannel* subchannel, grpc_connectivity_state state,
-      const absl::Status& status)
+      grpc_connectivity_state state, const absl::Status& status)
       : watcher_(std::move(watcher)) {
-    RefCountedPtr<ConnectedSubchannel> connected_subchannel;
-    if (state == GRPC_CHANNEL_READY) {
-      connected_subchannel = subchannel->connected_subchannel_;
-    }
-    watcher_->PushConnectivityStateChange(
-        {state, status, std::move(connected_subchannel)});
+    watcher_->PushConnectivityStateChange({state, status});
     ExecCtx::Run(DEBUG_LOCATION,
                  GRPC_CLOSURE_INIT(
                      &closure_,
@@ -405,10 +397,9 @@ void Subchannel::ConnectivityStateWatcherList::RemoveWatcherLocked(
 }
 
 void Subchannel::ConnectivityStateWatcherList::NotifyLocked(
-    Subchannel* subchannel, grpc_connectivity_state state,
-    const absl::Status& status) {
+    grpc_connectivity_state state, const absl::Status& status) {
   for (const auto& p : watchers_) {
-    new AsyncWatcherNotifierLocked(p.second, subchannel, state, status);
+    new AsyncWatcherNotifierLocked(p.second, state, status);
   }
 }
 
@@ -446,8 +437,7 @@ class Subchannel::HealthWatcherMap::HealthWatcher
       grpc_connectivity_state initial_state,
       RefCountedPtr<Subchannel::ConnectivityStateWatcherInterface> watcher) {
     if (state_ != initial_state) {
-      new AsyncWatcherNotifierLocked(watcher, subchannel_.get(), state_,
-                                     status_);
+      new AsyncWatcherNotifierLocked(watcher, state_, status_);
     }
     watcher_list_.AddWatcherLocked(std::move(watcher));
   }
@@ -469,14 +459,14 @@ class Subchannel::HealthWatcherMap::HealthWatcher
       if (state_ != GRPC_CHANNEL_CONNECTING) {
         state_ = GRPC_CHANNEL_CONNECTING;
         status_ = status;
-        watcher_list_.NotifyLocked(subchannel_.get(), state_, status);
+        watcher_list_.NotifyLocked(state_, status);
       }
       // If we've become connected, start health checking.
       StartHealthCheckingLocked();
     } else {
       state_ = state;
       status_ = status;
-      watcher_list_.NotifyLocked(subchannel_.get(), state_, status);
+      watcher_list_.NotifyLocked(state_, status);
       // We're not connected, so stop health checking.
       health_check_client_.reset();
     }
@@ -495,7 +485,7 @@ class Subchannel::HealthWatcherMap::HealthWatcher
     if (new_state != GRPC_CHANNEL_SHUTDOWN && health_check_client_ != nullptr) {
       state_ = new_state;
       status_ = status;
-      watcher_list_.NotifyLocked(subchannel_.get(), new_state, status);
+      watcher_list_.NotifyLocked(new_state, status);
     }
   }
 
@@ -655,42 +645,39 @@ Subchannel::Subchannel(SubchannelKey key,
           GRPC_TRACE_FLAG_ENABLED(grpc_trace_subchannel_refcount) ? "Subchannel"
                                                                   : nullptr),
       key_(std::move(key)),
+      pollset_set_(grpc_pollset_set_create()),
       connector_(std::move(connector)),
       backoff_(ParseArgsForBackoffValues(args, &min_connect_timeout_ms_)) {
   GRPC_STATS_INC_CLIENT_SUBCHANNELS_CREATED();
-  pollset_set_ = grpc_pollset_set_create();
-  grpc_resolved_address* addr =
-      static_cast<grpc_resolved_address*>(gpr_malloc(sizeof(*addr)));
-  GetAddressFromSubchannelAddressArg(args, addr);
+  GRPC_CLOSURE_INIT(&on_connecting_finished_, OnConnectingFinished, this,
+                    grpc_schedule_on_exec_ctx);
+  // Check proxy mapper to determine address to connect to and channel
+  // args to use.
+  address_for_connect_ = key_.address();
   grpc_resolved_address* new_address = nullptr;
   grpc_channel_args* new_args = nullptr;
-  if (ProxyMapperRegistry::MapAddress(*addr, args, &new_address, &new_args)) {
+  if (ProxyMapperRegistry::MapAddress(address_for_connect_, args, &new_address,
+                                      &new_args)) {
     GPR_ASSERT(new_address != nullptr);
-    gpr_free(addr);
-    addr = new_address;
+    address_for_connect_ = *new_address;
+    gpr_free(new_address);
   }
-  static const char* keys_to_remove[] = {GRPC_ARG_SUBCHANNEL_ADDRESS};
-  grpc_arg new_arg = CreateSubchannelAddressArg(addr);
-  gpr_free(addr);
-  args_ = grpc_channel_args_copy_and_add_and_remove(
-      new_args != nullptr ? new_args : args, keys_to_remove,
-      GPR_ARRAY_SIZE(keys_to_remove), &new_arg, 1);
-  gpr_free(new_arg.value.string);
-  if (new_args != nullptr) grpc_channel_args_destroy(new_args);
-  GRPC_CLOSURE_INIT(&on_connecting_finished_, OnConnectingFinished, this,
-                    grpc_schedule_on_exec_ctx);
-  const grpc_arg* arg = grpc_channel_args_find(args_, GRPC_ARG_ENABLE_CHANNELZ);
-  const bool channelz_enabled =
-      grpc_channel_arg_get_bool(arg, GRPC_ENABLE_CHANNELZ_DEFAULT);
-  arg = grpc_channel_args_find(
-      args_, GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE);
-  const grpc_integer_options options = {
-      GRPC_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE_DEFAULT, 0, INT_MAX};
-  size_t channel_tracer_max_memory =
-      static_cast<size_t>(grpc_channel_arg_get_integer(arg, options));
+  if (new_args != nullptr) {
+    args_ = new_args;
+  } else {
+    args_ = grpc_channel_args_copy(args);
+  }
+  // Initialize channelz.
+  const bool channelz_enabled = grpc_channel_args_find_bool(
+      args_, GRPC_ARG_ENABLE_CHANNELZ, GRPC_ENABLE_CHANNELZ_DEFAULT);
   if (channelz_enabled) {
+    const size_t channel_tracer_max_memory =
+        static_cast<size_t>(grpc_channel_args_find_integer(
+            args_, GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE,
+            {GRPC_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE_DEFAULT, 0,
+             INT_MAX}));
     channelz_node_ = MakeRefCounted<channelz::SubchannelNode>(
-        GetTargetAddress(), channel_tracer_max_memory);
+        grpc_sockaddr_to_uri(&key_.address()), channel_tracer_max_memory);
     channelz_node_->AddTraceEvent(
         channelz::ChannelTrace::Severity::Info,
         grpc_slice_from_static_string("subchannel created"));
@@ -711,8 +698,8 @@ Subchannel::~Subchannel() {
 
 RefCountedPtr<Subchannel> Subchannel::Create(
     OrphanablePtr<SubchannelConnector> connector,
-    const grpc_channel_args* args) {
-  SubchannelKey key(args);
+    const grpc_resolved_address& address, const grpc_channel_args* args) {
+  SubchannelKey key(address, args);
   SubchannelPoolInterface* subchannel_pool =
       SubchannelPoolInterface::GetSubchannelPoolFromChannelArgs(args);
   GPR_ASSERT(subchannel_pool != nullptr);
@@ -736,9 +723,9 @@ void Subchannel::ThrottleKeepaliveTime(int new_keepalive_time) {
   // Only update the value if the new keepalive time is larger.
   if (new_keepalive_time > keepalive_time_) {
     keepalive_time_ = new_keepalive_time;
-    if (grpc_trace_subchannel.enabled()) {
-      gpr_log(GPR_INFO, "Subchannel=%p: Throttling keepalive time to %d", this,
-              new_keepalive_time);
+    if (GRPC_TRACE_FLAG_ENABLED(grpc_trace_subchannel)) {
+      gpr_log(GPR_INFO, "subchannel %p %s: throttling keepalive time to %d",
+              this, key_.ToString().c_str(), new_keepalive_time);
     }
     const grpc_arg arg_to_add = grpc_channel_arg_integer_create(
         const_cast<char*>(GRPC_ARG_KEEPALIVE_TIME_MS), new_keepalive_time);
@@ -750,33 +737,18 @@ void Subchannel::ThrottleKeepaliveTime(int new_keepalive_time) {
   }
 }
 
-const char* Subchannel::GetTargetAddress() {
-  const grpc_arg* addr_arg =
-      grpc_channel_args_find(args_, GRPC_ARG_SUBCHANNEL_ADDRESS);
-  const char* addr_str = grpc_channel_arg_get_string(addr_arg);
-  GPR_ASSERT(addr_str != nullptr);  // Should have been set by LB policy.
-  return addr_str;
-}
-
 channelz::SubchannelNode* Subchannel::channelz_node() {
   return channelz_node_.get();
 }
 
 grpc_connectivity_state Subchannel::CheckConnectivityState(
-    const absl::optional<std::string>& health_check_service_name,
-    RefCountedPtr<ConnectedSubchannel>* connected_subchannel) {
+    const absl::optional<std::string>& health_check_service_name) {
   MutexLock lock(&mu_);
-  grpc_connectivity_state state;
-  if (!health_check_service_name.has_value()) {
-    state = state_;
-  } else {
-    state = health_watcher_map_.CheckConnectivityStateLocked(
+  if (health_check_service_name.has_value()) {
+    return health_watcher_map_.CheckConnectivityStateLocked(
         this, *health_check_service_name);
   }
-  if (connected_subchannel != nullptr && state == GRPC_CHANNEL_READY) {
-    *connected_subchannel = connected_subchannel_;
-  }
-  return state;
+  return state_;
 }
 
 void Subchannel::WatchConnectivityState(
@@ -790,7 +762,7 @@ void Subchannel::WatchConnectivityState(
   }
   if (!health_check_service_name.has_value()) {
     if (state_ != initial_state) {
-      new AsyncWatcherNotifierLocked(watcher, this, state_, status_);
+      new AsyncWatcherNotifierLocked(watcher, state_, status_);
     }
     watcher_list_.AddWatcherLocked(std::move(watcher));
   } else {
@@ -848,44 +820,6 @@ void Subchannel::Orphan() {
   health_watcher_map_.ShutdownLocked();
 }
 
-grpc_arg Subchannel::CreateSubchannelAddressArg(
-    const grpc_resolved_address* addr) {
-  return grpc_channel_arg_string_create(
-      const_cast<char*>(GRPC_ARG_SUBCHANNEL_ADDRESS),
-      gpr_strdup(addr->len > 0 ? grpc_sockaddr_to_uri(addr).c_str() : ""));
-}
-
-const char* Subchannel::GetUriFromSubchannelAddressArg(
-    const grpc_channel_args* args) {
-  const grpc_arg* addr_arg =
-      grpc_channel_args_find(args, GRPC_ARG_SUBCHANNEL_ADDRESS);
-  const char* addr_str = grpc_channel_arg_get_string(addr_arg);
-  GPR_ASSERT(addr_str != nullptr);  // Should have been set by LB policy.
-  return addr_str;
-}
-
-namespace {
-
-void UriToSockaddr(const char* uri_str, grpc_resolved_address* addr) {
-  absl::StatusOr<URI> uri = URI::Parse(uri_str);
-  if (!uri.ok()) {
-    gpr_log(GPR_ERROR, "%s", uri.status().ToString().c_str());
-    GPR_ASSERT(uri.ok());
-  }
-  if (!grpc_parse_uri(*uri, addr)) memset(addr, 0, sizeof(*addr));
-}
-
-}  // namespace
-
-void Subchannel::GetAddressFromSubchannelAddressArg(
-    const grpc_channel_args* args, grpc_resolved_address* addr) {
-  const char* addr_uri_str = GetUriFromSubchannelAddressArg(args);
-  memset(addr, 0, sizeof(*addr));
-  if (*addr_uri_str != '\0') {
-    UriToSockaddr(addr_uri_str, addr);
-  }
-}
-
 namespace {
 
 // Returns a string indicating the subchannel's connectivity state change to
@@ -922,7 +856,7 @@ void Subchannel::SetConnectivityStateLocked(grpc_connectivity_state state,
             SubchannelConnectivityStateChangeString(state)));
   }
   // Notify non-health watchers.
-  watcher_list_.NotifyLocked(this, state, status);
+  watcher_list_.NotifyLocked(state, status);
   // Notify health watchers.
   health_watcher_map_.NotifyLocked(state, status);
 }
@@ -952,10 +886,11 @@ void Subchannel::MaybeStartConnectingLocked() {
     const grpc_millis time_til_next =
         next_attempt_deadline_ - ExecCtx::Get()->Now();
     if (time_til_next <= 0) {
-      gpr_log(GPR_INFO, "Subchannel %p: Retry immediately", this);
+      gpr_log(GPR_INFO, "subchannel %p %s: Retry immediately", this,
+              key_.ToString().c_str());
     } else {
-      gpr_log(GPR_INFO, "Subchannel %p: Retry in %" PRId64 " milliseconds",
-              this, time_til_next);
+      gpr_log(GPR_INFO, "subchannel %p %s: Retry in %" PRId64 " milliseconds",
+              this, key_.ToString().c_str(), time_til_next);
     }
     GRPC_CLOSURE_INIT(&on_retry_alarm_, OnRetryAlarm, this,
                       grpc_schedule_on_exec_ctx);
@@ -974,10 +909,12 @@ void Subchannel::OnRetryAlarm(void* arg, grpc_error_handle error) {
     c->retry_immediately_ = false;
     error = GRPC_ERROR_NONE;
   } else {
-    GRPC_ERROR_REF(error);
+    (void)GRPC_ERROR_REF(error);
   }
   if (error == GRPC_ERROR_NONE) {
-    gpr_log(GPR_INFO, "Failed to connect to channel, retrying");
+    gpr_log(GPR_INFO,
+            "subchannel %p %s: failed to connect to channel, retrying", c.get(),
+            c->key_.ToString().c_str());
     c->ContinueConnectingLocked();
     // Still connecting, keep ref around. Note that this stolen ref won't
     // be dropped without first acquiring c->mu_.
@@ -988,6 +925,7 @@ void Subchannel::OnRetryAlarm(void* arg, grpc_error_handle error) {
 
 void Subchannel::ContinueConnectingLocked() {
   SubchannelConnector::Args args;
+  args.address = &address_for_connect_;
   args.interested_parties = pollset_set_;
   const grpc_millis min_deadline =
       min_connect_timeout_ms_ + ExecCtx::Get()->Now();
@@ -1009,8 +947,8 @@ void Subchannel::OnConnectingFinished(void* arg, grpc_error_handle error) {
         c->PublishTransportLocked()) {
       // Do nothing, transport was published.
     } else if (!c->disconnected_) {
-      gpr_log(GPR_INFO, "Connect failed: %s",
-              grpc_error_std_string(error).c_str());
+      gpr_log(GPR_INFO, "subchannel %p %s: connect failed: %s", c.get(),
+              c->key_.ToString().c_str(), grpc_error_std_string(error).c_str());
       c->SetConnectivityStateLocked(GRPC_CHANNEL_TRANSIENT_FAILURE,
                                     grpc_error_to_absl_status(error));
     }
@@ -1036,7 +974,8 @@ bool Subchannel::PublishTransportLocked() {
       builder, connecting_result_.channel_args);
   grpc_channel_stack_builder_set_transport(builder,
                                            connecting_result_.transport);
-  if (!grpc_channel_init_create_stack(builder, GRPC_CLIENT_SUBCHANNEL)) {
+  if (!CoreConfiguration::Get().channel_init().CreateStack(
+          builder, GRPC_CLIENT_SUBCHANNEL)) {
     grpc_channel_stack_builder_destroy(builder);
     return false;
   }
@@ -1046,8 +985,9 @@ bool Subchannel::PublishTransportLocked() {
       reinterpret_cast<void**>(&stk));
   if (error != GRPC_ERROR_NONE) {
     grpc_transport_destroy(connecting_result_.transport);
-    gpr_log(GPR_ERROR, "error initializing subchannel stack: %s",
-            grpc_error_std_string(error).c_str());
+    gpr_log(GPR_ERROR,
+            "subchannel %p %s: error initializing subchannel stack: %s", this,
+            key_.ToString().c_str(), grpc_error_std_string(error).c_str());
     GRPC_ERROR_UNREF(error);
     return false;
   }
@@ -1062,8 +1002,10 @@ bool Subchannel::PublishTransportLocked() {
   // Publish.
   connected_subchannel_.reset(
       new ConnectedSubchannel(stk, args_, channelz_node_));
-  gpr_log(GPR_INFO, "New connected subchannel at %p for subchannel %p",
-          connected_subchannel_.get(), this);
+  if (GRPC_TRACE_FLAG_ENABLED(grpc_trace_subchannel)) {
+    gpr_log(GPR_INFO, "subchannel %p %s: new connected subchannel at %p", this,
+            key_.ToString().c_str(), connected_subchannel_.get());
+  }
   if (channelz_node_ != nullptr) {
     channelz_node_->SetChildSocket(std::move(socket));
   }
index 9667fe7..d956d3e 100644 (file)
@@ -1,20 +1,18 @@
-/*
- *
- * 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.
- *
- */
+//
+// 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.
+//
 
 #ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SUBCHANNEL_H
 #define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SUBCHANNEL_H
@@ -39,9 +37,6 @@
 #include "src/core/lib/transport/connectivity_state.h"
 #include "src/core/lib/transport/metadata.h"
 
-// Channel arg containing a URI indicating the address to connect to.
-#define GRPC_ARG_SUBCHANNEL_ADDRESS "grpc.subchannel_address"
-
 namespace grpc_core {
 
 class SubchannelCall;
@@ -153,7 +148,6 @@ class Subchannel : public DualRefCounted<Subchannel> {
     struct ConnectivityStateChange {
       grpc_connectivity_state state;
       absl::Status status;
-      RefCountedPtr<ConnectedSubchannel> connected_subchannel;
     };
 
     ~ConnectivityStateWatcherInterface() override = default;
@@ -190,10 +184,10 @@ class Subchannel : public DualRefCounted<Subchannel> {
         ABSL_GUARDED_BY(&mu_);
   };
 
-  // Creates a subchannel given \a connector and \a args.
+  // Creates a subchannel.
   static RefCountedPtr<Subchannel> Create(
       OrphanablePtr<SubchannelConnector> connector,
-      const grpc_channel_args* args);
+      const grpc_resolved_address& address, const grpc_channel_args* args);
 
   // The ctor and dtor are not intended to use directly.
   Subchannel(SubchannelKey key, OrphanablePtr<SubchannelConnector> connector,
@@ -205,10 +199,6 @@ class Subchannel : public DualRefCounted<Subchannel> {
   // will have an affect when the subchannel creates a new ConnectedSubchannel.
   void ThrottleKeepaliveTime(int new_keepalive_time) ABSL_LOCKS_EXCLUDED(mu_);
 
-  // Gets the string representing the subchannel address.
-  // Caller doesn't take ownership.
-  const char* GetTargetAddress();
-
   const grpc_channel_args* channel_args() const { return args_; }
 
   channelz::SubchannelNode* channelz_node();
@@ -217,10 +207,8 @@ class Subchannel : public DualRefCounted<Subchannel> {
   // If health_check_service_name is non-null, the returned connectivity
   // state will be based on the state reported by the backend for that
   // service name.
-  // If the return value is GRPC_CHANNEL_READY, also sets *connected_subchannel.
   grpc_connectivity_state CheckConnectivityState(
-      const absl::optional<std::string>& health_check_service_name,
-      RefCountedPtr<ConnectedSubchannel>* connected_subchannel)
+      const absl::optional<std::string>& health_check_service_name)
       ABSL_LOCKS_EXCLUDED(mu_);
 
   // Starts watching the subchannel's connectivity state.
@@ -243,31 +231,21 @@ class Subchannel : public DualRefCounted<Subchannel> {
       const absl::optional<std::string>& health_check_service_name,
       ConnectivityStateWatcherInterface* watcher) ABSL_LOCKS_EXCLUDED(mu_);
 
+  RefCountedPtr<ConnectedSubchannel> connected_subchannel()
+      ABSL_LOCKS_EXCLUDED(mu_) {
+    MutexLock lock(&mu_);
+    return connected_subchannel_;
+  }
+
   // Attempt to connect to the backend.  Has no effect if already connected.
   void AttemptToConnect() ABSL_LOCKS_EXCLUDED(mu_);
 
   // Resets the connection backoff of the subchannel.
-  // TODO(roth): Move connection backoff out of subchannels and up into LB
-  // policy code (probably by adding a SubchannelGroup between
-  // SubchannelList and SubchannelData), at which point this method can
-  // go away.
   void ResetBackoff() ABSL_LOCKS_EXCLUDED(mu_);
 
   // Tears down any existing connection, and arranges for destruction
   void Orphan() override ABSL_LOCKS_EXCLUDED(mu_);
 
-  // Returns a new channel arg encoding the subchannel address as a URI
-  // string. Caller is responsible for freeing the string.
-  static grpc_arg CreateSubchannelAddressArg(const grpc_resolved_address* addr);
-
-  // Returns the URI string from the subchannel address arg in \a args.
-  static const char* GetUriFromSubchannelAddressArg(
-      const grpc_channel_args* args);
-
-  // Sets \a addr from the subchannel address arg in \a args.
-  static void GetAddressFromSubchannelAddressArg(const grpc_channel_args* args,
-                                                 grpc_resolved_address* addr);
-
  private:
   // A linked list of ConnectivityStateWatcherInterfaces that are monitoring
   // the subchannel's state.
@@ -280,7 +258,7 @@ class Subchannel : public DualRefCounted<Subchannel> {
     void RemoveWatcherLocked(ConnectivityStateWatcherInterface* watcher);
 
     // Notifies all watchers in the list about a change to state.
-    void NotifyLocked(Subchannel* subchannel, grpc_connectivity_state state,
+    void NotifyLocked(grpc_connectivity_state state,
                       const absl::Status& status);
 
     void Clear() { watchers_.clear(); }
@@ -350,9 +328,11 @@ class Subchannel : public DualRefCounted<Subchannel> {
 
   // The subchannel pool this subchannel is in.
   RefCountedPtr<SubchannelPoolInterface> subchannel_pool_;
-  // TODO(juanlishen): Consider using args_ as key_ directly.
   // Subchannel key that identifies this subchannel in the subchannel pool.
   const SubchannelKey key_;
+  // Actual address to connect to.  May be different than the address in
+  // key_ if overridden by proxy mapper.
+  grpc_resolved_address address_for_connect_;
   // Channel args.
   grpc_channel_args* args_;
   // pollset_set tracking who's interested in a connection being setup.
@@ -399,4 +379,4 @@ class Subchannel : public DualRefCounted<Subchannel> {
 
 }  // namespace grpc_core
 
-#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SUBCHANNEL_H */
+#endif  // GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SUBCHANNEL_H
index 308541c..d6b12ec 100644 (file)
 
 #include "src/core/ext/filters/client_channel/subchannel_pool_interface.h"
 
+#include "src/core/lib/address_utils/sockaddr_utils.h"
 #include "src/core/lib/gpr/useful.h"
 
 // The subchannel pool to reuse subchannels.
-#define GRPC_ARG_SUBCHANNEL_POOL "grpc.subchannel_pool"
+#define GRPC_ARG_SUBCHANNEL_POOL "grpc.internal.subchannel_pool"
 // The subchannel key ID that is only used in test to make each key unique.
 #define GRPC_ARG_SUBCHANNEL_KEY_TEST_ONLY_ID "grpc.subchannel_key_test_only_id"
 
@@ -31,8 +32,9 @@ namespace grpc_core {
 
 TraceFlag grpc_subchannel_pool_trace(false, "subchannel_pool");
 
-SubchannelKey::SubchannelKey(const grpc_channel_args* args) {
-  Init(args, grpc_channel_args_normalize);
+SubchannelKey::SubchannelKey(const grpc_resolved_address& address,
+                             const grpc_channel_args* args) {
+  Init(address, args, grpc_channel_args_normalize);
 }
 
 SubchannelKey::~SubchannelKey() {
@@ -40,7 +42,7 @@ SubchannelKey::~SubchannelKey() {
 }
 
 SubchannelKey::SubchannelKey(const SubchannelKey& other) {
-  Init(other.args_, grpc_channel_args_copy);
+  Init(other.address_, other.args_, grpc_channel_args_copy);
 }
 
 SubchannelKey& SubchannelKey::operator=(const SubchannelKey& other) {
@@ -48,31 +50,44 @@ SubchannelKey& SubchannelKey::operator=(const SubchannelKey& other) {
     return *this;
   }
   grpc_channel_args_destroy(const_cast<grpc_channel_args*>(args_));
-  Init(other.args_, grpc_channel_args_copy);
+  Init(other.address_, other.args_, grpc_channel_args_copy);
   return *this;
 }
 
 SubchannelKey::SubchannelKey(SubchannelKey&& other) noexcept {
+  address_ = other.address_;
   args_ = other.args_;
   other.args_ = nullptr;
 }
 
 SubchannelKey& SubchannelKey::operator=(SubchannelKey&& other) noexcept {
+  address_ = other.address_;
   args_ = other.args_;
   other.args_ = nullptr;
   return *this;
 }
 
 bool SubchannelKey::operator<(const SubchannelKey& other) const {
+  if (address_.len < other.address_.len) return true;
+  if (address_.len > other.address_.len) return false;
+  int r = memcmp(address_.addr, other.address_.addr, address_.len);
+  if (r < 0) return true;
+  if (r > 0) return false;
   return grpc_channel_args_compare(args_, other.args_) < 0;
 }
 
 void SubchannelKey::Init(
-    const grpc_channel_args* args,
+    const grpc_resolved_address& address, const grpc_channel_args* args,
     grpc_channel_args* (*copy_channel_args)(const grpc_channel_args* args)) {
+  address_ = address;
   args_ = copy_channel_args(args);
 }
 
+std::string SubchannelKey::ToString() const {
+  return absl::StrCat("{address=", grpc_sockaddr_to_uri(&address_),
+                      ", args=", grpc_channel_args_string(args_), "}");
+}
+
 namespace {
 
 void* arg_copy(void* p) {
@@ -86,7 +101,7 @@ void arg_destroy(void* p) {
   subchannel_pool->Unref();
 }
 
-int arg_cmp(void* a, void* b) { return GPR_ICMP(a, b); }
+int arg_cmp(void* a, void* b) { return QsortCompare(a, b); }
 
 const grpc_arg_pointer_vtable subchannel_pool_arg_vtable = {
     arg_copy, arg_destroy, arg_cmp};
index 8a8a0cb..515104d 100644 (file)
@@ -25,6 +25,7 @@
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/debug/trace.h"
 #include "src/core/lib/gprpp/ref_counted.h"
+#include "src/core/lib/iomgr/resolve_address.h"
 
 namespace grpc_core {
 
@@ -35,7 +36,8 @@ extern TraceFlag grpc_subchannel_pool_trace;
 // A key that can uniquely identify a subchannel.
 class SubchannelKey {
  public:
-  explicit SubchannelKey(const grpc_channel_args* args);
+  SubchannelKey(const grpc_resolved_address& address,
+                const grpc_channel_args* args);
   ~SubchannelKey();
 
   // Copyable.
@@ -47,13 +49,20 @@ class SubchannelKey {
 
   bool operator<(const SubchannelKey& other) const;
 
+  const grpc_resolved_address& address() const { return address_; }
+  const grpc_channel_args* args() const { return args_; }
+
+  // Human-readable string suitable for logging.
+  std::string ToString() const;
+
  private:
   // Initializes the subchannel key with the given \a args and the function to
   // copy channel args.
   void Init(
-      const grpc_channel_args* args,
+      const grpc_resolved_address& address, const grpc_channel_args* args,
       grpc_channel_args* (*copy_channel_args)(const grpc_channel_args* args));
 
+  grpc_resolved_address address_;
   const grpc_channel_args* args_;
 };
 
index f27509e..6cd3d12 100644 (file)
 
 #include <atomic>
 
+#include "src/core/ext/filters/client_idle/idle_filter_state.h"
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/channel/channel_stack_builder.h"
+#include "src/core/lib/config/core_configuration.h"
 #include "src/core/lib/iomgr/timer.h"
-#include "src/core/lib/surface/channel_init.h"
 #include "src/core/lib/transport/http2_errors.h"
 
 // TODO(juanlishen): The idle filter is disabled in client channel by default
@@ -47,78 +48,8 @@ TraceFlag grpc_trace_client_idle_filter(false, "client_idle_filter");
 
 namespace {
 
-/*
-  client_idle_filter maintains a state tracking if there are active calls in the
-  channel and its internal idle_timer_. The states are specified as following:
-
-  +--------------------------------------------+-------------+---------+
-  |               ChannelState                 | idle_timer_ | channel |
-  +--------------------------------------------+-------------+---------+
-  | IDLE                                       | unset       | idle    |
-  | CALLS_ACTIVE                               | unset       | busy    |
-  | TIMER_PENDING                              | set-valid   | idle    |
-  | TIMER_PENDING_CALLS_ACTIVE                 | set-invalid | busy    |
-  | TIMER_PENDING_CALLS_SEEN_SINCE_TIMER_START | set-invalid | idle    |
-  +--------------------------------------------+-------------+---------+
-
-  IDLE: The initial state of the client_idle_filter, indicating the channel is
-  in IDLE.
-
-  CALLS_ACTIVE: The channel has 1 or 1+ active calls and the timer is not set.
-
-  TIMER_PENDING: The state after the timer is set and no calls have arrived
-  after the timer is set. The channel must have 0 active call in this state. If
-  the timer is fired in this state, the channel will go into IDLE state.
-
-  TIMER_PENDING_CALLS_ACTIVE: The state after the timer is set and at least one
-  call has arrived after the timer is set. The channel must have 1 or 1+ active
-  calls in this state. If the timer is fired in this state, we won't reschedule
-  it.
-
-  TIMER_PENDING_CALLS_SEEN_SINCE_TIMER_START: The state after the timer is set
-  and at least one call has arrived after the timer is set, BUT the channel
-  currently has 0 active call. If the timer is fired in this state, we will
-  reschedule it according to the finish time of the latest call.
-
-  PROCESSING: The state set to block other threads when the setting thread is
-  doing some work to keep state consistency.
-
-  idle_timer_ will not be cancelled (unless the channel is shutting down).
-  If the timer callback is called when the idle_timer_ is valid (i.e. idle_state
-  is TIMER_PENDING), the channel will enter IDLE, otherwise the channel won't be
-  changed.
-
-  State transitions:
-                                            IDLE
-                                            |  ^
-            ---------------------------------  *
-            |                                  *
-            v                                  *
-      CALLS_ACTIVE =================> TIMER_PENDING
-            ^                               |  ^
-            *  ------------------------------  *
-            *  |                               *
-            *  v                               *
-TIMER_PENDING_CALLS_ACTIVE ===> TIMER_PENDING_CALLS_SEEN_SINCE_TIMER_START
-            ^                               |
-            |                               |
-            ---------------------------------
-
-  ---> Triggered by IncreaseCallCount()
-  ===> Triggered by DecreaseCallCount()
-  ***> Triggered by IdleTimerCallback()
-*/
-enum ChannelState {
-  IDLE,
-  CALLS_ACTIVE,
-  TIMER_PENDING,
-  TIMER_PENDING_CALLS_ACTIVE,
-  TIMER_PENDING_CALLS_SEEN_SINCE_TIMER_START,
-  PROCESSING
-};
-
 grpc_millis GetClientIdleTimeout(const grpc_channel_args* args) {
-  return GPR_MAX(
+  return std::max(
       grpc_channel_arg_get_integer(
           grpc_channel_args_find(args, GRPC_ARG_CLIENT_IDLE_TIMEOUT_MS),
           {DEFAULT_IDLE_TIMEOUT_MS, 0, INT_MAX}),
@@ -159,9 +90,7 @@ class ChannelData {
   const grpc_millis client_idle_timeout_;
 
   // Member data used to track the state of channel.
-  grpc_millis last_idle_time_;
-  std::atomic<intptr_t> call_count_{0};
-  std::atomic<ChannelState> state_{IDLE};
+  IdleFilterState idle_filter_state_{false};
 
   // Idle timer and its callback closure.
   grpc_timer idle_timer_;
@@ -202,86 +131,13 @@ void ChannelData::StartTransportOp(grpc_channel_element* elem,
 }
 
 void ChannelData::IncreaseCallCount() {
-  const intptr_t previous_value =
-      call_count_.fetch_add(1, std::memory_order_relaxed);
-  GRPC_IDLE_FILTER_LOG("call counter has increased to %" PRIuPTR,
-                       previous_value + 1);
-  if (previous_value == 0) {
-    // This call is the one that makes the channel busy.
-    // Loop here to make sure the previous decrease operation has finished.
-    ChannelState state = state_.load(std::memory_order_relaxed);
-    while (true) {
-      switch (state) {
-        // Timer has not been set. Switch to CALLS_ACTIVE.
-        case IDLE:
-          // In this case, no other threads will modify the state, so we can
-          // just store the value.
-          state_.store(CALLS_ACTIVE, std::memory_order_relaxed);
-          return;
-        // Timer has been set. Switch to TIMER_PENDING_CALLS_ACTIVE.
-        case TIMER_PENDING:
-        case TIMER_PENDING_CALLS_SEEN_SINCE_TIMER_START:
-          // At this point, the state may have been switched to IDLE by the
-          // idle timer callback. Therefore, use CAS operation to change the
-          // state atomically.
-          // Use std::memory_order_acquire on success to ensure last_idle_time_
-          // has been properly set in DecreaseCallCount().
-          if (state_.compare_exchange_weak(state, TIMER_PENDING_CALLS_ACTIVE,
-                                           std::memory_order_acquire,
-                                           std::memory_order_relaxed)) {
-            return;
-          }
-          break;
-        default:
-          // The state has not been switched to desired value yet, try again.
-          state = state_.load(std::memory_order_relaxed);
-          break;
-      }
-    }
-  }
+  idle_filter_state_.IncreaseCallCount();
 }
 
 void ChannelData::DecreaseCallCount() {
-  const intptr_t previous_value =
-      call_count_.fetch_sub(1, std::memory_order_relaxed);
-  GRPC_IDLE_FILTER_LOG("call counter has decreased to %" PRIuPTR,
-                       previous_value - 1);
-  if (previous_value == 1) {
-    // This call is the one that makes the channel idle.
-    // last_idle_time_ does not need to be std::atomic<> because busy-loops in
-    // IncreaseCallCount(), DecreaseCallCount() and IdleTimerCallback() will
-    // prevent multiple threads from simultaneously accessing this variable.
-    last_idle_time_ = ExecCtx::Get()->Now();
-    ChannelState state = state_.load(std::memory_order_relaxed);
-    while (true) {
-      switch (state) {
-        // Timer has not been set. Set the timer and switch to TIMER_PENDING
-        case CALLS_ACTIVE:
-          // Release store here to make other threads see the updated value of
-          // last_idle_time_.
-          StartIdleTimer();
-          state_.store(TIMER_PENDING, std::memory_order_release);
-          return;
-        // Timer has been set. Switch to
-        // TIMER_PENDING_CALLS_SEEN_SINCE_TIMER_START
-        case TIMER_PENDING_CALLS_ACTIVE:
-          // At this point, the state may have been switched to CALLS_ACTIVE by
-          // the idle timer callback. Therefore, use CAS operation to change the
-          // state atomically.
-          // Release store here to make the idle timer callback see the updated
-          // value of last_idle_time_ to properly reset the idle timer.
-          if (state_.compare_exchange_weak(
-                  state, TIMER_PENDING_CALLS_SEEN_SINCE_TIMER_START,
-                  std::memory_order_release, std::memory_order_relaxed)) {
-            return;
-          }
-          break;
-        default:
-          // The state has not been switched to desired value yet, try again.
-          state = state_.load(std::memory_order_relaxed);
-          break;
-      }
-    }
+  if (idle_filter_state_.DecreaseCallCount()) {
+    // If there are no more calls in progress, start the idle timer.
+    StartIdleTimer();
   }
 }
 
@@ -315,44 +171,10 @@ void ChannelData::IdleTimerCallback(void* arg, grpc_error_handle error) {
     GRPC_CHANNEL_STACK_UNREF(chand->channel_stack_, "max idle timer callback");
     return;
   }
-  bool finished = false;
-  ChannelState state = chand->state_.load(std::memory_order_relaxed);
-  while (!finished) {
-    switch (state) {
-      case TIMER_PENDING:
-        // Change the state to PROCESSING to block IncreaseCallCout() until the
-        // EnterIdle() operation finishes, preventing mistakenly entering IDLE
-        // when active RPC exists.
-        finished = chand->state_.compare_exchange_weak(
-            state, PROCESSING, std::memory_order_acquire,
-            std::memory_order_relaxed);
-        if (finished) {
-          chand->EnterIdle();
-          chand->state_.store(IDLE, std::memory_order_relaxed);
-        }
-        break;
-      case TIMER_PENDING_CALLS_ACTIVE:
-        finished = chand->state_.compare_exchange_weak(
-            state, CALLS_ACTIVE, std::memory_order_relaxed,
-            std::memory_order_relaxed);
-        break;
-      case TIMER_PENDING_CALLS_SEEN_SINCE_TIMER_START:
-        // Change the state to PROCESSING to block IncreaseCallCount() until the
-        // StartIdleTimer() operation finishes, preventing mistakenly restarting
-        // the timer after grpc_timer_cancel() when shutdown.
-        finished = chand->state_.compare_exchange_weak(
-            state, PROCESSING, std::memory_order_acquire,
-            std::memory_order_relaxed);
-        if (finished) {
-          chand->StartIdleTimer();
-          chand->state_.store(TIMER_PENDING, std::memory_order_relaxed);
-        }
-        break;
-      default:
-        // The state has not been switched to desired value yet, try again.
-        state = chand->state_.load(std::memory_order_relaxed);
-        break;
-    }
+  if (chand->idle_filter_state_.CheckTimer()) {
+    chand->StartIdleTimer();
+  } else {
+    chand->EnterIdle();
   }
   GRPC_IDLE_FILTER_LOG("timer finishes");
   GRPC_CHANNEL_STACK_UNREF(chand->channel_stack_, "max idle timer callback");
@@ -368,7 +190,7 @@ void ChannelData::StartIdleTimer() {
   GRPC_IDLE_FILTER_LOG("timer has started");
   // Hold a ref to the channel stack for the timer callback.
   GRPC_CHANNEL_STACK_REF(channel_stack_, "max idle timer callback");
-  grpc_timer_init(&idle_timer_, last_idle_time_ + client_idle_timeout_,
+  grpc_timer_init(&idle_timer_, ExecCtx::Get()->Now() + client_idle_timeout_,
                   &idle_timer_callback_);
 }
 
@@ -422,26 +244,21 @@ const grpc_channel_filter grpc_client_idle_filter = {
     grpc_channel_next_get_info,
     "client_idle"};
 
-static bool MaybeAddClientIdleFilter(grpc_channel_stack_builder* builder,
-                                     void* /*arg*/) {
-  const grpc_channel_args* channel_args =
-      grpc_channel_stack_builder_get_channel_arguments(builder);
-  if (!grpc_channel_args_want_minimal_stack(channel_args) &&
-      GetClientIdleTimeout(channel_args) != INT_MAX) {
-    return grpc_channel_stack_builder_prepend_filter(
-        builder, &grpc_client_idle_filter, nullptr, nullptr);
-  } else {
-    return true;
-  }
-}
-
 }  // namespace
-}  // namespace grpc_core
 
-void grpc_client_idle_filter_init(void) {
-  grpc_channel_init_register_stage(
+void RegisterClientIdleFilter(CoreConfiguration::Builder* builder) {
+  builder->channel_init()->RegisterStage(
       GRPC_CLIENT_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
-      grpc_core::MaybeAddClientIdleFilter, nullptr);
+      [](grpc_channel_stack_builder* builder) {
+        const grpc_channel_args* channel_args =
+            grpc_channel_stack_builder_get_channel_arguments(builder);
+        if (!grpc_channel_args_want_minimal_stack(channel_args) &&
+            GetClientIdleTimeout(channel_args) != INT_MAX) {
+          return grpc_channel_stack_builder_prepend_filter(
+              builder, &grpc_client_idle_filter, nullptr, nullptr);
+        } else {
+          return true;
+        }
+      });
 }
-
-void grpc_client_idle_filter_shutdown(void) {}
+}  // namespace grpc_core
diff --git a/src/core/ext/filters/client_idle/idle_filter_state.cc b/src/core/ext/filters/client_idle/idle_filter_state.cc
new file mode 100644 (file)
index 0000000..cd06897
--- /dev/null
@@ -0,0 +1,96 @@
+// 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 <grpc/support/port_platform.h>
+
+#include "src/core/ext/filters/client_idle/idle_filter_state.h"
+
+#include <assert.h>
+
+namespace grpc_core {
+
+IdleFilterState::IdleFilterState(bool start_timer)
+    : state_(start_timer ? kTimerStarted : 0) {}
+
+void IdleFilterState::IncreaseCallCount() {
+  uintptr_t state = state_.load(std::memory_order_relaxed);
+  uintptr_t new_state;
+  do {
+    // Increment the counter, and flag that there's been activity.
+    new_state = state;
+    new_state |= kCallsStartedSinceLastTimerCheck;
+    new_state += kCallIncrement;
+  } while (!state_.compare_exchange_weak(
+      state, new_state, std::memory_order_acq_rel, std::memory_order_relaxed));
+}
+
+bool IdleFilterState::DecreaseCallCount() {
+  uintptr_t state = state_.load(std::memory_order_relaxed);
+  uintptr_t new_state;
+  bool start_timer;
+  do {
+    start_timer = false;
+    new_state = state;
+    // Decrement call count (and assert there's at least one call outstanding!)
+    assert(new_state >= kCallIncrement);
+    new_state -= kCallIncrement;
+    // If that decrement reaches a call count of zero and we have not started a
+    // timer
+    if ((new_state >> kCallsInProgressShift) == 0 &&
+        (new_state & kTimerStarted) == 0) {
+      // Flag that we will start a timer, and mark it started so nobody else
+      // does.
+      start_timer = true;
+      new_state |= kTimerStarted;
+      new_state &= ~kCallsInProgressShift;
+    }
+  } while (!state_.compare_exchange_weak(
+      state, new_state, std::memory_order_acq_rel, std::memory_order_relaxed));
+  return start_timer;
+}
+
+bool IdleFilterState::CheckTimer() {
+  uintptr_t state = state_.load(std::memory_order_relaxed);
+  uintptr_t new_state;
+  bool start_timer;
+  do {
+    if ((state >> kCallsInProgressShift) != 0) {
+      // Still calls in progress: nothing needs updating, just return
+      // and keep the timer going!
+      return true;
+    }
+    new_state = state;
+    bool is_active = false;
+    if (new_state & kCallsStartedSinceLastTimerCheck) {
+      // If any calls started since the last time we checked, then consider the
+      // channel still active and try again.
+      is_active = true;
+      new_state &= ~kCallsStartedSinceLastTimerCheck;
+    }
+    if (is_active) {
+      // If we are still active, we should signal that the timer should start
+      // again.
+      start_timer = true;
+    } else {
+      // Otherwise, we should not start the timer again, and we should signal
+      // that in the updated state.
+      start_timer = false;
+      new_state &= ~kTimerStarted;
+    }
+  } while (!state_.compare_exchange_weak(
+      state, new_state, std::memory_order_acq_rel, std::memory_order_relaxed));
+  return start_timer;
+}
+
+}  // namespace grpc_core
diff --git a/src/core/ext/filters/client_idle/idle_filter_state.h b/src/core/ext/filters/client_idle/idle_filter_state.h
new file mode 100644 (file)
index 0000000..ef236b1
--- /dev/null
@@ -0,0 +1,66 @@
+// 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.
+
+#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_IDLE_IDLE_FILTER_STATE_H
+#define GRPC_CORE_EXT_FILTERS_CLIENT_IDLE_IDLE_FILTER_STATE_H
+
+#include <grpc/support/port_platform.h>
+
+#include <atomic>
+
+namespace grpc_core {
+
+// State machine for the idle filter.
+// Keeps track of how many calls are in progress, whether there is a timer
+// started, and whether we've seen calls since the previous timer fired.
+class IdleFilterState {
+ public:
+  explicit IdleFilterState(bool start_timer);
+  ~IdleFilterState() = default;
+
+  IdleFilterState(const IdleFilterState&);
+  IdleFilterState& operator=(const IdleFilterState&);
+
+  // Increment the number of calls in progress.
+  void IncreaseCallCount();
+
+  // Decrement the number of calls in progress.
+  // Return true if we reached idle with no timer started.
+  GRPC_MUST_USE_RESULT bool DecreaseCallCount();
+
+  // Check if there's been any activity since the last timer check.
+  // If there was, reset the activity flag and return true to indicated that
+  // a new timer should be started.
+  // If there was not, reset the timer flag and return false - in this case
+  // we know that the channel is idle and has been for one full cycle.
+  GRPC_MUST_USE_RESULT bool CheckTimer();
+
+ private:
+  // Bit in state_ indicating that the timer has been started.
+  static constexpr uintptr_t kTimerStarted = 1;
+  // Bit in state_ indicating that we've seen a call start or stop since the
+  // last timer.
+  static constexpr uintptr_t kCallsStartedSinceLastTimerCheck = 2;
+  // How much should we shift to get the number of calls in progress.
+  static constexpr uintptr_t kCallsInProgressShift = 2;
+  // How much to increment/decrement the state_ when a call is started/stopped.
+  // Ensures we don't clobber the preceding bits.
+  static constexpr uintptr_t kCallIncrement = uintptr_t(1)
+                                              << kCallsInProgressShift;
+  std::atomic<uintptr_t> state_;
+};
+
+}  // namespace grpc_core
+
+#endif  // GRPC_CORE_EXT_FILTERS_CLIENT_IDLE_IDLE_FILTER_STATE_H
index 8944f5d..9bdd51f 100644 (file)
 #include <grpc/support/time.h>
 
 #include "src/core/lib/channel/channel_stack_builder.h"
+#include "src/core/lib/config/core_configuration.h"
 #include "src/core/lib/gprpp/memory.h"
 #include "src/core/lib/iomgr/timer.h"
 #include "src/core/lib/slice/slice_internal.h"
-#include "src/core/lib/surface/channel_init.h"
 
 namespace grpc_core {
 
@@ -114,9 +114,7 @@ class TimerState {
 // synchronized.
 static void start_timer_if_needed(grpc_call_element* elem,
                                   grpc_millis deadline) {
-  if (deadline == GRPC_MILLIS_INF_FUTURE) {
-    return;
-  }
+  if (deadline == GRPC_MILLIS_INF_FUTURE) return;
   grpc_deadline_state* deadline_state =
       static_cast<grpc_deadline_state*>(elem->call_data);
   GPR_ASSERT(deadline_state->timer_state == nullptr);
@@ -295,7 +293,9 @@ static void deadline_client_start_transport_stream_op_batch(
 static void recv_initial_metadata_ready(void* arg, grpc_error_handle error) {
   grpc_call_element* elem = static_cast<grpc_call_element*>(arg);
   server_call_data* calld = static_cast<server_call_data*>(elem->call_data);
-  start_timer_if_needed(elem, calld->recv_initial_metadata->deadline);
+  start_timer_if_needed(
+      elem, calld->recv_initial_metadata->get(grpc_core::GrpcTimeoutMetadata())
+                .value_or(GRPC_MILLIS_INF_FUTURE));
   // Invoke the next callback.
   grpc_core::Closure::Run(DEBUG_LOCATION,
                           calld->next_recv_initial_metadata_ready,
@@ -370,25 +370,22 @@ bool grpc_deadline_checking_enabled(const grpc_channel_args* channel_args) {
       !grpc_channel_args_want_minimal_stack(channel_args));
 }
 
-static bool maybe_add_deadline_filter(grpc_channel_stack_builder* builder,
-                                      void* arg) {
-  return grpc_deadline_checking_enabled(
-             grpc_channel_stack_builder_get_channel_arguments(builder))
-             ? grpc_channel_stack_builder_prepend_filter(
-                   builder, static_cast<const grpc_channel_filter*>(arg),
-                   nullptr, nullptr)
-             : true;
-}
-
-void grpc_deadline_filter_init(void) {
-  grpc_channel_init_register_stage(
-      GRPC_CLIENT_DIRECT_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
-      maybe_add_deadline_filter,
-      const_cast<grpc_channel_filter*>(&grpc_client_deadline_filter));
-  grpc_channel_init_register_stage(
-      GRPC_SERVER_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
-      maybe_add_deadline_filter,
-      const_cast<grpc_channel_filter*>(&grpc_server_deadline_filter));
+namespace grpc_core {
+void RegisterDeadlineFilter(CoreConfiguration::Builder* builder) {
+  auto register_filter = [builder](grpc_channel_stack_type type,
+                                   const grpc_channel_filter* filter) {
+    builder->channel_init()->RegisterStage(
+        type, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
+        [filter](grpc_channel_stack_builder* builder) {
+          if (grpc_deadline_checking_enabled(
+                  grpc_channel_stack_builder_get_channel_arguments(builder))) {
+            return grpc_channel_stack_builder_prepend_filter(builder, filter,
+                                                             nullptr, nullptr);
+          }
+          return true;
+        });
+  };
+  register_filter(GRPC_CLIENT_DIRECT_CHANNEL, &grpc_client_deadline_filter);
+  register_filter(GRPC_SERVER_CHANNEL, &grpc_server_deadline_filter);
 }
-
-void grpc_deadline_filter_shutdown(void) {}
+}  // namespace grpc_core
index f4d4148..2a9a9be 100644 (file)
@@ -25,9 +25,8 @@
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 
-#include "src/core/ext/filters/client_channel/service_config.h"
-#include "src/core/ext/filters/client_channel/service_config_call_data.h"
 #include "src/core/ext/filters/fault_injection/service_config_parser.h"
+#include "src/core/ext/service_config/service_config_call_data.h"
 #include "src/core/lib/channel/channel_stack.h"
 #include "src/core/lib/channel/status_util.h"
 #include "src/core/lib/gprpp/sync.h"
@@ -46,27 +45,27 @@ static_assert(
     std::is_trivially_destructible<std::atomic<uint32_t>>::value,
     "the active fault counter needs to have a trivially destructible type");
 
-inline int GetLinkedMetadatumValueInt(grpc_linked_mdelem* md) {
+inline int GetMetadatumValueInt(grpc_mdelem md) {
   int res;
-  if (absl::SimpleAtoi(StringViewFromSlice(GRPC_MDVALUE(md->md)), &res)) {
+  if (absl::SimpleAtoi(StringViewFromSlice(GRPC_MDVALUE(md)), &res)) {
     return res;
   } else {
     return -1;
   }
 }
 
-inline uint32_t GetLinkedMetadatumValueUnsignedInt(grpc_linked_mdelem* md) {
+inline uint32_t GetMetadatumValueUnsignedInt(grpc_mdelem md) {
   uint32_t res;
-  if (absl::SimpleAtoi(StringViewFromSlice(GRPC_MDVALUE(md->md)), &res)) {
+  if (absl::SimpleAtoi(StringViewFromSlice(GRPC_MDVALUE(md)), &res)) {
     return res;
   } else {
     return -1;
   }
 }
 
-inline int64_t GetLinkedMetadatumValueInt64(grpc_linked_mdelem* md) {
+inline int64_t GetMetadatumValueInt64(grpc_mdelem md) {
   int64_t res;
-  if (absl::SimpleAtoi(StringViewFromSlice(GRPC_MDVALUE(md->md)), &res)) {
+  if (absl::SimpleAtoi(StringViewFromSlice(GRPC_MDVALUE(md)), &res)) {
     return res;
   } else {
     return -1;
@@ -347,9 +346,8 @@ void CallData::DecideWhetherToInjectFaults(
                 *fi_policy_);
       }
     };
-    for (grpc_linked_mdelem* md = initial_metadata->list.head; md != nullptr;
-         md = md->next) {
-      absl::string_view key = StringViewFromSlice(GRPC_MDKEY(md->md));
+    initial_metadata->ForEach([&](grpc_mdelem md) {
+      absl::string_view key = StringViewFromSlice(GRPC_MDKEY(md));
       // Only perform string comparison if:
       //   1. Needs to check this header;
       //   2. The value is not been filled before.
@@ -358,31 +356,31 @@ void CallData::DecideWhetherToInjectFaults(
            copied_policy->abort_code == GRPC_STATUS_OK) &&
           key == fi_policy_->abort_code_header) {
         maybe_copy_policy_func();
-        grpc_status_code_from_int(GetLinkedMetadatumValueInt(md),
+        grpc_status_code_from_int(GetMetadatumValueInt(md),
                                   &copied_policy->abort_code);
       }
       if (!fi_policy_->abort_percentage_header.empty() &&
           key == fi_policy_->abort_percentage_header) {
         maybe_copy_policy_func();
         copied_policy->abort_percentage_numerator =
-            GPR_MIN(GetLinkedMetadatumValueUnsignedInt(md),
-                    fi_policy_->abort_percentage_numerator);
+            std::min(GetMetadatumValueUnsignedInt(md),
+                     fi_policy_->abort_percentage_numerator);
       }
       if (!fi_policy_->delay_header.empty() &&
           (copied_policy == nullptr || copied_policy->delay == 0) &&
           key == fi_policy_->delay_header) {
         maybe_copy_policy_func();
         copied_policy->delay = static_cast<grpc_millis>(
-            GPR_MAX(GetLinkedMetadatumValueInt64(md), 0));
+            std::max(GetMetadatumValueInt64(md), int64_t(0)));
       }
       if (!fi_policy_->delay_percentage_header.empty() &&
           key == fi_policy_->delay_percentage_header) {
         maybe_copy_policy_func();
         copied_policy->delay_percentage_numerator =
-            GPR_MIN(GetLinkedMetadatumValueUnsignedInt(md),
-                    fi_policy_->delay_percentage_numerator);
+            std::min(GetMetadatumValueUnsignedInt(md),
+                     fi_policy_->delay_percentage_numerator);
       }
-    }
+    });
     if (copied_policy != nullptr) fi_policy_ = copied_policy;
   }
   // Roll the dice
@@ -456,8 +454,10 @@ void CallData::ResumeBatch(void* arg, grpc_error_handle error) {
   // Abort if needed.
   error = calld->MaybeAbort();
   if (error != GRPC_ERROR_NONE) {
+    calld->abort_error_ = error;
     grpc_transport_stream_op_batch_finish_with_failure(
-        calld->delayed_batch_, error, calld->call_combiner_);
+        calld->delayed_batch_, GRPC_ERROR_REF(calld->abort_error_),
+        calld->call_combiner_);
     return;
   }
   // Chain to the next filter.
index bbbff40..a0c8b41 100644 (file)
@@ -23,7 +23,6 @@
 #include "absl/strings/str_cat.h"
 #include "absl/strings/string_view.h"
 
-#include "src/core/ext/filters/client_channel/service_config.h"
 #include "src/core/ext/filters/fault_injection/fault_injection_filter.h"
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/channel/status_util.h"
index a885539..abf9165 100644 (file)
@@ -21,7 +21,7 @@
 
 #include <vector>
 
-#include "src/core/ext/filters/client_channel/service_config.h"
+#include "src/core/ext/service_config/service_config_parser.h"
 #include "src/core/lib/iomgr/exec_ctx.h"
 
 namespace grpc_core {
index a671d31..0804f90 100644 (file)
@@ -78,8 +78,6 @@ struct call_data {
   // State for handling send_initial_metadata ops.
   grpc_linked_mdelem method;
   grpc_linked_mdelem scheme;
-  grpc_linked_mdelem authority;
-  grpc_linked_mdelem te_trailers;
   grpc_linked_mdelem content_type;
   grpc_linked_mdelem user_agent;
   // State for handling recv_initial_metadata ops.
@@ -113,18 +111,18 @@ struct channel_data {
 
 static grpc_error_handle client_filter_incoming_metadata(
     grpc_metadata_batch* b) {
-  if (b->idx.named.status != nullptr) {
+  if (b->legacy_index()->named.status != nullptr) {
     /* If both gRPC status and HTTP status are provided in the response, we
      * should prefer the gRPC status code, as mentioned in
      * https://github.com/grpc/grpc/blob/master/doc/http-grpc-status-mapping.md.
      */
-    if (b->idx.named.grpc_status != nullptr ||
-        grpc_mdelem_static_value_eq(b->idx.named.status->md,
+    if (b->legacy_index()->named.grpc_status != nullptr ||
+        grpc_mdelem_static_value_eq(b->legacy_index()->named.status->md,
                                     GRPC_MDELEM_STATUS_200)) {
-      grpc_metadata_batch_remove(b, GRPC_BATCH_STATUS);
+      b->Remove(GRPC_BATCH_STATUS);
     } else {
-      char* val = grpc_dump_slice(GRPC_MDVALUE(b->idx.named.status->md),
-                                  GPR_DUMP_ASCII);
+      char* val = grpc_dump_slice(
+          GRPC_MDVALUE(b->legacy_index()->named.status->md), GPR_DUMP_ASCII);
       std::string msg =
           absl::StrCat("Received http2 header with status: ", val);
       grpc_error_handle e = grpc_error_set_str(
@@ -132,39 +130,42 @@ static grpc_error_handle client_filter_incoming_metadata(
               grpc_error_set_str(
                   GRPC_ERROR_CREATE_FROM_STATIC_STRING(
                       "Received http2 :status header with non-200 OK status"),
-                  GRPC_ERROR_STR_VALUE, grpc_slice_from_copied_string(val)),
+                  GRPC_ERROR_STR_VALUE, val),
               GRPC_ERROR_INT_GRPC_STATUS,
               grpc_http2_status_to_grpc_status(atoi(val))),
-          GRPC_ERROR_STR_GRPC_MESSAGE,
-          grpc_slice_from_cpp_string(std::move(msg)));
+          GRPC_ERROR_STR_GRPC_MESSAGE, msg);
       gpr_free(val);
       return e;
     }
   }
 
-  if (b->idx.named.grpc_message != nullptr) {
+  if (b->legacy_index()->named.grpc_message != nullptr) {
     grpc_slice pct_decoded_msg = grpc_core::PermissivePercentDecodeSlice(
-        GRPC_MDVALUE(b->idx.named.grpc_message->md));
-    if (grpc_slice_is_equivalent(pct_decoded_msg,
-                                 GRPC_MDVALUE(b->idx.named.grpc_message->md))) {
+        GRPC_MDVALUE(b->legacy_index()->named.grpc_message->md));
+    if (grpc_slice_is_equivalent(
+            pct_decoded_msg,
+            GRPC_MDVALUE(b->legacy_index()->named.grpc_message->md))) {
       grpc_slice_unref_internal(pct_decoded_msg);
     } else {
-      grpc_metadata_batch_set_value(b->idx.named.grpc_message, pct_decoded_msg);
+      grpc_metadata_batch_set_value(b->legacy_index()->named.grpc_message,
+                                    pct_decoded_msg);
     }
   }
 
-  if (b->idx.named.content_type != nullptr) {
+  if (b->legacy_index()->named.content_type != nullptr) {
     if (!grpc_mdelem_static_value_eq(
-            b->idx.named.content_type->md,
+            b->legacy_index()->named.content_type->md,
             GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC)) {
-      if (grpc_slice_buf_start_eq(GRPC_MDVALUE(b->idx.named.content_type->md),
-                                  EXPECTED_CONTENT_TYPE,
-                                  EXPECTED_CONTENT_TYPE_LENGTH) &&
+      if (grpc_slice_buf_start_eq(
+              GRPC_MDVALUE(b->legacy_index()->named.content_type->md),
+              EXPECTED_CONTENT_TYPE, EXPECTED_CONTENT_TYPE_LENGTH) &&
           (GRPC_SLICE_START_PTR(GRPC_MDVALUE(
-               b->idx.named.content_type->md))[EXPECTED_CONTENT_TYPE_LENGTH] ==
+               b->legacy_index()
+                   ->named.content_type->md))[EXPECTED_CONTENT_TYPE_LENGTH] ==
                '+' ||
            GRPC_SLICE_START_PTR(GRPC_MDVALUE(
-               b->idx.named.content_type->md))[EXPECTED_CONTENT_TYPE_LENGTH] ==
+               b->legacy_index()
+                   ->named.content_type->md))[EXPECTED_CONTENT_TYPE_LENGTH] ==
                ';')) {
         /* Although the C implementation doesn't (currently) generate them,
            any custom +-suffix is explicitly valid. */
@@ -174,13 +175,14 @@ static grpc_error_handle client_filter_incoming_metadata(
       } else {
         /* TODO(klempner): We're currently allowing this, but we shouldn't
            see it without a proxy so log for now. */
-        char* val = grpc_dump_slice(GRPC_MDVALUE(b->idx.named.content_type->md),
-                                    GPR_DUMP_ASCII);
+        char* val = grpc_dump_slice(
+            GRPC_MDVALUE(b->legacy_index()->named.content_type->md),
+            GPR_DUMP_ASCII);
         gpr_log(GPR_INFO, "Unexpected content-type '%s'", val);
         gpr_free(val);
       }
     }
-    grpc_metadata_batch_remove(b, GRPC_BATCH_CONTENT_TYPE);
+    b->Remove(GRPC_BATCH_CONTENT_TYPE);
   }
 
   return GRPC_ERROR_NONE;
@@ -194,7 +196,7 @@ static void recv_initial_metadata_ready(void* user_data,
     error = client_filter_incoming_metadata(calld->recv_initial_metadata);
     calld->recv_initial_metadata_error = GRPC_ERROR_REF(error);
   } else {
-    GRPC_ERROR_REF(error);
+    (void)GRPC_ERROR_REF(error);
   }
   grpc_closure* closure = calld->original_recv_initial_metadata_ready;
   calld->original_recv_initial_metadata_ready = nullptr;
@@ -221,7 +223,7 @@ static void recv_trailing_metadata_ready(void* user_data,
   if (error == GRPC_ERROR_NONE) {
     error = client_filter_incoming_metadata(calld->recv_trailing_metadata);
   } else {
-    GRPC_ERROR_REF(error);
+    (void)GRPC_ERROR_REF(error);
   }
   error = grpc_error_add_child(
       error, GRPC_ERROR_REF(calld->recv_initial_metadata_error));
@@ -317,7 +319,8 @@ static grpc_error_handle update_path_for_get(
   call_data* calld = static_cast<call_data*>(elem->call_data);
   grpc_slice path_slice =
       GRPC_MDVALUE(batch->payload->send_initial_metadata.send_initial_metadata
-                       ->idx.named.path->md);
+                       ->legacy_index()
+                       ->named.path->md);
   /* sum up individual component's lengths and allocate enough memory to
    * hold combined path+query */
   size_t estimated_len = GRPC_SLICE_LENGTH(path_slice);
@@ -341,24 +344,23 @@ static grpc_error_handle update_path_for_get(
                           true /* url_safe */, false /* multi_line */);
   gpr_free(payload_bytes);
   /* remove trailing unused memory and add trailing 0 to terminate string */
-  char* t = reinterpret_cast<char*> GRPC_SLICE_START_PTR(path_with_query_slice);
+  char* t =
+      reinterpret_cast<char*> GRPC_SLICE_START_PTR(path_with_query_slice) +
+      GRPC_SLICE_LENGTH(path_slice);
   /* safe to use strlen since base64_encode will always add '\0' */
-  path_with_query_slice =
-      grpc_slice_sub_no_ref(path_with_query_slice, 0, strlen(t));
+  path_with_query_slice = grpc_slice_sub_no_ref(
+      path_with_query_slice, 0, GRPC_SLICE_LENGTH(path_slice) + strlen(t));
   /* substitute previous path with the new path+query */
   grpc_mdelem mdelem_path_and_query =
       grpc_mdelem_from_slices(GRPC_MDSTR_PATH, path_with_query_slice);
   grpc_metadata_batch* b =
       batch->payload->send_initial_metadata.send_initial_metadata;
-  return grpc_metadata_batch_substitute(b, b->idx.named.path,
-                                        mdelem_path_and_query);
+  return b->Substitute(b->legacy_index()->named.path, mdelem_path_and_query);
 }
 
 static void remove_if_present(grpc_metadata_batch* batch,
                               grpc_metadata_batch_callouts_index idx) {
-  if (batch->idx.array[idx] != nullptr) {
-    grpc_metadata_batch_remove(batch, idx);
-  }
+  batch->Remove(idx);
 }
 
 static void http_client_start_transport_stream_op_batch(
@@ -442,9 +444,6 @@ static void http_client_start_transport_stream_op_batch(
         GRPC_BATCH_SCHEME);
     remove_if_present(
         batch->payload->send_initial_metadata.send_initial_metadata,
-        GRPC_BATCH_TE);
-    remove_if_present(
-        batch->payload->send_initial_metadata.send_initial_metadata,
         GRPC_BATCH_CONTENT_TYPE);
     remove_if_present(
         batch->payload->send_initial_metadata.send_initial_metadata,
@@ -460,10 +459,8 @@ static void http_client_start_transport_stream_op_batch(
         batch->payload->send_initial_metadata.send_initial_metadata,
         &calld->scheme, channeld->static_scheme, GRPC_BATCH_SCHEME);
     if (error != GRPC_ERROR_NONE) goto done;
-    error = grpc_metadata_batch_add_tail(
-        batch->payload->send_initial_metadata.send_initial_metadata,
-        &calld->te_trailers, GRPC_MDELEM_TE_TRAILERS, GRPC_BATCH_TE);
-    if (error != GRPC_ERROR_NONE) goto done;
+    batch->payload->send_initial_metadata.send_initial_metadata->Set(
+        grpc_core::TeMetadata(), grpc_core::TeMetadata::kTrailers);
     error = grpc_metadata_batch_add_tail(
         batch->payload->send_initial_metadata.send_initial_metadata,
         &calld->content_type, GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC,
index c1764ec..1915ebd 100644 (file)
 #include <grpc/support/string_util.h>
 
 #include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/channel/channel_stack_builder.h"
+#include "src/core/lib/config/core_configuration.h"
 #include "src/core/lib/gpr/string.h"
 #include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/slice/slice_string_helpers.h"
 #include "src/core/lib/surface/call.h"
-#include "src/core/lib/surface/channel_init.h"
 #include "src/core/lib/surface/channel_stack_type.h"
 #include "src/core/lib/transport/static_metadata.h"
 
@@ -56,8 +57,9 @@ void client_authority_start_transport_stream_op_batch(
   // Handle send_initial_metadata.
   // If the initial metadata doesn't already contain :authority, add it.
   if (batch->send_initial_metadata &&
-      batch->payload->send_initial_metadata.send_initial_metadata->idx.named
-              .authority == nullptr) {
+      batch->payload->send_initial_metadata.send_initial_metadata
+              ->legacy_index()
+              ->named.authority == nullptr) {
     grpc_error_handle error = grpc_metadata_batch_add_head(
         batch->payload->send_initial_metadata.send_initial_metadata,
         &calld->authority_storage,
@@ -131,8 +133,7 @@ const grpc_channel_filter grpc_client_authority_filter = {
     grpc_channel_next_get_info,
     "authority"};
 
-static bool add_client_authority_filter(grpc_channel_stack_builder* builder,
-                                        void* arg) {
+static bool add_client_authority_filter(grpc_channel_stack_builder* builder) {
   const grpc_channel_args* channel_args =
       grpc_channel_stack_builder_get_channel_arguments(builder);
   const grpc_arg* disable_client_authority_filter_arg = grpc_channel_args_find(
@@ -145,16 +146,14 @@ static bool add_client_authority_filter(grpc_channel_stack_builder* builder,
     }
   }
   return grpc_channel_stack_builder_prepend_filter(
-      builder, static_cast<const grpc_channel_filter*>(arg), nullptr, nullptr);
+      builder, &grpc_client_authority_filter, nullptr, nullptr);
 }
 
-void grpc_client_authority_filter_init(void) {
-  grpc_channel_init_register_stage(
-      GRPC_CLIENT_SUBCHANNEL, INT_MAX, add_client_authority_filter,
-      const_cast<grpc_channel_filter*>(&grpc_client_authority_filter));
-  grpc_channel_init_register_stage(
-      GRPC_CLIENT_DIRECT_CHANNEL, INT_MAX, add_client_authority_filter,
-      const_cast<grpc_channel_filter*>(&grpc_client_authority_filter));
+namespace grpc_core {
+void RegisterClientAuthorityFilter(CoreConfiguration::Builder* builder) {
+  builder->channel_init()->RegisterStage(GRPC_CLIENT_SUBCHANNEL, INT_MAX,
+                                         add_client_authority_filter);
+  builder->channel_init()->RegisterStage(GRPC_CLIENT_DIRECT_CHANNEL, INT_MAX,
+                                         add_client_authority_filter);
 }
-
-void grpc_client_authority_filter_shutdown(void) {}
+}  // namespace grpc_core
index d5577d5..dac830d 100644 (file)
 #include "src/core/ext/filters/http/message_compress/message_decompress_filter.h"
 #include "src/core/ext/filters/http/server/http_server_filter.h"
 #include "src/core/lib/channel/channel_stack_builder.h"
+#include "src/core/lib/config/core_configuration.h"
 #include "src/core/lib/surface/call.h"
-#include "src/core/lib/surface/channel_init.h"
 #include "src/core/lib/transport/transport_impl.h"
 
-struct optional_filter {
-  const grpc_channel_filter* filter;
-  const char* control_channel_arg;
-};
-
-static optional_filter compress_filter = {
-    &grpc_message_compress_filter, GRPC_ARG_ENABLE_PER_MESSAGE_COMPRESSION};
-
-static optional_filter decompress_filter = {
-    &grpc_core::MessageDecompressFilter,
-    GRPC_ARG_ENABLE_PER_MESSAGE_DECOMPRESSION};
-
 static bool is_building_http_like_transport(
     grpc_channel_stack_builder* builder) {
   grpc_transport* t = grpc_channel_stack_builder_get_transport(builder);
   return t != nullptr && strstr(t->vtable->name, "http");
 }
 
-template <bool enable_in_minimal_stack>
-static bool maybe_add_optional_filter(grpc_channel_stack_builder* builder,
-                                      void* arg) {
-  if (!is_building_http_like_transport(builder)) return true;
-  optional_filter* filtarg = static_cast<optional_filter*>(arg);
-  const grpc_channel_args* channel_args =
-      grpc_channel_stack_builder_get_channel_arguments(builder);
-  bool enable = grpc_channel_arg_get_bool(
-      grpc_channel_args_find(channel_args, filtarg->control_channel_arg),
-      enable_in_minimal_stack ||
-          !grpc_channel_args_want_minimal_stack(channel_args));
-  return enable ? grpc_channel_stack_builder_prepend_filter(
-                      builder, filtarg->filter, nullptr, nullptr)
-                : true;
-}
-
-static bool maybe_add_required_filter(grpc_channel_stack_builder* builder,
-                                      void* arg) {
-  return is_building_http_like_transport(builder)
-             ? grpc_channel_stack_builder_prepend_filter(
-                   builder, static_cast<const grpc_channel_filter*>(arg),
-                   nullptr, nullptr)
-             : true;
-}
-
-void grpc_http_filters_init(void) {
-  grpc_channel_init_register_stage(
-      GRPC_CLIENT_SUBCHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
-      maybe_add_optional_filter<false>, &compress_filter);
-  grpc_channel_init_register_stage(
-      GRPC_CLIENT_DIRECT_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
-      maybe_add_optional_filter<false>, &compress_filter);
-  grpc_channel_init_register_stage(
-      GRPC_SERVER_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
-      maybe_add_optional_filter<false>, &compress_filter);
-  grpc_channel_init_register_stage(
-      GRPC_CLIENT_SUBCHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
-      maybe_add_optional_filter<true>, &decompress_filter);
-  grpc_channel_init_register_stage(
-      GRPC_CLIENT_DIRECT_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
-      maybe_add_optional_filter<true>, &decompress_filter);
-  grpc_channel_init_register_stage(
-      GRPC_SERVER_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
-      maybe_add_optional_filter<true>, &decompress_filter);
-  grpc_channel_init_register_stage(
-      GRPC_CLIENT_SUBCHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
-      maybe_add_required_filter,
-      const_cast<grpc_channel_filter*>(&grpc_http_client_filter));
-  grpc_channel_init_register_stage(
-      GRPC_CLIENT_DIRECT_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
-      maybe_add_required_filter,
-      const_cast<grpc_channel_filter*>(&grpc_http_client_filter));
-  grpc_channel_init_register_stage(
-      GRPC_SERVER_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
-      maybe_add_required_filter,
-      const_cast<grpc_channel_filter*>(&grpc_http_server_filter));
+namespace grpc_core {
+void RegisterHttpFilters(CoreConfiguration::Builder* builder) {
+  auto optional = [builder](grpc_channel_stack_type channel_type,
+                            bool enable_in_minimal_stack,
+                            const char* control_channel_arg,
+                            const grpc_channel_filter* filter) {
+    builder->channel_init()->RegisterStage(
+        channel_type, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
+        [enable_in_minimal_stack, control_channel_arg,
+         filter](grpc_channel_stack_builder* builder) {
+          if (!is_building_http_like_transport(builder)) return true;
+          const grpc_channel_args* channel_args =
+              grpc_channel_stack_builder_get_channel_arguments(builder);
+          bool enable = grpc_channel_arg_get_bool(
+              grpc_channel_args_find(channel_args, control_channel_arg),
+              enable_in_minimal_stack ||
+                  !grpc_channel_args_want_minimal_stack(channel_args));
+          if (!enable) return true;
+          return grpc_channel_stack_builder_prepend_filter(builder, filter,
+                                                           nullptr, nullptr);
+        });
+  };
+  auto required = [builder](grpc_channel_stack_type channel_type,
+                            const grpc_channel_filter* filter) {
+    builder->channel_init()->RegisterStage(
+        channel_type, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
+        [filter](grpc_channel_stack_builder* builder) {
+          if (!is_building_http_like_transport(builder)) return true;
+          return grpc_channel_stack_builder_prepend_filter(builder, filter,
+                                                           nullptr, nullptr);
+        });
+  };
+  optional(GRPC_CLIENT_SUBCHANNEL, false,
+           GRPC_ARG_ENABLE_PER_MESSAGE_COMPRESSION,
+           &grpc_message_compress_filter);
+  optional(GRPC_CLIENT_DIRECT_CHANNEL, false,
+           GRPC_ARG_ENABLE_PER_MESSAGE_COMPRESSION,
+           &grpc_message_compress_filter);
+  optional(GRPC_SERVER_CHANNEL, false, GRPC_ARG_ENABLE_PER_MESSAGE_COMPRESSION,
+           &grpc_message_compress_filter);
+  optional(GRPC_CLIENT_SUBCHANNEL, true,
+           GRPC_ARG_ENABLE_PER_MESSAGE_DECOMPRESSION,
+           &grpc_core::MessageDecompressFilter);
+  optional(GRPC_CLIENT_DIRECT_CHANNEL, true,
+           GRPC_ARG_ENABLE_PER_MESSAGE_DECOMPRESSION,
+           &grpc_core::MessageDecompressFilter);
+  optional(GRPC_SERVER_CHANNEL, true, GRPC_ARG_ENABLE_PER_MESSAGE_DECOMPRESSION,
+           &grpc_core::MessageDecompressFilter);
+  required(GRPC_CLIENT_SUBCHANNEL, &grpc_http_client_filter);
+  required(GRPC_CLIENT_DIRECT_CHANNEL, &grpc_http_client_filter);
+  required(GRPC_SERVER_CHANNEL, &grpc_http_server_filter);
 }
-
-void grpc_http_filters_shutdown(void) {}
+}  // namespace grpc_core
index 8359b1f..f7a4b88 100644 (file)
@@ -55,11 +55,14 @@ class ChannelData {
         grpc_channel_args_get_channel_default_compression_algorithm(
             args->channel_args);
     // Make sure the default is enabled.
-    if (!GPR_BITGET(enabled_compression_algorithms_bitset_,
-                    default_compression_algorithm_)) {
+    if (size_t(default_compression_algorithm_) >= 32 ||
+        !grpc_core::GetBit(enabled_compression_algorithms_bitset_,
+                           default_compression_algorithm_)) {
       const char* name;
-      GPR_ASSERT(grpc_compression_algorithm_name(default_compression_algorithm_,
-                                                 &name) == 1);
+      if (!grpc_compression_algorithm_name(default_compression_algorithm_,
+                                           &name)) {
+        name = "<unknown>";
+      }
       gpr_log(GPR_ERROR,
               "default compression algorithm %s not enabled: switching to none",
               name);
@@ -108,7 +111,8 @@ class CallData {
     ChannelData* channeld = static_cast<ChannelData*>(elem->channel_data);
     // The call's message compression algorithm is set to channel's default
     // setting. It can be overridden later by initial metadata.
-    if (GPR_LIKELY(GPR_BITGET(channeld->enabled_compression_algorithms_bitset(),
+    if (GPR_LIKELY(
+            grpc_core::GetBit(channeld->enabled_compression_algorithms_bitset(),
                               channeld->default_compression_algorithm()))) {
       message_compression_algorithm_ =
           grpc_compression_algorithm_to_message_compression_algorithm(
@@ -191,24 +195,25 @@ bool CallData::SkipMessageCompression() {
 // channel's default setting.
 grpc_compression_algorithm FindCompressionAlgorithm(
     grpc_metadata_batch* initial_metadata, ChannelData* channeld) {
-  if (initial_metadata->idx.named.grpc_internal_encoding_request == nullptr) {
+  if (initial_metadata->legacy_index()->named.grpc_internal_encoding_request ==
+      nullptr) {
     return channeld->default_compression_algorithm();
   }
   grpc_compression_algorithm compression_algorithm;
   // Parse the compression algorithm from the initial metadata.
-  grpc_mdelem md =
-      initial_metadata->idx.named.grpc_internal_encoding_request->md;
+  grpc_mdelem md = initial_metadata->legacy_index()
+                       ->named.grpc_internal_encoding_request->md;
   GPR_ASSERT(grpc_compression_algorithm_parse(GRPC_MDVALUE(md),
                                               &compression_algorithm));
   // Remove this metadata since it's an internal one (i.e., it won't be
   // transmitted out).
-  grpc_metadata_batch_remove(initial_metadata,
-                             GRPC_BATCH_GRPC_INTERNAL_ENCODING_REQUEST);
+  initial_metadata->Remove(GRPC_BATCH_GRPC_INTERNAL_ENCODING_REQUEST);
   // Check if that algorithm is enabled. Note that GRPC_COMPRESS_NONE is always
   // enabled.
   // TODO(juanlishen): Maybe use channel default or abort() if the algorithm
   // from the initial metadata is disabled.
-  if (GPR_LIKELY(GPR_BITGET(channeld->enabled_compression_algorithms_bitset(),
+  if (GPR_LIKELY(
+          grpc_core::GetBit(channeld->enabled_compression_algorithms_bitset(),
                             compression_algorithm))) {
     return compression_algorithm;
   }
@@ -272,7 +277,7 @@ grpc_error_handle CallData::ProcessSendInitialMetadata(
   if (error != GRPC_ERROR_NONE) return error;
   // Do not overwrite accept-encoding header if it already presents (e.g., added
   // by some proxy).
-  if (!initial_metadata->idx.named.accept_encoding) {
+  if (!initial_metadata->legacy_index()->named.accept_encoding) {
     error = grpc_metadata_batch_add_tail(
         initial_metadata, &accept_stream_encoding_storage_,
         GRPC_MDELEM_ACCEPT_STREAM_ENCODING_FOR_ALGORITHMS(
index 27718e2..b465350 100644 (file)
@@ -153,7 +153,7 @@ void CallData::OnRecvInitialMetadataReady(void* arg, grpc_error_handle error) {
   CallData* calld = static_cast<CallData*>(arg);
   if (error == GRPC_ERROR_NONE) {
     grpc_linked_mdelem* grpc_encoding =
-        calld->recv_initial_metadata_->idx.named.grpc_encoding;
+        calld->recv_initial_metadata_->legacy_index()->named.grpc_encoding;
     if (grpc_encoding != nullptr) {
       calld->algorithm_ = DecodeMessageCompressionAlgorithm(grpc_encoding->md);
     }
index e599674..0a2108d 100644 (file)
@@ -104,15 +104,17 @@ struct channel_data {
 }  // namespace
 
 static grpc_error_handle hs_filter_outgoing_metadata(grpc_metadata_batch* b) {
-  if (b->idx.named.grpc_message != nullptr) {
+  if (b->legacy_index()->named.grpc_message != nullptr) {
     grpc_slice pct_encoded_msg = grpc_core::PercentEncodeSlice(
-        GRPC_MDVALUE(b->idx.named.grpc_message->md),
+        GRPC_MDVALUE(b->legacy_index()->named.grpc_message->md),
         grpc_core::PercentEncodingType::Compatible);
-    if (grpc_slice_is_equivalent(pct_encoded_msg,
-                                 GRPC_MDVALUE(b->idx.named.grpc_message->md))) {
+    if (grpc_slice_is_equivalent(
+            pct_encoded_msg,
+            GRPC_MDVALUE(b->legacy_index()->named.grpc_message->md))) {
       grpc_slice_unref_internal(pct_encoded_msg);
     } else {
-      grpc_metadata_batch_set_value(b->idx.named.grpc_message, pct_encoded_msg);
+      grpc_metadata_batch_set_value(b->legacy_index()->named.grpc_message,
+                                    pct_encoded_msg);
     }
   }
   return GRPC_ERROR_NONE;
@@ -159,18 +161,19 @@ static grpc_error_handle hs_filter_incoming_metadata(grpc_call_element* elem,
   grpc_error_handle error = GRPC_ERROR_NONE;
   static const char* error_name = "Failed processing incoming headers";
 
-  if (b->idx.named.method != nullptr) {
-    if (md_strict_equal(b->idx.named.method->md, GRPC_MDELEM_METHOD_POST)) {
+  if (b->legacy_index()->named.method != nullptr) {
+    if (md_strict_equal(b->legacy_index()->named.method->md,
+                        GRPC_MDELEM_METHOD_POST)) {
       *calld->recv_initial_metadata_flags &=
           ~(GRPC_INITIAL_METADATA_CACHEABLE_REQUEST |
             GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST);
-    } else if (md_strict_equal(b->idx.named.method->md,
+    } else if (md_strict_equal(b->legacy_index()->named.method->md,
                                GRPC_MDELEM_METHOD_PUT)) {
       *calld->recv_initial_metadata_flags &=
           ~GRPC_INITIAL_METADATA_CACHEABLE_REQUEST;
       *calld->recv_initial_metadata_flags |=
           GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST;
-    } else if (md_strict_equal(b->idx.named.method->md,
+    } else if (md_strict_equal(b->legacy_index()->named.method->md,
                                GRPC_MDELEM_METHOD_GET)) {
       *calld->recv_initial_metadata_flags |=
           GRPC_INITIAL_METADATA_CACHEABLE_REQUEST;
@@ -180,64 +183,63 @@ static grpc_error_handle hs_filter_incoming_metadata(grpc_call_element* elem,
       hs_add_error(error_name, &error,
                    grpc_attach_md_to_error(
                        GRPC_ERROR_CREATE_FROM_STATIC_STRING("Bad header"),
-                       b->idx.named.method->md));
+                       b->legacy_index()->named.method->md));
     }
-    grpc_metadata_batch_remove(b, GRPC_BATCH_METHOD);
+    b->Remove(GRPC_BATCH_METHOD);
   } else {
-    hs_add_error(
-        error_name, &error,
-        grpc_error_set_str(
-            GRPC_ERROR_CREATE_FROM_STATIC_STRING("Missing header"),
-            GRPC_ERROR_STR_KEY, grpc_slice_from_static_string(":method")));
+    hs_add_error(error_name, &error,
+                 grpc_error_set_str(
+                     GRPC_ERROR_CREATE_FROM_STATIC_STRING("Missing header"),
+                     GRPC_ERROR_STR_KEY, ":method"));
   }
 
-  if (b->idx.named.te != nullptr) {
-    if (!grpc_mdelem_static_value_eq(b->idx.named.te->md,
-                                     GRPC_MDELEM_TE_TRAILERS)) {
-      hs_add_error(error_name, &error,
-                   grpc_attach_md_to_error(
-                       GRPC_ERROR_CREATE_FROM_STATIC_STRING("Bad header"),
-                       b->idx.named.te->md));
-    }
-    grpc_metadata_batch_remove(b, GRPC_BATCH_TE);
-  } else {
+  auto te = b->Take(grpc_core::TeMetadata());
+  if (te == grpc_core::TeMetadata::kTrailers) {
+    // Do nothing, ok.
+  } else if (!te.has_value()) {
     hs_add_error(error_name, &error,
                  grpc_error_set_str(
                      GRPC_ERROR_CREATE_FROM_STATIC_STRING("Missing header"),
-                     GRPC_ERROR_STR_KEY, grpc_slice_from_static_string("te")));
+                     GRPC_ERROR_STR_KEY, "te"));
+  } else {
+    hs_add_error(error_name, &error,
+                 GRPC_ERROR_CREATE_FROM_STATIC_STRING("Bad te header"));
   }
 
-  if (b->idx.named.scheme != nullptr) {
-    if (!md_strict_equal(b->idx.named.scheme->md, GRPC_MDELEM_SCHEME_HTTP) &&
-        !md_strict_equal(b->idx.named.scheme->md, GRPC_MDELEM_SCHEME_HTTPS) &&
-        !grpc_mdelem_static_value_eq(b->idx.named.scheme->md,
+  if (b->legacy_index()->named.scheme != nullptr) {
+    if (!md_strict_equal(b->legacy_index()->named.scheme->md,
+                         GRPC_MDELEM_SCHEME_HTTP) &&
+        !md_strict_equal(b->legacy_index()->named.scheme->md,
+                         GRPC_MDELEM_SCHEME_HTTPS) &&
+        !grpc_mdelem_static_value_eq(b->legacy_index()->named.scheme->md,
                                      GRPC_MDELEM_SCHEME_GRPC)) {
       hs_add_error(error_name, &error,
                    grpc_attach_md_to_error(
                        GRPC_ERROR_CREATE_FROM_STATIC_STRING("Bad header"),
-                       b->idx.named.scheme->md));
+                       b->legacy_index()->named.scheme->md));
     }
-    grpc_metadata_batch_remove(b, GRPC_BATCH_SCHEME);
+    b->Remove(GRPC_BATCH_SCHEME);
   } else {
-    hs_add_error(
-        error_name, &error,
-        grpc_error_set_str(
-            GRPC_ERROR_CREATE_FROM_STATIC_STRING("Missing header"),
-            GRPC_ERROR_STR_KEY, grpc_slice_from_static_string(":scheme")));
+    hs_add_error(error_name, &error,
+                 grpc_error_set_str(
+                     GRPC_ERROR_CREATE_FROM_STATIC_STRING("Missing header"),
+                     GRPC_ERROR_STR_KEY, ":scheme"));
   }
 
-  if (b->idx.named.content_type != nullptr) {
+  if (b->legacy_index()->named.content_type != nullptr) {
     if (!grpc_mdelem_static_value_eq(
-            b->idx.named.content_type->md,
+            b->legacy_index()->named.content_type->md,
             GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC)) {
-      if (grpc_slice_buf_start_eq(GRPC_MDVALUE(b->idx.named.content_type->md),
-                                  EXPECTED_CONTENT_TYPE,
-                                  EXPECTED_CONTENT_TYPE_LENGTH) &&
+      if (grpc_slice_buf_start_eq(
+              GRPC_MDVALUE(b->legacy_index()->named.content_type->md),
+              EXPECTED_CONTENT_TYPE, EXPECTED_CONTENT_TYPE_LENGTH) &&
           (GRPC_SLICE_START_PTR(GRPC_MDVALUE(
-               b->idx.named.content_type->md))[EXPECTED_CONTENT_TYPE_LENGTH] ==
+               b->legacy_index()
+                   ->named.content_type->md))[EXPECTED_CONTENT_TYPE_LENGTH] ==
                '+' ||
            GRPC_SLICE_START_PTR(GRPC_MDVALUE(
-               b->idx.named.content_type->md))[EXPECTED_CONTENT_TYPE_LENGTH] ==
+               b->legacy_index()
+                   ->named.content_type->md))[EXPECTED_CONTENT_TYPE_LENGTH] ==
                ';')) {
         /* Although the C implementation doesn't (currently) generate them,
            any custom +-suffix is explicitly valid. */
@@ -247,27 +249,27 @@ static grpc_error_handle hs_filter_incoming_metadata(grpc_call_element* elem,
       } else {
         /* TODO(klempner): We're currently allowing this, but we shouldn't
            see it without a proxy so log for now. */
-        char* val = grpc_dump_slice(GRPC_MDVALUE(b->idx.named.content_type->md),
-                                    GPR_DUMP_ASCII);
+        char* val = grpc_dump_slice(
+            GRPC_MDVALUE(b->legacy_index()->named.content_type->md),
+            GPR_DUMP_ASCII);
         gpr_log(GPR_INFO, "Unexpected content-type '%s'", val);
         gpr_free(val);
       }
     }
-    grpc_metadata_batch_remove(b, GRPC_BATCH_CONTENT_TYPE);
+    b->Remove(GRPC_BATCH_CONTENT_TYPE);
   }
 
-  if (b->idx.named.path == nullptr) {
-    hs_add_error(
-        error_name, &error,
-        grpc_error_set_str(
-            GRPC_ERROR_CREATE_FROM_STATIC_STRING("Missing header"),
-            GRPC_ERROR_STR_KEY, grpc_slice_from_static_string(":path")));
+  if (b->legacy_index()->named.path == nullptr) {
+    hs_add_error(error_name, &error,
+                 grpc_error_set_str(
+                     GRPC_ERROR_CREATE_FROM_STATIC_STRING("Missing header"),
+                     GRPC_ERROR_STR_KEY, ":path"));
   } else if (*calld->recv_initial_metadata_flags &
              GRPC_INITIAL_METADATA_CACHEABLE_REQUEST) {
     /* We have a cacheable request made with GET verb. The path contains the
      * query parameter which is base64 encoded request payload. */
     const char k_query_separator = '?';
-    grpc_slice path_slice = GRPC_MDVALUE(b->idx.named.path->md);
+    grpc_slice path_slice = GRPC_MDVALUE(b->legacy_index()->named.path->md);
     uint8_t* path_ptr = GRPC_SLICE_START_PTR(path_slice);
     size_t path_length = GRPC_SLICE_LENGTH(path_slice);
     /* offset of the character '?' */
@@ -283,8 +285,8 @@ static grpc_error_handle hs_filter_incoming_metadata(grpc_call_element* elem,
       grpc_mdelem mdelem_path_without_query = grpc_mdelem_from_slices(
           GRPC_MDSTR_PATH, grpc_slice_sub(path_slice, 0, offset));
 
-      grpc_metadata_batch_substitute(b, b->idx.named.path,
-                                     mdelem_path_without_query);
+      (void)b->Substitute(b->legacy_index()->named.path,
+                          mdelem_path_without_query);
 
       /* decode payload from query and add to the slice buffer to be returned */
       const int k_url_safe = 1;
@@ -304,10 +306,11 @@ static grpc_error_handle hs_filter_incoming_metadata(grpc_call_element* elem,
     }
   }
 
-  if (b->idx.named.host != nullptr && b->idx.named.authority == nullptr) {
-    grpc_linked_mdelem* el = b->idx.named.host;
+  if (b->legacy_index()->named.host != nullptr &&
+      b->legacy_index()->named.authority == nullptr) {
+    grpc_linked_mdelem* el = b->legacy_index()->named.host;
     grpc_mdelem md = GRPC_MDELEM_REF(el->md);
-    grpc_metadata_batch_remove(b, el);
+    b->Remove(el);
     hs_add_error(
         error_name, &error,
         grpc_metadata_batch_add_head(
@@ -318,17 +321,17 @@ static grpc_error_handle hs_filter_incoming_metadata(grpc_call_element* elem,
     GRPC_MDELEM_UNREF(md);
   }
 
-  if (b->idx.named.authority == nullptr) {
-    hs_add_error(
-        error_name, &error,
-        grpc_error_set_str(
-            GRPC_ERROR_CREATE_FROM_STATIC_STRING("Missing header"),
-            GRPC_ERROR_STR_KEY, grpc_slice_from_static_string(":authority")));
+  if (b->legacy_index()->named.authority == nullptr) {
+    hs_add_error(error_name, &error,
+                 grpc_error_set_str(
+                     GRPC_ERROR_CREATE_FROM_STATIC_STRING("Missing header"),
+                     GRPC_ERROR_STR_KEY, ":authority"));
   }
 
   channel_data* chand = static_cast<channel_data*>(elem->channel_data);
-  if (!chand->surface_user_agent && b->idx.named.user_agent != nullptr) {
-    grpc_metadata_batch_remove(b, GRPC_BATCH_USER_AGENT);
+  if (!chand->surface_user_agent &&
+      b->legacy_index()->named.user_agent != nullptr) {
+    b->Remove(GRPC_BATCH_USER_AGENT);
   }
 
   return error;
@@ -359,7 +362,7 @@ static void hs_recv_initial_metadata_ready(void* user_data,
           "resuming recv_message_ready from recv_initial_metadata_ready");
     }
   } else {
-    GRPC_ERROR_REF(err);
+    (void)GRPC_ERROR_REF(err);
   }
   if (calld->seen_recv_trailing_metadata_ready) {
     GRPC_CALL_COMBINER_START(calld->call_combiner,
index 2427bc1..9be2f73 100644 (file)
@@ -200,8 +200,9 @@ void ServerLoadReportingCallData::StoreClientIpAndLrToken(const char* lr_token,
   if (lr_token_len != 0) {
     strncpy(cur_pos, lr_token, lr_token_len);
   }
-  GPR_ASSERT(cur_pos + lr_token_len - client_ip_and_lr_token_ ==
-             long(client_ip_and_lr_token_len_));
+  GPR_ASSERT(
+      static_cast<size_t>(cur_pos + lr_token_len - client_ip_and_lr_token_) ==
+      client_ip_and_lr_token_len_);
 }
 
 grpc_filtered_mdelem ServerLoadReportingCallData::RecvInitialMetadataFilter(
@@ -292,7 +293,9 @@ grpc_filtered_mdelem ServerLoadReportingCallData::SendTrailingMetadataFilter(
     }
     const double* cost_entry_ptr =
         reinterpret_cast<const double*>(GRPC_SLICE_START_PTR(value));
-    double cost_value = *cost_entry_ptr++;
+    double cost_value;
+    memcpy(&cost_value, cost_entry_ptr, sizeof(double));
+    cost_entry_ptr++;
     const char* cost_name = reinterpret_cast<const char*>(cost_entry_ptr);
     const size_t cost_name_len = cost_entry_size - sizeof(double);
     opencensus::stats::Record(
index 97a4dc2..c068728 100644 (file)
@@ -25,8 +25,8 @@
 
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/channel/channel_stack_builder.h"
+#include "src/core/lib/config/core_configuration.h"
 #include "src/core/lib/iomgr/timer.h"
-#include "src/core/lib/surface/channel_init.h"
 #include "src/core/lib/transport/http2_errors.h"
 
 /* If these settings change, make sure that we are not sending a GOAWAY for
@@ -534,29 +534,27 @@ const grpc_channel_filter grpc_max_age_filter = {
     grpc_channel_next_get_info,
     "max_age"};
 
-static bool maybe_add_max_age_filter(grpc_channel_stack_builder* builder,
-                                     void* /*arg*/) {
-  const grpc_channel_args* channel_args =
-      grpc_channel_stack_builder_get_channel_arguments(builder);
-  bool enable =
-      grpc_channel_arg_get_integer(
-          grpc_channel_args_find(channel_args, GRPC_ARG_MAX_CONNECTION_AGE_MS),
-          MAX_CONNECTION_AGE_INTEGER_OPTIONS) != INT_MAX ||
-      grpc_channel_arg_get_integer(
-          grpc_channel_args_find(channel_args, GRPC_ARG_MAX_CONNECTION_IDLE_MS),
-          MAX_CONNECTION_IDLE_INTEGER_OPTIONS) != INT_MAX;
-  if (enable) {
-    return grpc_channel_stack_builder_prepend_filter(
-        builder, &grpc_max_age_filter, nullptr, nullptr);
-  } else {
-    return true;
-  }
-}
-
-void grpc_max_age_filter_init(void) {
-  grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL,
-                                   GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
-                                   maybe_add_max_age_filter, nullptr);
+namespace grpc_core {
+void RegisterMaxAgeFilter(CoreConfiguration::Builder* builder) {
+  builder->channel_init()->RegisterStage(
+      GRPC_SERVER_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
+      [](grpc_channel_stack_builder* builder) {
+        const grpc_channel_args* channel_args =
+            grpc_channel_stack_builder_get_channel_arguments(builder);
+        bool enable = grpc_channel_arg_get_integer(
+                          grpc_channel_args_find(
+                              channel_args, GRPC_ARG_MAX_CONNECTION_AGE_MS),
+                          MAX_CONNECTION_AGE_INTEGER_OPTIONS) != INT_MAX ||
+                      grpc_channel_arg_get_integer(
+                          grpc_channel_args_find(
+                              channel_args, GRPC_ARG_MAX_CONNECTION_IDLE_MS),
+                          MAX_CONNECTION_IDLE_INTEGER_OPTIONS) != INT_MAX;
+        if (enable) {
+          return grpc_channel_stack_builder_prepend_filter(
+              builder, &grpc_max_age_filter, nullptr, nullptr);
+        } else {
+          return true;
+        }
+      });
 }
-
-void grpc_max_age_filter_shutdown(void) {}
+}  // namespace grpc_core
index d98e1c7..edb256c 100644 (file)
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 
-#include "src/core/ext/filters/client_channel/service_config.h"
-#include "src/core/ext/filters/client_channel/service_config_call_data.h"
+#include "src/core/ext/service_config/service_config_call_data.h"
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/channel/channel_stack_builder.h"
+#include "src/core/lib/config/core_configuration.h"
 #include "src/core/lib/gpr/string.h"
 #include "src/core/lib/gprpp/ref_counted.h"
 #include "src/core/lib/gprpp/ref_counted_ptr.h"
 #include "src/core/lib/surface/call.h"
-#include "src/core/lib/surface/channel_init.h"
 
 static void recv_message_ready(void* user_data, grpc_error_handle error);
 static void recv_trailing_metadata_ready(void* user_data,
@@ -211,7 +210,7 @@ static void recv_message_ready(void* user_data, grpc_error_handle error) {
     GRPC_ERROR_UNREF(calld->error);
     calld->error = GRPC_ERROR_REF(error);
   } else {
-    GRPC_ERROR_REF(error);
+    (void)GRPC_ERROR_REF(error);
   }
   // Invoke the next callback.
   grpc_closure* closure = calld->next_recv_message_ready;
@@ -344,7 +343,7 @@ const grpc_channel_filter grpc_message_size_filter = {
 
 // Used for GRPC_CLIENT_SUBCHANNEL
 static bool maybe_add_message_size_filter_subchannel(
-    grpc_channel_stack_builder* builder, void* /*arg*/) {
+    grpc_channel_stack_builder* builder) {
   const grpc_channel_args* channel_args =
       grpc_channel_stack_builder_get_channel_arguments(builder);
   if (grpc_channel_args_want_minimal_stack(channel_args)) {
@@ -356,8 +355,7 @@ static bool maybe_add_message_size_filter_subchannel(
 
 // Used for GRPC_CLIENT_DIRECT_CHANNEL and GRPC_SERVER_CHANNEL. Adds the filter
 // only if message size limits or service config is specified.
-static bool maybe_add_message_size_filter(grpc_channel_stack_builder* builder,
-                                          void* /*arg*/) {
+static bool maybe_add_message_size_filter(grpc_channel_stack_builder* builder) {
   const grpc_channel_args* channel_args =
       grpc_channel_stack_builder_get_channel_arguments(builder);
   if (grpc_channel_args_want_minimal_stack(channel_args)) {
@@ -384,16 +382,21 @@ static bool maybe_add_message_size_filter(grpc_channel_stack_builder* builder,
 }
 
 void grpc_message_size_filter_init(void) {
-  grpc_channel_init_register_stage(
-      GRPC_CLIENT_SUBCHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
-      maybe_add_message_size_filter_subchannel, nullptr);
-  grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL,
-                                   GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
-                                   maybe_add_message_size_filter, nullptr);
-  grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL,
-                                   GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
-                                   maybe_add_message_size_filter, nullptr);
   grpc_core::MessageSizeParser::Register();
 }
 
 void grpc_message_size_filter_shutdown(void) {}
+
+namespace grpc_core {
+void RegisterMessageSizeFilter(CoreConfiguration::Builder* builder) {
+  builder->channel_init()->RegisterStage(
+      GRPC_CLIENT_SUBCHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
+      maybe_add_message_size_filter_subchannel);
+  builder->channel_init()->RegisterStage(GRPC_CLIENT_DIRECT_CHANNEL,
+                                         GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
+                                         maybe_add_message_size_filter);
+  builder->channel_init()->RegisterStage(GRPC_SERVER_CHANNEL,
+                                         GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
+                                         maybe_add_message_size_filter);
+}
+}  // namespace grpc_core
index 6629803..b196534 100644 (file)
@@ -19,7 +19,7 @@
 
 #include <grpc/support/port_platform.h>
 
-#include "src/core/ext/filters/client_channel/service_config_parser.h"
+#include "src/core/ext/service_config/service_config_parser.h"
 #include "src/core/lib/channel/channel_stack.h"
 
 extern const grpc_channel_filter grpc_message_size_filter;
diff --git a/src/core/ext/filters/server_config_selector/server_config_selector.cc b/src/core/ext/filters/server_config_selector/server_config_selector.cc
new file mode 100644 (file)
index 0000000..85df64e
--- /dev/null
@@ -0,0 +1,67 @@
+//
+// 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 <grpc/support/port_platform.h>
+
+#include "src/core/ext/filters/server_config_selector/server_config_selector.h"
+
+#include "src/core/lib/channel/channel_args.h"
+
+namespace grpc_core {
+namespace {
+
+void* ServerConfigSelectorProviderArgCopy(void* p) {
+  ServerConfigSelectorProvider* arg =
+      static_cast<ServerConfigSelectorProvider*>(p);
+  return arg->Ref().release();
+}
+
+void ServerConfigSelectorProviderArgDestroy(void* p) {
+  ServerConfigSelectorProvider* arg =
+      static_cast<ServerConfigSelectorProvider*>(p);
+  arg->Unref();
+}
+
+int ServerConfigSelectorProviderArgCmp(void* p, void* q) {
+  return QsortCompare(p, q);
+}
+
+const grpc_arg_pointer_vtable kChannelArgVtable = {
+    ServerConfigSelectorProviderArgCopy, ServerConfigSelectorProviderArgDestroy,
+    ServerConfigSelectorProviderArgCmp};
+
+const char* kServerConfigSelectorProviderChannelArgName =
+    "grpc.internal.server_config_selector_provider";
+
+}  // namespace
+
+grpc_arg ServerConfigSelectorProvider::MakeChannelArg() const {
+  return grpc_channel_arg_pointer_create(
+      const_cast<char*>(kServerConfigSelectorProviderChannelArgName),
+      const_cast<ServerConfigSelectorProvider*>(this), &kChannelArgVtable);
+}
+
+RefCountedPtr<ServerConfigSelectorProvider>
+ServerConfigSelectorProvider::GetFromChannelArgs(
+    const grpc_channel_args& args) {
+  ServerConfigSelectorProvider* config_selector_provider =
+      grpc_channel_args_find_pointer<ServerConfigSelectorProvider>(
+          &args, kServerConfigSelectorProviderChannelArgName);
+  return config_selector_provider != nullptr ? config_selector_provider->Ref()
+                                             : nullptr;
+}
+
+}  // namespace grpc_core
diff --git a/src/core/ext/filters/server_config_selector/server_config_selector.h b/src/core/ext/filters/server_config_selector/server_config_selector.h
new file mode 100644 (file)
index 0000000..334bdbd
--- /dev/null
@@ -0,0 +1,70 @@
+//
+// 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.
+//
+
+#ifndef GRPC_CORE_EXT_FILTERS_SERVER_CONFIG_SELECTOR_SERVER_CONFIG_SELECTOR_H
+#define GRPC_CORE_EXT_FILTERS_SERVER_CONFIG_SELECTOR_SERVER_CONFIG_SELECTOR_H
+
+#include <grpc/support/port_platform.h>
+
+#include "absl/status/statusor.h"
+
+#include "src/core/ext/service_config/service_config.h"
+#include "src/core/lib/transport/metadata_batch.h"
+
+namespace grpc_core {
+
+// ServerConfigSelector allows for choosing the service config to apply to a
+// server-side call based on the received initial metadata.
+class ServerConfigSelector : public RefCounted<ServerConfigSelector> {
+ public:
+  // Configuration to apply to an incoming call
+  struct CallConfig {
+    grpc_error_handle error = GRPC_ERROR_NONE;
+    const ServiceConfigParser::ParsedConfigVector* method_configs = nullptr;
+    RefCountedPtr<ServiceConfig> service_config;
+  };
+
+  ~ServerConfigSelector() override = default;
+  // Returns the CallConfig to apply to a call based on the incoming \a metadata
+  virtual CallConfig GetCallConfig(grpc_metadata_batch* metadata) = 0;
+};
+
+// ServerConfigSelectorProvider allows for subscribers to watch for updates on
+// ServerConfigSelector. It is propagated via channel args.
+class ServerConfigSelectorProvider
+    : public RefCounted<ServerConfigSelectorProvider> {
+ public:
+  class ServerConfigSelectorWatcher {
+   public:
+    virtual ~ServerConfigSelectorWatcher() = default;
+    virtual void OnServerConfigSelectorUpdate(
+        absl::StatusOr<RefCountedPtr<ServerConfigSelector>> update) = 0;
+  };
+
+  ~ServerConfigSelectorProvider() override = default;
+  // Only a single watcher is allowed at present
+  virtual absl::StatusOr<RefCountedPtr<ServerConfigSelector>> Watch(
+      std::unique_ptr<ServerConfigSelectorWatcher> watcher) = 0;
+  virtual void CancelWatch() = 0;
+
+  grpc_arg MakeChannelArg() const;
+  static RefCountedPtr<ServerConfigSelectorProvider> GetFromChannelArgs(
+      const grpc_channel_args& args);
+};
+
+}  // namespace grpc_core
+
+#endif  // GRPC_CORE_EXT_FILTERS_SERVER_CONFIG_SELECTOR_SERVER_CONFIG_SELECTOR_H
diff --git a/src/core/ext/filters/server_config_selector/server_config_selector_filter.cc b/src/core/ext/filters/server_config_selector/server_config_selector_filter.cc
new file mode 100644 (file)
index 0000000..0f54ad5
--- /dev/null
@@ -0,0 +1,265 @@
+//
+//
+// 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 <grpc/support/port_platform.h>
+
+#include "src/core/ext/filters/server_config_selector/server_config_selector_filter.h"
+
+#include "src/core/ext/filters/server_config_selector/server_config_selector.h"
+#include "src/core/ext/service_config/service_config_call_data.h"
+#include "src/core/lib/transport/error_utils.h"
+
+namespace grpc_core {
+
+namespace {
+
+class ChannelData {
+ public:
+  static grpc_error_handle Init(grpc_channel_element* elem,
+                                grpc_channel_element_args* args);
+  static void Destroy(grpc_channel_element* elem);
+
+  absl::StatusOr<RefCountedPtr<ServerConfigSelector>> config_selector() {
+    MutexLock lock(&mu_);
+    return config_selector_;
+  }
+
+ private:
+  class ServerConfigSelectorWatcher
+      : public ServerConfigSelectorProvider::ServerConfigSelectorWatcher {
+   public:
+    explicit ServerConfigSelectorWatcher(ChannelData* chand) : chand_(chand) {}
+    void OnServerConfigSelectorUpdate(
+        absl::StatusOr<RefCountedPtr<ServerConfigSelector>> update) override {
+      MutexLock lock(&chand_->mu_);
+      chand_->config_selector_ = std::move(update);
+    }
+
+   private:
+    ChannelData* chand_;
+  };
+
+  explicit ChannelData(RefCountedPtr<ServerConfigSelectorProvider>
+                           server_config_selector_provider);
+  ~ChannelData();
+
+  RefCountedPtr<ServerConfigSelectorProvider> server_config_selector_provider_;
+  Mutex mu_;
+  absl::StatusOr<RefCountedPtr<ServerConfigSelector>> config_selector_
+      ABSL_GUARDED_BY(mu_);
+};
+
+class CallData {
+ public:
+  static grpc_error_handle Init(grpc_call_element* elem,
+                                const grpc_call_element_args* args);
+  static void Destroy(grpc_call_element* elem,
+                      const grpc_call_final_info* /* final_info */,
+                      grpc_closure* /* then_schedule_closure */);
+  static void StartTransportStreamOpBatch(grpc_call_element* elem,
+                                          grpc_transport_stream_op_batch* op);
+
+ private:
+  CallData(grpc_call_element* elem, const grpc_call_element_args& args);
+  ~CallData();
+  static void RecvInitialMetadataReady(void* user_data,
+                                       grpc_error_handle error);
+  static void RecvTrailingMetadataReady(void* user_data,
+                                        grpc_error_handle error);
+  void MaybeResumeRecvTrailingMetadataReady();
+
+  grpc_call_context_element* call_context_;
+  grpc_core::CallCombiner* call_combiner_;
+  ServiceConfigCallData service_config_call_data_;
+  // Overall error for the call
+  grpc_error_handle error_ = GRPC_ERROR_NONE;
+  // State for keeping track of recv_initial_metadata
+  grpc_metadata_batch* recv_initial_metadata_ = nullptr;
+  grpc_closure* original_recv_initial_metadata_ready_ = nullptr;
+  grpc_closure recv_initial_metadata_ready_;
+  // State for keeping of track of recv_trailing_metadata
+  grpc_closure* original_recv_trailing_metadata_ready_;
+  grpc_closure recv_trailing_metadata_ready_;
+  grpc_error_handle recv_trailing_metadata_ready_error_;
+  bool seen_recv_trailing_metadata_ready_ = false;
+};
+
+// ChannelData
+
+grpc_error_handle ChannelData::Init(grpc_channel_element* elem,
+                                    grpc_channel_element_args* args) {
+  GPR_ASSERT(elem->filter = &kServerConfigSelectorFilter);
+  RefCountedPtr<ServerConfigSelectorProvider> server_config_selector_provider =
+      ServerConfigSelectorProvider::GetFromChannelArgs(*args->channel_args);
+  if (server_config_selector_provider == nullptr) {
+    return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+        "No ServerConfigSelectorProvider object found");
+  }
+  new (elem->channel_data)
+      ChannelData(std::move(server_config_selector_provider));
+  return GRPC_ERROR_NONE;
+}
+
+void ChannelData::Destroy(grpc_channel_element* elem) {
+  auto* chand = static_cast<ChannelData*>(elem->channel_data);
+  chand->~ChannelData();
+}
+
+ChannelData::ChannelData(
+    RefCountedPtr<ServerConfigSelectorProvider> server_config_selector_provider)
+    : server_config_selector_provider_(
+          std::move(server_config_selector_provider)) {
+  GPR_ASSERT(server_config_selector_provider_ != nullptr);
+  auto server_config_selector_watcher =
+      absl::make_unique<ServerConfigSelectorWatcher>(this);
+  config_selector_ = server_config_selector_provider_->Watch(
+      std::move(server_config_selector_watcher));
+}
+
+ChannelData::~ChannelData() { server_config_selector_provider_->CancelWatch(); }
+
+// CallData
+
+grpc_error_handle CallData::Init(grpc_call_element* elem,
+                                 const grpc_call_element_args* args) {
+  new (elem->call_data) CallData(elem, *args);
+  return GRPC_ERROR_NONE;
+}
+
+void CallData::Destroy(grpc_call_element* elem,
+                       const grpc_call_final_info* /*final_info*/,
+                       grpc_closure* /*then_schedule_closure*/) {
+  auto* calld = static_cast<CallData*>(elem->call_data);
+  calld->~CallData();
+}
+
+void CallData::StartTransportStreamOpBatch(grpc_call_element* elem,
+                                           grpc_transport_stream_op_batch* op) {
+  CallData* calld = static_cast<CallData*>(elem->call_data);
+  if (op->recv_initial_metadata) {
+    calld->recv_initial_metadata_ =
+        op->payload->recv_initial_metadata.recv_initial_metadata;
+    calld->original_recv_initial_metadata_ready_ =
+        op->payload->recv_initial_metadata.recv_initial_metadata_ready;
+    op->payload->recv_initial_metadata.recv_initial_metadata_ready =
+        &calld->recv_initial_metadata_ready_;
+  }
+  if (op->recv_trailing_metadata) {
+    // We might generate errors on receiving initial metadata which we need to
+    // bubble up through recv_trailing_metadata_ready
+    calld->original_recv_trailing_metadata_ready_ =
+        op->payload->recv_trailing_metadata.recv_trailing_metadata_ready;
+    op->payload->recv_trailing_metadata.recv_trailing_metadata_ready =
+        &calld->recv_trailing_metadata_ready_;
+  }
+  // Chain to the next filter.
+  grpc_call_next_op(elem, op);
+}
+
+CallData::CallData(grpc_call_element* elem, const grpc_call_element_args& args)
+    : call_context_(args.context), call_combiner_(args.call_combiner) {
+  GRPC_CLOSURE_INIT(&recv_initial_metadata_ready_, RecvInitialMetadataReady,
+                    elem, grpc_schedule_on_exec_ctx);
+  GRPC_CLOSURE_INIT(&recv_trailing_metadata_ready_, RecvTrailingMetadataReady,
+                    elem, grpc_schedule_on_exec_ctx);
+}
+
+CallData::~CallData() {
+  // Remove the entry from call context, just in case anyone above us
+  // tries to look at it during call stack destruction.
+  call_context_[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].value = nullptr;
+  GRPC_ERROR_UNREF(error_);
+}
+
+void CallData::RecvInitialMetadataReady(void* user_data,
+                                        grpc_error_handle error) {
+  grpc_call_element* elem = static_cast<grpc_call_element*>(user_data);
+  CallData* calld = static_cast<CallData*>(elem->call_data);
+  ChannelData* chand = static_cast<ChannelData*>(elem->channel_data);
+  if (error == GRPC_ERROR_NONE) {
+    auto config_selector = chand->config_selector();
+    if (config_selector.ok()) {
+      auto call_config =
+          config_selector.value()->GetCallConfig(calld->recv_initial_metadata_);
+      if (call_config.error != GRPC_ERROR_NONE) {
+        calld->error_ = call_config.error;
+        error = call_config.error;  // Does not take a ref
+      } else {
+        calld->service_config_call_data_ =
+            ServiceConfigCallData(std::move(call_config.service_config),
+                                  call_config.method_configs, {});
+        calld->call_context_[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].value =
+            &calld->service_config_call_data_;
+      }
+    } else {
+      calld->error_ = absl_status_to_grpc_error(config_selector.status());
+      error = calld->error_;
+    }
+  }
+  calld->MaybeResumeRecvTrailingMetadataReady();
+  grpc_closure* closure = calld->original_recv_initial_metadata_ready_;
+  calld->original_recv_initial_metadata_ready_ = nullptr;
+  Closure::Run(DEBUG_LOCATION, closure, GRPC_ERROR_REF(error));
+}
+
+void CallData::RecvTrailingMetadataReady(void* user_data,
+                                         grpc_error_handle error) {
+  grpc_call_element* elem = static_cast<grpc_call_element*>(user_data);
+  CallData* calld = static_cast<CallData*>(elem->call_data);
+  if (calld->original_recv_initial_metadata_ready_ != nullptr) {
+    calld->seen_recv_trailing_metadata_ready_ = true;
+    calld->recv_trailing_metadata_ready_error_ = GRPC_ERROR_REF(error);
+    GRPC_CALL_COMBINER_STOP(calld->call_combiner_,
+                            "Deferring RecvTrailingMetadataReady until after "
+                            "RecvInitialMetadataReady");
+    return;
+  }
+  error = grpc_error_add_child(GRPC_ERROR_REF(error), calld->error_);
+  calld->error_ = GRPC_ERROR_NONE;
+  grpc_closure* closure = calld->original_recv_trailing_metadata_ready_;
+  calld->original_recv_trailing_metadata_ready_ = nullptr;
+  Closure::Run(DEBUG_LOCATION, closure, error);
+}
+
+void CallData::MaybeResumeRecvTrailingMetadataReady() {
+  if (seen_recv_trailing_metadata_ready_) {
+    seen_recv_trailing_metadata_ready_ = false;
+    grpc_error_handle error = recv_trailing_metadata_ready_error_;
+    recv_trailing_metadata_ready_error_ = GRPC_ERROR_NONE;
+    GRPC_CALL_COMBINER_START(call_combiner_, &recv_trailing_metadata_ready_,
+                             error, "Continuing RecvTrailingMetadataReady");
+  }
+}
+
+}  // namespace
+
+const grpc_channel_filter kServerConfigSelectorFilter = {
+    CallData::StartTransportStreamOpBatch,
+    grpc_channel_next_op,
+    sizeof(CallData),
+    CallData::Init,
+    grpc_call_stack_ignore_set_pollset_or_pollset_set,
+    CallData::Destroy,
+    sizeof(ChannelData),
+    ChannelData::Init,
+    ChannelData::Destroy,
+    grpc_channel_next_get_info,
+    "server_config_selector_filter",
+};
+
+}  // namespace grpc_core
diff --git a/src/core/ext/filters/server_config_selector/server_config_selector_filter.h b/src/core/ext/filters/server_config_selector/server_config_selector_filter.h
new file mode 100644 (file)
index 0000000..370a229
--- /dev/null
@@ -0,0 +1,32 @@
+//
+//
+// 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.
+//
+//
+
+#ifndef GRPC_CORE_EXT_FILTERS_SERVER_CONFIG_SELECTOR_SERVER_CONFIG_SELECTOR_FILTER_H
+#define GRPC_CORE_EXT_FILTERS_SERVER_CONFIG_SELECTOR_SERVER_CONFIG_SELECTOR_FILTER_H
+
+#include <grpc/support/port_platform.h>
+
+#include "src/core/lib/channel/channel_stack.h"
+
+namespace grpc_core {
+
+extern const grpc_channel_filter kServerConfigSelectorFilter;
+
+}  // namespace grpc_core
+
+#endif  // GRPC_CORE_EXT_FILTERS_SERVER_CONFIG_SELECTOR_SERVER_CONFIG_SELECTOR_FILTER_H
diff --git a/src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc b/src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc
deleted file mode 100644 (file)
index b2e8f3f..0000000
+++ /dev/null
@@ -1,211 +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 <grpc/support/port_platform.h>
-
-#include "src/core/ext/filters/workarounds/workaround_cronet_compression_filter.h"
-
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-
-#include "src/core/ext/filters/workarounds/workaround_utils.h"
-#include "src/core/lib/channel/channel_stack_builder.h"
-#include "src/core/lib/surface/channel_init.h"
-#include "src/core/lib/transport/metadata.h"
-
-namespace {
-struct call_data {
-  // Receive closures are chained: we inject this closure as the
-  // recv_initial_metadata_ready up-call on transport_stream_op, and remember to
-  // call our next_recv_initial_metadata_ready member after handling it.
-  grpc_closure recv_initial_metadata_ready;
-  // Used by recv_initial_metadata_ready.
-  grpc_metadata_batch* recv_initial_metadata;
-  // Original recv_initial_metadata_ready callback, invoked after our own.
-  grpc_closure* next_recv_initial_metadata_ready;
-
-  // Marks whether the workaround is active
-  bool workaround_active;
-};
-}  // namespace
-
-// Find the user agent metadata element in the batch
-static bool get_user_agent_mdelem(const grpc_metadata_batch* batch,
-                                  grpc_mdelem* md) {
-  if (batch->idx.named.user_agent != nullptr) {
-    *md = batch->idx.named.user_agent->md;
-    return true;
-  }
-  return false;
-}
-
-// Callback invoked when we receive an initial metadata.
-static void recv_initial_metadata_ready(void* user_data,
-                                        grpc_error_handle error) {
-  grpc_call_element* elem = static_cast<grpc_call_element*>(user_data);
-  call_data* calld = static_cast<call_data*>(elem->call_data);
-
-  if (GRPC_ERROR_NONE == error) {
-    grpc_mdelem md;
-    if (get_user_agent_mdelem(calld->recv_initial_metadata, &md)) {
-      grpc_workaround_user_agent_md* user_agent_md = grpc_parse_user_agent(md);
-      if (user_agent_md
-              ->workaround_active[GRPC_WORKAROUND_ID_CRONET_COMPRESSION]) {
-        calld->workaround_active = true;
-      }
-    }
-  }
-
-  // Invoke the next callback.
-  grpc_core::Closure::Run(DEBUG_LOCATION,
-                          calld->next_recv_initial_metadata_ready,
-                          GRPC_ERROR_REF(error));
-}
-
-// Start transport stream op.
-static void cronet_compression_start_transport_stream_op_batch(
-    grpc_call_element* elem, grpc_transport_stream_op_batch* op) {
-  call_data* calld = static_cast<call_data*>(elem->call_data);
-
-  // Inject callback for receiving initial metadata
-  if (op->recv_initial_metadata) {
-    calld->next_recv_initial_metadata_ready =
-        op->payload->recv_initial_metadata.recv_initial_metadata_ready;
-    op->payload->recv_initial_metadata.recv_initial_metadata_ready =
-        &calld->recv_initial_metadata_ready;
-    calld->recv_initial_metadata =
-        op->payload->recv_initial_metadata.recv_initial_metadata;
-  }
-
-  if (op->send_message) {
-    /* Send message happens after client's user-agent (initial metadata) is
-     * received, so workaround_active must be set already */
-    if (calld->workaround_active) {
-      op->payload->send_message.send_message->set_flags(
-          op->payload->send_message.send_message->flags() |
-          GRPC_WRITE_NO_COMPRESS);
-    }
-  }
-
-  // Chain to the next filter.
-  grpc_call_next_op(elem, op);
-}
-
-// Constructor for call_data.
-static grpc_error_handle cronet_compression_init_call_elem(
-    grpc_call_element* elem, const grpc_call_element_args* /*args*/) {
-  call_data* calld = static_cast<call_data*>(elem->call_data);
-  calld->next_recv_initial_metadata_ready = nullptr;
-  calld->workaround_active = false;
-  GRPC_CLOSURE_INIT(&calld->recv_initial_metadata_ready,
-                    recv_initial_metadata_ready, elem,
-                    grpc_schedule_on_exec_ctx);
-  return GRPC_ERROR_NONE;
-}
-
-// Destructor for call_data.
-static void cronet_compression_destroy_call_elem(
-    grpc_call_element* /*elem*/, const grpc_call_final_info* /*final_info*/,
-    grpc_closure* /*ignored*/) {}
-
-// Constructor for channel_data.
-static grpc_error_handle cronet_compression_init_channel_elem(
-    grpc_channel_element* /*elem*/, grpc_channel_element_args* /*args*/) {
-  return GRPC_ERROR_NONE;
-}
-
-// Destructor for channel_data.
-static void cronet_compression_destroy_channel_elem(
-    grpc_channel_element* /*elem*/) {}
-
-// Parse the user agent
-static bool parse_user_agent(grpc_mdelem md) {
-  const char grpc_objc_specifier[] = "grpc-objc/";
-  const size_t grpc_objc_specifier_len = sizeof(grpc_objc_specifier) - 1;
-  const char cronet_specifier[] = "cronet_http";
-  const size_t cronet_specifier_len = sizeof(cronet_specifier) - 1;
-
-  char* user_agent_str = grpc_slice_to_c_string(GRPC_MDVALUE(md));
-  bool grpc_objc_specifier_seen = false;
-  bool cronet_specifier_seen = false;
-  char *major_version_str = user_agent_str, *minor_version_str;
-  long major_version = 0, minor_version = 0;
-
-  char* head = strtok(user_agent_str, " ");
-  while (head != nullptr) {
-    if (!grpc_objc_specifier_seen &&
-        0 == strncmp(head, grpc_objc_specifier, grpc_objc_specifier_len)) {
-      major_version_str = head + grpc_objc_specifier_len;
-      grpc_objc_specifier_seen = true;
-    } else if (grpc_objc_specifier_seen &&
-               0 == strncmp(head, cronet_specifier, cronet_specifier_len)) {
-      cronet_specifier_seen = true;
-      break;
-    }
-
-    head = strtok(nullptr, " ");
-  }
-  if (grpc_objc_specifier_seen) {
-    major_version_str = strtok(major_version_str, ".");
-    minor_version_str = strtok(nullptr, ".");
-    major_version = atol(major_version_str);
-    minor_version = atol(minor_version_str);
-  }
-
-  gpr_free(user_agent_str);
-  return (grpc_objc_specifier_seen && cronet_specifier_seen &&
-          (major_version < 1 || (major_version == 1 && minor_version <= 3)));
-}
-
-const grpc_channel_filter grpc_workaround_cronet_compression_filter = {
-    cronet_compression_start_transport_stream_op_batch,
-    grpc_channel_next_op,
-    sizeof(call_data),
-    cronet_compression_init_call_elem,
-    grpc_call_stack_ignore_set_pollset_or_pollset_set,
-    cronet_compression_destroy_call_elem,
-    0,
-    cronet_compression_init_channel_elem,
-    cronet_compression_destroy_channel_elem,
-    grpc_channel_next_get_info,
-    "workaround_cronet_compression"};
-
-static bool register_workaround_cronet_compression(
-    grpc_channel_stack_builder* builder, void* /*arg*/) {
-  const grpc_channel_args* channel_args =
-      grpc_channel_stack_builder_get_channel_arguments(builder);
-  const grpc_arg* a = grpc_channel_args_find(
-      channel_args, GRPC_ARG_WORKAROUND_CRONET_COMPRESSION);
-  if (a == nullptr) {
-    return true;
-  }
-  if (!grpc_channel_arg_get_bool(a, false)) {
-    return true;
-  }
-  return grpc_channel_stack_builder_prepend_filter(
-      builder, &grpc_workaround_cronet_compression_filter, nullptr, nullptr);
-}
-
-void grpc_workaround_cronet_compression_filter_init(void) {
-  grpc_channel_init_register_stage(
-      GRPC_SERVER_CHANNEL, GRPC_WORKAROUND_PRIORITY_HIGH,
-      register_workaround_cronet_compression, nullptr);
-  grpc_register_workaround(GRPC_WORKAROUND_ID_CRONET_COMPRESSION,
-                           parse_user_agent);
-}
-
-void grpc_workaround_cronet_compression_filter_shutdown(void) {}
diff --git a/src/core/ext/filters/workarounds/workaround_cronet_compression_filter.h b/src/core/ext/filters/workarounds/workaround_cronet_compression_filter.h
deleted file mode 100644 (file)
index 94d20f0..0000000
+++ /dev/null
@@ -1,27 +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.
-//
-
-#ifndef GRPC_CORE_EXT_FILTERS_WORKAROUNDS_WORKAROUND_CRONET_COMPRESSION_FILTER_H
-#define GRPC_CORE_EXT_FILTERS_WORKAROUNDS_WORKAROUND_CRONET_COMPRESSION_FILTER_H
-
-#include <grpc/support/port_platform.h>
-
-#include "src/core/lib/channel/channel_stack.h"
-
-extern const grpc_channel_filter grpc_workaround_cronet_compression_filter;
-
-#endif /* GRPC_CORE_EXT_FILTERS_WORKAROUNDS_WORKAROUND_CRONET_COMPRESSION_FILTER_H \
-        */
diff --git a/src/core/ext/filters/workarounds/workaround_utils.cc b/src/core/ext/filters/workarounds/workaround_utils.cc
deleted file mode 100644 (file)
index 2a184ba..0000000
+++ /dev/null
@@ -1,53 +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 <grpc/support/port_platform.h>
-
-#include "src/core/ext/filters/workarounds/workaround_utils.h"
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-
-user_agent_parser ua_parser[GRPC_MAX_WORKAROUND_ID];
-
-static void destroy_user_agent_md(void* user_agent_md) {
-  gpr_free(user_agent_md);
-}
-
-grpc_workaround_user_agent_md* grpc_parse_user_agent(grpc_mdelem md) {
-  grpc_workaround_user_agent_md* user_agent_md =
-      static_cast<grpc_workaround_user_agent_md*>(
-          grpc_mdelem_get_user_data(md, destroy_user_agent_md));
-
-  if (nullptr != user_agent_md) {
-    return user_agent_md;
-  }
-  user_agent_md = static_cast<grpc_workaround_user_agent_md*>(
-      gpr_malloc(sizeof(grpc_workaround_user_agent_md)));
-  for (int i = 0; i < GRPC_MAX_WORKAROUND_ID; i++) {
-    if (ua_parser[i]) {
-      user_agent_md->workaround_active[i] = ua_parser[i](md);
-    }
-  }
-  grpc_mdelem_set_user_data(md, destroy_user_agent_md, user_agent_md);
-
-  return user_agent_md;
-}
-
-void grpc_register_workaround(uint32_t id, user_agent_parser parser) {
-  GPR_ASSERT(id < GRPC_MAX_WORKAROUND_ID);
-  ua_parser[id] = parser;
-}
diff --git a/src/core/ext/filters/workarounds/workaround_utils.h b/src/core/ext/filters/workarounds/workaround_utils.h
deleted file mode 100644 (file)
index f172ccc..0000000
+++ /dev/null
@@ -1,39 +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.
-//
-
-#ifndef GRPC_CORE_EXT_FILTERS_WORKAROUNDS_WORKAROUND_UTILS_H
-#define GRPC_CORE_EXT_FILTERS_WORKAROUNDS_WORKAROUND_UTILS_H
-
-#include <grpc/support/port_platform.h>
-
-#include <grpc/support/workaround_list.h>
-
-#include "src/core/lib/transport/metadata.h"
-
-#define GRPC_WORKAROUND_PRIORITY_HIGH 10001
-#define GRPC_WORKAROUND_PROIRITY_LOW 9999
-
-typedef struct grpc_workaround_user_agent_md {
-  bool workaround_active[GRPC_MAX_WORKAROUND_ID];
-} grpc_workaround_user_agent_md;
-
-grpc_workaround_user_agent_md* grpc_parse_user_agent(grpc_mdelem md);
-
-typedef bool (*user_agent_parser)(grpc_mdelem);
-
-void grpc_register_workaround(uint32_t id, user_agent_parser parser);
-
-#endif /* GRPC_CORE_EXT_FILTERS_WORKAROUNDS_WORKAROUND_UTILS_H */
diff --git a/src/core/ext/service_config/service_config.cc b/src/core/ext/service_config/service_config.cc
new file mode 100644 (file)
index 0000000..643b175
--- /dev/null
@@ -0,0 +1,227 @@
+//
+// 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 "src/core/ext/service_config/service_config.h"
+
+#include <string>
+
+#include "absl/strings/str_cat.h"
+
+#include <grpc/support/log.h>
+
+#include "src/core/ext/service_config/service_config_parser.h"
+#include "src/core/lib/json/json.h"
+#include "src/core/lib/slice/slice_internal.h"
+
+namespace grpc_core {
+
+RefCountedPtr<ServiceConfig> ServiceConfig::Create(
+    const grpc_channel_args* args, absl::string_view json_string,
+    grpc_error_handle* error) {
+  GPR_DEBUG_ASSERT(error != nullptr);
+  Json json = Json::Parse(json_string, error);
+  if (*error != GRPC_ERROR_NONE) return nullptr;
+  return MakeRefCounted<ServiceConfig>(args, std::string(json_string),
+                                       std::move(json), error);
+}
+
+ServiceConfig::ServiceConfig(const grpc_channel_args* args,
+                             std::string json_string, Json json,
+                             grpc_error_handle* error)
+    : json_string_(std::move(json_string)), json_(std::move(json)) {
+  GPR_DEBUG_ASSERT(error != nullptr);
+  if (json_.type() != Json::Type::OBJECT) {
+    *error =
+        GRPC_ERROR_CREATE_FROM_STATIC_STRING("JSON value is not an object");
+    return;
+  }
+  std::vector<grpc_error_handle> error_list;
+  grpc_error_handle global_error = GRPC_ERROR_NONE;
+  parsed_global_configs_ =
+      ServiceConfigParser::ParseGlobalParameters(args, json_, &global_error);
+  if (global_error != GRPC_ERROR_NONE) error_list.push_back(global_error);
+  grpc_error_handle local_error = ParsePerMethodParams(args);
+  if (local_error != GRPC_ERROR_NONE) error_list.push_back(local_error);
+  if (!error_list.empty()) {
+    *error = GRPC_ERROR_CREATE_FROM_VECTOR("Service config parsing error",
+                                           &error_list);
+  }
+}
+
+ServiceConfig::~ServiceConfig() {
+  for (auto& p : parsed_method_configs_map_) {
+    grpc_slice_unref_internal(p.first);
+  }
+}
+
+grpc_error_handle ServiceConfig::ParseJsonMethodConfig(
+    const grpc_channel_args* args, const Json& json) {
+  std::vector<grpc_error_handle> error_list;
+  // Parse method config with each registered parser.
+  auto parsed_configs =
+      absl::make_unique<ServiceConfigParser::ParsedConfigVector>();
+  grpc_error_handle parser_error = GRPC_ERROR_NONE;
+  *parsed_configs =
+      ServiceConfigParser::ParsePerMethodParameters(args, json, &parser_error);
+  if (parser_error != GRPC_ERROR_NONE) {
+    error_list.push_back(parser_error);
+  }
+  parsed_method_config_vectors_storage_.push_back(std::move(parsed_configs));
+  const auto* vector_ptr = parsed_method_config_vectors_storage_.back().get();
+  // Add an entry for each path.
+  bool found_name = false;
+  auto it = json.object_value().find("name");
+  if (it != json.object_value().end()) {
+    if (it->second.type() != Json::Type::ARRAY) {
+      error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+          "field:name error:not of type Array"));
+      return GRPC_ERROR_CREATE_FROM_VECTOR("methodConfig", &error_list);
+    }
+    const Json::Array& name_array = it->second.array_value();
+    for (const Json& name : name_array) {
+      grpc_error_handle parse_error = GRPC_ERROR_NONE;
+      std::string path = ParseJsonMethodName(name, &parse_error);
+      if (parse_error != GRPC_ERROR_NONE) {
+        error_list.push_back(parse_error);
+      } else {
+        found_name = true;
+        if (path.empty()) {
+          if (default_method_config_vector_ != nullptr) {
+            error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+                "field:name error:multiple default method configs"));
+          }
+          default_method_config_vector_ = vector_ptr;
+        } else {
+          grpc_slice key = grpc_slice_from_copied_string(path.c_str());
+          // If the key is not already present in the map, this will
+          // store a ref to the key in the map.
+          auto& value = parsed_method_configs_map_[key];
+          if (value != nullptr) {
+            error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+                "field:name error:multiple method configs with same name"));
+            // The map entry already existed, so we need to unref the
+            // key we just created.
+            grpc_slice_unref_internal(key);
+          } else {
+            value = vector_ptr;
+          }
+        }
+      }
+    }
+  }
+  if (!found_name) {
+    parsed_method_config_vectors_storage_.pop_back();
+  }
+  return GRPC_ERROR_CREATE_FROM_VECTOR("methodConfig", &error_list);
+}
+
+grpc_error_handle ServiceConfig::ParsePerMethodParams(
+    const grpc_channel_args* args) {
+  std::vector<grpc_error_handle> error_list;
+  auto it = json_.object_value().find("methodConfig");
+  if (it != json_.object_value().end()) {
+    if (it->second.type() != Json::Type::ARRAY) {
+      error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+          "field:methodConfig error:not of type Array"));
+    }
+    for (const Json& method_config : it->second.array_value()) {
+      if (method_config.type() != Json::Type::OBJECT) {
+        error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+            "field:methodConfig error:not of type Object"));
+        continue;
+      }
+      grpc_error_handle error = ParseJsonMethodConfig(args, method_config);
+      if (error != GRPC_ERROR_NONE) {
+        error_list.push_back(error);
+      }
+    }
+  }
+  return GRPC_ERROR_CREATE_FROM_VECTOR("Method Params", &error_list);
+}
+
+std::string ServiceConfig::ParseJsonMethodName(const Json& json,
+                                               grpc_error_handle* error) {
+  if (json.type() != Json::Type::OBJECT) {
+    *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+        "field:name error:type is not object");
+    return "";
+  }
+  // Find service name.
+  const std::string* service_name = nullptr;
+  auto it = json.object_value().find("service");
+  if (it != json.object_value().end() &&
+      it->second.type() != Json::Type::JSON_NULL) {
+    if (it->second.type() != Json::Type::STRING) {
+      *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+          "field:name error: field:service error:not of type string");
+      return "";
+    }
+    if (!it->second.string_value().empty()) {
+      service_name = &it->second.string_value();
+    }
+  }
+  const std::string* method_name = nullptr;
+  // Find method name.
+  it = json.object_value().find("method");
+  if (it != json.object_value().end() &&
+      it->second.type() != Json::Type::JSON_NULL) {
+    if (it->second.type() != Json::Type::STRING) {
+      *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+          "field:name error: field:method error:not of type string");
+      return "";
+    }
+    if (!it->second.string_value().empty()) {
+      method_name = &it->second.string_value();
+    }
+  }
+  // If neither service nor method are specified, it's the default.
+  // Method name may not be specified without service name.
+  if (service_name == nullptr) {
+    if (method_name != nullptr) {
+      *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+          "field:name error:method name populated without service name");
+    }
+    return "";
+  }
+  // Construct path.
+  return absl::StrCat("/", *service_name, "/",
+                      method_name == nullptr ? "" : *method_name);
+}
+
+const ServiceConfigParser::ParsedConfigVector*
+ServiceConfig::GetMethodParsedConfigVector(const grpc_slice& path) const {
+  if (parsed_method_configs_map_.empty()) {
+    return default_method_config_vector_;
+  }
+  // Try looking up the full path in the map.
+  auto it = parsed_method_configs_map_.find(path);
+  if (it != parsed_method_configs_map_.end()) return it->second;
+  // If we didn't find a match for the path, try looking for a wildcard
+  // entry (i.e., change "/service/method" to "/service/").
+  UniquePtr<char> path_str(grpc_slice_to_c_string(path));
+  char* sep = strrchr(path_str.get(), '/');
+  if (sep == nullptr) return nullptr;  // Shouldn't ever happen.
+  sep[1] = '\0';
+  grpc_slice wildcard_path = grpc_slice_from_static_string(path_str.get());
+  it = parsed_method_configs_map_.find(wildcard_path);
+  if (it != parsed_method_configs_map_.end()) return it->second;
+  // Try default method config, if set.
+  return default_method_config_vector_;
+}
+
+}  // namespace grpc_core
diff --git a/src/core/ext/service_config/service_config.h b/src/core/ext/service_config/service_config.h
new file mode 100644 (file)
index 0000000..0fc49be
--- /dev/null
@@ -0,0 +1,127 @@
+//
+// 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.
+//
+
+#ifndef GRPC_CORE_EXT_SERVICE_CONFIG_SERVICE_CONFIG_H
+#define GRPC_CORE_EXT_SERVICE_CONFIG_SERVICE_CONFIG_H
+
+#include <grpc/support/port_platform.h>
+
+#include <unordered_map>
+
+#include "absl/container/inlined_vector.h"
+
+#include <grpc/impl/codegen/grpc_types.h>
+#include <grpc/support/string_util.h>
+
+#include "src/core/ext/service_config/service_config_parser.h"
+#include "src/core/lib/gprpp/ref_counted.h"
+#include "src/core/lib/gprpp/ref_counted_ptr.h"
+#include "src/core/lib/iomgr/error.h"
+#include "src/core/lib/json/json.h"
+#include "src/core/lib/slice/slice_internal.h"
+
+// The main purpose of the code here is to parse the service config in
+// JSON form, which will look like this:
+//
+// {
+//   "loadBalancingPolicy": "string",  // optional
+//   "methodConfig": [  // array of one or more method_config objects
+//     {
+//       "name": [  // array of one or more name objects
+//         {
+//           "service": "string",  // required
+//           "method": "string",  // optional
+//         }
+//       ],
+//       // remaining fields are optional.
+//       // see https://developers.google.com/protocol-buffers/docs/proto3#json
+//       // for format details.
+//       "waitForReady": bool,
+//       "timeout": "duration_string",
+//       "maxRequestMessageBytes": "int64_string",
+//       "maxResponseMessageBytes": "int64_string",
+//     }
+//   ]
+// }
+
+namespace grpc_core {
+
+// TODO(roth): Consider stripping this down further to the completely minimal
+// interface requied to be exposed as part of the resolver API.
+class ServiceConfig : public RefCounted<ServiceConfig> {
+ public:
+  /// Creates a new service config from parsing \a json_string.
+  /// Returns null on parse error.
+  static RefCountedPtr<ServiceConfig> Create(const grpc_channel_args* args,
+                                             absl::string_view json_string,
+                                             grpc_error_handle* error);
+
+  ServiceConfig(const grpc_channel_args* args, std::string json_string,
+                Json json, grpc_error_handle* error);
+  ~ServiceConfig() override;
+
+  const std::string& json_string() const { return json_string_; }
+
+  /// Retrieves the global parsed config at index \a index. The
+  /// lifetime of the returned object is tied to the lifetime of the
+  /// ServiceConfig object.
+  ServiceConfigParser::ParsedConfig* GetGlobalParsedConfig(size_t index) {
+    GPR_DEBUG_ASSERT(index < parsed_global_configs_.size());
+    return parsed_global_configs_[index].get();
+  }
+
+  /// Retrieves the vector of parsed configs for the method identified
+  /// by \a path.  The lifetime of the returned vector and contained objects
+  /// is tied to the lifetime of the ServiceConfig object.
+  const ServiceConfigParser::ParsedConfigVector* GetMethodParsedConfigVector(
+      const grpc_slice& path) const;
+
+ private:
+  // Helper functions for parsing the method configs.
+  grpc_error_handle ParsePerMethodParams(const grpc_channel_args* args);
+  grpc_error_handle ParseJsonMethodConfig(const grpc_channel_args* args,
+                                          const Json& json);
+
+  // Returns a path string for the JSON name object specified by json.
+  // Sets *error on error.
+  static std::string ParseJsonMethodName(const Json& json,
+                                         grpc_error_handle* error);
+
+  std::string json_string_;
+  Json json_;
+
+  absl::InlinedVector<std::unique_ptr<ServiceConfigParser::ParsedConfig>,
+                      ServiceConfigParser::kNumPreallocatedParsers>
+      parsed_global_configs_;
+  // A map from the method name to the parsed config vector. Note that we are
+  // using a raw pointer and not a unique pointer so that we can use the same
+  // vector for multiple names.
+  std::unordered_map<grpc_slice, const ServiceConfigParser::ParsedConfigVector*,
+                     SliceHash>
+      parsed_method_configs_map_;
+  // Default method config.
+  const ServiceConfigParser::ParsedConfigVector* default_method_config_vector_ =
+      nullptr;
+  // Storage for all the vectors that are being used in
+  // parsed_method_configs_table_.
+  absl::InlinedVector<std::unique_ptr<ServiceConfigParser::ParsedConfigVector>,
+                      32>
+      parsed_method_config_vectors_storage_;
+};
+
+}  // namespace grpc_core
+
+#endif /* GRPC_CORE_EXT_SERVICE_CONFIG_SERVICE_CONFIG_H */
diff --git a/src/core/ext/service_config/service_config_call_data.h b/src/core/ext/service_config/service_config_call_data.h
new file mode 100644 (file)
index 0000000..0d3d09d
--- /dev/null
@@ -0,0 +1,72 @@
+//
+// 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.
+//
+
+#ifndef GRPC_CORE_EXT_SERVICE_CONFIG_SERVICE_CONFIG_CALL_DATA_H
+#define GRPC_CORE_EXT_SERVICE_CONFIG_SERVICE_CONFIG_CALL_DATA_H
+
+#include <grpc/support/port_platform.h>
+
+#include <map>
+
+#include "absl/strings/string_view.h"
+
+#include "src/core/ext/service_config/service_config.h"
+#include "src/core/ext/service_config/service_config_parser.h"
+#include "src/core/lib/channel/context.h"
+#include "src/core/lib/gprpp/ref_counted_ptr.h"
+
+namespace grpc_core {
+
+/// Stores the service config data associated with an individual call.
+/// A pointer to this object is stored in the call_context
+/// GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA element, so that filters can
+/// easily access method and global parameters for the call.
+class ServiceConfigCallData {
+ public:
+  using CallAttributes = std::map<const char*, absl::string_view>;
+
+  ServiceConfigCallData() : method_configs_(nullptr) {}
+
+  ServiceConfigCallData(
+      RefCountedPtr<ServiceConfig> service_config,
+      const ServiceConfigParser::ParsedConfigVector* method_configs,
+      CallAttributes call_attributes)
+      : service_config_(std::move(service_config)),
+        method_configs_(method_configs),
+        call_attributes_(std::move(call_attributes)) {}
+
+  ServiceConfig* service_config() { return service_config_.get(); }
+
+  ServiceConfigParser::ParsedConfig* GetMethodParsedConfig(size_t index) const {
+    return method_configs_ != nullptr ? (*method_configs_)[index].get()
+                                      : nullptr;
+  }
+
+  ServiceConfigParser::ParsedConfig* GetGlobalParsedConfig(size_t index) const {
+    return service_config_->GetGlobalParsedConfig(index);
+  }
+
+  const CallAttributes& call_attributes() const { return call_attributes_; }
+
+ private:
+  RefCountedPtr<ServiceConfig> service_config_;
+  const ServiceConfigParser::ParsedConfigVector* method_configs_;
+  CallAttributes call_attributes_;
+};
+
+}  // namespace grpc_core
+
+#endif /* GRPC_CORE_EXT_SERVICE_CONFIG_SERVICE_CONFIG_CALL_DATA_H */
diff --git a/src/core/ext/service_config/service_config_parser.cc b/src/core/ext/service_config/service_config_parser.cc
new file mode 100644 (file)
index 0000000..f649fd7
--- /dev/null
@@ -0,0 +1,89 @@
+//
+// 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 "src/core/ext/service_config/service_config_parser.h"
+
+#include <grpc/support/log.h>
+
+namespace grpc_core {
+
+namespace {
+typedef absl::InlinedVector<std::unique_ptr<ServiceConfigParser::Parser>,
+                            ServiceConfigParser::kNumPreallocatedParsers>
+    ServiceConfigParserList;
+ServiceConfigParserList* g_registered_parsers;
+}  // namespace
+
+void ServiceConfigParserInit() {
+  GPR_ASSERT(g_registered_parsers == nullptr);
+  g_registered_parsers = new ServiceConfigParserList();
+}
+
+void ServiceConfigParserShutdown() {
+  delete g_registered_parsers;
+  g_registered_parsers = nullptr;
+}
+
+size_t ServiceConfigParser::RegisterParser(std::unique_ptr<Parser> parser) {
+  g_registered_parsers->push_back(std::move(parser));
+  return g_registered_parsers->size() - 1;
+}
+
+ServiceConfigParser::ParsedConfigVector
+ServiceConfigParser::ParseGlobalParameters(const grpc_channel_args* args,
+                                           const Json& json,
+                                           grpc_error_handle* error) {
+  ParsedConfigVector parsed_global_configs;
+  std::vector<grpc_error_handle> error_list;
+  for (size_t i = 0; i < g_registered_parsers->size(); i++) {
+    grpc_error_handle parser_error = GRPC_ERROR_NONE;
+    auto parsed_config = (*g_registered_parsers)[i]->ParseGlobalParams(
+        args, json, &parser_error);
+    if (parser_error != GRPC_ERROR_NONE) {
+      error_list.push_back(parser_error);
+    }
+    parsed_global_configs.push_back(std::move(parsed_config));
+  }
+  if (!error_list.empty()) {
+    *error = GRPC_ERROR_CREATE_FROM_VECTOR("Global Params", &error_list);
+  }
+  return parsed_global_configs;
+}
+
+ServiceConfigParser::ParsedConfigVector
+ServiceConfigParser::ParsePerMethodParameters(const grpc_channel_args* args,
+                                              const Json& json,
+                                              grpc_error_handle* error) {
+  ParsedConfigVector parsed_method_configs;
+  std::vector<grpc_error_handle> error_list;
+  for (size_t i = 0; i < g_registered_parsers->size(); i++) {
+    grpc_error_handle parser_error = GRPC_ERROR_NONE;
+    auto parsed_config = (*g_registered_parsers)[i]->ParsePerMethodParams(
+        args, json, &parser_error);
+    if (parser_error != GRPC_ERROR_NONE) {
+      error_list.push_back(parser_error);
+    }
+    parsed_method_configs.push_back(std::move(parsed_config));
+  }
+  if (!error_list.empty()) {
+    *error = GRPC_ERROR_CREATE_FROM_VECTOR("methodConfig", &error_list);
+  }
+  return parsed_method_configs;
+}
+
+}  // namespace grpc_core
diff --git a/src/core/ext/service_config/service_config_parser.h b/src/core/ext/service_config/service_config_parser.h
new file mode 100644 (file)
index 0000000..522ca41
--- /dev/null
@@ -0,0 +1,97 @@
+//
+// 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.
+//
+
+#ifndef GRPC_CORE_EXT_SERVICE_CONFIG_SERVICE_CONFIG_PARSER_H
+#define GRPC_CORE_EXT_SERVICE_CONFIG_SERVICE_CONFIG_PARSER_H
+
+#include <grpc/support/port_platform.h>
+
+#include <memory>
+
+#include "absl/container/inlined_vector.h"
+
+#include <grpc/impl/codegen/grpc_types.h>
+
+#include "src/core/lib/iomgr/error.h"
+#include "src/core/lib/json/json.h"
+
+namespace grpc_core {
+
+// Initialization functions for ServiceConfigParser. ServiceConfigParser should
+// be initialized before any parser implementation is registered.
+void ServiceConfigParserInit();
+void ServiceConfigParserShutdown();
+
+// Service config parser registry.
+// See service_config.h for more information.
+class ServiceConfigParser {
+ public:
+  /// This is the base class that all service config parsers MUST use to store
+  /// parsed service config data.
+  class ParsedConfig {
+   public:
+    virtual ~ParsedConfig() = default;
+  };
+
+  /// This is the base class that all service config parsers should derive from.
+  class Parser {
+   public:
+    virtual ~Parser() = default;
+
+    virtual std::unique_ptr<ParsedConfig> ParseGlobalParams(
+        const grpc_channel_args*, const Json& /* json */,
+        grpc_error_handle* error) {
+      // Avoid unused parameter warning on debug-only parameter
+      (void)error;
+      GPR_DEBUG_ASSERT(error != nullptr);
+      return nullptr;
+    }
+
+    virtual std::unique_ptr<ParsedConfig> ParsePerMethodParams(
+        const grpc_channel_args*, const Json& /* json */,
+        grpc_error_handle* error) {
+      // Avoid unused parameter warning on debug-only parameter
+      (void)error;
+      GPR_DEBUG_ASSERT(error != nullptr);
+      return nullptr;
+    }
+  };
+
+  static constexpr int kNumPreallocatedParsers = 4;
+  typedef absl::InlinedVector<std::unique_ptr<ParsedConfig>,
+                              kNumPreallocatedParsers>
+      ParsedConfigVector;
+
+  /// Globally register a service config parser. On successful registration, it
+  /// returns the index at which the parser was registered. On failure, -1 is
+  /// returned. Each new service config update will go through all the
+  /// registered parser. Each parser is responsible for reading the service
+  /// config json and returning a parsed config. This parsed config can later be
+  /// retrieved using the same index that was returned at registration time.
+  static size_t RegisterParser(std::unique_ptr<Parser> parser);
+
+  static ParsedConfigVector ParseGlobalParameters(const grpc_channel_args* args,
+                                                  const Json& json,
+                                                  grpc_error_handle* error);
+
+  static ParsedConfigVector ParsePerMethodParameters(
+      const grpc_channel_args* args, const Json& json,
+      grpc_error_handle* error);
+};
+
+}  // namespace grpc_core
+
+#endif /* GRPC_CORE_EXT_SERVICE_CONFIG_SERVICE_CONFIG_PARSER_H */
diff --git a/src/core/ext/transport/binder/client/BUILD b/src/core/ext/transport/binder/client/BUILD
deleted file mode 100644 (file)
index 42abe0d..0000000
+++ /dev/null
@@ -1,76 +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.
-
-load("//bazel:grpc_build_system.bzl", "grpc_cc_library")
-
-licenses(["notice"])
-
-package(
-    default_visibility = ["//visibility:public"],
-    features = [
-        "layering_check",
-    ],
-)
-
-# TODO(mingcl): See if it is possible to add flags that warns about undefined symbol at link time
-grpc_cc_library(
-    name = "grpc_transport_binder_client",
-    srcs = [
-        "channel_create.cc",
-        "channel_create.h",
-        "jni_utils.cc",
-    ],
-    hdrs = [
-        "channel_create.h",
-        "jni_utils.h",
-    ],
-    external_deps = [
-        "absl/strings",
-        "absl/time",
-    ],
-    deps = [
-        ":grpc_transport_binder_client_impl",
-        "//:gpr",
-        "//:gpr_base",
-        "//:gpr_platform",
-        "//:grpc",
-        "//:grpc++_base",
-        "//:grpc_base",
-        "//:grpc_base_c",
-        "//:grpc_codegen",
-        "//src/core/ext/transport/binder/transport:binder_transport",
-        "//src/core/ext/transport/binder/utils:transport_stream_receiver",
-        "//src/core/ext/transport/binder/wire_format:binder_android",
-        "//src/core/ext/transport/binder/wire_format:wire_reader",
-    ],
-)
-
-grpc_cc_library(
-    name = "grpc_transport_binder_client_impl",
-    srcs = ["channel_create_impl.cc"],
-    hdrs = ["channel_create_impl.h"],
-    external_deps = [],
-    deps = [
-        "//:gpr",
-        "//:gpr_base",
-        "//:gpr_platform",
-        "//:grpc",
-        "//:grpc++_base",
-        "//:grpc_base",
-        "//:grpc_base_c",
-        "//:grpc_codegen",
-        "//src/core/ext/transport/binder/transport:binder_transport",
-        "//src/core/ext/transport/binder/wire_format:binder",
-    ],
-)
diff --git a/src/core/ext/transport/binder/client/binder_connector.cc b/src/core/ext/transport/binder/client/binder_connector.cc
new file mode 100644 (file)
index 0000000..6238d06
--- /dev/null
@@ -0,0 +1,134 @@
+// 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 <grpc/support/port_platform.h>
+
+#ifndef GRPC_NO_BINDER
+
+#include "src/core/ext/transport/binder/client/binder_connector.h"
+#include "src/core/lib/iomgr/port.h"
+
+#ifdef GRPC_HAVE_UNIX_SOCKET
+#include <sys/un.h>
+#endif
+
+#include <functional>
+#include <map>
+
+#include <grpcpp/security/binder_security_policy.h>
+
+#include "src/core/ext/filters/client_channel/connector.h"
+#include "src/core/ext/filters/client_channel/subchannel.h"
+#include "src/core/ext/transport/binder/client/endpoint_binder_pool.h"
+#include "src/core/ext/transport/binder/client/security_policy_setting.h"
+#include "src/core/ext/transport/binder/transport/binder_transport.h"
+#include "src/core/ext/transport/binder/wire_format/binder.h"
+
+namespace {
+
+// TODO(mingcl): Currently this does no error handling and assumes the
+// connection always succeeds in reasonable amount of time.
+class BinderConnector : public grpc_core::SubchannelConnector {
+ public:
+  BinderConnector() {}
+  ~BinderConnector() override {}
+  void Connect(const Args& args, Result* result,
+               grpc_closure* notify) override {
+#ifdef GRPC_HAVE_UNIX_SOCKET
+    {
+      struct sockaddr_un* un =
+          reinterpret_cast<struct sockaddr_un*>(args.address->addr);
+      // length of identifier, including null terminator
+      size_t id_length = args.address->len - sizeof(un->sun_family);
+      // The c-style string at least will have a null terminator, and the
+      // connection id itself should not be empty
+      GPR_ASSERT(id_length >= 2);
+      // Make sure there is null terminator at the expected location before
+      // reading from it
+      GPR_ASSERT(un->sun_path[id_length - 1] == '\0');
+      conn_id_ = un->sun_path;
+    }
+#else
+    GPR_ASSERT(0);
+#endif
+    gpr_log(GPR_ERROR, "conn_id_ = %s", conn_id_.c_str());
+
+    args_ = args;
+    GPR_ASSERT(notify_ == nullptr);
+    GPR_ASSERT(notify != nullptr);
+    notify_ = notify;
+    result_ = result;
+
+    Ref().release();  // Ref held by the following callback
+
+    grpc_binder::GetEndpointBinderPool()->GetEndpointBinder(
+        conn_id_,
+        std::bind(&BinderConnector::OnConnected, this, std::placeholders::_1));
+  }
+
+  void OnConnected(std::unique_ptr<grpc_binder::Binder> endpoint_binder) {
+    GPR_ASSERT(endpoint_binder != nullptr);
+    grpc_transport* transport = grpc_create_binder_transport_client(
+        std::move(endpoint_binder),
+        grpc_binder::GetSecurityPolicySetting()->Get(conn_id_));
+    GPR_ASSERT(transport != nullptr);
+    result_->channel_args = grpc_channel_args_copy(args_.channel_args);
+    result_->transport = transport;
+
+    GPR_ASSERT(notify_ != nullptr);
+    // ExecCtx is required here for running grpc_closure because this callback
+    // might be invoked from non-gRPC code
+    if (grpc_core::ExecCtx::Get() == nullptr) {
+      grpc_core::ExecCtx exec_ctx;
+      grpc_core::ExecCtx::Run(DEBUG_LOCATION, notify_, GRPC_ERROR_NONE);
+    } else {
+      grpc_core::ExecCtx::Run(DEBUG_LOCATION, notify_, GRPC_ERROR_NONE);
+    }
+
+    Unref();  // Was referenced in BinderConnector::Connect
+  }
+  void Shutdown(grpc_error_handle error) override { (void)error; }
+
+ private:
+  Args args_;
+  grpc_closure* notify_ = nullptr;
+  Result* result_ = nullptr;
+
+  std::string conn_id_;
+};
+
+}  // namespace
+
+namespace grpc_core {
+
+grpc_core::RefCountedPtr<grpc_core::Subchannel>
+BinderClientChannelFactory::CreateSubchannel(
+    const grpc_resolved_address& address, const grpc_channel_args* args) {
+  gpr_log(GPR_ERROR, "BinderClientChannelFactory::CreateSubchannel called");
+  grpc_arg default_authority_arg = grpc_channel_arg_string_create(
+      const_cast<char*>(GRPC_ARG_DEFAULT_AUTHORITY),
+      const_cast<char*>("binder.authority"));
+  grpc_channel_args* new_args =
+      grpc_channel_args_copy_and_add(args, &default_authority_arg, 1);
+
+  grpc_core::RefCountedPtr<grpc_core::Subchannel> s =
+      grpc_core::Subchannel::Create(
+          grpc_core::MakeOrphanable<BinderConnector>(), address, new_args);
+
+  return s;
+}
+
+}  // namespace grpc_core
+
+#endif  // GRPC_NO_BINDER
diff --git a/src/core/ext/transport/binder/client/binder_connector.h b/src/core/ext/transport/binder/client/binder_connector.h
new file mode 100644 (file)
index 0000000..a5fd6f0
--- /dev/null
@@ -0,0 +1,44 @@
+// 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.
+
+#ifndef GRPC_CORE_EXT_TRANSPORT_BINDER_CLIENT_BINDER_CONNECTOR_H
+#define GRPC_CORE_EXT_TRANSPORT_BINDER_CLIENT_BINDER_CONNECTOR_H
+
+#include <grpc/support/port_platform.h>
+
+#include <memory>
+#include <utility>
+
+#include "absl/strings/string_view.h"
+#include "absl/strings/strip.h"
+
+#include <grpc/impl/codegen/grpc_types.h>
+#include <grpcpp/channel.h>
+#include <grpcpp/support/channel_arguments.h>
+
+#include "src/core/ext/filters/client_channel/client_channel.h"
+#include "src/core/ext/filters/client_channel/client_channel_factory.h"
+
+namespace grpc_core {
+
+class BinderClientChannelFactory : public grpc_core::ClientChannelFactory {
+ public:
+  grpc_core::RefCountedPtr<grpc_core::Subchannel> CreateSubchannel(
+      const grpc_resolved_address& address,
+      const grpc_channel_args* args) override;
+};
+
+}  // namespace grpc_core
+
+#endif  // GRPC_CORE_EXT_TRANSPORT_BINDER_CLIENT_BINDER_CONNECTOR_H
index cfbe336..482efa6 100644 (file)
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
+
+#ifndef GRPC_NO_BINDER
 
-#include "src/core/ext/transport/binder/client/channel_create.h"
+#include <grpcpp/create_channel_binder.h>
 
 // The interface is only defined if GPR_ANDROID is defined, because some
 // arguments requires JNI.
 #include <grpc/support/log.h>
 #include <grpcpp/impl/grpc_library.h>
 
+#include "src/core/ext/filters/client_channel/client_channel.h"
 #include "src/core/ext/transport/binder/client/channel_create_impl.h"
+#include "src/core/ext/transport/binder/client/connection_id_generator.h"
+#include "src/core/ext/transport/binder/client/endpoint_binder_pool.h"
 #include "src/core/ext/transport/binder/client/jni_utils.h"
+#include "src/core/ext/transport/binder/client/security_policy_setting.h"
 #include "src/core/ext/transport/binder/transport/binder_transport.h"
 #include "src/core/ext/transport/binder/wire_format/binder.h"
 #include "src/core/ext/transport/binder/wire_format/binder_android.h"
+#include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/surface/channel.h"
 #include "src/core/lib/transport/transport.h"
 #include "src/cpp/client/create_channel_internal.h"
 namespace grpc {
 namespace experimental {
 
-// This should be called before calling CreateBinderChannel
-// TODO(mingcl): Invoke a callback and pass binder object to caller after a
-// successful bind
-void BindToOnDeviceServerService(void* jni_env_void, jobject application,
-                                 absl::string_view package_name,
-                                 absl::string_view class_name) {
-  // Init gRPC library first so gpr_log works
-  grpc::internal::GrpcLibrary init_lib;
-  init_lib.init();
-
-  JNIEnv* jni_env = static_cast<JNIEnv*>(jni_env_void);
-
-  // clang-format off
-  grpc_binder::CallStaticJavaMethod(jni_env,
-                       "io/grpc/binder/cpp/NativeConnectionHelper",
-                       "tryEstablishConnection",
-                       "(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;)V",
-                       application, std::string(package_name), std::string(class_name));
-  // clang-format on
-}
-
-// BindToOndeviceServerService need to be called before this, in a different
-// task (due to Android API design). (Reference:
-// https://stackoverflow.com/a/3055749)
-// TODO(mingcl): Support multiple endpoint binder objects
 std::shared_ptr<grpc::Channel> CreateBinderChannel(
     void* jni_env_void, jobject application, absl::string_view package_name,
-    absl::string_view class_name) {
+    absl::string_view class_name,
+    std::shared_ptr<grpc::experimental::binder::SecurityPolicy>
+        security_policy) {
   return CreateCustomBinderChannel(jni_env_void, application, package_name,
-                                   class_name, ChannelArguments());
+                                   class_name, security_policy,
+                                   ChannelArguments());
 }
 
-// BindToOndeviceServerService need to be called before this, in a different
-// task (due to Android API design). (Reference:
-// https://stackoverflow.com/a/3055749)
-// TODO(mingcl): Support multiple endpoint binder objects
 std::shared_ptr<grpc::Channel> CreateCustomBinderChannel(
-    void* jni_env_void, jobject /*application*/,
-    absl::string_view /*package_name*/, absl::string_view /*class_name*/,
+    void* jni_env_void, jobject application, absl::string_view package_name,
+    absl::string_view class_name,
+    std::shared_ptr<grpc::experimental::binder::SecurityPolicy> security_policy,
     const ChannelArguments& args) {
-  JNIEnv* jni_env = static_cast<JNIEnv*>(jni_env_void);
+  grpc::internal::GrpcLibrary init_lib;
+  init_lib.init();
 
+  GPR_ASSERT(jni_env_void != nullptr);
+  GPR_ASSERT(security_policy != nullptr);
+
+  std::string connection_id = grpc_binder::GetConnectionIdGenerator()->Generate(
+      std::string(package_name), std::string(class_name));
+
+  // After invoking this Java method, Java code will put endpoint binder into
+  // `EndpointBinderPool` after the connection succeeds
+  // TODO(mingcl): Consider if we want to delay the connection establishment
+  // until SubchannelConnector start establishing connection. For now we don't
+  // see any benifits doing that.
   // clang-format off
-  jobject object = grpc_binder::CallStaticJavaMethodForObject(
-      jni_env,
-      "io/grpc/binder/cpp/NativeConnectionHelper",
-      "getServiceBinder",
-      "()Landroid/os/IBinder;");
+  grpc_binder::CallStaticJavaMethod(static_cast<JNIEnv*>(jni_env_void),
+                       "io/grpc/binder/cpp/NativeConnectionHelper",
+                       "tryEstablishConnection",
+                       "(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V",
+                       application, std::string(package_name), std::string(class_name), connection_id);
   // clang-format on
 
+  // Set server URI to a URI that contains connection id. The URI will be used
+  // by subchannel connector to obtain correct endpoint binder from
+  // `EndpointBinderPool`.
   grpc_channel_args channel_args;
   args.SetChannelArgs(&channel_args);
-  return CreateChannelInternal(
-      "",
-      ::grpc::internal::CreateChannelFromBinderImpl(
-          absl::make_unique<grpc_binder::BinderAndroid>(
-              grpc_binder::FromJavaBinder(jni_env, object)),
-          &channel_args),
+  grpc_channel_args* new_args;
+  {
+    grpc_arg server_uri_arg = grpc_channel_arg_string_create(
+        const_cast<char*>(GRPC_ARG_SERVER_URI),
+        const_cast<char*>(("binder:" + connection_id).c_str()));
+    const char* to_remove[] = {GRPC_ARG_SERVER_URI};
+    new_args = grpc_channel_args_copy_and_add_and_remove(
+        &channel_args, to_remove, 1, &server_uri_arg, 1);
+  }
+
+  grpc_binder::GetSecurityPolicySetting()->Set(connection_id, security_policy);
+
+  auto channel = CreateChannelInternal(
+      "", ::grpc::internal::CreateClientBinderChannelImpl(new_args),
       std::vector<
           std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>());
+
+  grpc_channel_args_destroy(new_args);
+
+  return channel;
 }
 
 }  // namespace experimental
@@ -130,15 +139,16 @@ void BindToOnDeviceServerService(void*, jobject, absl::string_view,
   GPR_ASSERT(0);
 }
 
-std::shared_ptr<grpc::Channel> CreateBinderChannel(void*, jobject,
-                                                   absl::string_view,
-                                                   absl::string_view) {
+std::shared_ptr<grpc::Channel> CreateBinderChannel(
+    void*, jobject, absl::string_view, absl::string_view,
+    std::shared_ptr<grpc::experimental::binder::SecurityPolicy>) {
   GPR_ASSERT(0);
   return {};
 }
 
 std::shared_ptr<grpc::Channel> CreateCustomBinderChannel(
     void*, jobject, absl::string_view, absl::string_view,
+    std::shared_ptr<grpc::experimental::binder::SecurityPolicy>,
     const ChannelArguments&) {
   GPR_ASSERT(0);
   return {};
@@ -150,3 +160,5 @@ std::shared_ptr<grpc::Channel> CreateCustomBinderChannel(
 #endif  // GPR_SUPPORT_BINDER_TRANSPORT
 
 #endif  // GPR_ANDROID
+
+#endif  // GRPC_NO_BINDER
diff --git a/src/core/ext/transport/binder/client/channel_create.h b/src/core/ext/transport/binder/client/channel_create.h
deleted file mode 100644 (file)
index e53ccc4..0000000
+++ /dev/null
@@ -1,60 +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.
-
-#ifndef GRPC_CORE_EXT_TRANSPORT_BINDER_CLIENT_CHANNEL_CREATE_H
-#define GRPC_CORE_EXT_TRANSPORT_BINDER_CLIENT_CHANNEL_CREATE_H
-
-#include <grpc/impl/codegen/port_platform.h>
-
-#ifdef GPR_ANDROID
-
-#include <grpc/support/port_platform.h>
-
-#include <jni.h>
-
-#include "absl/strings/string_view.h"
-
-#include <grpc/impl/codegen/grpc_types.h>
-#include <grpcpp/channel.h>
-#include <grpcpp/support/channel_arguments.h>
-
-namespace grpc {
-namespace experimental {
-
-// This need be called before calling CreateBinderChannel, and the thread need
-// to be free before invoking CreateBinderChannel.
-// TODO(mingcl): Add more explanation on this after we determine the interfaces.
-void BindToOnDeviceServerService(void* jni_env_void, jobject application,
-                                 absl::string_view /*package_name*/,
-                                 absl::string_view /*class_name*/);
-
-// Need to be invoked after BindToOnDeviceServerService
-// Create a new Channel from server package name and service class name
-std::shared_ptr<grpc::Channel> CreateBinderChannel(
-    void* jni_env_void, jobject application, absl::string_view package_name,
-    absl::string_view class_name);
-
-// Need to be invoked after BindToOnDeviceServerService
-// Create a new Channel from server package name and service class name and with
-// custom channel arguments.
-std::shared_ptr<grpc::Channel> CreateCustomBinderChannel(
-    void* jni_env_void, jobject application, absl::string_view package_name,
-    absl::string_view class_name, const ChannelArguments& args);
-
-}  // namespace experimental
-}  // namespace grpc
-
-#endif
-
-#endif  // GRPC_CORE_EXT_TRANSPORT_BINDER_CLIENT_CHANNEL_CREATE_H
index bde2afc..a3fb6a4 100644 (file)
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include "src/core/ext/transport/binder/client/channel_create_impl.h"
 
+#ifndef GRPC_NO_BINDER
+
 #include <memory>
 #include <utility>
 
+#include "src/core/ext/transport/binder/client/binder_connector.h"
 #include "src/core/ext/transport/binder/transport/binder_transport.h"
 #include "src/core/ext/transport/binder/wire_format/binder.h"
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/surface/api_trace.h"
 #include "src/core/lib/surface/channel.h"
 
+namespace {
+
+grpc_core::BinderClientChannelFactory* g_factory;
+gpr_once g_factory_once = GPR_ONCE_INIT;
+
+void FactoryInit() { g_factory = new grpc_core::BinderClientChannelFactory(); }
+}  // namespace
+
 namespace grpc {
 namespace internal {
 
-grpc_channel* CreateChannelFromBinderImpl(
+grpc_channel* CreateDirectBinderChannelImplForTesting(
     std::unique_ptr<grpc_binder::Binder> endpoint_binder,
-    const grpc_channel_args* args) {
+    const grpc_channel_args* args,
+    std::shared_ptr<grpc::experimental::binder::SecurityPolicy>
+        security_policy) {
   grpc_core::ExecCtx exec_ctx;
-  GRPC_API_TRACE("grpc_channel_create_from_binder(target=%p, args=%p)", 2,
-                 ((void*)1234, args));
 
-  grpc_transport* transport =
-      grpc_create_binder_transport_client(std::move(endpoint_binder));
-  GPR_ASSERT(transport);
+  grpc_transport* transport = grpc_create_binder_transport_client(
+      std::move(endpoint_binder), security_policy);
+  GPR_ASSERT(transport != nullptr);
 
-  // TODO(b/192207753): check binder alive and ping binder
-
-  // TODO(b/192207758): Figure out if we are required to set authority here
   grpc_arg default_authority_arg = grpc_channel_arg_string_create(
       const_cast<char*>(GRPC_ARG_DEFAULT_AUTHORITY),
-      const_cast<char*>("test.authority"));
+      const_cast<char*>("binder.authority"));
   grpc_channel_args* final_args =
       grpc_channel_args_copy_and_add(args, &default_authority_arg, 1);
   grpc_error_handle error = GRPC_ERROR_NONE;
   grpc_channel* channel = grpc_channel_create(
       "binder_target_placeholder", final_args, GRPC_CLIENT_DIRECT_CHANNEL,
       transport, nullptr, 0, &error);
-  // TODO(mingcl): Handle error properly
   GPR_ASSERT(error == GRPC_ERROR_NONE);
   grpc_channel_args_destroy(final_args);
   return channel;
 }
 
+grpc_channel* CreateClientBinderChannelImpl(const grpc_channel_args* args) {
+  grpc_core::ExecCtx exec_ctx;
+
+  gpr_once_init(&g_factory_once, FactoryInit);
+
+  // Set channel factory argument
+  grpc_arg channel_factory_arg =
+      grpc_core::ClientChannelFactory::CreateChannelArg(g_factory);
+  const char* arg_to_remove = channel_factory_arg.key;
+  grpc_channel_args* new_args = grpc_channel_args_copy_and_add_and_remove(
+      args, &arg_to_remove, 1, &channel_factory_arg, 1);
+
+  grpc_error_handle error = GRPC_ERROR_NONE;
+
+  grpc_channel* channel =
+      grpc_channel_create("binder_channel_target_placeholder", new_args,
+                          GRPC_CLIENT_CHANNEL, nullptr, nullptr, 0, &error);
+
+  // Clean up.
+  grpc_channel_args_destroy(new_args);
+  if (channel == nullptr) {
+    intptr_t integer;
+    grpc_status_code status = GRPC_STATUS_INTERNAL;
+    if (grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, &integer)) {
+      status = static_cast<grpc_status_code>(integer);
+    }
+    GRPC_ERROR_UNREF(error);
+    channel = grpc_lame_client_channel_create(
+        "binder_channel_target_placeholder", status,
+        "Failed to create binder channel");
+  }
+
+  return channel;
+}
+
 }  // namespace internal
 }  // namespace grpc
+#endif
index 017d5b2..d48fa22 100644 (file)
@@ -15,7 +15,9 @@
 #ifndef GRPC_CORE_EXT_TRANSPORT_BINDER_CLIENT_CHANNEL_CREATE_IMPL_H
 #define GRPC_CORE_EXT_TRANSPORT_BINDER_CLIENT_CHANNEL_CREATE_IMPL_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
+
+#include <grpcpp/security/binder_security_policy.h>
 
 #include "src/core/ext/transport/binder/wire_format/binder.h"
 #include "src/core/lib/channel/channel_args.h"
 namespace grpc {
 namespace internal {
 
-grpc_channel* CreateChannelFromBinderImpl(
+// Creates a GRPC_CLIENT_DIRECT_CHANNEL channel from endpoint binder
+// At this moment this is only used for testing.
+grpc_channel* CreateDirectBinderChannelImplForTesting(
     std::unique_ptr<grpc_binder::Binder> endpoint_binder,
-    const grpc_channel_args* args);
+    const grpc_channel_args* args,
+    std::shared_ptr<grpc::experimental::binder::SecurityPolicy>
+        security_policy);
+
+// Creates a GRPC_CLIENT_CHANNEL channel
+grpc_channel* CreateClientBinderChannelImpl(const grpc_channel_args* args);
 
 }  // namespace internal
 }  // namespace grpc
diff --git a/src/core/ext/transport/binder/client/connection_id_generator.cc b/src/core/ext/transport/binder/client/connection_id_generator.cc
new file mode 100644 (file)
index 0000000..f957a7a
--- /dev/null
@@ -0,0 +1,70 @@
+// 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 <grpc/support/port_platform.h>
+
+#include "src/core/ext/transport/binder/client/connection_id_generator.h"
+
+#ifndef GRPC_NO_BINDER
+
+#include "absl/strings/str_cat.h"
+
+namespace {
+// Make sure `s` does not contain characters other than numbers, alphabets,
+// period and underscore
+std::string Normalize(absl::string_view str_view) {
+  std::string s = std::string(str_view);
+  for (size_t i = 0; i < s.length(); i++) {
+    if (!isalnum(s[i]) && s[i] != '.') {
+      s[i] = '_';
+    }
+  }
+  return s;
+}
+
+// Remove prefix of the string if the string is longer than len
+std::string StripToLength(const std::string& s, size_t len) {
+  if (s.length() > len) {
+    return s.substr(s.length() - len, len);
+  }
+  return s;
+}
+}  // namespace
+
+namespace grpc_binder {
+
+std::string ConnectionIdGenerator::Generate(absl::string_view package_name,
+                                            absl::string_view class_name) {
+  // reserve some room for serial number
+  const size_t kReserveForNumbers = 15;
+  std::string s = StripToLength(
+      absl::StrCat(Normalize(package_name), "-", Normalize(class_name)),
+      kPathLengthLimit - kReserveForNumbers);
+  std::string ret;
+  {
+    grpc_core::MutexLock l(&m_);
+    // Insert a hyphen before serial number
+    ret = absl::StrCat(s, "-", ++count_);
+  }
+  GPR_ASSERT(ret.length() < kPathLengthLimit);
+  return ret;
+}
+
+ConnectionIdGenerator* GetConnectionIdGenerator() {
+  static ConnectionIdGenerator* cig = new ConnectionIdGenerator();
+  return cig;
+}
+
+}  // namespace grpc_binder
+#endif
diff --git a/src/core/ext/transport/binder/client/connection_id_generator.h b/src/core/ext/transport/binder/client/connection_id_generator.h
new file mode 100644 (file)
index 0000000..543e67e
--- /dev/null
@@ -0,0 +1,52 @@
+// 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.
+
+#ifndef GRPC_CORE_EXT_TRANSPORT_BINDER_CLIENT_CONNECTION_ID_GENERATOR_H
+#define GRPC_CORE_EXT_TRANSPORT_BINDER_CLIENT_CONNECTION_ID_GENERATOR_H
+
+#include <grpc/support/port_platform.h>
+
+#include <map>
+
+#include "absl/strings/string_view.h"
+
+#include "src/core/lib/gprpp/sync.h"
+
+namespace grpc_binder {
+
+// Generates somewhat human-readable unique identifiers from package name and
+// class name. We will generate a Id that only contains unreserved URI
+// characters (uppercase and lowercase letters, decimal digits, hyphen, period,
+// underscore, and tilde).
+class ConnectionIdGenerator {
+ public:
+  std::string Generate(absl::string_view package_name,
+                       absl::string_view class_name);
+
+ private:
+  // Our generated Id need to fit in unix socket path length limit. We use 100
+  // here to be safe.
+  const size_t kPathLengthLimit = 100;
+
+  grpc_core::Mutex m_;
+  // Every generated identifier will followed by the value of this counter to
+  // make sure every generated id is unique.
+  int count_ ABSL_GUARDED_BY(m_);
+};
+
+ConnectionIdGenerator* GetConnectionIdGenerator();
+
+}  // namespace grpc_binder
+
+#endif  // GRPC_CORE_EXT_TRANSPORT_BINDER_CLIENT_CONNECTION_ID_GENERATOR_H
diff --git a/src/core/ext/transport/binder/client/endpoint_binder_pool.cc b/src/core/ext/transport/binder/client/endpoint_binder_pool.cc
new file mode 100644 (file)
index 0000000..7ae7818
--- /dev/null
@@ -0,0 +1,111 @@
+// 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 <grpc/support/port_platform.h>
+
+#include "src/core/ext/transport/binder/client/endpoint_binder_pool.h"
+
+#ifndef GRPC_NO_BINDER
+
+#include "src/core/ext/transport/binder/client/jni_utils.h"
+
+#ifdef GPR_SUPPORT_BINDER_TRANSPORT
+
+#include <jni.h>
+
+#include "src/core/ext/transport/binder/wire_format/binder_android.h"
+
+extern "C" {
+// Adds endpoint binder to binder pool when Java notify us that the endpoint
+// binder is ready. This is called from GrpcBinderConnection.java
+JNIEXPORT void JNICALL
+Java_io_grpc_binder_cpp_GrpcBinderConnection_notifyConnected__Ljava_lang_String_2Landroid_os_IBinder_2(
+    JNIEnv* jni_env, jobject, jstring conn_id_jstring, jobject ibinder) {
+  jboolean isCopy;
+  const char* conn_id = jni_env->GetStringUTFChars(conn_id_jstring, &isCopy);
+  gpr_log(GPR_ERROR, "%s called with conn_id = %s", __func__, conn_id);
+  GPR_ASSERT(ibinder != nullptr);
+  ndk::SpAIBinder aibinder = grpc_binder::FromJavaBinder(jni_env, ibinder);
+  gpr_log(GPR_ERROR, "aibinder = %p", aibinder.get());
+  auto b = absl::make_unique<grpc_binder::BinderAndroid>(aibinder);
+  GPR_ASSERT(b != nullptr);
+  grpc_binder::GetEndpointBinderPool()->AddEndpointBinder(conn_id,
+                                                          std::move(b));
+  if (isCopy == JNI_TRUE) {
+    jni_env->ReleaseStringUTFChars(conn_id_jstring, conn_id);
+  }
+}
+}
+
+#endif  // GPR_SUPPORT_BINDER_TRANSPORT
+
+namespace grpc_binder {
+
+void EndpointBinderPool ::GetEndpointBinder(
+    std::string conn_id,
+    std::function<void(std::unique_ptr<grpc_binder::Binder>)> cb) {
+  gpr_log(GPR_ERROR, "GetEndpointBinder %s", conn_id.c_str());
+  std::unique_ptr<grpc_binder::Binder> b;
+  {
+    grpc_core::MutexLock l(&m_);
+    if (binder_map_.count(conn_id)) {
+      b = std::move(binder_map_[conn_id]);
+      binder_map_.erase(conn_id);
+      GPR_ASSERT(b != nullptr);
+    } else {
+      if (pending_requests_.count(conn_id) != 0) {
+        gpr_log(GPR_ERROR, "Duplicate GetEndpointBinder request. conn_id = %s",
+                conn_id.c_str());
+        return;
+      }
+      pending_requests_[conn_id] = std::move(cb);
+      return;
+    }
+  }
+  GPR_ASSERT(b != nullptr);
+  cb(std::move(b));
+}
+
+void EndpointBinderPool::AddEndpointBinder(
+    std::string conn_id, std::unique_ptr<grpc_binder::Binder> b) {
+  gpr_log(GPR_ERROR, "AddEndpointBinder %s", conn_id.c_str());
+  GPR_ASSERT(b != nullptr);
+  // cb will be set in the following block if there is a pending callback
+  std::function<void(std::unique_ptr<grpc_binder::Binder>)> cb = nullptr;
+  {
+    grpc_core::MutexLock l(&m_);
+    if (binder_map_.count(conn_id) != 0) {
+      gpr_log(GPR_ERROR, "EndpointBinder already in the pool. conn_id = %s",
+              conn_id.c_str());
+      return;
+    }
+    if (pending_requests_.count(conn_id)) {
+      cb = std::move(pending_requests_[conn_id]);
+      pending_requests_.erase(conn_id);
+    } else {
+      binder_map_[conn_id] = std::move(b);
+      b = nullptr;
+    }
+  }
+  if (cb != nullptr) {
+    cb(std::move(b));
+  }
+}
+
+EndpointBinderPool* GetEndpointBinderPool() {
+  static EndpointBinderPool* p = new EndpointBinderPool();
+  return p;
+}
+}  // namespace grpc_binder
+#endif
diff --git a/src/core/ext/transport/binder/client/endpoint_binder_pool.h b/src/core/ext/transport/binder/client/endpoint_binder_pool.h
new file mode 100644 (file)
index 0000000..9d19e72
--- /dev/null
@@ -0,0 +1,65 @@
+// 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.
+
+#ifndef GRPC_CORE_EXT_TRANSPORT_BINDER_CLIENT_ENDPOINT_BINDER_POOL_H
+#define GRPC_CORE_EXT_TRANSPORT_BINDER_CLIENT_ENDPOINT_BINDER_POOL_H
+
+#include <grpc/support/port_platform.h>
+
+#include <functional>
+#include <string>
+
+#include "absl/container/flat_hash_map.h"
+
+#include "src/core/ext/transport/binder/wire_format/binder.h"
+#include "src/core/lib/gprpp/sync.h"
+
+namespace grpc_binder {
+
+// This class serves as a buffer of endpoint binders between C++ and
+// Java. `AddEndpointBinder` will be indirectly invoked by Java code, and
+// `GetEndpointBinder` is for C++ code to register callback to get endpoint
+// binder when become available. This simplifies JNI related threading issues
+// since both side only need to interact with this buffer in non-blocking
+// manner and avoids cross-language callbacks.
+class EndpointBinderPool {
+ public:
+  // Invokes the callback when the binder corresponding to the conn_id become
+  // available. If the binder is already available, invokes the callback
+  // immediately.
+  // Ownership of the endpoint binder will be transferred to the callback
+  // function and it will be removed from the pool
+  void GetEndpointBinder(
+      std::string conn_id,
+      std::function<void(std::unique_ptr<grpc_binder::Binder>)> cb);
+
+  // Add an endpoint binder to the pool
+  void AddEndpointBinder(std::string conn_id,
+                         std::unique_ptr<grpc_binder::Binder> b);
+
+ private:
+  grpc_core::Mutex m_;
+  absl::flat_hash_map<std::string, std::unique_ptr<grpc_binder::Binder>>
+      binder_map_ ABSL_GUARDED_BY(m_);
+  absl::flat_hash_map<std::string,
+                      std::function<void(std::unique_ptr<grpc_binder::Binder>)>>
+      pending_requests_ ABSL_GUARDED_BY(m_);
+};
+
+// Returns the singleton
+EndpointBinderPool* GetEndpointBinderPool();
+
+}  // namespace grpc_binder
+
+#endif  // GRPC_CORE_EXT_TRANSPORT_BINDER_CLIENT_ENDPOINT_BINDER_POOL_H
index fcdea61..a9ee678 100644 (file)
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include "src/core/ext/transport/binder/client/jni_utils.h"
 
+#ifndef GRPC_NO_BINDER
+
 #include <grpc/support/log.h>
 
 #if defined(ANDROID) || defined(__ANDROID__)
@@ -41,6 +43,25 @@ void CallStaticJavaMethod(JNIEnv* env, const std::string& clazz,
                             env->NewStringUTF(cls.c_str()));
 }
 
+void CallStaticJavaMethod(JNIEnv* env, const std::string& clazz,
+                          const std::string& method, const std::string& type,
+                          jobject application, const std::string& pkg,
+                          const std::string& cls, const std::string& conn_id) {
+  jclass cl = env->FindClass(clazz.c_str());
+  if (cl == nullptr) {
+    gpr_log(GPR_ERROR, "No class %s", clazz.c_str());
+  }
+
+  jmethodID mid = env->GetStaticMethodID(cl, method.c_str(), type.c_str());
+  if (mid == nullptr) {
+    gpr_log(GPR_ERROR, "No method id %s", method.c_str());
+  }
+
+  env->CallStaticVoidMethod(
+      cl, mid, application, env->NewStringUTF(pkg.c_str()),
+      env->NewStringUTF(cls.c_str()), env->NewStringUTF(conn_id.c_str()));
+}
+
 jobject CallStaticJavaMethodForObject(JNIEnv* env, const std::string& clazz,
                                       const std::string& method,
                                       const std::string& type) {
@@ -68,3 +89,4 @@ jobject CallStaticJavaMethodForObject(JNIEnv* env, const std::string& clazz,
 }  // namespace grpc_binder
 
 #endif
+#endif
index b7c55d4..ea884ed 100644 (file)
@@ -17,7 +17,7 @@
 
 #if defined(ANDROID) || defined(__ANDROID__)
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include <jni.h>
 
 
 namespace grpc_binder {
 
-// TODO(mingcl): Use string_view
 // For now we hard code the arguments of the Java function because this is only
 // used to call that single function.
 void CallStaticJavaMethod(JNIEnv* env, const std::string& clazz,
                           const std::string& method, const std::string& type,
                           jobject application, const std::string& pkg,
                           const std::string& cls);
+void CallStaticJavaMethod(JNIEnv* env, const std::string& clazz,
+                          const std::string& method, const std::string& type,
+                          jobject application, const std::string& pkg,
+                          const std::string& cls, const std::string& conn_id);
 
 jobject CallStaticJavaMethodForObject(JNIEnv* env, const std::string& clazz,
                                       const std::string& method,
diff --git a/src/core/ext/transport/binder/client/security_policy_setting.cc b/src/core/ext/transport/binder/client/security_policy_setting.cc
new file mode 100644 (file)
index 0000000..d873914
--- /dev/null
@@ -0,0 +1,45 @@
+// 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 <grpc/support/port_platform.h>
+
+#ifndef GRPC_NO_BINDER
+
+#include "src/core/ext/transport/binder/client/security_policy_setting.h"
+
+namespace grpc_binder {
+
+void SecurityPolicySetting::Set(
+    absl::string_view connection_id,
+    std::shared_ptr<grpc::experimental::binder::SecurityPolicy>
+        security_policy) {
+  grpc_core::MutexLock l(&m_);
+  GPR_ASSERT(security_policy_map_.count(std::string(connection_id)) == 0);
+  security_policy_map_[std::string(connection_id)] = security_policy;
+}
+
+std::shared_ptr<grpc::experimental::binder::SecurityPolicy>
+SecurityPolicySetting::Get(absl::string_view connection_id) {
+  grpc_core::MutexLock l(&m_);
+  GPR_ASSERT(security_policy_map_.count(std::string(connection_id)) != 0);
+  return security_policy_map_[std::string(connection_id)];
+}
+
+SecurityPolicySetting* GetSecurityPolicySetting() {
+  static SecurityPolicySetting* s = new SecurityPolicySetting();
+  return s;
+}
+
+}  // namespace grpc_binder
+#endif
diff --git a/src/core/ext/transport/binder/client/security_policy_setting.h b/src/core/ext/transport/binder/client/security_policy_setting.h
new file mode 100644 (file)
index 0000000..d251661
--- /dev/null
@@ -0,0 +1,51 @@
+// 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.
+
+#ifndef GRPC_CORE_EXT_TRANSPORT_BINDER_CLIENT_SECURITY_POLICY_SETTING_H
+#define GRPC_CORE_EXT_TRANSPORT_BINDER_CLIENT_SECURITY_POLICY_SETTING_H
+
+#include <grpc/support/port_platform.h>
+
+#include "absl/container/flat_hash_map.h"
+#include "absl/strings/string_view.h"
+
+#include <grpcpp/security/binder_security_policy.h>
+
+#include "src/core/lib/gprpp/sync.h"
+
+namespace grpc_binder {
+
+// A singleton class for setting security setting for each connection. This is
+// required because we cannot pass security policy shared pointers around using
+// gRPC arguments, we can only pass connection_id around as part of URI
+class SecurityPolicySetting {
+ public:
+  void Set(absl::string_view connection_id,
+           std::shared_ptr<grpc::experimental::binder::SecurityPolicy>
+               security_policy);
+  std::shared_ptr<grpc::experimental::binder::SecurityPolicy> Get(
+      absl::string_view connection_id);
+
+ private:
+  grpc_core::Mutex m_;
+  absl::flat_hash_map<
+      std::string, std::shared_ptr<grpc::experimental::binder::SecurityPolicy>>
+      security_policy_map_ ABSL_GUARDED_BY(m_);
+};
+
+SecurityPolicySetting* GetSecurityPolicySetting();
+
+}  // namespace grpc_binder
+
+#endif  // GRPC_CORE_EXT_TRANSPORT_BINDER_CLIENT_SECURITY_POLICY_SETTING_H
index 7af224e..8da1c37 100644 (file)
@@ -19,8 +19,9 @@ licenses(["notice"])
 android_library(
     name = "connection_helper",
     srcs = [
+        "GrpcBinderConnection.java",
+        "GrpcCppServerBuilder.java",
         "NativeConnectionHelper.java",
-        "SyncServiceConnection.java",
     ],
     visibility = ["//visibility:public"],
     deps = [],
diff --git a/src/core/ext/transport/binder/java/io/grpc/binder/cpp/GrpcBinderConnection.java b/src/core/ext/transport/binder/java/io/grpc/binder/cpp/GrpcBinderConnection.java
new file mode 100644 (file)
index 0000000..4953113
--- /dev/null
@@ -0,0 +1,85 @@
+// 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.
+
+package io.grpc.binder.cpp;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.IBinder;
+import android.util.Log;
+
+/* Handles the binder connection state with OnDeviceServer server */
+public class GrpcBinderConnection implements ServiceConnection {
+  private static final String logTag = "GrpcBinderConnection";
+
+  private Context mContext;
+  private IBinder mService;
+
+  // A string that identifies this service connection
+  private final String mConnId;
+
+  public GrpcBinderConnection(Context context, String connId) {
+    mContext = context;
+    mConnId = connId;
+  }
+
+  @Override
+  public void onNullBinding(ComponentName className) {
+    // TODO(mingcl): Notify C++ that the connection is never going to happen
+    Log.e(logTag, "Service returned null IBinder. mConnId = " + mConnId);
+  }
+
+  @Override
+  public void onServiceConnected(ComponentName className, IBinder service) {
+    Log.e(logTag, "Service has connected. mConnId = " + mConnId);
+    if (service == null) {
+      // This should not happen since onNullBinding should be invoked instead
+      throw new IllegalArgumentException("service was null");
+    }
+    synchronized (this) {
+      mService = service;
+    }
+    notifyConnected(mConnId, mService);
+  }
+
+  @Override
+  public void onServiceDisconnected(ComponentName className) {
+    Log.e(logTag, "Service has disconnected. mConnId = " + mConnId);
+  }
+
+  public void tryConnect(String pkg, String cls) {
+    synchronized (this) {
+      Intent intent = new Intent("grpc.io.action.BIND");
+      ComponentName compName = new ComponentName(pkg, cls);
+      intent.setComponent(compName);
+      // Will return true if the system is in the process of bringing up a service that your client
+      // has permission to bind to; false if the system couldn't find the service or if your client
+      // doesn't have permission to bind to it
+      boolean result = mContext.bindService(intent, this, Context.BIND_AUTO_CREATE);
+      if (result) {
+        Log.e(logTag, "bindService returns ok");
+      } else {
+        Log.e(
+            logTag,
+            "bindService failed. Maybe the system couldn't find the service or the"
+                + " client doesn't have permission to bind to it.");
+      }
+    }
+  }
+
+  // Calls a function defined in endpoint_binder_pool.cc
+  private static native void notifyConnected(String connId, IBinder service);
+}
diff --git a/src/core/ext/transport/binder/java/io/grpc/binder/cpp/GrpcCppServerBuilder.java b/src/core/ext/transport/binder/java/io/grpc/binder/cpp/GrpcCppServerBuilder.java
new file mode 100644 (file)
index 0000000..c5ccfd3
--- /dev/null
@@ -0,0 +1,38 @@
+// 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.
+
+package io.grpc.binder.cpp;
+
+import android.os.IBinder;
+import android.util.Log;
+
+/* EXPERIMENTAL. Provides a interface to get endpoint binder from C++ */
+public class GrpcCppServerBuilder {
+  private static final String logTag = "GrpcCppServerBuilder";
+
+  public static IBinder GetEndpointBinder(String uri) {
+    String scheme = "binder:";
+    if (uri.startsWith(scheme)) {
+      String path = uri.substring(scheme.length());
+      // TODO(mingcl): Consider if we would like to make sure the path only contain valid
+      // characters here
+      return GetEndpointBinderInternal(path);
+    } else {
+      Log.e(logTag, "URI " + uri + " does not start with 'binder:'");
+      return null;
+    }
+  }
+
+  private static native IBinder GetEndpointBinderInternal(String conn_id);
+}
index 6dd1755..adc67e9 100644 (file)
 package io.grpc.binder.cpp;
 
 import android.content.Context;
-import android.os.IBinder;
 import android.os.Parcel;
+import java.util.HashMap;
+import java.util.Map;
 
 /**
  * This class will be invoked by gRPC binder transport internal implementation to perform operations
  * that are only possible in Java
  */
 final class NativeConnectionHelper {
-  static SyncServiceConnection s;
+  // Maps connection id to GrpcBinderConnection instances
+  static Map<String, GrpcBinderConnection> s = new HashMap<>();
 
-  static void tryEstablishConnection(Context context, String pkg, String cls) {
-    s = new SyncServiceConnection(context);
-    s.tryConnect(pkg, cls);
-  }
-
-  // TODO(mingcl): We should notify C++ once we got the service binder so they don't need to call
-  // this function to check. For now we assume that this function will only be called after
-  // successful connection
-  static IBinder getServiceBinder() {
-    return s.getIBinder();
+  static void tryEstablishConnection(Context context, String pkg, String cls, String connId) {
+    // TODO(mingcl): Assert that connId is unique
+    s.put(connId, new GrpcBinderConnection(context, connId));
+    s.get(connId).tryConnect(pkg, cls);
   }
 
   static Parcel getEmptyParcel() {
diff --git a/src/core/ext/transport/binder/java/io/grpc/binder/cpp/SyncServiceConnection.java b/src/core/ext/transport/binder/java/io/grpc/binder/cpp/SyncServiceConnection.java
deleted file mode 100644 (file)
index 66848f3..0000000
+++ /dev/null
@@ -1,68 +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.
-
-package io.grpc.binder.cpp;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.os.IBinder;
-import android.util.Log;
-
-/* Connects to a service synchronously */
-public class SyncServiceConnection implements ServiceConnection {
-  private final String logTag = "SyncServiceConnection";
-
-  private Context mContext;
-  private IBinder mService;
-
-  public SyncServiceConnection(Context context) {
-    mContext = context;
-  }
-
-  @Override
-  public void onServiceConnected(ComponentName className, IBinder service) {
-    Log.e(logTag, "Service has connected: ");
-    synchronized (this) {
-      mService = service;
-    }
-  }
-
-  @Override
-  public void onServiceDisconnected(ComponentName className) {
-    Log.e(logTag, "Service has disconnected: ");
-  }
-
-  public void tryConnect(String pkg, String cls) {
-    synchronized (this) {
-      Intent intent = new Intent("grpc.io.action.BIND");
-      ComponentName compName = new ComponentName(pkg, cls);
-      intent.setComponent(compName);
-      // Will return true if the system is in the process of bringing up a service that your client
-      // has permission to bind to; false if the system couldn't find the service or if your client
-      // doesn't have permission to bind to it
-      boolean result = mContext.bindService(intent, this, Context.BIND_AUTO_CREATE);
-      if (result) {
-        Log.e(logTag, "bindService ok");
-      } else {
-        Log.e(logTag, "bindService not ok");
-      }
-    }
-  }
-
-  public IBinder getIBinder() {
-    return mService;
-  }
-}
diff --git a/src/core/ext/transport/binder/security_policy/binder_security_policy.cc b/src/core/ext/transport/binder/security_policy/binder_security_policy.cc
new file mode 100644 (file)
index 0000000..1381619
--- /dev/null
@@ -0,0 +1,52 @@
+// 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 <grpc/support/port_platform.h>
+
+#ifndef GRPC_NO_BINDER
+
+#include <grpcpp/security/binder_security_policy.h>
+
+#ifdef GPR_ANDROID
+
+#include <unistd.h>
+
+#endif
+
+namespace grpc {
+namespace experimental {
+namespace binder {
+
+UntrustedSecurityPolicy::UntrustedSecurityPolicy() = default;
+
+UntrustedSecurityPolicy::~UntrustedSecurityPolicy() = default;
+
+bool UntrustedSecurityPolicy::IsAuthorized(int) { return true; };
+
+InternalOnlySecurityPolicy::InternalOnlySecurityPolicy() = default;
+
+InternalOnlySecurityPolicy::~InternalOnlySecurityPolicy() = default;
+
+#ifdef GPR_ANDROID
+bool InternalOnlySecurityPolicy::IsAuthorized(int uid) {
+  return static_cast<uid_t>(uid) == getuid();
+}
+#else
+bool InternalOnlySecurityPolicy::IsAuthorized(int) { return false; }
+#endif
+
+}  // namespace binder
+}  // namespace experimental
+}  // namespace grpc
+#endif
diff --git a/src/core/ext/transport/binder/security_policy/internal_only_security_policy.h b/src/core/ext/transport/binder/security_policy/internal_only_security_policy.h
new file mode 100644 (file)
index 0000000..ed46e4c
--- /dev/null
@@ -0,0 +1,42 @@
+// 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.
+
+#ifndef GRPC_CORE_EXT_TRANSPORT_BINDER_SECURITY_POLICY_INTERNAL_ONLY_SECURITY_POLICY_H
+#define GRPC_CORE_EXT_TRANSPORT_BINDER_SECURITY_POLICY_INTERNAL_ONLY_SECURITY_POLICY_H
+
+#include <grpc/support/port_platform.h>
+
+#include "src/core/ext/transport/binder/security_policy/security_policy.h"
+
+#ifdef GPR_ANDROID
+
+namespace grpc {
+namespace experimental {
+namespace binder {
+
+// Only allows the connections from processes with the same UID
+class InternalOnlySecurityPolicy : public SecurityPolicy {
+ public:
+  InternalOnlySecurityPolicy();
+  ~InternalOnlySecurityPolicy() override;
+  bool IsAuthorized(int uid) override;
+};
+
+}  // namespace binder
+}  // namespace experimental
+}  // namespace grpc
+
+#endif
+
+#endif  // GRPC_CORE_EXT_TRANSPORT_BINDER_SECURITY_POLICY_INTERNAL_ONLY_SECURITY_POLICY_H
diff --git a/src/core/ext/transport/binder/security_policy/security_policy.h b/src/core/ext/transport/binder/security_policy/security_policy.h
new file mode 100644 (file)
index 0000000..69a6e95
--- /dev/null
@@ -0,0 +1,40 @@
+// 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.
+
+#ifndef GRPC_CORE_EXT_TRANSPORT_BINDER_SECURITY_POLICY_SECURITY_POLICY_H
+#define GRPC_CORE_EXT_TRANSPORT_BINDER_SECURITY_POLICY_SECURITY_POLICY_H
+
+#include <grpc/support/port_platform.h>
+
+namespace grpc {
+namespace experimental {
+namespace binder {
+
+// This interface is for determining if a connection is allowed to be
+// established on Android. See https://source.android.com/security/app-sandbox
+// for more info about UID.
+class SecurityPolicy {
+ public:
+  virtual ~SecurityPolicy() = default;
+  // Returns true if the UID is authorized to connect.
+  // Must return the same value for the same inputs so callers can safely cache
+  // the result.
+  virtual bool IsAuthorized(int uid) = 0;
+};
+
+}  // namespace binder
+}  // namespace experimental
+}  // namespace grpc
+
+#endif  // GRPC_CORE_EXT_TRANSPORT_BINDER_SECURITY_POLICY_SECURITY_POLICY_H
diff --git a/src/core/ext/transport/binder/server/BUILD b/src/core/ext/transport/binder/server/BUILD
deleted file mode 100644 (file)
index a5cf6df..0000000
+++ /dev/null
@@ -1,50 +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.
-
-load("//bazel:grpc_build_system.bzl", "grpc_cc_library")
-
-licenses(["notice"])
-
-package(
-    default_visibility = ["//visibility:public"],
-    features = [
-        "layering_check",
-    ],
-)
-
-grpc_cc_library(
-    name = "grpc_transport_binder_server",
-    srcs = [
-        "binder_server.cc",
-        "binder_server_credentials.cc",
-    ],
-    hdrs = [
-        "binder_server.h",
-        "binder_server_credentials.h",
-    ],
-    external_deps = [
-        "absl/container:flat_hash_map",
-        "absl/memory",
-        "absl/status",
-    ],
-    language = "c++",
-    deps = [
-        "//:gpr_platform",
-        "//:grpc++_internals",
-        "//:grpc_base_c",
-        "//src/core/ext/transport/binder/transport:binder_transport",
-        "//src/core/ext/transport/binder/wire_format:binder",
-        "//src/core/ext/transport/binder/wire_format:binder_android",
-    ],
-)
index dae27d3..7907437 100644 (file)
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include "src/core/ext/transport/binder/server/binder_server.h"
 
+#ifndef GRPC_NO_BINDER
+
 #include <memory>
 #include <string>
 #include <utility>
 #include "src/core/lib/surface/server.h"
 #include "src/core/lib/transport/error_utils.h"
 
+#ifdef GPR_SUPPORT_BINDER_TRANSPORT
+
+#include <android/binder_ibinder.h>
+#include <android/binder_ibinder_jni.h>
+#include <jni.h>
+
+extern "C" {
+
+// This will be invoked from
+// src/core/ext/transport/binder/java/io/grpc/binder/cpp/GrpcCppServerBuilder.java
+JNIEXPORT jobject JNICALL
+Java_io_grpc_binder_cpp_GrpcCppServerBuilder_GetEndpointBinderInternal__Ljava_lang_String_2(
+    JNIEnv* jni_env, jobject, jstring conn_id_jstring) {
+  AIBinder* ai_binder = nullptr;
+
+  {
+    // This block is the scope of conn_id c-string
+    jboolean isCopy;
+    const char* conn_id = jni_env->GetStringUTFChars(conn_id_jstring, &isCopy);
+    ai_binder =
+        static_cast<AIBinder*>(grpc_get_endpoint_binder(std::string(conn_id)));
+    if (ai_binder == nullptr) {
+      gpr_log(GPR_ERROR, "Cannot find endpoint binder with connection id = %s",
+              conn_id);
+    }
+    if (isCopy == JNI_TRUE) {
+      jni_env->ReleaseStringUTFChars(conn_id_jstring, conn_id);
+    }
+  }
+
+  if (ai_binder == nullptr) {
+    return nullptr;
+  }
+
+  return AIBinder_toJavaBinder(jni_env, ai_binder);
+}
+}
+
+#endif
+
 namespace grpc {
 namespace experimental {
 namespace binder {
@@ -92,16 +134,20 @@ namespace grpc_core {
 
 class BinderServerListener : public Server::ListenerInterface {
  public:
-  BinderServerListener(Server* server, std::string addr,
-                       BinderTxReceiverFactory factory)
-      : server_(server), addr_(std::move(addr)), factory_(std::move(factory)) {}
+  BinderServerListener(
+      Server* server, std::string addr, BinderTxReceiverFactory factory,
+      std::shared_ptr<grpc::experimental::binder::SecurityPolicy>
+          security_policy)
+      : server_(server),
+        addr_(std::move(addr)),
+        factory_(std::move(factory)),
+        security_policy_(security_policy) {}
 
   void Start(Server* /*server*/,
              const std::vector<grpc_pollset*>* /*pollsets*/) override {
-    tx_receiver_ = factory_([this](transaction_code_t code,
-                                   const grpc_binder::ReadableParcel* parcel) {
-      return OnSetupTransport(code, parcel);
-    });
+    tx_receiver_ = factory_(
+        [this](transaction_code_t code, grpc_binder::ReadableParcel* parcel,
+               int uid) { return OnSetupTransport(code, parcel, uid); });
     endpoint_binder_ = tx_receiver_->GetRawBinder();
     grpc_add_endpoint_binder(addr_, endpoint_binder_);
   }
@@ -127,12 +173,24 @@ class BinderServerListener : public Server::ListenerInterface {
 
  private:
   absl::Status OnSetupTransport(transaction_code_t code,
-                                const grpc_binder::ReadableParcel* parcel) {
+                                grpc_binder::ReadableParcel* parcel, int uid) {
     grpc_core::ExecCtx exec_ctx;
     if (grpc_binder::BinderTransportTxCode(code) !=
         grpc_binder::BinderTransportTxCode::SETUP_TRANSPORT) {
       return absl::InvalidArgumentError("Not a SETUP_TRANSPORT request");
     }
+
+    gpr_log(GPR_ERROR, "calling uid = %d", uid);
+    if (!security_policy_->IsAuthorized(uid)) {
+      // TODO(mingcl): For now we just ignore this unauthorized
+      // SETUP_TRANSPORT transaction and ghost the client. Check if we should
+      // send back a SHUTDOWN_TRANSPORT in this case.
+      return absl::PermissionDeniedError(
+          "UID " + std::to_string(uid) +
+          " is not allowed to connect to this "
+          "server according to security policy.");
+    }
+
     int version;
     absl::Status status = parcel->ReadInt32(&version);
     if (!status.ok()) {
@@ -151,8 +209,8 @@ class BinderServerListener : public Server::ListenerInterface {
     client_binder->Initialize();
     // Finish the second half of SETUP_TRANSPORT in
     // grpc_create_binder_transport_server().
-    grpc_transport* server_transport =
-        grpc_create_binder_transport_server(std::move(client_binder));
+    grpc_transport* server_transport = grpc_create_binder_transport_server(
+        std::move(client_binder), security_policy_);
     GPR_ASSERT(server_transport);
     grpc_channel_args* args = grpc_channel_args_copy(server_->channel_args());
     grpc_error_handle error = server_->SetupTransport(server_transport, nullptr,
@@ -165,24 +223,29 @@ class BinderServerListener : public Server::ListenerInterface {
   grpc_closure* on_destroy_done_ = nullptr;
   std::string addr_;
   BinderTxReceiverFactory factory_;
+  std::shared_ptr<grpc::experimental::binder::SecurityPolicy> security_policy_;
   void* endpoint_binder_ = nullptr;
   std::unique_ptr<grpc_binder::TransactionReceiver> tx_receiver_;
 };
 
 bool AddBinderPort(const std::string& addr, grpc_server* server,
-                   BinderTxReceiverFactory factory) {
+                   BinderTxReceiverFactory factory,
+                   std::shared_ptr<grpc::experimental::binder::SecurityPolicy>
+                       security_policy) {
+  // TODO(mingcl): Check if the addr is valid here after binder address resolver
+  // related code are merged.
   const std::string kBinderUriScheme = "binder:";
   if (addr.compare(0, kBinderUriScheme.size(), kBinderUriScheme) != 0) {
     return false;
   }
-  size_t pos = kBinderUriScheme.size();
-  while (pos < addr.size() && addr[pos] == '/') pos++;
+  std::string conn_id = addr.substr(kBinderUriScheme.size());
   grpc_core::Server* core_server = server->core_server.get();
   core_server->AddListener(
       grpc_core::OrphanablePtr<grpc_core::Server::ListenerInterface>(
-          new grpc_core::BinderServerListener(core_server, addr.substr(pos),
-                                              std::move(factory))));
+          new grpc_core::BinderServerListener(
+              core_server, conn_id, std::move(factory), security_policy)));
   return true;
 }
 
 }  // namespace grpc_core
+#endif
index 66cbb81..6fc1b88 100644 (file)
 #ifndef GRPC_CORE_EXT_TRANSPORT_BINDER_SERVER_BINDER_SERVER_H
 #define GRPC_CORE_EXT_TRANSPORT_BINDER_SERVER_BINDER_SERVER_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include <string>
 
 #include "absl/container/flat_hash_map.h"
 #include "absl/status/status.h"
 
+#include <grpcpp/security/binder_security_policy.h>
+
 #include "src/core/ext/transport/binder/transport/binder_transport.h"
 #include "src/core/ext/transport/binder/wire_format/binder.h"
 #include "src/core/lib/iomgr/exec_ctx.h"
@@ -56,7 +58,9 @@ using BinderTxReceiverFactory =
         grpc_binder::TransactionReceiver::OnTransactCb)>;
 
 bool AddBinderPort(const std::string& addr, grpc_server* server,
-                   BinderTxReceiverFactory factory);
+                   BinderTxReceiverFactory factory,
+                   std::shared_ptr<grpc::experimental::binder::SecurityPolicy>
+                       security_policy);
 
 }  // namespace grpc_core
 
index ee57e6b..d43f928 100644 (file)
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
+#ifndef GRPC_NO_BINDER
+
+#include <grpcpp/security/binder_security_policy.h>
 #include <grpcpp/security/server_credentials.h>
 
 #include "src/core/ext/transport/binder/server/binder_server.h"
@@ -26,21 +29,26 @@ namespace {
 
 class BinderServerCredentialsImpl final : public ServerCredentials {
  public:
-#ifdef GPR_ANDROID
+  explicit BinderServerCredentialsImpl(
+      std::shared_ptr<grpc::experimental::binder::SecurityPolicy>
+          security_policy)
+      : security_policy_(security_policy) {}
+#ifdef GPR_SUPPORT_BINDER_TRANSPORT
   int AddPortToServer(const std::string& addr, grpc_server* server) override {
     return grpc_core::AddBinderPort(
         std::string(addr), server,
         [](grpc_binder::TransactionReceiver::OnTransactCb transact_cb) {
           return absl::make_unique<grpc_binder::TransactionReceiverAndroid>(
               nullptr, std::move(transact_cb));
-        });
+        },
+        security_policy_);
   }
 #else
   int AddPortToServer(const std::string& /*addr*/,
                       grpc_server* /*server*/) override {
     return 0;
   }
-#endif  // GPR_ANDROID
+#endif  // GPR_SUPPORT_BINDER_TRANSPORT
 
   void SetAuthMetadataProcessor(
       const std::shared_ptr<AuthMetadataProcessor>& /*processor*/) override {
@@ -49,13 +57,20 @@ class BinderServerCredentialsImpl final : public ServerCredentials {
 
  private:
   bool IsInsecure() const override { return true; }
+
+  std::shared_ptr<grpc::experimental::binder::SecurityPolicy> security_policy_;
 };
 
 }  // namespace
 
-std::shared_ptr<ServerCredentials> BinderServerCredentials() {
-  return std::shared_ptr<ServerCredentials>(new BinderServerCredentialsImpl());
+std::shared_ptr<ServerCredentials> BinderServerCredentials(
+    std::shared_ptr<grpc::experimental::binder::SecurityPolicy>
+        security_policy) {
+  GPR_ASSERT(security_policy != nullptr);
+  return std::shared_ptr<ServerCredentials>(
+      new BinderServerCredentialsImpl(security_policy));
 }
 
 }  // namespace experimental
 }  // namespace grpc
+#endif
diff --git a/src/core/ext/transport/binder/server/binder_server_credentials.h b/src/core/ext/transport/binder/server/binder_server_credentials.h
deleted file mode 100644 (file)
index e8c326f..0000000
+++ /dev/null
@@ -1,35 +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.
-
-#ifndef GRPC_CORE_EXT_TRANSPORT_BINDER_SERVER_BINDER_SERVER_CREDENTIALS_H
-#define GRPC_CORE_EXT_TRANSPORT_BINDER_SERVER_BINDER_SERVER_CREDENTIALS_H
-
-#include <grpc/impl/codegen/port_platform.h>
-
-#include <grpcpp/security/server_credentials.h>
-
-namespace grpc {
-namespace experimental {
-
-/// Builds Binder ServerCredentials.
-///
-/// Calling \a ServerBuilder::AddListeningPort() with Binder ServerCredentials
-/// in a non-Android environment will make the subsequent call to
-/// \a ServerBuilder::BuildAndStart() returns a null pointer.
-std::shared_ptr<grpc::ServerCredentials> BinderServerCredentials();
-
-}  // namespace experimental
-}  // namespace grpc
-
-#endif  // GRPC_CORE_EXT_TRANSPORT_BINDER_SERVER_BINDER_SERVER_CREDENTIALS_H
diff --git a/src/core/ext/transport/binder/transport/BUILD b/src/core/ext/transport/binder/transport/BUILD
deleted file mode 100644 (file)
index 2f83a4e..0000000
+++ /dev/null
@@ -1,49 +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.
-
-load("//bazel:grpc_build_system.bzl", "grpc_cc_library")
-
-licenses(["notice"])
-
-package(
-    default_visibility = ["//visibility:public"],
-    features = [
-        "layering_check",
-    ],
-)
-
-grpc_cc_library(
-    name = "binder_transport",
-    srcs = [
-        "binder_transport.cc",
-    ],
-    hdrs = [
-        "binder_stream.h",
-        "binder_transport.h",
-    ],
-    external_deps = [
-        "absl/container:flat_hash_map",
-        "absl/memory",
-        "absl/strings",
-    ],
-    deps = [
-        "//:gpr_base",
-        "//:gpr_platform",
-        "//:grpc_base_c",
-        "//src/core/ext/transport/binder/utils:transport_stream_receiver",
-        "//src/core/ext/transport/binder/wire_format:binder",
-        "//src/core/ext/transport/binder/wire_format:wire_reader",
-        "//src/core/ext/transport/binder/wire_format:wire_writer",
-    ],
-)
index 3bdd5d7..8b6d38d 100644 (file)
@@ -15,7 +15,7 @@
 #ifndef GRPC_CORE_EXT_TRANSPORT_BINDER_TRANSPORT_BINDER_STREAM_H
 #define GRPC_CORE_EXT_TRANSPORT_BINDER_TRANSPORT_BINDER_STREAM_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include "src/core/ext/transport/binder/transport/binder_transport.h"
 
@@ -52,7 +52,8 @@ struct grpc_binder_stream {
         refcount(refcount),
         arena(arena),
         tx_code(tx_code),
-        is_client(is_client) {
+        is_client(is_client),
+        is_closed(false) {
     // TODO(waynetu): Should this be protected?
     t->registered_stream[tx_code] = this;
 
@@ -79,8 +80,8 @@ struct grpc_binder_stream {
   grpc_core::Arena* arena;
   grpc_core::ManualConstructor<grpc_core::SliceBufferByteStream> sbs;
   int tx_code;
-  bool is_client;
-  bool is_closed = false;
+  const bool is_client;
+  bool is_closed;
 
   grpc_closure* destroy_stream_then_closure = nullptr;
   grpc_closure destroy_stream;
index dbde037..aae2adc 100644 (file)
@@ -16,6 +16,8 @@
 
 #include "src/core/ext/transport/binder/transport/binder_transport.h"
 
+#ifndef GRPC_NO_BINDER
+
 #include <cstdint>
 #include <memory>
 #include <string>
@@ -118,21 +120,11 @@ static void set_pollset_set(grpc_transport*, grpc_stream*, grpc_pollset_set*) {
   gpr_log(GPR_INFO, __func__);
 }
 
-static void AssignMetadata(grpc_metadata_batch* mb, grpc_core::Arena* arena,
+static void AssignMetadata(grpc_metadata_batch* mb,
                            const grpc_binder::Metadata& md) {
-  grpc_metadata_batch_init(mb);
+  mb->Clear();
   for (auto& p : md) {
-    grpc_linked_mdelem* glm = static_cast<grpc_linked_mdelem*>(
-        arena->Alloc(sizeof(grpc_linked_mdelem)));
-    memset(glm, 0, sizeof(grpc_linked_mdelem));
-    grpc_slice key = grpc_slice_from_cpp_string(p.first);
-    grpc_slice value = grpc_slice_from_cpp_string(p.second);
-    glm->md = grpc_mdelem_from_slices(grpc_slice_intern(key),
-                                      grpc_slice_intern(value));
-    // Unref here to prevent memory leak
-    grpc_slice_unref_internal(key);
-    grpc_slice_unref_internal(value);
-    GPR_ASSERT(grpc_metadata_batch_link_tail(mb, glm) == GRPC_ERROR_NONE);
+    mb->Append(p.first, grpc_slice_from_cpp_string(p.second));
   }
 }
 
@@ -172,6 +164,20 @@ static void cancel_stream_locked(grpc_binder_transport* gbt,
   GRPC_ERROR_UNREF(error);
 }
 
+static bool ContainsAuthorityAndPath(const grpc_binder::Metadata& metadata) {
+  bool has_authority = false;
+  bool has_path = false;
+  for (const auto& kv : metadata) {
+    if (kv.first == grpc_core::StringViewFromSlice(GRPC_MDSTR_AUTHORITY)) {
+      has_authority = true;
+    }
+    if (kv.first == grpc_core::StringViewFromSlice(GRPC_MDSTR_PATH)) {
+      has_path = true;
+    }
+  }
+  return has_authority && has_path;
+}
+
 static void recv_initial_metadata_locked(void* arg,
                                          grpc_error_handle /*error*/) {
   RecvInitialMetadataArgs* args = static_cast<RecvInitialMetadataArgs*>(arg);
@@ -189,8 +195,14 @@ static void recv_initial_metadata_locked(void* arg,
         gpr_log(GPR_ERROR, "Failed to parse initial metadata");
         return absl_status_to_grpc_error(args->initial_metadata.status());
       }
-      AssignMetadata(gbs->recv_initial_metadata, gbs->arena,
-                     *args->initial_metadata);
+      if (!gbs->is_client) {
+        // For server, we expect :authority and :path in initial metadata.
+        if (!ContainsAuthorityAndPath(*args->initial_metadata)) {
+          return GRPC_ERROR_CREATE_FROM_CPP_STRING(
+              "Missing :authority or :path in initial metadata");
+        }
+      }
+      AssignMetadata(gbs->recv_initial_metadata, *args->initial_metadata);
       return GRPC_ERROR_NONE;
     }();
 
@@ -272,8 +284,7 @@ static void recv_trailing_metadata_locked(void* arg,
           return GRPC_ERROR_CANCELLED;
         }
       } else {
-        AssignMetadata(gbs->recv_trailing_metadata, gbs->arena,
-                       *args->trailing_metadata);
+        AssignMetadata(gbs->recv_trailing_metadata, *args->trailing_metadata);
         // Append status to metadata
         // TODO(b/192208695): See if we can avoid to manually put status
         // code into the header
@@ -281,8 +292,8 @@ static void recv_trailing_metadata_locked(void* arg,
         grpc_linked_mdelem* glm = static_cast<grpc_linked_mdelem*>(
             gbs->arena->Alloc(sizeof(grpc_linked_mdelem)));
         glm->md = grpc_get_reffed_status_elem(args->status);
-        GPR_ASSERT(grpc_metadata_batch_link_tail(gbs->recv_trailing_metadata,
-                                                 glm) == GRPC_ERROR_NONE);
+        GPR_ASSERT(gbs->recv_trailing_metadata->LinkTail(glm) ==
+                   GRPC_ERROR_NONE);
         gpr_log(GPR_INFO, "trailing_metadata = %p",
                 gbs->recv_trailing_metadata);
         gpr_log(GPR_INFO, "glm = %p", glm);
@@ -375,15 +386,13 @@ static void perform_stream_op_locked(void* stream_op,
     grpc_binder::Metadata init_md;
     auto batch = op->payload->send_initial_metadata.send_initial_metadata;
 
-    for (grpc_linked_mdelem* md = batch->list.head; md != nullptr;
-         md = md->next) {
-      absl::string_view key =
-          grpc_core::StringViewFromSlice(GRPC_MDKEY(md->md));
+    batch->ForEach([&](grpc_mdelem md) {
+      absl::string_view key = grpc_core::StringViewFromSlice(GRPC_MDKEY(md));
       absl::string_view value =
-          grpc_core::StringViewFromSlice(GRPC_MDVALUE(md->md));
+          grpc_core::StringViewFromSlice(GRPC_MDVALUE(md));
       gpr_log(GPR_INFO, "send initial metatday key-value %s",
               absl::StrCat(key, " ", value).c_str());
-      if (grpc_slice_eq(GRPC_MDKEY(md->md), GRPC_MDSTR_PATH)) {
+      if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_PATH)) {
         // TODO(b/192208403): Figure out if it is correct to simply drop '/'
         // prefix and treat it as rpc method name
         GPR_ASSERT(value[0] == '/');
@@ -395,7 +404,7 @@ static void perform_stream_op_locked(void* stream_op,
       } else {
         init_md.emplace_back(std::string(key), std::string(value));
       }
-    }
+    });
     tx.SetPrefix(init_md);
   }
   if (op->send_message) {
@@ -429,25 +438,23 @@ static void perform_stream_op_locked(void* stream_op,
     auto batch = op->payload->send_trailing_metadata.send_trailing_metadata;
     grpc_binder::Metadata trailing_metadata;
 
-    for (grpc_linked_mdelem* md = batch->list.head; md != nullptr;
-         md = md->next) {
+    batch->ForEach([&](grpc_mdelem md) {
       // Client will not send trailing metadata.
       GPR_ASSERT(!gbt->is_client);
 
-      if (grpc_slice_eq(GRPC_MDKEY(md->md), GRPC_MDSTR_GRPC_STATUS)) {
-        int status = grpc_get_status_code_from_metadata(md->md);
+      if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_STATUS)) {
+        int status = grpc_get_status_code_from_metadata(md);
         gpr_log(GPR_INFO, "send trailing metadata status = %d", status);
         tx.SetStatus(status);
       } else {
-        absl::string_view key =
-            grpc_core::StringViewFromSlice(GRPC_MDKEY(md->md));
+        absl::string_view key = grpc_core::StringViewFromSlice(GRPC_MDKEY(md));
         absl::string_view value =
-            grpc_core::StringViewFromSlice(GRPC_MDVALUE(md->md));
+            grpc_core::StringViewFromSlice(GRPC_MDVALUE(md));
         gpr_log(GPR_INFO, "send trailing metatday key-value %s",
                 absl::StrCat(key, " ", value).c_str());
         trailing_metadata.emplace_back(std::string(key), std::string(value));
       }
-    }
+    });
     // TODO(mingcl): Will we ever has key-value pair here? According to
     // wireformat client suffix data is always empty.
     tx.SetSuffix(trailing_metadata);
@@ -465,10 +472,6 @@ static void perform_stream_op_locked(void* stream_op,
         tx_code, [tx_code, gbs,
                   gbt](absl::StatusOr<grpc_binder::Metadata> initial_metadata) {
           grpc_core::ExecCtx exec_ctx;
-          if (gbs->is_closed) {
-            GRPC_BINDER_STREAM_UNREF(gbs, "recv_initial_metadata");
-            return;
-          }
           gbs->recv_initial_metadata_args.tx_code = tx_code;
           gbs->recv_initial_metadata_args.initial_metadata =
               std::move(initial_metadata);
@@ -489,10 +492,6 @@ static void perform_stream_op_locked(void* stream_op,
     gbt->transport_stream_receiver->RegisterRecvMessage(
         tx_code, [tx_code, gbs, gbt](absl::StatusOr<std::string> message) {
           grpc_core::ExecCtx exec_ctx;
-          if (gbs->is_closed) {
-            GRPC_BINDER_STREAM_UNREF(gbs, "recv_message");
-            return;
-          }
           gbs->recv_message_args.tx_code = tx_code;
           gbs->recv_message_args.message = std::move(message);
           gbt->combiner->Run(
@@ -513,10 +512,6 @@ static void perform_stream_op_locked(void* stream_op,
                      absl::StatusOr<grpc_binder::Metadata> trailing_metadata,
                      int status) {
           grpc_core::ExecCtx exec_ctx;
-          if (gbs->is_closed) {
-            GRPC_BINDER_STREAM_UNREF(gbs, "recv_trailing_metadata");
-            return;
-          }
           gbs->recv_trailing_metadata_args.tx_code = tx_code;
           gbs->recv_trailing_metadata_args.trailing_metadata =
               std::move(trailing_metadata);
@@ -700,7 +695,8 @@ static void accept_stream_locked(void* gt, grpc_error_handle /*error*/) {
 }
 
 grpc_binder_transport::grpc_binder_transport(
-    std::unique_ptr<grpc_binder::Binder> binder, bool is_client)
+    std::unique_ptr<grpc_binder::Binder> binder, bool is_client,
+    std::shared_ptr<grpc::experimental::binder::SecurityPolicy> security_policy)
     : is_client(is_client),
       combiner(grpc_combiner_create()),
       state_tracker(is_client ? "binder_transport_client"
@@ -719,8 +715,9 @@ grpc_binder_transport::grpc_binder_transport(
   // WireReader holds a ref to grpc_binder_transport.
   GRPC_BINDER_REF_TRANSPORT(this, "wire reader");
   wire_reader = grpc_core::MakeOrphanable<grpc_binder::WireReaderImpl>(
-      transport_stream_receiver, is_client,
-      /*on_destruct_callback=*/[this] {
+      transport_stream_receiver, is_client, security_policy,
+      /*on_destruct_callback=*/
+      [this] {
         // Unref transport when destructed.
         GRPC_BINDER_UNREF_TRANSPORT(this, "wire reader");
       });
@@ -732,21 +729,32 @@ grpc_binder_transport::~grpc_binder_transport() {
 }
 
 grpc_transport* grpc_create_binder_transport_client(
-    std::unique_ptr<grpc_binder::Binder> endpoint_binder) {
+    std::unique_ptr<grpc_binder::Binder> endpoint_binder,
+    std::shared_ptr<grpc::experimental::binder::SecurityPolicy>
+        security_policy) {
   gpr_log(GPR_INFO, __func__);
 
-  grpc_binder_transport* t =
-      new grpc_binder_transport(std::move(endpoint_binder), /*is_client=*/true);
+  GPR_ASSERT(endpoint_binder != nullptr);
+  GPR_ASSERT(security_policy != nullptr);
+
+  grpc_binder_transport* t = new grpc_binder_transport(
+      std::move(endpoint_binder), /*is_client=*/true, security_policy);
 
   return &t->base;
 }
 
 grpc_transport* grpc_create_binder_transport_server(
-    std::unique_ptr<grpc_binder::Binder> client_binder) {
+    std::unique_ptr<grpc_binder::Binder> client_binder,
+    std::shared_ptr<grpc::experimental::binder::SecurityPolicy>
+        security_policy) {
   gpr_log(GPR_INFO, __func__);
 
-  grpc_binder_transport* t =
-      new grpc_binder_transport(std::move(client_binder), /*is_client=*/false);
+  GPR_ASSERT(client_binder != nullptr);
+  GPR_ASSERT(security_policy != nullptr);
+
+  grpc_binder_transport* t = new grpc_binder_transport(
+      std::move(client_binder), /*is_client=*/false, security_policy);
 
   return &t->base;
 }
+#endif
index d7e141b..8cad2d5 100644 (file)
@@ -15,7 +15,7 @@
 #ifndef GRPC_CORE_EXT_TRANSPORT_BINDER_TRANSPORT_BINDER_TRANSPORT_H
 #define GRPC_CORE_EXT_TRANSPORT_BINDER_TRANSPORT_BINDER_TRANSPORT_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include <memory>
 #include <string>
@@ -25,6 +25,7 @@
 #include "absl/container/flat_hash_map.h"
 
 #include <grpc/support/log.h>
+#include <grpcpp/security/binder_security_policy.h>
 
 #include "src/core/ext/transport/binder/utils/transport_stream_receiver.h"
 #include "src/core/ext/transport/binder/wire_format/binder.h"
@@ -41,8 +42,10 @@ struct grpc_binder_stream;
 // TODO(mingcl): Decide casing for this class name. Should we use C-style class
 // name here or just go with C++ style?
 struct grpc_binder_transport {
-  explicit grpc_binder_transport(std::unique_ptr<grpc_binder::Binder> binder,
-                                 bool is_client);
+  explicit grpc_binder_transport(
+      std::unique_ptr<grpc_binder::Binder> binder, bool is_client,
+      std::shared_ptr<grpc::experimental::binder::SecurityPolicy>
+          security_policy);
   ~grpc_binder_transport();
 
   int NewStreamTxCode() {
@@ -81,8 +84,12 @@ struct grpc_binder_transport {
 };
 
 grpc_transport* grpc_create_binder_transport_client(
-    std::unique_ptr<grpc_binder::Binder> endpoint_binder);
+    std::unique_ptr<grpc_binder::Binder> endpoint_binder,
+    std::shared_ptr<grpc::experimental::binder::SecurityPolicy>
+        security_policy);
 grpc_transport* grpc_create_binder_transport_server(
-    std::unique_ptr<grpc_binder::Binder> client_binder);
+    std::unique_ptr<grpc_binder::Binder> client_binder,
+    std::shared_ptr<grpc::experimental::binder::SecurityPolicy>
+        security_policy);
 
 #endif  // GRPC_CORE_EXT_TRANSPORT_BINDER_TRANSPORT_BINDER_TRANSPORT_H
diff --git a/src/core/ext/transport/binder/utils/BUILD b/src/core/ext/transport/binder/utils/BUILD
deleted file mode 100644 (file)
index 50e86a9..0000000
+++ /dev/null
@@ -1,46 +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.
-
-load("//bazel:grpc_build_system.bzl", "grpc_cc_library")
-
-licenses(["notice"])
-
-package(
-    default_visibility = ["//visibility:public"],
-    features = [
-        "layering_check",
-    ],
-)
-
-grpc_cc_library(
-    name = "transport_stream_receiver",
-    srcs = [
-        "transport_stream_receiver_impl.cc",
-    ],
-    hdrs = [
-        "transport_stream_receiver.h",
-        "transport_stream_receiver_impl.h",
-    ],
-    external_deps = [
-        "absl/status:statusor",
-        "absl/strings",
-        "absl/synchronization",
-    ],
-    deps = [
-        "//:gpr",
-        "//:gpr_base",
-        "//:gpr_platform",
-        "//src/core/ext/transport/binder/wire_format:transaction",
-    ],
-)
index 1b306b1..b9991a0 100644 (file)
@@ -15,7 +15,7 @@
 #ifndef GRPC_CORE_EXT_TRANSPORT_BINDER_UTILS_TRANSPORT_STREAM_RECEIVER_H
 #define GRPC_CORE_EXT_TRANSPORT_BINDER_UTILS_TRANSPORT_STREAM_RECEIVER_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include <functional>
 #include <string>
index 1add6e7..d7cbf7a 100644 (file)
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include "src/core/ext/transport/binder/utils/transport_stream_receiver_impl.h"
 
+#ifndef GRPC_NO_BINDER
+
 #include <functional>
 #include <string>
 #include <utility>
@@ -117,7 +119,7 @@ void TransportStreamReceiverImpl::RegisterRecvTrailingMetadata(
 void TransportStreamReceiverImpl::NotifyRecvInitialMetadata(
     StreamIdentifier id, absl::StatusOr<Metadata> initial_metadata) {
   gpr_log(GPR_INFO, "%s id = %d is_client = %d", __func__, id, is_client_);
-  if (!is_client_ && accept_stream_callback_) {
+  if (!is_client_ && accept_stream_callback_ && initial_metadata.ok()) {
     accept_stream_callback_();
   }
   InitialMetadataCallbackType cb;
@@ -250,3 +252,4 @@ void TransportStreamReceiverImpl::CancelStream(StreamIdentifier id) {
   pending_trailing_metadata_.erase(id);
 }
 }  // namespace grpc_binder
+#endif
index 2cf0355..ffafaf4 100644 (file)
@@ -15,7 +15,7 @@
 #ifndef GRPC_CORE_EXT_TRANSPORT_BINDER_UTILS_TRANSPORT_STREAM_RECEIVER_IMPL_H
 #define GRPC_CORE_EXT_TRANSPORT_BINDER_UTILS_TRANSPORT_STREAM_RECEIVER_IMPL_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include <functional>
 #include <map>
diff --git a/src/core/ext/transport/binder/wire_format/BUILD b/src/core/ext/transport/binder/wire_format/BUILD
deleted file mode 100644 (file)
index dd57094..0000000
+++ /dev/null
@@ -1,122 +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.
-
-load("//bazel:grpc_build_system.bzl", "grpc_cc_library")
-
-licenses(["notice"])
-
-package(
-    default_visibility = ["//visibility:public"],
-    features = [
-        "layering_check",
-    ],
-)
-
-grpc_cc_library(
-    name = "transaction",
-    srcs = [
-        "transaction.cc",
-    ],
-    hdrs = [
-        "transaction.h",
-    ],
-    external_deps = [
-        "absl/base:core_headers",
-        "absl/strings",
-    ],
-    deps = [
-        "//:gpr",
-        "//:gpr_platform",
-    ],
-)
-
-grpc_cc_library(
-    name = "binder",
-    srcs = [
-        "binder_constants.cc",
-    ],
-    hdrs = [
-        "binder.h",
-        "binder_constants.h",
-    ],
-    external_deps = [
-        "absl/base:core_headers",
-        "absl/status",
-        "absl/strings",
-    ],
-    deps = [
-        "//:gpr",
-        "//:gpr_platform",
-        "//:orphanable",
-    ],
-)
-
-grpc_cc_library(
-    name = "binder_android",
-    srcs = [
-        "binder_android.cc",
-    ],
-    hdrs = [
-        "binder_android.h",
-    ],
-    external_deps = [
-        "absl/synchronization",
-        "absl/memory",
-    ],
-    deps = [
-        ":binder",
-        ":wire_reader",
-        "//:gpr_platform",
-    ],
-)
-
-grpc_cc_library(
-    name = "wire_writer",
-    srcs = ["wire_writer.cc"],
-    hdrs = ["wire_writer.h"],
-    external_deps = [
-        "absl/container:flat_hash_map",
-        "absl/strings",
-    ],
-    deps = [
-        ":binder",
-        ":transaction",
-        "//:gpr",
-        "//:gpr_base",
-        "//:gpr_platform",
-    ],
-)
-
-grpc_cc_library(
-    name = "wire_reader",
-    srcs = ["wire_reader_impl.cc"],
-    hdrs = [
-        "wire_reader.h",
-        "wire_reader_impl.h",
-    ],
-    external_deps = [
-        "absl/container:flat_hash_map",
-        "absl/synchronization",
-        "absl/memory",
-        "absl/status:statusor",
-    ],
-    deps = [
-        ":binder",
-        ":wire_writer",
-        "//:gpr",
-        "//:gpr_platform",
-        "//:orphanable",
-        "//src/core/ext/transport/binder/utils:transport_stream_receiver",
-    ],
-)
index 4a05fdd..493df44 100644 (file)
@@ -15,7 +15,7 @@
 #ifndef GRPC_CORE_EXT_TRANSPORT_BINDER_WIRE_FORMAT_BINDER_H
 #define GRPC_CORE_EXT_TRANSPORT_BINDER_WIRE_FORMAT_BINDER_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include <cstdint>
 #include <functional>
@@ -44,9 +44,7 @@ class Binder;
 class WritableParcel {
  public:
   virtual ~WritableParcel() = default;
-  virtual int32_t GetDataPosition() const = 0;
   virtual int32_t GetDataSize() const = 0;
-  virtual absl::Status SetDataPosition(int32_t pos) = 0;
   virtual absl::Status WriteInt32(int32_t data) = 0;
   virtual absl::Status WriteInt64(int64_t data) = 0;
   virtual absl::Status WriteBinder(HasRawBinder* binder) = 0;
@@ -69,19 +67,17 @@ class ReadableParcel {
  public:
   virtual ~ReadableParcel() = default;
   virtual int32_t GetDataSize() const = 0;
-  virtual absl::Status ReadInt32(int32_t* data) const = 0;
-  virtual absl::Status ReadInt64(int64_t* data) const = 0;
-  virtual absl::Status ReadBinder(std::unique_ptr<Binder>* data) const = 0;
-  // TODO(waynetu): Provide better interfaces.
-  virtual absl::Status ReadByteArray(std::string* data) const = 0;
-  // FIXME(waynetu): This is just a temporary interface.
-  virtual absl::Status ReadString(char data[111]) const = 0;
+  virtual absl::Status ReadInt32(int32_t* data) = 0;
+  virtual absl::Status ReadInt64(int64_t* data) = 0;
+  virtual absl::Status ReadBinder(std::unique_ptr<Binder>* data) = 0;
+  virtual absl::Status ReadByteArray(std::string* data) = 0;
+  virtual absl::Status ReadString(std::string* str) = 0;
 };
 
 class TransactionReceiver : public HasRawBinder {
  public:
   using OnTransactCb =
-      std::function<absl::Status(transaction_code_t, const ReadableParcel*)>;
+      std::function<absl::Status(transaction_code_t, ReadableParcel*, int uid)>;
 
   ~TransactionReceiver() override = default;
 };
@@ -97,7 +93,6 @@ class Binder : public HasRawBinder {
   virtual absl::Status Transact(BinderTransportTxCode tx_code) = 0;
 
   virtual WritableParcel* GetWritableParcel() const = 0;
-  virtual ReadableParcel* GetReadableParcel() const = 0;
 
   // TODO(waynetu): Can we decouple the receiver from the binder?
   virtual std::unique_ptr<TransactionReceiver> ConstructTxReceiver(
index 1df139b..1683682 100644 (file)
@@ -12,7 +12,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
+
+#ifndef GRPC_NO_BINDER
 
 #ifdef GPR_SUPPORT_BINDER_TRANSPORT
 
@@ -78,7 +80,8 @@ binder_status_t f_onTransact(AIBinder* binder, transaction_code_t code,
   std::unique_ptr<ReadableParcel> output =
       absl::make_unique<ReadableParcelAndroid>(in);
   // The lock should be released "after" the callback finishes.
-  absl::Status status = (*callback)(code, output.get());
+  absl::Status status =
+      (*callback)(code, output.get(), AIBinder_getCallingUid());
   if (status.ok()) {
     return STATUS_OK;
   } else {
@@ -86,6 +89,43 @@ binder_status_t f_onTransact(AIBinder* binder, transaction_code_t code,
     return STATUS_UNKNOWN_ERROR;
   }
 }
+
+// StdStringAllocator, ReadString, StdVectorAllocator, and ReadVector's
+// implementations are copied from android/binder_parcel_utils.h
+// We cannot include the header because it does not compile in C++11
+
+bool StdStringAllocator(void* stringData, int32_t length, char** buffer) {
+  if (length <= 0) return false;
+
+  std::string* str = static_cast<std::string*>(stringData);
+  str->resize(static_cast<size_t>(length) - 1);
+  *buffer = &(*str)[0];
+  return true;
+}
+
+binder_status_t AParcelReadString(const AParcel* parcel, std::string* str) {
+  void* stringData = static_cast<void*>(str);
+  return AParcel_readString(parcel, stringData, StdStringAllocator);
+}
+
+template <typename T>
+bool StdVectorAllocator(void* vectorData, int32_t length, T** outBuffer) {
+  if (length < 0) return false;
+
+  std::vector<T>* vec = static_cast<std::vector<T>*>(vectorData);
+  if (static_cast<size_t>(length) > vec->max_size()) return false;
+
+  vec->resize(static_cast<size_t>(length));
+  *outBuffer = vec->data();
+  return true;
+}
+
+binder_status_t AParcelReadVector(const AParcel* parcel,
+                                  std::vector<uint8_t>* vec) {
+  void* vectorData = static_cast<void*>(vec);
+  return AParcel_readByteArray(parcel, vectorData, StdVectorAllocator<int8_t>);
+}
+
 }  // namespace
 
 ndk::SpAIBinder FromJavaBinder(JNIEnv* jni_env, jobject binder) {
@@ -178,11 +218,16 @@ absl::Status BinderAndroid::PrepareTransaction() {
 
 absl::Status BinderAndroid::Transact(BinderTransportTxCode tx_code) {
   AIBinder* binder = binder_.get();
-  return AIBinder_transact(binder, static_cast<transaction_code_t>(tx_code),
-                           &input_parcel_->parcel_, &output_parcel_->parcel_,
-                           FLAG_ONEWAY) == STATUS_OK
-             ? absl::OkStatus()
-             : absl::InternalError("AIBinder_transact failed");
+  // We only do one-way transaction and thus the output parcel is never used.
+  AParcel* unused_output_parcel;
+  absl::Status result =
+      (AIBinder_transact(binder, static_cast<transaction_code_t>(tx_code),
+                         &input_parcel_->parcel_, &unused_output_parcel,
+                         FLAG_ONEWAY) == STATUS_OK)
+          ? absl::OkStatus()
+          : absl::InternalError("AIBinder_transact failed");
+  AParcel_delete(unused_output_parcel);
+  return result;
 }
 
 std::unique_ptr<TransactionReceiver> BinderAndroid::ConstructTxReceiver(
@@ -192,10 +237,6 @@ std::unique_ptr<TransactionReceiver> BinderAndroid::ConstructTxReceiver(
                                                        transact_cb);
 }
 
-int32_t WritableParcelAndroid::GetDataPosition() const {
-  return AParcel_getDataPosition(parcel_);
-}
-
 int32_t WritableParcelAndroid::GetDataSize() const {
   if (AParcel_getDataSize) {
     return AParcel_getDataSize(parcel_);
@@ -205,12 +246,6 @@ int32_t WritableParcelAndroid::GetDataSize() const {
   }
 }
 
-absl::Status WritableParcelAndroid::SetDataPosition(int32_t pos) {
-  return AParcel_setDataPosition(parcel_, pos) == STATUS_OK
-             ? absl::OkStatus()
-             : absl::InternalError("AParcel_setDataPosition failed");
-}
-
 absl::Status WritableParcelAndroid::WriteInt32(int32_t data) {
   return AParcel_writeInt32(parcel_, data) == STATUS_OK
              ? absl::OkStatus()
@@ -249,24 +284,23 @@ int32_t ReadableParcelAndroid::GetDataSize() const {
     return AParcel_getDataSize(parcel_);
   } else {
     gpr_log(GPR_INFO, "[Warning] AParcel_getDataSize is not available");
-    return -1;
+    return 0;
   }
 }
 
-absl::Status ReadableParcelAndroid::ReadInt32(int32_t* data) const {
+absl::Status ReadableParcelAndroid::ReadInt32(int32_t* data) {
   return AParcel_readInt32(parcel_, data) == STATUS_OK
              ? absl::OkStatus()
              : absl::InternalError("AParcel_readInt32 failed");
 }
 
-absl::Status ReadableParcelAndroid::ReadInt64(int64_t* data) const {
+absl::Status ReadableParcelAndroid::ReadInt64(int64_t* data) {
   return AParcel_readInt64(parcel_, data) == STATUS_OK
              ? absl::OkStatus()
              : absl::InternalError("AParcel_readInt64 failed");
 }
 
-absl::Status ReadableParcelAndroid::ReadBinder(
-    std::unique_ptr<Binder>* data) const {
+absl::Status ReadableParcelAndroid::ReadBinder(std::unique_ptr<Binder>* data) {
   AIBinder* binder;
   if (AParcel_readStrongBinder(parcel_, &binder) != STATUS_OK) {
     *data = nullptr;
@@ -276,36 +310,20 @@ absl::Status ReadableParcelAndroid::ReadBinder(
   return absl::OkStatus();
 }
 
-namespace {
-
-bool byte_array_allocator(void* arrayData, int32_t length, int8_t** outBuffer) {
-  std::string tmp;
-  tmp.resize(length);
-  *reinterpret_cast<std::string*>(arrayData) = tmp;
-  *outBuffer = reinterpret_cast<int8_t*>(
-      &(*reinterpret_cast<std::string*>(arrayData))[0]);
-  return true;
-}
-
-bool string_allocator(void* stringData, int32_t length, char** outBuffer) {
-  if (length > 0) {
-    // TODO(mingcl): Don't fix the length of the string
-    GPR_ASSERT(length < 100);  // call should preallocate 100 bytes
-    *outBuffer = reinterpret_cast<char*>(stringData);
+absl::Status ReadableParcelAndroid::ReadByteArray(std::string* data) {
+  std::vector<uint8_t> vec;
+  if (AParcelReadVector(parcel_, &vec) == STATUS_OK) {
+    data->resize(vec.size());
+    if (!vec.empty()) {
+      memcpy(&((*data)[0]), vec.data(), vec.size());
+    }
+    return absl::OkStatus();
   }
-  return true;
-}
-
-}  // namespace
-
-absl::Status ReadableParcelAndroid::ReadByteArray(std::string* data) const {
-  return AParcel_readByteArray(parcel_, data, byte_array_allocator) == STATUS_OK
-             ? absl::OkStatus()
-             : absl::InternalError("AParcel_readByteArray failed");
+  return absl::InternalError("AParcel_readByteArray failed");
 }
 
-absl::Status ReadableParcelAndroid::ReadString(char data[111]) const {
-  return AParcel_readString(parcel_, data, string_allocator) == STATUS_OK
+absl::Status ReadableParcelAndroid::ReadString(std::string* str) {
+  return AParcelReadString(parcel_, str) == STATUS_OK
              ? absl::OkStatus()
              : absl::InternalError("AParcel_readString failed");
 }
@@ -313,3 +331,4 @@ absl::Status ReadableParcelAndroid::ReadString(char data[111]) const {
 }  // namespace grpc_binder
 
 #endif  // GPR_SUPPORT_BINDER_TRANSPORT
+#endif
index 46fcd53..3d4f63e 100644 (file)
@@ -15,7 +15,7 @@
 #ifndef GRPC_CORE_EXT_TRANSPORT_BINDER_WIRE_FORMAT_BINDER_ANDROID_H
 #define GRPC_CORE_EXT_TRANSPORT_BINDER_WIRE_FORMAT_BINDER_ANDROID_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #ifdef GPR_SUPPORT_BINDER_TRANSPORT
 
@@ -44,9 +44,7 @@ class WritableParcelAndroid final : public WritableParcel {
   explicit WritableParcelAndroid(AParcel* parcel) : parcel_(parcel) {}
   ~WritableParcelAndroid() override = default;
 
-  int32_t GetDataPosition() const override;
   int32_t GetDataSize() const override;
-  absl::Status SetDataPosition(int32_t pos) override;
   absl::Status WriteInt32(int32_t data) override;
   absl::Status WriteInt64(int64_t data) override;
   absl::Status WriteBinder(HasRawBinder* binder) override;
@@ -63,20 +61,18 @@ class ReadableParcelAndroid final : public ReadableParcel {
  public:
   ReadableParcelAndroid() = default;
   // TODO(waynetu): Get rid of the const_cast.
-  explicit ReadableParcelAndroid(const AParcel* parcel)
-      : parcel_(const_cast<AParcel*>(parcel)) {}
+  explicit ReadableParcelAndroid(const AParcel* parcel) : parcel_(parcel) {}
   ~ReadableParcelAndroid() override = default;
 
   int32_t GetDataSize() const override;
-  absl::Status ReadInt32(int32_t* data) const override;
-  absl::Status ReadInt64(int64_t* data) const override;
-  absl::Status ReadBinder(std::unique_ptr<Binder>* data) const override;
-  absl::Status ReadByteArray(std::string* data) const override;
-  // FIXME(waynetu): Fix the interface.
-  absl::Status ReadString(char data[111]) const override;
+  absl::Status ReadInt32(int32_t* data) override;
+  absl::Status ReadInt64(int64_t* data) override;
+  absl::Status ReadBinder(std::unique_ptr<Binder>* data) override;
+  absl::Status ReadByteArray(std::string* data) override;
+  absl::Status ReadString(std::string* str) override;
 
  private:
-  AParcel* parcel_ = nullptr;
+  const AParcel* parcel_ = nullptr;
 
   friend class BinderAndroid;
 };
@@ -85,8 +81,7 @@ class BinderAndroid final : public Binder {
  public:
   explicit BinderAndroid(ndk::SpAIBinder binder)
       : binder_(binder),
-        input_parcel_(absl::make_unique<WritableParcelAndroid>()),
-        output_parcel_(absl::make_unique<ReadableParcelAndroid>()) {}
+        input_parcel_(absl::make_unique<WritableParcelAndroid>()) {}
   ~BinderAndroid() override = default;
 
   void* GetRawBinder() override { return binder_.get(); }
@@ -98,9 +93,6 @@ class BinderAndroid final : public Binder {
   WritableParcel* GetWritableParcel() const override {
     return input_parcel_.get();
   }
-  ReadableParcel* GetReadableParcel() const override {
-    return output_parcel_.get();
-  };
 
   std::unique_ptr<TransactionReceiver> ConstructTxReceiver(
       grpc_core::RefCountedPtr<WireReader> wire_reader_ref,
@@ -109,7 +101,6 @@ class BinderAndroid final : public Binder {
  private:
   ndk::SpAIBinder binder_;
   std::unique_ptr<WritableParcelAndroid> input_parcel_;
-  std::unique_ptr<ReadableParcelAndroid> output_parcel_;
 };
 
 class TransactionReceiverAndroid final : public TransactionReceiver {
index a4ca49d..a92f39b 100644 (file)
@@ -12,7 +12,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
+
+#ifndef GRPC_NO_BINDER
 
 #include "src/core/ext/transport/binder/wire_format/binder_constants.h"
 
@@ -28,3 +30,4 @@ namespace grpc_binder {
 const int kFirstCallId = FIRST_CALL_TRANSACTION + 1000;
 
 }  // namespace grpc_binder
+#endif
index e17e6d5..030dff0 100644 (file)
@@ -15,7 +15,7 @@
 #ifndef GRPC_CORE_EXT_TRANSPORT_BINDER_WIRE_FORMAT_BINDER_CONSTANTS_H
 #define GRPC_CORE_EXT_TRANSPORT_BINDER_WIRE_FORMAT_BINDER_CONSTANTS_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include "absl/base/attributes.h"
 
index aa16bce..939b557 100644 (file)
@@ -12,7 +12,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
+
+#ifndef GRPC_NO_BINDER
 
 #include "src/core/ext/transport/binder/wire_format/transaction.h"
 
@@ -28,3 +30,4 @@ const int kFlagMessageDataIsParcelable = 0x40;
 const int kFlagMessageDataIsPartial = 0x80;
 
 }  // namespace grpc_binder
+#endif
index 33e02a2..eb6d180 100644 (file)
@@ -15,7 +15,7 @@
 #ifndef GRPC_CORE_EXT_TRANSPORT_BINDER_WIRE_FORMAT_TRANSACTION_H
 #define GRPC_CORE_EXT_TRANSPORT_BINDER_WIRE_FORMAT_TRANSACTION_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include <string>
 #include <vector>
index c6d944a..8a5068e 100644 (file)
@@ -15,7 +15,7 @@
 #ifndef GRPC_CORE_EXT_TRANSPORT_BINDER_WIRE_FORMAT_WIRE_READER_H
 #define GRPC_CORE_EXT_TRANSPORT_BINDER_WIRE_FORMAT_WIRE_READER_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include <memory>
 #include <utility>
index 0c0d522..bba7c55 100644 (file)
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include "src/core/ext/transport/binder/wire_format/wire_reader_impl.h"
 
+#ifndef GRPC_NO_BINDER
+
 #include <functional>
 #include <limits>
 #include <string>
@@ -40,7 +42,7 @@
 namespace grpc_binder {
 namespace {
 
-absl::StatusOr<Metadata> parse_metadata(const ReadableParcel* reader) {
+absl::StatusOr<Metadata> parse_metadata(ReadableParcel* reader) {
   int num_header;
   RETURN_IF_ERROR(reader->ReadInt32(&num_header));
   gpr_log(GPR_INFO, "num_header = %d", num_header);
@@ -69,9 +71,12 @@ absl::StatusOr<Metadata> parse_metadata(const ReadableParcel* reader) {
 
 WireReaderImpl::WireReaderImpl(
     std::shared_ptr<TransportStreamReceiver> transport_stream_receiver,
-    bool is_client, std::function<void()> on_destruct_callback)
+    bool is_client,
+    std::shared_ptr<grpc::experimental::binder::SecurityPolicy> security_policy,
+    std::function<void()> on_destruct_callback)
     : transport_stream_receiver_(std::move(transport_stream_receiver)),
       is_client_(is_client),
+      security_policy_(security_policy),
       on_destruct_callback_(on_destruct_callback) {}
 
 WireReaderImpl::~WireReaderImpl() {
@@ -109,14 +114,9 @@ void WireReaderImpl::SendSetupTransport(Binder* binder) {
   gpr_log(GPR_INFO, "prepare transaction = %d",
           binder->PrepareTransaction().ok());
   WritableParcel* writable_parcel = binder->GetWritableParcel();
-  gpr_log(GPR_INFO, "data position = %d", writable_parcel->GetDataPosition());
-  // gpr_log(GPR_INFO, "set data position to 0 = %d",
-  // writer->SetDataPosition(0));
-  gpr_log(GPR_INFO, "data position = %d", writable_parcel->GetDataPosition());
   int32_t version = 77;
   gpr_log(GPR_INFO, "write int32 = %d",
           writable_parcel->WriteInt32(version).ok());
-  gpr_log(GPR_INFO, "data position = %d", writable_parcel->GetDataPosition());
   // The lifetime of the transaction receiver is the same as the wire writer's.
   // The transaction receiver is responsible for not calling the on-transact
   // callback when it's dead.
@@ -125,8 +125,9 @@ void WireReaderImpl::SendSetupTransport(Binder* binder) {
   // callback owns a Ref() when it's being invoked.
   tx_receiver_ = binder->ConstructTxReceiver(
       /*wire_reader_ref=*/Ref(),
-      [this](transaction_code_t code, const ReadableParcel* readable_parcel) {
-        return this->ProcessTransaction(code, readable_parcel);
+      [this](transaction_code_t code, ReadableParcel* readable_parcel,
+             int uid) {
+        return this->ProcessTransaction(code, readable_parcel, uid);
       });
 
   gpr_log(GPR_INFO, "tx_receiver = %p", tx_receiver_->GetRawBinder());
@@ -146,7 +147,8 @@ std::unique_ptr<Binder> WireReaderImpl::RecvSetupTransport() {
 }
 
 absl::Status WireReaderImpl::ProcessTransaction(transaction_code_t code,
-                                                const ReadableParcel* parcel) {
+                                                ReadableParcel* parcel,
+                                                int uid) {
   gpr_log(GPR_INFO, __func__);
   gpr_log(GPR_INFO, "tx code = %u", code);
   if (code >= static_cast<unsigned>(kFirstCallId)) {
@@ -171,6 +173,9 @@ absl::Status WireReaderImpl::ProcessTransaction(transaction_code_t code,
     return absl::InvalidArgumentError("Transports not connected yet");
   }
 
+  // TODO(mingcl): See if we want to check the security policy for every RPC
+  // call or just during transport setup.
+
   switch (BinderTransportTxCode(code)) {
     case BinderTransportTxCode::SETUP_TRANSPORT: {
       if (recvd_setup_transport_) {
@@ -178,13 +183,17 @@ absl::Status WireReaderImpl::ProcessTransaction(transaction_code_t code,
             "Already received a SETUP_TRANSPORT request");
       }
       recvd_setup_transport_ = true;
-      // int datasize;
+
+      gpr_log(GPR_ERROR, "calling uid = %d", uid);
+      if (!security_policy_->IsAuthorized(uid)) {
+        return absl::PermissionDeniedError(
+            "UID " + std::to_string(uid) +
+            " is not allowed to connect to this "
+            "transport according to security policy.");
+      }
+
       int version;
-      // getDataSize not supported until 31
-      // gpr_log(GPR_INFO, "getDataSize = %d", AParcel_getDataSize(in,
-      // &datasize));
       RETURN_IF_ERROR(parcel->ReadInt32(&version));
-      // gpr_log(GPR_INFO, "data size = %d", datasize);
       gpr_log(GPR_INFO, "version = %d", version);
       std::unique_ptr<Binder> binder{};
       RETURN_IF_ERROR(parcel->ReadBinder(&binder));
@@ -230,7 +239,7 @@ absl::Status WireReaderImpl::ProcessTransaction(transaction_code_t code,
 }
 
 absl::Status WireReaderImpl::ProcessStreamingTransaction(
-    transaction_code_t code, const ReadableParcel* parcel) {
+    transaction_code_t code, ReadableParcel* parcel) {
   grpc_core::MutexLock lock(&mu_);
   if (!connected_) {
     return absl::InvalidArgumentError("Transports not connected yet");
@@ -272,8 +281,7 @@ absl::Status WireReaderImpl::ProcessStreamingTransaction(
 }
 
 absl::Status WireReaderImpl::ProcessStreamingTransactionImpl(
-    transaction_code_t code, const ReadableParcel* parcel,
-    int* cancellation_flags) {
+    transaction_code_t code, ReadableParcel* parcel, int* cancellation_flags) {
   GPR_ASSERT(cancellation_flags);
   num_incoming_bytes_ += parcel->GetDataSize();
 
@@ -316,10 +324,9 @@ absl::Status WireReaderImpl::ProcessStreamingTransactionImpl(
   expectation++;
   gpr_log(GPR_INFO, "sequence number = %d", seq_num);
   if (flags & kFlagPrefix) {
-    char method_ref[111];
-    memset(method_ref, 0, sizeof(method_ref));
+    std::string method_ref;
     if (!is_client_) {
-      RETURN_IF_ERROR(parcel->ReadString(method_ref));
+      RETURN_IF_ERROR(parcel->ReadString(&method_ref));
     }
     absl::StatusOr<Metadata> initial_metadata_or_error = parse_metadata(parcel);
     if (!initial_metadata_or_error.ok()) {
@@ -353,10 +360,9 @@ absl::Status WireReaderImpl::ProcessStreamingTransactionImpl(
   if (flags & kFlagSuffix) {
     if (flags & kFlagStatusDescription) {
       // FLAG_STATUS_DESCRIPTION set
-      char desc[111];
-      memset(desc, 0, sizeof(desc));
-      RETURN_IF_ERROR(parcel->ReadString(desc));
-      gpr_log(GPR_INFO, "description = %s", desc);
+      std::string desc;
+      RETURN_IF_ERROR(parcel->ReadString(&desc));
+      gpr_log(GPR_INFO, "description = %s", desc.c_str());
     }
     Metadata trailing_metadata;
     if (is_client_) {
@@ -375,3 +381,4 @@ absl::Status WireReaderImpl::ProcessStreamingTransactionImpl(
 }
 
 }  // namespace grpc_binder
+#endif
index db1f7d5..24043ac 100644 (file)
@@ -15,7 +15,7 @@
 #ifndef GRPC_CORE_EXT_TRANSPORT_BINDER_WIRE_FORMAT_WIRE_READER_IMPL_H
 #define GRPC_CORE_EXT_TRANSPORT_BINDER_WIRE_FORMAT_WIRE_READER_IMPL_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include <memory>
 #include <utility>
@@ -23,6 +23,8 @@
 #include "absl/container/flat_hash_map.h"
 #include "absl/synchronization/notification.h"
 
+#include <grpcpp/security/binder_security_policy.h>
+
 #include "src/core/ext/transport/binder/utils/transport_stream_receiver.h"
 #include "src/core/ext/transport/binder/wire_format/binder.h"
 #include "src/core/ext/transport/binder/wire_format/wire_reader.h"
@@ -34,7 +36,10 @@ class WireReaderImpl : public WireReader {
  public:
   WireReaderImpl(
       std::shared_ptr<TransportStreamReceiver> transport_stream_receiver,
-      bool is_client, std::function<void()> on_destruct_callback = nullptr);
+      bool is_client,
+      std::shared_ptr<grpc::experimental::binder::SecurityPolicy>
+          security_policy,
+      std::function<void()> on_destruct_callback = nullptr);
   ~WireReaderImpl() override;
 
   void Orphan() override { Unref(); }
@@ -67,7 +72,7 @@ class WireReaderImpl : public WireReader {
       std::unique_ptr<Binder> binder) override;
 
   absl::Status ProcessTransaction(transaction_code_t code,
-                                  const ReadableParcel* parcel);
+                                  ReadableParcel* parcel, int uid);
 
   /// Send SETUP_TRANSPORT request through \p binder.
   ///
@@ -93,9 +98,9 @@ class WireReaderImpl : public WireReader {
 
  private:
   absl::Status ProcessStreamingTransaction(transaction_code_t code,
-                                           const ReadableParcel* parcel);
+                                           ReadableParcel* parcel);
   absl::Status ProcessStreamingTransactionImpl(transaction_code_t code,
-                                               const ReadableParcel* parcel,
+                                               ReadableParcel* parcel,
                                                int* cancellation_flags)
       ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
 
@@ -113,6 +118,7 @@ class WireReaderImpl : public WireReader {
       ABSL_GUARDED_BY(mu_);
   std::unique_ptr<TransactionReceiver> tx_receiver_;
   bool is_client_;
+  std::shared_ptr<grpc::experimental::binder::SecurityPolicy> security_policy_;
   // When WireReaderImpl gets destructed, call on_destruct_callback_. This is
   // mostly for decrementing the reference count of its transport.
   std::function<void()> on_destruct_callback_;
index 3540941..fe796a9 100644 (file)
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include "src/core/ext/transport/binder/wire_format/wire_writer.h"
 
+#ifndef GRPC_NO_BINDER
+
 #include <utility>
 
 #include <grpc/support/log.h>
@@ -179,3 +181,4 @@ void WireWriterImpl::OnAckReceived(int64_t num_bytes) {
 }
 
 }  // namespace grpc_binder
+#endif
index 765c6e6..52b082b 100644 (file)
@@ -15,7 +15,7 @@
 #ifndef GRPC_CORE_EXT_TRANSPORT_BINDER_WIRE_FORMAT_WIRE_WRITER_H
 #define GRPC_CORE_EXT_TRANSPORT_BINDER_WIRE_FORMAT_WIRE_WRITER_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include <string>
 #include <vector>
diff --git a/src/core/ext/transport/chttp2/client/authority.cc b/src/core/ext/transport/chttp2/client/authority.cc
deleted file mode 100644 (file)
index 8e4f8c1..0000000
+++ /dev/null
@@ -1,42 +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 <grpc/support/port_platform.h>
-
-#include "src/core/ext/transport/chttp2/client/authority.h"
-
-grpc_channel_args* grpc_default_authority_add_if_not_present(
-    const grpc_channel_args* args) {
-  const bool has_default_authority =
-      grpc_channel_args_find(args, GRPC_ARG_DEFAULT_AUTHORITY) != nullptr;
-  grpc_arg new_args[1];
-  size_t num_new_args = 0;
-  std::string default_authority;
-  if (!has_default_authority) {
-    const grpc_arg* server_uri_arg =
-        grpc_channel_args_find(args, GRPC_ARG_SERVER_URI);
-    const char* server_uri_str = grpc_channel_arg_get_string(server_uri_arg);
-    GPR_ASSERT(server_uri_str != nullptr);
-    default_authority =
-        grpc_core::ResolverRegistry::GetDefaultAuthority(server_uri_str);
-    new_args[num_new_args++] = grpc_channel_arg_string_create(
-        const_cast<char*>(GRPC_ARG_DEFAULT_AUTHORITY),
-        const_cast<char*>(default_authority.c_str()));
-  }
-  return grpc_channel_args_copy_and_add(args, new_args, num_new_args);
-}
diff --git a/src/core/ext/transport/chttp2/client/authority.h b/src/core/ext/transport/chttp2/client/authority.h
deleted file mode 100644 (file)
index 642584e..0000000
+++ /dev/null
@@ -1,36 +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.
- *
- */
-
-#ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_CLIENT_AUTHORITY_H
-#define GRPC_CORE_EXT_TRANSPORT_CHTTP2_CLIENT_AUTHORITY_H
-
-#include <grpc/support/port_platform.h>
-
-#include <grpc/grpc.h>
-
-#include "src/core/ext/filters/client_channel/client_channel.h"
-#include "src/core/ext/filters/client_channel/resolver_registry.h"
-#include "src/core/lib/channel/channel_args.h"
-#include "src/core/lib/gprpp/memory.h"
-
-/// Returns a copy of \a args with the default authority channel arg set if it
-/// wasn't already present.
-grpc_channel_args* grpc_default_authority_add_if_not_present(
-    const grpc_channel_args* args);
-
-#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_CLIENT_AUTHORITY_H */
index 96dd4eb..03e95a1 100644 (file)
@@ -28,7 +28,6 @@
 #include <grpc/support/string_util.h>
 
 #include "src/core/ext/filters/client_channel/connector.h"
-#include "src/core/ext/filters/client_channel/subchannel.h"
 #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
 #include "src/core/lib/address_utils/sockaddr_utils.h"
 #include "src/core/lib/channel/channel_args.h"
@@ -54,8 +53,6 @@ Chttp2Connector::~Chttp2Connector() {
 
 void Chttp2Connector::Connect(const Args& args, Result* result,
                               grpc_closure* notify) {
-  grpc_resolved_address addr;
-  Subchannel::GetAddressFromSubchannelAddressArg(args.channel_args, &addr);
   grpc_endpoint** ep;
   {
     MutexLock lock(&mu_);
@@ -83,9 +80,9 @@ void Chttp2Connector::Connect(const Args& args, Result* result,
   grpc_tcp_client_connect(
       &connected_, ep,
       grpc_slice_allocator_create(resource_quota_,
-                                  grpc_sockaddr_to_string(&addr, false),
+                                  grpc_sockaddr_to_string(args.address, false),
                                   args.channel_args),
-      args.interested_parties, args.channel_args, &addr, args.deadline);
+      args.interested_parties, args.channel_args, args.address, args.deadline);
 }
 
 void Chttp2Connector::Shutdown(grpc_error_handle error) {
index 40b3f6d..8d5674a 100644 (file)
@@ -1,20 +1,18 @@
-/*
- *
- * 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.
- *
- */
+//
+// 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>
 
@@ -26,7 +24,6 @@
 
 #include "src/core/ext/filters/client_channel/client_channel.h"
 #include "src/core/ext/filters/client_channel/resolver_registry.h"
-#include "src/core/ext/transport/chttp2/client/authority.h"
 #include "src/core/ext/transport/chttp2/client/chttp2_connector.h"
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/surface/api_trace.h"
@@ -37,13 +34,9 @@ namespace grpc_core {
 class Chttp2InsecureClientChannelFactory : public ClientChannelFactory {
  public:
   RefCountedPtr<Subchannel> CreateSubchannel(
+      const grpc_resolved_address& address,
       const grpc_channel_args* args) override {
-    grpc_channel_args* new_args =
-        grpc_default_authority_add_if_not_present(args);
-    RefCountedPtr<Subchannel> s =
-        Subchannel::Create(MakeOrphanable<Chttp2Connector>(), new_args);
-    grpc_channel_args_destroy(new_args);
-    return s;
+    return Subchannel::Create(MakeOrphanable<Chttp2Connector>(), address, args);
   }
 };
 
@@ -95,6 +88,7 @@ grpc_channel* grpc_insecure_channel_create(const char* target,
                                            const grpc_channel_args* args,
                                            void* reserved) {
   grpc_core::ExecCtx exec_ctx;
+  args = grpc_channel_args_remove_grpc_internal(args);
   GRPC_API_TRACE(
       "grpc_insecure_channel_create(target=%s, args=%p, reserved=%p)", 3,
       (target, args, reserved));
@@ -110,6 +104,7 @@ grpc_channel* grpc_insecure_channel_create(const char* target,
   grpc_channel* channel = grpc_core::CreateChannel(target, new_args, &error);
   // Clean up.
   grpc_channel_args_destroy(new_args);
+  grpc_channel_args_destroy(args);
   if (channel == nullptr) {
     intptr_t integer;
     grpc_status_code status = GRPC_STATUS_INTERNAL;
index e6fccf6..68cd3a9 100644 (file)
@@ -1,20 +1,18 @@
-/*
- *
- * 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.
- *
- */
+//
+// 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>
 
@@ -35,7 +33,6 @@
 #include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/surface/api_trace.h"
 #include "src/core/lib/surface/channel.h"
-#include "src/core/lib/transport/authority_override.h"
 #include "src/core/lib/uri/uri_parser.h"
 
 namespace grpc_core {
@@ -43,6 +40,7 @@ namespace grpc_core {
 class Chttp2SecureClientChannelFactory : public ClientChannelFactory {
  public:
   RefCountedPtr<Subchannel> CreateSubchannel(
+      const grpc_resolved_address& address,
       const grpc_channel_args* args) override {
     grpc_channel_args* new_args = GetSecureNamingChannelArgs(args);
     if (new_args == nullptr) {
@@ -50,8 +48,8 @@ class Chttp2SecureClientChannelFactory : public ClientChannelFactory {
               "Failed to create channel args during subchannel creation.");
       return nullptr;
     }
-    RefCountedPtr<Subchannel> s =
-        Subchannel::Create(MakeOrphanable<Chttp2Connector>(), new_args);
+    RefCountedPtr<Subchannel> s = Subchannel::Create(
+        MakeOrphanable<Chttp2Connector>(), address, new_args);
     grpc_channel_args_destroy(new_args);
     return s;
   }
@@ -75,52 +73,29 @@ class Chttp2SecureClientChannelFactory : public ClientChannelFactory {
       return nullptr;
     }
     // Find the authority to use in the security connector.
-    // First, check the authority override channel arg.
-    // Otherwise, get it from the server name used to construct the
-    // channel.
-    std::string authority(FindAuthorityOverrideInArgs(args));
-    if (authority.empty()) {
-      const char* server_uri_str =
-          grpc_channel_args_find_string(args, GRPC_ARG_SERVER_URI);
-      GPR_ASSERT(server_uri_str != nullptr);
-      authority = ResolverRegistry::GetDefaultAuthority(server_uri_str);
-    }
-    grpc_arg args_to_add[2];
-    size_t num_args_to_add = 0;
-    if (grpc_channel_args_find(args, GRPC_ARG_DEFAULT_AUTHORITY) == nullptr) {
-      // If the channel args don't already contain GRPC_ARG_DEFAULT_AUTHORITY,
-      // add the arg, setting it to the value just obtained.
-      args_to_add[num_args_to_add++] = grpc_channel_arg_string_create(
-          const_cast<char*>(GRPC_ARG_DEFAULT_AUTHORITY),
-          const_cast<char*>(authority.c_str()));
-    }
-    grpc_channel_args* args_with_authority =
-        grpc_channel_args_copy_and_add(args, args_to_add, num_args_to_add);
+    const char* authority =
+        grpc_channel_args_find_string(args, GRPC_ARG_DEFAULT_AUTHORITY);
+    GPR_ASSERT(authority != nullptr);
     // Create the security connector using the credentials and target name.
     grpc_channel_args* new_args_from_connector = nullptr;
     RefCountedPtr<grpc_channel_security_connector>
         subchannel_security_connector =
             channel_credentials->create_security_connector(
-                /*call_creds=*/nullptr, authority.c_str(), args_with_authority,
+                /*call_creds=*/nullptr, authority, args,
                 &new_args_from_connector);
     if (subchannel_security_connector == nullptr) {
       gpr_log(GPR_ERROR,
               "Failed to create secure subchannel for secure name '%s'",
-              authority.c_str());
-      grpc_channel_args_destroy(args_with_authority);
+              authority);
       return nullptr;
     }
     grpc_arg new_security_connector_arg =
         grpc_security_connector_to_arg(subchannel_security_connector.get());
     grpc_channel_args* new_args = grpc_channel_args_copy_and_add(
-        new_args_from_connector != nullptr ? new_args_from_connector
-                                           : args_with_authority,
+        new_args_from_connector != nullptr ? new_args_from_connector : args,
         &new_security_connector_arg, 1);
     subchannel_security_connector.reset(DEBUG_LOCATION, "lb_channel_create");
-    if (new_args_from_connector != nullptr) {
-      grpc_channel_args_destroy(new_args_from_connector);
-    }
-    grpc_channel_args_destroy(args_with_authority);
+    grpc_channel_args_destroy(new_args_from_connector);
     return new_args;
   }
 };
@@ -179,6 +154,7 @@ grpc_channel* grpc_secure_channel_create(grpc_channel_credentials* creds,
       "reserved=%p)",
       4, ((void*)creds, target, (void*)args, (void*)reserved));
   GPR_ASSERT(reserved == nullptr);
+  args = grpc_channel_args_remove_grpc_internal(args);
   grpc_channel* channel = nullptr;
   grpc_error_handle error = GRPC_ERROR_NONE;
   if (creds != nullptr) {
@@ -198,6 +174,7 @@ grpc_channel* grpc_secure_channel_create(grpc_channel_credentials* creds,
     // Clean up.
     grpc_channel_args_destroy(new_args);
   }
+  grpc_channel_args_destroy(args);
   if (channel == nullptr) {
     intptr_t integer;
     grpc_status_code status = GRPC_STATUS_INTERNAL;
index 8d330ae..c2e1e14 100644 (file)
@@ -221,10 +221,10 @@ class Chttp2ServerListener : public Server::ListenerInterface {
   grpc_resolved_address resolved_address_;
   Chttp2ServerArgsModifier const args_modifier_;
   ConfigFetcherWatcher* config_fetcher_watcher_ = nullptr;
-  Mutex channel_args_mu_;
-  grpc_channel_args* args_ ABSL_GUARDED_BY(channel_args_mu_);
+  grpc_channel_args* args_;
+  Mutex connection_manager_mu_;
   RefCountedPtr<grpc_server_config_fetcher::ConnectionManager>
-      connection_manager_ ABSL_GUARDED_BY(channel_args_mu_);
+      connection_manager_ ABSL_GUARDED_BY(connection_manager_mu_);
   Mutex mu_;
   // Signals whether grpc_tcp_server_start() has been called.
   bool started_ ABSL_GUARDED_BY(mu_) = false;
@@ -252,7 +252,7 @@ void Chttp2ServerListener::ConfigFetcherWatcher::UpdateConnectionManager(
   RefCountedPtr<grpc_server_config_fetcher::ConnectionManager>
       connection_manager_to_destroy;
   {
-    MutexLock lock(&listener_->channel_args_mu_);
+    MutexLock lock(&listener_->connection_manager_mu_);
     connection_manager_to_destroy = listener_->connection_manager_;
     listener_->connection_manager_ = std::move(connection_manager);
   }
@@ -596,6 +596,7 @@ grpc_error_handle Chttp2ServerListener::Create(
   // The bulk of this method is inside of a lambda to make cleanup
   // easier without using goto.
   grpc_error_handle error = [&]() {
+    grpc_error_handle error = GRPC_ERROR_NONE;
     // Create Chttp2ServerListener.
     listener = new Chttp2ServerListener(
         server, args, args_modifier,
@@ -692,16 +693,10 @@ Chttp2ServerListener::~Chttp2ServerListener() {
 void Chttp2ServerListener::Start(
     Server* /*server*/, const std::vector<grpc_pollset*>* /* pollsets */) {
   if (server_->config_fetcher() != nullptr) {
-    grpc_channel_args* args = nullptr;
     auto watcher = absl::make_unique<ConfigFetcherWatcher>(Ref());
     config_fetcher_watcher_ = watcher.get();
-    {
-      MutexLock lock(&channel_args_mu_);
-      args = grpc_channel_args_copy(args_);
-    }
     server_->config_fetcher()->StartWatch(
-        grpc_sockaddr_to_string(&resolved_address_, false), args,
-        std::move(watcher));
+        grpc_sockaddr_to_string(&resolved_address_, false), std::move(watcher));
   } else {
     {
       MutexLock lock(&mu_);
@@ -725,12 +720,12 @@ void Chttp2ServerListener::OnAccept(void* arg, grpc_endpoint* tcp,
                                     grpc_pollset* accepting_pollset,
                                     grpc_tcp_server_acceptor* acceptor) {
   Chttp2ServerListener* self = static_cast<Chttp2ServerListener*>(arg);
-  grpc_channel_args* args = nullptr;
+  grpc_channel_args* args = self->args_;
+  grpc_channel_args* args_to_destroy = nullptr;
   RefCountedPtr<grpc_server_config_fetcher::ConnectionManager>
       connection_manager;
   {
-    MutexLock lock(&self->channel_args_mu_);
-    args = grpc_channel_args_copy(self->args_);
+    MutexLock lock(&self->connection_manager_mu_);
     connection_manager = self->connection_manager_;
   }
   auto endpoint_cleanup = [&](grpc_error_handle error) {
@@ -743,11 +738,12 @@ void Chttp2ServerListener::OnAccept(void* arg, grpc_endpoint* tcp,
       grpc_error_handle error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
           "No ConnectionManager configured. Closing connection.");
       endpoint_cleanup(error);
-      grpc_channel_args_destroy(args);
       return;
     }
     // TODO(yashykt): Maybe combine the following two arg modifiers into a
     // single one.
+    // Make a copy of the args so as to avoid destroying the original.
+    args = grpc_channel_args_copy(args);
     absl::StatusOr<grpc_channel_args*> args_result =
         connection_manager->UpdateChannelArgsForConnection(args, tcp);
     if (!args_result.ok()) {
@@ -766,6 +762,7 @@ void Chttp2ServerListener::OnAccept(void* arg, grpc_endpoint* tcp,
       grpc_channel_args_destroy(args);
       return;
     }
+    args_to_destroy = args;
   }
   grpc_resource_user* channel_resource_user = grpc_resource_user_create(
       self->resource_quota_,
@@ -803,7 +800,7 @@ void Chttp2ServerListener::OnAccept(void* arg, grpc_endpoint* tcp,
   } else {
     connection_ref->Start(std::move(listener_ref), tcp, args);
   }
-  grpc_channel_args_destroy(args);
+  grpc_channel_args_destroy(args_to_destroy);
 }
 
 void Chttp2ServerListener::TcpServerShutdownComplete(void* arg,
@@ -861,6 +858,7 @@ grpc_error_handle Chttp2ServerAddPort(Server* server, const char* addr,
   std::vector<grpc_error_handle> error_list;
   // Using lambda to avoid use of goto.
   grpc_error_handle error = [&]() {
+    grpc_error_handle error = GRPC_ERROR_NONE;
     if (absl::StartsWith(addr, kUnixUriPrefix)) {
       error = grpc_resolve_unix_domain_address(
           addr + sizeof(kUnixUriPrefix) - 1, &resolved);
diff --git a/src/core/ext/transport/chttp2/transport/chttp2_slice_allocator.cc b/src/core/ext/transport/chttp2/transport/chttp2_slice_allocator.cc
deleted file mode 100644 (file)
index 05742ce..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2021 The gRPC Authors
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-#include <grpc/support/port_platform.h>
-
-#include "src/core/ext/transport/chttp2/transport/chttp2_slice_allocator.h"
-
-#include <functional>
-
-#include "absl/memory/memory.h"
-#include "absl/status/status.h"
-
-#include <grpc/event_engine/slice_allocator.h>
-
-#include "src/core/lib/iomgr/resource_quota.h"
-
-namespace grpc_event_engine {
-namespace experimental {
-
-Chttp2SliceAllocator::Chttp2SliceAllocator(grpc_resource_user* user)
-    : resource_user_(user) {}
-
-Chttp2SliceAllocator::~Chttp2SliceAllocator() {
-  if (resource_user_ != nullptr) {
-    grpc_resource_user_unref(resource_user_);
-  }
-}
-
-absl::Status Chttp2SliceAllocator::Allocate(
-    size_t size, SliceBuffer* dest, SliceAllocator::AllocateCallback cb) {
-  // TODO(hork): merge the implementation from the uv-ee branch.
-  (void)size;
-  (void)dest;
-  (void)cb;
-  return absl::OkStatus();
-}
-
-Chttp2SliceAllocatorFactory::Chttp2SliceAllocatorFactory(
-    grpc_resource_quota* quota)
-    : resource_quota_(quota) {
-  grpc_resource_quota_ref_internal(resource_quota_);
-}
-
-Chttp2SliceAllocatorFactory::~Chttp2SliceAllocatorFactory() {
-  if (resource_quota_ != nullptr) {
-    grpc_resource_quota_unref_internal(resource_quota_);
-  }
-}
-
-std::unique_ptr<SliceAllocator>
-Chttp2SliceAllocatorFactory::CreateSliceAllocator(absl::string_view peer_name) {
-  return absl::make_unique<Chttp2SliceAllocator>(
-      grpc_resource_user_create(resource_quota_, peer_name));
-}
-
-}  // namespace experimental
-}  // namespace grpc_event_engine
diff --git a/src/core/ext/transport/chttp2/transport/chttp2_slice_allocator.h b/src/core/ext/transport/chttp2/transport/chttp2_slice_allocator.h
deleted file mode 100644 (file)
index 01b7d77..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2021 The gRPC Authors
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-#ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_CHTTP2_SLICE_ALLOCATOR_H
-#define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_CHTTP2_SLICE_ALLOCATOR_H
-
-#include <grpc/support/port_platform.h>
-
-#include <functional>
-
-#include "absl/status/status.h"
-
-#include <grpc/event_engine/slice_allocator.h>
-
-#include "src/core/lib/iomgr/resource_quota.h"
-
-namespace grpc_event_engine {
-namespace experimental {
-
-class Chttp2SliceAllocator
-    : public grpc_event_engine::experimental::SliceAllocator {
- public:
-  /// gRPC-internal constructor. Takes ownership of a resource_user ref from the
-  /// caller.
-  explicit Chttp2SliceAllocator(grpc_resource_user* user);
-  // Not copyable
-  Chttp2SliceAllocator(Chttp2SliceAllocator& other) = delete;
-  Chttp2SliceAllocator& operator=(const Chttp2SliceAllocator& other) = delete;
-  // Not Moveable
-  Chttp2SliceAllocator(Chttp2SliceAllocator&& other) = delete;
-  Chttp2SliceAllocator& operator=(Chttp2SliceAllocator&& other) = delete;
-  ~Chttp2SliceAllocator() override;
-  absl::Status Allocate(size_t size, SliceBuffer* dest,
-                        SliceAllocator::AllocateCallback cb) override;
-
- private:
-  grpc_resource_user* resource_user_;
-};
-
-class Chttp2SliceAllocatorFactory
-    : public grpc_event_engine::experimental::SliceAllocatorFactory {
- public:
-  // gRPC-internal constructor
-  explicit Chttp2SliceAllocatorFactory(grpc_resource_quota* quota);
-  // Not copyable
-  Chttp2SliceAllocatorFactory(Chttp2SliceAllocatorFactory& other) = delete;
-  Chttp2SliceAllocatorFactory& operator=(
-      const Chttp2SliceAllocatorFactory& other) = delete;
-  // Not Moveable
-  Chttp2SliceAllocatorFactory(Chttp2SliceAllocatorFactory&& other) = delete;
-  Chttp2SliceAllocatorFactory& operator=(Chttp2SliceAllocatorFactory&& other) =
-      delete;
-  ~Chttp2SliceAllocatorFactory() override;
-  std::unique_ptr<SliceAllocator> CreateSliceAllocator(
-      absl::string_view peer_name) override;
-
- private:
-  grpc_resource_quota* resource_quota_;
-};
-
-}  // namespace experimental
-}  // namespace grpc_event_engine
-
-#endif  // GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_CHTTP2_SLICE_ALLOCATOR_H
index 80b1d31..adada28 100644 (file)
@@ -646,8 +646,8 @@ grpc_chttp2_stream::grpc_chttp2_stream(grpc_chttp2_transport* t,
     : t(t),
       refcount(refcount),
       reffer(this),
-      metadata_buffer{grpc_chttp2_incoming_metadata_buffer(arena),
-                      grpc_chttp2_incoming_metadata_buffer(arena)} {
+      initial_metadata_buffer(arena),
+      trailing_metadata_buffer(arena) {
   if (server_data) {
     id = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(server_data));
     *t->accepting_stream = this;
@@ -1064,7 +1064,7 @@ static void queue_setting_update(grpc_chttp2_transport* t,
                                  grpc_chttp2_setting_id id, uint32_t value) {
   const grpc_chttp2_setting_parameters* sp =
       &grpc_chttp2_settings_parameters[id];
-  uint32_t use_value = GPR_CLAMP(value, sp->min_value, sp->max_value);
+  uint32_t use_value = grpc_core::Clamp(value, sp->min_value, sp->max_value);
   if (use_value != value) {
     gpr_log(GPR_INFO, "Requested parameter %s clamped from %d to %d", sp->name,
             value, use_value);
@@ -1078,7 +1078,7 @@ static void queue_setting_update(grpc_chttp2_transport* t,
 void grpc_chttp2_add_incoming_goaway(grpc_chttp2_transport* t,
                                      uint32_t goaway_error,
                                      uint32_t last_stream_id,
-                                     const grpc_slice& goaway_text) {
+                                     absl::string_view goaway_text) {
   // Discard the error from a previous goaway frame (if any)
   if (t->goaway_error != GRPC_ERROR_NONE) {
     GRPC_ERROR_UNREF(t->goaway_error);
@@ -1107,7 +1107,7 @@ void grpc_chttp2_add_incoming_goaway(grpc_chttp2_transport* t,
   // for new connections on that channel.
   if (GPR_UNLIKELY(t->is_client &&
                    goaway_error == GRPC_HTTP2_ENHANCE_YOUR_CALM &&
-                   grpc_slice_str_cmp(goaway_text, "too_many_pings") == 0)) {
+                   goaway_text == "too_many_pings")) {
     gpr_log(GPR_ERROR,
             "Received a GOAWAY with error code ENHANCE_YOUR_CALM and debug "
             "data equal to \"too_many_pings\"");
@@ -1230,9 +1230,9 @@ void grpc_chttp2_complete_closure_step(grpc_chttp2_transport* t,
     if (closure->error_data.error == GRPC_ERROR_NONE) {
       closure->error_data.error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
           "Error in HTTP transport completing operation");
-      closure->error_data.error = grpc_error_set_str(
-          closure->error_data.error, GRPC_ERROR_STR_TARGET_ADDRESS,
-          grpc_slice_from_copied_string(t->peer_string.c_str()));
+      closure->error_data.error =
+          grpc_error_set_str(closure->error_data.error,
+                             GRPC_ERROR_STR_TARGET_ADDRESS, t->peer_string);
     }
     closure->error_data.error =
         grpc_error_add_child(closure->error_data.error, error);
@@ -1252,9 +1252,10 @@ void grpc_chttp2_complete_closure_step(grpc_chttp2_transport* t,
 }
 
 static bool contains_non_ok_status(grpc_metadata_batch* batch) {
-  if (batch->idx.named.grpc_status != nullptr) {
-    return !grpc_mdelem_static_value_eq(batch->idx.named.grpc_status->md,
-                                        GRPC_MDELEM_GRPC_STATUS_0);
+  if (batch->legacy_index()->named.grpc_status != nullptr) {
+    return !grpc_mdelem_static_value_eq(
+        batch->legacy_index()->named.grpc_status->md,
+        GRPC_MDELEM_GRPC_STATUS_0);
   }
   return false;
 }
@@ -1349,15 +1350,14 @@ static void complete_fetch_locked(void* gs, grpc_error_handle error) {
 
 static void log_metadata(const grpc_metadata_batch* md_batch, uint32_t id,
                          bool is_client, bool is_initial) {
-  for (grpc_linked_mdelem* md = md_batch->list.head; md != nullptr;
-       md = md->next) {
-    char* key = grpc_slice_to_c_string(GRPC_MDKEY(md->md));
-    char* value = grpc_slice_to_c_string(GRPC_MDVALUE(md->md));
+  md_batch->ForEach([=](grpc_mdelem md) {
+    char* key = grpc_slice_to_c_string(GRPC_MDKEY(md));
+    char* value = grpc_slice_to_c_string(GRPC_MDVALUE(md));
     gpr_log(GPR_INFO, "HTTP:%d:%s:%s: %s: %s", id, is_initial ? "HDR" : "TRL",
             is_client ? "CLI" : "SVR", key, value);
     gpr_free(key);
     gpr_free(value);
-  }
+  });
 }
 
 static void perform_stream_op_locked(void* stream_op,
@@ -1411,12 +1411,13 @@ static void perform_stream_op_locked(void* stream_op,
     on_complete->next_data.scratch |= CLOSURE_BARRIER_MAY_COVER_WRITE;
 
     // Identify stream compression
-    if (op_payload->send_initial_metadata.send_initial_metadata->idx.named
-                .content_encoding == nullptr ||
+    if (op_payload->send_initial_metadata.send_initial_metadata->legacy_index()
+                ->named.content_encoding == nullptr ||
         grpc_stream_compression_method_parse(
             GRPC_MDVALUE(
-                op_payload->send_initial_metadata.send_initial_metadata->idx
-                    .named.content_encoding->md),
+                op_payload->send_initial_metadata.send_initial_metadata
+                    ->legacy_index()
+                    ->named.content_encoding->md),
             true, &s->stream_compression_method) == 0) {
       s->stream_compression_method = GRPC_STREAM_COMPRESSION_IDENTITY_COMPRESS;
     }
@@ -1430,7 +1431,10 @@ static void perform_stream_op_locked(void* stream_op,
     s->send_initial_metadata =
         op_payload->send_initial_metadata.send_initial_metadata;
     if (t->is_client) {
-      s->deadline = GPR_MIN(s->deadline, s->send_initial_metadata->deadline);
+      s->deadline = std::min(
+          s->deadline,
+          s->send_initial_metadata->get(grpc_core::GrpcTimeoutMetadata())
+              .value_or(GRPC_MILLIS_INF_FUTURE));
     }
     if (contains_non_ok_status(s->send_initial_metadata)) {
       s->seen_error = true;
@@ -1536,8 +1540,7 @@ static void perform_stream_op_locked(void* stream_op,
       s->sent_trailing_metadata_op = nullptr;
       grpc_chttp2_complete_closure_step(
           t, s, &s->send_trailing_metadata_finished,
-          grpc_metadata_batch_is_empty(
-              op->payload->send_trailing_metadata.send_trailing_metadata)
+          op->payload->send_trailing_metadata.send_trailing_metadata->empty()
               ? GRPC_ERROR_NONE
               : GRPC_ERROR_CREATE_FROM_STATIC_STRING(
                     "Attempt to send trailing metadata after "
@@ -1623,14 +1626,14 @@ static void perform_stream_op(grpc_transport* gt, grpc_stream* gs,
 
   if (!t->is_client) {
     if (op->send_initial_metadata) {
-      grpc_millis deadline =
-          op->payload->send_initial_metadata.send_initial_metadata->deadline;
-      GPR_ASSERT(deadline == GRPC_MILLIS_INF_FUTURE);
+      GPR_ASSERT(!op->payload->send_initial_metadata.send_initial_metadata
+                      ->get(grpc_core::GrpcTimeoutMetadata())
+                      .has_value());
     }
     if (op->send_trailing_metadata) {
-      grpc_millis deadline =
-          op->payload->send_trailing_metadata.send_trailing_metadata->deadline;
-      GPR_ASSERT(deadline == GRPC_MILLIS_INF_FUTURE);
+      GPR_ASSERT(!op->payload->send_trailing_metadata.send_trailing_metadata
+                      ->get(grpc_core::GrpcTimeoutMetadata())
+                      .has_value());
     }
   }
 
@@ -1749,12 +1752,12 @@ static void send_goaway(grpc_chttp2_transport* t, grpc_error_handle error) {
           grpc_error_std_string(error).c_str());
   t->sent_goaway_state = GRPC_CHTTP2_GOAWAY_SEND_SCHEDULED;
   grpc_http2_error_code http_error;
-  grpc_slice slice;
-  grpc_error_get_status(error, GRPC_MILLIS_INF_FUTURE, nullptr, &slice,
+  std::string message;
+  grpc_error_get_status(error, GRPC_MILLIS_INF_FUTURE, nullptr, &message,
                         &http_error, nullptr);
-  grpc_chttp2_goaway_append(t->last_new_stream_id,
-                            static_cast<uint32_t>(http_error),
-                            grpc_slice_ref_internal(slice), &t->qbuf);
+  grpc_chttp2_goaway_append(
+      t->last_new_stream_id, static_cast<uint32_t>(http_error),
+      grpc_slice_from_cpp_string(std::move(message)), &t->qbuf);
   grpc_chttp2_initiate_write(t, GRPC_CHTTP2_INITIATE_WRITE_GOAWAY_SENT);
   GRPC_ERROR_UNREF(error);
 }
@@ -1856,8 +1859,7 @@ void grpc_chttp2_maybe_complete_recv_initial_metadata(
             &s->unprocessed_incoming_frames_buffer);
       }
     }
-    grpc_chttp2_incoming_metadata_buffer_publish(&s->metadata_buffer[0],
-                                                 s->recv_initial_metadata);
+    *s->recv_initial_metadata = std::move(s->initial_metadata_buffer);
     null_then_sched_closure(&s->recv_initial_metadata_ready);
   }
 }
@@ -1973,7 +1975,8 @@ void grpc_chttp2_maybe_complete_recv_trailing_metadata(grpc_chttp2_transport* t,
           GRPC_STREAM_COMPRESSION_IDENTITY_DECOMPRESS) {
         grpc_slice_buffer_move_first(
             &s->frame_storage,
-            GPR_MIN(s->frame_storage.length, GRPC_HEADER_SIZE_IN_BYTES),
+            std::min(s->frame_storage.length,
+                     size_t(GRPC_HEADER_SIZE_IN_BYTES)),
             &s->unprocessed_incoming_frames_buffer);
         if (s->unprocessed_incoming_frames_buffer.length > 0) {
           s->unprocessed_incoming_frames_decompressed = true;
@@ -2010,8 +2013,7 @@ void grpc_chttp2_maybe_complete_recv_trailing_metadata(grpc_chttp2_transport* t,
         s->recv_trailing_metadata_finished != nullptr) {
       grpc_transport_move_stats(&s->stats, s->collecting_stats);
       s->collecting_stats = nullptr;
-      grpc_chttp2_incoming_metadata_buffer_publish(&s->metadata_buffer[1],
-                                                   s->recv_trailing_metadata);
+      *s->recv_trailing_metadata = std::move(s->trailing_metadata_buffer);
       null_then_sched_closure(&s->recv_trailing_metadata_finished);
     }
   }
@@ -2087,8 +2089,9 @@ void grpc_chttp2_cancel_stream(grpc_chttp2_transport* t, grpc_chttp2_stream* s,
 void grpc_chttp2_fake_status(grpc_chttp2_transport* t, grpc_chttp2_stream* s,
                              grpc_error_handle error) {
   grpc_status_code status;
-  grpc_slice slice;
-  grpc_error_get_status(error, s->deadline, &status, &slice, nullptr, nullptr);
+  std::string message;
+  grpc_error_get_status(error, s->deadline, &status, &message, nullptr,
+                        nullptr);
   if (status != GRPC_STATUS_OK) {
     s->seen_error = true;
   }
@@ -2103,17 +2106,14 @@ void grpc_chttp2_fake_status(grpc_chttp2_transport* t, grpc_chttp2_stream* s,
     char status_string[GPR_LTOA_MIN_BUFSIZE];
     gpr_ltoa(status, status_string);
     GRPC_LOG_IF_ERROR("add_status",
-                      grpc_chttp2_incoming_metadata_buffer_replace_or_add(
-                          &s->metadata_buffer[1],
-                          grpc_mdelem_from_slices(
-                              GRPC_MDSTR_GRPC_STATUS,
-                              grpc_core::UnmanagedMemorySlice(status_string))));
-    if (!GRPC_SLICE_IS_EMPTY(slice)) {
-      GRPC_LOG_IF_ERROR(
-          "add_status_message",
-          grpc_chttp2_incoming_metadata_buffer_replace_or_add(
-              &s->metadata_buffer[1],
-              grpc_mdelem_create(GRPC_MDSTR_GRPC_MESSAGE, slice, nullptr)));
+                      s->trailing_metadata_buffer.ReplaceOrAppend(
+                          GRPC_MDSTR_GRPC_STATUS,
+                          grpc_core::UnmanagedMemorySlice(status_string)));
+    if (!message.empty()) {
+      grpc_slice message_slice = grpc_slice_from_cpp_string(std::move(message));
+      GRPC_LOG_IF_ERROR("add_status_message",
+                        s->trailing_metadata_buffer.ReplaceOrAppend(
+                            GRPC_MDSTR_GRPC_MESSAGE, message_slice));
     }
     s->published_metadata[1] = GRPC_METADATA_SYNTHESIZED_FROM_FAKE;
     grpc_chttp2_maybe_complete_recv_trailing_metadata(t, s);
@@ -2253,8 +2253,8 @@ static void close_from_api(grpc_chttp2_transport* t, grpc_chttp2_stream* s,
   uint8_t* p;
   uint32_t len = 0;
   grpc_status_code grpc_status;
-  grpc_slice slice;
-  grpc_error_get_status(error, s->deadline, &grpc_status, &slice, nullptr,
+  std::string message;
+  grpc_error_get_status(error, s->deadline, &grpc_status, &message, nullptr,
                         nullptr);
 
   GPR_ASSERT(grpc_status >= 0 && (int)grpc_status < 100);
@@ -2347,7 +2347,7 @@ static void close_from_api(grpc_chttp2_transport* t, grpc_chttp2_stream* s,
   GPR_ASSERT(p == GRPC_SLICE_END_PTR(status_hdr));
   len += static_cast<uint32_t> GRPC_SLICE_LENGTH(status_hdr);
 
-  size_t msg_len = GRPC_SLICE_LENGTH(slice);
+  size_t msg_len = message.length();
   GPR_ASSERT(msg_len <= UINT32_MAX);
   grpc_core::VarintWriter<1> msg_len_writer(msg_len);
   message_pfx = GRPC_SLICE_MALLOC(14 + msg_len_writer.length());
@@ -2392,7 +2392,8 @@ static void close_from_api(grpc_chttp2_transport* t, grpc_chttp2_stream* s,
   }
   grpc_slice_buffer_add(&t->qbuf, status_hdr);
   grpc_slice_buffer_add(&t->qbuf, message_pfx);
-  grpc_slice_buffer_add(&t->qbuf, grpc_slice_ref_internal(slice));
+  grpc_slice_buffer_add(&t->qbuf,
+                        grpc_slice_from_cpp_string(std::move(message)));
   grpc_chttp2_reset_ping_clock(t);
   grpc_chttp2_add_rst_stream_to_next_write(t, s->id, GRPC_HTTP2_NO_ERROR,
                                            &s->stats.outgoing);
@@ -2508,7 +2509,7 @@ static void read_action_locked(void* tp, grpc_error_handle error) {
 
   grpc_chttp2_transport* t = static_cast<grpc_chttp2_transport*>(tp);
 
-  GRPC_ERROR_REF(error);
+  (void)GRPC_ERROR_REF(error);
 
   grpc_error_handle err = error;
   if (err != GRPC_ERROR_NONE) {
@@ -2517,7 +2518,7 @@ static void read_action_locked(void* tp, grpc_error_handle error) {
                              GRPC_ERROR_INT_OCCURRED_DURING_WRITE,
                              t->write_state);
   }
-  GPR_SWAP(grpc_error_handle, err, error);
+  std::swap(err, error);
   GRPC_ERROR_UNREF(err);
   if (t->closed_with_error == GRPC_ERROR_NONE) {
     GPR_TIMER_SCOPE("reading_action.parse", 0);
index 40abc24..739d15d 100644 (file)
@@ -48,7 +48,7 @@ bool g_test_only_transport_flow_control_window_check;
 namespace {
 
 static constexpr const int kTracePadding = 30;
-static constexpr const uint32_t kMaxWindowUpdateSize = (1u << 31) - 1;
+static constexpr const int64_t kMaxWindowUpdateSize = (1u << 31) - 1;
 
 static char* fmt_int64_diff_str(int64_t old_val, int64_t new_val) {
   std::string str;
@@ -181,7 +181,7 @@ TransportFlowControl::TransportFlowControl(const grpc_chttp2_transport* t,
     : t_(t),
       enable_bdp_probe_(enable_bdp_probe),
       bdp_estimator_(t->peer_string.c_str()),
-      pid_controller_(grpc_core::PidController::Args()
+      pid_controller_(PidController::Args()
                           .set_gain_p(4)
                           .set_gain_i(8)
                           .set_gain_d(0)
@@ -189,7 +189,7 @@ TransportFlowControl::TransportFlowControl(const grpc_chttp2_transport* t,
                           .set_min_control_value(-1)
                           .set_max_control_value(25)
                           .set_integral_range(10)),
-      last_pid_update_(grpc_core::ExecCtx::Get()->Now()) {}
+      last_pid_update_(ExecCtx::Get()->Now()) {}
 
 uint32_t TransportFlowControl::MaybeSendUpdate(bool writing_anyway) {
   FlowControlTrace trace("t updt sent", this, nullptr);
@@ -197,8 +197,9 @@ uint32_t TransportFlowControl::MaybeSendUpdate(bool writing_anyway) {
       static_cast<uint32_t>(target_window());
   if ((writing_anyway || announced_window_ <= target_announced_window / 2) &&
       announced_window_ != target_announced_window) {
-    const uint32_t announce = static_cast<uint32_t> GPR_CLAMP(
-        target_announced_window - announced_window_, 0, kMaxWindowUpdateSize);
+    const uint32_t announce =
+        static_cast<uint32_t>(Clamp(target_announced_window - announced_window_,
+                                    int64_t(0), kMaxWindowUpdateSize));
     announced_window_ += announce;
     return announce;
   }
@@ -280,8 +281,9 @@ uint32_t StreamFlowControl::MaybeSendUpdate() {
     }
   }
   if (local_window_delta_ > announced_window_delta_) {
-    uint32_t announce = static_cast<uint32_t> GPR_CLAMP(
-        local_window_delta_ - announced_window_delta_, 0, kMaxWindowUpdateSize);
+    uint32_t announce = static_cast<uint32_t>(
+        Clamp(local_window_delta_ - announced_window_delta_, int64_t(0),
+              kMaxWindowUpdateSize));
     UpdateAnnouncedWindowDelta(tfc_, announce);
     return announce;
   }
@@ -334,8 +336,8 @@ static double AdjustForMemoryPressure(grpc_resource_quota* quota,
     target = (target - kZeroTarget) * memory_pressure / kLowMemPressure +
              kZeroTarget;
   } else if (memory_pressure > kHighMemPressure) {
-    target *= 1 - GPR_MIN(1, (memory_pressure - kHighMemPressure) /
-                                 (kMaxMemPressure - kHighMemPressure));
+    target *= 1 - std::min(1.0, (memory_pressure - kHighMemPressure) /
+                                    (kMaxMemPressure - kHighMemPressure));
   }
   return target;
 }
@@ -346,7 +348,7 @@ double TransportFlowControl::TargetLogBdp() {
 }
 
 double TransportFlowControl::SmoothLogBdp(double value) {
-  grpc_millis now = grpc_core::ExecCtx::Get()->Now();
+  grpc_millis now = ExecCtx::Get()->Now();
   double bdp_error = value - pid_controller_.last_control_value();
   const double dt = static_cast<double>(now - last_pid_update_) * 1e-3;
   last_pid_update_ = now;
@@ -383,8 +385,8 @@ FlowControlAction TransportFlowControl::PeriodicUpdate() {
     }
     // Though initial window 'could' drop to 0, we keep the floor at
     // kMinInitialWindowSize
-    target_initial_window_size_ = static_cast<int32_t> GPR_CLAMP(
-        target, kMinInitialWindowSize, kMaxInitialWindowSize);
+    target_initial_window_size_ = static_cast<int32_t>(Clamp(
+        target, double(kMinInitialWindowSize), double(kMaxInitialWindowSize)));
     action.set_send_initial_window_update(
         DeltaUrgency(target_initial_window_size_,
                      GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE),
@@ -393,10 +395,11 @@ FlowControlAction TransportFlowControl::PeriodicUpdate() {
     // get bandwidth estimate and update max_frame accordingly.
     double bw_dbl = bdp_estimator_.EstimateBandwidth();
     // we target the max of BDP or bandwidth in microseconds.
-    int32_t frame_size = static_cast<int32_t> GPR_CLAMP(
-        GPR_MAX((int32_t)GPR_CLAMP(bw_dbl, 0, INT_MAX) / 1000,
-                target_initial_window_size_),
-        16384, 16777215);
+    int32_t frame_size = static_cast<int32_t>(Clamp(
+        std::max(
+            static_cast<int32_t>(Clamp(bw_dbl, 0.0, double(INT_MAX))) / 1000,
+            static_cast<int32_t>(target_initial_window_size_)),
+        16384, 16777215));
     action.set_send_max_frame_size_update(
         DeltaUrgency(static_cast<int64_t>(frame_size),
                      GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE),
index 8f266e4..aeb5a81 100644 (file)
@@ -274,10 +274,10 @@ class TransportFlowControl final : public TransportFlowControlBase {
   // See comment above announced_stream_total_over_incoming_window_ for the
   // logic behind this decision.
   int64_t target_window() const override {
-    return static_cast<uint32_t> GPR_MIN(
-        (int64_t)((1u << 31) - 1),
-        announced_stream_total_over_incoming_window_ +
-            target_initial_window_size_);
+    return static_cast<uint32_t>(
+        std::min(static_cast<int64_t>((1u << 31) - 1),
+                 announced_stream_total_over_incoming_window_ +
+                     target_initial_window_size_));
   }
 
   const grpc_chttp2_transport* transport() const { return t_; }
index 88de467..91a3f2d 100644 (file)
@@ -133,10 +133,10 @@ grpc_error_handle grpc_deframe_unprocessed_incoming_frames(
                 absl::StrFormat("Bad GRPC frame type 0x%02x", p->frame_type));
             p->error = grpc_error_set_int(p->error, GRPC_ERROR_INT_STREAM_ID,
                                           static_cast<intptr_t>(s->id));
-            p->error = grpc_error_set_str(
-                p->error, GRPC_ERROR_STR_RAW_BYTES,
-                grpc_slice_from_moved_string(grpc_core::UniquePtr<char>(
-                    grpc_dump_slice(*slice, GPR_DUMP_HEX | GPR_DUMP_ASCII))));
+            grpc_core::UniquePtr<char> dmp(
+                grpc_dump_slice(*slice, GPR_DUMP_HEX | GPR_DUMP_ASCII));
+            p->error = grpc_error_set_str(p->error, GRPC_ERROR_STR_RAW_BYTES,
+                                          dmp.get());
             p->error =
                 grpc_error_set_int(p->error, GRPC_ERROR_INT_OFFSET, cur - beg);
             p->state = GRPC_CHTTP2_DATA_ERROR;
index 45f250f..eb90e2e 100644 (file)
@@ -139,7 +139,8 @@ grpc_error_handle grpc_chttp2_goaway_parser_parse(void* parser,
       if (is_last) {
         grpc_chttp2_add_incoming_goaway(
             t, p->error_code, p->last_stream_id,
-            grpc_slice_new(p->debug_data, p->debug_length, gpr_free));
+            absl::string_view(p->debug_data, p->debug_length));
+        gpr_free(p->debug_data);
         p->debug_data = nullptr;
       }
       return GRPC_ERROR_NONE;
index ceee078..3ee99eb 100644 (file)
@@ -112,7 +112,8 @@ grpc_error_handle grpc_chttp2_ping_parser_parse(void* parser,
       }
       if (!g_disable_ping_ack) {
         if (t->ping_ack_count == t->ping_ack_capacity) {
-          t->ping_ack_capacity = GPR_MAX(t->ping_ack_capacity * 3 / 2, 3);
+          t->ping_ack_capacity =
+              std::max(t->ping_ack_capacity * 3 / 2, size_t(3));
           t->ping_acks = static_cast<uint64_t*>(gpr_realloc(
               t->ping_acks, t->ping_ack_capacity * sizeof(*t->ping_acks)));
         }
index 57bf74b..bd92557 100644 (file)
@@ -103,13 +103,12 @@ grpc_error_handle grpc_chttp2_rst_stream_parser_parse(void* parser,
                       ((static_cast<uint32_t>(p->reason_bytes[2])) << 8) |
                       ((static_cast<uint32_t>(p->reason_bytes[3])));
     grpc_error_handle error = GRPC_ERROR_NONE;
-    if (reason != GRPC_HTTP2_NO_ERROR || s->metadata_buffer[1].size == 0) {
+    if (reason != GRPC_HTTP2_NO_ERROR || s->trailing_metadata_buffer.empty()) {
       error = grpc_error_set_int(
           grpc_error_set_str(
               GRPC_ERROR_CREATE_FROM_STATIC_STRING("RST_STREAM"),
               GRPC_ERROR_STR_GRPC_MESSAGE,
-              grpc_slice_from_cpp_string(absl::StrCat(
-                  "Received RST_STREAM with error code ", reason))),
+              absl::StrCat("Received RST_STREAM with error code ", reason)),
           GRPC_ERROR_INT_HTTP2_ERROR, static_cast<intptr_t>(reason));
     }
     grpc_chttp2_mark_stream_closed(t, s, true, true, error);
index 66b3118..c488f5a 100644 (file)
@@ -217,8 +217,8 @@ grpc_error_handle grpc_chttp2_settings_parser_parse(void* p,
           if (parser->value < sp->min_value || parser->value > sp->max_value) {
             switch (sp->invalid_value_behavior) {
               case GRPC_CHTTP2_CLAMP_INVALID_VALUE:
-                parser->value =
-                    GPR_CLAMP(parser->value, sp->min_value, sp->max_value);
+                parser->value = grpc_core::Clamp(parser->value, sp->min_value,
+                                                 sp->max_value);
                 break;
               case GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE:
                 grpc_chttp2_goaway_append(
index fb98917..f588652 100644 (file)
@@ -15,7 +15,7 @@
 #ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HPACK_CONSTANTS_H
 #define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HPACK_CONSTANTS_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include <stdint.h>
 
index e455088..5dfd11d 100644 (file)
@@ -265,6 +265,22 @@ class StringValue {
   VarintWriter<1> len_val_;
 };
 
+class NonBinaryStringValue {
+ public:
+  explicit NonBinaryStringValue(const grpc_slice& value)
+      : value_(value), len_val_(GRPC_SLICE_LENGTH(value)) {}
+
+  size_t prefix_length() const { return len_val_.length(); }
+
+  void WritePrefix(uint8_t* prefix_data) { len_val_.Write(0x00, prefix_data); }
+
+  const grpc_slice& data() { return value_; }
+
+ private:
+  grpc_slice value_;
+  VarintWriter<1> len_val_;
+};
+
 class StringKey {
  public:
   explicit StringKey(grpc_slice key)
@@ -317,6 +333,18 @@ void HPackCompressor::Framer::EmitLitHdrWithStringKeyIncIdx(grpc_mdelem elem) {
   Add(emit.data());
 }
 
+void HPackCompressor::Framer::EmitLitHdrWithNonBinaryStringKeyIncIdx(
+    const grpc_slice& key_slice, const grpc_slice& value_slice) {
+  GRPC_STATS_INC_HPACK_SEND_LITHDR_INCIDX_V();
+  GRPC_STATS_INC_HPACK_SEND_UNCOMPRESSED();
+  StringKey key(key_slice);
+  key.WritePrefix(0x40, AddTiny(key.prefix_length()));
+  Add(grpc_slice_ref_internal(key.key()));
+  NonBinaryStringValue emit(value_slice);
+  emit.WritePrefix(AddTiny(emit.prefix_length()));
+  Add(grpc_slice_ref_internal(emit.data()));
+}
+
 void HPackCompressor::Framer::EmitLitHdrWithStringKeyNotIdx(grpc_mdelem elem) {
   GRPC_STATS_INC_HPACK_SEND_LITHDR_NOTIDX_V();
   GRPC_STATS_INC_HPACK_SEND_UNCOMPRESSED();
@@ -448,7 +476,19 @@ void HPackCompressor::Framer::EncodeDynamic(grpc_mdelem elem) {
   }
 }
 
-void HPackCompressor::Framer::EncodeDeadline(grpc_millis deadline) {
+void HPackCompressor::Framer::Encode(TeMetadata, TeMetadata::ValueType value) {
+  GPR_ASSERT(value == TeMetadata::ValueType::kTrailers);
+  if (compressor_->table_.ConvertableToDynamicIndex(compressor_->te_index_)) {
+    EmitIndexed(compressor_->table_.DynamicIndex(compressor_->te_index_));
+  } else {
+    compressor_->te_index_ = compressor_->table_.AllocateIndex(
+        2 /* te */ + 8 /* trailers */ + hpack_constants::kEntryOverhead);
+    EmitLitHdrWithNonBinaryStringKeyIncIdx(GRPC_MDSTR_TE, GRPC_MDSTR_TRAILERS);
+  }
+}
+
+void HPackCompressor::Framer::Encode(GrpcTimeoutMetadata,
+                                     grpc_millis deadline) {
   char timeout_str[GRPC_HTTP2_TIMEOUT_ENCODE_MIN_BUFSIZE];
   grpc_mdelem mdelem;
   grpc_http2_encode_timeout(deadline - grpc_core::ExecCtx::Get()->Now(),
index b2b4ee3..547da35 100644 (file)
@@ -117,7 +117,8 @@ class HPackCompressor {
     Framer& operator=(const Framer&) = delete;
 
     void Encode(grpc_mdelem md);
-    void EncodeDeadline(grpc_millis deadline);
+    void Encode(GrpcTimeoutMetadata, grpc_millis deadline);
+    void Encode(TeMetadata, TeMetadata::ValueType value);
 
    private:
     struct FramePrefix {
@@ -140,6 +141,8 @@ class HPackCompressor {
     void EmitLitHdrIncIdx(uint32_t key_index, grpc_mdelem elem);
     void EmitLitHdrNotIdx(uint32_t key_index, grpc_mdelem elem);
     void EmitLitHdrWithStringKeyIncIdx(grpc_mdelem elem);
+    void EmitLitHdrWithNonBinaryStringKeyIncIdx(const grpc_slice& key_slice,
+                                                const grpc_slice& value_slice);
     void EmitLitHdrWithStringKeyNotIdx(grpc_mdelem elem);
 
     size_t CurrentFrameSize() const;
@@ -187,7 +190,7 @@ class HPackCompressor {
   // a new literal should be added to the compression table or not.
   // They track a single integer that counts how often a particular value has
   // been seen. When that count reaches max (255), all values are halved.
-  grpc_core::PopularityCount<kNumFilterValues> filter_elems_;
+  PopularityCount<kNumFilterValues> filter_elems_;
 
   class KeyElem {
    public:
@@ -264,8 +267,9 @@ class HPackCompressor {
 
   // entry tables for keys & elems: these tables track values that have been
   // seen and *may* be in the decompressor table
-  grpc_core::HPackEncoderIndex<KeyElem, kNumFilterValues> elem_index_;
-  grpc_core::HPackEncoderIndex<KeySliceRef, kNumFilterValues> key_index_;
+  HPackEncoderIndex<KeyElem, kNumFilterValues> elem_index_;
+  HPackEncoderIndex<KeySliceRef, kNumFilterValues> key_index_;
+  uint32_t te_index_ = 0;
 };
 
 }  // namespace grpc_core
index 232d3df..0517281 100644 (file)
@@ -15,7 +15,7 @@
 #ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HPACK_ENCODER_INDEX_H
 #define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HPACK_ENCODER_INDEX_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include "absl/types/optional.h"
 
index 09681fa..eb2f2f4 100644 (file)
@@ -51,7 +51,7 @@
 
 namespace grpc_core {
 
-DebugOnlyTraceFlag grpc_trace_chttp2_hpack_parser(false, "chttp2_hpack_parser");
+TraceFlag grpc_trace_chttp2_hpack_parser(false, "chttp2_hpack_parser");
 
 /* state table for huffman decoding: given a state, gives an index/16 into
    next_sub_tbl. Taking that index and adding the value of the nibble being
@@ -935,15 +935,20 @@ class HPackParser::String {
       value_;
 };
 
-// Parser parses one frame + continuations worth of headers.
+// Parser parses one key/value pair from a byte stream.
 class HPackParser::Parser {
  public:
-  Parser(Input* input, HPackParser::Sink* sink, HPackTable* table,
-         uint8_t* dynamic_table_updates_allowed)
+  Parser(Input* input, grpc_metadata_batch* metadata_buffer,
+         uint32_t metadata_size_limit, HPackTable* table,
+         uint8_t* dynamic_table_updates_allowed, uint32_t* frame_length,
+         LogInfo log_info)
       : input_(input),
-        sink_(sink),
+        metadata_buffer_(metadata_buffer),
         table_(table),
-        dynamic_table_updates_allowed_(dynamic_table_updates_allowed) {}
+        dynamic_table_updates_allowed_(dynamic_table_updates_allowed),
+        frame_length_(frame_length),
+        metadata_size_limit_(metadata_size_limit),
+        log_info_(log_info) {}
 
   // Skip any priority bits, or return false on failure
   bool SkipPriority() {
@@ -965,13 +970,12 @@ class HPackParser::Parser {
       case 1:
         switch (cur & 0xf) {
           case 0:  // literal key
-            return FinishHeader<TableAction::kOmitFromTable>(
-                ParseLiteralKey<String::Extern>());
+            return FinishHeaderOmitFromTable(ParseLiteralKey<String::Extern>());
           case 0xf:  // varint encoded key index
-            return FinishHeader<TableAction::kOmitFromTable>(
+            return FinishHeaderOmitFromTable(
                 ParseVarIdxKey<String::Extern>(0xf));
           default:  // inline encoded key index
-            return FinishHeader<TableAction::kOmitFromTable>(
+            return FinishHeaderOmitFromTable(
                 ParseIdxKey<String::Extern>(cur & 0xf));
         }
         // Update max table size.
@@ -999,23 +1003,22 @@ class HPackParser::Parser {
       case 4:
         if (cur == 0x40) {
           // literal key
-          return FinishHeader<TableAction::kAddToTable>(
-              ParseLiteralKey<String::Intern>());
+          return FinishHeaderAndAddToTable(ParseLiteralKey<String::Intern>());
         }
         ABSL_FALLTHROUGH_INTENDED;
       case 5:
       case 6:
         // inline encoded key index
-        return FinishHeader<TableAction::kAddToTable>(
+        return FinishHeaderAndAddToTable(
             ParseIdxKey<String::Intern>(cur & 0x3f));
       case 7:
         if (cur == 0x7f) {
           // varint encoded key index
-          return FinishHeader<TableAction::kAddToTable>(
+          return FinishHeaderAndAddToTable(
               ParseVarIdxKey<String::Intern>(0x3f));
         } else {
           // inline encoded key index
-          return FinishHeader<TableAction::kAddToTable>(
+          return FinishHeaderAndAddToTable(
               ParseIdxKey<String::Intern>(cur & 0x3f));
         }
         // Indexed Header Field Representation
@@ -1056,102 +1059,110 @@ class HPackParser::Parser {
   }
 
  private:
-  void GPR_ATTRIBUTE_NOINLINE LogHeader(grpc_mdelem md) {
-    char* k = grpc_slice_to_c_string(GRPC_MDKEY(md));
-    char* v = nullptr;
-    if (grpc_is_binary_header_internal(GRPC_MDKEY(md))) {
-      v = grpc_dump_slice(GRPC_MDVALUE(md), GPR_DUMP_HEX);
-    } else {
-      v = grpc_slice_to_c_string(GRPC_MDVALUE(md));
+  void GPR_ATTRIBUTE_NOINLINE LogHeader(const HPackTable::Memento& memento) {
+    const char* type;
+    switch (log_info_.type) {
+      case LogInfo::kHeaders:
+        type = "HDR";
+        break;
+      case LogInfo::kTrailers:
+        type = "TRL";
+        break;
+      case LogInfo::kDontKnow:
+        type = "???";
+        break;
     }
-    gpr_log(
-        GPR_INFO,
-        "Decode: '%s: %s', elem_interned=%d [%d], k_interned=%d, v_interned=%d",
-        k, v, GRPC_MDELEM_IS_INTERNED(md), GRPC_MDELEM_STORAGE(md),
-        grpc_slice_is_interned(GRPC_MDKEY(md)),
-        grpc_slice_is_interned(GRPC_MDVALUE(md)));
-    gpr_free(k);
-    gpr_free(v);
+    gpr_log(GPR_DEBUG, "HTTP:%d:%s:%s: %s", log_info_.stream_id, type,
+            log_info_.is_client ? "CLI" : "SVR", memento.DebugString().c_str());
   }
 
-  // During FinishHeader, how should the header be treated in the hpack table
-  enum class TableAction {
-    // Add to the table
-    kAddToTable,
-    // Do not add to the table
-    kOmitFromTable,
-  };
+  bool EmitHeader(const HPackTable::Memento& md) {
+    // Pass up to the transport
+    if (GPR_UNLIKELY(metadata_buffer_ == nullptr)) return true;
+    *frame_length_ += md.transport_size();
+    if (GPR_UNLIKELY(*frame_length_ > metadata_size_limit_)) {
+      return HandleMetadataSizeLimitExceeded(md);
+    }
 
-  template <TableAction action>
-  bool FinishHeader(grpc_mdelem md) {
+    grpc_error_handle err = metadata_buffer_->Set(md);
+    if (GPR_UNLIKELY(err != GRPC_ERROR_NONE)) {
+      input_->SetError(err);
+      return false;
+    }
+    return true;
+  }
+
+  bool FinishHeaderAndAddToTable(absl::optional<HPackTable::Memento> md) {
     // Allow higher code to just pass in failures ... simplifies things a bit.
-    if (GRPC_MDISNULL(md)) return false;
+    if (!md.has_value()) return false;
     // Log if desired
     if (GRPC_TRACE_FLAG_ENABLED(grpc_trace_chttp2_hpack_parser)) {
-      LogHeader(md);
-    }
-    // Add to the hpack table if needed
-    if (action == TableAction::kAddToTable) {
-      GPR_DEBUG_ASSERT(GRPC_MDELEM_STORAGE(md) ==
-                           GRPC_MDELEM_STORAGE_INTERNED ||
-                       GRPC_MDELEM_STORAGE(md) == GRPC_MDELEM_STORAGE_STATIC);
-      grpc_error_handle err = table_->Add(md);
-      if (GPR_UNLIKELY(err != GRPC_ERROR_NONE)) {
-        input_->SetError(err);
-        return false;
-      };
+      LogHeader(*md);
     }
-    // Pass up to the transport
-    grpc_error_handle err = (*sink_)(md);
+    // Emit whilst we own the metadata.
+    auto r = EmitHeader(*md);
+    // Add to the hpack table
+    grpc_error_handle err = table_->Add(std::move(*md));
     if (GPR_UNLIKELY(err != GRPC_ERROR_NONE)) {
       input_->SetError(err);
       return false;
+    };
+    return r;
+  }
+
+  bool FinishHeaderOmitFromTable(absl::optional<HPackTable::Memento> md) {
+    // Allow higher code to just pass in failures ... simplifies things a bit.
+    if (!md.has_value()) return false;
+    return FinishHeaderOmitFromTable(*md);
+  }
+
+  bool FinishHeaderOmitFromTable(const HPackTable::Memento& md) {
+    // Log if desired
+    if (GRPC_TRACE_FLAG_ENABLED(grpc_trace_chttp2_hpack_parser)) {
+      LogHeader(md);
     }
-    return true;
+    return EmitHeader(md);
   }
 
   // Parse a string encoded key and a string encoded value
   template <typename TakeValueType>
-  grpc_mdelem ParseLiteralKey() {
+  absl::optional<HPackTable::Memento> ParseLiteralKey() {
     auto key = String::Parse(input_);
-    if (!key.has_value()) return GRPC_MDNULL;
+    if (!key.has_value()) return {};
     auto key_slice = key->Take<String::Intern>();
-    auto value = ParseValueString(key_slice);
+    auto value =
+        ParseValueString(grpc_is_refcounted_slice_binary_header(key_slice));
     if (GPR_UNLIKELY(!value.has_value())) {
       grpc_slice_unref_internal(key_slice);
-      return GRPC_MDNULL;
+      return {};
     }
-    return grpc_mdelem_from_slices(key_slice, value->Take<TakeValueType>());
+    return grpc_metadata_batch::Parse(key_slice, value->Take<TakeValueType>());
   }
 
   // Parse an index encoded key and a string encoded value
   template <typename TakeValueType>
-  grpc_mdelem ParseIdxKey(uint32_t index) {
-    auto elem = table_->Peek(index);
-    if (GPR_UNLIKELY(GRPC_MDISNULL(elem))) {
-      return InvalidHPackIndexError(index, elem);
+  absl::optional<HPackTable::Memento> ParseIdxKey(uint32_t index) {
+    const auto* elem = table_->Lookup(index);
+    if (GPR_UNLIKELY(elem == nullptr)) {
+      return InvalidHPackIndexError(index,
+                                    absl::optional<HPackTable::Memento>());
     }
-    GPR_DEBUG_ASSERT(GRPC_MDELEM_IS_INTERNED(elem));
-    auto value = ParseValueString(GRPC_MDKEY(elem));
-    if (GPR_UNLIKELY(!value.has_value())) return GRPC_MDNULL;
-    return grpc_mdelem_from_slices(
-        static_cast<const ManagedMemorySlice&>(
-            grpc_slice_ref_internal(GRPC_MDKEY(elem))),
-        value->Take<TakeValueType>());
+    auto value = ParseValueString(elem->is_binary_header());
+    if (GPR_UNLIKELY(!value.has_value())) return {};
+    return elem->WithNewValue(value->Take<TakeValueType>());
   }
 
   // Parse a varint index encoded key and a string encoded value
   template <typename TakeValueType>
-  grpc_mdelem ParseVarIdxKey(uint32_t offset) {
+  absl::optional<HPackTable::Memento> ParseVarIdxKey(uint32_t offset) {
     auto index = input_->ParseVarint(offset);
-    if (GPR_UNLIKELY(!index.has_value())) return GRPC_MDNULL;
+    if (GPR_UNLIKELY(!index.has_value())) return {};
     return ParseIdxKey<TakeValueType>(*index);
   }
 
   // Parse a string, figuring out if it's binary or not by the key name.
-  template <typename SliceType>
-  absl::optional<String> ParseValueString(const SliceType& key) {
-    if (grpc_is_refcounted_slice_binary_header(key)) {
+  absl::optional<String> ParseValueString(bool is_binary) {
+    if (is_binary) {
       return String::ParseBinary(input_);
     } else {
       return String::Parse(input_);
@@ -1162,12 +1173,12 @@ class HPackParser::Parser {
   bool FinishIndexed(absl::optional<uint32_t> index) {
     *dynamic_table_updates_allowed_ = 0;
     if (!index.has_value()) return false;
-    grpc_mdelem md = table_->Fetch(*index);
-    if (GPR_UNLIKELY(GRPC_MDISNULL(md))) {
+    const auto* elem = table_->Lookup(*index);
+    if (GPR_UNLIKELY(elem == nullptr)) {
       return InvalidHPackIndexError(*index, false);
     }
     GRPC_STATS_INC_HPACK_RECV_INDEXED();
-    return FinishHeader<TableAction::kOmitFromTable>(md);
+    return FinishHeaderOmitFromTable(*elem);
   }
 
   // finish parsing a max table size change
@@ -1182,9 +1193,6 @@ class HPackParser::Parser {
           false);
     }
     (*dynamic_table_updates_allowed_)--;
-    if (GRPC_TRACE_FLAG_ENABLED(grpc_trace_chttp2_hpack_parser)) {
-      gpr_log(GPR_INFO, "MAX TABLE SIZE: %d", *size);
-    }
     grpc_error_handle err = table_->SetCurrentTableSize(*size);
     if (err != GRPC_ERROR_NONE) {
       input_->SetError(err);
@@ -1207,21 +1215,44 @@ class HPackParser::Parser {
               GRPC_ERROR_INT_SIZE,
               static_cast<intptr_t>(this->table_->num_entries()));
         },
-        result);
+        std::move(result));
+  }
+
+  GPR_ATTRIBUTE_NOINLINE
+  bool HandleMetadataSizeLimitExceeded(const HPackTable::Memento&) {
+    gpr_log(GPR_DEBUG,
+            "received initial metadata size exceeds limit (%" PRIu32
+            " vs. %" PRIu32
+            "). GRPC_ARG_MAX_METADATA_SIZE can be set to increase this limit.",
+            *frame_length_, metadata_size_limit_);
+    return input_->MaybeSetErrorAndReturn(
+        [] {
+          return grpc_error_set_int(
+              GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+                  "received initial metadata size exceeds limit"),
+              GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_RESOURCE_EXHAUSTED);
+        },
+        false);
   }
 
-  Input* input_;
-  HPackParser::Sink* sink_;
+  Input* const input_;
+  grpc_metadata_batch* const metadata_buffer_;
   HPackTable* const table_;
-  uint8_t* dynamic_table_updates_allowed_;
+  uint8_t* const dynamic_table_updates_allowed_;
+  uint32_t* const frame_length_;
+  const uint32_t metadata_size_limit_;
+  const LogInfo log_info_;
 };
 
 UnmanagedMemorySlice HPackParser::String::Take(Extern) {
   auto s = Match(
       value_,
       [](const grpc_slice& slice) {
+        // TODO(ctiller): Think about this before submission.
         GPR_DEBUG_ASSERT(!grpc_slice_is_interned(slice));
-        return static_cast<const UnmanagedMemorySlice&>(slice);
+        auto out_slice = grpc_slice_copy(slice);
+        grpc_slice_unref_internal(slice);
+        return static_cast<const UnmanagedMemorySlice&>(out_slice);
       },
       [](absl::Span<const uint8_t> span) {
         return UnmanagedMemorySlice(
@@ -1263,11 +1294,16 @@ HPackParser::HPackParser() = default;
 
 HPackParser::~HPackParser() = default;
 
-void HPackParser::BeginFrame(Sink sink, Boundary boundary, Priority priority) {
-  sink_ = std::move(sink);
+void HPackParser::BeginFrame(grpc_metadata_batch* metadata_buffer,
+                             uint32_t metadata_size_limit, Boundary boundary,
+                             Priority priority, LogInfo log_info) {
+  metadata_buffer_ = metadata_buffer;
   boundary_ = boundary;
   priority_ = priority;
   dynamic_table_updates_allowed_ = 2;
+  frame_length_ = 0;
+  metadata_size_limit_ = metadata_size_limit;
+  log_info_ = log_info;
 }
 
 grpc_error_handle HPackParser::Parse(const grpc_slice& slice, bool is_last) {
@@ -1310,9 +1346,10 @@ bool HPackParser::ParseInputInner(Input* input) {
     }
   }
   while (!input->end_of_stream()) {
-    if (GPR_UNLIKELY(
-            !Parser(input, &sink_, &table_, &dynamic_table_updates_allowed_)
-                 .Parse())) {
+    if (GPR_UNLIKELY(!Parser(input, metadata_buffer_, metadata_size_limit_,
+                             &table_, &dynamic_table_updates_allowed_,
+                             &frame_length_, log_info_)
+                          .Parse())) {
       return false;
     }
     input->UpdateFrontier();
@@ -1320,7 +1357,7 @@ bool HPackParser::ParseInputInner(Input* input) {
   return true;
 }
 
-void HPackParser::FinishFrame() { sink_ = Sink(); }
+void HPackParser::FinishFrame() { metadata_buffer_ = nullptr; }
 
 }  // namespace grpc_core
 
@@ -1348,10 +1385,11 @@ static void force_client_rst_stream(void* sp, grpc_error_handle /*error*/) {
 static void parse_stream_compression_md(grpc_chttp2_transport* /*t*/,
                                         grpc_chttp2_stream* s,
                                         grpc_metadata_batch* initial_metadata) {
-  if (initial_metadata->idx.named.content_encoding == nullptr ||
+  if (initial_metadata->legacy_index()->named.content_encoding == nullptr ||
       grpc_stream_compression_method_parse(
-          GRPC_MDVALUE(initial_metadata->idx.named.content_encoding->md), false,
-          &s->stream_decompression_method) == 0) {
+          GRPC_MDVALUE(
+              initial_metadata->legacy_index()->named.content_encoding->md),
+          false, &s->stream_decompression_method) == 0) {
     s->stream_decompression_method =
         GRPC_STREAM_COMPRESSION_IDENTITY_DECOMPRESS;
   }
@@ -1382,14 +1420,14 @@ grpc_error_handle grpc_chttp2_header_parser_parse(void* hpack_parser,
        stream id on a header */
     if (s != nullptr) {
       if (parser->is_boundary()) {
-        if (s->header_frames_received == GPR_ARRAY_SIZE(s->metadata_buffer)) {
+        if (s->header_frames_received == 2) {
           return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
               "Too many trailer frames");
         }
         /* Process stream compression md element if it exists */
         if (s->header_frames_received ==
             0) { /* Only acts on initial metadata */
-          parse_stream_compression_md(t, s, &s->metadata_buffer[0].batch);
+          parse_stream_compression_md(t, s, &s->initial_metadata_buffer);
         }
         s->published_metadata[s->header_frames_received] =
             GRPC_METADATA_PUBLISHED_FROM_WIRE;
index 0ae7413..88b5d52 100644 (file)
@@ -26,6 +26,7 @@
 #include "src/core/ext/transport/chttp2/transport/frame.h"
 #include "src/core/ext/transport/chttp2/transport/hpack_parser_table.h"
 #include "src/core/lib/transport/metadata.h"
+#include "src/core/lib/transport/metadata_batch.h"
 
 namespace grpc_core {
 
@@ -48,9 +49,20 @@ class HPackParser {
     // Yes there's a priority field
     Included
   };
-
-  // User specified structure called for each received header.
-  using Sink = std::function<grpc_error_handle(grpc_mdelem)>;
+  // Details about a frame we only need to know for logging
+  struct LogInfo {
+    // The stream ID
+    uint32_t stream_id;
+    // Headers or trailers?
+    enum Type : uint8_t {
+      kHeaders,
+      kTrailers,
+      kDontKnow,
+    };
+    Type type;
+    // Client or server?
+    bool is_client;
+  };
 
   HPackParser();
   ~HPackParser();
@@ -61,9 +73,11 @@ class HPackParser {
 
   // Begin parsing a new frame
   // Sink receives each parsed header,
-  void BeginFrame(Sink sink, Boundary boundary, Priority priority);
-  // Change the header sink mid parse
-  void ResetSink(Sink sink) { sink_ = std::move(sink); }
+  void BeginFrame(grpc_metadata_batch* metadata_buffer,
+                  uint32_t metadata_size_limit, Boundary boundary,
+                  Priority priority, LogInfo log_info);
+  // Start throwing away any received headers after parsing them.
+  void StopBufferingFrame() { metadata_buffer_ = nullptr; }
   // Parse one slice worth of data
   grpc_error_handle Parse(const grpc_slice& slice, bool is_last);
   // Reset state ready for the next BeginFrame
@@ -85,8 +99,8 @@ class HPackParser {
   grpc_error_handle ParseInput(Input input, bool is_last);
   bool ParseInputInner(Input* input);
 
-  // Callback per header received
-  Sink sink_;
+  // Target metadata buffer
+  grpc_metadata_batch* metadata_buffer_ = nullptr;
 
   // Bytes that could not be parsed last parsing round
   std::vector<uint8_t> unparsed_bytes_;
@@ -99,6 +113,11 @@ class HPackParser {
   // buffering.
   Priority priority_;
   uint8_t dynamic_table_updates_allowed_;
+  // Length of frame so far.
+  uint32_t frame_length_;
+  uint32_t metadata_size_limit_;
+  // Information for logging
+  LogInfo log_info_;
 
   // hpack table
   HPackTable table_;
index 151fb29..80a026e 100644 (file)
@@ -38,32 +38,24 @@ extern grpc_core::TraceFlag grpc_http_trace;
 
 namespace grpc_core {
 
-HPackTable::HPackTable() = default;
+HPackTable::HPackTable() : static_metadata_(GetStaticMementos()) {}
 
-HPackTable::~HPackTable() {
-  for (size_t i = 0; i < num_entries_; i++) {
-    GRPC_MDELEM_UNREF(entries_[(first_entry_ + i) % entries_.size()]);
-  }
-}
+HPackTable::~HPackTable() = default;
 
 /* Evict one element from the table */
 void HPackTable::EvictOne() {
-  grpc_mdelem first_entry = entries_[first_entry_];
-  size_t elem_bytes = GRPC_SLICE_LENGTH(GRPC_MDKEY(first_entry)) +
-                      GRPC_SLICE_LENGTH(GRPC_MDVALUE(first_entry)) +
-                      hpack_constants::kEntryOverhead;
-  GPR_ASSERT(elem_bytes <= mem_used_);
-  mem_used_ -= static_cast<uint32_t>(elem_bytes);
+  auto first_entry = std::move(entries_[first_entry_]);
+  GPR_ASSERT(first_entry.transport_size() <= mem_used_);
+  mem_used_ -= first_entry.transport_size();
   first_entry_ = ((first_entry_ + 1) % entries_.size());
   num_entries_--;
-  GRPC_MDELEM_UNREF(first_entry);
 }
 
 void HPackTable::Rebuild(uint32_t new_cap) {
   EntriesVec entries;
   entries.resize(new_cap);
   for (size_t i = 0; i < num_entries_; i++) {
-    entries[i] = entries_[(first_entry_ + i) % entries_.size()];
+    entries[i] = std::move(entries_[(first_entry_ + i) % entries_.size()]);
   }
   first_entry_ = 0;
   entries_.swap(entries);
@@ -113,12 +105,7 @@ grpc_error_handle HPackTable::SetCurrentTableSize(uint32_t bytes) {
   return GRPC_ERROR_NONE;
 }
 
-grpc_error_handle HPackTable::Add(grpc_mdelem md) {
-  /* determine how many bytes of buffer this entry represents */
-  size_t elem_bytes = GRPC_SLICE_LENGTH(GRPC_MDKEY(md)) +
-                      GRPC_SLICE_LENGTH(GRPC_MDVALUE(md)) +
-                      hpack_constants::kEntryOverhead;
-
+grpc_error_handle HPackTable::Add(Memento md) {
   if (current_table_bytes_ > max_bytes_) {
     return GRPC_ERROR_CREATE_FROM_CPP_STRING(absl::StrFormat(
         "HPACK max table size reduced to %d but not reflected by hpack "
@@ -127,7 +114,7 @@ grpc_error_handle HPackTable::Add(grpc_mdelem md) {
   }
 
   // we can't add elements bigger than the max table size
-  if (elem_bytes > current_table_bytes_) {
+  if (md.transport_size() > current_table_bytes_) {
     // HPACK draft 10 section 4.4 states:
     // If the size of the new entry is less than or equal to the maximum
     // size, that entry is added to the table.  It is not an error to
@@ -142,17 +129,17 @@ grpc_error_handle HPackTable::Add(grpc_mdelem md) {
   }
 
   // evict entries to ensure no overflow
-  while (elem_bytes > static_cast<size_t>(current_table_bytes_) - mem_used_) {
+  while (md.transport_size() >
+         static_cast<size_t>(current_table_bytes_) - mem_used_) {
     EvictOne();
   }
 
   // copy the finalized entry in
-  entries_[(first_entry_ + num_entries_) % entries_.size()] =
-      GRPC_MDELEM_REF(md);
+  mem_used_ += md.transport_size();
+  entries_[(first_entry_ + num_entries_) % entries_.size()] = std::move(md);
 
   // update accounting values
   num_entries_++;
-  mem_used_ += static_cast<uint32_t>(elem_bytes);
   return GRPC_ERROR_NONE;
 }
 
index c1bdf6b..db69903 100644 (file)
@@ -27,6 +27,7 @@
 #include "src/core/lib/gprpp/memory.h"
 #include "src/core/lib/iomgr/error.h"
 #include "src/core/lib/transport/metadata.h"
+#include "src/core/lib/transport/metadata_batch.h"
 #include "src/core/lib/transport/static_metadata.h"
 
 namespace grpc_core {
@@ -37,30 +38,16 @@ class HPackTable {
   HPackTable();
   ~HPackTable();
 
-  HPackTable(const HPackTable&);
-  HPackTable& operator=(const HPackTable&);
+  HPackTable(const HPackTable&) = delete;
+  HPackTable& operator=(const HPackTable&) = delete;
 
   void SetMaxBytes(uint32_t max_bytes);
   grpc_error_handle SetCurrentTableSize(uint32_t bytes);
 
-  // Lookup, but don't ref.
-  grpc_mdelem Peek(uint32_t index) const { return Lookup<false>(index); }
-  // Lookup, taking a ref if found.
-  grpc_mdelem Fetch(uint32_t index) const { return Lookup<true>(index); }
-
-  // add a table entry to the index
-  grpc_error_handle Add(grpc_mdelem md) GRPC_MUST_USE_RESULT;
-
-  // Current entry count in the table.
-  uint32_t num_entries() const { return num_entries_; }
+  using Memento = ParsedMetadata<grpc_metadata_batch>;
 
- private:
-  enum { kInlineEntries = hpack_constants::kInitialTableEntries };
-  using EntriesVec = absl::InlinedVector<grpc_mdelem, kInlineEntries>;
-
-  /* lookup a table entry based on its hpack index */
-  template <bool take_ref>
-  grpc_mdelem Lookup(uint32_t index) const {
+  // Lookup, but don't ref.
+  const Memento* Lookup(uint32_t index) const {
     // Static table comes first, just return an entry from it.
     // NB: This imposes the constraint that the first
     // GRPC_CHTTP2_LAST_STATIC_ENTRY entries in the core static metadata table
@@ -68,27 +55,45 @@ class HPackTable {
     // reading the core static metadata table here; at that point we'd need our
     // own singleton static metadata in the correct order.
     if (index <= hpack_constants::kLastStaticEntry) {
-      return grpc_static_mdelem_manifested()[index - 1];
+      return &static_metadata_.memento[index - 1];
     } else {
-      return LookupDynamic<take_ref>(index);
+      return LookupDynamic(index);
     }
   }
 
-  template <bool take_ref>
-  grpc_mdelem LookupDynamic(uint32_t index) const {
+  // add a table entry to the index
+  grpc_error_handle Add(Memento md) GRPC_MUST_USE_RESULT;
+
+  // Current entry count in the table.
+  uint32_t num_entries() const { return num_entries_; }
+
+ private:
+  struct StaticMementos {
+    StaticMementos() {
+      for (uint32_t i = 0; i < hpack_constants::kLastStaticEntry; i++) {
+        memento[i] = Memento(g_static_mdelem_manifested[i]);
+      }
+    }
+    Memento memento[hpack_constants::kLastStaticEntry];
+  };
+  static const StaticMementos& GetStaticMementos() {
+    static const StaticMementos static_mementos;
+    return static_mementos;
+  }
+
+  enum { kInlineEntries = hpack_constants::kInitialTableEntries };
+  using EntriesVec = absl::InlinedVector<Memento, kInlineEntries>;
+
+  const Memento* LookupDynamic(uint32_t index) const {
     // Not static - find the value in the list of valid entries
     const uint32_t tbl_index = index - (hpack_constants::kLastStaticEntry + 1);
     if (tbl_index < num_entries_) {
       uint32_t offset =
           (num_entries_ - 1u - tbl_index + first_entry_) % entries_.size();
-      grpc_mdelem md = entries_[offset];
-      if (take_ref) {
-        GRPC_MDELEM_REF(md);
-      }
-      return md;
+      return &entries_[offset];
     }
     // Invalid entry: return error
-    return GRPC_MDNULL;
+    return nullptr;
   }
 
   void EvictOne();
@@ -110,6 +115,8 @@ class HPackTable {
   uint32_t max_entries_ = hpack_constants::kInitialTableEntries;
   // HPack table entries
   EntriesVec entries_{hpack_constants::kInitialTableEntries};
+  // Mementos for static data
+  const StaticMementos& static_metadata_;
 };
 
 }  // namespace grpc_core
@@ -120,7 +127,7 @@ class HPackTable {
 inline uintptr_t grpc_chttp2_get_static_hpack_table_index(grpc_mdelem md) {
   uintptr_t index =
       reinterpret_cast<grpc_core::StaticMetadata*>(GRPC_MDELEM_DATA(md)) -
-      grpc_static_mdelem_table();
+      grpc_core::g_static_mdelem_table;
   if (index < grpc_core::hpack_constants::kLastStaticEntry) {
     return index + 1;  // Hpack static metadata element indices start at 1
   }
diff --git a/src/core/ext/transport/chttp2/transport/incoming_metadata.cc b/src/core/ext/transport/chttp2/transport/incoming_metadata.cc
deleted file mode 100644 (file)
index c803d79..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- *
- * Copyright 2015 gRPC authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#include <grpc/support/port_platform.h>
-
-#include "src/core/ext/transport/chttp2/transport/incoming_metadata.h"
-
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-
-#include "src/core/ext/transport/chttp2/transport/internal.h"
-
-grpc_error_handle grpc_chttp2_incoming_metadata_buffer_add(
-    grpc_chttp2_incoming_metadata_buffer* buffer, grpc_mdelem elem) {
-  buffer->size += GRPC_MDELEM_LENGTH(elem);
-  grpc_linked_mdelem* storage;
-  if (buffer->count < buffer->kPreallocatedMDElem) {
-    storage = &buffer->preallocated_mdelems[buffer->count];
-    buffer->count++;
-  } else {
-    storage = static_cast<grpc_linked_mdelem*>(
-        buffer->arena->Alloc(sizeof(grpc_linked_mdelem)));
-  }
-  storage->md = elem;
-  return grpc_metadata_batch_link_tail(&buffer->batch, storage);
-}
-
-grpc_error_handle grpc_chttp2_incoming_metadata_buffer_replace_or_add(
-    grpc_chttp2_incoming_metadata_buffer* buffer, grpc_mdelem elem) {
-  for (grpc_linked_mdelem* l = buffer->batch.list.head; l != nullptr;
-       l = l->next) {
-    if (grpc_slice_eq(GRPC_MDKEY(l->md), GRPC_MDKEY(elem))) {
-      GRPC_MDELEM_UNREF(l->md);
-      l->md = elem;
-      return GRPC_ERROR_NONE;
-    }
-  }
-  return grpc_chttp2_incoming_metadata_buffer_add(buffer, elem);
-}
-
-void grpc_chttp2_incoming_metadata_buffer_set_deadline(
-    grpc_chttp2_incoming_metadata_buffer* buffer, grpc_millis deadline) {
-  buffer->batch.deadline = deadline;
-}
-
-void grpc_chttp2_incoming_metadata_buffer_publish(
-    grpc_chttp2_incoming_metadata_buffer* buffer, grpc_metadata_batch* batch) {
-  grpc_metadata_batch_move(&buffer->batch, batch);
-}
diff --git a/src/core/ext/transport/chttp2/transport/incoming_metadata.h b/src/core/ext/transport/chttp2/transport/incoming_metadata.h
deleted file mode 100644 (file)
index 68413b0..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- *
- * Copyright 2015 gRPC authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_INCOMING_METADATA_H
-#define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_INCOMING_METADATA_H
-
-#include <grpc/support/port_platform.h>
-
-#include "src/core/lib/transport/transport.h"
-
-struct grpc_chttp2_incoming_metadata_buffer {
-  explicit grpc_chttp2_incoming_metadata_buffer(grpc_core::Arena* arena)
-      : arena(arena) {
-    grpc_metadata_batch_init(&batch);
-    batch.deadline = GRPC_MILLIS_INF_FUTURE;
-  }
-  ~grpc_chttp2_incoming_metadata_buffer() {
-    grpc_metadata_batch_destroy(&batch);
-  }
-
-  static constexpr size_t kPreallocatedMDElem = 10;
-
-  grpc_core::Arena* arena;
-  size_t size = 0;   // total size of metadata.
-  size_t count = 0;  // minimum of count of metadata and kPreallocatedMDElem.
-  // These preallocated mdelems are used while count < kPreallocatedMDElem.
-  grpc_linked_mdelem preallocated_mdelems[kPreallocatedMDElem];
-  grpc_metadata_batch batch;
-};
-
-void grpc_chttp2_incoming_metadata_buffer_publish(
-    grpc_chttp2_incoming_metadata_buffer* buffer, grpc_metadata_batch* batch);
-
-grpc_error_handle grpc_chttp2_incoming_metadata_buffer_add(
-    grpc_chttp2_incoming_metadata_buffer* buffer,
-    grpc_mdelem elem) GRPC_MUST_USE_RESULT;
-grpc_error_handle grpc_chttp2_incoming_metadata_buffer_replace_or_add(
-    grpc_chttp2_incoming_metadata_buffer* buffer,
-    grpc_mdelem elem) GRPC_MUST_USE_RESULT;
-void grpc_chttp2_incoming_metadata_buffer_set_deadline(
-    grpc_chttp2_incoming_metadata_buffer* buffer, grpc_millis deadline);
-
-#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_INCOMING_METADATA_H */
index ddf8ea2..4e2c0e5 100644 (file)
@@ -34,7 +34,6 @@
 #include "src/core/ext/transport/chttp2/transport/frame_window_update.h"
 #include "src/core/ext/transport/chttp2/transport/hpack_encoder.h"
 #include "src/core/ext/transport/chttp2/transport/hpack_parser.h"
-#include "src/core/ext/transport/chttp2/transport/incoming_metadata.h"
 #include "src/core/ext/transport/chttp2/transport/stream_map.h"
 #include "src/core/lib/channel/channelz.h"
 #include "src/core/lib/compression/stream_compression.h"
@@ -43,6 +42,7 @@
 #include "src/core/lib/iomgr/endpoint.h"
 #include "src/core/lib/iomgr/timer.h"
 #include "src/core/lib/transport/connectivity_state.h"
+#include "src/core/lib/transport/metadata_batch.h"
 #include "src/core/lib/transport/transport_impl.h"
 
 namespace grpc_core {
@@ -589,7 +589,8 @@ struct grpc_chttp2_stream {
   grpc_published_metadata_method published_metadata[2] = {};
   bool final_metadata_requested = false;
 
-  grpc_chttp2_incoming_metadata_buffer metadata_buffer[2];
+  grpc_metadata_batch initial_metadata_buffer;
+  grpc_metadata_batch trailing_metadata_buffer;
 
   grpc_slice_buffer frame_storage; /* protected by t combiner */
 
@@ -766,7 +767,7 @@ grpc_chttp2_stream* grpc_chttp2_parsing_accept_stream(grpc_chttp2_transport* t,
 void grpc_chttp2_add_incoming_goaway(grpc_chttp2_transport* t,
                                      uint32_t goaway_error,
                                      uint32_t last_stream_id,
-                                     const grpc_slice& goaway_text);
+                                     absl::string_view goaway_text);
 
 void grpc_chttp2_parsing_become_skip_parser(grpc_chttp2_transport* t);
 
index aa2765c..5f75fff 100644 (file)
@@ -324,13 +324,26 @@ static HPackParser::Boundary hpack_boundary_type(grpc_chttp2_transport* t,
   }
 }
 
+static HPackParser::LogInfo hpack_parser_log_info(
+    grpc_chttp2_transport* t, HPackParser::LogInfo::Type type) {
+  return HPackParser::LogInfo{
+      t->incoming_stream_id,
+      type,
+      t->is_client,
+  };
+}
+
 static grpc_error_handle init_header_skip_frame_parser(
     grpc_chttp2_transport* t, HPackParser::Priority priority_type) {
   bool is_eoh = t->expect_continuation_stream_id != 0;
   t->parser = grpc_chttp2_header_parser_parse;
   t->parser_data = &t->hpack_parser;
-  t->hpack_parser.BeginFrame(skip_header, hpack_boundary_type(t, is_eoh),
-                             priority_type);
+  t->hpack_parser.BeginFrame(
+      nullptr,
+      t->settings[GRPC_ACKED_SETTINGS]
+                 [GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE],
+      hpack_boundary_type(t, is_eoh), priority_type,
+      hpack_parser_log_info(t, HPackParser::LogInfo::kDontKnow));
   return GRPC_ERROR_NONE;
 }
 
@@ -342,7 +355,7 @@ static grpc_error_handle init_non_header_skip_frame_parser(
 
 void grpc_chttp2_parsing_become_skip_parser(grpc_chttp2_transport* t) {
   if (t->parser == grpc_chttp2_header_parser_parse) {
-    t->hpack_parser.ResetSink(skip_header);
+    t->hpack_parser.StopBufferingFrame();
   } else {
     t->parser = skip_parser;
   }
@@ -409,170 +422,6 @@ error_handler:
   }
 }
 
-static void free_timeout(void* p) { gpr_free(p); }
-
-static bool md_key_cmp(grpc_mdelem md, const grpc_slice& reference) {
-  GPR_DEBUG_ASSERT(grpc_slice_is_interned(GRPC_MDKEY(md)));
-  return GRPC_MDKEY(md).refcount == reference.refcount;
-}
-
-static void GPR_ATTRIBUTE_NOINLINE on_initial_header_log(
-    grpc_chttp2_transport* t, grpc_chttp2_stream* s, grpc_mdelem md) {
-  char* key = grpc_slice_to_c_string(GRPC_MDKEY(md));
-  char* value =
-      grpc_dump_slice(GRPC_MDVALUE(md), GPR_DUMP_HEX | GPR_DUMP_ASCII);
-  gpr_log(GPR_INFO, "HTTP:%d:HDR:%s: %s: %s", s->id,
-          t->is_client ? "CLI" : "SVR", key, value);
-  gpr_free(key);
-  gpr_free(value);
-}
-
-static grpc_error_handle GPR_ATTRIBUTE_NOINLINE
-handle_timeout(grpc_chttp2_stream* s, grpc_mdelem md) {
-  grpc_millis* cached_timeout =
-      static_cast<grpc_millis*>(grpc_mdelem_get_user_data(md, free_timeout));
-  grpc_millis timeout;
-  if (cached_timeout != nullptr) {
-    timeout = *cached_timeout;
-  } else {
-    if (GPR_UNLIKELY(!grpc_http2_decode_timeout(GRPC_MDVALUE(md), &timeout))) {
-      char* val = grpc_slice_to_c_string(GRPC_MDVALUE(md));
-      gpr_log(GPR_ERROR, "Ignoring bad timeout value '%s'", val);
-      gpr_free(val);
-      timeout = GRPC_MILLIS_INF_FUTURE;
-    }
-    if (GRPC_MDELEM_IS_INTERNED(md)) {
-      /* store the result */
-      cached_timeout =
-          static_cast<grpc_millis*>(gpr_malloc(sizeof(grpc_millis)));
-      *cached_timeout = timeout;
-      grpc_mdelem_set_user_data(md, free_timeout, cached_timeout);
-    }
-  }
-  if (timeout != GRPC_MILLIS_INF_FUTURE) {
-    grpc_chttp2_incoming_metadata_buffer_set_deadline(
-        &s->metadata_buffer[0], grpc_core::ExecCtx::Get()->Now() + timeout);
-  }
-  GRPC_MDELEM_UNREF(md);
-  return GRPC_ERROR_NONE;
-}
-
-static grpc_error_handle GPR_ATTRIBUTE_NOINLINE
-handle_metadata_size_limit_exceeded(grpc_chttp2_transport* t,
-                                    grpc_chttp2_stream* s, grpc_mdelem md,
-                                    size_t new_size,
-                                    size_t metadata_size_limit) {
-  gpr_log(GPR_DEBUG,
-          "received initial metadata size exceeds limit (%" PRIuPTR
-          " vs. %" PRIuPTR
-          "). GRPC_ARG_MAX_METADATA_SIZE can be set to increase this limit.",
-          new_size, metadata_size_limit);
-  grpc_chttp2_cancel_stream(
-      t, s,
-      grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
-                             "received initial metadata size exceeds limit"),
-                         GRPC_ERROR_INT_GRPC_STATUS,
-                         GRPC_STATUS_RESOURCE_EXHAUSTED));
-  grpc_chttp2_parsing_become_skip_parser(t);
-  s->seen_error = true;
-  GRPC_MDELEM_UNREF(md);
-  return GRPC_ERROR_NONE;
-}
-
-static grpc_error_handle GPR_ATTRIBUTE_NOINLINE
-handle_metadata_add_failure(grpc_chttp2_transport* t, grpc_chttp2_stream* s,
-                            grpc_mdelem md, grpc_error_handle error) {
-  grpc_chttp2_cancel_stream(t, s, error);
-  grpc_chttp2_parsing_become_skip_parser(t);
-  s->seen_error = true;
-  GRPC_MDELEM_UNREF(md);
-  return GRPC_ERROR_NONE;
-}
-
-static grpc_error_handle on_initial_header(void* tp, grpc_mdelem md) {
-  GPR_TIMER_SCOPE("on_initial_header", 0);
-
-  grpc_chttp2_transport* t = static_cast<grpc_chttp2_transport*>(tp);
-  grpc_chttp2_stream* s = t->incoming_stream;
-  GPR_DEBUG_ASSERT(s != nullptr);
-
-  if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace)) {
-    on_initial_header_log(t, s, md);
-  }
-
-  if (md_key_cmp(md, GRPC_MDSTR_GRPC_TIMEOUT)) {
-    return handle_timeout(s, md);
-  }
-
-  const size_t new_size = s->metadata_buffer[0].size + GRPC_MDELEM_LENGTH(md);
-  const size_t metadata_size_limit =
-      t->settings[GRPC_ACKED_SETTINGS]
-                 [GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE];
-  if (GPR_UNLIKELY(new_size > metadata_size_limit)) {
-    return handle_metadata_size_limit_exceeded(t, s, md, new_size,
-                                               metadata_size_limit);
-  } else {
-    grpc_error_handle error =
-        grpc_chttp2_incoming_metadata_buffer_add(&s->metadata_buffer[0], md);
-    if (GPR_UNLIKELY(error != GRPC_ERROR_NONE)) {
-      return handle_metadata_add_failure(t, s, md, error);
-    }
-  }
-  // Not timeout-related metadata, and no error occurred.
-  return GRPC_ERROR_NONE;
-}
-
-static grpc_error_handle on_trailing_header(void* tp, grpc_mdelem md) {
-  GPR_TIMER_SCOPE("on_trailing_header", 0);
-
-  grpc_chttp2_transport* t = static_cast<grpc_chttp2_transport*>(tp);
-  grpc_chttp2_stream* s = t->incoming_stream;
-  GPR_DEBUG_ASSERT(s != nullptr);
-
-  if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace)) {
-    char* key = grpc_slice_to_c_string(GRPC_MDKEY(md));
-    char* value =
-        grpc_dump_slice(GRPC_MDVALUE(md), GPR_DUMP_HEX | GPR_DUMP_ASCII);
-    gpr_log(GPR_INFO, "HTTP:%d:TRL:%s: %s: %s", s->id,
-            t->is_client ? "CLI" : "SVR", key, value);
-    gpr_free(key);
-    gpr_free(value);
-  }
-
-  const size_t new_size = s->metadata_buffer[1].size + GRPC_MDELEM_LENGTH(md);
-  const size_t metadata_size_limit =
-      t->settings[GRPC_ACKED_SETTINGS]
-                 [GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE];
-  if (new_size > metadata_size_limit) {
-    gpr_log(GPR_DEBUG,
-            "received trailing metadata size exceeds limit (%" PRIuPTR
-            " vs. %" PRIuPTR
-            "). Please note that the status is also included in the trailing "
-            "metadata and a large status message can also trigger this. "
-            "GRPC_ARG_MAX_METADATA_SIZE can be set to increase this limit.",
-            new_size, metadata_size_limit);
-    grpc_chttp2_cancel_stream(
-        t, s,
-        grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
-                               "received trailing metadata size exceeds limit"),
-                           GRPC_ERROR_INT_GRPC_STATUS,
-                           GRPC_STATUS_RESOURCE_EXHAUSTED));
-    grpc_chttp2_parsing_become_skip_parser(t);
-    s->seen_error = true;
-    GRPC_MDELEM_UNREF(md);
-  } else {
-    grpc_error_handle error =
-        grpc_chttp2_incoming_metadata_buffer_add(&s->metadata_buffer[1], md);
-    if (error != GRPC_ERROR_NONE) {
-      grpc_chttp2_cancel_stream(t, s, error);
-      grpc_chttp2_parsing_become_skip_parser(t);
-      s->seen_error = true;
-      GRPC_MDELEM_UNREF(md);
-    }
-  }
-  return GRPC_ERROR_NONE;
-}
-
 static grpc_error_handle init_header_frame_parser(grpc_chttp2_transport* t,
                                                   int is_continuation) {
   const bool is_eoh =
@@ -664,7 +513,8 @@ static grpc_error_handle init_header_frame_parser(grpc_chttp2_transport* t,
   if (t->header_eof) {
     s->eos_received = true;
   }
-  HPackParser::Sink on_header;
+  grpc_metadata_batch* incoming_metadata_buffer = nullptr;
+  HPackParser::LogInfo::Type frame_type = HPackParser::LogInfo::kDontKnow;
   switch (s->header_frames_received) {
     case 0:
       if (t->is_client && t->header_eof) {
@@ -672,22 +522,29 @@ static grpc_error_handle init_header_frame_parser(grpc_chttp2_transport* t,
         if (s->trailing_metadata_available != nullptr) {
           *s->trailing_metadata_available = true;
         }
-        on_header = [t](grpc_mdelem md) { return on_trailing_header(t, md); };
+        incoming_metadata_buffer = &s->trailing_metadata_buffer;
+        frame_type = HPackParser::LogInfo::kTrailers;
       } else {
         GRPC_CHTTP2_IF_TRACING(gpr_log(GPR_INFO, "parsing initial_metadata"));
-        on_header = [t](grpc_mdelem md) { return on_initial_header(t, md); };
+        incoming_metadata_buffer = &s->initial_metadata_buffer;
+        frame_type = HPackParser::LogInfo::kHeaders;
       }
       break;
     case 1:
       GRPC_CHTTP2_IF_TRACING(gpr_log(GPR_INFO, "parsing trailing_metadata"));
-      on_header = [t](grpc_mdelem md) { return on_trailing_header(t, md); };
+      incoming_metadata_buffer = &s->trailing_metadata_buffer;
+      frame_type = HPackParser::LogInfo::kTrailers;
       break;
     case 2:
       gpr_log(GPR_ERROR, "too many header frames received");
       return init_header_skip_frame_parser(t, priority_type);
   }
-  t->hpack_parser.BeginFrame(std::move(on_header),
-                             hpack_boundary_type(t, is_eoh), priority_type);
+  t->hpack_parser.BeginFrame(
+      incoming_metadata_buffer,
+      t->settings[GRPC_ACKED_SETTINGS]
+                 [GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE],
+      hpack_boundary_type(t, is_eoh), priority_type,
+      hpack_parser_log_info(t, frame_type));
   return GRPC_ERROR_NONE;
 }
 
index 1e2c28e..3f4b4d1 100644 (file)
@@ -15,7 +15,7 @@
 #ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_POPULARITY_COUNT_H
 #define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_POPULARITY_COUNT_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 namespace grpc_core {
 
index ccd6944..bd8f555 100644 (file)
@@ -177,11 +177,12 @@ static void report_stall(grpc_chttp2_transport* t, grpc_chttp2_stream* s,
         t->settings[GRPC_ACKED_SETTINGS]
                    [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE],
         t->flow_control->remote_window(),
-        static_cast<uint32_t> GPR_MAX(
-            0,
+        static_cast<uint32_t>(std::max(
+            int64_t(0),
             s->flow_control->remote_window_delta() +
-                (int64_t)t->settings[GRPC_PEER_SETTINGS]
-                                    [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]),
+                static_cast<int64_t>(
+                    t->settings[GRPC_PEER_SETTINGS]
+                               [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]))),
         s->flow_control->remote_window_delta());
   }
 }
@@ -193,7 +194,8 @@ static uint32_t target_write_size(grpc_chttp2_transport* /*t*/) {
 
 // Returns true if initial_metadata contains only default headers.
 static bool is_default_initial_metadata(grpc_metadata_batch* initial_metadata) {
-  return initial_metadata->list.default_count == initial_metadata->list.count;
+  return initial_metadata->default_count() ==
+         initial_metadata->non_deadline_count();
 }
 
 namespace {
@@ -325,27 +327,30 @@ class DataSendContext {
         sending_bytes_before_(s_->sending_bytes) {}
 
   uint32_t stream_remote_window() const {
-    return static_cast<uint32_t> GPR_MAX(
-        0, s_->flow_control->remote_window_delta() +
-               (int64_t)t_->settings[GRPC_PEER_SETTINGS]
-                                    [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]);
+    return static_cast<uint32_t>(std::max(
+        int64_t(0),
+        s_->flow_control->remote_window_delta() +
+            static_cast<int64_t>(
+                t_->settings[GRPC_PEER_SETTINGS]
+                            [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE])));
   }
 
   uint32_t max_outgoing() const {
-    return static_cast<uint32_t> GPR_MIN(
+    return static_cast<uint32_t>(std::min(
         t_->settings[GRPC_PEER_SETTINGS][GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE],
-        GPR_MIN(stream_remote_window(), t_->flow_control->remote_window()));
+        static_cast<uint32_t>(std::min(int64_t(stream_remote_window()),
+                                       t_->flow_control->remote_window()))));
   }
 
   bool AnyOutgoing() const { return max_outgoing() > 0; }
 
   void FlushUncompressedBytes() {
-    uint32_t send_bytes = static_cast<uint32_t> GPR_MIN(
-        max_outgoing(), s_->flow_controlled_buffer.length);
+    uint32_t send_bytes = static_cast<uint32_t>(
+        std::min(size_t(max_outgoing()), s_->flow_controlled_buffer.length));
     is_last_frame_ = send_bytes == s_->flow_controlled_buffer.length &&
                      s_->fetching_send_message == nullptr &&
                      s_->send_trailing_metadata != nullptr &&
-                     grpc_metadata_batch_is_empty(s_->send_trailing_metadata);
+                     s_->send_trailing_metadata->empty();
     grpc_chttp2_encode_data(s_->id, &s_->flow_controlled_buffer, send_bytes,
                             is_last_frame_, &s_->stats.outgoing, &t_->outbuf);
     s_->flow_control->SentData(send_bytes);
@@ -356,8 +361,8 @@ class DataSendContext {
     GPR_DEBUG_ASSERT(s_->stream_compression_method !=
                      GRPC_STREAM_COMPRESSION_IDENTITY_COMPRESS);
 
-    uint32_t send_bytes = static_cast<uint32_t> GPR_MIN(
-        max_outgoing(), s_->compressed_data_buffer.length);
+    uint32_t send_bytes = static_cast<uint32_t>(
+        std::min(size_t(max_outgoing()), s_->compressed_data_buffer.length));
     bool is_last_data_frame =
         (send_bytes == s_->compressed_data_buffer.length &&
          s_->flow_controlled_buffer.length == 0 &&
@@ -380,7 +385,7 @@ class DataSendContext {
     }
     is_last_frame_ = is_last_data_frame &&
                      s_->send_trailing_metadata != nullptr &&
-                     grpc_metadata_batch_is_empty(s_->send_trailing_metadata);
+                     s_->send_trailing_metadata->empty();
     grpc_chttp2_encode_data(s_->id, &s_->compressed_data_buffer, send_bytes,
                             is_last_frame_, &s_->stats.outgoing, &t_->outbuf);
     s_->flow_control->SentData(send_bytes);
@@ -561,7 +566,7 @@ class StreamWriteContext {
     if (compressed_data_buffer_len() != 0) return;
 
     GRPC_CHTTP2_IF_TRACING(gpr_log(GPR_INFO, "sending trailing_metadata"));
-    if (grpc_metadata_batch_is_empty(s_->send_trailing_metadata)) {
+    if (s_->send_trailing_metadata->empty()) {
       grpc_chttp2_encode_data(s_->id, &s_->flow_controlled_buffer, 0, true,
                               &s_->stats.outgoing, &t_->outbuf);
     } else {
@@ -600,15 +605,17 @@ class StreamWriteContext {
         gpr_log(GPR_INFO, "not sending initial_metadata (Trailers-Only)"));
     // When sending Trailers-Only, we need to move the :status and
     // content-type headers to the trailers.
-    if (s_->send_initial_metadata->idx.named.status != nullptr) {
+    if (s_->send_initial_metadata->legacy_index()->named.status != nullptr) {
       extra_headers_for_trailing_metadata_
           [num_extra_headers_for_trailing_metadata_++] =
-              &s_->send_initial_metadata->idx.named.status->md;
+              &s_->send_initial_metadata->legacy_index()->named.status->md;
     }
-    if (s_->send_initial_metadata->idx.named.content_type != nullptr) {
+    if (s_->send_initial_metadata->legacy_index()->named.content_type !=
+        nullptr) {
       extra_headers_for_trailing_metadata_
           [num_extra_headers_for_trailing_metadata_++] =
-              &s_->send_initial_metadata->idx.named.content_type->md;
+              &s_->send_initial_metadata->legacy_index()
+                   ->named.content_type->md;
     }
   }
 
index 9c5848b..6ac15b3 100644 (file)
@@ -19,7 +19,7 @@ load(
     "grpc_cc_library",
 )
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 package(
     default_visibility = ["//visibility:public"],
index b379a4d..ef1a9b5 100644 (file)
@@ -16,7 +16,7 @@
  *
  */
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include "src/core/ext/transport/cronet/client/secure/cronet_channel_create.h"
 
index 8df100f..9557b65 100644 (file)
@@ -29,8 +29,15 @@ void grpc_deadline_filter_shutdown(void);
 void grpc_client_channel_init(void);
 void grpc_client_channel_shutdown(void);
 
+namespace grpc_core {
+void ServiceConfigParserInit(void);
+void ServiceConfigParserShutdown(void);
+}  // namespace grpc_core
+
 void grpc_register_built_in_plugins(void) {
   grpc_register_plugin(grpc_http_filters_init, grpc_http_filters_shutdown);
+  grpc_register_plugin(grpc_core::ServiceConfigParserInit,
+                       grpc_core::ServiceConfigParserShutdown);
   grpc_register_plugin(grpc_chttp2_plugin_init, grpc_chttp2_plugin_shutdown);
   grpc_register_plugin(grpc_deadline_filter_init,
                        grpc_deadline_filter_shutdown);
index fcf1115..8b831f2 100644 (file)
@@ -16,7 +16,7 @@
  *
  */
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include "src/core/ext/transport/cronet/transport/cronet_status.h"
 
index ee1262a..0b4ff3f 100644 (file)
@@ -19,7 +19,7 @@
 #ifndef GRPC_CORE_EXT_TRANSPORT_CRONET_TRANSPORT_CRONET_STATUS_H
 #define GRPC_CORE_EXT_TRANSPORT_CRONET_TRANSPORT_CRONET_STATUS_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include <grpc/status.h>
 
index 9b2ca6f..4c719e5 100644 (file)
@@ -34,7 +34,6 @@
 
 #include "src/core/ext/transport/chttp2/transport/bin_decoder.h"
 #include "src/core/ext/transport/chttp2/transport/bin_encoder.h"
-#include "src/core/ext/transport/chttp2/transport/incoming_metadata.h"
 #include "src/core/ext/transport/cronet/transport/cronet_status.h"
 #include "src/core/lib/debug/trace.h"
 #include "src/core/lib/gpr/string.h"
@@ -138,11 +137,11 @@ struct read_state {
   grpc_slice_buffer read_slice_buffer;
 
   /* vars for trailing metadata */
-  grpc_chttp2_incoming_metadata_buffer trailing_metadata;
+  grpc_metadata_batch trailing_metadata;
   bool trailing_metadata_valid = false;
 
   /* vars for initial metadata */
-  grpc_chttp2_incoming_metadata_buffer initial_metadata;
+  grpc_metadata_batch initial_metadata;
 };
 
 struct write_state {
@@ -405,14 +404,12 @@ static void execute_from_storage(stream_obj* s) {
 
 static void convert_cronet_array_to_metadata(
     const bidirectional_stream_header_array* header_array,
-    grpc_chttp2_incoming_metadata_buffer* mds) {
+    grpc_metadata_batch* mds) {
   for (size_t i = 0; i < header_array->count; i++) {
     CRONET_LOG(GPR_DEBUG, "header key=%s, value=%s",
                header_array->headers[i].key, header_array->headers[i].value);
-    grpc_slice key = grpc_slice_intern(
-        grpc_slice_from_static_string(header_array->headers[i].key));
     grpc_slice value;
-    if (grpc_is_refcounted_slice_binary_header(key)) {
+    if (absl::EndsWith(header_array->headers[i].key, "-bin")) {
       value = grpc_slice_from_static_string(header_array->headers[i].value);
       value = grpc_slice_intern(grpc_chttp2_base64_decode_with_length(
           value, grpc_chttp2_base64_infer_length_after_decode(value)));
@@ -420,9 +417,7 @@ static void convert_cronet_array_to_metadata(
       value = grpc_slice_intern(
           grpc_slice_from_static_string(header_array->headers[i].value));
     }
-    GRPC_LOG_IF_ERROR("convert_cronet_array_to_metadata",
-                      grpc_chttp2_incoming_metadata_buffer_add(
-                          mds, grpc_mdelem_from_slices(key, value)));
+    mds->Append(header_array->headers[i].key, value);
   }
 }
 
@@ -697,41 +692,37 @@ static void create_grpc_frame(grpc_slice_buffer* write_slice_buffer,
   }
 }
 
-/*
- Convert metadata in a format that Cronet can consume
-*/
-static void convert_metadata_to_cronet_headers(
-    grpc_metadata_batch* metadata, const char* host, std::string* pp_url,
-    bidirectional_stream_header** pp_headers, size_t* p_num_headers,
-    const char** method) {
-  grpc_linked_mdelem* curr = metadata->list.head;
-  /* Walk the linked list and get number of header fields */
-  size_t num_headers_available = 0;
-  while (curr != nullptr) {
-    curr = curr->next;
-    num_headers_available++;
+namespace {
+class CronetMetadataEncoder {
+ public:
+  explicit CronetMetadataEncoder(bidirectional_stream_header** pp_headers,
+                                 size_t* p_count, const char* host,
+                                 size_t capacity, const char** method,
+                                 std::string* url)
+      : host_(host),
+        capacity_(capacity),
+        count_(*p_count),
+        headers_(*pp_headers),
+        method_(method),
+        url_(url) {
+    count_ = 0;
+    headers_ = static_cast<bidirectional_stream_header*>(
+        gpr_malloc(sizeof(bidirectional_stream_header) * capacity_));
   }
-  grpc_millis deadline = metadata->deadline;
-  if (deadline != GRPC_MILLIS_INF_FUTURE) {
-    num_headers_available++;
+
+  CronetMetadataEncoder(const CronetMetadataEncoder&) = delete;
+  CronetMetadataEncoder& operator=(const CronetMetadataEncoder&) = delete;
+
+  template <class T, class V>
+  void Encode(T, V value) {
+    auto value_slice = T::Encode(value);
+    auto key_slice = grpc_slice_from_static_string(T::key());
+    auto mdelem = grpc_mdelem_from_slices(key_slice, value_slice);
+    Encode(mdelem);
+    GRPC_MDELEM_UNREF(mdelem);
   }
-  /* Allocate enough memory. It is freed in the on_stream_ready callback
-   */
-  bidirectional_stream_header* headers =
-      static_cast<bidirectional_stream_header*>(gpr_malloc(
-          sizeof(bidirectional_stream_header) * num_headers_available));
-  *pp_headers = headers;
-
-  /* Walk the linked list again, this time copying the header fields.
-    s->num_headers can be less than num_headers_available, as some headers
-    are not used for cronet.
-    TODO (makdharma): Eliminate need to traverse the LL second time for perf.
-   */
-  curr = metadata->list.head;
-  size_t num_headers = 0;
-  while (num_headers < num_headers_available) {
-    grpc_mdelem mdelem = curr->md;
-    curr = curr->next;
+
+  void Encode(grpc_mdelem mdelem) {
     char* key = grpc_slice_to_c_string(GRPC_MDKEY(mdelem));
     char* value;
     if (grpc_is_binary_header_internal(GRPC_MDKEY(mdelem))) {
@@ -747,47 +738,53 @@ static void convert_metadata_to_cronet_headers(
       /* Cronet populates these fields on its own */
       gpr_free(key);
       gpr_free(value);
-      continue;
+      return;
     }
     if (grpc_slice_eq_static_interned(GRPC_MDKEY(mdelem), GRPC_MDSTR_METHOD)) {
       if (grpc_slice_eq_static_interned(GRPC_MDVALUE(mdelem), GRPC_MDSTR_PUT)) {
-        *method = "PUT";
+        *method_ = "PUT";
       } else {
         /* POST method in default*/
-        *method = "POST";
+        *method_ = "POST";
       }
       gpr_free(key);
       gpr_free(value);
-      continue;
+      return;
     }
     if (grpc_slice_eq_static_interned(GRPC_MDKEY(mdelem), GRPC_MDSTR_PATH)) {
       /* Create URL by appending :path value to the hostname */
-      *pp_url = absl::StrCat("https://", host, value);
+      *url_ = absl::StrCat("https://", host_, value);
       gpr_free(key);
       gpr_free(value);
-      continue;
+      return;
     }
     CRONET_LOG(GPR_DEBUG, "header %s = %s", key, value);
-    headers[num_headers].key = key;
-    headers[num_headers].value = value;
-    num_headers++;
-    if (curr == nullptr) {
-      break;
-    }
-  }
-  if (deadline != GRPC_MILLIS_INF_FUTURE) {
-    char* key = grpc_slice_to_c_string(GRPC_MDSTR_GRPC_TIMEOUT);
-    char* value =
-        static_cast<char*>(gpr_malloc(GRPC_HTTP2_TIMEOUT_ENCODE_MIN_BUFSIZE));
-    grpc_http2_encode_timeout(deadline - grpc_core::ExecCtx::Get()->Now(),
-                              value);
-    headers[num_headers].key = key;
-    headers[num_headers].value = value;
-
-    num_headers++;
+    GPR_ASSERT(count_ < capacity_);
+    headers_[count_].key = key;
+    headers_[count_].value = value;
+    ++count_;
   }
 
-  *p_num_headers = num_headers;
+ private:
+  const char* host_;
+  size_t capacity_;
+  size_t& count_;
+  bidirectional_stream_header*& headers_;
+  const char** method_;
+  std::string* url_;
+};
+}  // namespace
+
+/*
+ Convert metadata in a format that Cronet can consume
+*/
+static void convert_metadata_to_cronet_headers(
+    grpc_metadata_batch* metadata, const char* host, std::string* pp_url,
+    bidirectional_stream_header** pp_headers, size_t* p_num_headers,
+    const char** method) {
+  CronetMetadataEncoder encoder(pp_headers, p_num_headers, host,
+                                metadata->count(), method, pp_url);
+  metadata->Encode(&encoder);
 }
 
 static void parse_grpc_header(const uint8_t* data, int* length,
@@ -802,15 +799,14 @@ static void parse_grpc_header(const uint8_t* data, int* length,
   *length |= (*p++);
 }
 
-static bool header_has_authority(grpc_linked_mdelem* head) {
-  while (head != nullptr) {
-    if (grpc_slice_eq_static_interned(GRPC_MDKEY(head->md),
-                                      GRPC_MDSTR_AUTHORITY)) {
-      return true;
+static bool header_has_authority(const grpc_metadata_batch* b) {
+  bool found = false;
+  b->ForEach([&](grpc_mdelem elem) {
+    if (grpc_slice_eq_static_interned(GRPC_MDKEY(elem), GRPC_MDSTR_AUTHORITY)) {
+      found = true;
     }
-    head = head->next;
-  }
-  return false;
+  });
+  return found;
 }
 
 /*
@@ -1168,9 +1164,8 @@ static enum e_op_result execute_stream_op(struct op_and_state* oas) {
           stream_op->payload->recv_initial_metadata.recv_initial_metadata_ready,
           GRPC_ERROR_NONE);
     } else {
-      grpc_chttp2_incoming_metadata_buffer_publish(
-          &oas->s->state.rs.initial_metadata,
-          stream_op->payload->recv_initial_metadata.recv_initial_metadata);
+      *stream_op->payload->recv_initial_metadata.recv_initial_metadata =
+          std::move(oas->s->state.rs.initial_metadata);
       grpc_core::ExecCtx::Run(
           DEBUG_LOCATION,
           stream_op->payload->recv_initial_metadata.recv_initial_metadata_ready,
@@ -1324,9 +1319,8 @@ static enum e_op_result execute_stream_op(struct op_and_state* oas) {
       error =
           make_error_with_desc(grpc_error_code, stream_state->net_error, desc);
     } else if (oas->s->state.rs.trailing_metadata_valid) {
-      grpc_chttp2_incoming_metadata_buffer_publish(
-          &oas->s->state.rs.trailing_metadata,
-          stream_op->payload->recv_trailing_metadata.recv_trailing_metadata);
+      *stream_op->payload->recv_trailing_metadata.recv_trailing_metadata =
+          std::move(oas->s->state.rs.trailing_metadata);
       stream_state->rs.trailing_metadata_valid = false;
     }
     grpc_core::ExecCtx::Run(
@@ -1346,7 +1340,7 @@ static enum e_op_result execute_stream_op(struct op_and_state* oas) {
       result = ACTION_TAKEN_NO_CALLBACK;
     }
     stream_state->state_op_done[OP_CANCEL_ERROR] = true;
-    if (!stream_state->cancel_error) {
+    if (stream_state->cancel_error == GRPC_ERROR_NONE) {
       stream_state->cancel_error =
           GRPC_ERROR_REF(stream_op->payload->cancel_stream.cancel_error);
     }
@@ -1438,8 +1432,8 @@ static void perform_stream_op(grpc_transport* /*gt*/, grpc_stream* gs,
                               grpc_transport_stream_op_batch* op) {
   CRONET_LOG(GPR_DEBUG, "perform_stream_op");
   if (op->send_initial_metadata &&
-      header_has_authority(op->payload->send_initial_metadata
-                               .send_initial_metadata->list.head)) {
+      header_has_authority(
+          op->payload->send_initial_metadata.send_initial_metadata)) {
     /* Cronet does not support :authority header field. We cancel the call when
      this field is present in metadata */
     if (op->recv_initial_metadata) {
index bbe62e5..31d5e0b 100644 (file)
@@ -32,7 +32,6 @@
 #include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/surface/api_trace.h"
 #include "src/core/lib/surface/channel.h"
-#include "src/core/lib/surface/channel_stack_type.h"
 #include "src/core/lib/surface/server.h"
 #include "src/core/lib/transport/connectivity_state.h"
 #include "src/core/lib/transport/error_utils.h"
@@ -58,10 +57,9 @@ void maybe_process_ops_locked(inproc_stream* s, grpc_error_handle error);
 void op_state_machine_locked(inproc_stream* s, grpc_error_handle error);
 void log_metadata(const grpc_metadata_batch* md_batch, bool is_client,
                   bool is_initial);
-grpc_error_handle fill_in_metadata(inproc_stream* s,
-                                   const grpc_metadata_batch* metadata,
-                                   uint32_t flags, grpc_metadata_batch* out_md,
-                                   uint32_t* outflags, bool* markfilled);
+void fill_in_metadata(inproc_stream* s, const grpc_metadata_batch* metadata,
+                      uint32_t flags, grpc_metadata_batch* out_md,
+                      uint32_t* outflags, bool* markfilled);
 
 struct shared_mu {
   shared_mu() {
@@ -132,11 +130,6 @@ struct inproc_stream {
     ref("inproc_init_stream:init");
     ref("inproc_init_stream:list");
 
-    grpc_metadata_batch_init(&to_read_initial_md);
-    grpc_metadata_batch_init(&to_read_trailing_md);
-    grpc_metadata_batch_init(&write_buffer_initial_md);
-    grpc_metadata_batch_init(&write_buffer_trailing_md);
-
     stream_list_prev = nullptr;
     gpr_mu_lock(&t->mu->mu);
     stream_list_next = t->stream_list;
@@ -172,18 +165,19 @@ struct inproc_stream {
       // Now transfer from the other side's write_buffer if any to the to_read
       // buffer
       if (cs->write_buffer_initial_md_filled) {
-        fill_in_metadata(this, &cs->write_buffer_initial_md,
-                         cs->write_buffer_initial_md_flags, &to_read_initial_md,
-                         &to_read_initial_md_flags, &to_read_initial_md_filled);
-        deadline = GPR_MIN(deadline, cs->write_buffer_deadline);
-        grpc_metadata_batch_clear(&cs->write_buffer_initial_md);
+        (void)fill_in_metadata(this, &cs->write_buffer_initial_md,
+                               cs->write_buffer_initial_md_flags,
+                               &to_read_initial_md, &to_read_initial_md_flags,
+                               &to_read_initial_md_filled);
+        deadline = std::min(deadline, cs->write_buffer_deadline);
+        cs->write_buffer_initial_md.Clear();
         cs->write_buffer_initial_md_filled = false;
       }
       if (cs->write_buffer_trailing_md_filled) {
-        fill_in_metadata(this, &cs->write_buffer_trailing_md, 0,
-                         &to_read_trailing_md, nullptr,
-                         &to_read_trailing_md_filled);
-        grpc_metadata_batch_clear(&cs->write_buffer_trailing_md);
+        (void)fill_in_metadata(this, &cs->write_buffer_trailing_md, 0,
+                               &to_read_trailing_md, nullptr,
+                               &to_read_trailing_md_filled);
+        cs->write_buffer_trailing_md.Clear();
         cs->write_buffer_trailing_md_filled = false;
       }
       if (cs->write_buffer_cancel_error != GRPC_ERROR_NONE) {
@@ -228,28 +222,28 @@ struct inproc_stream {
 #undef STREAM_UNREF
 
   inproc_transport* t;
-  grpc_metadata_batch to_read_initial_md;
+  grpc_stream_refcount* refs;
+  grpc_core::Arena* arena;
+
+  grpc_metadata_batch to_read_initial_md{arena};
   uint32_t to_read_initial_md_flags = 0;
   bool to_read_initial_md_filled = false;
-  grpc_metadata_batch to_read_trailing_md;
+  grpc_metadata_batch to_read_trailing_md{arena};
   bool to_read_trailing_md_filled = false;
   bool ops_needed = false;
   // Write buffer used only during gap at init time when client-side
   // stream is set up but server side stream is not yet set up
-  grpc_metadata_batch write_buffer_initial_md;
+  grpc_metadata_batch write_buffer_initial_md{arena};
   bool write_buffer_initial_md_filled = false;
   uint32_t write_buffer_initial_md_flags = 0;
   grpc_millis write_buffer_deadline = GRPC_MILLIS_INF_FUTURE;
-  grpc_metadata_batch write_buffer_trailing_md;
+  grpc_metadata_batch write_buffer_trailing_md{arena};
   bool write_buffer_trailing_md_filled = false;
   grpc_error_handle write_buffer_cancel_error = GRPC_ERROR_NONE;
 
   struct inproc_stream* other_side;
   bool other_side_closed = false;               // won't talk anymore
   bool write_buffer_other_side_closed = false;  // on hold
-  grpc_stream_refcount* refs;
-
-  grpc_core::Arena* arena;
 
   grpc_transport_stream_op_batch* send_message_op = nullptr;
   grpc_transport_stream_op_batch* send_trailing_md_op = nullptr;
@@ -285,21 +279,51 @@ struct inproc_stream {
 
 void log_metadata(const grpc_metadata_batch* md_batch, bool is_client,
                   bool is_initial) {
-  for (grpc_linked_mdelem* md = md_batch->list.head; md != nullptr;
-       md = md->next) {
-    char* key = grpc_slice_to_c_string(GRPC_MDKEY(md->md));
-    char* value = grpc_slice_to_c_string(GRPC_MDVALUE(md->md));
+  md_batch->ForEach([=](grpc_mdelem md) {
+    char* key = grpc_slice_to_c_string(GRPC_MDKEY(md));
+    char* value = grpc_slice_to_c_string(GRPC_MDVALUE(md));
     gpr_log(GPR_INFO, "INPROC:%s:%s: %s: %s", is_initial ? "HDR" : "TRL",
             is_client ? "CLI" : "SVR", key, value);
     gpr_free(key);
     gpr_free(value);
-  }
+  });
 }
 
-grpc_error_handle fill_in_metadata(inproc_stream* s,
-                                   const grpc_metadata_batch* metadata,
-                                   uint32_t flags, grpc_metadata_batch* out_md,
-                                   uint32_t* outflags, bool* markfilled) {
+namespace {
+
+class CopySink {
+ public:
+  explicit CopySink(grpc_metadata_batch* dst) : dst_(dst) {}
+
+  void Encode(grpc_mdelem md) {
+    // Differently to grpc_metadata_batch_copy, we always copy slices here so
+    // that we don't need to deal with the plethora of edge cases in that world.
+    // TODO(ctiller): revisit this when deleting mdelem.
+    md = grpc_mdelem_from_slices(grpc_slice_intern(GRPC_MDKEY(md)),
+                                 grpc_slice_copy(GRPC_MDVALUE(md)));
+    // Error unused in non-debug builds.
+    grpc_error_handle GRPC_UNUSED error = dst_->Append(md);
+    // The only way that Append() can fail is if
+    // there's a duplicate entry for a callout.  However, that can't be
+    // the case here, because we would not have been allowed to create
+    // a source batch that had that kind of conflict.
+    GPR_DEBUG_ASSERT(error == GRPC_ERROR_NONE);
+  }
+
+  template <class T, class V>
+  void Encode(T trait, V value) {
+    dst_->Set(trait, value);
+  }
+
+ private:
+  grpc_metadata_batch* dst_;
+};
+
+}  // namespace
+
+void fill_in_metadata(inproc_stream* s, const grpc_metadata_batch* metadata,
+                      uint32_t flags, grpc_metadata_batch* out_md,
+                      uint32_t* outflags, bool* markfilled) {
   if (GRPC_TRACE_FLAG_ENABLED(grpc_inproc_trace)) {
     log_metadata(metadata, s->t->is_client, outflags != nullptr);
   }
@@ -310,18 +334,13 @@ grpc_error_handle fill_in_metadata(inproc_stream* s,
   if (markfilled != nullptr) {
     *markfilled = true;
   }
-  grpc_error_handle error = GRPC_ERROR_NONE;
-  for (grpc_linked_mdelem* elem = metadata->list.head;
-       (elem != nullptr) && (error == GRPC_ERROR_NONE); elem = elem->next) {
-    grpc_linked_mdelem* nelem =
-        static_cast<grpc_linked_mdelem*>(s->arena->Alloc(sizeof(*nelem)));
-    nelem->md =
-        grpc_mdelem_from_slices(grpc_slice_intern(GRPC_MDKEY(elem->md)),
-                                grpc_slice_intern(GRPC_MDVALUE(elem->md)));
-
-    error = grpc_metadata_batch_link_tail(out_md, nelem);
-  }
-  return error;
+
+  // TODO(ctiller): copy the metadata batch, don't rely on a bespoke copy
+  // function. Can only do this once mdelems are out of the way though, too many
+  // edge cases otherwise.
+  out_md->Clear();
+  CopySink sink(out_md);
+  metadata->Encode(&sink);
 }
 
 int init_stream(grpc_transport* gt, grpc_stream* gs,
@@ -336,8 +355,8 @@ int init_stream(grpc_transport* gt, grpc_stream* gs,
 void close_stream_locked(inproc_stream* s) {
   if (!s->closed) {
     // Release the metadata that we would have written out
-    grpc_metadata_batch_destroy(&s->write_buffer_initial_md);
-    grpc_metadata_batch_destroy(&s->write_buffer_trailing_md);
+    s->write_buffer_initial_md.Clear();
+    s->write_buffer_trailing_md.Clear();
 
     if (s->listed) {
       inproc_stream* p = s->stream_list_prev;
@@ -362,8 +381,8 @@ void close_stream_locked(inproc_stream* s) {
 void close_other_side_locked(inproc_stream* s, const char* reason) {
   if (s->other_side != nullptr) {
     // First release the metadata that came from the other side's arena
-    grpc_metadata_batch_destroy(&s->to_read_initial_md);
-    grpc_metadata_batch_destroy(&s->to_read_trailing_md);
+    s->to_read_initial_md.Clear();
+    s->to_read_trailing_md.Clear();
 
     s->other_side->unref(reason);
     s->other_side_closed = true;
@@ -413,17 +432,14 @@ void fail_helper_locked(inproc_stream* s, grpc_error_handle error) {
     // Send trailing md to the other side indicating cancellation
     s->trailing_md_sent = true;
 
-    grpc_metadata_batch fake_md;
-    grpc_metadata_batch_init(&fake_md);
-
+    grpc_metadata_batch fake_md(s->arena);
     inproc_stream* other = s->other_side;
     grpc_metadata_batch* dest = (other == nullptr)
                                     ? &s->write_buffer_trailing_md
                                     : &other->to_read_trailing_md;
     bool* destfilled = (other == nullptr) ? &s->write_buffer_trailing_md_filled
                                           : &other->to_read_trailing_md_filled;
-    fill_in_metadata(s, &fake_md, 0, dest, nullptr, destfilled);
-    grpc_metadata_batch_destroy(&fake_md);
+    (void)fill_in_metadata(s, &fake_md, 0, dest, nullptr, destfilled);
 
     if (other != nullptr) {
       if (other->cancel_other_error == GRPC_ERROR_NONE) {
@@ -439,26 +455,22 @@ void fail_helper_locked(inproc_stream* s, grpc_error_handle error) {
     if (!s->t->is_client) {
       // If this is a server, provide initial metadata with a path and authority
       // since it expects that as well as no error yet
-      grpc_metadata_batch fake_md;
-      grpc_metadata_batch_init(&fake_md);
+      grpc_metadata_batch fake_md(s->arena);
       grpc_linked_mdelem* path_md =
           static_cast<grpc_linked_mdelem*>(s->arena->Alloc(sizeof(*path_md)));
       path_md->md = grpc_mdelem_from_slices(g_fake_path_key, g_fake_path_value);
-      GPR_ASSERT(grpc_metadata_batch_link_tail(&fake_md, path_md) ==
-                 GRPC_ERROR_NONE);
+      GPR_ASSERT(fake_md.LinkTail(path_md) == GRPC_ERROR_NONE);
       grpc_linked_mdelem* auth_md =
           static_cast<grpc_linked_mdelem*>(s->arena->Alloc(sizeof(*auth_md)));
       auth_md->md = grpc_mdelem_from_slices(g_fake_auth_key, g_fake_auth_value);
-      GPR_ASSERT(grpc_metadata_batch_link_tail(&fake_md, auth_md) ==
-                 GRPC_ERROR_NONE);
+      GPR_ASSERT(fake_md.LinkTail(auth_md) == GRPC_ERROR_NONE);
 
-      fill_in_metadata(
+      (void)fill_in_metadata(
           s, &fake_md, 0,
           s->recv_initial_md_op->payload->recv_initial_metadata
               .recv_initial_metadata,
           s->recv_initial_md_op->payload->recv_initial_metadata.recv_flags,
           nullptr);
-      grpc_metadata_batch_destroy(&fake_md);
       err = GRPC_ERROR_NONE;
     } else {
       err = GRPC_ERROR_REF(error);
@@ -656,10 +668,11 @@ void op_state_machine_locked(inproc_stream* s, grpc_error_handle error) {
       goto done;
     } else {
       if (!other || !other->closed) {
-        fill_in_metadata(s,
-                         s->send_trailing_md_op->payload->send_trailing_metadata
-                             .send_trailing_metadata,
-                         0, dest, nullptr, destfilled);
+        (void)fill_in_metadata(
+            s,
+            s->send_trailing_md_op->payload->send_trailing_metadata
+                .send_trailing_metadata,
+            0, dest, nullptr, destfilled);
       }
       s->trailing_md_sent = true;
       if (s->send_trailing_md_op->payload->send_trailing_metadata.sent) {
@@ -703,42 +716,34 @@ void op_state_machine_locked(inproc_stream* s, grpc_error_handle error) {
 
     if (s->to_read_initial_md_filled) {
       s->initial_md_recvd = true;
-      new_err = fill_in_metadata(
+      fill_in_metadata(
           s, &s->to_read_initial_md, s->to_read_initial_md_flags,
           s->recv_initial_md_op->payload->recv_initial_metadata
               .recv_initial_metadata,
           s->recv_initial_md_op->payload->recv_initial_metadata.recv_flags,
           nullptr);
-      s->recv_initial_md_op->payload->recv_initial_metadata
-          .recv_initial_metadata->deadline = s->deadline;
+      if (s->deadline != GRPC_MILLIS_INF_FUTURE) {
+        s->recv_initial_md_op->payload->recv_initial_metadata
+            .recv_initial_metadata->Set(grpc_core::GrpcTimeoutMetadata(),
+                                        s->deadline);
+      }
       if (s->recv_initial_md_op->payload->recv_initial_metadata
               .trailing_metadata_available != nullptr) {
         *s->recv_initial_md_op->payload->recv_initial_metadata
              .trailing_metadata_available =
             (other != nullptr && other->send_trailing_md_op != nullptr);
       }
-      grpc_metadata_batch_clear(&s->to_read_initial_md);
+      s->to_read_initial_md.Clear();
       s->to_read_initial_md_filled = false;
-      INPROC_LOG(GPR_INFO,
-                 "op_state_machine %p scheduling initial-metadata-ready %s", s,
-                 grpc_error_std_string(new_err).c_str());
       grpc_core::ExecCtx::Run(
           DEBUG_LOCATION,
           s->recv_initial_md_op->payload->recv_initial_metadata
               .recv_initial_metadata_ready,
-          GRPC_ERROR_REF(new_err));
+          GRPC_ERROR_NONE);
       complete_if_batch_end_locked(
-          s, new_err, s->recv_initial_md_op,
+          s, GRPC_ERROR_NONE, s->recv_initial_md_op,
           "op_state_machine scheduling recv-initial-metadata-on-complete");
       s->recv_initial_md_op = nullptr;
-
-      if (new_err != GRPC_ERROR_NONE) {
-        INPROC_LOG(GPR_INFO,
-                   "op_state_machine %p scheduling on_complete errors2 %s", s,
-                   grpc_error_std_string(new_err).c_str());
-        fail_helper_locked(s, GRPC_ERROR_REF(new_err));
-        goto done;
-      }
     }
   }
   if (s->recv_message_op) {
@@ -754,7 +759,7 @@ void op_state_machine_locked(inproc_stream* s, grpc_error_handle error) {
                    "op_state_machine %p already implicitly received trailing "
                    "metadata, so ignoring new trailing metadata from client",
                    s);
-        grpc_metadata_batch_clear(&s->to_read_trailing_md);
+        s->to_read_trailing_md.Clear();
         s->to_read_trailing_md_filled = false;
         s->trailing_md_recvd_implicit_only = false;
       } else {
@@ -796,12 +801,11 @@ void op_state_machine_locked(inproc_stream* s, grpc_error_handle error) {
     if (s->recv_trailing_md_op != nullptr) {
       // We wanted trailing metadata and we got it
       s->trailing_md_recvd = true;
-      new_err =
-          fill_in_metadata(s, &s->to_read_trailing_md, 0,
-                           s->recv_trailing_md_op->payload
-                               ->recv_trailing_metadata.recv_trailing_metadata,
-                           nullptr, nullptr);
-      grpc_metadata_batch_clear(&s->to_read_trailing_md);
+      fill_in_metadata(s, &s->to_read_trailing_md, 0,
+                       s->recv_trailing_md_op->payload->recv_trailing_metadata
+                           .recv_trailing_metadata,
+                       nullptr, nullptr);
+      s->to_read_trailing_md.Clear();
       s->to_read_trailing_md_filled = false;
 
       // We should schedule the recv_trailing_md_op completion if
@@ -810,24 +814,16 @@ void op_state_machine_locked(inproc_stream* s, grpc_error_handle error) {
       //    (If the server hasn't already sent its trailing md, it doesn't have
       //     a final status, so don't mark this op complete)
       if (s->t->is_client || s->trailing_md_sent) {
-        INPROC_LOG(GPR_INFO,
-                   "op_state_machine %p scheduling trailing-md-on-complete %s",
-                   s, grpc_error_std_string(new_err).c_str());
         grpc_core::ExecCtx::Run(
             DEBUG_LOCATION,
             s->recv_trailing_md_op->payload->recv_trailing_metadata
                 .recv_trailing_metadata_ready,
-            GRPC_ERROR_REF(new_err));
+            GRPC_ERROR_NONE);
         grpc_core::ExecCtx::Run(DEBUG_LOCATION,
                                 s->recv_trailing_md_op->on_complete,
-                                GRPC_ERROR_REF(new_err));
+                                GRPC_ERROR_NONE);
         s->recv_trailing_md_op = nullptr;
         needs_close = s->trailing_md_sent;
-      } else {
-        INPROC_LOG(GPR_INFO,
-                   "op_state_machine %p server needs to delay handling "
-                   "trailing-md-on-complete %s",
-                   s, grpc_error_std_string(new_err).c_str());
       }
     } else if (!s->trailing_md_recvd) {
       INPROC_LOG(
@@ -911,16 +907,14 @@ bool cancel_stream_locked(inproc_stream* s, grpc_error_handle error) {
     // already have
     s->trailing_md_sent = true;
 
-    grpc_metadata_batch cancel_md;
-    grpc_metadata_batch_init(&cancel_md);
+    grpc_metadata_batch cancel_md(s->arena);
 
     grpc_metadata_batch* dest = (other == nullptr)
                                     ? &s->write_buffer_trailing_md
                                     : &other->to_read_trailing_md;
     bool* destfilled = (other == nullptr) ? &s->write_buffer_trailing_md_filled
                                           : &other->to_read_trailing_md_filled;
-    fill_in_metadata(s, &cancel_md, 0, dest, nullptr, destfilled);
-    grpc_metadata_batch_destroy(&cancel_md);
+    (void)fill_in_metadata(s, &cancel_md, 0, dest, nullptr, destfilled);
 
     if (other != nullptr) {
       if (other->cancel_other_error == GRPC_ERROR_NONE) {
@@ -1025,7 +1019,7 @@ void perform_stream_op(grpc_transport* gt, grpc_stream* gs,
         error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Extra initial metadata");
       } else {
         if (!s->other_side_closed) {
-          fill_in_metadata(
+          (void)fill_in_metadata(
               s, op->payload->send_initial_metadata.send_initial_metadata,
               op->payload->send_initial_metadata.send_initial_metadata_flags,
               dest, destflags, destfilled);
@@ -1033,8 +1027,10 @@ void perform_stream_op(grpc_transport* gt, grpc_stream* gs,
         if (s->t->is_client) {
           grpc_millis* dl =
               (other == nullptr) ? &s->write_buffer_deadline : &other->deadline;
-          *dl = GPR_MIN(*dl, op->payload->send_initial_metadata
-                                 .send_initial_metadata->deadline);
+          *dl = std::min(
+              *dl, op->payload->send_initial_metadata.send_initial_metadata
+                       ->get(grpc_core::GrpcTimeoutMetadata())
+                       .value_or(GRPC_MILLIS_INF_FUTURE));
           s->initial_md_sent = true;
         }
       }
index 003330c..2f4ed97 100644 (file)
@@ -49,7 +49,7 @@ const upb_msglayout envoy_config_cluster_v3_ClusterCollection_msginit = {
   UPB_SIZE(8, 16), 1, false, 1, 255,
 };
 
-static const upb_msglayout *const envoy_config_cluster_v3_Cluster_submsgs[34] = {
+static const upb_msglayout *const envoy_config_cluster_v3_Cluster_submsgs[35] = {
   &envoy_config_cluster_v3_CircuitBreakers_msginit,
   &envoy_config_cluster_v3_Cluster_CommonLbConfig_msginit,
   &envoy_config_cluster_v3_Cluster_CustomClusterType_msginit,
@@ -61,6 +61,7 @@ static const upb_msglayout *const envoy_config_cluster_v3_Cluster_submsgs[34] =
   &envoy_config_cluster_v3_Cluster_PreconnectPolicy_msginit,
   &envoy_config_cluster_v3_Cluster_RefreshRate_msginit,
   &envoy_config_cluster_v3_Cluster_RingHashLbConfig_msginit,
+  &envoy_config_cluster_v3_Cluster_RoundRobinLbConfig_msginit,
   &envoy_config_cluster_v3_Cluster_TransportSocketMatch_msginit,
   &envoy_config_cluster_v3_Cluster_TypedExtensionProtocolOptionsEntry_msginit,
   &envoy_config_cluster_v3_Filter_msginit,
@@ -86,63 +87,64 @@ static const upb_msglayout *const envoy_config_cluster_v3_Cluster_submsgs[34] =
   &google_protobuf_UInt32Value_msginit,
 };
 
-static const upb_msglayout_field envoy_config_cluster_v3_Cluster__fields[50] = {
+static const upb_msglayout_field envoy_config_cluster_v3_Cluster__fields[51] = {
   {1, UPB_SIZE(24, 24), 0, 0, 9, _UPB_MODE_SCALAR},
   {2, UPB_SIZE(172, 320), UPB_SIZE(-177, -329), 0, 14, _UPB_MODE_SCALAR},
   {3, UPB_SIZE(40, 56), 1, 3, 11, _UPB_MODE_SCALAR},
-  {4, UPB_SIZE(44, 64), 2, 32, 11, _UPB_MODE_SCALAR},
-  {5, UPB_SIZE(48, 72), 3, 33, 11, _UPB_MODE_SCALAR},
+  {4, UPB_SIZE(44, 64), 2, 33, 11, _UPB_MODE_SCALAR},
+  {5, UPB_SIZE(48, 72), 3, 34, 11, _UPB_MODE_SCALAR},
   {6, UPB_SIZE(4, 4), 0, 0, 14, _UPB_MODE_SCALAR},
-  {8, UPB_SIZE(152, 280), 0, 22, 11, _UPB_MODE_ARRAY},
-  {9, UPB_SIZE(52, 80), 4, 33, 11, _UPB_MODE_SCALAR},
+  {8, UPB_SIZE(152, 280), 0, 23, 11, _UPB_MODE_ARRAY},
+  {9, UPB_SIZE(52, 80), 4, 34, 11, _UPB_MODE_SCALAR},
   {10, UPB_SIZE(56, 88), 5, 0, 11, _UPB_MODE_SCALAR},
-  {13, UPB_SIZE(60, 96), 6, 23, 11, _UPB_MODE_SCALAR},
-  {14, UPB_SIZE(64, 104), 7, 24, 11, _UPB_MODE_SCALAR},
-  {16, UPB_SIZE(68, 112), 8, 32, 11, _UPB_MODE_SCALAR},
+  {13, UPB_SIZE(60, 96), 6, 24, 11, _UPB_MODE_SCALAR},
+  {14, UPB_SIZE(64, 104), 7, 25, 11, _UPB_MODE_SCALAR},
+  {16, UPB_SIZE(68, 112), 8, 33, 11, _UPB_MODE_SCALAR},
   {17, UPB_SIZE(8, 8), 0, 0, 14, _UPB_MODE_SCALAR},
-  {18, UPB_SIZE(156, 288), 0, 18, 11, _UPB_MODE_ARRAY},
-  {19, UPB_SIZE(72, 120), 9, 15, 11, _UPB_MODE_SCALAR},
-  {20, UPB_SIZE(76, 128), 10, 32, 11, _UPB_MODE_SCALAR},
-  {21, UPB_SIZE(80, 136), 11, 19, 11, _UPB_MODE_SCALAR},
+  {18, UPB_SIZE(156, 288), 0, 19, 11, _UPB_MODE_ARRAY},
+  {19, UPB_SIZE(72, 120), 9, 16, 11, _UPB_MODE_SCALAR},
+  {20, UPB_SIZE(76, 128), 10, 33, 11, _UPB_MODE_SCALAR},
+  {21, UPB_SIZE(80, 136), 11, 20, 11, _UPB_MODE_SCALAR},
   {22, UPB_SIZE(84, 144), 12, 4, 11, _UPB_MODE_SCALAR},
   {23, UPB_SIZE(180, 336), UPB_SIZE(-185, -345), 10, 11, _UPB_MODE_SCALAR},
-  {24, UPB_SIZE(88, 152), 13, 27, 11, _UPB_MODE_SCALAR},
-  {25, UPB_SIZE(92, 160), 14, 26, 11, _UPB_MODE_SCALAR},
+  {24, UPB_SIZE(88, 152), 13, 28, 11, _UPB_MODE_SCALAR},
+  {25, UPB_SIZE(92, 160), 14, 27, 11, _UPB_MODE_SCALAR},
   {26, UPB_SIZE(12, 12), 0, 0, 14, _UPB_MODE_SCALAR},
   {27, UPB_SIZE(96, 168), 15, 1, 11, _UPB_MODE_SCALAR},
   {28, UPB_SIZE(32, 40), 0, 0, 9, _UPB_MODE_SCALAR},
-  {29, UPB_SIZE(100, 176), 16, 25, 11, _UPB_MODE_SCALAR},
-  {30, UPB_SIZE(104, 184), 17, 17, 11, _UPB_MODE_SCALAR},
+  {29, UPB_SIZE(100, 176), 16, 26, 11, _UPB_MODE_SCALAR},
+  {30, UPB_SIZE(104, 184), 17, 18, 11, _UPB_MODE_SCALAR},
   {31, UPB_SIZE(16, 16), 0, 0, 8, _UPB_MODE_SCALAR},
   {32, UPB_SIZE(17, 17), 0, 0, 8, _UPB_MODE_SCALAR},
-  {33, UPB_SIZE(108, 192), 18, 30, 11, _UPB_MODE_SCALAR},
+  {33, UPB_SIZE(108, 192), 18, 31, 11, _UPB_MODE_SCALAR},
   {34, UPB_SIZE(180, 336), UPB_SIZE(-185, -345), 7, 11, _UPB_MODE_SCALAR},
-  {36, UPB_SIZE(160, 296), 0, 12, 11, _UPB_MODE_MAP},
+  {36, UPB_SIZE(160, 296), 0, 13, 11, _UPB_MODE_MAP},
   {37, UPB_SIZE(180, 336), UPB_SIZE(-185, -345), 5, 11, _UPB_MODE_SCALAR},
   {38, UPB_SIZE(172, 320), UPB_SIZE(-177, -329), 2, 11, _UPB_MODE_SCALAR},
   {39, UPB_SIZE(18, 18), 0, 0, 8, _UPB_MODE_SCALAR},
-  {40, UPB_SIZE(164, 304), 0, 13, 11, _UPB_MODE_ARRAY},
-  {41, UPB_SIZE(112, 200), 19, 14, 11, _UPB_MODE_SCALAR},
-  {42, UPB_SIZE(116, 208), 20, 20, 11, _UPB_MODE_SCALAR},
-  {43, UPB_SIZE(168, 312), 0, 11, 11, _UPB_MODE_ARRAY},
+  {40, UPB_SIZE(164, 304), 0, 14, 11, _UPB_MODE_ARRAY},
+  {41, UPB_SIZE(112, 200), 19, 15, 11, _UPB_MODE_SCALAR},
+  {42, UPB_SIZE(116, 208), 20, 21, 11, _UPB_MODE_SCALAR},
+  {43, UPB_SIZE(168, 312), 0, 12, 11, _UPB_MODE_ARRAY},
   {44, UPB_SIZE(120, 216), 21, 9, 11, _UPB_MODE_SCALAR},
   {45, UPB_SIZE(19, 19), 0, 0, 8, _UPB_MODE_SCALAR},
-  {46, UPB_SIZE(124, 224), 22, 29, 11, _UPB_MODE_SCALAR},
+  {46, UPB_SIZE(124, 224), 22, 30, 11, _UPB_MODE_SCALAR},
   {47, UPB_SIZE(20, 20), 0, 0, 8, _UPB_MODE_SCALAR},
-  {48, UPB_SIZE(128, 232), 23, 28, 11, _UPB_MODE_SCALAR},
-  {49, UPB_SIZE(132, 240), 24, 16, 11, _UPB_MODE_SCALAR},
+  {48, UPB_SIZE(128, 232), 23, 29, 11, _UPB_MODE_SCALAR},
+  {49, UPB_SIZE(132, 240), 24, 17, 11, _UPB_MODE_SCALAR},
   {50, UPB_SIZE(136, 248), 25, 8, 11, _UPB_MODE_SCALAR},
   {51, UPB_SIZE(21, 21), 0, 0, 8, _UPB_MODE_SCALAR},
   {52, UPB_SIZE(180, 336), UPB_SIZE(-185, -345), 6, 11, _UPB_MODE_SCALAR},
-  {53, UPB_SIZE(140, 256), 26, 21, 11, _UPB_MODE_SCALAR},
-  {54, UPB_SIZE(144, 264), 27, 31, 11, _UPB_MODE_SCALAR},
-  {55, UPB_SIZE(148, 272), 28, 28, 11, _UPB_MODE_SCALAR},
+  {53, UPB_SIZE(140, 256), 26, 22, 11, _UPB_MODE_SCALAR},
+  {54, UPB_SIZE(144, 264), 27, 32, 11, _UPB_MODE_SCALAR},
+  {55, UPB_SIZE(148, 272), 28, 29, 11, _UPB_MODE_SCALAR},
+  {56, UPB_SIZE(180, 336), UPB_SIZE(-185, -345), 11, 11, _UPB_MODE_SCALAR},
 };
 
 const upb_msglayout envoy_config_cluster_v3_Cluster_msginit = {
   &envoy_config_cluster_v3_Cluster_submsgs[0],
   &envoy_config_cluster_v3_Cluster__fields[0],
-  UPB_SIZE(192, 352), 50, false, 6, 255,
+  UPB_SIZE(192, 352), 51, false, 6, 255,
 };
 
 static const upb_msglayout *const envoy_config_cluster_v3_Cluster_TransportSocketMatch_submsgs[2] = {
@@ -226,20 +228,52 @@ const upb_msglayout envoy_config_cluster_v3_Cluster_LbSubsetConfig_LbSubsetSelec
   UPB_SIZE(16, 24), 4, false, 4, 255,
 };
 
-static const upb_msglayout *const envoy_config_cluster_v3_Cluster_LeastRequestLbConfig_submsgs[2] = {
+static const upb_msglayout *const envoy_config_cluster_v3_Cluster_SlowStartConfig_submsgs[2] = {
   &envoy_config_core_v3_RuntimeDouble_msginit,
-  &google_protobuf_UInt32Value_msginit,
+  &google_protobuf_Duration_msginit,
 };
 
-static const upb_msglayout_field envoy_config_cluster_v3_Cluster_LeastRequestLbConfig__fields[2] = {
+static const upb_msglayout_field envoy_config_cluster_v3_Cluster_SlowStartConfig__fields[2] = {
   {1, UPB_SIZE(4, 8), 1, 1, 11, _UPB_MODE_SCALAR},
   {2, UPB_SIZE(8, 16), 2, 0, 11, _UPB_MODE_SCALAR},
 };
 
+const upb_msglayout envoy_config_cluster_v3_Cluster_SlowStartConfig_msginit = {
+  &envoy_config_cluster_v3_Cluster_SlowStartConfig_submsgs[0],
+  &envoy_config_cluster_v3_Cluster_SlowStartConfig__fields[0],
+  UPB_SIZE(16, 24), 2, false, 2, 255,
+};
+
+static const upb_msglayout *const envoy_config_cluster_v3_Cluster_RoundRobinLbConfig_submsgs[1] = {
+  &envoy_config_cluster_v3_Cluster_SlowStartConfig_msginit,
+};
+
+static const upb_msglayout_field envoy_config_cluster_v3_Cluster_RoundRobinLbConfig__fields[1] = {
+  {1, UPB_SIZE(4, 8), 1, 0, 11, _UPB_MODE_SCALAR},
+};
+
+const upb_msglayout envoy_config_cluster_v3_Cluster_RoundRobinLbConfig_msginit = {
+  &envoy_config_cluster_v3_Cluster_RoundRobinLbConfig_submsgs[0],
+  &envoy_config_cluster_v3_Cluster_RoundRobinLbConfig__fields[0],
+  UPB_SIZE(8, 16), 1, false, 1, 255,
+};
+
+static const upb_msglayout *const envoy_config_cluster_v3_Cluster_LeastRequestLbConfig_submsgs[3] = {
+  &envoy_config_cluster_v3_Cluster_SlowStartConfig_msginit,
+  &envoy_config_core_v3_RuntimeDouble_msginit,
+  &google_protobuf_UInt32Value_msginit,
+};
+
+static const upb_msglayout_field envoy_config_cluster_v3_Cluster_LeastRequestLbConfig__fields[3] = {
+  {1, UPB_SIZE(4, 8), 1, 2, 11, _UPB_MODE_SCALAR},
+  {2, UPB_SIZE(8, 16), 2, 1, 11, _UPB_MODE_SCALAR},
+  {3, UPB_SIZE(12, 24), 3, 0, 11, _UPB_MODE_SCALAR},
+};
+
 const upb_msglayout envoy_config_cluster_v3_Cluster_LeastRequestLbConfig_msginit = {
   &envoy_config_cluster_v3_Cluster_LeastRequestLbConfig_submsgs[0],
   &envoy_config_cluster_v3_Cluster_LeastRequestLbConfig__fields[0],
-  UPB_SIZE(16, 24), 2, false, 2, 255,
+  UPB_SIZE(16, 32), 3, false, 3, 255,
 };
 
 static const upb_msglayout *const envoy_config_cluster_v3_Cluster_RingHashLbConfig_submsgs[1] = {
index 293ded8..21e689b 100644 (file)
@@ -27,6 +27,8 @@ struct envoy_config_cluster_v3_Cluster_CustomClusterType;
 struct envoy_config_cluster_v3_Cluster_EdsClusterConfig;
 struct envoy_config_cluster_v3_Cluster_LbSubsetConfig;
 struct envoy_config_cluster_v3_Cluster_LbSubsetConfig_LbSubsetSelector;
+struct envoy_config_cluster_v3_Cluster_SlowStartConfig;
+struct envoy_config_cluster_v3_Cluster_RoundRobinLbConfig;
 struct envoy_config_cluster_v3_Cluster_LeastRequestLbConfig;
 struct envoy_config_cluster_v3_Cluster_RingHashLbConfig;
 struct envoy_config_cluster_v3_Cluster_MaglevLbConfig;
@@ -50,6 +52,8 @@ typedef struct envoy_config_cluster_v3_Cluster_CustomClusterType envoy_config_cl
 typedef struct envoy_config_cluster_v3_Cluster_EdsClusterConfig envoy_config_cluster_v3_Cluster_EdsClusterConfig;
 typedef struct envoy_config_cluster_v3_Cluster_LbSubsetConfig envoy_config_cluster_v3_Cluster_LbSubsetConfig;
 typedef struct envoy_config_cluster_v3_Cluster_LbSubsetConfig_LbSubsetSelector envoy_config_cluster_v3_Cluster_LbSubsetConfig_LbSubsetSelector;
+typedef struct envoy_config_cluster_v3_Cluster_SlowStartConfig envoy_config_cluster_v3_Cluster_SlowStartConfig;
+typedef struct envoy_config_cluster_v3_Cluster_RoundRobinLbConfig envoy_config_cluster_v3_Cluster_RoundRobinLbConfig;
 typedef struct envoy_config_cluster_v3_Cluster_LeastRequestLbConfig envoy_config_cluster_v3_Cluster_LeastRequestLbConfig;
 typedef struct envoy_config_cluster_v3_Cluster_RingHashLbConfig envoy_config_cluster_v3_Cluster_RingHashLbConfig;
 typedef struct envoy_config_cluster_v3_Cluster_MaglevLbConfig envoy_config_cluster_v3_Cluster_MaglevLbConfig;
@@ -73,6 +77,8 @@ extern const upb_msglayout envoy_config_cluster_v3_Cluster_CustomClusterType_msg
 extern const upb_msglayout envoy_config_cluster_v3_Cluster_EdsClusterConfig_msginit;
 extern const upb_msglayout envoy_config_cluster_v3_Cluster_LbSubsetConfig_msginit;
 extern const upb_msglayout envoy_config_cluster_v3_Cluster_LbSubsetConfig_LbSubsetSelector_msginit;
+extern const upb_msglayout envoy_config_cluster_v3_Cluster_SlowStartConfig_msginit;
+extern const upb_msglayout envoy_config_cluster_v3_Cluster_RoundRobinLbConfig_msginit;
 extern const upb_msglayout envoy_config_cluster_v3_Cluster_LeastRequestLbConfig_msginit;
 extern const upb_msglayout envoy_config_cluster_v3_Cluster_RingHashLbConfig_msginit;
 extern const upb_msglayout envoy_config_cluster_v3_Cluster_MaglevLbConfig_msginit;
@@ -160,7 +166,8 @@ typedef enum {
 typedef enum {
   envoy_config_cluster_v3_Cluster_AUTO = 0,
   envoy_config_cluster_v3_Cluster_V4_ONLY = 1,
-  envoy_config_cluster_v3_Cluster_V6_ONLY = 2
+  envoy_config_cluster_v3_Cluster_V6_ONLY = 2,
+  envoy_config_cluster_v3_Cluster_V4_PREFERRED = 3
 } envoy_config_cluster_v3_Cluster_DnsLookupFamily;
 
 typedef enum {
@@ -274,6 +281,7 @@ typedef enum {
   envoy_config_cluster_v3_Cluster_lb_config_maglev_lb_config = 52,
   envoy_config_cluster_v3_Cluster_lb_config_original_dst_lb_config = 34,
   envoy_config_cluster_v3_Cluster_lb_config_least_request_lb_config = 37,
+  envoy_config_cluster_v3_Cluster_lb_config_round_robin_lb_config = 56,
   envoy_config_cluster_v3_Cluster_lb_config_NOT_SET = 0
 } envoy_config_cluster_v3_Cluster_lb_config_oneofcases;
 UPB_INLINE envoy_config_cluster_v3_Cluster_lb_config_oneofcases envoy_config_cluster_v3_Cluster_lb_config_case(const envoy_config_cluster_v3_Cluster* msg) { return (envoy_config_cluster_v3_Cluster_lb_config_oneofcases)*UPB_PTR_AT(msg, UPB_SIZE(184, 344), int32_t); }
@@ -369,6 +377,8 @@ UPB_INLINE bool envoy_config_cluster_v3_Cluster_has_wait_for_warm_on_init(const
 UPB_INLINE const struct google_protobuf_BoolValue* envoy_config_cluster_v3_Cluster_wait_for_warm_on_init(const envoy_config_cluster_v3_Cluster *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(144, 264), const struct google_protobuf_BoolValue*); }
 UPB_INLINE bool envoy_config_cluster_v3_Cluster_has_typed_dns_resolver_config(const envoy_config_cluster_v3_Cluster *msg) { return _upb_hasbit(msg, 28); }
 UPB_INLINE const struct envoy_config_core_v3_TypedExtensionConfig* envoy_config_cluster_v3_Cluster_typed_dns_resolver_config(const envoy_config_cluster_v3_Cluster *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(148, 272), const struct envoy_config_core_v3_TypedExtensionConfig*); }
+UPB_INLINE bool envoy_config_cluster_v3_Cluster_has_round_robin_lb_config(const envoy_config_cluster_v3_Cluster *msg) { return _upb_getoneofcase(msg, UPB_SIZE(184, 344)) == 56; }
+UPB_INLINE const envoy_config_cluster_v3_Cluster_RoundRobinLbConfig* envoy_config_cluster_v3_Cluster_round_robin_lb_config(const envoy_config_cluster_v3_Cluster *msg) { return UPB_READ_ONEOF(msg, const envoy_config_cluster_v3_Cluster_RoundRobinLbConfig*, UPB_SIZE(180, 336), UPB_SIZE(184, 344), 56, NULL); }
 
 UPB_INLINE void envoy_config_cluster_v3_Cluster_set_name(envoy_config_cluster_v3_Cluster *msg, upb_strview value) {
   *UPB_PTR_AT(msg, UPB_SIZE(24, 24), upb_strview) = value;
@@ -886,6 +896,18 @@ UPB_INLINE struct envoy_config_core_v3_TypedExtensionConfig* envoy_config_cluste
   }
   return sub;
 }
+UPB_INLINE void envoy_config_cluster_v3_Cluster_set_round_robin_lb_config(envoy_config_cluster_v3_Cluster *msg, envoy_config_cluster_v3_Cluster_RoundRobinLbConfig* value) {
+  UPB_WRITE_ONEOF(msg, envoy_config_cluster_v3_Cluster_RoundRobinLbConfig*, UPB_SIZE(180, 336), value, UPB_SIZE(184, 344), 56);
+}
+UPB_INLINE struct envoy_config_cluster_v3_Cluster_RoundRobinLbConfig* envoy_config_cluster_v3_Cluster_mutable_round_robin_lb_config(envoy_config_cluster_v3_Cluster *msg, upb_arena *arena) {
+  struct envoy_config_cluster_v3_Cluster_RoundRobinLbConfig* sub = (struct envoy_config_cluster_v3_Cluster_RoundRobinLbConfig*)envoy_config_cluster_v3_Cluster_round_robin_lb_config(msg);
+  if (sub == NULL) {
+    sub = (struct envoy_config_cluster_v3_Cluster_RoundRobinLbConfig*)_upb_msg_new(&envoy_config_cluster_v3_Cluster_RoundRobinLbConfig_msginit, arena);
+    if (!sub) return NULL;
+    envoy_config_cluster_v3_Cluster_set_round_robin_lb_config(msg, sub);
+  }
+  return sub;
+}
 
 /* envoy.config.cluster.v3.Cluster.TransportSocketMatch */
 
@@ -1179,6 +1201,107 @@ UPB_INLINE void envoy_config_cluster_v3_Cluster_LbSubsetConfig_LbSubsetSelector_
   *UPB_PTR_AT(msg, UPB_SIZE(4, 4), bool) = value;
 }
 
+/* envoy.config.cluster.v3.Cluster.SlowStartConfig */
+
+UPB_INLINE envoy_config_cluster_v3_Cluster_SlowStartConfig *envoy_config_cluster_v3_Cluster_SlowStartConfig_new(upb_arena *arena) {
+  return (envoy_config_cluster_v3_Cluster_SlowStartConfig *)_upb_msg_new(&envoy_config_cluster_v3_Cluster_SlowStartConfig_msginit, arena);
+}
+UPB_INLINE envoy_config_cluster_v3_Cluster_SlowStartConfig *envoy_config_cluster_v3_Cluster_SlowStartConfig_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  envoy_config_cluster_v3_Cluster_SlowStartConfig *ret = envoy_config_cluster_v3_Cluster_SlowStartConfig_new(arena);
+  if (!ret) return NULL;
+  if (!upb_decode(buf, size, ret, &envoy_config_cluster_v3_Cluster_SlowStartConfig_msginit, arena)) return NULL;
+  return ret;
+}
+UPB_INLINE envoy_config_cluster_v3_Cluster_SlowStartConfig *envoy_config_cluster_v3_Cluster_SlowStartConfig_parse_ex(const char *buf, size_t size,
+                           const upb_extreg *extreg, int options,
+                           upb_arena *arena) {
+  envoy_config_cluster_v3_Cluster_SlowStartConfig *ret = envoy_config_cluster_v3_Cluster_SlowStartConfig_new(arena);
+  if (!ret) return NULL;
+  if (!_upb_decode(buf, size, ret, &envoy_config_cluster_v3_Cluster_SlowStartConfig_msginit, extreg, options, arena)) {
+    return NULL;
+  }
+  return ret;
+}
+UPB_INLINE char *envoy_config_cluster_v3_Cluster_SlowStartConfig_serialize(const envoy_config_cluster_v3_Cluster_SlowStartConfig *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &envoy_config_cluster_v3_Cluster_SlowStartConfig_msginit, arena, len);
+}
+
+UPB_INLINE bool envoy_config_cluster_v3_Cluster_SlowStartConfig_has_slow_start_window(const envoy_config_cluster_v3_Cluster_SlowStartConfig *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE const struct google_protobuf_Duration* envoy_config_cluster_v3_Cluster_SlowStartConfig_slow_start_window(const envoy_config_cluster_v3_Cluster_SlowStartConfig *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), const struct google_protobuf_Duration*); }
+UPB_INLINE bool envoy_config_cluster_v3_Cluster_SlowStartConfig_has_aggression(const envoy_config_cluster_v3_Cluster_SlowStartConfig *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE const struct envoy_config_core_v3_RuntimeDouble* envoy_config_cluster_v3_Cluster_SlowStartConfig_aggression(const envoy_config_cluster_v3_Cluster_SlowStartConfig *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 16), const struct envoy_config_core_v3_RuntimeDouble*); }
+
+UPB_INLINE void envoy_config_cluster_v3_Cluster_SlowStartConfig_set_slow_start_window(envoy_config_cluster_v3_Cluster_SlowStartConfig *msg, struct google_protobuf_Duration* value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), struct google_protobuf_Duration*) = value;
+}
+UPB_INLINE struct google_protobuf_Duration* envoy_config_cluster_v3_Cluster_SlowStartConfig_mutable_slow_start_window(envoy_config_cluster_v3_Cluster_SlowStartConfig *msg, upb_arena *arena) {
+  struct google_protobuf_Duration* sub = (struct google_protobuf_Duration*)envoy_config_cluster_v3_Cluster_SlowStartConfig_slow_start_window(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_Duration*)_upb_msg_new(&google_protobuf_Duration_msginit, arena);
+    if (!sub) return NULL;
+    envoy_config_cluster_v3_Cluster_SlowStartConfig_set_slow_start_window(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE void envoy_config_cluster_v3_Cluster_SlowStartConfig_set_aggression(envoy_config_cluster_v3_Cluster_SlowStartConfig *msg, struct envoy_config_core_v3_RuntimeDouble* value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(8, 16), struct envoy_config_core_v3_RuntimeDouble*) = value;
+}
+UPB_INLINE struct envoy_config_core_v3_RuntimeDouble* envoy_config_cluster_v3_Cluster_SlowStartConfig_mutable_aggression(envoy_config_cluster_v3_Cluster_SlowStartConfig *msg, upb_arena *arena) {
+  struct envoy_config_core_v3_RuntimeDouble* sub = (struct envoy_config_core_v3_RuntimeDouble*)envoy_config_cluster_v3_Cluster_SlowStartConfig_aggression(msg);
+  if (sub == NULL) {
+    sub = (struct envoy_config_core_v3_RuntimeDouble*)_upb_msg_new(&envoy_config_core_v3_RuntimeDouble_msginit, arena);
+    if (!sub) return NULL;
+    envoy_config_cluster_v3_Cluster_SlowStartConfig_set_aggression(msg, sub);
+  }
+  return sub;
+}
+
+/* envoy.config.cluster.v3.Cluster.RoundRobinLbConfig */
+
+UPB_INLINE envoy_config_cluster_v3_Cluster_RoundRobinLbConfig *envoy_config_cluster_v3_Cluster_RoundRobinLbConfig_new(upb_arena *arena) {
+  return (envoy_config_cluster_v3_Cluster_RoundRobinLbConfig *)_upb_msg_new(&envoy_config_cluster_v3_Cluster_RoundRobinLbConfig_msginit, arena);
+}
+UPB_INLINE envoy_config_cluster_v3_Cluster_RoundRobinLbConfig *envoy_config_cluster_v3_Cluster_RoundRobinLbConfig_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  envoy_config_cluster_v3_Cluster_RoundRobinLbConfig *ret = envoy_config_cluster_v3_Cluster_RoundRobinLbConfig_new(arena);
+  if (!ret) return NULL;
+  if (!upb_decode(buf, size, ret, &envoy_config_cluster_v3_Cluster_RoundRobinLbConfig_msginit, arena)) return NULL;
+  return ret;
+}
+UPB_INLINE envoy_config_cluster_v3_Cluster_RoundRobinLbConfig *envoy_config_cluster_v3_Cluster_RoundRobinLbConfig_parse_ex(const char *buf, size_t size,
+                           const upb_extreg *extreg, int options,
+                           upb_arena *arena) {
+  envoy_config_cluster_v3_Cluster_RoundRobinLbConfig *ret = envoy_config_cluster_v3_Cluster_RoundRobinLbConfig_new(arena);
+  if (!ret) return NULL;
+  if (!_upb_decode(buf, size, ret, &envoy_config_cluster_v3_Cluster_RoundRobinLbConfig_msginit, extreg, options, arena)) {
+    return NULL;
+  }
+  return ret;
+}
+UPB_INLINE char *envoy_config_cluster_v3_Cluster_RoundRobinLbConfig_serialize(const envoy_config_cluster_v3_Cluster_RoundRobinLbConfig *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &envoy_config_cluster_v3_Cluster_RoundRobinLbConfig_msginit, arena, len);
+}
+
+UPB_INLINE bool envoy_config_cluster_v3_Cluster_RoundRobinLbConfig_has_slow_start_config(const envoy_config_cluster_v3_Cluster_RoundRobinLbConfig *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE const envoy_config_cluster_v3_Cluster_SlowStartConfig* envoy_config_cluster_v3_Cluster_RoundRobinLbConfig_slow_start_config(const envoy_config_cluster_v3_Cluster_RoundRobinLbConfig *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), const envoy_config_cluster_v3_Cluster_SlowStartConfig*); }
+
+UPB_INLINE void envoy_config_cluster_v3_Cluster_RoundRobinLbConfig_set_slow_start_config(envoy_config_cluster_v3_Cluster_RoundRobinLbConfig *msg, envoy_config_cluster_v3_Cluster_SlowStartConfig* value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), envoy_config_cluster_v3_Cluster_SlowStartConfig*) = value;
+}
+UPB_INLINE struct envoy_config_cluster_v3_Cluster_SlowStartConfig* envoy_config_cluster_v3_Cluster_RoundRobinLbConfig_mutable_slow_start_config(envoy_config_cluster_v3_Cluster_RoundRobinLbConfig *msg, upb_arena *arena) {
+  struct envoy_config_cluster_v3_Cluster_SlowStartConfig* sub = (struct envoy_config_cluster_v3_Cluster_SlowStartConfig*)envoy_config_cluster_v3_Cluster_RoundRobinLbConfig_slow_start_config(msg);
+  if (sub == NULL) {
+    sub = (struct envoy_config_cluster_v3_Cluster_SlowStartConfig*)_upb_msg_new(&envoy_config_cluster_v3_Cluster_SlowStartConfig_msginit, arena);
+    if (!sub) return NULL;
+    envoy_config_cluster_v3_Cluster_RoundRobinLbConfig_set_slow_start_config(msg, sub);
+  }
+  return sub;
+}
+
 /* envoy.config.cluster.v3.Cluster.LeastRequestLbConfig */
 
 UPB_INLINE envoy_config_cluster_v3_Cluster_LeastRequestLbConfig *envoy_config_cluster_v3_Cluster_LeastRequestLbConfig_new(upb_arena *arena) {
@@ -1209,6 +1332,8 @@ UPB_INLINE bool envoy_config_cluster_v3_Cluster_LeastRequestLbConfig_has_choice_
 UPB_INLINE const struct google_protobuf_UInt32Value* envoy_config_cluster_v3_Cluster_LeastRequestLbConfig_choice_count(const envoy_config_cluster_v3_Cluster_LeastRequestLbConfig *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), const struct google_protobuf_UInt32Value*); }
 UPB_INLINE bool envoy_config_cluster_v3_Cluster_LeastRequestLbConfig_has_active_request_bias(const envoy_config_cluster_v3_Cluster_LeastRequestLbConfig *msg) { return _upb_hasbit(msg, 2); }
 UPB_INLINE const struct envoy_config_core_v3_RuntimeDouble* envoy_config_cluster_v3_Cluster_LeastRequestLbConfig_active_request_bias(const envoy_config_cluster_v3_Cluster_LeastRequestLbConfig *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 16), const struct envoy_config_core_v3_RuntimeDouble*); }
+UPB_INLINE bool envoy_config_cluster_v3_Cluster_LeastRequestLbConfig_has_slow_start_config(const envoy_config_cluster_v3_Cluster_LeastRequestLbConfig *msg) { return _upb_hasbit(msg, 3); }
+UPB_INLINE const envoy_config_cluster_v3_Cluster_SlowStartConfig* envoy_config_cluster_v3_Cluster_LeastRequestLbConfig_slow_start_config(const envoy_config_cluster_v3_Cluster_LeastRequestLbConfig *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const envoy_config_cluster_v3_Cluster_SlowStartConfig*); }
 
 UPB_INLINE void envoy_config_cluster_v3_Cluster_LeastRequestLbConfig_set_choice_count(envoy_config_cluster_v3_Cluster_LeastRequestLbConfig *msg, struct google_protobuf_UInt32Value* value) {
   _upb_sethas(msg, 1);
@@ -1236,6 +1361,19 @@ UPB_INLINE struct envoy_config_core_v3_RuntimeDouble* envoy_config_cluster_v3_Cl
   }
   return sub;
 }
+UPB_INLINE void envoy_config_cluster_v3_Cluster_LeastRequestLbConfig_set_slow_start_config(envoy_config_cluster_v3_Cluster_LeastRequestLbConfig *msg, envoy_config_cluster_v3_Cluster_SlowStartConfig* value) {
+  _upb_sethas(msg, 3);
+  *UPB_PTR_AT(msg, UPB_SIZE(12, 24), envoy_config_cluster_v3_Cluster_SlowStartConfig*) = value;
+}
+UPB_INLINE struct envoy_config_cluster_v3_Cluster_SlowStartConfig* envoy_config_cluster_v3_Cluster_LeastRequestLbConfig_mutable_slow_start_config(envoy_config_cluster_v3_Cluster_LeastRequestLbConfig *msg, upb_arena *arena) {
+  struct envoy_config_cluster_v3_Cluster_SlowStartConfig* sub = (struct envoy_config_cluster_v3_Cluster_SlowStartConfig*)envoy_config_cluster_v3_Cluster_LeastRequestLbConfig_slow_start_config(msg);
+  if (sub == NULL) {
+    sub = (struct envoy_config_cluster_v3_Cluster_SlowStartConfig*)_upb_msg_new(&envoy_config_cluster_v3_Cluster_SlowStartConfig_msginit, arena);
+    if (!sub) return NULL;
+    envoy_config_cluster_v3_Cluster_LeastRequestLbConfig_set_slow_start_config(msg, sub);
+  }
+  return sub;
+}
 
 /* envoy.config.cluster.v3.Cluster.RingHashLbConfig */
 
index cfb9327..d02898e 100644 (file)
@@ -214,6 +214,17 @@ const upb_msglayout envoy_config_core_v3_RuntimeFeatureFlag_msginit = {
   UPB_SIZE(16, 32), 2, false, 2, 255,
 };
 
+static const upb_msglayout_field envoy_config_core_v3_QueryParameter__fields[2] = {
+  {1, UPB_SIZE(0, 0), 0, 0, 9, _UPB_MODE_SCALAR},
+  {2, UPB_SIZE(8, 16), 0, 0, 9, _UPB_MODE_SCALAR},
+};
+
+const upb_msglayout envoy_config_core_v3_QueryParameter_msginit = {
+  NULL,
+  &envoy_config_core_v3_QueryParameter__fields[0],
+  UPB_SIZE(16, 32), 2, false, 2, 255,
+};
+
 static const upb_msglayout_field envoy_config_core_v3_HeaderValue__fields[2] = {
   {1, UPB_SIZE(0, 0), 0, 0, 9, _UPB_MODE_SCALAR},
   {2, UPB_SIZE(8, 16), 0, 0, 9, _UPB_MODE_SCALAR},
@@ -230,15 +241,16 @@ static const upb_msglayout *const envoy_config_core_v3_HeaderValueOption_submsgs
   &google_protobuf_BoolValue_msginit,
 };
 
-static const upb_msglayout_field envoy_config_core_v3_HeaderValueOption__fields[2] = {
-  {1, UPB_SIZE(4, 8), 1, 0, 11, _UPB_MODE_SCALAR},
-  {2, UPB_SIZE(8, 16), 2, 1, 11, _UPB_MODE_SCALAR},
+static const upb_msglayout_field envoy_config_core_v3_HeaderValueOption__fields[3] = {
+  {1, UPB_SIZE(8, 8), 1, 0, 11, _UPB_MODE_SCALAR},
+  {2, UPB_SIZE(12, 16), 2, 1, 11, _UPB_MODE_SCALAR},
+  {3, UPB_SIZE(4, 4), 0, 0, 14, _UPB_MODE_SCALAR},
 };
 
 const upb_msglayout envoy_config_core_v3_HeaderValueOption_msginit = {
   &envoy_config_core_v3_HeaderValueOption_submsgs[0],
   &envoy_config_core_v3_HeaderValueOption__fields[0],
-  UPB_SIZE(16, 24), 2, false, 2, 255,
+  UPB_SIZE(16, 24), 3, false, 3, 255,
 };
 
 static const upb_msglayout *const envoy_config_core_v3_HeaderMap_submsgs[1] = {
index 8d36c96..d4a4732 100644 (file)
@@ -32,6 +32,7 @@ struct envoy_config_core_v3_RuntimeUInt32;
 struct envoy_config_core_v3_RuntimePercent;
 struct envoy_config_core_v3_RuntimeDouble;
 struct envoy_config_core_v3_RuntimeFeatureFlag;
+struct envoy_config_core_v3_QueryParameter;
 struct envoy_config_core_v3_HeaderValue;
 struct envoy_config_core_v3_HeaderValueOption;
 struct envoy_config_core_v3_HeaderMap;
@@ -55,6 +56,7 @@ typedef struct envoy_config_core_v3_RuntimeUInt32 envoy_config_core_v3_RuntimeUI
 typedef struct envoy_config_core_v3_RuntimePercent envoy_config_core_v3_RuntimePercent;
 typedef struct envoy_config_core_v3_RuntimeDouble envoy_config_core_v3_RuntimeDouble;
 typedef struct envoy_config_core_v3_RuntimeFeatureFlag envoy_config_core_v3_RuntimeFeatureFlag;
+typedef struct envoy_config_core_v3_QueryParameter envoy_config_core_v3_QueryParameter;
 typedef struct envoy_config_core_v3_HeaderValue envoy_config_core_v3_HeaderValue;
 typedef struct envoy_config_core_v3_HeaderValueOption envoy_config_core_v3_HeaderValueOption;
 typedef struct envoy_config_core_v3_HeaderMap envoy_config_core_v3_HeaderMap;
@@ -78,6 +80,7 @@ extern const upb_msglayout envoy_config_core_v3_RuntimeUInt32_msginit;
 extern const upb_msglayout envoy_config_core_v3_RuntimePercent_msginit;
 extern const upb_msglayout envoy_config_core_v3_RuntimeDouble_msginit;
 extern const upb_msglayout envoy_config_core_v3_RuntimeFeatureFlag_msginit;
+extern const upb_msglayout envoy_config_core_v3_QueryParameter_msginit;
 extern const upb_msglayout envoy_config_core_v3_HeaderValue_msginit;
 extern const upb_msglayout envoy_config_core_v3_HeaderValueOption_msginit;
 extern const upb_msglayout envoy_config_core_v3_HeaderMap_msginit;
@@ -113,6 +116,12 @@ extern const upb_msglayout google_protobuf_UInt32Value_msginit;
 extern const upb_msglayout xds_core_v3_ContextParams_msginit;
 
 typedef enum {
+  envoy_config_core_v3_HeaderValueOption_APPEND_IF_EXISTS_OR_ADD = 0,
+  envoy_config_core_v3_HeaderValueOption_ADD_IF_ABSENT = 1,
+  envoy_config_core_v3_HeaderValueOption_OVERWRITE_IF_EXISTS_OR_ADD = 2
+} envoy_config_core_v3_HeaderValueOption_HeaderAppendAction;
+
+typedef enum {
   envoy_config_core_v3_METHOD_UNSPECIFIED = 0,
   envoy_config_core_v3_GET = 1,
   envoy_config_core_v3_HEAD = 2,
@@ -703,6 +712,42 @@ UPB_INLINE void envoy_config_core_v3_RuntimeFeatureFlag_set_runtime_key(envoy_co
   *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
 }
 
+/* envoy.config.core.v3.QueryParameter */
+
+UPB_INLINE envoy_config_core_v3_QueryParameter *envoy_config_core_v3_QueryParameter_new(upb_arena *arena) {
+  return (envoy_config_core_v3_QueryParameter *)_upb_msg_new(&envoy_config_core_v3_QueryParameter_msginit, arena);
+}
+UPB_INLINE envoy_config_core_v3_QueryParameter *envoy_config_core_v3_QueryParameter_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  envoy_config_core_v3_QueryParameter *ret = envoy_config_core_v3_QueryParameter_new(arena);
+  if (!ret) return NULL;
+  if (!upb_decode(buf, size, ret, &envoy_config_core_v3_QueryParameter_msginit, arena)) return NULL;
+  return ret;
+}
+UPB_INLINE envoy_config_core_v3_QueryParameter *envoy_config_core_v3_QueryParameter_parse_ex(const char *buf, size_t size,
+                           const upb_extreg *extreg, int options,
+                           upb_arena *arena) {
+  envoy_config_core_v3_QueryParameter *ret = envoy_config_core_v3_QueryParameter_new(arena);
+  if (!ret) return NULL;
+  if (!_upb_decode(buf, size, ret, &envoy_config_core_v3_QueryParameter_msginit, extreg, options, arena)) {
+    return NULL;
+  }
+  return ret;
+}
+UPB_INLINE char *envoy_config_core_v3_QueryParameter_serialize(const envoy_config_core_v3_QueryParameter *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &envoy_config_core_v3_QueryParameter_msginit, arena, len);
+}
+
+UPB_INLINE upb_strview envoy_config_core_v3_QueryParameter_key(const envoy_config_core_v3_QueryParameter *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(0, 0), upb_strview); }
+UPB_INLINE upb_strview envoy_config_core_v3_QueryParameter_value(const envoy_config_core_v3_QueryParameter *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 16), upb_strview); }
+
+UPB_INLINE void envoy_config_core_v3_QueryParameter_set_key(envoy_config_core_v3_QueryParameter *msg, upb_strview value) {
+  *UPB_PTR_AT(msg, UPB_SIZE(0, 0), upb_strview) = value;
+}
+UPB_INLINE void envoy_config_core_v3_QueryParameter_set_value(envoy_config_core_v3_QueryParameter *msg, upb_strview value) {
+  *UPB_PTR_AT(msg, UPB_SIZE(8, 16), upb_strview) = value;
+}
+
 /* envoy.config.core.v3.HeaderValue */
 
 UPB_INLINE envoy_config_core_v3_HeaderValue *envoy_config_core_v3_HeaderValue_new(upb_arena *arena) {
@@ -766,13 +811,14 @@ UPB_INLINE char *envoy_config_core_v3_HeaderValueOption_serialize(const envoy_co
 }
 
 UPB_INLINE bool envoy_config_core_v3_HeaderValueOption_has_header(const envoy_config_core_v3_HeaderValueOption *msg) { return _upb_hasbit(msg, 1); }
-UPB_INLINE const envoy_config_core_v3_HeaderValue* envoy_config_core_v3_HeaderValueOption_header(const envoy_config_core_v3_HeaderValueOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), const envoy_config_core_v3_HeaderValue*); }
+UPB_INLINE const envoy_config_core_v3_HeaderValue* envoy_config_core_v3_HeaderValueOption_header(const envoy_config_core_v3_HeaderValueOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), const envoy_config_core_v3_HeaderValue*); }
 UPB_INLINE bool envoy_config_core_v3_HeaderValueOption_has_append(const envoy_config_core_v3_HeaderValueOption *msg) { return _upb_hasbit(msg, 2); }
-UPB_INLINE const struct google_protobuf_BoolValue* envoy_config_core_v3_HeaderValueOption_append(const envoy_config_core_v3_HeaderValueOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 16), const struct google_protobuf_BoolValue*); }
+UPB_INLINE const struct google_protobuf_BoolValue* envoy_config_core_v3_HeaderValueOption_append(const envoy_config_core_v3_HeaderValueOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 16), const struct google_protobuf_BoolValue*); }
+UPB_INLINE int32_t envoy_config_core_v3_HeaderValueOption_append_action(const envoy_config_core_v3_HeaderValueOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); }
 
 UPB_INLINE void envoy_config_core_v3_HeaderValueOption_set_header(envoy_config_core_v3_HeaderValueOption *msg, envoy_config_core_v3_HeaderValue* value) {
   _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), envoy_config_core_v3_HeaderValue*) = value;
+  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), envoy_config_core_v3_HeaderValue*) = value;
 }
 UPB_INLINE struct envoy_config_core_v3_HeaderValue* envoy_config_core_v3_HeaderValueOption_mutable_header(envoy_config_core_v3_HeaderValueOption *msg, upb_arena *arena) {
   struct envoy_config_core_v3_HeaderValue* sub = (struct envoy_config_core_v3_HeaderValue*)envoy_config_core_v3_HeaderValueOption_header(msg);
@@ -785,7 +831,7 @@ UPB_INLINE struct envoy_config_core_v3_HeaderValue* envoy_config_core_v3_HeaderV
 }
 UPB_INLINE void envoy_config_core_v3_HeaderValueOption_set_append(envoy_config_core_v3_HeaderValueOption *msg, struct google_protobuf_BoolValue* value) {
   _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(8, 16), struct google_protobuf_BoolValue*) = value;
+  *UPB_PTR_AT(msg, UPB_SIZE(12, 16), struct google_protobuf_BoolValue*) = value;
 }
 UPB_INLINE struct google_protobuf_BoolValue* envoy_config_core_v3_HeaderValueOption_mutable_append(envoy_config_core_v3_HeaderValueOption *msg, upb_arena *arena) {
   struct google_protobuf_BoolValue* sub = (struct google_protobuf_BoolValue*)envoy_config_core_v3_HeaderValueOption_append(msg);
@@ -796,6 +842,9 @@ UPB_INLINE struct google_protobuf_BoolValue* envoy_config_core_v3_HeaderValueOpt
   }
   return sub;
 }
+UPB_INLINE void envoy_config_core_v3_HeaderValueOption_set_append_action(envoy_config_core_v3_HeaderValueOption *msg, int32_t value) {
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
+}
 
 /* envoy.config.core.v3.HeaderMap */
 
index a1cb228..5168f6e 100644 (file)
@@ -87,7 +87,7 @@ static const upb_msglayout *const envoy_config_core_v3_HealthCheck_HttpHealthChe
   &envoy_type_v3_Int64Range_msginit,
 };
 
-static const upb_msglayout_field envoy_config_core_v3_HealthCheck_HttpHealthCheck__fields[9] = {
+static const upb_msglayout_field envoy_config_core_v3_HealthCheck_HttpHealthCheck__fields[10] = {
   {1, UPB_SIZE(8, 8), 0, 0, 9, _UPB_MODE_SCALAR},
   {2, UPB_SIZE(16, 24), 0, 0, 9, _UPB_MODE_SCALAR},
   {3, UPB_SIZE(24, 40), 1, 1, 11, _UPB_MODE_SCALAR},
@@ -97,12 +97,13 @@ static const upb_msglayout_field envoy_config_core_v3_HealthCheck_HttpHealthChec
   {9, UPB_SIZE(44, 80), 0, 3, 11, _UPB_MODE_ARRAY},
   {10, UPB_SIZE(4, 4), 0, 0, 14, _UPB_MODE_SCALAR},
   {11, UPB_SIZE(32, 56), 3, 2, 11, _UPB_MODE_SCALAR},
+  {12, UPB_SIZE(48, 88), 0, 3, 11, _UPB_MODE_ARRAY},
 };
 
 const upb_msglayout envoy_config_core_v3_HealthCheck_HttpHealthCheck_msginit = {
   &envoy_config_core_v3_HealthCheck_HttpHealthCheck_submsgs[0],
   &envoy_config_core_v3_HealthCheck_HttpHealthCheck__fields[0],
-  UPB_SIZE(48, 96), 9, false, 4, 255,
+  UPB_SIZE(56, 96), 10, false, 4, 255,
 };
 
 static const upb_msglayout *const envoy_config_core_v3_HealthCheck_TcpHealthCheck_submsgs[1] = {
index cc8b0f0..98d388a 100644 (file)
@@ -503,6 +503,8 @@ UPB_INLINE const struct envoy_type_v3_Int64Range* const* envoy_config_core_v3_He
 UPB_INLINE int32_t envoy_config_core_v3_HealthCheck_HttpHealthCheck_codec_client_type(const envoy_config_core_v3_HealthCheck_HttpHealthCheck *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); }
 UPB_INLINE bool envoy_config_core_v3_HealthCheck_HttpHealthCheck_has_service_name_matcher(const envoy_config_core_v3_HealthCheck_HttpHealthCheck *msg) { return _upb_hasbit(msg, 3); }
 UPB_INLINE const struct envoy_type_matcher_v3_StringMatcher* envoy_config_core_v3_HealthCheck_HttpHealthCheck_service_name_matcher(const envoy_config_core_v3_HealthCheck_HttpHealthCheck *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(32, 56), const struct envoy_type_matcher_v3_StringMatcher*); }
+UPB_INLINE bool envoy_config_core_v3_HealthCheck_HttpHealthCheck_has_retriable_statuses(const envoy_config_core_v3_HealthCheck_HttpHealthCheck *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(48, 88)); }
+UPB_INLINE const struct envoy_type_v3_Int64Range* const* envoy_config_core_v3_HealthCheck_HttpHealthCheck_retriable_statuses(const envoy_config_core_v3_HealthCheck_HttpHealthCheck *msg, size_t *len) { return (const struct envoy_type_v3_Int64Range* const*)_upb_array_accessor(msg, UPB_SIZE(48, 88), len); }
 
 UPB_INLINE void envoy_config_core_v3_HealthCheck_HttpHealthCheck_set_host(envoy_config_core_v3_HealthCheck_HttpHealthCheck *msg, upb_strview value) {
   *UPB_PTR_AT(msg, UPB_SIZE(8, 8), upb_strview) = value;
@@ -588,6 +590,19 @@ UPB_INLINE struct envoy_type_matcher_v3_StringMatcher* envoy_config_core_v3_Heal
   }
   return sub;
 }
+UPB_INLINE struct envoy_type_v3_Int64Range** envoy_config_core_v3_HealthCheck_HttpHealthCheck_mutable_retriable_statuses(envoy_config_core_v3_HealthCheck_HttpHealthCheck *msg, size_t *len) {
+  return (struct envoy_type_v3_Int64Range**)_upb_array_mutable_accessor(msg, UPB_SIZE(48, 88), len);
+}
+UPB_INLINE struct envoy_type_v3_Int64Range** envoy_config_core_v3_HealthCheck_HttpHealthCheck_resize_retriable_statuses(envoy_config_core_v3_HealthCheck_HttpHealthCheck *msg, size_t len, upb_arena *arena) {
+  return (struct envoy_type_v3_Int64Range**)_upb_array_resize_accessor2(msg, UPB_SIZE(48, 88), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct envoy_type_v3_Int64Range* envoy_config_core_v3_HealthCheck_HttpHealthCheck_add_retriable_statuses(envoy_config_core_v3_HealthCheck_HttpHealthCheck *msg, upb_arena *arena) {
+  struct envoy_type_v3_Int64Range* sub = (struct envoy_type_v3_Int64Range*)_upb_msg_new(&envoy_type_v3_Int64Range_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(48, 88), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
 
 /* envoy.config.core.v3.HealthCheck.TcpHealthCheck */
 
index b1f1cd0..6e1ea0f 100644 (file)
@@ -13,6 +13,7 @@
 #include "envoy/type/v3/percent.upb.h"
 #include "google/protobuf/duration.upb.h"
 #include "google/protobuf/wrappers.upb.h"
+#include "xds/annotations/v3/status.upb.h"
 #include "envoy/annotations/deprecation.upb.h"
 #include "udpa/annotations/status.upb.h"
 #include "udpa/annotations/versioning.upb.h"
@@ -42,30 +43,33 @@ const upb_msglayout envoy_config_core_v3_QuicProtocolOptions_msginit = {
   UPB_SIZE(16, 32), 3, false, 3, 255,
 };
 
-static const upb_msglayout_field envoy_config_core_v3_UpstreamHttpProtocolOptions__fields[2] = {
+static const upb_msglayout_field envoy_config_core_v3_UpstreamHttpProtocolOptions__fields[3] = {
   {1, UPB_SIZE(0, 0), 0, 0, 8, _UPB_MODE_SCALAR},
   {2, UPB_SIZE(1, 1), 0, 0, 8, _UPB_MODE_SCALAR},
+  {3, UPB_SIZE(4, 8), 0, 0, 9, _UPB_MODE_SCALAR},
 };
 
 const upb_msglayout envoy_config_core_v3_UpstreamHttpProtocolOptions_msginit = {
   NULL,
   &envoy_config_core_v3_UpstreamHttpProtocolOptions__fields[0],
-  UPB_SIZE(8, 8), 2, false, 2, 255,
+  UPB_SIZE(16, 32), 3, false, 3, 255,
 };
 
-static const upb_msglayout *const envoy_config_core_v3_AlternateProtocolsCacheOptions_submsgs[1] = {
+static const upb_msglayout *const envoy_config_core_v3_AlternateProtocolsCacheOptions_submsgs[2] = {
+  &envoy_config_core_v3_TypedExtensionConfig_msginit,
   &google_protobuf_UInt32Value_msginit,
 };
 
-static const upb_msglayout_field envoy_config_core_v3_AlternateProtocolsCacheOptions__fields[2] = {
+static const upb_msglayout_field envoy_config_core_v3_AlternateProtocolsCacheOptions__fields[3] = {
   {1, UPB_SIZE(4, 8), 0, 0, 9, _UPB_MODE_SCALAR},
-  {2, UPB_SIZE(12, 24), 1, 0, 11, _UPB_MODE_SCALAR},
+  {2, UPB_SIZE(12, 24), 1, 1, 11, _UPB_MODE_SCALAR},
+  {3, UPB_SIZE(16, 32), 2, 0, 11, _UPB_MODE_SCALAR},
 };
 
 const upb_msglayout envoy_config_core_v3_AlternateProtocolsCacheOptions_msginit = {
   &envoy_config_core_v3_AlternateProtocolsCacheOptions_submsgs[0],
   &envoy_config_core_v3_AlternateProtocolsCacheOptions__fields[0],
-  UPB_SIZE(16, 32), 2, false, 2, 255,
+  UPB_SIZE(24, 48), 3, false, 3, 255,
 };
 
 static const upb_msglayout *const envoy_config_core_v3_HttpProtocolOptions_submsgs[2] = {
@@ -214,15 +218,16 @@ static const upb_msglayout *const envoy_config_core_v3_Http3ProtocolOptions_subm
   &google_protobuf_BoolValue_msginit,
 };
 
-static const upb_msglayout_field envoy_config_core_v3_Http3ProtocolOptions__fields[2] = {
+static const upb_msglayout_field envoy_config_core_v3_Http3ProtocolOptions__fields[3] = {
   {1, UPB_SIZE(4, 8), 1, 0, 11, _UPB_MODE_SCALAR},
   {2, UPB_SIZE(8, 16), 2, 1, 11, _UPB_MODE_SCALAR},
+  {5, UPB_SIZE(1, 1), 0, 0, 8, _UPB_MODE_SCALAR},
 };
 
 const upb_msglayout envoy_config_core_v3_Http3ProtocolOptions_msginit = {
   &envoy_config_core_v3_Http3ProtocolOptions_submsgs[0],
   &envoy_config_core_v3_Http3ProtocolOptions__fields[0],
-  UPB_SIZE(16, 24), 2, false, 2, 255,
+  UPB_SIZE(16, 24), 3, false, 2, 255,
 };
 
 static const upb_msglayout_field envoy_config_core_v3_SchemeHeaderTransformation__fields[1] = {
index 891459b..9618218 100644 (file)
@@ -209,6 +209,7 @@ UPB_INLINE char *envoy_config_core_v3_UpstreamHttpProtocolOptions_serialize(cons
 
 UPB_INLINE bool envoy_config_core_v3_UpstreamHttpProtocolOptions_auto_sni(const envoy_config_core_v3_UpstreamHttpProtocolOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(0, 0), bool); }
 UPB_INLINE bool envoy_config_core_v3_UpstreamHttpProtocolOptions_auto_san_validation(const envoy_config_core_v3_UpstreamHttpProtocolOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); }
+UPB_INLINE upb_strview envoy_config_core_v3_UpstreamHttpProtocolOptions_override_auto_sni_header(const envoy_config_core_v3_UpstreamHttpProtocolOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
 
 UPB_INLINE void envoy_config_core_v3_UpstreamHttpProtocolOptions_set_auto_sni(envoy_config_core_v3_UpstreamHttpProtocolOptions *msg, bool value) {
   *UPB_PTR_AT(msg, UPB_SIZE(0, 0), bool) = value;
@@ -216,6 +217,9 @@ UPB_INLINE void envoy_config_core_v3_UpstreamHttpProtocolOptions_set_auto_sni(en
 UPB_INLINE void envoy_config_core_v3_UpstreamHttpProtocolOptions_set_auto_san_validation(envoy_config_core_v3_UpstreamHttpProtocolOptions *msg, bool value) {
   *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value;
 }
+UPB_INLINE void envoy_config_core_v3_UpstreamHttpProtocolOptions_set_override_auto_sni_header(envoy_config_core_v3_UpstreamHttpProtocolOptions *msg, upb_strview value) {
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
+}
 
 /* envoy.config.core.v3.AlternateProtocolsCacheOptions */
 
@@ -246,6 +250,8 @@ UPB_INLINE char *envoy_config_core_v3_AlternateProtocolsCacheOptions_serialize(c
 UPB_INLINE upb_strview envoy_config_core_v3_AlternateProtocolsCacheOptions_name(const envoy_config_core_v3_AlternateProtocolsCacheOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
 UPB_INLINE bool envoy_config_core_v3_AlternateProtocolsCacheOptions_has_max_entries(const envoy_config_core_v3_AlternateProtocolsCacheOptions *msg) { return _upb_hasbit(msg, 1); }
 UPB_INLINE const struct google_protobuf_UInt32Value* envoy_config_core_v3_AlternateProtocolsCacheOptions_max_entries(const envoy_config_core_v3_AlternateProtocolsCacheOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const struct google_protobuf_UInt32Value*); }
+UPB_INLINE bool envoy_config_core_v3_AlternateProtocolsCacheOptions_has_key_value_store_config(const envoy_config_core_v3_AlternateProtocolsCacheOptions *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE const struct envoy_config_core_v3_TypedExtensionConfig* envoy_config_core_v3_AlternateProtocolsCacheOptions_key_value_store_config(const envoy_config_core_v3_AlternateProtocolsCacheOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 32), const struct envoy_config_core_v3_TypedExtensionConfig*); }
 
 UPB_INLINE void envoy_config_core_v3_AlternateProtocolsCacheOptions_set_name(envoy_config_core_v3_AlternateProtocolsCacheOptions *msg, upb_strview value) {
   *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
@@ -263,6 +269,19 @@ UPB_INLINE struct google_protobuf_UInt32Value* envoy_config_core_v3_AlternatePro
   }
   return sub;
 }
+UPB_INLINE void envoy_config_core_v3_AlternateProtocolsCacheOptions_set_key_value_store_config(envoy_config_core_v3_AlternateProtocolsCacheOptions *msg, struct envoy_config_core_v3_TypedExtensionConfig* value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(16, 32), struct envoy_config_core_v3_TypedExtensionConfig*) = value;
+}
+UPB_INLINE struct envoy_config_core_v3_TypedExtensionConfig* envoy_config_core_v3_AlternateProtocolsCacheOptions_mutable_key_value_store_config(envoy_config_core_v3_AlternateProtocolsCacheOptions *msg, upb_arena *arena) {
+  struct envoy_config_core_v3_TypedExtensionConfig* sub = (struct envoy_config_core_v3_TypedExtensionConfig*)envoy_config_core_v3_AlternateProtocolsCacheOptions_key_value_store_config(msg);
+  if (sub == NULL) {
+    sub = (struct envoy_config_core_v3_TypedExtensionConfig*)_upb_msg_new(&envoy_config_core_v3_TypedExtensionConfig_msginit, arena);
+    if (!sub) return NULL;
+    envoy_config_core_v3_AlternateProtocolsCacheOptions_set_key_value_store_config(msg, sub);
+  }
+  return sub;
+}
 
 /* envoy.config.core.v3.HttpProtocolOptions */
 
@@ -990,6 +1009,7 @@ UPB_INLINE bool envoy_config_core_v3_Http3ProtocolOptions_has_quic_protocol_opti
 UPB_INLINE const envoy_config_core_v3_QuicProtocolOptions* envoy_config_core_v3_Http3ProtocolOptions_quic_protocol_options(const envoy_config_core_v3_Http3ProtocolOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), const envoy_config_core_v3_QuicProtocolOptions*); }
 UPB_INLINE bool envoy_config_core_v3_Http3ProtocolOptions_has_override_stream_error_on_invalid_http_message(const envoy_config_core_v3_Http3ProtocolOptions *msg) { return _upb_hasbit(msg, 2); }
 UPB_INLINE const struct google_protobuf_BoolValue* envoy_config_core_v3_Http3ProtocolOptions_override_stream_error_on_invalid_http_message(const envoy_config_core_v3_Http3ProtocolOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 16), const struct google_protobuf_BoolValue*); }
+UPB_INLINE bool envoy_config_core_v3_Http3ProtocolOptions_allow_extended_connect(const envoy_config_core_v3_Http3ProtocolOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); }
 
 UPB_INLINE void envoy_config_core_v3_Http3ProtocolOptions_set_quic_protocol_options(envoy_config_core_v3_Http3ProtocolOptions *msg, envoy_config_core_v3_QuicProtocolOptions* value) {
   _upb_sethas(msg, 1);
@@ -1017,6 +1037,9 @@ UPB_INLINE struct google_protobuf_BoolValue* envoy_config_core_v3_Http3ProtocolO
   }
   return sub;
 }
+UPB_INLINE void envoy_config_core_v3_Http3ProtocolOptions_set_allow_extended_connect(envoy_config_core_v3_Http3ProtocolOptions *msg, bool value) {
+  *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value;
+}
 
 /* envoy.config.core.v3.SchemeHeaderTransformation */
 
index 20642ea..3ab03ec 100644 (file)
@@ -14,7 +14,6 @@
 #include "envoy/config/core/v3/config_source.upb.h"
 #include "envoy/config/core/v3/health_check.upb.h"
 #include "google/protobuf/wrappers.upb.h"
-#include "udpa/annotations/migrate.upb.h"
 #include "udpa/annotations/status.upb.h"
 #include "udpa/annotations/versioning.upb.h"
 #include "validate/validate.upb.h"
index d92b08e..5284885 100644 (file)
@@ -10,6 +10,7 @@
 #include "upb/msg_internal.h"
 #include "envoy/config/rbac/v3/rbac.upb.h"
 #include "envoy/config/core/v3/address.upb.h"
+#include "envoy/config/core/v3/extension.upb.h"
 #include "envoy/config/route/v3/route_components.upb.h"
 #include "envoy/type/matcher/v3/metadata.upb.h"
 #include "envoy/type/matcher/v3/path.upb.h"
@@ -75,8 +76,9 @@ const upb_msglayout envoy_config_rbac_v3_Policy_msginit = {
   UPB_SIZE(24, 40), 4, false, 4, 255,
 };
 
-static const upb_msglayout *const envoy_config_rbac_v3_Permission_submsgs[8] = {
+static const upb_msglayout *const envoy_config_rbac_v3_Permission_submsgs[9] = {
   &envoy_config_core_v3_CidrRange_msginit,
+  &envoy_config_core_v3_TypedExtensionConfig_msginit,
   &envoy_config_rbac_v3_Permission_msginit,
   &envoy_config_rbac_v3_Permission_Set_msginit,
   &envoy_config_route_v3_HeaderMatcher_msginit,
@@ -86,24 +88,25 @@ static const upb_msglayout *const envoy_config_rbac_v3_Permission_submsgs[8] = {
   &envoy_type_v3_Int32Range_msginit,
 };
 
-static const upb_msglayout_field envoy_config_rbac_v3_Permission__fields[11] = {
-  {1, UPB_SIZE(0, 0), UPB_SIZE(-5, -9), 2, 11, _UPB_MODE_SCALAR},
-  {2, UPB_SIZE(0, 0), UPB_SIZE(-5, -9), 2, 11, _UPB_MODE_SCALAR},
+static const upb_msglayout_field envoy_config_rbac_v3_Permission__fields[12] = {
+  {1, UPB_SIZE(0, 0), UPB_SIZE(-5, -9), 3, 11, _UPB_MODE_SCALAR},
+  {2, UPB_SIZE(0, 0), UPB_SIZE(-5, -9), 3, 11, _UPB_MODE_SCALAR},
   {3, UPB_SIZE(0, 0), UPB_SIZE(-5, -9), 0, 8, _UPB_MODE_SCALAR},
-  {4, UPB_SIZE(0, 0), UPB_SIZE(-5, -9), 3, 11, _UPB_MODE_SCALAR},
+  {4, UPB_SIZE(0, 0), UPB_SIZE(-5, -9), 4, 11, _UPB_MODE_SCALAR},
   {5, UPB_SIZE(0, 0), UPB_SIZE(-5, -9), 0, 11, _UPB_MODE_SCALAR},
   {6, UPB_SIZE(0, 0), UPB_SIZE(-5, -9), 0, 13, _UPB_MODE_SCALAR},
-  {7, UPB_SIZE(0, 0), UPB_SIZE(-5, -9), 4, 11, _UPB_MODE_SCALAR},
-  {8, UPB_SIZE(0, 0), UPB_SIZE(-5, -9), 1, 11, _UPB_MODE_SCALAR},
-  {9, UPB_SIZE(0, 0), UPB_SIZE(-5, -9), 6, 11, _UPB_MODE_SCALAR},
-  {10, UPB_SIZE(0, 0), UPB_SIZE(-5, -9), 5, 11, _UPB_MODE_SCALAR},
-  {11, UPB_SIZE(0, 0), UPB_SIZE(-5, -9), 7, 11, _UPB_MODE_SCALAR},
+  {7, UPB_SIZE(0, 0), UPB_SIZE(-5, -9), 5, 11, _UPB_MODE_SCALAR},
+  {8, UPB_SIZE(0, 0), UPB_SIZE(-5, -9), 2, 11, _UPB_MODE_SCALAR},
+  {9, UPB_SIZE(0, 0), UPB_SIZE(-5, -9), 7, 11, _UPB_MODE_SCALAR},
+  {10, UPB_SIZE(0, 0), UPB_SIZE(-5, -9), 6, 11, _UPB_MODE_SCALAR},
+  {11, UPB_SIZE(0, 0), UPB_SIZE(-5, -9), 8, 11, _UPB_MODE_SCALAR},
+  {12, UPB_SIZE(0, 0), UPB_SIZE(-5, -9), 1, 11, _UPB_MODE_SCALAR},
 };
 
 const upb_msglayout envoy_config_rbac_v3_Permission_msginit = {
   &envoy_config_rbac_v3_Permission_submsgs[0],
   &envoy_config_rbac_v3_Permission__fields[0],
-  UPB_SIZE(8, 16), 11, false, 11, 255,
+  UPB_SIZE(8, 16), 12, false, 12, 255,
 };
 
 static const upb_msglayout *const envoy_config_rbac_v3_Permission_Set_submsgs[1] = {
index 89b54d9..e24be71 100644 (file)
@@ -45,6 +45,7 @@ extern const upb_msglayout envoy_config_rbac_v3_Principal_msginit;
 extern const upb_msglayout envoy_config_rbac_v3_Principal_Set_msginit;
 extern const upb_msglayout envoy_config_rbac_v3_Principal_Authenticated_msginit;
 struct envoy_config_core_v3_CidrRange;
+struct envoy_config_core_v3_TypedExtensionConfig;
 struct envoy_config_route_v3_HeaderMatcher;
 struct envoy_type_matcher_v3_MetadataMatcher;
 struct envoy_type_matcher_v3_PathMatcher;
@@ -53,6 +54,7 @@ struct envoy_type_v3_Int32Range;
 struct google_api_expr_v1alpha1_CheckedExpr;
 struct google_api_expr_v1alpha1_Expr;
 extern const upb_msglayout envoy_config_core_v3_CidrRange_msginit;
+extern const upb_msglayout envoy_config_core_v3_TypedExtensionConfig_msginit;
 extern const upb_msglayout envoy_config_route_v3_HeaderMatcher_msginit;
 extern const upb_msglayout envoy_type_matcher_v3_MetadataMatcher_msginit;
 extern const upb_msglayout envoy_type_matcher_v3_PathMatcher_msginit;
@@ -252,6 +254,7 @@ typedef enum {
   envoy_config_rbac_v3_Permission_rule_metadata = 7,
   envoy_config_rbac_v3_Permission_rule_not_rule = 8,
   envoy_config_rbac_v3_Permission_rule_requested_server_name = 9,
+  envoy_config_rbac_v3_Permission_rule_matcher = 12,
   envoy_config_rbac_v3_Permission_rule_NOT_SET = 0
 } envoy_config_rbac_v3_Permission_rule_oneofcases;
 UPB_INLINE envoy_config_rbac_v3_Permission_rule_oneofcases envoy_config_rbac_v3_Permission_rule_case(const envoy_config_rbac_v3_Permission* msg) { return (envoy_config_rbac_v3_Permission_rule_oneofcases)*UPB_PTR_AT(msg, UPB_SIZE(4, 8), int32_t); }
@@ -278,6 +281,8 @@ UPB_INLINE bool envoy_config_rbac_v3_Permission_has_url_path(const envoy_config_
 UPB_INLINE const struct envoy_type_matcher_v3_PathMatcher* envoy_config_rbac_v3_Permission_url_path(const envoy_config_rbac_v3_Permission *msg) { return UPB_READ_ONEOF(msg, const struct envoy_type_matcher_v3_PathMatcher*, UPB_SIZE(0, 0), UPB_SIZE(4, 8), 10, NULL); }
 UPB_INLINE bool envoy_config_rbac_v3_Permission_has_destination_port_range(const envoy_config_rbac_v3_Permission *msg) { return _upb_getoneofcase(msg, UPB_SIZE(4, 8)) == 11; }
 UPB_INLINE const struct envoy_type_v3_Int32Range* envoy_config_rbac_v3_Permission_destination_port_range(const envoy_config_rbac_v3_Permission *msg) { return UPB_READ_ONEOF(msg, const struct envoy_type_v3_Int32Range*, UPB_SIZE(0, 0), UPB_SIZE(4, 8), 11, NULL); }
+UPB_INLINE bool envoy_config_rbac_v3_Permission_has_matcher(const envoy_config_rbac_v3_Permission *msg) { return _upb_getoneofcase(msg, UPB_SIZE(4, 8)) == 12; }
+UPB_INLINE const struct envoy_config_core_v3_TypedExtensionConfig* envoy_config_rbac_v3_Permission_matcher(const envoy_config_rbac_v3_Permission *msg) { return UPB_READ_ONEOF(msg, const struct envoy_config_core_v3_TypedExtensionConfig*, UPB_SIZE(0, 0), UPB_SIZE(4, 8), 12, NULL); }
 
 UPB_INLINE void envoy_config_rbac_v3_Permission_set_and_rules(envoy_config_rbac_v3_Permission *msg, envoy_config_rbac_v3_Permission_Set* value) {
   UPB_WRITE_ONEOF(msg, envoy_config_rbac_v3_Permission_Set*, UPB_SIZE(0, 0), value, UPB_SIZE(4, 8), 1);
@@ -393,6 +398,18 @@ UPB_INLINE struct envoy_type_v3_Int32Range* envoy_config_rbac_v3_Permission_muta
   }
   return sub;
 }
+UPB_INLINE void envoy_config_rbac_v3_Permission_set_matcher(envoy_config_rbac_v3_Permission *msg, struct envoy_config_core_v3_TypedExtensionConfig* value) {
+  UPB_WRITE_ONEOF(msg, struct envoy_config_core_v3_TypedExtensionConfig*, UPB_SIZE(0, 0), value, UPB_SIZE(4, 8), 12);
+}
+UPB_INLINE struct envoy_config_core_v3_TypedExtensionConfig* envoy_config_rbac_v3_Permission_mutable_matcher(envoy_config_rbac_v3_Permission *msg, upb_arena *arena) {
+  struct envoy_config_core_v3_TypedExtensionConfig* sub = (struct envoy_config_core_v3_TypedExtensionConfig*)envoy_config_rbac_v3_Permission_matcher(msg);
+  if (sub == NULL) {
+    sub = (struct envoy_config_core_v3_TypedExtensionConfig*)_upb_msg_new(&envoy_config_core_v3_TypedExtensionConfig_msginit, arena);
+    if (!sub) return NULL;
+    envoy_config_rbac_v3_Permission_set_matcher(msg, sub);
+  }
+  return sub;
+}
 
 /* envoy.config.rbac.v3.Permission.Set */
 
index 79962b1..1289c33 100644 (file)
@@ -501,7 +501,8 @@ const upb_msglayout envoy_config_route_v3_RouteAction_MaxStreamDuration_msginit
   UPB_SIZE(16, 32), 3, false, 3, 255,
 };
 
-static const upb_msglayout *const envoy_config_route_v3_RetryPolicy_submsgs[7] = {
+static const upb_msglayout *const envoy_config_route_v3_RetryPolicy_submsgs[8] = {
+  &envoy_config_core_v3_TypedExtensionConfig_msginit,
   &envoy_config_route_v3_HeaderMatcher_msginit,
   &envoy_config_route_v3_RetryPolicy_RateLimitedRetryBackOff_msginit,
   &envoy_config_route_v3_RetryPolicy_RetryBackOff_msginit,
@@ -511,24 +512,26 @@ static const upb_msglayout *const envoy_config_route_v3_RetryPolicy_submsgs[7] =
   &google_protobuf_UInt32Value_msginit,
 };
 
-static const upb_msglayout_field envoy_config_route_v3_RetryPolicy__fields[11] = {
+static const upb_msglayout_field envoy_config_route_v3_RetryPolicy__fields[13] = {
   {1, UPB_SIZE(16, 16), 0, 0, 9, _UPB_MODE_SCALAR},
-  {2, UPB_SIZE(24, 32), 1, 6, 11, _UPB_MODE_SCALAR},
-  {3, UPB_SIZE(28, 40), 2, 5, 11, _UPB_MODE_SCALAR},
-  {4, UPB_SIZE(32, 48), 3, 4, 11, _UPB_MODE_SCALAR},
-  {5, UPB_SIZE(44, 72), 0, 3, 11, _UPB_MODE_ARRAY},
+  {2, UPB_SIZE(24, 32), 1, 7, 11, _UPB_MODE_SCALAR},
+  {3, UPB_SIZE(28, 40), 2, 6, 11, _UPB_MODE_SCALAR},
+  {4, UPB_SIZE(32, 48), 3, 5, 11, _UPB_MODE_SCALAR},
+  {5, UPB_SIZE(48, 80), 0, 4, 11, _UPB_MODE_ARRAY},
   {6, UPB_SIZE(8, 8), 0, 0, 3, _UPB_MODE_SCALAR},
-  {7, UPB_SIZE(48, 80), 0, 0, 13, _UPB_MODE_ARRAY | _UPB_MODE_IS_PACKED},
-  {8, UPB_SIZE(36, 56), 4, 2, 11, _UPB_MODE_SCALAR},
-  {9, UPB_SIZE(52, 88), 0, 0, 11, _UPB_MODE_ARRAY},
-  {10, UPB_SIZE(56, 96), 0, 0, 11, _UPB_MODE_ARRAY},
-  {11, UPB_SIZE(40, 64), 5, 1, 11, _UPB_MODE_SCALAR},
+  {7, UPB_SIZE(52, 88), 0, 0, 13, _UPB_MODE_ARRAY | _UPB_MODE_IS_PACKED},
+  {8, UPB_SIZE(36, 56), 4, 3, 11, _UPB_MODE_SCALAR},
+  {9, UPB_SIZE(56, 96), 0, 1, 11, _UPB_MODE_ARRAY},
+  {10, UPB_SIZE(60, 104), 0, 1, 11, _UPB_MODE_ARRAY},
+  {11, UPB_SIZE(40, 64), 5, 2, 11, _UPB_MODE_SCALAR},
+  {12, UPB_SIZE(64, 112), 0, 0, 11, _UPB_MODE_ARRAY},
+  {13, UPB_SIZE(44, 72), 6, 6, 11, _UPB_MODE_SCALAR},
 };
 
 const upb_msglayout envoy_config_route_v3_RetryPolicy_msginit = {
   &envoy_config_route_v3_RetryPolicy_submsgs[0],
   &envoy_config_route_v3_RetryPolicy__fields[0],
-  UPB_SIZE(64, 112), 11, false, 11, 255,
+  UPB_SIZE(72, 128), 13, false, 13, 255,
 };
 
 static const upb_msglayout *const envoy_config_route_v3_RetryPolicy_RetryPriority_submsgs[1] = {
index 095088e..497bfe4 100644 (file)
@@ -2414,18 +2414,22 @@ UPB_INLINE bool envoy_config_route_v3_RetryPolicy_has_per_try_timeout(const envo
 UPB_INLINE const struct google_protobuf_Duration* envoy_config_route_v3_RetryPolicy_per_try_timeout(const envoy_config_route_v3_RetryPolicy *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(28, 40), const struct google_protobuf_Duration*); }
 UPB_INLINE bool envoy_config_route_v3_RetryPolicy_has_retry_priority(const envoy_config_route_v3_RetryPolicy *msg) { return _upb_hasbit(msg, 3); }
 UPB_INLINE const envoy_config_route_v3_RetryPolicy_RetryPriority* envoy_config_route_v3_RetryPolicy_retry_priority(const envoy_config_route_v3_RetryPolicy *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(32, 48), const envoy_config_route_v3_RetryPolicy_RetryPriority*); }
-UPB_INLINE bool envoy_config_route_v3_RetryPolicy_has_retry_host_predicate(const envoy_config_route_v3_RetryPolicy *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(44, 72)); }
-UPB_INLINE const envoy_config_route_v3_RetryPolicy_RetryHostPredicate* const* envoy_config_route_v3_RetryPolicy_retry_host_predicate(const envoy_config_route_v3_RetryPolicy *msg, size_t *len) { return (const envoy_config_route_v3_RetryPolicy_RetryHostPredicate* const*)_upb_array_accessor(msg, UPB_SIZE(44, 72), len); }
+UPB_INLINE bool envoy_config_route_v3_RetryPolicy_has_retry_host_predicate(const envoy_config_route_v3_RetryPolicy *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(48, 80)); }
+UPB_INLINE const envoy_config_route_v3_RetryPolicy_RetryHostPredicate* const* envoy_config_route_v3_RetryPolicy_retry_host_predicate(const envoy_config_route_v3_RetryPolicy *msg, size_t *len) { return (const envoy_config_route_v3_RetryPolicy_RetryHostPredicate* const*)_upb_array_accessor(msg, UPB_SIZE(48, 80), len); }
 UPB_INLINE int64_t envoy_config_route_v3_RetryPolicy_host_selection_retry_max_attempts(const envoy_config_route_v3_RetryPolicy *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int64_t); }
-UPB_INLINE uint32_t const* envoy_config_route_v3_RetryPolicy_retriable_status_codes(const envoy_config_route_v3_RetryPolicy *msg, size_t *len) { return (uint32_t const*)_upb_array_accessor(msg, UPB_SIZE(48, 80), len); }
+UPB_INLINE uint32_t const* envoy_config_route_v3_RetryPolicy_retriable_status_codes(const envoy_config_route_v3_RetryPolicy *msg, size_t *len) { return (uint32_t const*)_upb_array_accessor(msg, UPB_SIZE(52, 88), len); }
 UPB_INLINE bool envoy_config_route_v3_RetryPolicy_has_retry_back_off(const envoy_config_route_v3_RetryPolicy *msg) { return _upb_hasbit(msg, 4); }
 UPB_INLINE const envoy_config_route_v3_RetryPolicy_RetryBackOff* envoy_config_route_v3_RetryPolicy_retry_back_off(const envoy_config_route_v3_RetryPolicy *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(36, 56), const envoy_config_route_v3_RetryPolicy_RetryBackOff*); }
-UPB_INLINE bool envoy_config_route_v3_RetryPolicy_has_retriable_headers(const envoy_config_route_v3_RetryPolicy *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(52, 88)); }
-UPB_INLINE const envoy_config_route_v3_HeaderMatcher* const* envoy_config_route_v3_RetryPolicy_retriable_headers(const envoy_config_route_v3_RetryPolicy *msg, size_t *len) { return (const envoy_config_route_v3_HeaderMatcher* const*)_upb_array_accessor(msg, UPB_SIZE(52, 88), len); }
-UPB_INLINE bool envoy_config_route_v3_RetryPolicy_has_retriable_request_headers(const envoy_config_route_v3_RetryPolicy *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(56, 96)); }
-UPB_INLINE const envoy_config_route_v3_HeaderMatcher* const* envoy_config_route_v3_RetryPolicy_retriable_request_headers(const envoy_config_route_v3_RetryPolicy *msg, size_t *len) { return (const envoy_config_route_v3_HeaderMatcher* const*)_upb_array_accessor(msg, UPB_SIZE(56, 96), len); }
+UPB_INLINE bool envoy_config_route_v3_RetryPolicy_has_retriable_headers(const envoy_config_route_v3_RetryPolicy *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(56, 96)); }
+UPB_INLINE const envoy_config_route_v3_HeaderMatcher* const* envoy_config_route_v3_RetryPolicy_retriable_headers(const envoy_config_route_v3_RetryPolicy *msg, size_t *len) { return (const envoy_config_route_v3_HeaderMatcher* const*)_upb_array_accessor(msg, UPB_SIZE(56, 96), len); }
+UPB_INLINE bool envoy_config_route_v3_RetryPolicy_has_retriable_request_headers(const envoy_config_route_v3_RetryPolicy *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(60, 104)); }
+UPB_INLINE const envoy_config_route_v3_HeaderMatcher* const* envoy_config_route_v3_RetryPolicy_retriable_request_headers(const envoy_config_route_v3_RetryPolicy *msg, size_t *len) { return (const envoy_config_route_v3_HeaderMatcher* const*)_upb_array_accessor(msg, UPB_SIZE(60, 104), len); }
 UPB_INLINE bool envoy_config_route_v3_RetryPolicy_has_rate_limited_retry_back_off(const envoy_config_route_v3_RetryPolicy *msg) { return _upb_hasbit(msg, 5); }
 UPB_INLINE const envoy_config_route_v3_RetryPolicy_RateLimitedRetryBackOff* envoy_config_route_v3_RetryPolicy_rate_limited_retry_back_off(const envoy_config_route_v3_RetryPolicy *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(40, 64), const envoy_config_route_v3_RetryPolicy_RateLimitedRetryBackOff*); }
+UPB_INLINE bool envoy_config_route_v3_RetryPolicy_has_retry_options_predicates(const envoy_config_route_v3_RetryPolicy *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(64, 112)); }
+UPB_INLINE const struct envoy_config_core_v3_TypedExtensionConfig* const* envoy_config_route_v3_RetryPolicy_retry_options_predicates(const envoy_config_route_v3_RetryPolicy *msg, size_t *len) { return (const struct envoy_config_core_v3_TypedExtensionConfig* const*)_upb_array_accessor(msg, UPB_SIZE(64, 112), len); }
+UPB_INLINE bool envoy_config_route_v3_RetryPolicy_has_per_try_idle_timeout(const envoy_config_route_v3_RetryPolicy *msg) { return _upb_hasbit(msg, 6); }
+UPB_INLINE const struct google_protobuf_Duration* envoy_config_route_v3_RetryPolicy_per_try_idle_timeout(const envoy_config_route_v3_RetryPolicy *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(44, 72), const struct google_protobuf_Duration*); }
 
 UPB_INLINE void envoy_config_route_v3_RetryPolicy_set_retry_on(envoy_config_route_v3_RetryPolicy *msg, upb_strview value) {
   *UPB_PTR_AT(msg, UPB_SIZE(16, 16), upb_strview) = value;
@@ -2470,15 +2474,15 @@ UPB_INLINE struct envoy_config_route_v3_RetryPolicy_RetryPriority* envoy_config_
   return sub;
 }
 UPB_INLINE envoy_config_route_v3_RetryPolicy_RetryHostPredicate** envoy_config_route_v3_RetryPolicy_mutable_retry_host_predicate(envoy_config_route_v3_RetryPolicy *msg, size_t *len) {
-  return (envoy_config_route_v3_RetryPolicy_RetryHostPredicate**)_upb_array_mutable_accessor(msg, UPB_SIZE(44, 72), len);
+  return (envoy_config_route_v3_RetryPolicy_RetryHostPredicate**)_upb_array_mutable_accessor(msg, UPB_SIZE(48, 80), len);
 }
 UPB_INLINE envoy_config_route_v3_RetryPolicy_RetryHostPredicate** envoy_config_route_v3_RetryPolicy_resize_retry_host_predicate(envoy_config_route_v3_RetryPolicy *msg, size_t len, upb_arena *arena) {
-  return (envoy_config_route_v3_RetryPolicy_RetryHostPredicate**)_upb_array_resize_accessor2(msg, UPB_SIZE(44, 72), len, UPB_SIZE(2, 3), arena);
+  return (envoy_config_route_v3_RetryPolicy_RetryHostPredicate**)_upb_array_resize_accessor2(msg, UPB_SIZE(48, 80), len, UPB_SIZE(2, 3), arena);
 }
 UPB_INLINE struct envoy_config_route_v3_RetryPolicy_RetryHostPredicate* envoy_config_route_v3_RetryPolicy_add_retry_host_predicate(envoy_config_route_v3_RetryPolicy *msg, upb_arena *arena) {
   struct envoy_config_route_v3_RetryPolicy_RetryHostPredicate* sub = (struct envoy_config_route_v3_RetryPolicy_RetryHostPredicate*)_upb_msg_new(&envoy_config_route_v3_RetryPolicy_RetryHostPredicate_msginit, arena);
   bool ok = _upb_array_append_accessor2(
-      msg, UPB_SIZE(44, 72), UPB_SIZE(2, 3), &sub, arena);
+      msg, UPB_SIZE(48, 80), UPB_SIZE(2, 3), &sub, arena);
   if (!ok) return NULL;
   return sub;
 }
@@ -2486,13 +2490,13 @@ UPB_INLINE void envoy_config_route_v3_RetryPolicy_set_host_selection_retry_max_a
   *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int64_t) = value;
 }
 UPB_INLINE uint32_t* envoy_config_route_v3_RetryPolicy_mutable_retriable_status_codes(envoy_config_route_v3_RetryPolicy *msg, size_t *len) {
-  return (uint32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(48, 80), len);
+  return (uint32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(52, 88), len);
 }
 UPB_INLINE uint32_t* envoy_config_route_v3_RetryPolicy_resize_retriable_status_codes(envoy_config_route_v3_RetryPolicy *msg, size_t len, upb_arena *arena) {
-  return (uint32_t*)_upb_array_resize_accessor2(msg, UPB_SIZE(48, 80), len, 2, arena);
+  return (uint32_t*)_upb_array_resize_accessor2(msg, UPB_SIZE(52, 88), len, 2, arena);
 }
 UPB_INLINE bool envoy_config_route_v3_RetryPolicy_add_retriable_status_codes(envoy_config_route_v3_RetryPolicy *msg, uint32_t val, upb_arena *arena) {
-  return _upb_array_append_accessor2(msg, UPB_SIZE(48, 80), 2, &val,
+  return _upb_array_append_accessor2(msg, UPB_SIZE(52, 88), 2, &val,
       arena);
 }
 UPB_INLINE void envoy_config_route_v3_RetryPolicy_set_retry_back_off(envoy_config_route_v3_RetryPolicy *msg, envoy_config_route_v3_RetryPolicy_RetryBackOff* value) {
@@ -2509,28 +2513,28 @@ UPB_INLINE struct envoy_config_route_v3_RetryPolicy_RetryBackOff* envoy_config_r
   return sub;
 }
 UPB_INLINE envoy_config_route_v3_HeaderMatcher** envoy_config_route_v3_RetryPolicy_mutable_retriable_headers(envoy_config_route_v3_RetryPolicy *msg, size_t *len) {
-  return (envoy_config_route_v3_HeaderMatcher**)_upb_array_mutable_accessor(msg, UPB_SIZE(52, 88), len);
+  return (envoy_config_route_v3_HeaderMatcher**)_upb_array_mutable_accessor(msg, UPB_SIZE(56, 96), len);
 }
 UPB_INLINE envoy_config_route_v3_HeaderMatcher** envoy_config_route_v3_RetryPolicy_resize_retriable_headers(envoy_config_route_v3_RetryPolicy *msg, size_t len, upb_arena *arena) {
-  return (envoy_config_route_v3_HeaderMatcher**)_upb_array_resize_accessor2(msg, UPB_SIZE(52, 88), len, UPB_SIZE(2, 3), arena);
+  return (envoy_config_route_v3_HeaderMatcher**)_upb_array_resize_accessor2(msg, UPB_SIZE(56, 96), len, UPB_SIZE(2, 3), arena);
 }
 UPB_INLINE struct envoy_config_route_v3_HeaderMatcher* envoy_config_route_v3_RetryPolicy_add_retriable_headers(envoy_config_route_v3_RetryPolicy *msg, upb_arena *arena) {
   struct envoy_config_route_v3_HeaderMatcher* sub = (struct envoy_config_route_v3_HeaderMatcher*)_upb_msg_new(&envoy_config_route_v3_HeaderMatcher_msginit, arena);
   bool ok = _upb_array_append_accessor2(
-      msg, UPB_SIZE(52, 88), UPB_SIZE(2, 3), &sub, arena);
+      msg, UPB_SIZE(56, 96), UPB_SIZE(2, 3), &sub, arena);
   if (!ok) return NULL;
   return sub;
 }
 UPB_INLINE envoy_config_route_v3_HeaderMatcher** envoy_config_route_v3_RetryPolicy_mutable_retriable_request_headers(envoy_config_route_v3_RetryPolicy *msg, size_t *len) {
-  return (envoy_config_route_v3_HeaderMatcher**)_upb_array_mutable_accessor(msg, UPB_SIZE(56, 96), len);
+  return (envoy_config_route_v3_HeaderMatcher**)_upb_array_mutable_accessor(msg, UPB_SIZE(60, 104), len);
 }
 UPB_INLINE envoy_config_route_v3_HeaderMatcher** envoy_config_route_v3_RetryPolicy_resize_retriable_request_headers(envoy_config_route_v3_RetryPolicy *msg, size_t len, upb_arena *arena) {
-  return (envoy_config_route_v3_HeaderMatcher**)_upb_array_resize_accessor2(msg, UPB_SIZE(56, 96), len, UPB_SIZE(2, 3), arena);
+  return (envoy_config_route_v3_HeaderMatcher**)_upb_array_resize_accessor2(msg, UPB_SIZE(60, 104), len, UPB_SIZE(2, 3), arena);
 }
 UPB_INLINE struct envoy_config_route_v3_HeaderMatcher* envoy_config_route_v3_RetryPolicy_add_retriable_request_headers(envoy_config_route_v3_RetryPolicy *msg, upb_arena *arena) {
   struct envoy_config_route_v3_HeaderMatcher* sub = (struct envoy_config_route_v3_HeaderMatcher*)_upb_msg_new(&envoy_config_route_v3_HeaderMatcher_msginit, arena);
   bool ok = _upb_array_append_accessor2(
-      msg, UPB_SIZE(56, 96), UPB_SIZE(2, 3), &sub, arena);
+      msg, UPB_SIZE(60, 104), UPB_SIZE(2, 3), &sub, arena);
   if (!ok) return NULL;
   return sub;
 }
@@ -2547,6 +2551,32 @@ UPB_INLINE struct envoy_config_route_v3_RetryPolicy_RateLimitedRetryBackOff* env
   }
   return sub;
 }
+UPB_INLINE struct envoy_config_core_v3_TypedExtensionConfig** envoy_config_route_v3_RetryPolicy_mutable_retry_options_predicates(envoy_config_route_v3_RetryPolicy *msg, size_t *len) {
+  return (struct envoy_config_core_v3_TypedExtensionConfig**)_upb_array_mutable_accessor(msg, UPB_SIZE(64, 112), len);
+}
+UPB_INLINE struct envoy_config_core_v3_TypedExtensionConfig** envoy_config_route_v3_RetryPolicy_resize_retry_options_predicates(envoy_config_route_v3_RetryPolicy *msg, size_t len, upb_arena *arena) {
+  return (struct envoy_config_core_v3_TypedExtensionConfig**)_upb_array_resize_accessor2(msg, UPB_SIZE(64, 112), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct envoy_config_core_v3_TypedExtensionConfig* envoy_config_route_v3_RetryPolicy_add_retry_options_predicates(envoy_config_route_v3_RetryPolicy *msg, upb_arena *arena) {
+  struct envoy_config_core_v3_TypedExtensionConfig* sub = (struct envoy_config_core_v3_TypedExtensionConfig*)_upb_msg_new(&envoy_config_core_v3_TypedExtensionConfig_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(64, 112), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE void envoy_config_route_v3_RetryPolicy_set_per_try_idle_timeout(envoy_config_route_v3_RetryPolicy *msg, struct google_protobuf_Duration* value) {
+  _upb_sethas(msg, 6);
+  *UPB_PTR_AT(msg, UPB_SIZE(44, 72), struct google_protobuf_Duration*) = value;
+}
+UPB_INLINE struct google_protobuf_Duration* envoy_config_route_v3_RetryPolicy_mutable_per_try_idle_timeout(envoy_config_route_v3_RetryPolicy *msg, upb_arena *arena) {
+  struct google_protobuf_Duration* sub = (struct google_protobuf_Duration*)envoy_config_route_v3_RetryPolicy_per_try_idle_timeout(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_Duration*)_upb_msg_new(&google_protobuf_Duration_msginit, arena);
+    if (!sub) return NULL;
+    envoy_config_route_v3_RetryPolicy_set_per_try_idle_timeout(msg, sub);
+  }
+  return sub;
+}
 
 /* envoy.config.route.v3.RetryPolicy.RetryPriority */
 
diff --git a/src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls.upb.c b/src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls.upb.c
new file mode 100644 (file)
index 0000000..44534dc
--- /dev/null
@@ -0,0 +1,55 @@
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ *     src/proto/grpc/lookup/v1/rls.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#include <stddef.h>
+#include "upb/msg_internal.h"
+#include "src/proto/grpc/lookup/v1/rls.upb.h"
+
+#include "upb/port_def.inc"
+
+static const upb_msglayout *const grpc_lookup_v1_RouteLookupRequest_submsgs[1] = {
+  &grpc_lookup_v1_RouteLookupRequest_KeyMapEntry_msginit,
+};
+
+static const upb_msglayout_field grpc_lookup_v1_RouteLookupRequest__fields[4] = {
+  {3, UPB_SIZE(4, 8), 0, 0, 9, _UPB_MODE_SCALAR},
+  {4, UPB_SIZE(20, 40), 0, 0, 11, _UPB_MODE_MAP},
+  {5, UPB_SIZE(0, 0), 0, 0, 14, _UPB_MODE_SCALAR},
+  {6, UPB_SIZE(12, 24), 0, 0, 9, _UPB_MODE_SCALAR},
+};
+
+const upb_msglayout grpc_lookup_v1_RouteLookupRequest_msginit = {
+  &grpc_lookup_v1_RouteLookupRequest_submsgs[0],
+  &grpc_lookup_v1_RouteLookupRequest__fields[0],
+  UPB_SIZE(24, 48), 4, false, 0, 255,
+};
+
+static const upb_msglayout_field grpc_lookup_v1_RouteLookupRequest_KeyMapEntry__fields[2] = {
+  {1, UPB_SIZE(0, 0), 0, 0, 9, _UPB_MODE_SCALAR},
+  {2, UPB_SIZE(8, 16), 0, 0, 9, _UPB_MODE_SCALAR},
+};
+
+const upb_msglayout grpc_lookup_v1_RouteLookupRequest_KeyMapEntry_msginit = {
+  NULL,
+  &grpc_lookup_v1_RouteLookupRequest_KeyMapEntry__fields[0],
+  UPB_SIZE(16, 32), 2, false, 2, 255,
+};
+
+static const upb_msglayout_field grpc_lookup_v1_RouteLookupResponse__fields[2] = {
+  {2, UPB_SIZE(0, 0), 0, 0, 9, _UPB_MODE_SCALAR},
+  {3, UPB_SIZE(8, 16), 0, 0, 9, _UPB_MODE_ARRAY},
+};
+
+const upb_msglayout grpc_lookup_v1_RouteLookupResponse_msginit = {
+  NULL,
+  &grpc_lookup_v1_RouteLookupResponse__fields[0],
+  UPB_SIZE(16, 32), 2, false, 0, 255,
+};
+
+#include "upb/port_undef.inc"
+
diff --git a/src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls.upb.h b/src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls.upb.h
new file mode 100644 (file)
index 0000000..bbc8a09
--- /dev/null
@@ -0,0 +1,154 @@
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ *     src/proto/grpc/lookup/v1/rls.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#ifndef SRC_PROTO_GRPC_LOOKUP_V1_RLS_PROTO_UPB_H_
+#define SRC_PROTO_GRPC_LOOKUP_V1_RLS_PROTO_UPB_H_
+
+#include "upb/msg_internal.h"
+#include "upb/decode.h"
+#include "upb/decode_fast.h"
+#include "upb/encode.h"
+
+#include "upb/port_def.inc"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct grpc_lookup_v1_RouteLookupRequest;
+struct grpc_lookup_v1_RouteLookupRequest_KeyMapEntry;
+struct grpc_lookup_v1_RouteLookupResponse;
+typedef struct grpc_lookup_v1_RouteLookupRequest grpc_lookup_v1_RouteLookupRequest;
+typedef struct grpc_lookup_v1_RouteLookupRequest_KeyMapEntry grpc_lookup_v1_RouteLookupRequest_KeyMapEntry;
+typedef struct grpc_lookup_v1_RouteLookupResponse grpc_lookup_v1_RouteLookupResponse;
+extern const upb_msglayout grpc_lookup_v1_RouteLookupRequest_msginit;
+extern const upb_msglayout grpc_lookup_v1_RouteLookupRequest_KeyMapEntry_msginit;
+extern const upb_msglayout grpc_lookup_v1_RouteLookupResponse_msginit;
+
+typedef enum {
+  grpc_lookup_v1_RouteLookupRequest_REASON_UNKNOWN = 0,
+  grpc_lookup_v1_RouteLookupRequest_REASON_MISS = 1,
+  grpc_lookup_v1_RouteLookupRequest_REASON_STALE = 2
+} grpc_lookup_v1_RouteLookupRequest_Reason;
+
+
+/* grpc.lookup.v1.RouteLookupRequest */
+
+UPB_INLINE grpc_lookup_v1_RouteLookupRequest *grpc_lookup_v1_RouteLookupRequest_new(upb_arena *arena) {
+  return (grpc_lookup_v1_RouteLookupRequest *)_upb_msg_new(&grpc_lookup_v1_RouteLookupRequest_msginit, arena);
+}
+UPB_INLINE grpc_lookup_v1_RouteLookupRequest *grpc_lookup_v1_RouteLookupRequest_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  grpc_lookup_v1_RouteLookupRequest *ret = grpc_lookup_v1_RouteLookupRequest_new(arena);
+  if (!ret) return NULL;
+  if (!upb_decode(buf, size, ret, &grpc_lookup_v1_RouteLookupRequest_msginit, arena)) return NULL;
+  return ret;
+}
+UPB_INLINE grpc_lookup_v1_RouteLookupRequest *grpc_lookup_v1_RouteLookupRequest_parse_ex(const char *buf, size_t size,
+                           const upb_extreg *extreg, int options,
+                           upb_arena *arena) {
+  grpc_lookup_v1_RouteLookupRequest *ret = grpc_lookup_v1_RouteLookupRequest_new(arena);
+  if (!ret) return NULL;
+  if (!_upb_decode(buf, size, ret, &grpc_lookup_v1_RouteLookupRequest_msginit, extreg, options, arena)) {
+    return NULL;
+  }
+  return ret;
+}
+UPB_INLINE char *grpc_lookup_v1_RouteLookupRequest_serialize(const grpc_lookup_v1_RouteLookupRequest *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &grpc_lookup_v1_RouteLookupRequest_msginit, arena, len);
+}
+
+UPB_INLINE upb_strview grpc_lookup_v1_RouteLookupRequest_target_type(const grpc_lookup_v1_RouteLookupRequest *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
+UPB_INLINE bool grpc_lookup_v1_RouteLookupRequest_has_key_map(const grpc_lookup_v1_RouteLookupRequest *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(20, 40)); }
+UPB_INLINE size_t grpc_lookup_v1_RouteLookupRequest_key_map_size(const grpc_lookup_v1_RouteLookupRequest *msg) {return _upb_msg_map_size(msg, UPB_SIZE(20, 40)); }
+UPB_INLINE bool grpc_lookup_v1_RouteLookupRequest_key_map_get(const grpc_lookup_v1_RouteLookupRequest *msg, upb_strview key, upb_strview *val) { return _upb_msg_map_get(msg, UPB_SIZE(20, 40), &key, 0, val, 0); }
+UPB_INLINE const grpc_lookup_v1_RouteLookupRequest_KeyMapEntry* grpc_lookup_v1_RouteLookupRequest_key_map_next(const grpc_lookup_v1_RouteLookupRequest *msg, size_t* iter) { return (const grpc_lookup_v1_RouteLookupRequest_KeyMapEntry*)_upb_msg_map_next(msg, UPB_SIZE(20, 40), iter); }
+UPB_INLINE int32_t grpc_lookup_v1_RouteLookupRequest_reason(const grpc_lookup_v1_RouteLookupRequest *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(0, 0), int32_t); }
+UPB_INLINE upb_strview grpc_lookup_v1_RouteLookupRequest_stale_header_data(const grpc_lookup_v1_RouteLookupRequest *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview); }
+
+UPB_INLINE void grpc_lookup_v1_RouteLookupRequest_set_target_type(grpc_lookup_v1_RouteLookupRequest *msg, upb_strview value) {
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
+}
+UPB_INLINE void grpc_lookup_v1_RouteLookupRequest_key_map_clear(grpc_lookup_v1_RouteLookupRequest *msg) { _upb_msg_map_clear(msg, UPB_SIZE(20, 40)); }
+UPB_INLINE bool grpc_lookup_v1_RouteLookupRequest_key_map_set(grpc_lookup_v1_RouteLookupRequest *msg, upb_strview key, upb_strview val, upb_arena *a) { return _upb_msg_map_set(msg, UPB_SIZE(20, 40), &key, 0, &val, 0, a); }
+UPB_INLINE bool grpc_lookup_v1_RouteLookupRequest_key_map_delete(grpc_lookup_v1_RouteLookupRequest *msg, upb_strview key) { return _upb_msg_map_delete(msg, UPB_SIZE(20, 40), &key, 0); }
+UPB_INLINE grpc_lookup_v1_RouteLookupRequest_KeyMapEntry* grpc_lookup_v1_RouteLookupRequest_key_map_nextmutable(grpc_lookup_v1_RouteLookupRequest *msg, size_t* iter) { return (grpc_lookup_v1_RouteLookupRequest_KeyMapEntry*)_upb_msg_map_next(msg, UPB_SIZE(20, 40), iter); }
+UPB_INLINE void grpc_lookup_v1_RouteLookupRequest_set_reason(grpc_lookup_v1_RouteLookupRequest *msg, int32_t value) {
+  *UPB_PTR_AT(msg, UPB_SIZE(0, 0), int32_t) = value;
+}
+UPB_INLINE void grpc_lookup_v1_RouteLookupRequest_set_stale_header_data(grpc_lookup_v1_RouteLookupRequest *msg, upb_strview value) {
+  *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview) = value;
+}
+
+/* grpc.lookup.v1.RouteLookupRequest.KeyMapEntry */
+
+UPB_INLINE upb_strview grpc_lookup_v1_RouteLookupRequest_KeyMapEntry_key(const grpc_lookup_v1_RouteLookupRequest_KeyMapEntry *msg) {
+  upb_strview ret;
+  _upb_msg_map_key(msg, &ret, 0);
+  return ret;
+}
+UPB_INLINE upb_strview grpc_lookup_v1_RouteLookupRequest_KeyMapEntry_value(const grpc_lookup_v1_RouteLookupRequest_KeyMapEntry *msg) {
+  upb_strview ret;
+  _upb_msg_map_value(msg, &ret, 0);
+  return ret;
+}
+
+UPB_INLINE void grpc_lookup_v1_RouteLookupRequest_KeyMapEntry_set_value(grpc_lookup_v1_RouteLookupRequest_KeyMapEntry *msg, upb_strview value) {
+  _upb_msg_map_set_value(msg, &value, 0);
+}
+
+/* grpc.lookup.v1.RouteLookupResponse */
+
+UPB_INLINE grpc_lookup_v1_RouteLookupResponse *grpc_lookup_v1_RouteLookupResponse_new(upb_arena *arena) {
+  return (grpc_lookup_v1_RouteLookupResponse *)_upb_msg_new(&grpc_lookup_v1_RouteLookupResponse_msginit, arena);
+}
+UPB_INLINE grpc_lookup_v1_RouteLookupResponse *grpc_lookup_v1_RouteLookupResponse_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  grpc_lookup_v1_RouteLookupResponse *ret = grpc_lookup_v1_RouteLookupResponse_new(arena);
+  if (!ret) return NULL;
+  if (!upb_decode(buf, size, ret, &grpc_lookup_v1_RouteLookupResponse_msginit, arena)) return NULL;
+  return ret;
+}
+UPB_INLINE grpc_lookup_v1_RouteLookupResponse *grpc_lookup_v1_RouteLookupResponse_parse_ex(const char *buf, size_t size,
+                           const upb_extreg *extreg, int options,
+                           upb_arena *arena) {
+  grpc_lookup_v1_RouteLookupResponse *ret = grpc_lookup_v1_RouteLookupResponse_new(arena);
+  if (!ret) return NULL;
+  if (!_upb_decode(buf, size, ret, &grpc_lookup_v1_RouteLookupResponse_msginit, extreg, options, arena)) {
+    return NULL;
+  }
+  return ret;
+}
+UPB_INLINE char *grpc_lookup_v1_RouteLookupResponse_serialize(const grpc_lookup_v1_RouteLookupResponse *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &grpc_lookup_v1_RouteLookupResponse_msginit, arena, len);
+}
+
+UPB_INLINE upb_strview grpc_lookup_v1_RouteLookupResponse_header_data(const grpc_lookup_v1_RouteLookupResponse *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(0, 0), upb_strview); }
+UPB_INLINE upb_strview const* grpc_lookup_v1_RouteLookupResponse_targets(const grpc_lookup_v1_RouteLookupResponse *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(8, 16), len); }
+
+UPB_INLINE void grpc_lookup_v1_RouteLookupResponse_set_header_data(grpc_lookup_v1_RouteLookupResponse *msg, upb_strview value) {
+  *UPB_PTR_AT(msg, UPB_SIZE(0, 0), upb_strview) = value;
+}
+UPB_INLINE upb_strview* grpc_lookup_v1_RouteLookupResponse_mutable_targets(grpc_lookup_v1_RouteLookupResponse *msg, size_t *len) {
+  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(8, 16), len);
+}
+UPB_INLINE upb_strview* grpc_lookup_v1_RouteLookupResponse_resize_targets(grpc_lookup_v1_RouteLookupResponse *msg, size_t len, upb_arena *arena) {
+  return (upb_strview*)_upb_array_resize_accessor2(msg, UPB_SIZE(8, 16), len, UPB_SIZE(3, 4), arena);
+}
+UPB_INLINE bool grpc_lookup_v1_RouteLookupResponse_add_targets(grpc_lookup_v1_RouteLookupResponse *msg, upb_strview val, upb_arena *arena) {
+  return _upb_array_append_accessor2(msg, UPB_SIZE(8, 16), UPB_SIZE(3, 4), &val,
+      arena);
+}
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#include "upb/port_undef.inc"
+
+#endif  /* SRC_PROTO_GRPC_LOOKUP_V1_RLS_PROTO_UPB_H_ */
index 732903d..e367207 100644 (file)
@@ -10,9 +10,7 @@
 #include "upb/msg_internal.h"
 #include "udpa/annotations/security.upb.h"
 #include "udpa/annotations/status.upb.h"
-#include "google/protobuf/any.upb.h"
 #include "google/protobuf/descriptor.upb.h"
-#include "validate/validate.upb.h"
 
 #include "upb/port_def.inc"
 
diff --git a/src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c b/src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c
deleted file mode 100644 (file)
index 38feb7b..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/* This file was generated by upbc (the upb compiler) from the input
- * file:
- *
- *     udpa/data/orca/v1/orca_load_report.proto
- *
- * Do not edit -- your changes will be discarded when the file is
- * regenerated. */
-
-#include <stddef.h>
-#include "upb/msg_internal.h"
-#include "udpa/data/orca/v1/orca_load_report.upb.h"
-#include "validate/validate.upb.h"
-
-#include "upb/port_def.inc"
-
-static const upb_msglayout *const udpa_data_orca_v1_OrcaLoadReport_submsgs[2] = {
-  &udpa_data_orca_v1_OrcaLoadReport_RequestCostEntry_msginit,
-  &udpa_data_orca_v1_OrcaLoadReport_UtilizationEntry_msginit,
-};
-
-static const upb_msglayout_field udpa_data_orca_v1_OrcaLoadReport__fields[5] = {
-  {1, UPB_SIZE(0, 0), 0, 0, 1, _UPB_MODE_SCALAR},
-  {2, UPB_SIZE(8, 8), 0, 0, 1, _UPB_MODE_SCALAR},
-  {3, UPB_SIZE(16, 16), 0, 0, 4, _UPB_MODE_SCALAR},
-  {4, UPB_SIZE(24, 24), 0, 0, 11, _UPB_MODE_MAP},
-  {5, UPB_SIZE(28, 32), 0, 1, 11, _UPB_MODE_MAP},
-};
-
-const upb_msglayout udpa_data_orca_v1_OrcaLoadReport_msginit = {
-  &udpa_data_orca_v1_OrcaLoadReport_submsgs[0],
-  &udpa_data_orca_v1_OrcaLoadReport__fields[0],
-  UPB_SIZE(32, 40), 5, false, 5, 255,
-};
-
-static const upb_msglayout_field udpa_data_orca_v1_OrcaLoadReport_RequestCostEntry__fields[2] = {
-  {1, UPB_SIZE(0, 0), 0, 0, 9, _UPB_MODE_SCALAR},
-  {2, UPB_SIZE(8, 16), 0, 0, 1, _UPB_MODE_SCALAR},
-};
-
-const upb_msglayout udpa_data_orca_v1_OrcaLoadReport_RequestCostEntry_msginit = {
-  NULL,
-  &udpa_data_orca_v1_OrcaLoadReport_RequestCostEntry__fields[0],
-  UPB_SIZE(16, 32), 2, false, 2, 255,
-};
-
-static const upb_msglayout_field udpa_data_orca_v1_OrcaLoadReport_UtilizationEntry__fields[2] = {
-  {1, UPB_SIZE(0, 0), 0, 0, 9, _UPB_MODE_SCALAR},
-  {2, UPB_SIZE(8, 16), 0, 0, 1, _UPB_MODE_SCALAR},
-};
-
-const upb_msglayout udpa_data_orca_v1_OrcaLoadReport_UtilizationEntry_msginit = {
-  NULL,
-  &udpa_data_orca_v1_OrcaLoadReport_UtilizationEntry__fields[0],
-  UPB_SIZE(16, 32), 2, false, 2, 255,
-};
-
-#include "upb/port_undef.inc"
-
diff --git a/src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h b/src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h
deleted file mode 100644 (file)
index dbefd80..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-/* This file was generated by upbc (the upb compiler) from the input
- * file:
- *
- *     udpa/data/orca/v1/orca_load_report.proto
- *
- * Do not edit -- your changes will be discarded when the file is
- * regenerated. */
-
-#ifndef UDPA_DATA_ORCA_V1_ORCA_LOAD_REPORT_PROTO_UPB_H_
-#define UDPA_DATA_ORCA_V1_ORCA_LOAD_REPORT_PROTO_UPB_H_
-
-#include "upb/msg_internal.h"
-#include "upb/decode.h"
-#include "upb/decode_fast.h"
-#include "upb/encode.h"
-
-#include "upb/port_def.inc"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct udpa_data_orca_v1_OrcaLoadReport;
-struct udpa_data_orca_v1_OrcaLoadReport_RequestCostEntry;
-struct udpa_data_orca_v1_OrcaLoadReport_UtilizationEntry;
-typedef struct udpa_data_orca_v1_OrcaLoadReport udpa_data_orca_v1_OrcaLoadReport;
-typedef struct udpa_data_orca_v1_OrcaLoadReport_RequestCostEntry udpa_data_orca_v1_OrcaLoadReport_RequestCostEntry;
-typedef struct udpa_data_orca_v1_OrcaLoadReport_UtilizationEntry udpa_data_orca_v1_OrcaLoadReport_UtilizationEntry;
-extern const upb_msglayout udpa_data_orca_v1_OrcaLoadReport_msginit;
-extern const upb_msglayout udpa_data_orca_v1_OrcaLoadReport_RequestCostEntry_msginit;
-extern const upb_msglayout udpa_data_orca_v1_OrcaLoadReport_UtilizationEntry_msginit;
-
-
-/* udpa.data.orca.v1.OrcaLoadReport */
-
-UPB_INLINE udpa_data_orca_v1_OrcaLoadReport *udpa_data_orca_v1_OrcaLoadReport_new(upb_arena *arena) {
-  return (udpa_data_orca_v1_OrcaLoadReport *)_upb_msg_new(&udpa_data_orca_v1_OrcaLoadReport_msginit, arena);
-}
-UPB_INLINE udpa_data_orca_v1_OrcaLoadReport *udpa_data_orca_v1_OrcaLoadReport_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  udpa_data_orca_v1_OrcaLoadReport *ret = udpa_data_orca_v1_OrcaLoadReport_new(arena);
-  if (!ret) return NULL;
-  if (!upb_decode(buf, size, ret, &udpa_data_orca_v1_OrcaLoadReport_msginit, arena)) return NULL;
-  return ret;
-}
-UPB_INLINE udpa_data_orca_v1_OrcaLoadReport *udpa_data_orca_v1_OrcaLoadReport_parse_ex(const char *buf, size_t size,
-                           const upb_extreg *extreg, int options,
-                           upb_arena *arena) {
-  udpa_data_orca_v1_OrcaLoadReport *ret = udpa_data_orca_v1_OrcaLoadReport_new(arena);
-  if (!ret) return NULL;
-  if (!_upb_decode(buf, size, ret, &udpa_data_orca_v1_OrcaLoadReport_msginit, extreg, options, arena)) {
-    return NULL;
-  }
-  return ret;
-}
-UPB_INLINE char *udpa_data_orca_v1_OrcaLoadReport_serialize(const udpa_data_orca_v1_OrcaLoadReport *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &udpa_data_orca_v1_OrcaLoadReport_msginit, arena, len);
-}
-
-UPB_INLINE double udpa_data_orca_v1_OrcaLoadReport_cpu_utilization(const udpa_data_orca_v1_OrcaLoadReport *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(0, 0), double); }
-UPB_INLINE double udpa_data_orca_v1_OrcaLoadReport_mem_utilization(const udpa_data_orca_v1_OrcaLoadReport *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), double); }
-UPB_INLINE uint64_t udpa_data_orca_v1_OrcaLoadReport_rps(const udpa_data_orca_v1_OrcaLoadReport *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), uint64_t); }
-UPB_INLINE bool udpa_data_orca_v1_OrcaLoadReport_has_request_cost(const udpa_data_orca_v1_OrcaLoadReport *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(24, 24)); }
-UPB_INLINE size_t udpa_data_orca_v1_OrcaLoadReport_request_cost_size(const udpa_data_orca_v1_OrcaLoadReport *msg) {return _upb_msg_map_size(msg, UPB_SIZE(24, 24)); }
-UPB_INLINE bool udpa_data_orca_v1_OrcaLoadReport_request_cost_get(const udpa_data_orca_v1_OrcaLoadReport *msg, upb_strview key, double *val) { return _upb_msg_map_get(msg, UPB_SIZE(24, 24), &key, 0, val, sizeof(*val)); }
-UPB_INLINE const udpa_data_orca_v1_OrcaLoadReport_RequestCostEntry* udpa_data_orca_v1_OrcaLoadReport_request_cost_next(const udpa_data_orca_v1_OrcaLoadReport *msg, size_t* iter) { return (const udpa_data_orca_v1_OrcaLoadReport_RequestCostEntry*)_upb_msg_map_next(msg, UPB_SIZE(24, 24), iter); }
-UPB_INLINE bool udpa_data_orca_v1_OrcaLoadReport_has_utilization(const udpa_data_orca_v1_OrcaLoadReport *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(28, 32)); }
-UPB_INLINE size_t udpa_data_orca_v1_OrcaLoadReport_utilization_size(const udpa_data_orca_v1_OrcaLoadReport *msg) {return _upb_msg_map_size(msg, UPB_SIZE(28, 32)); }
-UPB_INLINE bool udpa_data_orca_v1_OrcaLoadReport_utilization_get(const udpa_data_orca_v1_OrcaLoadReport *msg, upb_strview key, double *val) { return _upb_msg_map_get(msg, UPB_SIZE(28, 32), &key, 0, val, sizeof(*val)); }
-UPB_INLINE const udpa_data_orca_v1_OrcaLoadReport_UtilizationEntry* udpa_data_orca_v1_OrcaLoadReport_utilization_next(const udpa_data_orca_v1_OrcaLoadReport *msg, size_t* iter) { return (const udpa_data_orca_v1_OrcaLoadReport_UtilizationEntry*)_upb_msg_map_next(msg, UPB_SIZE(28, 32), iter); }
-
-UPB_INLINE void udpa_data_orca_v1_OrcaLoadReport_set_cpu_utilization(udpa_data_orca_v1_OrcaLoadReport *msg, double value) {
-  *UPB_PTR_AT(msg, UPB_SIZE(0, 0), double) = value;
-}
-UPB_INLINE void udpa_data_orca_v1_OrcaLoadReport_set_mem_utilization(udpa_data_orca_v1_OrcaLoadReport *msg, double value) {
-  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), double) = value;
-}
-UPB_INLINE void udpa_data_orca_v1_OrcaLoadReport_set_rps(udpa_data_orca_v1_OrcaLoadReport *msg, uint64_t value) {
-  *UPB_PTR_AT(msg, UPB_SIZE(16, 16), uint64_t) = value;
-}
-UPB_INLINE void udpa_data_orca_v1_OrcaLoadReport_request_cost_clear(udpa_data_orca_v1_OrcaLoadReport *msg) { _upb_msg_map_clear(msg, UPB_SIZE(24, 24)); }
-UPB_INLINE bool udpa_data_orca_v1_OrcaLoadReport_request_cost_set(udpa_data_orca_v1_OrcaLoadReport *msg, upb_strview key, double val, upb_arena *a) { return _upb_msg_map_set(msg, UPB_SIZE(24, 24), &key, 0, &val, sizeof(val), a); }
-UPB_INLINE bool udpa_data_orca_v1_OrcaLoadReport_request_cost_delete(udpa_data_orca_v1_OrcaLoadReport *msg, upb_strview key) { return _upb_msg_map_delete(msg, UPB_SIZE(24, 24), &key, 0); }
-UPB_INLINE udpa_data_orca_v1_OrcaLoadReport_RequestCostEntry* udpa_data_orca_v1_OrcaLoadReport_request_cost_nextmutable(udpa_data_orca_v1_OrcaLoadReport *msg, size_t* iter) { return (udpa_data_orca_v1_OrcaLoadReport_RequestCostEntry*)_upb_msg_map_next(msg, UPB_SIZE(24, 24), iter); }
-UPB_INLINE void udpa_data_orca_v1_OrcaLoadReport_utilization_clear(udpa_data_orca_v1_OrcaLoadReport *msg) { _upb_msg_map_clear(msg, UPB_SIZE(28, 32)); }
-UPB_INLINE bool udpa_data_orca_v1_OrcaLoadReport_utilization_set(udpa_data_orca_v1_OrcaLoadReport *msg, upb_strview key, double val, upb_arena *a) { return _upb_msg_map_set(msg, UPB_SIZE(28, 32), &key, 0, &val, sizeof(val), a); }
-UPB_INLINE bool udpa_data_orca_v1_OrcaLoadReport_utilization_delete(udpa_data_orca_v1_OrcaLoadReport *msg, upb_strview key) { return _upb_msg_map_delete(msg, UPB_SIZE(28, 32), &key, 0); }
-UPB_INLINE udpa_data_orca_v1_OrcaLoadReport_UtilizationEntry* udpa_data_orca_v1_OrcaLoadReport_utilization_nextmutable(udpa_data_orca_v1_OrcaLoadReport *msg, size_t* iter) { return (udpa_data_orca_v1_OrcaLoadReport_UtilizationEntry*)_upb_msg_map_next(msg, UPB_SIZE(28, 32), iter); }
-
-/* udpa.data.orca.v1.OrcaLoadReport.RequestCostEntry */
-
-UPB_INLINE upb_strview udpa_data_orca_v1_OrcaLoadReport_RequestCostEntry_key(const udpa_data_orca_v1_OrcaLoadReport_RequestCostEntry *msg) {
-  upb_strview ret;
-  _upb_msg_map_key(msg, &ret, 0);
-  return ret;
-}
-UPB_INLINE double udpa_data_orca_v1_OrcaLoadReport_RequestCostEntry_value(const udpa_data_orca_v1_OrcaLoadReport_RequestCostEntry *msg) {
-  double ret;
-  _upb_msg_map_value(msg, &ret, sizeof(ret));
-  return ret;
-}
-
-UPB_INLINE void udpa_data_orca_v1_OrcaLoadReport_RequestCostEntry_set_value(udpa_data_orca_v1_OrcaLoadReport_RequestCostEntry *msg, double value) {
-  _upb_msg_map_set_value(msg, &value, sizeof(double));
-}
-
-/* udpa.data.orca.v1.OrcaLoadReport.UtilizationEntry */
-
-UPB_INLINE upb_strview udpa_data_orca_v1_OrcaLoadReport_UtilizationEntry_key(const udpa_data_orca_v1_OrcaLoadReport_UtilizationEntry *msg) {
-  upb_strview ret;
-  _upb_msg_map_key(msg, &ret, 0);
-  return ret;
-}
-UPB_INLINE double udpa_data_orca_v1_OrcaLoadReport_UtilizationEntry_value(const udpa_data_orca_v1_OrcaLoadReport_UtilizationEntry *msg) {
-  double ret;
-  _upb_msg_map_value(msg, &ret, sizeof(ret));
-  return ret;
-}
-
-UPB_INLINE void udpa_data_orca_v1_OrcaLoadReport_UtilizationEntry_set_value(udpa_data_orca_v1_OrcaLoadReport_UtilizationEntry *msg, double value) {
-  _upb_msg_map_set_value(msg, &value, sizeof(double));
-}
-
-#ifdef __cplusplus
-}  /* extern "C" */
-#endif
-
-#include "upb/port_undef.inc"
-
-#endif  /* UDPA_DATA_ORCA_V1_ORCA_LOAD_REPORT_PROTO_UPB_H_ */
diff --git a/src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.c b/src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.c
deleted file mode 100644 (file)
index 347fb1e..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/* This file was generated by upbc (the upb compiler) from the input
- * file:
- *
- *     udpa/type/v1/typed_struct.proto
- *
- * Do not edit -- your changes will be discarded when the file is
- * regenerated. */
-
-#include <stddef.h>
-#include "upb/msg_internal.h"
-#include "udpa/type/v1/typed_struct.upb.h"
-#include "validate/validate.upb.h"
-#include "google/protobuf/struct.upb.h"
-
-#include "upb/port_def.inc"
-
-static const upb_msglayout *const udpa_type_v1_TypedStruct_submsgs[1] = {
-  &google_protobuf_Struct_msginit,
-};
-
-static const upb_msglayout_field udpa_type_v1_TypedStruct__fields[2] = {
-  {1, UPB_SIZE(4, 8), 0, 0, 9, _UPB_MODE_SCALAR},
-  {2, UPB_SIZE(12, 24), 1, 0, 11, _UPB_MODE_SCALAR},
-};
-
-const upb_msglayout udpa_type_v1_TypedStruct_msginit = {
-  &udpa_type_v1_TypedStruct_submsgs[0],
-  &udpa_type_v1_TypedStruct__fields[0],
-  UPB_SIZE(16, 32), 2, false, 2, 255,
-};
-
-#include "upb/port_undef.inc"
-
diff --git a/src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.h b/src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.h
deleted file mode 100644 (file)
index 431413c..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-/* This file was generated by upbc (the upb compiler) from the input
- * file:
- *
- *     udpa/type/v1/typed_struct.proto
- *
- * Do not edit -- your changes will be discarded when the file is
- * regenerated. */
-
-#ifndef UDPA_TYPE_V1_TYPED_STRUCT_PROTO_UPB_H_
-#define UDPA_TYPE_V1_TYPED_STRUCT_PROTO_UPB_H_
-
-#include "upb/msg_internal.h"
-#include "upb/decode.h"
-#include "upb/decode_fast.h"
-#include "upb/encode.h"
-
-#include "upb/port_def.inc"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct udpa_type_v1_TypedStruct;
-typedef struct udpa_type_v1_TypedStruct udpa_type_v1_TypedStruct;
-extern const upb_msglayout udpa_type_v1_TypedStruct_msginit;
-struct google_protobuf_Struct;
-extern const upb_msglayout google_protobuf_Struct_msginit;
-
-
-/* udpa.type.v1.TypedStruct */
-
-UPB_INLINE udpa_type_v1_TypedStruct *udpa_type_v1_TypedStruct_new(upb_arena *arena) {
-  return (udpa_type_v1_TypedStruct *)_upb_msg_new(&udpa_type_v1_TypedStruct_msginit, arena);
-}
-UPB_INLINE udpa_type_v1_TypedStruct *udpa_type_v1_TypedStruct_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  udpa_type_v1_TypedStruct *ret = udpa_type_v1_TypedStruct_new(arena);
-  if (!ret) return NULL;
-  if (!upb_decode(buf, size, ret, &udpa_type_v1_TypedStruct_msginit, arena)) return NULL;
-  return ret;
-}
-UPB_INLINE udpa_type_v1_TypedStruct *udpa_type_v1_TypedStruct_parse_ex(const char *buf, size_t size,
-                           const upb_extreg *extreg, int options,
-                           upb_arena *arena) {
-  udpa_type_v1_TypedStruct *ret = udpa_type_v1_TypedStruct_new(arena);
-  if (!ret) return NULL;
-  if (!_upb_decode(buf, size, ret, &udpa_type_v1_TypedStruct_msginit, extreg, options, arena)) {
-    return NULL;
-  }
-  return ret;
-}
-UPB_INLINE char *udpa_type_v1_TypedStruct_serialize(const udpa_type_v1_TypedStruct *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &udpa_type_v1_TypedStruct_msginit, arena, len);
-}
-
-UPB_INLINE upb_strview udpa_type_v1_TypedStruct_type_url(const udpa_type_v1_TypedStruct *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
-UPB_INLINE bool udpa_type_v1_TypedStruct_has_value(const udpa_type_v1_TypedStruct *msg) { return _upb_hasbit(msg, 1); }
-UPB_INLINE const struct google_protobuf_Struct* udpa_type_v1_TypedStruct_value(const udpa_type_v1_TypedStruct *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const struct google_protobuf_Struct*); }
-
-UPB_INLINE void udpa_type_v1_TypedStruct_set_type_url(udpa_type_v1_TypedStruct *msg, upb_strview value) {
-  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
-}
-UPB_INLINE void udpa_type_v1_TypedStruct_set_value(udpa_type_v1_TypedStruct *msg, struct google_protobuf_Struct* value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(12, 24), struct google_protobuf_Struct*) = value;
-}
-UPB_INLINE struct google_protobuf_Struct* udpa_type_v1_TypedStruct_mutable_value(udpa_type_v1_TypedStruct *msg, upb_arena *arena) {
-  struct google_protobuf_Struct* sub = (struct google_protobuf_Struct*)udpa_type_v1_TypedStruct_value(msg);
-  if (sub == NULL) {
-    sub = (struct google_protobuf_Struct*)_upb_msg_new(&google_protobuf_Struct_msginit, arena);
-    if (!sub) return NULL;
-    udpa_type_v1_TypedStruct_set_value(msg, sub);
-  }
-  return sub;
-}
-
-#ifdef __cplusplus
-}  /* extern "C" */
-#endif
-
-#include "upb/port_undef.inc"
-
-#endif  /* UDPA_TYPE_V1_TYPED_STRUCT_PROTO_UPB_H_ */
diff --git a/src/core/ext/upb-generated/xds/annotations/v3/status.upb.c b/src/core/ext/upb-generated/xds/annotations/v3/status.upb.c
new file mode 100644 (file)
index 0000000..49c092f
--- /dev/null
@@ -0,0 +1,58 @@
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ *     xds/annotations/v3/status.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#include <stddef.h>
+#include "upb/msg_internal.h"
+#include "xds/annotations/v3/status.upb.h"
+#include "google/protobuf/descriptor.upb.h"
+
+#include "upb/port_def.inc"
+
+static const upb_msglayout_field xds_annotations_v3_FileStatusAnnotation__fields[1] = {
+  {1, UPB_SIZE(0, 0), 0, 0, 8, _UPB_MODE_SCALAR},
+};
+
+const upb_msglayout xds_annotations_v3_FileStatusAnnotation_msginit = {
+  NULL,
+  &xds_annotations_v3_FileStatusAnnotation__fields[0],
+  UPB_SIZE(8, 8), 1, false, 1, 255,
+};
+
+static const upb_msglayout_field xds_annotations_v3_MessageStatusAnnotation__fields[1] = {
+  {1, UPB_SIZE(0, 0), 0, 0, 8, _UPB_MODE_SCALAR},
+};
+
+const upb_msglayout xds_annotations_v3_MessageStatusAnnotation_msginit = {
+  NULL,
+  &xds_annotations_v3_MessageStatusAnnotation__fields[0],
+  UPB_SIZE(8, 8), 1, false, 1, 255,
+};
+
+static const upb_msglayout_field xds_annotations_v3_FieldStatusAnnotation__fields[1] = {
+  {1, UPB_SIZE(0, 0), 0, 0, 8, _UPB_MODE_SCALAR},
+};
+
+const upb_msglayout xds_annotations_v3_FieldStatusAnnotation_msginit = {
+  NULL,
+  &xds_annotations_v3_FieldStatusAnnotation__fields[0],
+  UPB_SIZE(8, 8), 1, false, 1, 255,
+};
+
+static const upb_msglayout_field xds_annotations_v3_StatusAnnotation__fields[2] = {
+  {1, UPB_SIZE(4, 4), 0, 0, 8, _UPB_MODE_SCALAR},
+  {2, UPB_SIZE(0, 0), 0, 0, 14, _UPB_MODE_SCALAR},
+};
+
+const upb_msglayout xds_annotations_v3_StatusAnnotation_msginit = {
+  NULL,
+  &xds_annotations_v3_StatusAnnotation__fields[0],
+  UPB_SIZE(8, 8), 2, false, 2, 255,
+};
+
+#include "upb/port_undef.inc"
+
diff --git a/src/core/ext/upb-generated/xds/annotations/v3/status.upb.h b/src/core/ext/upb-generated/xds/annotations/v3/status.upb.h
new file mode 100644 (file)
index 0000000..5c46491
--- /dev/null
@@ -0,0 +1,182 @@
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ *     xds/annotations/v3/status.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#ifndef XDS_ANNOTATIONS_V3_STATUS_PROTO_UPB_H_
+#define XDS_ANNOTATIONS_V3_STATUS_PROTO_UPB_H_
+
+#include "upb/msg_internal.h"
+#include "upb/decode.h"
+#include "upb/decode_fast.h"
+#include "upb/encode.h"
+
+#include "upb/port_def.inc"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct xds_annotations_v3_FileStatusAnnotation;
+struct xds_annotations_v3_MessageStatusAnnotation;
+struct xds_annotations_v3_FieldStatusAnnotation;
+struct xds_annotations_v3_StatusAnnotation;
+typedef struct xds_annotations_v3_FileStatusAnnotation xds_annotations_v3_FileStatusAnnotation;
+typedef struct xds_annotations_v3_MessageStatusAnnotation xds_annotations_v3_MessageStatusAnnotation;
+typedef struct xds_annotations_v3_FieldStatusAnnotation xds_annotations_v3_FieldStatusAnnotation;
+typedef struct xds_annotations_v3_StatusAnnotation xds_annotations_v3_StatusAnnotation;
+extern const upb_msglayout xds_annotations_v3_FileStatusAnnotation_msginit;
+extern const upb_msglayout xds_annotations_v3_MessageStatusAnnotation_msginit;
+extern const upb_msglayout xds_annotations_v3_FieldStatusAnnotation_msginit;
+extern const upb_msglayout xds_annotations_v3_StatusAnnotation_msginit;
+
+typedef enum {
+  xds_annotations_v3_UNKNOWN = 0,
+  xds_annotations_v3_FROZEN = 1,
+  xds_annotations_v3_ACTIVE = 2,
+  xds_annotations_v3_NEXT_MAJOR_VERSION_CANDIDATE = 3
+} xds_annotations_v3_PackageVersionStatus;
+
+
+/* xds.annotations.v3.FileStatusAnnotation */
+
+UPB_INLINE xds_annotations_v3_FileStatusAnnotation *xds_annotations_v3_FileStatusAnnotation_new(upb_arena *arena) {
+  return (xds_annotations_v3_FileStatusAnnotation *)_upb_msg_new(&xds_annotations_v3_FileStatusAnnotation_msginit, arena);
+}
+UPB_INLINE xds_annotations_v3_FileStatusAnnotation *xds_annotations_v3_FileStatusAnnotation_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  xds_annotations_v3_FileStatusAnnotation *ret = xds_annotations_v3_FileStatusAnnotation_new(arena);
+  if (!ret) return NULL;
+  if (!upb_decode(buf, size, ret, &xds_annotations_v3_FileStatusAnnotation_msginit, arena)) return NULL;
+  return ret;
+}
+UPB_INLINE xds_annotations_v3_FileStatusAnnotation *xds_annotations_v3_FileStatusAnnotation_parse_ex(const char *buf, size_t size,
+                           const upb_extreg *extreg, int options,
+                           upb_arena *arena) {
+  xds_annotations_v3_FileStatusAnnotation *ret = xds_annotations_v3_FileStatusAnnotation_new(arena);
+  if (!ret) return NULL;
+  if (!_upb_decode(buf, size, ret, &xds_annotations_v3_FileStatusAnnotation_msginit, extreg, options, arena)) {
+    return NULL;
+  }
+  return ret;
+}
+UPB_INLINE char *xds_annotations_v3_FileStatusAnnotation_serialize(const xds_annotations_v3_FileStatusAnnotation *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &xds_annotations_v3_FileStatusAnnotation_msginit, arena, len);
+}
+
+UPB_INLINE bool xds_annotations_v3_FileStatusAnnotation_work_in_progress(const xds_annotations_v3_FileStatusAnnotation *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(0, 0), bool); }
+
+UPB_INLINE void xds_annotations_v3_FileStatusAnnotation_set_work_in_progress(xds_annotations_v3_FileStatusAnnotation *msg, bool value) {
+  *UPB_PTR_AT(msg, UPB_SIZE(0, 0), bool) = value;
+}
+
+/* xds.annotations.v3.MessageStatusAnnotation */
+
+UPB_INLINE xds_annotations_v3_MessageStatusAnnotation *xds_annotations_v3_MessageStatusAnnotation_new(upb_arena *arena) {
+  return (xds_annotations_v3_MessageStatusAnnotation *)_upb_msg_new(&xds_annotations_v3_MessageStatusAnnotation_msginit, arena);
+}
+UPB_INLINE xds_annotations_v3_MessageStatusAnnotation *xds_annotations_v3_MessageStatusAnnotation_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  xds_annotations_v3_MessageStatusAnnotation *ret = xds_annotations_v3_MessageStatusAnnotation_new(arena);
+  if (!ret) return NULL;
+  if (!upb_decode(buf, size, ret, &xds_annotations_v3_MessageStatusAnnotation_msginit, arena)) return NULL;
+  return ret;
+}
+UPB_INLINE xds_annotations_v3_MessageStatusAnnotation *xds_annotations_v3_MessageStatusAnnotation_parse_ex(const char *buf, size_t size,
+                           const upb_extreg *extreg, int options,
+                           upb_arena *arena) {
+  xds_annotations_v3_MessageStatusAnnotation *ret = xds_annotations_v3_MessageStatusAnnotation_new(arena);
+  if (!ret) return NULL;
+  if (!_upb_decode(buf, size, ret, &xds_annotations_v3_MessageStatusAnnotation_msginit, extreg, options, arena)) {
+    return NULL;
+  }
+  return ret;
+}
+UPB_INLINE char *xds_annotations_v3_MessageStatusAnnotation_serialize(const xds_annotations_v3_MessageStatusAnnotation *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &xds_annotations_v3_MessageStatusAnnotation_msginit, arena, len);
+}
+
+UPB_INLINE bool xds_annotations_v3_MessageStatusAnnotation_work_in_progress(const xds_annotations_v3_MessageStatusAnnotation *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(0, 0), bool); }
+
+UPB_INLINE void xds_annotations_v3_MessageStatusAnnotation_set_work_in_progress(xds_annotations_v3_MessageStatusAnnotation *msg, bool value) {
+  *UPB_PTR_AT(msg, UPB_SIZE(0, 0), bool) = value;
+}
+
+/* xds.annotations.v3.FieldStatusAnnotation */
+
+UPB_INLINE xds_annotations_v3_FieldStatusAnnotation *xds_annotations_v3_FieldStatusAnnotation_new(upb_arena *arena) {
+  return (xds_annotations_v3_FieldStatusAnnotation *)_upb_msg_new(&xds_annotations_v3_FieldStatusAnnotation_msginit, arena);
+}
+UPB_INLINE xds_annotations_v3_FieldStatusAnnotation *xds_annotations_v3_FieldStatusAnnotation_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  xds_annotations_v3_FieldStatusAnnotation *ret = xds_annotations_v3_FieldStatusAnnotation_new(arena);
+  if (!ret) return NULL;
+  if (!upb_decode(buf, size, ret, &xds_annotations_v3_FieldStatusAnnotation_msginit, arena)) return NULL;
+  return ret;
+}
+UPB_INLINE xds_annotations_v3_FieldStatusAnnotation *xds_annotations_v3_FieldStatusAnnotation_parse_ex(const char *buf, size_t size,
+                           const upb_extreg *extreg, int options,
+                           upb_arena *arena) {
+  xds_annotations_v3_FieldStatusAnnotation *ret = xds_annotations_v3_FieldStatusAnnotation_new(arena);
+  if (!ret) return NULL;
+  if (!_upb_decode(buf, size, ret, &xds_annotations_v3_FieldStatusAnnotation_msginit, extreg, options, arena)) {
+    return NULL;
+  }
+  return ret;
+}
+UPB_INLINE char *xds_annotations_v3_FieldStatusAnnotation_serialize(const xds_annotations_v3_FieldStatusAnnotation *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &xds_annotations_v3_FieldStatusAnnotation_msginit, arena, len);
+}
+
+UPB_INLINE bool xds_annotations_v3_FieldStatusAnnotation_work_in_progress(const xds_annotations_v3_FieldStatusAnnotation *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(0, 0), bool); }
+
+UPB_INLINE void xds_annotations_v3_FieldStatusAnnotation_set_work_in_progress(xds_annotations_v3_FieldStatusAnnotation *msg, bool value) {
+  *UPB_PTR_AT(msg, UPB_SIZE(0, 0), bool) = value;
+}
+
+/* xds.annotations.v3.StatusAnnotation */
+
+UPB_INLINE xds_annotations_v3_StatusAnnotation *xds_annotations_v3_StatusAnnotation_new(upb_arena *arena) {
+  return (xds_annotations_v3_StatusAnnotation *)_upb_msg_new(&xds_annotations_v3_StatusAnnotation_msginit, arena);
+}
+UPB_INLINE xds_annotations_v3_StatusAnnotation *xds_annotations_v3_StatusAnnotation_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  xds_annotations_v3_StatusAnnotation *ret = xds_annotations_v3_StatusAnnotation_new(arena);
+  if (!ret) return NULL;
+  if (!upb_decode(buf, size, ret, &xds_annotations_v3_StatusAnnotation_msginit, arena)) return NULL;
+  return ret;
+}
+UPB_INLINE xds_annotations_v3_StatusAnnotation *xds_annotations_v3_StatusAnnotation_parse_ex(const char *buf, size_t size,
+                           const upb_extreg *extreg, int options,
+                           upb_arena *arena) {
+  xds_annotations_v3_StatusAnnotation *ret = xds_annotations_v3_StatusAnnotation_new(arena);
+  if (!ret) return NULL;
+  if (!_upb_decode(buf, size, ret, &xds_annotations_v3_StatusAnnotation_msginit, extreg, options, arena)) {
+    return NULL;
+  }
+  return ret;
+}
+UPB_INLINE char *xds_annotations_v3_StatusAnnotation_serialize(const xds_annotations_v3_StatusAnnotation *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &xds_annotations_v3_StatusAnnotation_msginit, arena, len);
+}
+
+UPB_INLINE bool xds_annotations_v3_StatusAnnotation_work_in_progress(const xds_annotations_v3_StatusAnnotation *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), bool); }
+UPB_INLINE int32_t xds_annotations_v3_StatusAnnotation_package_version_status(const xds_annotations_v3_StatusAnnotation *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(0, 0), int32_t); }
+
+UPB_INLINE void xds_annotations_v3_StatusAnnotation_set_work_in_progress(xds_annotations_v3_StatusAnnotation *msg, bool value) {
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 4), bool) = value;
+}
+UPB_INLINE void xds_annotations_v3_StatusAnnotation_set_package_version_status(xds_annotations_v3_StatusAnnotation *msg, int32_t value) {
+  *UPB_PTR_AT(msg, UPB_SIZE(0, 0), int32_t) = value;
+}
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#include "upb/port_undef.inc"
+
+#endif  /* XDS_ANNOTATIONS_V3_STATUS_PROTO_UPB_H_ */
index de06e07..b246003 100644 (file)
@@ -9,7 +9,7 @@
 #include <stddef.h>
 #include "upb/msg_internal.h"
 #include "xds/core/v3/authority.upb.h"
-#include "udpa/annotations/status.upb.h"
+#include "xds/annotations/v3/status.upb.h"
 #include "validate/validate.upb.h"
 
 #include "upb/port_def.inc"
index e4584e4..690762a 100644 (file)
@@ -10,7 +10,7 @@
 #include "upb/msg_internal.h"
 #include "xds/core/v3/collection_entry.upb.h"
 #include "google/protobuf/any.upb.h"
-#include "udpa/annotations/status.upb.h"
+#include "xds/annotations/v3/status.upb.h"
 #include "xds/core/v3/resource_locator.upb.h"
 #include "validate/validate.upb.h"
 
index b78d54c..f4aff2f 100644 (file)
@@ -9,7 +9,7 @@
 #include <stddef.h>
 #include "upb/msg_internal.h"
 #include "xds/core/v3/context_params.upb.h"
-#include "udpa/annotations/status.upb.h"
+#include "xds/annotations/v3/status.upb.h"
 
 #include "upb/port_def.inc"
 
index c3fa6ab..6ed2adc 100644 (file)
@@ -10,7 +10,7 @@
 #include "upb/msg_internal.h"
 #include "xds/core/v3/resource.upb.h"
 #include "google/protobuf/any.upb.h"
-#include "udpa/annotations/status.upb.h"
+#include "xds/annotations/v3/status.upb.h"
 #include "xds/core/v3/resource_name.upb.h"
 
 #include "upb/port_def.inc"
index 575e556..f4abf5c 100644 (file)
@@ -9,7 +9,7 @@
 #include <stddef.h>
 #include "upb/msg_internal.h"
 #include "xds/core/v3/resource_locator.upb.h"
-#include "udpa/annotations/status.upb.h"
+#include "xds/annotations/v3/status.upb.h"
 #include "xds/core/v3/context_params.upb.h"
 #include "validate/validate.upb.h"
 
index f0bf9b3..4661675 100644 (file)
@@ -9,7 +9,7 @@
 #include <stddef.h>
 #include "upb/msg_internal.h"
 #include "xds/core/v3/resource_name.upb.h"
-#include "udpa/annotations/status.upb.h"
+#include "xds/annotations/v3/status.upb.h"
 #include "xds/core/v3/context_params.upb.h"
 #include "validate/validate.upb.h"
 
diff --git a/src/core/ext/upb-generated/xds/data/orca/v3/orca_load_report.upb.c b/src/core/ext/upb-generated/xds/data/orca/v3/orca_load_report.upb.c
new file mode 100644 (file)
index 0000000..c78073c
--- /dev/null
@@ -0,0 +1,58 @@
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ *     xds/data/orca/v3/orca_load_report.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#include <stddef.h>
+#include "upb/msg_internal.h"
+#include "xds/data/orca/v3/orca_load_report.upb.h"
+#include "validate/validate.upb.h"
+
+#include "upb/port_def.inc"
+
+static const upb_msglayout *const xds_data_orca_v3_OrcaLoadReport_submsgs[2] = {
+  &xds_data_orca_v3_OrcaLoadReport_RequestCostEntry_msginit,
+  &xds_data_orca_v3_OrcaLoadReport_UtilizationEntry_msginit,
+};
+
+static const upb_msglayout_field xds_data_orca_v3_OrcaLoadReport__fields[5] = {
+  {1, UPB_SIZE(0, 0), 0, 0, 1, _UPB_MODE_SCALAR},
+  {2, UPB_SIZE(8, 8), 0, 0, 1, _UPB_MODE_SCALAR},
+  {3, UPB_SIZE(16, 16), 0, 0, 4, _UPB_MODE_SCALAR},
+  {4, UPB_SIZE(24, 24), 0, 0, 11, _UPB_MODE_MAP},
+  {5, UPB_SIZE(28, 32), 0, 1, 11, _UPB_MODE_MAP},
+};
+
+const upb_msglayout xds_data_orca_v3_OrcaLoadReport_msginit = {
+  &xds_data_orca_v3_OrcaLoadReport_submsgs[0],
+  &xds_data_orca_v3_OrcaLoadReport__fields[0],
+  UPB_SIZE(32, 40), 5, false, 5, 255,
+};
+
+static const upb_msglayout_field xds_data_orca_v3_OrcaLoadReport_RequestCostEntry__fields[2] = {
+  {1, UPB_SIZE(0, 0), 0, 0, 9, _UPB_MODE_SCALAR},
+  {2, UPB_SIZE(8, 16), 0, 0, 1, _UPB_MODE_SCALAR},
+};
+
+const upb_msglayout xds_data_orca_v3_OrcaLoadReport_RequestCostEntry_msginit = {
+  NULL,
+  &xds_data_orca_v3_OrcaLoadReport_RequestCostEntry__fields[0],
+  UPB_SIZE(16, 32), 2, false, 2, 255,
+};
+
+static const upb_msglayout_field xds_data_orca_v3_OrcaLoadReport_UtilizationEntry__fields[2] = {
+  {1, UPB_SIZE(0, 0), 0, 0, 9, _UPB_MODE_SCALAR},
+  {2, UPB_SIZE(8, 16), 0, 0, 1, _UPB_MODE_SCALAR},
+};
+
+const upb_msglayout xds_data_orca_v3_OrcaLoadReport_UtilizationEntry_msginit = {
+  NULL,
+  &xds_data_orca_v3_OrcaLoadReport_UtilizationEntry__fields[0],
+  UPB_SIZE(16, 32), 2, false, 2, 255,
+};
+
+#include "upb/port_undef.inc"
+
diff --git a/src/core/ext/upb-generated/xds/data/orca/v3/orca_load_report.upb.h b/src/core/ext/upb-generated/xds/data/orca/v3/orca_load_report.upb.h
new file mode 100644 (file)
index 0000000..2dcb8b5
--- /dev/null
@@ -0,0 +1,130 @@
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ *     xds/data/orca/v3/orca_load_report.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#ifndef XDS_DATA_ORCA_V3_ORCA_LOAD_REPORT_PROTO_UPB_H_
+#define XDS_DATA_ORCA_V3_ORCA_LOAD_REPORT_PROTO_UPB_H_
+
+#include "upb/msg_internal.h"
+#include "upb/decode.h"
+#include "upb/decode_fast.h"
+#include "upb/encode.h"
+
+#include "upb/port_def.inc"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct xds_data_orca_v3_OrcaLoadReport;
+struct xds_data_orca_v3_OrcaLoadReport_RequestCostEntry;
+struct xds_data_orca_v3_OrcaLoadReport_UtilizationEntry;
+typedef struct xds_data_orca_v3_OrcaLoadReport xds_data_orca_v3_OrcaLoadReport;
+typedef struct xds_data_orca_v3_OrcaLoadReport_RequestCostEntry xds_data_orca_v3_OrcaLoadReport_RequestCostEntry;
+typedef struct xds_data_orca_v3_OrcaLoadReport_UtilizationEntry xds_data_orca_v3_OrcaLoadReport_UtilizationEntry;
+extern const upb_msglayout xds_data_orca_v3_OrcaLoadReport_msginit;
+extern const upb_msglayout xds_data_orca_v3_OrcaLoadReport_RequestCostEntry_msginit;
+extern const upb_msglayout xds_data_orca_v3_OrcaLoadReport_UtilizationEntry_msginit;
+
+
+/* xds.data.orca.v3.OrcaLoadReport */
+
+UPB_INLINE xds_data_orca_v3_OrcaLoadReport *xds_data_orca_v3_OrcaLoadReport_new(upb_arena *arena) {
+  return (xds_data_orca_v3_OrcaLoadReport *)_upb_msg_new(&xds_data_orca_v3_OrcaLoadReport_msginit, arena);
+}
+UPB_INLINE xds_data_orca_v3_OrcaLoadReport *xds_data_orca_v3_OrcaLoadReport_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  xds_data_orca_v3_OrcaLoadReport *ret = xds_data_orca_v3_OrcaLoadReport_new(arena);
+  if (!ret) return NULL;
+  if (!upb_decode(buf, size, ret, &xds_data_orca_v3_OrcaLoadReport_msginit, arena)) return NULL;
+  return ret;
+}
+UPB_INLINE xds_data_orca_v3_OrcaLoadReport *xds_data_orca_v3_OrcaLoadReport_parse_ex(const char *buf, size_t size,
+                           const upb_extreg *extreg, int options,
+                           upb_arena *arena) {
+  xds_data_orca_v3_OrcaLoadReport *ret = xds_data_orca_v3_OrcaLoadReport_new(arena);
+  if (!ret) return NULL;
+  if (!_upb_decode(buf, size, ret, &xds_data_orca_v3_OrcaLoadReport_msginit, extreg, options, arena)) {
+    return NULL;
+  }
+  return ret;
+}
+UPB_INLINE char *xds_data_orca_v3_OrcaLoadReport_serialize(const xds_data_orca_v3_OrcaLoadReport *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &xds_data_orca_v3_OrcaLoadReport_msginit, arena, len);
+}
+
+UPB_INLINE double xds_data_orca_v3_OrcaLoadReport_cpu_utilization(const xds_data_orca_v3_OrcaLoadReport *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(0, 0), double); }
+UPB_INLINE double xds_data_orca_v3_OrcaLoadReport_mem_utilization(const xds_data_orca_v3_OrcaLoadReport *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), double); }
+UPB_INLINE uint64_t xds_data_orca_v3_OrcaLoadReport_rps(const xds_data_orca_v3_OrcaLoadReport *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), uint64_t); }
+UPB_INLINE bool xds_data_orca_v3_OrcaLoadReport_has_request_cost(const xds_data_orca_v3_OrcaLoadReport *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(24, 24)); }
+UPB_INLINE size_t xds_data_orca_v3_OrcaLoadReport_request_cost_size(const xds_data_orca_v3_OrcaLoadReport *msg) {return _upb_msg_map_size(msg, UPB_SIZE(24, 24)); }
+UPB_INLINE bool xds_data_orca_v3_OrcaLoadReport_request_cost_get(const xds_data_orca_v3_OrcaLoadReport *msg, upb_strview key, double *val) { return _upb_msg_map_get(msg, UPB_SIZE(24, 24), &key, 0, val, sizeof(*val)); }
+UPB_INLINE const xds_data_orca_v3_OrcaLoadReport_RequestCostEntry* xds_data_orca_v3_OrcaLoadReport_request_cost_next(const xds_data_orca_v3_OrcaLoadReport *msg, size_t* iter) { return (const xds_data_orca_v3_OrcaLoadReport_RequestCostEntry*)_upb_msg_map_next(msg, UPB_SIZE(24, 24), iter); }
+UPB_INLINE bool xds_data_orca_v3_OrcaLoadReport_has_utilization(const xds_data_orca_v3_OrcaLoadReport *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(28, 32)); }
+UPB_INLINE size_t xds_data_orca_v3_OrcaLoadReport_utilization_size(const xds_data_orca_v3_OrcaLoadReport *msg) {return _upb_msg_map_size(msg, UPB_SIZE(28, 32)); }
+UPB_INLINE bool xds_data_orca_v3_OrcaLoadReport_utilization_get(const xds_data_orca_v3_OrcaLoadReport *msg, upb_strview key, double *val) { return _upb_msg_map_get(msg, UPB_SIZE(28, 32), &key, 0, val, sizeof(*val)); }
+UPB_INLINE const xds_data_orca_v3_OrcaLoadReport_UtilizationEntry* xds_data_orca_v3_OrcaLoadReport_utilization_next(const xds_data_orca_v3_OrcaLoadReport *msg, size_t* iter) { return (const xds_data_orca_v3_OrcaLoadReport_UtilizationEntry*)_upb_msg_map_next(msg, UPB_SIZE(28, 32), iter); }
+
+UPB_INLINE void xds_data_orca_v3_OrcaLoadReport_set_cpu_utilization(xds_data_orca_v3_OrcaLoadReport *msg, double value) {
+  *UPB_PTR_AT(msg, UPB_SIZE(0, 0), double) = value;
+}
+UPB_INLINE void xds_data_orca_v3_OrcaLoadReport_set_mem_utilization(xds_data_orca_v3_OrcaLoadReport *msg, double value) {
+  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), double) = value;
+}
+UPB_INLINE void xds_data_orca_v3_OrcaLoadReport_set_rps(xds_data_orca_v3_OrcaLoadReport *msg, uint64_t value) {
+  *UPB_PTR_AT(msg, UPB_SIZE(16, 16), uint64_t) = value;
+}
+UPB_INLINE void xds_data_orca_v3_OrcaLoadReport_request_cost_clear(xds_data_orca_v3_OrcaLoadReport *msg) { _upb_msg_map_clear(msg, UPB_SIZE(24, 24)); }
+UPB_INLINE bool xds_data_orca_v3_OrcaLoadReport_request_cost_set(xds_data_orca_v3_OrcaLoadReport *msg, upb_strview key, double val, upb_arena *a) { return _upb_msg_map_set(msg, UPB_SIZE(24, 24), &key, 0, &val, sizeof(val), a); }
+UPB_INLINE bool xds_data_orca_v3_OrcaLoadReport_request_cost_delete(xds_data_orca_v3_OrcaLoadReport *msg, upb_strview key) { return _upb_msg_map_delete(msg, UPB_SIZE(24, 24), &key, 0); }
+UPB_INLINE xds_data_orca_v3_OrcaLoadReport_RequestCostEntry* xds_data_orca_v3_OrcaLoadReport_request_cost_nextmutable(xds_data_orca_v3_OrcaLoadReport *msg, size_t* iter) { return (xds_data_orca_v3_OrcaLoadReport_RequestCostEntry*)_upb_msg_map_next(msg, UPB_SIZE(24, 24), iter); }
+UPB_INLINE void xds_data_orca_v3_OrcaLoadReport_utilization_clear(xds_data_orca_v3_OrcaLoadReport *msg) { _upb_msg_map_clear(msg, UPB_SIZE(28, 32)); }
+UPB_INLINE bool xds_data_orca_v3_OrcaLoadReport_utilization_set(xds_data_orca_v3_OrcaLoadReport *msg, upb_strview key, double val, upb_arena *a) { return _upb_msg_map_set(msg, UPB_SIZE(28, 32), &key, 0, &val, sizeof(val), a); }
+UPB_INLINE bool xds_data_orca_v3_OrcaLoadReport_utilization_delete(xds_data_orca_v3_OrcaLoadReport *msg, upb_strview key) { return _upb_msg_map_delete(msg, UPB_SIZE(28, 32), &key, 0); }
+UPB_INLINE xds_data_orca_v3_OrcaLoadReport_UtilizationEntry* xds_data_orca_v3_OrcaLoadReport_utilization_nextmutable(xds_data_orca_v3_OrcaLoadReport *msg, size_t* iter) { return (xds_data_orca_v3_OrcaLoadReport_UtilizationEntry*)_upb_msg_map_next(msg, UPB_SIZE(28, 32), iter); }
+
+/* xds.data.orca.v3.OrcaLoadReport.RequestCostEntry */
+
+UPB_INLINE upb_strview xds_data_orca_v3_OrcaLoadReport_RequestCostEntry_key(const xds_data_orca_v3_OrcaLoadReport_RequestCostEntry *msg) {
+  upb_strview ret;
+  _upb_msg_map_key(msg, &ret, 0);
+  return ret;
+}
+UPB_INLINE double xds_data_orca_v3_OrcaLoadReport_RequestCostEntry_value(const xds_data_orca_v3_OrcaLoadReport_RequestCostEntry *msg) {
+  double ret;
+  _upb_msg_map_value(msg, &ret, sizeof(ret));
+  return ret;
+}
+
+UPB_INLINE void xds_data_orca_v3_OrcaLoadReport_RequestCostEntry_set_value(xds_data_orca_v3_OrcaLoadReport_RequestCostEntry *msg, double value) {
+  _upb_msg_map_set_value(msg, &value, sizeof(double));
+}
+
+/* xds.data.orca.v3.OrcaLoadReport.UtilizationEntry */
+
+UPB_INLINE upb_strview xds_data_orca_v3_OrcaLoadReport_UtilizationEntry_key(const xds_data_orca_v3_OrcaLoadReport_UtilizationEntry *msg) {
+  upb_strview ret;
+  _upb_msg_map_key(msg, &ret, 0);
+  return ret;
+}
+UPB_INLINE double xds_data_orca_v3_OrcaLoadReport_UtilizationEntry_value(const xds_data_orca_v3_OrcaLoadReport_UtilizationEntry *msg) {
+  double ret;
+  _upb_msg_map_value(msg, &ret, sizeof(ret));
+  return ret;
+}
+
+UPB_INLINE void xds_data_orca_v3_OrcaLoadReport_UtilizationEntry_set_value(xds_data_orca_v3_OrcaLoadReport_UtilizationEntry *msg, double value) {
+  _upb_msg_map_set_value(msg, &value, sizeof(double));
+}
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#include "upb/port_undef.inc"
+
+#endif  /* XDS_DATA_ORCA_V3_ORCA_LOAD_REPORT_PROTO_UPB_H_ */
diff --git a/src/core/ext/upb-generated/xds/type/v3/typed_struct.upb.c b/src/core/ext/upb-generated/xds/type/v3/typed_struct.upb.c
new file mode 100644 (file)
index 0000000..5b1f309
--- /dev/null
@@ -0,0 +1,33 @@
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ *     xds/type/v3/typed_struct.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#include <stddef.h>
+#include "upb/msg_internal.h"
+#include "xds/type/v3/typed_struct.upb.h"
+#include "validate/validate.upb.h"
+#include "google/protobuf/struct.upb.h"
+
+#include "upb/port_def.inc"
+
+static const upb_msglayout *const xds_type_v3_TypedStruct_submsgs[1] = {
+  &google_protobuf_Struct_msginit,
+};
+
+static const upb_msglayout_field xds_type_v3_TypedStruct__fields[2] = {
+  {1, UPB_SIZE(4, 8), 0, 0, 9, _UPB_MODE_SCALAR},
+  {2, UPB_SIZE(12, 24), 1, 0, 11, _UPB_MODE_SCALAR},
+};
+
+const upb_msglayout xds_type_v3_TypedStruct_msginit = {
+  &xds_type_v3_TypedStruct_submsgs[0],
+  &xds_type_v3_TypedStruct__fields[0],
+  UPB_SIZE(16, 32), 2, false, 2, 255,
+};
+
+#include "upb/port_undef.inc"
+
diff --git a/src/core/ext/upb-generated/xds/type/v3/typed_struct.upb.h b/src/core/ext/upb-generated/xds/type/v3/typed_struct.upb.h
new file mode 100644 (file)
index 0000000..89299af
--- /dev/null
@@ -0,0 +1,83 @@
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ *     xds/type/v3/typed_struct.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#ifndef XDS_TYPE_V3_TYPED_STRUCT_PROTO_UPB_H_
+#define XDS_TYPE_V3_TYPED_STRUCT_PROTO_UPB_H_
+
+#include "upb/msg_internal.h"
+#include "upb/decode.h"
+#include "upb/decode_fast.h"
+#include "upb/encode.h"
+
+#include "upb/port_def.inc"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct xds_type_v3_TypedStruct;
+typedef struct xds_type_v3_TypedStruct xds_type_v3_TypedStruct;
+extern const upb_msglayout xds_type_v3_TypedStruct_msginit;
+struct google_protobuf_Struct;
+extern const upb_msglayout google_protobuf_Struct_msginit;
+
+
+/* xds.type.v3.TypedStruct */
+
+UPB_INLINE xds_type_v3_TypedStruct *xds_type_v3_TypedStruct_new(upb_arena *arena) {
+  return (xds_type_v3_TypedStruct *)_upb_msg_new(&xds_type_v3_TypedStruct_msginit, arena);
+}
+UPB_INLINE xds_type_v3_TypedStruct *xds_type_v3_TypedStruct_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  xds_type_v3_TypedStruct *ret = xds_type_v3_TypedStruct_new(arena);
+  if (!ret) return NULL;
+  if (!upb_decode(buf, size, ret, &xds_type_v3_TypedStruct_msginit, arena)) return NULL;
+  return ret;
+}
+UPB_INLINE xds_type_v3_TypedStruct *xds_type_v3_TypedStruct_parse_ex(const char *buf, size_t size,
+                           const upb_extreg *extreg, int options,
+                           upb_arena *arena) {
+  xds_type_v3_TypedStruct *ret = xds_type_v3_TypedStruct_new(arena);
+  if (!ret) return NULL;
+  if (!_upb_decode(buf, size, ret, &xds_type_v3_TypedStruct_msginit, extreg, options, arena)) {
+    return NULL;
+  }
+  return ret;
+}
+UPB_INLINE char *xds_type_v3_TypedStruct_serialize(const xds_type_v3_TypedStruct *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &xds_type_v3_TypedStruct_msginit, arena, len);
+}
+
+UPB_INLINE upb_strview xds_type_v3_TypedStruct_type_url(const xds_type_v3_TypedStruct *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
+UPB_INLINE bool xds_type_v3_TypedStruct_has_value(const xds_type_v3_TypedStruct *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE const struct google_protobuf_Struct* xds_type_v3_TypedStruct_value(const xds_type_v3_TypedStruct *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const struct google_protobuf_Struct*); }
+
+UPB_INLINE void xds_type_v3_TypedStruct_set_type_url(xds_type_v3_TypedStruct *msg, upb_strview value) {
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
+}
+UPB_INLINE void xds_type_v3_TypedStruct_set_value(xds_type_v3_TypedStruct *msg, struct google_protobuf_Struct* value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(12, 24), struct google_protobuf_Struct*) = value;
+}
+UPB_INLINE struct google_protobuf_Struct* xds_type_v3_TypedStruct_mutable_value(xds_type_v3_TypedStruct *msg, upb_arena *arena) {
+  struct google_protobuf_Struct* sub = (struct google_protobuf_Struct*)xds_type_v3_TypedStruct_value(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_Struct*)_upb_msg_new(&google_protobuf_Struct_msginit, arena);
+    if (!sub) return NULL;
+    xds_type_v3_TypedStruct_set_value(msg, sub);
+  }
+  return sub;
+}
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#include "upb/port_undef.inc"
+
+#endif  /* XDS_TYPE_V3_TYPED_STRUCT_PROTO_UPB_H_ */
index 9068d1f..c15cf2f 100644 (file)
@@ -39,6 +39,8 @@ extern const upb_msglayout envoy_config_cluster_v3_Cluster_CustomClusterType_msg
 extern const upb_msglayout envoy_config_cluster_v3_Cluster_EdsClusterConfig_msginit;
 extern const upb_msglayout envoy_config_cluster_v3_Cluster_LbSubsetConfig_msginit;
 extern const upb_msglayout envoy_config_cluster_v3_Cluster_LbSubsetConfig_LbSubsetSelector_msginit;
+extern const upb_msglayout envoy_config_cluster_v3_Cluster_SlowStartConfig_msginit;
+extern const upb_msglayout envoy_config_cluster_v3_Cluster_RoundRobinLbConfig_msginit;
 extern const upb_msglayout envoy_config_cluster_v3_Cluster_LeastRequestLbConfig_msginit;
 extern const upb_msglayout envoy_config_cluster_v3_Cluster_RingHashLbConfig_msginit;
 extern const upb_msglayout envoy_config_cluster_v3_Cluster_MaglevLbConfig_msginit;
@@ -56,7 +58,7 @@ extern const upb_msglayout envoy_config_cluster_v3_UpstreamBindConfig_msginit;
 extern const upb_msglayout envoy_config_cluster_v3_UpstreamConnectionOptions_msginit;
 extern const upb_msglayout envoy_config_cluster_v3_TrackClusterStats_msginit;
 
-static const upb_msglayout *layouts[23] = {
+static const upb_msglayout *layouts[25] = {
   &envoy_config_cluster_v3_ClusterCollection_msginit,
   &envoy_config_cluster_v3_Cluster_msginit,
   &envoy_config_cluster_v3_Cluster_TransportSocketMatch_msginit,
@@ -64,6 +66,8 @@ static const upb_msglayout *layouts[23] = {
   &envoy_config_cluster_v3_Cluster_EdsClusterConfig_msginit,
   &envoy_config_cluster_v3_Cluster_LbSubsetConfig_msginit,
   &envoy_config_cluster_v3_Cluster_LbSubsetConfig_LbSubsetSelector_msginit,
+  &envoy_config_cluster_v3_Cluster_SlowStartConfig_msginit,
+  &envoy_config_cluster_v3_Cluster_RoundRobinLbConfig_msginit,
   &envoy_config_cluster_v3_Cluster_LeastRequestLbConfig_msginit,
   &envoy_config_cluster_v3_Cluster_RingHashLbConfig_msginit,
   &envoy_config_cluster_v3_Cluster_MaglevLbConfig_msginit,
@@ -82,7 +86,7 @@ static const upb_msglayout *layouts[23] = {
   &envoy_config_cluster_v3_TrackClusterStats_msginit,
 };
 
-static const char descriptor[11317] = {'\n', '%', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'c', 'l', 'u', 's', 't', 'e', 'r', '/', 'v', '3', 
+static const char descriptor[11811] = {'\n', '%', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'c', 'l', 'u', 's', 't', 'e', 'r', '/', 'v', '3', 
 '/', 'c', 'l', 'u', 's', 't', 'e', 'r', '.', 'p', 'r', 'o', 't', 'o', '\022', '\027', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 
 'f', 'i', 'g', '.', 'c', 'l', 'u', 's', 't', 'e', 'r', '.', 'v', '3', '\032', '-', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 
 'f', 'i', 'g', '/', 'c', 'l', 'u', 's', 't', 'e', 'r', '/', 'v', '3', '/', 'c', 'i', 'r', 'c', 'u', 'i', 't', '_', 'b', 'r', 
@@ -120,7 +124,7 @@ static const char descriptor[11317] = {'\n', '%', 'e', 'n', 'v', 'o', 'y', '/',
 'e', '.', 'p', 'r', 'o', 't', 'o', '\"', 'K', '\n', '\021', 'C', 'l', 'u', 's', 't', 'e', 'r', 'C', 'o', 'l', 'l', 'e', 'c', 't', 
 'i', 'o', 'n', '\022', '6', '\n', '\007', 'e', 'n', 't', 'r', 'i', 'e', 's', '\030', '\001', ' ', '\001', '(', '\013', '2', '\034', '.', 'x', 'd', 
 's', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'C', 'o', 'l', 'l', 'e', 'c', 't', 'i', 'o', 'n', 'E', 'n', 't', 'r', 'y', 
-'R', '\007', 'e', 'n', 't', 'r', 'i', 'e', 's', '\"', '\276', 'J', '\n', '\007', 'C', 'l', 'u', 's', 't', 'e', 'r', '\022', 'o', '\n', '\030', 
+'R', '\007', 'e', 'n', 't', 'r', 'i', 'e', 's', '\"', '\254', 'N', '\n', '\007', 'C', 'l', 'u', 's', 't', 'e', 'r', '\022', 'o', '\n', '\030', 
 't', 'r', 'a', 'n', 's', 'p', 'o', 'r', 't', '_', 's', 'o', 'c', 'k', 'e', 't', '_', 'm', 'a', 't', 'c', 'h', 'e', 's', '\030', 
 '+', ' ', '\003', '(', '\013', '2', '5', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'l', 'u', 's', 
 't', 'e', 'r', '.', 'v', '3', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', '.', 'T', 'r', 'a', 'n', 's', 'p', 'o', 'r', 't', 'S', 
@@ -250,291 +254,311 @@ static const char descriptor[11317] = {'\n', '%', 'e', 'n', 'v', 'o', 'y', '/',
 '\013', '2', '5', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'l', 'u', 's', 't', 'e', 'r', '.', 
 'v', '3', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', '.', 'L', 'e', 'a', 's', 't', 'R', 'e', 'q', 'u', 'e', 's', 't', 'L', 'b', 
 'C', 'o', 'n', 'f', 'i', 'g', 'H', '\001', 'R', '\024', 'l', 'e', 'a', 's', 't', 'R', 'e', 'q', 'u', 'e', 's', 't', 'L', 'b', 'C', 
-'o', 'n', 'f', 'i', 'g', '\022', 'Y', '\n', '\020', 'c', 'o', 'm', 'm', 'o', 'n', '_', 'l', 'b', '_', 'c', 'o', 'n', 'f', 'i', 'g', 
-'\030', '\033', ' ', '\001', '(', '\013', '2', '/', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'l', 'u', 
-'s', 't', 'e', 'r', '.', 'v', '3', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', '.', 'C', 'o', 'm', 'm', 'o', 'n', 'L', 'b', 'C', 
-'o', 'n', 'f', 'i', 'g', 'R', '\016', 'c', 'o', 'm', 'm', 'o', 'n', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', '\022', 'P', '\n', '\020', 
-'t', 'r', 'a', 'n', 's', 'p', 'o', 'r', 't', '_', 's', 'o', 'c', 'k', 'e', 't', '\030', '\030', ' ', '\001', '(', '\013', '2', '%', '.', 
-'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'T', 'r', 'a', 'n', 
-'s', 'p', 'o', 'r', 't', 'S', 'o', 'c', 'k', 'e', 't', 'R', '\017', 't', 'r', 'a', 'n', 's', 'p', 'o', 'r', 't', 'S', 'o', 'c', 
-'k', 'e', 't', '\022', ':', '\n', '\010', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', '\030', '\031', ' ', '\001', '(', '\013', '2', '\036', '.', 'e', 
-'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'M', 'e', 't', 'a', 'd', 
-'a', 't', 'a', 'R', '\010', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', '\022', 'u', '\n', '\022', 'p', 'r', 'o', 't', 'o', 'c', 'o', 'l', 
-'_', 's', 'e', 'l', 'e', 'c', 't', 'i', 'o', 'n', '\030', '\032', ' ', '\001', '(', '\016', '2', '9', '.', 'e', 'n', 'v', 'o', 'y', '.', 
+'o', 'n', 'f', 'i', 'g', '\022', 'h', '\n', '\025', 'r', 'o', 'u', 'n', 'd', '_', 'r', 'o', 'b', 'i', 'n', '_', 'l', 'b', '_', 'c', 
+'o', 'n', 'f', 'i', 'g', '\030', '8', ' ', '\001', '(', '\013', '2', '3', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 
+'g', '.', 'c', 'l', 'u', 's', 't', 'e', 'r', '.', 'v', '3', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', '.', 'R', 'o', 'u', 'n', 
+'d', 'R', 'o', 'b', 'i', 'n', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', 'H', '\001', 'R', '\022', 'r', 'o', 'u', 'n', 'd', 'R', 'o', 
+'b', 'i', 'n', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', '\022', 'Y', '\n', '\020', 'c', 'o', 'm', 'm', 'o', 'n', '_', 'l', 'b', '_', 
+'c', 'o', 'n', 'f', 'i', 'g', '\030', '\033', ' ', '\001', '(', '\013', '2', '/', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 
+'i', 'g', '.', 'c', 'l', 'u', 's', 't', 'e', 'r', '.', 'v', '3', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', '.', 'C', 'o', 'm', 
+'m', 'o', 'n', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', 'R', '\016', 'c', 'o', 'm', 'm', 'o', 'n', 'L', 'b', 'C', 'o', 'n', 'f', 
+'i', 'g', '\022', 'P', '\n', '\020', 't', 'r', 'a', 'n', 's', 'p', 'o', 'r', 't', '_', 's', 'o', 'c', 'k', 'e', 't', '\030', '\030', ' ', 
+'\001', '(', '\013', '2', '%', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', 
+'3', '.', 'T', 'r', 'a', 'n', 's', 'p', 'o', 'r', 't', 'S', 'o', 'c', 'k', 'e', 't', 'R', '\017', 't', 'r', 'a', 'n', 's', 'p', 
+'o', 'r', 't', 'S', 'o', 'c', 'k', 'e', 't', '\022', ':', '\n', '\010', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', '\030', '\031', ' ', '\001', 
+'(', '\013', '2', '\036', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', 
+'.', 'M', 'e', 't', 'a', 'd', 'a', 't', 'a', 'R', '\010', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', '\022', 'u', '\n', '\022', 'p', 'r', 
+'o', 't', 'o', 'c', 'o', 'l', '_', 's', 'e', 'l', 'e', 'c', 't', 'i', 'o', 'n', '\030', '\032', ' ', '\001', '(', '\016', '2', '9', '.', 
+'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'l', 'u', 's', 't', 'e', 'r', '.', 'v', '3', '.', 'C', 
+'l', 'u', 's', 't', 'e', 'r', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'S', 'e', 'l', 
+'e', 'c', 't', 'i', 'o', 'n', 'B', '\013', '\030', '\001', '\222', '\307', '\206', '\330', '\004', '\003', '3', '.', '0', 'R', '\021', 'p', 'r', 'o', 't', 
+'o', 'c', 'o', 'l', 'S', 'e', 'l', 'e', 'c', 't', 'i', 'o', 'n', '\022', 'r', '\n', '\033', 'u', 'p', 's', 't', 'r', 'e', 'a', 'm', 
+'_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '_', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\036', ' ', '\001', '(', '\013', 
+'2', '2', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'l', 'u', 's', 't', 'e', 'r', '.', 'v', 
+'3', '.', 'U', 'p', 's', 't', 'r', 'e', 'a', 'm', 'C', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', 'O', 'p', 't', 'i', 'o', 
+'n', 's', 'R', '\031', 'u', 'p', 's', 't', 'r', 'e', 'a', 'm', 'C', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', 'O', 'p', 't', 
+'i', 'o', 'n', 's', '\022', 'U', '\n', '(', 'c', 'l', 'o', 's', 'e', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', 's', 
+'_', 'o', 'n', '_', 'h', 'o', 's', 't', '_', 'h', 'e', 'a', 'l', 't', 'h', '_', 'f', 'a', 'i', 'l', 'u', 'r', 'e', '\030', '\037', 
+' ', '\001', '(', '\010', 'R', '#', 'c', 'l', 'o', 's', 'e', 'C', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', 's', 'O', 'n', 'H', 
+'o', 's', 't', 'H', 'e', 'a', 'l', 't', 'h', 'F', 'a', 'i', 'l', 'u', 'r', 'e', '\022', '@', '\n', '\035', 'i', 'g', 'n', 'o', 'r', 
+'e', '_', 'h', 'e', 'a', 'l', 't', 'h', '_', 'o', 'n', '_', 'h', 'o', 's', 't', '_', 'r', 'e', 'm', 'o', 'v', 'a', 'l', '\030', 
+' ', ' ', '\001', '(', '\010', 'R', '\031', 'i', 'g', 'n', 'o', 'r', 'e', 'H', 'e', 'a', 'l', 't', 'h', 'O', 'n', 'H', 'o', 's', 't', 
+'R', 'e', 'm', 'o', 'v', 'a', 'l', '\022', '9', '\n', '\007', 'f', 'i', 'l', 't', 'e', 'r', 's', '\030', '(', ' ', '\003', '(', '\013', '2', 
+'\037', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'l', 'u', 's', 't', 'e', 'r', '.', 'v', '3', 
+'.', 'F', 'i', 'l', 't', 'e', 'r', 'R', '\007', 'f', 'i', 'l', 't', 'e', 'r', 's', '\022', '`', '\n', '\025', 'l', 'o', 'a', 'd', '_', 
+'b', 'a', 'l', 'a', 'n', 'c', 'i', 'n', 'g', '_', 'p', 'o', 'l', 'i', 'c', 'y', '\030', ')', ' ', '\001', '(', '\013', '2', ',', '.', 
+'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'l', 'u', 's', 't', 'e', 'r', '.', 'v', '3', '.', 'L', 
+'o', 'a', 'd', 'B', 'a', 'l', 'a', 'n', 'c', 'i', 'n', 'g', 'P', 'o', 'l', 'i', 'c', 'y', 'R', '\023', 'l', 'o', 'a', 'd', 'B', 
+'a', 'l', 'a', 'n', 'c', 'i', 'n', 'g', 'P', 'o', 'l', 'i', 'c', 'y', '\022', 'A', '\n', '\n', 'l', 'r', 's', '_', 's', 'e', 'r', 
+'v', 'e', 'r', '\030', '*', ' ', '\001', '(', '\013', '2', '\"', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 
+'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'C', 'o', 'n', 'f', 'i', 'g', 'S', 'o', 'u', 'r', 'c', 'e', 'R', '\t', 'l', 'r', 's', 
+'S', 'e', 'r', 'v', 'e', 'r', '\022', '?', '\n', '\025', 't', 'r', 'a', 'c', 'k', '_', 't', 'i', 'm', 'e', 'o', 'u', 't', '_', 'b', 
+'u', 'd', 'g', 'e', 't', 's', '\030', '/', ' ', '\001', '(', '\010', 'B', '\013', '\030', '\001', '\222', '\307', '\206', '\330', '\004', '\003', '3', '.', '0', 
+'R', '\023', 't', 'r', 'a', 'c', 'k', 'T', 'i', 'm', 'e', 'o', 'u', 't', 'B', 'u', 'd', 'g', 'e', 't', 's', '\022', 'S', '\n', '\017', 
+'u', 'p', 's', 't', 'r', 'e', 'a', 'm', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '0', ' ', '\001', '(', '\013', '2', '*', '.', 'e', 
+'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'T', 'y', 'p', 'e', 'd', 
+'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'C', 'o', 'n', 'f', 'i', 'g', 'R', '\016', 'u', 'p', 's', 't', 'r', 'e', 'a', 'm', 
+'C', 'o', 'n', 'f', 'i', 'g', '\022', 'Z', '\n', '\023', 't', 'r', 'a', 'c', 'k', '_', 'c', 'l', 'u', 's', 't', 'e', 'r', '_', 's', 
+'t', 'a', 't', 's', '\030', '1', ' ', '\001', '(', '\013', '2', '*', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', 
+'.', 'c', 'l', 'u', 's', 't', 'e', 'r', '.', 'v', '3', '.', 'T', 'r', 'a', 'c', 'k', 'C', 'l', 'u', 's', 't', 'e', 'r', 'S', 
+'t', 'a', 't', 's', 'R', '\021', 't', 'r', 'a', 'c', 'k', 'C', 'l', 'u', 's', 't', 'e', 'r', 'S', 't', 'a', 't', 's', '\022', '^', 
+'\n', '\021', 'p', 'r', 'e', 'c', 'o', 'n', 'n', 'e', 'c', 't', '_', 'p', 'o', 'l', 'i', 'c', 'y', '\030', '2', ' ', '\001', '(', '\013', 
+'2', '1', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'l', 'u', 's', 't', 'e', 'r', '.', 'v', 
+'3', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', '.', 'P', 'r', 'e', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'P', 'o', 'l', 'i', 'c', 
+'y', 'R', '\020', 'p', 'r', 'e', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'P', 'o', 'l', 'i', 'c', 'y', '\022', 'X', '\n', ')', 'c', 'o', 
+'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '_', 'p', 'o', 'o', 'l', '_', 'p', 'e', 'r', '_', 'd', 'o', 'w', 'n', 's', 't', 'r', 
+'e', 'a', 'm', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '\030', '3', ' ', '\001', '(', '\010', 'R', '%', 'c', 'o', 'n', 
+'n', 'e', 'c', 't', 'i', 'o', 'n', 'P', 'o', 'o', 'l', 'P', 'e', 'r', 'D', 'o', 'w', 'n', 's', 't', 'r', 'e', 'a', 'm', 'C', 
+'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '\032', '\346', '\001', '\n', '\024', 'T', 'r', 'a', 'n', 's', 'p', 'o', 'r', 't', 'S', 'o', 
+'c', 'k', 'e', 't', 'M', 'a', 't', 'c', 'h', '\022', '\033', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\007', 
+'\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '-', '\n', '\005', 'm', 'a', 't', 'c', 'h', '\030', '\002', ' ', 
+'\001', '(', '\013', '2', '\027', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'S', 't', 'r', 
+'u', 'c', 't', 'R', '\005', 'm', 'a', 't', 'c', 'h', '\022', 'P', '\n', '\020', 't', 'r', 'a', 'n', 's', 'p', 'o', 'r', 't', '_', 's', 
+'o', 'c', 'k', 'e', 't', '\030', '\003', ' ', '\001', '(', '\013', '2', '%', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 
+'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'T', 'r', 'a', 'n', 's', 'p', 'o', 'r', 't', 'S', 'o', 'c', 'k', 'e', 't', 
+'R', '\017', 't', 'r', 'a', 'n', 's', 'p', 'o', 'r', 't', 'S', 'o', 'c', 'k', 'e', 't', ':', '0', '\232', '\305', '\210', '\036', '+', '\n', 
+')', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', '.', 'T', 'r', 'a', 
+'n', 's', 'p', 'o', 'r', 't', 'S', 'o', 'c', 'k', 'e', 't', 'M', 'a', 't', 'c', 'h', '\032', '\230', '\001', '\n', '\021', 'C', 'u', 's', 
+'t', 'o', 'm', 'C', 'l', 'u', 's', 't', 'e', 'r', 'T', 'y', 'p', 'e', '\022', '\033', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', 
+'\001', '(', '\t', 'B', '\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '7', '\n', '\014', 't', 'y', 'p', 
+'e', 'd', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\002', ' ', '\001', '(', '\013', '2', '\024', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 
+'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'A', 'n', 'y', 'R', '\013', 't', 'y', 'p', 'e', 'd', 'C', 'o', 'n', 'f', 'i', 'g', 
+':', '-', '\232', '\305', '\210', '\036', '(', '\n', '&', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'C', 'l', 'u', 
+'s', 't', 'e', 'r', '.', 'C', 'u', 's', 't', 'o', 'm', 'C', 'l', 'u', 's', 't', 'e', 'r', 'T', 'y', 'p', 'e', '\032', '\246', '\001', 
+'\n', '\020', 'E', 'd', 's', 'C', 'l', 'u', 's', 't', 'e', 'r', 'C', 'o', 'n', 'f', 'i', 'g', '\022', 'A', '\n', '\n', 'e', 'd', 's', 
+'_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\001', ' ', '\001', '(', '\013', '2', '\"', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 
+'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'C', 'o', 'n', 'f', 'i', 'g', 'S', 'o', 'u', 'r', 'c', 'e', 'R', 
+'\t', 'e', 'd', 's', 'C', 'o', 'n', 'f', 'i', 'g', '\022', '!', '\n', '\014', 's', 'e', 'r', 'v', 'i', 'c', 'e', '_', 'n', 'a', 'm', 
+'e', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\013', 's', 'e', 'r', 'v', 'i', 'c', 'e', 'N', 'a', 'm', 'e', ':', ',', '\232', '\305', '\210', 
+'\036', '\'', '\n', '%', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', '.', 
+'E', 'd', 's', 'C', 'l', 'u', 's', 't', 'e', 'r', 'C', 'o', 'n', 'f', 'i', 'g', '\032', '\300', '\010', '\n', '\016', 'L', 'b', 'S', 'u', 
+'b', 's', 'e', 't', 'C', 'o', 'n', 'f', 'i', 'g', '\022', 'y', '\n', '\017', 'f', 'a', 'l', 'l', 'b', 'a', 'c', 'k', '_', 'p', 'o', 
+'l', 'i', 'c', 'y', '\030', '\001', ' ', '\001', '(', '\016', '2', 'F', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', 
+'.', 'c', 'l', 'u', 's', 't', 'e', 'r', '.', 'v', '3', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', '.', 'L', 'b', 'S', 'u', 'b', 
+'s', 'e', 't', 'C', 'o', 'n', 'f', 'i', 'g', '.', 'L', 'b', 'S', 'u', 'b', 's', 'e', 't', 'F', 'a', 'l', 'l', 'b', 'a', 'c', 
+'k', 'P', 'o', 'l', 'i', 'c', 'y', 'B', '\010', '\372', 'B', '\005', '\202', '\001', '\002', '\020', '\001', 'R', '\016', 'f', 'a', 'l', 'l', 'b', 'a', 
+'c', 'k', 'P', 'o', 'l', 'i', 'c', 'y', '\022', '>', '\n', '\016', 'd', 'e', 'f', 'a', 'u', 'l', 't', '_', 's', 'u', 'b', 's', 'e', 
+'t', '\030', '\002', ' ', '\001', '(', '\013', '2', '\027', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', 
+'.', 'S', 't', 'r', 'u', 'c', 't', 'R', '\r', 'd', 'e', 'f', 'a', 'u', 'l', 't', 'S', 'u', 'b', 's', 'e', 't', '\022', 'k', '\n', 
+'\020', 's', 'u', 'b', 's', 'e', 't', '_', 's', 'e', 'l', 'e', 'c', 't', 'o', 'r', 's', '\030', '\003', ' ', '\003', '(', '\013', '2', '@', 
+'.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'l', 'u', 's', 't', 'e', 'r', '.', 'v', '3', '.', 
+'C', 'l', 'u', 's', 't', 'e', 'r', '.', 'L', 'b', 'S', 'u', 'b', 's', 'e', 't', 'C', 'o', 'n', 'f', 'i', 'g', '.', 'L', 'b', 
+'S', 'u', 'b', 's', 'e', 't', 'S', 'e', 'l', 'e', 'c', 't', 'o', 'r', 'R', '\017', 's', 'u', 'b', 's', 'e', 't', 'S', 'e', 'l', 
+'e', 'c', 't', 'o', 'r', 's', '\022', '2', '\n', '\025', 'l', 'o', 'c', 'a', 'l', 'i', 't', 'y', '_', 'w', 'e', 'i', 'g', 'h', 't', 
+'_', 'a', 'w', 'a', 'r', 'e', '\030', '\004', ' ', '\001', '(', '\010', 'R', '\023', 'l', 'o', 'c', 'a', 'l', 'i', 't', 'y', 'W', 'e', 'i', 
+'g', 'h', 't', 'A', 'w', 'a', 'r', 'e', '\022', '2', '\n', '\025', 's', 'c', 'a', 'l', 'e', '_', 'l', 'o', 'c', 'a', 'l', 'i', 't', 
+'y', '_', 'w', 'e', 'i', 'g', 'h', 't', '\030', '\005', ' ', '\001', '(', '\010', 'R', '\023', 's', 'c', 'a', 'l', 'e', 'L', 'o', 'c', 'a', 
+'l', 'i', 't', 'y', 'W', 'e', 'i', 'g', 'h', 't', '\022', '$', '\n', '\016', 'p', 'a', 'n', 'i', 'c', '_', 'm', 'o', 'd', 'e', '_', 
+'a', 'n', 'y', '\030', '\006', ' ', '\001', '(', '\010', 'R', '\014', 'p', 'a', 'n', 'i', 'c', 'M', 'o', 'd', 'e', 'A', 'n', 'y', '\022', '\036', 
+'\n', '\013', 'l', 'i', 's', 't', '_', 'a', 's', '_', 'a', 'n', 'y', '\030', '\007', ' ', '\001', '(', '\010', 'R', '\t', 'l', 'i', 's', 't', 
+'A', 's', 'A', 'n', 'y', '\032', '\332', '\003', '\n', '\020', 'L', 'b', 'S', 'u', 'b', 's', 'e', 't', 'S', 'e', 'l', 'e', 'c', 't', 'o', 
+'r', '\022', '\022', '\n', '\004', 'k', 'e', 'y', 's', '\030', '\001', ' ', '\003', '(', '\t', 'R', '\004', 'k', 'e', 'y', 's', '\022', '3', '\n', '\026', 
+'s', 'i', 'n', 'g', 'l', 'e', '_', 'h', 'o', 's', 't', '_', 'p', 'e', 'r', '_', 's', 'u', 'b', 's', 'e', 't', '\030', '\004', ' ', 
+'\001', '(', '\010', 'R', '\023', 's', 'i', 'n', 'g', 'l', 'e', 'H', 'o', 's', 't', 'P', 'e', 'r', 'S', 'u', 'b', 's', 'e', 't', '\022', 
+'\222', '\001', '\n', '\017', 'f', 'a', 'l', 'l', 'b', 'a', 'c', 'k', '_', 'p', 'o', 'l', 'i', 'c', 'y', '\030', '\002', ' ', '\001', '(', '\016', 
+'2', '_', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'l', 'u', 's', 't', 'e', 'r', '.', 'v', 
+'3', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', '.', 'L', 'b', 'S', 'u', 'b', 's', 'e', 't', 'C', 'o', 'n', 'f', 'i', 'g', '.', 
+'L', 'b', 'S', 'u', 'b', 's', 'e', 't', 'S', 'e', 'l', 'e', 'c', 't', 'o', 'r', '.', 'L', 'b', 'S', 'u', 'b', 's', 'e', 't', 
+'S', 'e', 'l', 'e', 'c', 't', 'o', 'r', 'F', 'a', 'l', 'l', 'b', 'a', 'c', 'k', 'P', 'o', 'l', 'i', 'c', 'y', 'B', '\010', '\372', 
+'B', '\005', '\202', '\001', '\002', '\020', '\001', 'R', '\016', 'f', 'a', 'l', 'l', 'b', 'a', 'c', 'k', 'P', 'o', 'l', 'i', 'c', 'y', '\022', '0', 
+'\n', '\024', 'f', 'a', 'l', 'l', 'b', 'a', 'c', 'k', '_', 'k', 'e', 'y', 's', '_', 's', 'u', 'b', 's', 'e', 't', '\030', '\003', ' ', 
+'\003', '(', '\t', 'R', '\022', 'f', 'a', 'l', 'l', 'b', 'a', 'c', 'k', 'K', 'e', 'y', 's', 'S', 'u', 'b', 's', 'e', 't', '\"', 'y', 
+'\n', '\036', 'L', 'b', 'S', 'u', 'b', 's', 'e', 't', 'S', 'e', 'l', 'e', 'c', 't', 'o', 'r', 'F', 'a', 'l', 'l', 'b', 'a', 'c', 
+'k', 'P', 'o', 'l', 'i', 'c', 'y', '\022', '\017', '\n', '\013', 'N', 'O', 'T', '_', 'D', 'E', 'F', 'I', 'N', 'E', 'D', '\020', '\000', '\022', 
+'\017', '\n', '\013', 'N', 'O', '_', 'F', 'A', 'L', 'L', 'B', 'A', 'C', 'K', '\020', '\001', '\022', '\020', '\n', '\014', 'A', 'N', 'Y', '_', 'E', 
+'N', 'D', 'P', 'O', 'I', 'N', 'T', '\020', '\002', '\022', '\022', '\n', '\016', 'D', 'E', 'F', 'A', 'U', 'L', 'T', '_', 'S', 'U', 'B', 'S', 
+'E', 'T', '\020', '\003', '\022', '\017', '\n', '\013', 'K', 'E', 'Y', 'S', '_', 'S', 'U', 'B', 'S', 'E', 'T', '\020', '\004', ':', ';', '\232', '\305', 
+'\210', '\036', '6', '\n', '4', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', 
+'.', 'L', 'b', 'S', 'u', 'b', 's', 'e', 't', 'C', 'o', 'n', 'f', 'i', 'g', '.', 'L', 'b', 'S', 'u', 'b', 's', 'e', 't', 'S', 
+'e', 'l', 'e', 'c', 't', 'o', 'r', '\"', 'O', '\n', '\026', 'L', 'b', 'S', 'u', 'b', 's', 'e', 't', 'F', 'a', 'l', 'l', 'b', 'a', 
+'c', 'k', 'P', 'o', 'l', 'i', 'c', 'y', '\022', '\017', '\n', '\013', 'N', 'O', '_', 'F', 'A', 'L', 'L', 'B', 'A', 'C', 'K', '\020', '\000', 
+'\022', '\020', '\n', '\014', 'A', 'N', 'Y', '_', 'E', 'N', 'D', 'P', 'O', 'I', 'N', 'T', '\020', '\001', '\022', '\022', '\n', '\016', 'D', 'E', 'F', 
+'A', 'U', 'L', 'T', '_', 'S', 'U', 'B', 'S', 'E', 'T', '\020', '\002', ':', '*', '\232', '\305', '\210', '\036', '%', '\n', '#', 'e', 'n', 'v', 
+'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', '.', 'L', 'b', 'S', 'u', 'b', 's', 'e', 
+'t', 'C', 'o', 'n', 'f', 'i', 'g', '\032', '\235', '\001', '\n', '\017', 'S', 'l', 'o', 'w', 'S', 't', 'a', 'r', 't', 'C', 'o', 'n', 'f', 
+'i', 'g', '\022', 'E', '\n', '\021', 's', 'l', 'o', 'w', '_', 's', 't', 'a', 'r', 't', '_', 'w', 'i', 'n', 'd', 'o', 'w', '\030', '\001', 
+' ', '\001', '(', '\013', '2', '\031', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'u', 
+'r', 'a', 't', 'i', 'o', 'n', 'R', '\017', 's', 'l', 'o', 'w', 'S', 't', 'a', 'r', 't', 'W', 'i', 'n', 'd', 'o', 'w', '\022', 'C', 
+'\n', '\n', 'a', 'g', 'g', 'r', 'e', 's', 's', 'i', 'o', 'n', '\030', '\002', ' ', '\001', '(', '\013', '2', '#', '.', 'e', 'n', 'v', 'o', 
+'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'R', 'u', 'n', 't', 'i', 'm', 'e', 'D', 
+'o', 'u', 'b', 'l', 'e', 'R', '\n', 'a', 'g', 'g', 'r', 'e', 's', 's', 'i', 'o', 'n', '\032', 'r', '\n', '\022', 'R', 'o', 'u', 'n', 
+'d', 'R', 'o', 'b', 'i', 'n', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', '\022', '\\', '\n', '\021', 's', 'l', 'o', 'w', '_', 's', 't', 
+'a', 'r', 't', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\001', ' ', '\001', '(', '\013', '2', '0', '.', 'e', 'n', 'v', 'o', 'y', '.', 
 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'l', 'u', 's', 't', 'e', 'r', '.', 'v', '3', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', 
-'.', 'C', 'l', 'u', 's', 't', 'e', 'r', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'S', 'e', 'l', 'e', 'c', 't', 'i', 'o', 'n', 
-'B', '\013', '\030', '\001', '\222', '\307', '\206', '\330', '\004', '\003', '3', '.', '0', 'R', '\021', 'p', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'S', 'e', 
-'l', 'e', 'c', 't', 'i', 'o', 'n', '\022', 'r', '\n', '\033', 'u', 'p', 's', 't', 'r', 'e', 'a', 'm', '_', 'c', 'o', 'n', 'n', 'e', 
-'c', 't', 'i', 'o', 'n', '_', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\036', ' ', '\001', '(', '\013', '2', '2', '.', 'e', 'n', 'v', 
-'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'l', 'u', 's', 't', 'e', 'r', '.', 'v', '3', '.', 'U', 'p', 's', 't', 
-'r', 'e', 'a', 'm', 'C', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', 'O', 'p', 't', 'i', 'o', 'n', 's', 'R', '\031', 'u', 'p', 
-'s', 't', 'r', 'e', 'a', 'm', 'C', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', 'U', 
-'\n', '(', 'c', 'l', 'o', 's', 'e', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', 's', '_', 'o', 'n', '_', 'h', 'o', 
-'s', 't', '_', 'h', 'e', 'a', 'l', 't', 'h', '_', 'f', 'a', 'i', 'l', 'u', 'r', 'e', '\030', '\037', ' ', '\001', '(', '\010', 'R', '#', 
-'c', 'l', 'o', 's', 'e', 'C', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', 's', 'O', 'n', 'H', 'o', 's', 't', 'H', 'e', 'a', 
-'l', 't', 'h', 'F', 'a', 'i', 'l', 'u', 'r', 'e', '\022', '@', '\n', '\035', 'i', 'g', 'n', 'o', 'r', 'e', '_', 'h', 'e', 'a', 'l', 
-'t', 'h', '_', 'o', 'n', '_', 'h', 'o', 's', 't', '_', 'r', 'e', 'm', 'o', 'v', 'a', 'l', '\030', ' ', ' ', '\001', '(', '\010', 'R', 
-'\031', 'i', 'g', 'n', 'o', 'r', 'e', 'H', 'e', 'a', 'l', 't', 'h', 'O', 'n', 'H', 'o', 's', 't', 'R', 'e', 'm', 'o', 'v', 'a', 
-'l', '\022', '9', '\n', '\007', 'f', 'i', 'l', 't', 'e', 'r', 's', '\030', '(', ' ', '\003', '(', '\013', '2', '\037', '.', 'e', 'n', 'v', 'o', 
-'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'l', 'u', 's', 't', 'e', 'r', '.', 'v', '3', '.', 'F', 'i', 'l', 't', 'e', 
-'r', 'R', '\007', 'f', 'i', 'l', 't', 'e', 'r', 's', '\022', '`', '\n', '\025', 'l', 'o', 'a', 'd', '_', 'b', 'a', 'l', 'a', 'n', 'c', 
-'i', 'n', 'g', '_', 'p', 'o', 'l', 'i', 'c', 'y', '\030', ')', ' ', '\001', '(', '\013', '2', ',', '.', 'e', 'n', 'v', 'o', 'y', '.', 
-'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'l', 'u', 's', 't', 'e', 'r', '.', 'v', '3', '.', 'L', 'o', 'a', 'd', 'B', 'a', 'l', 
-'a', 'n', 'c', 'i', 'n', 'g', 'P', 'o', 'l', 'i', 'c', 'y', 'R', '\023', 'l', 'o', 'a', 'd', 'B', 'a', 'l', 'a', 'n', 'c', 'i', 
-'n', 'g', 'P', 'o', 'l', 'i', 'c', 'y', '\022', 'A', '\n', '\n', 'l', 'r', 's', '_', 's', 'e', 'r', 'v', 'e', 'r', '\030', '*', ' ', 
-'\001', '(', '\013', '2', '\"', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', 
-'3', '.', 'C', 'o', 'n', 'f', 'i', 'g', 'S', 'o', 'u', 'r', 'c', 'e', 'R', '\t', 'l', 'r', 's', 'S', 'e', 'r', 'v', 'e', 'r', 
-'\022', '?', '\n', '\025', 't', 'r', 'a', 'c', 'k', '_', 't', 'i', 'm', 'e', 'o', 'u', 't', '_', 'b', 'u', 'd', 'g', 'e', 't', 's', 
-'\030', '/', ' ', '\001', '(', '\010', 'B', '\013', '\030', '\001', '\222', '\307', '\206', '\330', '\004', '\003', '3', '.', '0', 'R', '\023', 't', 'r', 'a', 'c', 
-'k', 'T', 'i', 'm', 'e', 'o', 'u', 't', 'B', 'u', 'd', 'g', 'e', 't', 's', '\022', 'S', '\n', '\017', 'u', 'p', 's', 't', 'r', 'e', 
-'a', 'm', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '0', ' ', '\001', '(', '\013', '2', '*', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 
-'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'T', 'y', 'p', 'e', 'd', 'E', 'x', 't', 'e', 'n', 's', 
-'i', 'o', 'n', 'C', 'o', 'n', 'f', 'i', 'g', 'R', '\016', 'u', 'p', 's', 't', 'r', 'e', 'a', 'm', 'C', 'o', 'n', 'f', 'i', 'g', 
-'\022', 'Z', '\n', '\023', 't', 'r', 'a', 'c', 'k', '_', 'c', 'l', 'u', 's', 't', 'e', 'r', '_', 's', 't', 'a', 't', 's', '\030', '1', 
-' ', '\001', '(', '\013', '2', '*', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'l', 'u', 's', 't', 
-'e', 'r', '.', 'v', '3', '.', 'T', 'r', 'a', 'c', 'k', 'C', 'l', 'u', 's', 't', 'e', 'r', 'S', 't', 'a', 't', 's', 'R', '\021', 
-'t', 'r', 'a', 'c', 'k', 'C', 'l', 'u', 's', 't', 'e', 'r', 'S', 't', 'a', 't', 's', '\022', '^', '\n', '\021', 'p', 'r', 'e', 'c', 
-'o', 'n', 'n', 'e', 'c', 't', '_', 'p', 'o', 'l', 'i', 'c', 'y', '\030', '2', ' ', '\001', '(', '\013', '2', '1', '.', 'e', 'n', 'v', 
-'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'l', 'u', 's', 't', 'e', 'r', '.', 'v', '3', '.', 'C', 'l', 'u', 's', 
-'t', 'e', 'r', '.', 'P', 'r', 'e', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'P', 'o', 'l', 'i', 'c', 'y', 'R', '\020', 'p', 'r', 'e', 
-'c', 'o', 'n', 'n', 'e', 'c', 't', 'P', 'o', 'l', 'i', 'c', 'y', '\022', 'X', '\n', ')', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 
-'o', 'n', '_', 'p', 'o', 'o', 'l', '_', 'p', 'e', 'r', '_', 'd', 'o', 'w', 'n', 's', 't', 'r', 'e', 'a', 'm', '_', 'c', 'o', 
-'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '\030', '3', ' ', '\001', '(', '\010', 'R', '%', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 
-'n', 'P', 'o', 'o', 'l', 'P', 'e', 'r', 'D', 'o', 'w', 'n', 's', 't', 'r', 'e', 'a', 'm', 'C', 'o', 'n', 'n', 'e', 'c', 't', 
-'i', 'o', 'n', '\032', '\346', '\001', '\n', '\024', 'T', 'r', 'a', 'n', 's', 'p', 'o', 'r', 't', 'S', 'o', 'c', 'k', 'e', 't', 'M', 'a', 
-'t', 'c', 'h', '\022', '\033', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\007', '\372', 'B', '\004', 'r', '\002', '\020', 
-'\001', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '-', '\n', '\005', 'm', 'a', 't', 'c', 'h', '\030', '\002', ' ', '\001', '(', '\013', '2', '\027', '.', 
-'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'S', 't', 'r', 'u', 'c', 't', 'R', '\005', 'm', 
-'a', 't', 'c', 'h', '\022', 'P', '\n', '\020', 't', 'r', 'a', 'n', 's', 'p', 'o', 'r', 't', '_', 's', 'o', 'c', 'k', 'e', 't', '\030', 
-'\003', ' ', '\001', '(', '\013', '2', '%', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', 
-'.', 'v', '3', '.', 'T', 'r', 'a', 'n', 's', 'p', 'o', 'r', 't', 'S', 'o', 'c', 'k', 'e', 't', 'R', '\017', 't', 'r', 'a', 'n', 
-'s', 'p', 'o', 'r', 't', 'S', 'o', 'c', 'k', 'e', 't', ':', '0', '\232', '\305', '\210', '\036', '+', '\n', ')', 'e', 'n', 'v', 'o', 'y', 
-'.', 'a', 'p', 'i', '.', 'v', '2', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', '.', 'T', 'r', 'a', 'n', 's', 'p', 'o', 'r', 't', 
-'S', 'o', 'c', 'k', 'e', 't', 'M', 'a', 't', 'c', 'h', '\032', '\230', '\001', '\n', '\021', 'C', 'u', 's', 't', 'o', 'm', 'C', 'l', 'u', 
-'s', 't', 'e', 'r', 'T', 'y', 'p', 'e', '\022', '\033', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\007', '\372', 
-'B', '\004', 'r', '\002', '\020', '\001', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '7', '\n', '\014', 't', 'y', 'p', 'e', 'd', '_', 'c', 'o', 'n', 
-'f', 'i', 'g', '\030', '\002', ' ', '\001', '(', '\013', '2', '\024', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 
-'u', 'f', '.', 'A', 'n', 'y', 'R', '\013', 't', 'y', 'p', 'e', 'd', 'C', 'o', 'n', 'f', 'i', 'g', ':', '-', '\232', '\305', '\210', '\036', 
-'(', '\n', '&', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', '.', 'C', 
-'u', 's', 't', 'o', 'm', 'C', 'l', 'u', 's', 't', 'e', 'r', 'T', 'y', 'p', 'e', '\032', '\246', '\001', '\n', '\020', 'E', 'd', 's', 'C', 
-'l', 'u', 's', 't', 'e', 'r', 'C', 'o', 'n', 'f', 'i', 'g', '\022', 'A', '\n', '\n', 'e', 'd', 's', '_', 'c', 'o', 'n', 'f', 'i', 
-'g', '\030', '\001', ' ', '\001', '(', '\013', '2', '\"', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 
-'r', 'e', '.', 'v', '3', '.', 'C', 'o', 'n', 'f', 'i', 'g', 'S', 'o', 'u', 'r', 'c', 'e', 'R', '\t', 'e', 'd', 's', 'C', 'o', 
-'n', 'f', 'i', 'g', '\022', '!', '\n', '\014', 's', 'e', 'r', 'v', 'i', 'c', 'e', '_', 'n', 'a', 'm', 'e', '\030', '\002', ' ', '\001', '(', 
-'\t', 'R', '\013', 's', 'e', 'r', 'v', 'i', 'c', 'e', 'N', 'a', 'm', 'e', ':', ',', '\232', '\305', '\210', '\036', '\'', '\n', '%', 'e', 'n', 
-'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', '.', 'E', 'd', 's', 'C', 'l', 'u', 
-'s', 't', 'e', 'r', 'C', 'o', 'n', 'f', 'i', 'g', '\032', '\300', '\010', '\n', '\016', 'L', 'b', 'S', 'u', 'b', 's', 'e', 't', 'C', 'o', 
-'n', 'f', 'i', 'g', '\022', 'y', '\n', '\017', 'f', 'a', 'l', 'l', 'b', 'a', 'c', 'k', '_', 'p', 'o', 'l', 'i', 'c', 'y', '\030', '\001', 
-' ', '\001', '(', '\016', '2', 'F', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'l', 'u', 's', 't', 
-'e', 'r', '.', 'v', '3', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', '.', 'L', 'b', 'S', 'u', 'b', 's', 'e', 't', 'C', 'o', 'n', 
-'f', 'i', 'g', '.', 'L', 'b', 'S', 'u', 'b', 's', 'e', 't', 'F', 'a', 'l', 'l', 'b', 'a', 'c', 'k', 'P', 'o', 'l', 'i', 'c', 
-'y', 'B', '\010', '\372', 'B', '\005', '\202', '\001', '\002', '\020', '\001', 'R', '\016', 'f', 'a', 'l', 'l', 'b', 'a', 'c', 'k', 'P', 'o', 'l', 'i', 
-'c', 'y', '\022', '>', '\n', '\016', 'd', 'e', 'f', 'a', 'u', 'l', 't', '_', 's', 'u', 'b', 's', 'e', 't', '\030', '\002', ' ', '\001', '(', 
-'\013', '2', '\027', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'S', 't', 'r', 'u', 'c', 
-'t', 'R', '\r', 'd', 'e', 'f', 'a', 'u', 'l', 't', 'S', 'u', 'b', 's', 'e', 't', '\022', 'k', '\n', '\020', 's', 'u', 'b', 's', 'e', 
-'t', '_', 's', 'e', 'l', 'e', 'c', 't', 'o', 'r', 's', '\030', '\003', ' ', '\003', '(', '\013', '2', '@', '.', 'e', 'n', 'v', 'o', 'y', 
-'.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'l', 'u', 's', 't', 'e', 'r', '.', 'v', '3', '.', 'C', 'l', 'u', 's', 't', 'e', 
-'r', '.', 'L', 'b', 'S', 'u', 'b', 's', 'e', 't', 'C', 'o', 'n', 'f', 'i', 'g', '.', 'L', 'b', 'S', 'u', 'b', 's', 'e', 't', 
-'S', 'e', 'l', 'e', 'c', 't', 'o', 'r', 'R', '\017', 's', 'u', 'b', 's', 'e', 't', 'S', 'e', 'l', 'e', 'c', 't', 'o', 'r', 's', 
-'\022', '2', '\n', '\025', 'l', 'o', 'c', 'a', 'l', 'i', 't', 'y', '_', 'w', 'e', 'i', 'g', 'h', 't', '_', 'a', 'w', 'a', 'r', 'e', 
-'\030', '\004', ' ', '\001', '(', '\010', 'R', '\023', 'l', 'o', 'c', 'a', 'l', 'i', 't', 'y', 'W', 'e', 'i', 'g', 'h', 't', 'A', 'w', 'a', 
-'r', 'e', '\022', '2', '\n', '\025', 's', 'c', 'a', 'l', 'e', '_', 'l', 'o', 'c', 'a', 'l', 'i', 't', 'y', '_', 'w', 'e', 'i', 'g', 
-'h', 't', '\030', '\005', ' ', '\001', '(', '\010', 'R', '\023', 's', 'c', 'a', 'l', 'e', 'L', 'o', 'c', 'a', 'l', 'i', 't', 'y', 'W', 'e', 
-'i', 'g', 'h', 't', '\022', '$', '\n', '\016', 'p', 'a', 'n', 'i', 'c', '_', 'm', 'o', 'd', 'e', '_', 'a', 'n', 'y', '\030', '\006', ' ', 
-'\001', '(', '\010', 'R', '\014', 'p', 'a', 'n', 'i', 'c', 'M', 'o', 'd', 'e', 'A', 'n', 'y', '\022', '\036', '\n', '\013', 'l', 'i', 's', 't', 
-'_', 'a', 's', '_', 'a', 'n', 'y', '\030', '\007', ' ', '\001', '(', '\010', 'R', '\t', 'l', 'i', 's', 't', 'A', 's', 'A', 'n', 'y', '\032', 
-'\332', '\003', '\n', '\020', 'L', 'b', 'S', 'u', 'b', 's', 'e', 't', 'S', 'e', 'l', 'e', 'c', 't', 'o', 'r', '\022', '\022', '\n', '\004', 'k', 
-'e', 'y', 's', '\030', '\001', ' ', '\003', '(', '\t', 'R', '\004', 'k', 'e', 'y', 's', '\022', '3', '\n', '\026', 's', 'i', 'n', 'g', 'l', 'e', 
-'_', 'h', 'o', 's', 't', '_', 'p', 'e', 'r', '_', 's', 'u', 'b', 's', 'e', 't', '\030', '\004', ' ', '\001', '(', '\010', 'R', '\023', 's', 
-'i', 'n', 'g', 'l', 'e', 'H', 'o', 's', 't', 'P', 'e', 'r', 'S', 'u', 'b', 's', 'e', 't', '\022', '\222', '\001', '\n', '\017', 'f', 'a', 
-'l', 'l', 'b', 'a', 'c', 'k', '_', 'p', 'o', 'l', 'i', 'c', 'y', '\030', '\002', ' ', '\001', '(', '\016', '2', '_', '.', 'e', 'n', 'v', 
+'.', 'S', 'l', 'o', 'w', 'S', 't', 'a', 'r', 't', 'C', 'o', 'n', 'f', 'i', 'g', 'R', '\017', 's', 'l', 'o', 'w', 'S', 't', 'a', 
+'r', 't', 'C', 'o', 'n', 'f', 'i', 'g', '\032', '\305', '\002', '\n', '\024', 'L', 'e', 'a', 's', 't', 'R', 'e', 'q', 'u', 'e', 's', 't', 
+'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', '\022', 'H', '\n', '\014', 'c', 'h', 'o', 'i', 'c', 'e', '_', 'c', 'o', 'u', 'n', 't', '\030', 
+'\001', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 
+'I', 'n', 't', '3', '2', 'V', 'a', 'l', 'u', 'e', 'B', '\007', '\372', 'B', '\004', '*', '\002', '(', '\002', 'R', '\013', 'c', 'h', 'o', 'i', 
+'c', 'e', 'C', 'o', 'u', 'n', 't', '\022', 'S', '\n', '\023', 'a', 'c', 't', 'i', 'v', 'e', '_', 'r', 'e', 'q', 'u', 'e', 's', 't', 
+'_', 'b', 'i', 'a', 's', '\030', '\002', ' ', '\001', '(', '\013', '2', '#', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 
+'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'R', 'u', 'n', 't', 'i', 'm', 'e', 'D', 'o', 'u', 'b', 'l', 'e', 'R', '\021', 
+'a', 'c', 't', 'i', 'v', 'e', 'R', 'e', 'q', 'u', 'e', 's', 't', 'B', 'i', 'a', 's', '\022', '\\', '\n', '\021', 's', 'l', 'o', 'w', 
+'_', 's', 't', 'a', 'r', 't', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\003', ' ', '\001', '(', '\013', '2', '0', '.', 'e', 'n', 'v', 
 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'l', 'u', 's', 't', 'e', 'r', '.', 'v', '3', '.', 'C', 'l', 'u', 's', 
-'t', 'e', 'r', '.', 'L', 'b', 'S', 'u', 'b', 's', 'e', 't', 'C', 'o', 'n', 'f', 'i', 'g', '.', 'L', 'b', 'S', 'u', 'b', 's', 
-'e', 't', 'S', 'e', 'l', 'e', 'c', 't', 'o', 'r', '.', 'L', 'b', 'S', 'u', 'b', 's', 'e', 't', 'S', 'e', 'l', 'e', 'c', 't', 
-'o', 'r', 'F', 'a', 'l', 'l', 'b', 'a', 'c', 'k', 'P', 'o', 'l', 'i', 'c', 'y', 'B', '\010', '\372', 'B', '\005', '\202', '\001', '\002', '\020', 
-'\001', 'R', '\016', 'f', 'a', 'l', 'l', 'b', 'a', 'c', 'k', 'P', 'o', 'l', 'i', 'c', 'y', '\022', '0', '\n', '\024', 'f', 'a', 'l', 'l', 
-'b', 'a', 'c', 'k', '_', 'k', 'e', 'y', 's', '_', 's', 'u', 'b', 's', 'e', 't', '\030', '\003', ' ', '\003', '(', '\t', 'R', '\022', 'f', 
-'a', 'l', 'l', 'b', 'a', 'c', 'k', 'K', 'e', 'y', 's', 'S', 'u', 'b', 's', 'e', 't', '\"', 'y', '\n', '\036', 'L', 'b', 'S', 'u', 
-'b', 's', 'e', 't', 'S', 'e', 'l', 'e', 'c', 't', 'o', 'r', 'F', 'a', 'l', 'l', 'b', 'a', 'c', 'k', 'P', 'o', 'l', 'i', 'c', 
-'y', '\022', '\017', '\n', '\013', 'N', 'O', 'T', '_', 'D', 'E', 'F', 'I', 'N', 'E', 'D', '\020', '\000', '\022', '\017', '\n', '\013', 'N', 'O', '_', 
-'F', 'A', 'L', 'L', 'B', 'A', 'C', 'K', '\020', '\001', '\022', '\020', '\n', '\014', 'A', 'N', 'Y', '_', 'E', 'N', 'D', 'P', 'O', 'I', 'N', 
-'T', '\020', '\002', '\022', '\022', '\n', '\016', 'D', 'E', 'F', 'A', 'U', 'L', 'T', '_', 'S', 'U', 'B', 'S', 'E', 'T', '\020', '\003', '\022', '\017', 
-'\n', '\013', 'K', 'E', 'Y', 'S', '_', 'S', 'U', 'B', 'S', 'E', 'T', '\020', '\004', ':', ';', '\232', '\305', '\210', '\036', '6', '\n', '4', 'e', 
-'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', '.', 'L', 'b', 'S', 'u', 'b', 
-'s', 'e', 't', 'C', 'o', 'n', 'f', 'i', 'g', '.', 'L', 'b', 'S', 'u', 'b', 's', 'e', 't', 'S', 'e', 'l', 'e', 'c', 't', 'o', 
-'r', '\"', 'O', '\n', '\026', 'L', 'b', 'S', 'u', 'b', 's', 'e', 't', 'F', 'a', 'l', 'l', 'b', 'a', 'c', 'k', 'P', 'o', 'l', 'i', 
-'c', 'y', '\022', '\017', '\n', '\013', 'N', 'O', '_', 'F', 'A', 'L', 'L', 'B', 'A', 'C', 'K', '\020', '\000', '\022', '\020', '\n', '\014', 'A', 'N', 
-'Y', '_', 'E', 'N', 'D', 'P', 'O', 'I', 'N', 'T', '\020', '\001', '\022', '\022', '\n', '\016', 'D', 'E', 'F', 'A', 'U', 'L', 'T', '_', 'S', 
-'U', 'B', 'S', 'E', 'T', '\020', '\002', ':', '*', '\232', '\305', '\210', '\036', '%', '\n', '#', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', 
-'.', 'v', '2', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', '.', 'L', 'b', 'S', 'u', 'b', 's', 'e', 't', 'C', 'o', 'n', 'f', 'i', 
-'g', '\032', '\347', '\001', '\n', '\024', 'L', 'e', 'a', 's', 't', 'R', 'e', 'q', 'u', 'e', 's', 't', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 
-'g', '\022', 'H', '\n', '\014', 'c', 'h', 'o', 'i', 'c', 'e', '_', 'c', 'o', 'u', 'n', 't', '\030', '\001', ' ', '\001', '(', '\013', '2', '\034', 
-'.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'I', 'n', 't', '3', '2', 'V', 'a', 
-'l', 'u', 'e', 'B', '\007', '\372', 'B', '\004', '*', '\002', '(', '\002', 'R', '\013', 'c', 'h', 'o', 'i', 'c', 'e', 'C', 'o', 'u', 'n', 't', 
-'\022', 'S', '\n', '\023', 'a', 'c', 't', 'i', 'v', 'e', '_', 'r', 'e', 'q', 'u', 'e', 's', 't', '_', 'b', 'i', 'a', 's', '\030', '\002', 
-' ', '\001', '(', '\013', '2', '#', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 
-'v', '3', '.', 'R', 'u', 'n', 't', 'i', 'm', 'e', 'D', 'o', 'u', 'b', 'l', 'e', 'R', '\021', 'a', 'c', 't', 'i', 'v', 'e', 'R', 
-'e', 'q', 'u', 'e', 's', 't', 'B', 'i', 'a', 's', ':', '0', '\232', '\305', '\210', '\036', '+', '\n', ')', 'e', 'n', 'v', 'o', 'y', '.', 
-'a', 'p', 'i', '.', 'v', '2', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', '.', 'L', 'e', 'a', 's', 't', 'R', 'e', 'q', 'u', 'e', 
-'s', 't', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', '\032', '\221', '\003', '\n', '\020', 'R', 'i', 'n', 'g', 'H', 'a', 's', 'h', 'L', 'b', 
-'C', 'o', 'n', 'f', 'i', 'g', '\022', 'T', '\n', '\021', 'm', 'i', 'n', 'i', 'm', 'u', 'm', '_', 'r', 'i', 'n', 'g', '_', 's', 'i', 
-'z', 'e', '\030', '\001', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 
-'f', '.', 'U', 'I', 'n', 't', '6', '4', 'V', 'a', 'l', 'u', 'e', 'B', '\n', '\372', 'B', '\007', '2', '\005', '\030', '\200', '\200', '\200', '\004', 
-'R', '\017', 'm', 'i', 'n', 'i', 'm', 'u', 'm', 'R', 'i', 'n', 'g', 'S', 'i', 'z', 'e', '\022', 'm', '\n', '\r', 'h', 'a', 's', 'h', 
-'_', 'f', 'u', 'n', 'c', 't', 'i', 'o', 'n', '\030', '\003', ' ', '\001', '(', '\016', '2', '>', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 
-'o', 'n', 'f', 'i', 'g', '.', 'c', 'l', 'u', 's', 't', 'e', 'r', '.', 'v', '3', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', '.', 
-'R', 'i', 'n', 'g', 'H', 'a', 's', 'h', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', '.', 'H', 'a', 's', 'h', 'F', 'u', 'n', 'c', 
-'t', 'i', 'o', 'n', 'B', '\010', '\372', 'B', '\005', '\202', '\001', '\002', '\020', '\001', 'R', '\014', 'h', 'a', 's', 'h', 'F', 'u', 'n', 'c', 't', 
-'i', 'o', 'n', '\022', 'T', '\n', '\021', 'm', 'a', 'x', 'i', 'm', 'u', 'm', '_', 'r', 'i', 'n', 'g', '_', 's', 'i', 'z', 'e', '\030', 
-'\004', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 
-'I', 'n', 't', '6', '4', 'V', 'a', 'l', 'u', 'e', 'B', '\n', '\372', 'B', '\007', '2', '\005', '\030', '\200', '\200', '\200', '\004', 'R', '\017', 'm', 
-'a', 'x', 'i', 'm', 'u', 'm', 'R', 'i', 'n', 'g', 'S', 'i', 'z', 'e', '\"', '.', '\n', '\014', 'H', 'a', 's', 'h', 'F', 'u', 'n', 
-'c', 't', 'i', 'o', 'n', '\022', '\013', '\n', '\007', 'X', 'X', '_', 'H', 'A', 'S', 'H', '\020', '\000', '\022', '\021', '\n', '\r', 'M', 'U', 'R', 
-'M', 'U', 'R', '_', 'H', 'A', 'S', 'H', '_', '2', '\020', '\001', ':', ',', '\232', '\305', '\210', '\036', '\'', '\n', '%', 'e', 'n', 'v', 'o', 
-'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', '.', 'R', 'i', 'n', 'g', 'H', 'a', 's', 'h', 
-'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', 'J', '\004', '\010', '\002', '\020', '\003', '\032', 'Y', '\n', '\016', 'M', 'a', 'g', 'l', 'e', 'v', 'L', 
-'b', 'C', 'o', 'n', 'f', 'i', 'g', '\022', 'G', '\n', '\n', 't', 'a', 'b', 'l', 'e', '_', 's', 'i', 'z', 'e', '\030', '\001', ' ', '\001', 
-'(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'I', 'n', 't', 
-'6', '4', 'V', 'a', 'l', 'u', 'e', 'B', '\n', '\372', 'B', '\007', '2', '\005', '\030', '\313', '\226', '\261', '\002', 'R', '\t', 't', 'a', 'b', 'l', 
-'e', 'S', 'i', 'z', 'e', '\032', 'n', '\n', '\023', 'O', 'r', 'i', 'g', 'i', 'n', 'a', 'l', 'D', 's', 't', 'L', 'b', 'C', 'o', 'n', 
-'f', 'i', 'g', '\022', '&', '\n', '\017', 'u', 's', 'e', '_', 'h', 't', 't', 'p', '_', 'h', 'e', 'a', 'd', 'e', 'r', '\030', '\001', ' ', 
-'\001', '(', '\010', 'R', '\r', 'u', 's', 'e', 'H', 't', 't', 'p', 'H', 'e', 'a', 'd', 'e', 'r', ':', '/', '\232', '\305', '\210', '\036', '*', 
-'\n', '(', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', '.', 'O', 'r', 
-'i', 'g', 'i', 'n', 'a', 'l', 'D', 's', 't', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', '\032', '\374', '\n', '\n', '\016', 'C', 'o', 'm', 
-'m', 'o', 'n', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', '\022', 'N', '\n', '\027', 'h', 'e', 'a', 'l', 't', 'h', 'y', '_', 'p', 'a', 
-'n', 'i', 'c', '_', 't', 'h', 'r', 'e', 's', 'h', 'o', 'l', 'd', '\030', '\001', ' ', '\001', '(', '\013', '2', '\026', '.', 'e', 'n', 'v', 
-'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'v', '3', '.', 'P', 'e', 'r', 'c', 'e', 'n', 't', 'R', '\025', 'h', 'e', 'a', 'l', 't', 
-'h', 'y', 'P', 'a', 'n', 'i', 'c', 'T', 'h', 'r', 'e', 's', 'h', 'o', 'l', 'd', '\022', 't', '\n', '\024', 'z', 'o', 'n', 'e', '_', 
-'a', 'w', 'a', 'r', 'e', '_', 'l', 'b', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\002', ' ', '\001', '(', '\013', '2', 'A', '.', 'e', 
-'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'l', 'u', 's', 't', 'e', 'r', '.', 'v', '3', '.', 'C', 'l', 
-'u', 's', 't', 'e', 'r', '.', 'C', 'o', 'm', 'm', 'o', 'n', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', '.', 'Z', 'o', 'n', 'e', 
-'A', 'w', 'a', 'r', 'e', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', 'H', '\000', 'R', '\021', 'z', 'o', 'n', 'e', 'A', 'w', 'a', 'r', 
-'e', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', '\022', '\211', '\001', '\n', '\033', 'l', 'o', 'c', 'a', 'l', 'i', 't', 'y', '_', 'w', 'e', 
-'i', 'g', 'h', 't', 'e', 'd', '_', 'l', 'b', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\003', ' ', '\001', '(', '\013', '2', 'H', '.', 
+'t', 'e', 'r', '.', 'S', 'l', 'o', 'w', 'S', 't', 'a', 'r', 't', 'C', 'o', 'n', 'f', 'i', 'g', 'R', '\017', 's', 'l', 'o', 'w', 
+'S', 't', 'a', 'r', 't', 'C', 'o', 'n', 'f', 'i', 'g', ':', '0', '\232', '\305', '\210', '\036', '+', '\n', ')', 'e', 'n', 'v', 'o', 'y', 
+'.', 'a', 'p', 'i', '.', 'v', '2', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', '.', 'L', 'e', 'a', 's', 't', 'R', 'e', 'q', 'u', 
+'e', 's', 't', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', '\032', '\221', '\003', '\n', '\020', 'R', 'i', 'n', 'g', 'H', 'a', 's', 'h', 'L', 
+'b', 'C', 'o', 'n', 'f', 'i', 'g', '\022', 'T', '\n', '\021', 'm', 'i', 'n', 'i', 'm', 'u', 'm', '_', 'r', 'i', 'n', 'g', '_', 's', 
+'i', 'z', 'e', '\030', '\001', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 
+'u', 'f', '.', 'U', 'I', 'n', 't', '6', '4', 'V', 'a', 'l', 'u', 'e', 'B', '\n', '\372', 'B', '\007', '2', '\005', '\030', '\200', '\200', '\200', 
+'\004', 'R', '\017', 'm', 'i', 'n', 'i', 'm', 'u', 'm', 'R', 'i', 'n', 'g', 'S', 'i', 'z', 'e', '\022', 'm', '\n', '\r', 'h', 'a', 's', 
+'h', '_', 'f', 'u', 'n', 'c', 't', 'i', 'o', 'n', '\030', '\003', ' ', '\001', '(', '\016', '2', '>', '.', 'e', 'n', 'v', 'o', 'y', '.', 
+'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'l', 'u', 's', 't', 'e', 'r', '.', 'v', '3', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', 
+'.', 'R', 'i', 'n', 'g', 'H', 'a', 's', 'h', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', '.', 'H', 'a', 's', 'h', 'F', 'u', 'n', 
+'c', 't', 'i', 'o', 'n', 'B', '\010', '\372', 'B', '\005', '\202', '\001', '\002', '\020', '\001', 'R', '\014', 'h', 'a', 's', 'h', 'F', 'u', 'n', 'c', 
+'t', 'i', 'o', 'n', '\022', 'T', '\n', '\021', 'm', 'a', 'x', 'i', 'm', 'u', 'm', '_', 'r', 'i', 'n', 'g', '_', 's', 'i', 'z', 'e', 
+'\030', '\004', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 
+'U', 'I', 'n', 't', '6', '4', 'V', 'a', 'l', 'u', 'e', 'B', '\n', '\372', 'B', '\007', '2', '\005', '\030', '\200', '\200', '\200', '\004', 'R', '\017', 
+'m', 'a', 'x', 'i', 'm', 'u', 'm', 'R', 'i', 'n', 'g', 'S', 'i', 'z', 'e', '\"', '.', '\n', '\014', 'H', 'a', 's', 'h', 'F', 'u', 
+'n', 'c', 't', 'i', 'o', 'n', '\022', '\013', '\n', '\007', 'X', 'X', '_', 'H', 'A', 'S', 'H', '\020', '\000', '\022', '\021', '\n', '\r', 'M', 'U', 
+'R', 'M', 'U', 'R', '_', 'H', 'A', 'S', 'H', '_', '2', '\020', '\001', ':', ',', '\232', '\305', '\210', '\036', '\'', '\n', '%', 'e', 'n', 'v', 
+'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', '.', 'R', 'i', 'n', 'g', 'H', 'a', 's', 
+'h', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', 'J', '\004', '\010', '\002', '\020', '\003', '\032', 'Y', '\n', '\016', 'M', 'a', 'g', 'l', 'e', 'v', 
+'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', '\022', 'G', '\n', '\n', 't', 'a', 'b', 'l', 'e', '_', 's', 'i', 'z', 'e', '\030', '\001', ' ', 
+'\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'I', 'n', 
+'t', '6', '4', 'V', 'a', 'l', 'u', 'e', 'B', '\n', '\372', 'B', '\007', '2', '\005', '\030', '\313', '\226', '\261', '\002', 'R', '\t', 't', 'a', 'b', 
+'l', 'e', 'S', 'i', 'z', 'e', '\032', 'n', '\n', '\023', 'O', 'r', 'i', 'g', 'i', 'n', 'a', 'l', 'D', 's', 't', 'L', 'b', 'C', 'o', 
+'n', 'f', 'i', 'g', '\022', '&', '\n', '\017', 'u', 's', 'e', '_', 'h', 't', 't', 'p', '_', 'h', 'e', 'a', 'd', 'e', 'r', '\030', '\001', 
+' ', '\001', '(', '\010', 'R', '\r', 'u', 's', 'e', 'H', 't', 't', 'p', 'H', 'e', 'a', 'd', 'e', 'r', ':', '/', '\232', '\305', '\210', '\036', 
+'*', '\n', '(', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', '.', 'O', 
+'r', 'i', 'g', 'i', 'n', 'a', 'l', 'D', 's', 't', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', '\032', '\374', '\n', '\n', '\016', 'C', 'o', 
+'m', 'm', 'o', 'n', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', '\022', 'N', '\n', '\027', 'h', 'e', 'a', 'l', 't', 'h', 'y', '_', 'p', 
+'a', 'n', 'i', 'c', '_', 't', 'h', 'r', 'e', 's', 'h', 'o', 'l', 'd', '\030', '\001', ' ', '\001', '(', '\013', '2', '\026', '.', 'e', 'n', 
+'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'v', '3', '.', 'P', 'e', 'r', 'c', 'e', 'n', 't', 'R', '\025', 'h', 'e', 'a', 'l', 
+'t', 'h', 'y', 'P', 'a', 'n', 'i', 'c', 'T', 'h', 'r', 'e', 's', 'h', 'o', 'l', 'd', '\022', 't', '\n', '\024', 'z', 'o', 'n', 'e', 
+'_', 'a', 'w', 'a', 'r', 'e', '_', 'l', 'b', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\002', ' ', '\001', '(', '\013', '2', 'A', '.', 
 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'l', 'u', 's', 't', 'e', 'r', '.', 'v', '3', '.', 'C', 
-'l', 'u', 's', 't', 'e', 'r', '.', 'C', 'o', 'm', 'm', 'o', 'n', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', '.', 'L', 'o', 'c', 
-'a', 'l', 'i', 't', 'y', 'W', 'e', 'i', 'g', 'h', 't', 'e', 'd', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', 'H', '\000', 'R', '\030', 
-'l', 'o', 'c', 'a', 'l', 'i', 't', 'y', 'W', 'e', 'i', 'g', 'h', 't', 'e', 'd', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', '\022', 
-'I', '\n', '\023', 'u', 'p', 'd', 'a', 't', 'e', '_', 'm', 'e', 'r', 'g', 'e', '_', 'w', 'i', 'n', 'd', 'o', 'w', '\030', '\004', ' ', 
-'\001', '(', '\013', '2', '\031', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'u', 'r', 
-'a', 't', 'i', 'o', 'n', 'R', '\021', 'u', 'p', 'd', 'a', 't', 'e', 'M', 'e', 'r', 'g', 'e', 'W', 'i', 'n', 'd', 'o', 'w', '\022', 
-'C', '\n', '\037', 'i', 'g', 'n', 'o', 'r', 'e', '_', 'n', 'e', 'w', '_', 'h', 'o', 's', 't', 's', '_', 'u', 'n', 't', 'i', 'l', 
-'_', 'f', 'i', 'r', 's', 't', '_', 'h', 'c', '\030', '\005', ' ', '\001', '(', '\010', 'R', '\032', 'i', 'g', 'n', 'o', 'r', 'e', 'N', 'e', 
-'w', 'H', 'o', 's', 't', 's', 'U', 'n', 't', 'i', 'l', 'F', 'i', 'r', 's', 't', 'H', 'c', '\022', 'M', '\n', '$', 'c', 'l', 'o', 
-'s', 'e', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', 's', '_', 'o', 'n', '_', 'h', 'o', 's', 't', '_', 's', 'e', 
-'t', '_', 'c', 'h', 'a', 'n', 'g', 'e', '\030', '\006', ' ', '\001', '(', '\010', 'R', '\037', 'c', 'l', 'o', 's', 'e', 'C', 'o', 'n', 'n', 
-'e', 'c', 't', 'i', 'o', 'n', 's', 'O', 'n', 'H', 'o', 's', 't', 'S', 'e', 't', 'C', 'h', 'a', 'n', 'g', 'e', '\022', '\212', '\001', 
-'\n', '\034', 'c', 'o', 'n', 's', 'i', 's', 't', 'e', 'n', 't', '_', 'h', 'a', 's', 'h', 'i', 'n', 'g', '_', 'l', 'b', '_', 'c', 
-'o', 'n', 'f', 'i', 'g', '\030', '\007', ' ', '\001', '(', '\013', '2', 'I', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 
-'g', '.', 'c', 'l', 'u', 's', 't', 'e', 'r', '.', 'v', '3', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', '.', 'C', 'o', 'm', 'm', 
-'o', 'n', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', '.', 'C', 'o', 'n', 's', 'i', 's', 't', 'e', 'n', 't', 'H', 'a', 's', 'h', 
-'i', 'n', 'g', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', 'R', '\031', 'c', 'o', 'n', 's', 'i', 's', 't', 'e', 'n', 't', 'H', 'a', 
-'s', 'h', 'i', 'n', 'g', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', '\032', '\215', '\002', '\n', '\021', 'Z', 'o', 'n', 'e', 'A', 'w', 'a', 
-'r', 'e', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', '\022', '?', '\n', '\017', 'r', 'o', 'u', 't', 'i', 'n', 'g', '_', 'e', 'n', 'a', 
-'b', 'l', 'e', 'd', '\030', '\001', ' ', '\001', '(', '\013', '2', '\026', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'v', 
-'3', '.', 'P', 'e', 'r', 'c', 'e', 'n', 't', 'R', '\016', 'r', 'o', 'u', 't', 'i', 'n', 'g', 'E', 'n', 'a', 'b', 'l', 'e', 'd', 
-'\022', 'F', '\n', '\020', 'm', 'i', 'n', '_', 'c', 'l', 'u', 's', 't', 'e', 'r', '_', 's', 'i', 'z', 'e', '\030', '\002', ' ', '\001', '(', 
-'\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'I', 'n', 't', '6', 
-'4', 'V', 'a', 'l', 'u', 'e', 'R', '\016', 'm', 'i', 'n', 'C', 'l', 'u', 's', 't', 'e', 'r', 'S', 'i', 'z', 'e', '\022', '1', '\n', 
-'\025', 'f', 'a', 'i', 'l', '_', 't', 'r', 'a', 'f', 'f', 'i', 'c', '_', 'o', 'n', '_', 'p', 'a', 'n', 'i', 'c', '\030', '\003', ' ', 
-'\001', '(', '\010', 'R', '\022', 'f', 'a', 'i', 'l', 'T', 'r', 'a', 'f', 'f', 'i', 'c', 'O', 'n', 'P', 'a', 'n', 'i', 'c', ':', '<', 
-'\232', '\305', '\210', '\036', '7', '\n', '5', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'C', 'l', 'u', 's', 't', 
-'e', 'r', '.', 'C', 'o', 'm', 'm', 'o', 'n', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', '.', 'Z', 'o', 'n', 'e', 'A', 'w', 'a', 
-'r', 'e', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', '\032', '_', '\n', '\030', 'L', 'o', 'c', 'a', 'l', 'i', 't', 'y', 'W', 'e', 'i', 
-'g', 'h', 't', 'e', 'd', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', ':', 'C', '\232', '\305', '\210', '\036', '>', '\n', '<', 'e', 'n', 'v', 
-'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', '.', 'C', 'o', 'm', 'm', 'o', 'n', 'L', 
-'b', 'C', 'o', 'n', 'f', 'i', 'g', '.', 'L', 'o', 'c', 'a', 'l', 'i', 't', 'y', 'W', 'e', 'i', 'g', 'h', 't', 'e', 'd', 'L', 
-'b', 'C', 'o', 'n', 'f', 'i', 'g', '\032', '\361', '\001', '\n', '\031', 'C', 'o', 'n', 's', 'i', 's', 't', 'e', 'n', 't', 'H', 'a', 's', 
-'h', 'i', 'n', 'g', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', '\022', '7', '\n', '\030', 'u', 's', 'e', '_', 'h', 'o', 's', 't', 'n', 
-'a', 'm', 'e', '_', 'f', 'o', 'r', '_', 'h', 'a', 's', 'h', 'i', 'n', 'g', '\030', '\001', ' ', '\001', '(', '\010', 'R', '\025', 'u', 's', 
-'e', 'H', 'o', 's', 't', 'n', 'a', 'm', 'e', 'F', 'o', 'r', 'H', 'a', 's', 'h', 'i', 'n', 'g', '\022', 'U', '\n', '\023', 'h', 'a', 
-'s', 'h', '_', 'b', 'a', 'l', 'a', 'n', 'c', 'e', '_', 'f', 'a', 'c', 't', 'o', 'r', '\030', '\002', ' ', '\001', '(', '\013', '2', '\034', 
-'.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'I', 'n', 't', '3', '2', 'V', 'a', 
-'l', 'u', 'e', 'B', '\007', '\372', 'B', '\004', '*', '\002', '(', 'd', 'R', '\021', 'h', 'a', 's', 'h', 'B', 'a', 'l', 'a', 'n', 'c', 'e', 
-'F', 'a', 'c', 't', 'o', 'r', ':', 'D', '\232', '\305', '\210', '\036', '?', '\n', '=', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 
-'v', '2', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', '.', 'C', 'o', 'm', 'm', 'o', 'n', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', 
-'.', 'C', 'o', 'n', 's', 'i', 's', 't', 'e', 'n', 't', 'H', 'a', 's', 'h', 'i', 'n', 'g', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 
-'g', ':', '*', '\232', '\305', '\210', '\036', '%', '\n', '#', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'C', 'l', 
-'u', 's', 't', 'e', 'r', '.', 'C', 'o', 'm', 'm', 'o', 'n', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', 'B', '\033', '\n', '\031', 'l', 
-'o', 'c', 'a', 'l', 'i', 't', 'y', '_', 'c', 'o', 'n', 'f', 'i', 'g', '_', 's', 'p', 'e', 'c', 'i', 'f', 'i', 'e', 'r', '\032', 
-'\322', '\001', '\n', '\013', 'R', 'e', 'f', 'r', 'e', 's', 'h', 'R', 'a', 't', 'e', '\022', 'N', '\n', '\r', 'b', 'a', 's', 'e', '_', 'i', 
-'n', 't', 'e', 'r', 'v', 'a', 'l', '\030', '\001', ' ', '\001', '(', '\013', '2', '\031', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 
-'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'u', 'r', 'a', 't', 'i', 'o', 'n', 'B', '\016', '\372', 'B', '\013', '\252', '\001', '\010', '\010', '\001', 
-'*', '\004', '\020', '\300', '\204', '=', 'R', '\014', 'b', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'v', 'a', 'l', '\022', 'J', '\n', '\014', 'm', 
-'a', 'x', '_', 'i', 'n', 't', 'e', 'r', 'v', 'a', 'l', '\030', '\002', ' ', '\001', '(', '\013', '2', '\031', '.', 'g', 'o', 'o', 'g', 'l', 
-'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'u', 'r', 'a', 't', 'i', 'o', 'n', 'B', '\014', '\372', 'B', '\t', '\252', 
-'\001', '\006', '*', '\004', '\020', '\300', '\204', '=', 'R', '\013', 'm', 'a', 'x', 'I', 'n', 't', 'e', 'r', 'v', 'a', 'l', ':', '\'', '\232', '\305', 
-'\210', '\036', '\"', '\n', ' ', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', 
-'.', 'R', 'e', 'f', 'r', 'e', 's', 'h', 'R', 'a', 't', 'e', '\032', '\203', '\002', '\n', '\020', 'P', 'r', 'e', 'c', 'o', 'n', 'n', 'e', 
-'c', 't', 'P', 'o', 'l', 'i', 'c', 'y', '\022', 'x', '\n', '\035', 'p', 'e', 'r', '_', 'u', 'p', 's', 't', 'r', 'e', 'a', 'm', '_', 
-'p', 'r', 'e', 'c', 'o', 'n', 'n', 'e', 'c', 't', '_', 'r', 'a', 't', 'i', 'o', '\030', '\001', ' ', '\001', '(', '\013', '2', '\034', '.', 
-'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'o', 'u', 'b', 'l', 'e', 'V', 'a', 'l', 
-'u', 'e', 'B', '\027', '\372', 'B', '\024', '\022', '\022', '\031', '\000', '\000', '\000', '\000', '\000', '\000', '\010', '@', ')', '\000', '\000', '\000', '\000', '\000', '\000', 
-'\360', '?', 'R', '\032', 'p', 'e', 'r', 'U', 'p', 's', 't', 'r', 'e', 'a', 'm', 'P', 'r', 'e', 'c', 'o', 'n', 'n', 'e', 'c', 't', 
-'R', 'a', 't', 'i', 'o', '\022', 'u', '\n', '\033', 'p', 'r', 'e', 'd', 'i', 'c', 't', 'i', 'v', 'e', '_', 'p', 'r', 'e', 'c', 'o', 
-'n', 'n', 'e', 'c', 't', '_', 'r', 'a', 't', 'i', 'o', '\030', '\002', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 
-'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'o', 'u', 'b', 'l', 'e', 'V', 'a', 'l', 'u', 'e', 'B', '\027', '\372', 
-'B', '\024', '\022', '\022', '\031', '\000', '\000', '\000', '\000', '\000', '\000', '\010', '@', ')', '\000', '\000', '\000', '\000', '\000', '\000', '\360', '?', 'R', '\031', 'p', 
-'r', 'e', 'd', 'i', 'c', 't', 'i', 'v', 'e', 'P', 'r', 'e', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'R', 'a', 't', 'i', 'o', '\032', 
-'f', '\n', '\"', 'T', 'y', 'p', 'e', 'd', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 
-'O', 'p', 't', 'i', 'o', 'n', 's', 'E', 'n', 't', 'r', 'y', '\022', '\020', '\n', '\003', 'k', 'e', 'y', '\030', '\001', ' ', '\001', '(', '\t', 
-'R', '\003', 'k', 'e', 'y', '\022', '*', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\001', '(', '\013', '2', '\024', '.', 'g', 'o', 
-'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'A', 'n', 'y', 'R', '\005', 'v', 'a', 'l', 'u', 'e', ':', 
-'\002', '8', '\001', '\"', 'W', '\n', '\r', 'D', 'i', 's', 'c', 'o', 'v', 'e', 'r', 'y', 'T', 'y', 'p', 'e', '\022', '\n', '\n', '\006', 'S', 
-'T', 'A', 'T', 'I', 'C', '\020', '\000', '\022', '\016', '\n', '\n', 'S', 'T', 'R', 'I', 'C', 'T', '_', 'D', 'N', 'S', '\020', '\001', '\022', '\017', 
-'\n', '\013', 'L', 'O', 'G', 'I', 'C', 'A', 'L', '_', 'D', 'N', 'S', '\020', '\002', '\022', '\007', '\n', '\003', 'E', 'D', 'S', '\020', '\003', '\022', 
-'\020', '\n', '\014', 'O', 'R', 'I', 'G', 'I', 'N', 'A', 'L', '_', 'D', 'S', 'T', '\020', '\004', '\"', '\244', '\001', '\n', '\010', 'L', 'b', 'P', 
-'o', 'l', 'i', 'c', 'y', '\022', '\017', '\n', '\013', 'R', 'O', 'U', 'N', 'D', '_', 'R', 'O', 'B', 'I', 'N', '\020', '\000', '\022', '\021', '\n', 
-'\r', 'L', 'E', 'A', 'S', 'T', '_', 'R', 'E', 'Q', 'U', 'E', 'S', 'T', '\020', '\001', '\022', '\r', '\n', '\t', 'R', 'I', 'N', 'G', '_', 
-'H', 'A', 'S', 'H', '\020', '\002', '\022', '\n', '\n', '\006', 'R', 'A', 'N', 'D', 'O', 'M', '\020', '\003', '\022', '\n', '\n', '\006', 'M', 'A', 'G', 
-'L', 'E', 'V', '\020', '\005', '\022', '\024', '\n', '\020', 'C', 'L', 'U', 'S', 'T', 'E', 'R', '_', 'P', 'R', 'O', 'V', 'I', 'D', 'E', 'D', 
-'\020', '\006', '\022', ' ', '\n', '\034', 'L', 'O', 'A', 'D', '_', 'B', 'A', 'L', 'A', 'N', 'C', 'I', 'N', 'G', '_', 'P', 'O', 'L', 'I', 
-'C', 'Y', '_', 'C', 'O', 'N', 'F', 'I', 'G', '\020', '\007', '\"', '\004', '\010', '\004', '\020', '\004', '*', '\017', 'O', 'R', 'I', 'G', 'I', 'N', 
-'A', 'L', '_', 'D', 'S', 'T', '_', 'L', 'B', '\"', '5', '\n', '\017', 'D', 'n', 's', 'L', 'o', 'o', 'k', 'u', 'p', 'F', 'a', 'm', 
-'i', 'l', 'y', '\022', '\010', '\n', '\004', 'A', 'U', 'T', 'O', '\020', '\000', '\022', '\013', '\n', '\007', 'V', '4', '_', 'O', 'N', 'L', 'Y', '\020', 
-'\001', '\022', '\013', '\n', '\007', 'V', '6', '_', 'O', 'N', 'L', 'Y', '\020', '\002', '\"', 'T', '\n', '\030', 'C', 'l', 'u', 's', 't', 'e', 'r', 
-'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'S', 'e', 'l', 'e', 'c', 't', 'i', 'o', 'n', '\022', '\033', '\n', '\027', 'U', 'S', 'E', '_', 
-'C', 'O', 'N', 'F', 'I', 'G', 'U', 'R', 'E', 'D', '_', 'P', 'R', 'O', 'T', 'O', 'C', 'O', 'L', '\020', '\000', '\022', '\033', '\n', '\027', 
-'U', 'S', 'E', '_', 'D', 'O', 'W', 'N', 'S', 'T', 'R', 'E', 'A', 'M', '_', 'P', 'R', 'O', 'T', 'O', 'C', 'O', 'L', '\020', '\001', 
-':', '\033', '\232', '\305', '\210', '\036', '\026', '\n', '\024', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'C', 'l', 'u', 
-'s', 't', 'e', 'r', 'B', '\030', '\n', '\026', 'c', 'l', 'u', 's', 't', 'e', 'r', '_', 'd', 'i', 's', 'c', 'o', 'v', 'e', 'r', 'y', 
-'_', 't', 'y', 'p', 'e', 'B', '\013', '\n', '\t', 'l', 'b', '_', 'c', 'o', 'n', 'f', 'i', 'g', 'J', '\004', '\010', '\014', '\020', '\r', 'J', 
-'\004', '\010', '\017', '\020', '\020', 'J', '\004', '\010', '\007', '\020', '\010', 'J', '\004', '\010', '\013', '\020', '\014', 'J', '\004', '\010', '#', '\020', '$', 'R', '\005', 
-'h', 'o', 's', 't', 's', 'R', '\013', 't', 'l', 's', '_', 'c', 'o', 'n', 't', 'e', 'x', 't', 'R', '\032', 'e', 'x', 't', 'e', 'n', 
-'s', 'i', 'o', 'n', '_', 'p', 'r', 'o', 't', 'o', 'c', 'o', 'l', '_', 'o', 'p', 't', 'i', 'o', 'n', 's', '\"', '\332', '\002', '\n', 
-'\023', 'L', 'o', 'a', 'd', 'B', 'a', 'l', 'a', 'n', 'c', 'i', 'n', 'g', 'P', 'o', 'l', 'i', 'c', 'y', '\022', 'O', '\n', '\010', 'p', 
-'o', 'l', 'i', 'c', 'i', 'e', 's', '\030', '\001', ' ', '\003', '(', '\013', '2', '3', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 
-'f', 'i', 'g', '.', 'c', 'l', 'u', 's', 't', 'e', 'r', '.', 'v', '3', '.', 'L', 'o', 'a', 'd', 'B', 'a', 'l', 'a', 'n', 'c', 
-'i', 'n', 'g', 'P', 'o', 'l', 'i', 'c', 'y', '.', 'P', 'o', 'l', 'i', 'c', 'y', 'R', '\010', 'p', 'o', 'l', 'i', 'c', 'i', 'e', 
-'s', '\032', '\310', '\001', '\n', '\006', 'P', 'o', 'l', 'i', 'c', 'y', '\022', '`', '\n', '\026', 't', 'y', 'p', 'e', 'd', '_', 'e', 'x', 't', 
-'e', 'n', 's', 'i', 'o', 'n', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\004', ' ', '\001', '(', '\013', '2', '*', '.', 'e', 'n', 'v', 
-'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'T', 'y', 'p', 'e', 'd', 'E', 'x', 
-'t', 'e', 'n', 's', 'i', 'o', 'n', 'C', 'o', 'n', 'f', 'i', 'g', 'R', '\024', 't', 'y', 'p', 'e', 'd', 'E', 'x', 't', 'e', 'n', 
-'s', 'i', 'o', 'n', 'C', 'o', 'n', 'f', 'i', 'g', ':', '.', '\232', '\305', '\210', '\036', ')', '\n', '\'', 'e', 'n', 'v', 'o', 'y', '.', 
-'a', 'p', 'i', '.', 'v', '2', '.', 'L', 'o', 'a', 'd', 'B', 'a', 'l', 'a', 'n', 'c', 'i', 'n', 'g', 'P', 'o', 'l', 'i', 'c', 
-'y', '.', 'P', 'o', 'l', 'i', 'c', 'y', 'J', '\004', '\010', '\002', '\020', '\003', 'J', '\004', '\010', '\001', '\020', '\002', 'J', '\004', '\010', '\003', '\020', 
-'\004', 'R', '\006', 'c', 'o', 'n', 'f', 'i', 'g', 'R', '\004', 'n', 'a', 'm', 'e', 'R', '\014', 't', 'y', 'p', 'e', 'd', '_', 'c', 'o', 
-'n', 'f', 'i', 'g', ':', '\'', '\232', '\305', '\210', '\036', '\"', '\n', ' ', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', 
-'.', 'L', 'o', 'a', 'd', 'B', 'a', 'l', 'a', 'n', 'c', 'i', 'n', 'g', 'P', 'o', 'l', 'i', 'c', 'y', '\"', '\202', '\001', '\n', '\022', 
-'U', 'p', 's', 't', 'r', 'e', 'a', 'm', 'B', 'i', 'n', 'd', 'C', 'o', 'n', 'f', 'i', 'g', '\022', 'D', '\n', '\016', 's', 'o', 'u', 
-'r', 'c', 'e', '_', 'a', 'd', 'd', 'r', 'e', 's', 's', '\030', '\001', ' ', '\001', '(', '\013', '2', '\035', '.', 'e', 'n', 'v', 'o', 'y', 
-'.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'A', 'd', 'd', 'r', 'e', 's', 's', 'R', '\r', 
-'s', 'o', 'u', 'r', 'c', 'e', 'A', 'd', 'd', 'r', 'e', 's', 's', ':', '&', '\232', '\305', '\210', '\036', '!', '\n', '\037', 'e', 'n', 'v', 
-'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'U', 'p', 's', 't', 'r', 'e', 'a', 'm', 'B', 'i', 'n', 'd', 'C', 'o', 'n', 
-'f', 'i', 'g', '\"', '\223', '\001', '\n', '\031', 'U', 'p', 's', 't', 'r', 'e', 'a', 'm', 'C', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 
-'n', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', 'G', '\n', '\r', 't', 'c', 'p', '_', 'k', 'e', 'e', 'p', 'a', 'l', 'i', 'v', 'e', 
-'\030', '\001', ' ', '\001', '(', '\013', '2', '\"', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 
-'e', '.', 'v', '3', '.', 'T', 'c', 'p', 'K', 'e', 'e', 'p', 'a', 'l', 'i', 'v', 'e', 'R', '\014', 't', 'c', 'p', 'K', 'e', 'e', 
-'p', 'a', 'l', 'i', 'v', 'e', ':', '-', '\232', '\305', '\210', '\036', '(', '\n', '&', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 
-'v', '2', '.', 'U', 'p', 's', 't', 'r', 'e', 'a', 'm', 'C', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', 'O', 'p', 't', 'i', 
-'o', 'n', 's', '\"', 'r', '\n', '\021', 'T', 'r', 'a', 'c', 'k', 'C', 'l', 'u', 's', 't', 'e', 'r', 'S', 't', 'a', 't', 's', '\022', 
-'\'', '\n', '\017', 't', 'i', 'm', 'e', 'o', 'u', 't', '_', 'b', 'u', 'd', 'g', 'e', 't', 's', '\030', '\001', ' ', '\001', '(', '\010', 'R', 
-'\016', 't', 'i', 'm', 'e', 'o', 'u', 't', 'B', 'u', 'd', 'g', 'e', 't', 's', '\022', '4', '\n', '\026', 'r', 'e', 'q', 'u', 'e', 's', 
-'t', '_', 'r', 'e', 's', 'p', 'o', 'n', 's', 'e', '_', 's', 'i', 'z', 'e', 's', '\030', '\002', ' ', '\001', '(', '\010', 'R', '\024', 'r', 
-'e', 'q', 'u', 'e', 's', 't', 'R', 'e', 's', 'p', 'o', 'n', 's', 'e', 'S', 'i', 'z', 'e', 's', 'B', '?', '\n', '%', 'i', 'o', 
-'.', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 
-'c', 'l', 'u', 's', 't', 'e', 'r', '.', 'v', '3', 'B', '\014', 'C', 'l', 'u', 's', 't', 'e', 'r', 'P', 'r', 'o', 't', 'o', 'P', 
-'\001', '\272', '\200', '\310', '\321', '\006', '\002', '\020', '\002', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', 
+'l', 'u', 's', 't', 'e', 'r', '.', 'C', 'o', 'm', 'm', 'o', 'n', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', '.', 'Z', 'o', 'n', 
+'e', 'A', 'w', 'a', 'r', 'e', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', 'H', '\000', 'R', '\021', 'z', 'o', 'n', 'e', 'A', 'w', 'a', 
+'r', 'e', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', '\022', '\211', '\001', '\n', '\033', 'l', 'o', 'c', 'a', 'l', 'i', 't', 'y', '_', 'w', 
+'e', 'i', 'g', 'h', 't', 'e', 'd', '_', 'l', 'b', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\003', ' ', '\001', '(', '\013', '2', 'H', 
+'.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'l', 'u', 's', 't', 'e', 'r', '.', 'v', '3', '.', 
+'C', 'l', 'u', 's', 't', 'e', 'r', '.', 'C', 'o', 'm', 'm', 'o', 'n', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', '.', 'L', 'o', 
+'c', 'a', 'l', 'i', 't', 'y', 'W', 'e', 'i', 'g', 'h', 't', 'e', 'd', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', 'H', '\000', 'R', 
+'\030', 'l', 'o', 'c', 'a', 'l', 'i', 't', 'y', 'W', 'e', 'i', 'g', 'h', 't', 'e', 'd', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', 
+'\022', 'I', '\n', '\023', 'u', 'p', 'd', 'a', 't', 'e', '_', 'm', 'e', 'r', 'g', 'e', '_', 'w', 'i', 'n', 'd', 'o', 'w', '\030', '\004', 
+' ', '\001', '(', '\013', '2', '\031', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'u', 
+'r', 'a', 't', 'i', 'o', 'n', 'R', '\021', 'u', 'p', 'd', 'a', 't', 'e', 'M', 'e', 'r', 'g', 'e', 'W', 'i', 'n', 'd', 'o', 'w', 
+'\022', 'C', '\n', '\037', 'i', 'g', 'n', 'o', 'r', 'e', '_', 'n', 'e', 'w', '_', 'h', 'o', 's', 't', 's', '_', 'u', 'n', 't', 'i', 
+'l', '_', 'f', 'i', 'r', 's', 't', '_', 'h', 'c', '\030', '\005', ' ', '\001', '(', '\010', 'R', '\032', 'i', 'g', 'n', 'o', 'r', 'e', 'N', 
+'e', 'w', 'H', 'o', 's', 't', 's', 'U', 'n', 't', 'i', 'l', 'F', 'i', 'r', 's', 't', 'H', 'c', '\022', 'M', '\n', '$', 'c', 'l', 
+'o', 's', 'e', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', 's', '_', 'o', 'n', '_', 'h', 'o', 's', 't', '_', 's', 
+'e', 't', '_', 'c', 'h', 'a', 'n', 'g', 'e', '\030', '\006', ' ', '\001', '(', '\010', 'R', '\037', 'c', 'l', 'o', 's', 'e', 'C', 'o', 'n', 
+'n', 'e', 'c', 't', 'i', 'o', 'n', 's', 'O', 'n', 'H', 'o', 's', 't', 'S', 'e', 't', 'C', 'h', 'a', 'n', 'g', 'e', '\022', '\212', 
+'\001', '\n', '\034', 'c', 'o', 'n', 's', 'i', 's', 't', 'e', 'n', 't', '_', 'h', 'a', 's', 'h', 'i', 'n', 'g', '_', 'l', 'b', '_', 
+'c', 'o', 'n', 'f', 'i', 'g', '\030', '\007', ' ', '\001', '(', '\013', '2', 'I', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 
+'i', 'g', '.', 'c', 'l', 'u', 's', 't', 'e', 'r', '.', 'v', '3', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', '.', 'C', 'o', 'm', 
+'m', 'o', 'n', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', '.', 'C', 'o', 'n', 's', 'i', 's', 't', 'e', 'n', 't', 'H', 'a', 's', 
+'h', 'i', 'n', 'g', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', 'R', '\031', 'c', 'o', 'n', 's', 'i', 's', 't', 'e', 'n', 't', 'H', 
+'a', 's', 'h', 'i', 'n', 'g', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', '\032', '\215', '\002', '\n', '\021', 'Z', 'o', 'n', 'e', 'A', 'w', 
+'a', 'r', 'e', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', '\022', '?', '\n', '\017', 'r', 'o', 'u', 't', 'i', 'n', 'g', '_', 'e', 'n', 
+'a', 'b', 'l', 'e', 'd', '\030', '\001', ' ', '\001', '(', '\013', '2', '\026', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 
+'v', '3', '.', 'P', 'e', 'r', 'c', 'e', 'n', 't', 'R', '\016', 'r', 'o', 'u', 't', 'i', 'n', 'g', 'E', 'n', 'a', 'b', 'l', 'e', 
+'d', '\022', 'F', '\n', '\020', 'm', 'i', 'n', '_', 'c', 'l', 'u', 's', 't', 'e', 'r', '_', 's', 'i', 'z', 'e', '\030', '\002', ' ', '\001', 
+'(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'I', 'n', 't', 
+'6', '4', 'V', 'a', 'l', 'u', 'e', 'R', '\016', 'm', 'i', 'n', 'C', 'l', 'u', 's', 't', 'e', 'r', 'S', 'i', 'z', 'e', '\022', '1', 
+'\n', '\025', 'f', 'a', 'i', 'l', '_', 't', 'r', 'a', 'f', 'f', 'i', 'c', '_', 'o', 'n', '_', 'p', 'a', 'n', 'i', 'c', '\030', '\003', 
+' ', '\001', '(', '\010', 'R', '\022', 'f', 'a', 'i', 'l', 'T', 'r', 'a', 'f', 'f', 'i', 'c', 'O', 'n', 'P', 'a', 'n', 'i', 'c', ':', 
+'<', '\232', '\305', '\210', '\036', '7', '\n', '5', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'C', 'l', 'u', 's', 
+'t', 'e', 'r', '.', 'C', 'o', 'm', 'm', 'o', 'n', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', '.', 'Z', 'o', 'n', 'e', 'A', 'w', 
+'a', 'r', 'e', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', '\032', '_', '\n', '\030', 'L', 'o', 'c', 'a', 'l', 'i', 't', 'y', 'W', 'e', 
+'i', 'g', 'h', 't', 'e', 'd', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', ':', 'C', '\232', '\305', '\210', '\036', '>', '\n', '<', 'e', 'n', 
+'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', '.', 'C', 'o', 'm', 'm', 'o', 'n', 
+'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', '.', 'L', 'o', 'c', 'a', 'l', 'i', 't', 'y', 'W', 'e', 'i', 'g', 'h', 't', 'e', 'd', 
+'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', '\032', '\361', '\001', '\n', '\031', 'C', 'o', 'n', 's', 'i', 's', 't', 'e', 'n', 't', 'H', 'a', 
+'s', 'h', 'i', 'n', 'g', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', '\022', '7', '\n', '\030', 'u', 's', 'e', '_', 'h', 'o', 's', 't', 
+'n', 'a', 'm', 'e', '_', 'f', 'o', 'r', '_', 'h', 'a', 's', 'h', 'i', 'n', 'g', '\030', '\001', ' ', '\001', '(', '\010', 'R', '\025', 'u', 
+'s', 'e', 'H', 'o', 's', 't', 'n', 'a', 'm', 'e', 'F', 'o', 'r', 'H', 'a', 's', 'h', 'i', 'n', 'g', '\022', 'U', '\n', '\023', 'h', 
+'a', 's', 'h', '_', 'b', 'a', 'l', 'a', 'n', 'c', 'e', '_', 'f', 'a', 'c', 't', 'o', 'r', '\030', '\002', ' ', '\001', '(', '\013', '2', 
+'\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'I', 'n', 't', '3', '2', 'V', 
+'a', 'l', 'u', 'e', 'B', '\007', '\372', 'B', '\004', '*', '\002', '(', 'd', 'R', '\021', 'h', 'a', 's', 'h', 'B', 'a', 'l', 'a', 'n', 'c', 
+'e', 'F', 'a', 'c', 't', 'o', 'r', ':', 'D', '\232', '\305', '\210', '\036', '?', '\n', '=', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', 
+'.', 'v', '2', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', '.', 'C', 'o', 'm', 'm', 'o', 'n', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 
+'g', '.', 'C', 'o', 'n', 's', 'i', 's', 't', 'e', 'n', 't', 'H', 'a', 's', 'h', 'i', 'n', 'g', 'L', 'b', 'C', 'o', 'n', 'f', 
+'i', 'g', ':', '*', '\232', '\305', '\210', '\036', '%', '\n', '#', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'C', 
+'l', 'u', 's', 't', 'e', 'r', '.', 'C', 'o', 'm', 'm', 'o', 'n', 'L', 'b', 'C', 'o', 'n', 'f', 'i', 'g', 'B', '\033', '\n', '\031', 
+'l', 'o', 'c', 'a', 'l', 'i', 't', 'y', '_', 'c', 'o', 'n', 'f', 'i', 'g', '_', 's', 'p', 'e', 'c', 'i', 'f', 'i', 'e', 'r', 
+'\032', '\322', '\001', '\n', '\013', 'R', 'e', 'f', 'r', 'e', 's', 'h', 'R', 'a', 't', 'e', '\022', 'N', '\n', '\r', 'b', 'a', 's', 'e', '_', 
+'i', 'n', 't', 'e', 'r', 'v', 'a', 'l', '\030', '\001', ' ', '\001', '(', '\013', '2', '\031', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 
+'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'u', 'r', 'a', 't', 'i', 'o', 'n', 'B', '\016', '\372', 'B', '\013', '\252', '\001', '\010', '\010', 
+'\001', '*', '\004', '\020', '\300', '\204', '=', 'R', '\014', 'b', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'v', 'a', 'l', '\022', 'J', '\n', '\014', 
+'m', 'a', 'x', '_', 'i', 'n', 't', 'e', 'r', 'v', 'a', 'l', '\030', '\002', ' ', '\001', '(', '\013', '2', '\031', '.', 'g', 'o', 'o', 'g', 
+'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'u', 'r', 'a', 't', 'i', 'o', 'n', 'B', '\014', '\372', 'B', '\t', 
+'\252', '\001', '\006', '*', '\004', '\020', '\300', '\204', '=', 'R', '\013', 'm', 'a', 'x', 'I', 'n', 't', 'e', 'r', 'v', 'a', 'l', ':', '\'', '\232', 
+'\305', '\210', '\036', '\"', '\n', ' ', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'C', 'l', 'u', 's', 't', 'e', 
+'r', '.', 'R', 'e', 'f', 'r', 'e', 's', 'h', 'R', 'a', 't', 'e', '\032', '\203', '\002', '\n', '\020', 'P', 'r', 'e', 'c', 'o', 'n', 'n', 
+'e', 'c', 't', 'P', 'o', 'l', 'i', 'c', 'y', '\022', 'x', '\n', '\035', 'p', 'e', 'r', '_', 'u', 'p', 's', 't', 'r', 'e', 'a', 'm', 
+'_', 'p', 'r', 'e', 'c', 'o', 'n', 'n', 'e', 'c', 't', '_', 'r', 'a', 't', 'i', 'o', '\030', '\001', ' ', '\001', '(', '\013', '2', '\034', 
+'.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'o', 'u', 'b', 'l', 'e', 'V', 'a', 
+'l', 'u', 'e', 'B', '\027', '\372', 'B', '\024', '\022', '\022', '\031', '\000', '\000', '\000', '\000', '\000', '\000', '\010', '@', ')', '\000', '\000', '\000', '\000', '\000', 
+'\000', '\360', '?', 'R', '\032', 'p', 'e', 'r', 'U', 'p', 's', 't', 'r', 'e', 'a', 'm', 'P', 'r', 'e', 'c', 'o', 'n', 'n', 'e', 'c', 
+'t', 'R', 'a', 't', 'i', 'o', '\022', 'u', '\n', '\033', 'p', 'r', 'e', 'd', 'i', 'c', 't', 'i', 'v', 'e', '_', 'p', 'r', 'e', 'c', 
+'o', 'n', 'n', 'e', 'c', 't', '_', 'r', 'a', 't', 'i', 'o', '\030', '\002', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 
+'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'o', 'u', 'b', 'l', 'e', 'V', 'a', 'l', 'u', 'e', 'B', '\027', 
+'\372', 'B', '\024', '\022', '\022', '\031', '\000', '\000', '\000', '\000', '\000', '\000', '\010', '@', ')', '\000', '\000', '\000', '\000', '\000', '\000', '\360', '?', 'R', '\031', 
+'p', 'r', 'e', 'd', 'i', 'c', 't', 'i', 'v', 'e', 'P', 'r', 'e', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'R', 'a', 't', 'i', 'o', 
+'\032', 'f', '\n', '\"', 'T', 'y', 'p', 'e', 'd', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'P', 'r', 'o', 't', 'o', 'c', 'o', 
+'l', 'O', 'p', 't', 'i', 'o', 'n', 's', 'E', 'n', 't', 'r', 'y', '\022', '\020', '\n', '\003', 'k', 'e', 'y', '\030', '\001', ' ', '\001', '(', 
+'\t', 'R', '\003', 'k', 'e', 'y', '\022', '*', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\001', '(', '\013', '2', '\024', '.', 'g', 
+'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'A', 'n', 'y', 'R', '\005', 'v', 'a', 'l', 'u', 'e', 
+':', '\002', '8', '\001', '\"', 'W', '\n', '\r', 'D', 'i', 's', 'c', 'o', 'v', 'e', 'r', 'y', 'T', 'y', 'p', 'e', '\022', '\n', '\n', '\006', 
+'S', 'T', 'A', 'T', 'I', 'C', '\020', '\000', '\022', '\016', '\n', '\n', 'S', 'T', 'R', 'I', 'C', 'T', '_', 'D', 'N', 'S', '\020', '\001', '\022', 
+'\017', '\n', '\013', 'L', 'O', 'G', 'I', 'C', 'A', 'L', '_', 'D', 'N', 'S', '\020', '\002', '\022', '\007', '\n', '\003', 'E', 'D', 'S', '\020', '\003', 
+'\022', '\020', '\n', '\014', 'O', 'R', 'I', 'G', 'I', 'N', 'A', 'L', '_', 'D', 'S', 'T', '\020', '\004', '\"', '\244', '\001', '\n', '\010', 'L', 'b', 
+'P', 'o', 'l', 'i', 'c', 'y', '\022', '\017', '\n', '\013', 'R', 'O', 'U', 'N', 'D', '_', 'R', 'O', 'B', 'I', 'N', '\020', '\000', '\022', '\021', 
+'\n', '\r', 'L', 'E', 'A', 'S', 'T', '_', 'R', 'E', 'Q', 'U', 'E', 'S', 'T', '\020', '\001', '\022', '\r', '\n', '\t', 'R', 'I', 'N', 'G', 
+'_', 'H', 'A', 'S', 'H', '\020', '\002', '\022', '\n', '\n', '\006', 'R', 'A', 'N', 'D', 'O', 'M', '\020', '\003', '\022', '\n', '\n', '\006', 'M', 'A', 
+'G', 'L', 'E', 'V', '\020', '\005', '\022', '\024', '\n', '\020', 'C', 'L', 'U', 'S', 'T', 'E', 'R', '_', 'P', 'R', 'O', 'V', 'I', 'D', 'E', 
+'D', '\020', '\006', '\022', ' ', '\n', '\034', 'L', 'O', 'A', 'D', '_', 'B', 'A', 'L', 'A', 'N', 'C', 'I', 'N', 'G', '_', 'P', 'O', 'L', 
+'I', 'C', 'Y', '_', 'C', 'O', 'N', 'F', 'I', 'G', '\020', '\007', '\"', '\004', '\010', '\004', '\020', '\004', '*', '\017', 'O', 'R', 'I', 'G', 'I', 
+'N', 'A', 'L', '_', 'D', 'S', 'T', '_', 'L', 'B', '\"', 'G', '\n', '\017', 'D', 'n', 's', 'L', 'o', 'o', 'k', 'u', 'p', 'F', 'a', 
+'m', 'i', 'l', 'y', '\022', '\010', '\n', '\004', 'A', 'U', 'T', 'O', '\020', '\000', '\022', '\013', '\n', '\007', 'V', '4', '_', 'O', 'N', 'L', 'Y', 
+'\020', '\001', '\022', '\013', '\n', '\007', 'V', '6', '_', 'O', 'N', 'L', 'Y', '\020', '\002', '\022', '\020', '\n', '\014', 'V', '4', '_', 'P', 'R', 'E', 
+'F', 'E', 'R', 'R', 'E', 'D', '\020', '\003', '\"', 'T', '\n', '\030', 'C', 'l', 'u', 's', 't', 'e', 'r', 'P', 'r', 'o', 't', 'o', 'c', 
+'o', 'l', 'S', 'e', 'l', 'e', 'c', 't', 'i', 'o', 'n', '\022', '\033', '\n', '\027', 'U', 'S', 'E', '_', 'C', 'O', 'N', 'F', 'I', 'G', 
+'U', 'R', 'E', 'D', '_', 'P', 'R', 'O', 'T', 'O', 'C', 'O', 'L', '\020', '\000', '\022', '\033', '\n', '\027', 'U', 'S', 'E', '_', 'D', 'O', 
+'W', 'N', 'S', 'T', 'R', 'E', 'A', 'M', '_', 'P', 'R', 'O', 'T', 'O', 'C', 'O', 'L', '\020', '\001', ':', '\033', '\232', '\305', '\210', '\036', 
+'\026', '\n', '\024', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', 'B', '\030', 
+'\n', '\026', 'c', 'l', 'u', 's', 't', 'e', 'r', '_', 'd', 'i', 's', 'c', 'o', 'v', 'e', 'r', 'y', '_', 't', 'y', 'p', 'e', 'B', 
+'\013', '\n', '\t', 'l', 'b', '_', 'c', 'o', 'n', 'f', 'i', 'g', 'J', '\004', '\010', '\014', '\020', '\r', 'J', '\004', '\010', '\017', '\020', '\020', 'J', 
+'\004', '\010', '\007', '\020', '\010', 'J', '\004', '\010', '\013', '\020', '\014', 'J', '\004', '\010', '#', '\020', '$', 'R', '\005', 'h', 'o', 's', 't', 's', 'R', 
+'\013', 't', 'l', 's', '_', 'c', 'o', 'n', 't', 'e', 'x', 't', 'R', '\032', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', '_', 'p', 
+'r', 'o', 't', 'o', 'c', 'o', 'l', '_', 'o', 'p', 't', 'i', 'o', 'n', 's', '\"', '\332', '\002', '\n', '\023', 'L', 'o', 'a', 'd', 'B', 
+'a', 'l', 'a', 'n', 'c', 'i', 'n', 'g', 'P', 'o', 'l', 'i', 'c', 'y', '\022', 'O', '\n', '\010', 'p', 'o', 'l', 'i', 'c', 'i', 'e', 
+'s', '\030', '\001', ' ', '\003', '(', '\013', '2', '3', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'l', 
+'u', 's', 't', 'e', 'r', '.', 'v', '3', '.', 'L', 'o', 'a', 'd', 'B', 'a', 'l', 'a', 'n', 'c', 'i', 'n', 'g', 'P', 'o', 'l', 
+'i', 'c', 'y', '.', 'P', 'o', 'l', 'i', 'c', 'y', 'R', '\010', 'p', 'o', 'l', 'i', 'c', 'i', 'e', 's', '\032', '\310', '\001', '\n', '\006', 
+'P', 'o', 'l', 'i', 'c', 'y', '\022', '`', '\n', '\026', 't', 'y', 'p', 'e', 'd', '_', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 
+'_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\004', ' ', '\001', '(', '\013', '2', '*', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 
+'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'T', 'y', 'p', 'e', 'd', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 
+'n', 'C', 'o', 'n', 'f', 'i', 'g', 'R', '\024', 't', 'y', 'p', 'e', 'd', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'C', 'o', 
+'n', 'f', 'i', 'g', ':', '.', '\232', '\305', '\210', '\036', ')', '\n', '\'', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', 
+'.', 'L', 'o', 'a', 'd', 'B', 'a', 'l', 'a', 'n', 'c', 'i', 'n', 'g', 'P', 'o', 'l', 'i', 'c', 'y', '.', 'P', 'o', 'l', 'i', 
+'c', 'y', 'J', '\004', '\010', '\002', '\020', '\003', 'J', '\004', '\010', '\001', '\020', '\002', 'J', '\004', '\010', '\003', '\020', '\004', 'R', '\006', 'c', 'o', 'n', 
+'f', 'i', 'g', 'R', '\004', 'n', 'a', 'm', 'e', 'R', '\014', 't', 'y', 'p', 'e', 'd', '_', 'c', 'o', 'n', 'f', 'i', 'g', ':', '\'', 
+'\232', '\305', '\210', '\036', '\"', '\n', ' ', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'L', 'o', 'a', 'd', 'B', 
+'a', 'l', 'a', 'n', 'c', 'i', 'n', 'g', 'P', 'o', 'l', 'i', 'c', 'y', '\"', '\202', '\001', '\n', '\022', 'U', 'p', 's', 't', 'r', 'e', 
+'a', 'm', 'B', 'i', 'n', 'd', 'C', 'o', 'n', 'f', 'i', 'g', '\022', 'D', '\n', '\016', 's', 'o', 'u', 'r', 'c', 'e', '_', 'a', 'd', 
+'d', 'r', 'e', 's', 's', '\030', '\001', ' ', '\001', '(', '\013', '2', '\035', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 
+'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'A', 'd', 'd', 'r', 'e', 's', 's', 'R', '\r', 's', 'o', 'u', 'r', 'c', 'e', 
+'A', 'd', 'd', 'r', 'e', 's', 's', ':', '&', '\232', '\305', '\210', '\036', '!', '\n', '\037', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', 
+'.', 'v', '2', '.', 'U', 'p', 's', 't', 'r', 'e', 'a', 'm', 'B', 'i', 'n', 'd', 'C', 'o', 'n', 'f', 'i', 'g', '\"', '\223', '\001', 
+'\n', '\031', 'U', 'p', 's', 't', 'r', 'e', 'a', 'm', 'C', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', 'O', 'p', 't', 'i', 'o', 
+'n', 's', '\022', 'G', '\n', '\r', 't', 'c', 'p', '_', 'k', 'e', 'e', 'p', 'a', 'l', 'i', 'v', 'e', '\030', '\001', ' ', '\001', '(', '\013', 
+'2', '\"', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'T', 
+'c', 'p', 'K', 'e', 'e', 'p', 'a', 'l', 'i', 'v', 'e', 'R', '\014', 't', 'c', 'p', 'K', 'e', 'e', 'p', 'a', 'l', 'i', 'v', 'e', 
+':', '-', '\232', '\305', '\210', '\036', '(', '\n', '&', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'U', 'p', 's', 
+'t', 'r', 'e', 'a', 'm', 'C', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', 'O', 'p', 't', 'i', 'o', 'n', 's', '\"', 'r', '\n', 
+'\021', 'T', 'r', 'a', 'c', 'k', 'C', 'l', 'u', 's', 't', 'e', 'r', 'S', 't', 'a', 't', 's', '\022', '\'', '\n', '\017', 't', 'i', 'm', 
+'e', 'o', 'u', 't', '_', 'b', 'u', 'd', 'g', 'e', 't', 's', '\030', '\001', ' ', '\001', '(', '\010', 'R', '\016', 't', 'i', 'm', 'e', 'o', 
+'u', 't', 'B', 'u', 'd', 'g', 'e', 't', 's', '\022', '4', '\n', '\026', 'r', 'e', 'q', 'u', 'e', 's', 't', '_', 'r', 'e', 's', 'p', 
+'o', 'n', 's', 'e', '_', 's', 'i', 'z', 'e', 's', '\030', '\002', ' ', '\001', '(', '\010', 'R', '\024', 'r', 'e', 'q', 'u', 'e', 's', 't', 
+'R', 'e', 's', 'p', 'o', 'n', 's', 'e', 'S', 'i', 'z', 'e', 's', 'B', '?', '\n', '%', 'i', 'o', '.', 'e', 'n', 'v', 'o', 'y', 
+'p', 'r', 'o', 'x', 'y', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'l', 'u', 's', 't', 'e', 
+'r', '.', 'v', '3', 'B', '\014', 'C', 'l', 'u', 's', 't', 'e', 'r', 'P', 'r', 'o', 't', 'o', 'P', '\001', '\272', '\200', '\310', '\321', '\006', 
+'\002', '\020', '\002', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', 
 };
 
 static upb_def_init *deps[24] = {
@@ -568,5 +592,5 @@ upb_def_init envoy_config_cluster_v3_cluster_proto_upbdefinit = {
   deps,
   layouts,
   "envoy/config/cluster/v3/cluster.proto",
-  UPB_STRVIEW_INIT(descriptor, 11317)
+  UPB_STRVIEW_INIT(descriptor, 11811)
 };
index 1bbc899..cd32ef2 100644 (file)
@@ -56,6 +56,16 @@ UPB_INLINE const upb_msgdef *envoy_config_cluster_v3_Cluster_LbSubsetConfig_LbSu
   return upb_symtab_lookupmsg(s, "envoy.config.cluster.v3.Cluster.LbSubsetConfig.LbSubsetSelector");
 }
 
+UPB_INLINE const upb_msgdef *envoy_config_cluster_v3_Cluster_SlowStartConfig_getmsgdef(upb_symtab *s) {
+  _upb_symtab_loaddefinit(s, &envoy_config_cluster_v3_cluster_proto_upbdefinit);
+  return upb_symtab_lookupmsg(s, "envoy.config.cluster.v3.Cluster.SlowStartConfig");
+}
+
+UPB_INLINE const upb_msgdef *envoy_config_cluster_v3_Cluster_RoundRobinLbConfig_getmsgdef(upb_symtab *s) {
+  _upb_symtab_loaddefinit(s, &envoy_config_cluster_v3_cluster_proto_upbdefinit);
+  return upb_symtab_lookupmsg(s, "envoy.config.cluster.v3.Cluster.RoundRobinLbConfig");
+}
+
 UPB_INLINE const upb_msgdef *envoy_config_cluster_v3_Cluster_LeastRequestLbConfig_getmsgdef(upb_symtab *s) {
   _upb_symtab_loaddefinit(s, &envoy_config_cluster_v3_cluster_proto_upbdefinit);
   return upb_symtab_lookupmsg(s, "envoy.config.cluster.v3.Cluster.LeastRequestLbConfig");
index fbc28a9..a440444 100644 (file)
@@ -35,6 +35,7 @@ extern const upb_msglayout envoy_config_core_v3_RuntimeUInt32_msginit;
 extern const upb_msglayout envoy_config_core_v3_RuntimePercent_msginit;
 extern const upb_msglayout envoy_config_core_v3_RuntimeDouble_msginit;
 extern const upb_msglayout envoy_config_core_v3_RuntimeFeatureFlag_msginit;
+extern const upb_msglayout envoy_config_core_v3_QueryParameter_msginit;
 extern const upb_msglayout envoy_config_core_v3_HeaderValue_msginit;
 extern const upb_msglayout envoy_config_core_v3_HeaderValueOption_msginit;
 extern const upb_msglayout envoy_config_core_v3_HeaderMap_msginit;
@@ -47,7 +48,7 @@ extern const upb_msglayout envoy_config_core_v3_TransportSocket_msginit;
 extern const upb_msglayout envoy_config_core_v3_RuntimeFractionalPercent_msginit;
 extern const upb_msglayout envoy_config_core_v3_ControlPlane_msginit;
 
-static const upb_msglayout *layouts[23] = {
+static const upb_msglayout *layouts[24] = {
   &envoy_config_core_v3_Locality_msginit,
   &envoy_config_core_v3_BuildVersion_msginit,
   &envoy_config_core_v3_Extension_msginit,
@@ -60,6 +61,7 @@ static const upb_msglayout *layouts[23] = {
   &envoy_config_core_v3_RuntimePercent_msginit,
   &envoy_config_core_v3_RuntimeDouble_msginit,
   &envoy_config_core_v3_RuntimeFeatureFlag_msginit,
+  &envoy_config_core_v3_QueryParameter_msginit,
   &envoy_config_core_v3_HeaderValue_msginit,
   &envoy_config_core_v3_HeaderValueOption_msginit,
   &envoy_config_core_v3_HeaderMap_msginit,
@@ -73,7 +75,7 @@ static const upb_msglayout *layouts[23] = {
   &envoy_config_core_v3_ControlPlane_msginit,
 };
 
-static const char descriptor[4952] = {'\n', '\037', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '/', 'b', 'a', 
+static const char descriptor[5228] = {'\n', '\037', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '/', 'b', 'a', 
 's', 'e', '.', 'p', 'r', 'o', 't', 'o', '\022', '\024', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 
 'r', 'e', '.', 'v', '3', '\032', '\"', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'c', 'o', 'r', 'e', '/', 
 'v', '3', '/', 'a', 'd', 'd', 'r', 'e', 's', 's', '.', 'p', 'r', 'o', 't', 'o', '\032', '\"', 'e', 'n', 'v', 'o', 'y', '/', 'c', 
@@ -187,91 +189,102 @@ static const char descriptor[4952] = {'\n', '\037', 'e', 'n', 'v', 'o', 'y', '/'
 'l', 'u', 'e', '\022', '(', '\n', '\013', 'r', 'u', 'n', 't', 'i', 'm', 'e', '_', 'k', 'e', 'y', '\030', '\002', ' ', '\001', '(', '\t', 'B', 
 '\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\n', 'r', 'u', 'n', 't', 'i', 'm', 'e', 'K', 'e', 'y', ':', '+', '\232', '\305', '\210', 
 '\036', '&', '\n', '$', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'c', 'o', 'r', 'e', '.', 'R', 'u', 'n', 
-'t', 'i', 'm', 'e', 'F', 'e', 'a', 't', 'u', 'r', 'e', 'F', 'l', 'a', 'g', '\"', '\177', '\n', '\013', 'H', 'e', 'a', 'd', 'e', 'r', 
-'V', 'a', 'l', 'u', 'e', '\022', '#', '\n', '\003', 'k', 'e', 'y', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\021', '\372', 'B', '\016', 'r', '\014', 
-'\020', '\001', '(', '\200', '\200', '\001', '\300', '\001', '\001', '\310', '\001', '\000', 'R', '\003', 'k', 'e', 'y', '\022', '%', '\n', '\005', 'v', 'a', 'l', 'u', 
-'e', '\030', '\002', ' ', '\001', '(', '\t', 'B', '\017', '\372', 'B', '\014', 'r', '\n', '(', '\200', '\200', '\001', '\300', '\001', '\002', '\310', '\001', '\000', 'R', 
-'\005', 'v', 'a', 'l', 'u', 'e', ':', '$', '\232', '\305', '\210', '\036', '\037', '\n', '\035', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 
-'v', '2', '.', 'c', 'o', 'r', 'e', '.', 'H', 'e', 'a', 'd', 'e', 'r', 'V', 'a', 'l', 'u', 'e', '\"', '\270', '\001', '\n', '\021', 'H', 
-'e', 'a', 'd', 'e', 'r', 'V', 'a', 'l', 'u', 'e', 'O', 'p', 't', 'i', 'o', 'n', '\022', 'C', '\n', '\006', 'h', 'e', 'a', 'd', 'e', 
-'r', '\030', '\001', ' ', '\001', '(', '\013', '2', '!', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 
-'r', 'e', '.', 'v', '3', '.', 'H', 'e', 'a', 'd', 'e', 'r', 'V', 'a', 'l', 'u', 'e', 'B', '\010', '\372', 'B', '\005', '\212', '\001', '\002', 
-'\020', '\001', 'R', '\006', 'h', 'e', 'a', 'd', 'e', 'r', '\022', '2', '\n', '\006', 'a', 'p', 'p', 'e', 'n', 'd', '\030', '\002', ' ', '\001', '(', 
-'\013', '2', '\032', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'B', 'o', 'o', 'l', 'V', 
-'a', 'l', 'u', 'e', 'R', '\006', 'a', 'p', 'p', 'e', 'n', 'd', ':', '*', '\232', '\305', '\210', '\036', '%', '\n', '#', 'e', 'n', 'v', 'o', 
-'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'c', 'o', 'r', 'e', '.', 'H', 'e', 'a', 'd', 'e', 'r', 'V', 'a', 'l', 'u', 'e', 
-'O', 'p', 't', 'i', 'o', 'n', '\"', 'l', '\n', '\t', 'H', 'e', 'a', 'd', 'e', 'r', 'M', 'a', 'p', '\022', ';', '\n', '\007', 'h', 'e', 
-'a', 'd', 'e', 'r', 's', '\030', '\001', ' ', '\003', '(', '\013', '2', '!', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 
-'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'H', 'e', 'a', 'd', 'e', 'r', 'V', 'a', 'l', 'u', 'e', 'R', '\007', 'h', 'e', 
-'a', 'd', 'e', 'r', 's', ':', '\"', '\232', '\305', '\210', '\036', '\035', '\n', '\033', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', 
-'2', '.', 'c', 'o', 'r', 'e', '.', 'H', 'e', 'a', 'd', 'e', 'r', 'M', 'a', 'p', '\"', '/', '\n', '\020', 'W', 'a', 't', 'c', 'h', 
-'e', 'd', 'D', 'i', 'r', 'e', 'c', 't', 'o', 'r', 'y', '\022', '\033', '\n', '\004', 'p', 'a', 't', 'h', '\030', '\001', ' ', '\001', '(', '\t', 
-'B', '\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\004', 'p', 'a', 't', 'h', '\"', '\266', '\001', '\n', '\n', 'D', 'a', 't', 'a', 'S', 
-'o', 'u', 'r', 'c', 'e', '\022', '%', '\n', '\010', 'f', 'i', 'l', 'e', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\007', 
-'\372', 'B', '\004', 'r', '\002', '\020', '\001', 'H', '\000', 'R', '\010', 'f', 'i', 'l', 'e', 'n', 'a', 'm', 'e', '\022', '#', '\n', '\014', 'i', 'n', 
-'l', 'i', 'n', 'e', '_', 'b', 'y', 't', 'e', 's', '\030', '\002', ' ', '\001', '(', '\014', 'H', '\000', 'R', '\013', 'i', 'n', 'l', 'i', 'n', 
-'e', 'B', 'y', 't', 'e', 's', '\022', '%', '\n', '\r', 'i', 'n', 'l', 'i', 'n', 'e', '_', 's', 't', 'r', 'i', 'n', 'g', '\030', '\003', 
-' ', '\001', '(', '\t', 'H', '\000', 'R', '\014', 'i', 'n', 'l', 'i', 'n', 'e', 'S', 't', 'r', 'i', 'n', 'g', ':', '#', '\232', '\305', '\210', 
-'\036', '\036', '\n', '\034', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'c', 'o', 'r', 'e', '.', 'D', 'a', 't', 
-'a', 'S', 'o', 'u', 'r', 'c', 'e', 'B', '\020', '\n', '\t', 's', 'p', 'e', 'c', 'i', 'f', 'i', 'e', 'r', '\022', '\003', '\370', 'B', '\001', 
-'\"', '\324', '\001', '\n', '\013', 'R', 'e', 't', 'r', 'y', 'P', 'o', 'l', 'i', 'c', 'y', '\022', 'K', '\n', '\016', 'r', 'e', 't', 'r', 'y', 
-'_', 'b', 'a', 'c', 'k', '_', 'o', 'f', 'f', '\030', '\001', ' ', '\001', '(', '\013', '2', '%', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 
-'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'B', 'a', 'c', 'k', 'o', 'f', 'f', 'S', 't', 'r', 'a', 
-'t', 'e', 'g', 'y', 'R', '\014', 'r', 'e', 't', 'r', 'y', 'B', 'a', 'c', 'k', 'O', 'f', 'f', '\022', 'R', '\n', '\013', 'n', 'u', 'm', 
-'_', 'r', 'e', 't', 'r', 'i', 'e', 's', '\030', '\002', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 
-'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'I', 'n', 't', '3', '2', 'V', 'a', 'l', 'u', 'e', 'B', '\023', '\362', '\230', '\376', '\217', 
-'\005', '\r', '\n', '\013', 'm', 'a', 'x', '_', 'r', 'e', 't', 'r', 'i', 'e', 's', 'R', '\n', 'n', 'u', 'm', 'R', 'e', 't', 'r', 'i', 
-'e', 's', ':', '$', '\232', '\305', '\210', '\036', '\037', '\n', '\035', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'c', 
-'o', 'r', 'e', '.', 'R', 'e', 't', 'r', 'y', 'P', 'o', 'l', 'i', 'c', 'y', '\"', '\350', '\001', '\n', '\020', 'R', 'e', 'm', 'o', 't', 
-'e', 'D', 'a', 't', 'a', 'S', 'o', 'u', 'r', 'c', 'e', '\022', 'B', '\n', '\010', 'h', 't', 't', 'p', '_', 'u', 'r', 'i', '\030', '\001', 
-' ', '\001', '(', '\013', '2', '\035', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 
-'v', '3', '.', 'H', 't', 't', 'p', 'U', 'r', 'i', 'B', '\010', '\372', 'B', '\005', '\212', '\001', '\002', '\020', '\001', 'R', '\007', 'h', 't', 't', 
-'p', 'U', 'r', 'i', '\022', '\037', '\n', '\006', 's', 'h', 'a', '2', '5', '6', '\030', '\002', ' ', '\001', '(', '\t', 'B', '\007', '\372', 'B', '\004', 
-'r', '\002', '\020', '\001', 'R', '\006', 's', 'h', 'a', '2', '5', '6', '\022', 'D', '\n', '\014', 'r', 'e', 't', 'r', 'y', '_', 'p', 'o', 'l', 
-'i', 'c', 'y', '\030', '\003', ' ', '\001', '(', '\013', '2', '!', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 
-'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'R', 'e', 't', 'r', 'y', 'P', 'o', 'l', 'i', 'c', 'y', 'R', '\013', 'r', 'e', 't', 'r', 
-'y', 'P', 'o', 'l', 'i', 'c', 'y', ':', ')', '\232', '\305', '\210', '\036', '$', '\n', '\"', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', 
-'.', 'v', '2', '.', 'c', 'o', 'r', 'e', '.', 'R', 'e', 'm', 'o', 't', 'e', 'D', 'a', 't', 'a', 'S', 'o', 'u', 'r', 'c', 'e', 
-'\"', '\311', '\001', '\n', '\017', 'A', 's', 'y', 'n', 'c', 'D', 'a', 't', 'a', 'S', 'o', 'u', 'r', 'c', 'e', '\022', '8', '\n', '\005', 'l', 
-'o', 'c', 'a', 'l', '\030', '\001', ' ', '\001', '(', '\013', '2', ' ', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', 
-'.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'D', 'a', 't', 'a', 'S', 'o', 'u', 'r', 'c', 'e', 'H', '\000', 'R', '\005', 'l', 'o', 
-'c', 'a', 'l', '\022', '@', '\n', '\006', 'r', 'e', 'm', 'o', 't', 'e', '\030', '\002', ' ', '\001', '(', '\013', '2', '&', '.', 'e', 'n', 'v', 
-'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'R', 'e', 'm', 'o', 't', 'e', 'D', 
-'a', 't', 'a', 'S', 'o', 'u', 'r', 'c', 'e', 'H', '\000', 'R', '\006', 'r', 'e', 'm', 'o', 't', 'e', ':', '(', '\232', '\305', '\210', '\036', 
-'#', '\n', '!', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'c', 'o', 'r', 'e', '.', 'A', 's', 'y', 'n', 
-'c', 'D', 'a', 't', 'a', 'S', 'o', 'u', 'r', 'c', 'e', 'B', '\020', '\n', '\t', 's', 'p', 'e', 'c', 'i', 'f', 'i', 'e', 'r', '\022', 
-'\003', '\370', 'B', '\001', '\"', '\260', '\001', '\n', '\017', 'T', 'r', 'a', 'n', 's', 'p', 'o', 'r', 't', 'S', 'o', 'c', 'k', 'e', 't', '\022', 
-'\033', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\004', 'n', 
-'a', 'm', 'e', '\022', '9', '\n', '\014', 't', 'y', 'p', 'e', 'd', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\003', ' ', '\001', '(', '\013', 
-'2', '\024', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'A', 'n', 'y', 'H', '\000', 'R', 
-'\013', 't', 'y', 'p', 'e', 'd', 'C', 'o', 'n', 'f', 'i', 'g', ':', '(', '\232', '\305', '\210', '\036', '#', '\n', '!', 'e', 'n', 'v', 'o', 
-'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'c', 'o', 'r', 'e', '.', 'T', 'r', 'a', 'n', 's', 'p', 'o', 'r', 't', 'S', 'o', 
-'c', 'k', 'e', 't', 'B', '\r', '\n', '\013', 'c', 'o', 'n', 'f', 'i', 'g', '_', 't', 'y', 'p', 'e', 'J', '\004', '\010', '\002', '\020', '\003', 
-'R', '\006', 'c', 'o', 'n', 'f', 'i', 'g', '\"', '\277', '\001', '\n', '\030', 'R', 'u', 'n', 't', 'i', 'm', 'e', 'F', 'r', 'a', 'c', 't', 
-'i', 'o', 'n', 'a', 'l', 'P', 'e', 'r', 'c', 'e', 'n', 't', '\022', 'O', '\n', '\r', 'd', 'e', 'f', 'a', 'u', 'l', 't', '_', 'v', 
-'a', 'l', 'u', 'e', '\030', '\001', ' ', '\001', '(', '\013', '2', ' ', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'v', 
-'3', '.', 'F', 'r', 'a', 'c', 't', 'i', 'o', 'n', 'a', 'l', 'P', 'e', 'r', 'c', 'e', 'n', 't', 'B', '\010', '\372', 'B', '\005', '\212', 
-'\001', '\002', '\020', '\001', 'R', '\014', 'd', 'e', 'f', 'a', 'u', 'l', 't', 'V', 'a', 'l', 'u', 'e', '\022', '\037', '\n', '\013', 'r', 'u', 'n', 
-'t', 'i', 'm', 'e', '_', 'k', 'e', 'y', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\n', 'r', 'u', 'n', 't', 'i', 'm', 'e', 'K', 'e', 
-'y', ':', '1', '\232', '\305', '\210', '\036', ',', '\n', '*', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'c', 'o', 
-'r', 'e', '.', 'R', 'u', 'n', 't', 'i', 'm', 'e', 'F', 'r', 'a', 'c', 't', 'i', 'o', 'n', 'a', 'l', 'P', 'e', 'r', 'c', 'e', 
-'n', 't', '\"', 'U', '\n', '\014', 'C', 'o', 'n', 't', 'r', 'o', 'l', 'P', 'l', 'a', 'n', 'e', '\022', '\036', '\n', '\n', 'i', 'd', 'e', 
-'n', 't', 'i', 'f', 'i', 'e', 'r', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\n', 'i', 'd', 'e', 'n', 't', 'i', 'f', 'i', 'e', 'r', 
-':', '%', '\232', '\305', '\210', '\036', ' ', '\n', '\036', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'c', 'o', 'r', 
-'e', '.', 'C', 'o', 'n', 't', 'r', 'o', 'l', 'P', 'l', 'a', 'n', 'e', '*', '(', '\n', '\017', 'R', 'o', 'u', 't', 'i', 'n', 'g', 
-'P', 'r', 'i', 'o', 'r', 'i', 't', 'y', '\022', '\013', '\n', '\007', 'D', 'E', 'F', 'A', 'U', 'L', 'T', '\020', '\000', '\022', '\010', '\n', '\004', 
-'H', 'I', 'G', 'H', '\020', '\001', '*', '\211', '\001', '\n', '\r', 'R', 'e', 'q', 'u', 'e', 's', 't', 'M', 'e', 't', 'h', 'o', 'd', '\022', 
-'\026', '\n', '\022', 'M', 'E', 'T', 'H', 'O', 'D', '_', 'U', 'N', 'S', 'P', 'E', 'C', 'I', 'F', 'I', 'E', 'D', '\020', '\000', '\022', '\007', 
-'\n', '\003', 'G', 'E', 'T', '\020', '\001', '\022', '\010', '\n', '\004', 'H', 'E', 'A', 'D', '\020', '\002', '\022', '\010', '\n', '\004', 'P', 'O', 'S', 'T', 
-'\020', '\003', '\022', '\007', '\n', '\003', 'P', 'U', 'T', '\020', '\004', '\022', '\n', '\n', '\006', 'D', 'E', 'L', 'E', 'T', 'E', '\020', '\005', '\022', '\013', 
-'\n', '\007', 'C', 'O', 'N', 'N', 'E', 'C', 'T', '\020', '\006', '\022', '\013', '\n', '\007', 'O', 'P', 'T', 'I', 'O', 'N', 'S', '\020', '\007', '\022', 
-'\t', '\n', '\005', 'T', 'R', 'A', 'C', 'E', '\020', '\010', '\022', '\t', '\n', '\005', 'P', 'A', 'T', 'C', 'H', '\020', '\t', '*', '>', '\n', '\020', 
-'T', 'r', 'a', 'f', 'f', 'i', 'c', 'D', 'i', 'r', 'e', 'c', 't', 'i', 'o', 'n', '\022', '\017', '\n', '\013', 'U', 'N', 'S', 'P', 'E', 
-'C', 'I', 'F', 'I', 'E', 'D', '\020', '\000', '\022', '\013', '\n', '\007', 'I', 'N', 'B', 'O', 'U', 'N', 'D', '\020', '\001', '\022', '\014', '\n', '\010', 
-'O', 'U', 'T', 'B', 'O', 'U', 'N', 'D', '\020', '\002', 'B', '9', '\n', '\"', 'i', 'o', '.', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o', 
-'x', 'y', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', 'B', '\t', 
-'B', 'a', 's', 'e', 'P', 'r', 'o', 't', 'o', 'P', '\001', '\272', '\200', '\310', '\321', '\006', '\002', '\020', '\002', 'b', '\006', 'p', 'r', 'o', 't', 
-'o', '3', 
+'t', 'i', 'm', 'e', 'F', 'e', 'a', 't', 'u', 'r', 'e', 'F', 'l', 'a', 'g', '\"', 'A', '\n', '\016', 'Q', 'u', 'e', 'r', 'y', 'P', 
+'a', 'r', 'a', 'm', 'e', 't', 'e', 'r', '\022', '\031', '\n', '\003', 'k', 'e', 'y', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\007', '\372', 'B', 
+'\004', 'r', '\002', '\020', '\001', 'R', '\003', 'k', 'e', 'y', '\022', '\024', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\001', '(', '\t', 
+'R', '\005', 'v', 'a', 'l', 'u', 'e', '\"', '\177', '\n', '\013', 'H', 'e', 'a', 'd', 'e', 'r', 'V', 'a', 'l', 'u', 'e', '\022', '#', '\n', 
+'\003', 'k', 'e', 'y', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\021', '\372', 'B', '\016', 'r', '\014', '\020', '\001', '(', '\200', '\200', '\001', '\300', '\001', 
+'\001', '\310', '\001', '\000', 'R', '\003', 'k', 'e', 'y', '\022', '%', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\001', '(', '\t', 'B', 
+'\017', '\372', 'B', '\014', 'r', '\n', '(', '\200', '\200', '\001', '\300', '\001', '\002', '\310', '\001', '\000', 'R', '\005', 'v', 'a', 'l', 'u', 'e', ':', '$', 
+'\232', '\305', '\210', '\036', '\037', '\n', '\035', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'c', 'o', 'r', 'e', '.', 
+'H', 'e', 'a', 'd', 'e', 'r', 'V', 'a', 'l', 'u', 'e', '\"', '\211', '\003', '\n', '\021', 'H', 'e', 'a', 'd', 'e', 'r', 'V', 'a', 'l', 
+'u', 'e', 'O', 'p', 't', 'i', 'o', 'n', '\022', 'C', '\n', '\006', 'h', 'e', 'a', 'd', 'e', 'r', '\030', '\001', ' ', '\001', '(', '\013', '2', 
+'!', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'H', 'e', 
+'a', 'd', 'e', 'r', 'V', 'a', 'l', 'u', 'e', 'B', '\010', '\372', 'B', '\005', '\212', '\001', '\002', '\020', '\001', 'R', '\006', 'h', 'e', 'a', 'd', 
+'e', 'r', '\022', '2', '\n', '\006', 'a', 'p', 'p', 'e', 'n', 'd', '\030', '\002', ' ', '\001', '(', '\013', '2', '\032', '.', 'g', 'o', 'o', 'g', 
+'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'B', 'o', 'o', 'l', 'V', 'a', 'l', 'u', 'e', 'R', '\006', 'a', 'p', 
+'p', 'e', 'n', 'd', '\022', 'i', '\n', '\r', 'a', 'p', 'p', 'e', 'n', 'd', '_', 'a', 'c', 't', 'i', 'o', 'n', '\030', '\003', ' ', '\001', 
+'(', '\016', '2', ':', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', 
+'.', 'H', 'e', 'a', 'd', 'e', 'r', 'V', 'a', 'l', 'u', 'e', 'O', 'p', 't', 'i', 'o', 'n', '.', 'H', 'e', 'a', 'd', 'e', 'r', 
+'A', 'p', 'p', 'e', 'n', 'd', 'A', 'c', 't', 'i', 'o', 'n', 'B', '\010', '\372', 'B', '\005', '\202', '\001', '\002', '\020', '\001', 'R', '\014', 'a', 
+'p', 'p', 'e', 'n', 'd', 'A', 'c', 't', 'i', 'o', 'n', '\"', 'd', '\n', '\022', 'H', 'e', 'a', 'd', 'e', 'r', 'A', 'p', 'p', 'e', 
+'n', 'd', 'A', 'c', 't', 'i', 'o', 'n', '\022', '\033', '\n', '\027', 'A', 'P', 'P', 'E', 'N', 'D', '_', 'I', 'F', '_', 'E', 'X', 'I', 
+'S', 'T', 'S', '_', 'O', 'R', '_', 'A', 'D', 'D', '\020', '\000', '\022', '\021', '\n', '\r', 'A', 'D', 'D', '_', 'I', 'F', '_', 'A', 'B', 
+'S', 'E', 'N', 'T', '\020', '\001', '\022', '\036', '\n', '\032', 'O', 'V', 'E', 'R', 'W', 'R', 'I', 'T', 'E', '_', 'I', 'F', '_', 'E', 'X', 
+'I', 'S', 'T', 'S', '_', 'O', 'R', '_', 'A', 'D', 'D', '\020', '\002', ':', '*', '\232', '\305', '\210', '\036', '%', '\n', '#', 'e', 'n', 'v', 
+'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'c', 'o', 'r', 'e', '.', 'H', 'e', 'a', 'd', 'e', 'r', 'V', 'a', 'l', 'u', 
+'e', 'O', 'p', 't', 'i', 'o', 'n', '\"', 'l', '\n', '\t', 'H', 'e', 'a', 'd', 'e', 'r', 'M', 'a', 'p', '\022', ';', '\n', '\007', 'h', 
+'e', 'a', 'd', 'e', 'r', 's', '\030', '\001', ' ', '\003', '(', '\013', '2', '!', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 
+'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'H', 'e', 'a', 'd', 'e', 'r', 'V', 'a', 'l', 'u', 'e', 'R', '\007', 'h', 
+'e', 'a', 'd', 'e', 'r', 's', ':', '\"', '\232', '\305', '\210', '\036', '\035', '\n', '\033', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 
+'v', '2', '.', 'c', 'o', 'r', 'e', '.', 'H', 'e', 'a', 'd', 'e', 'r', 'M', 'a', 'p', '\"', '/', '\n', '\020', 'W', 'a', 't', 'c', 
+'h', 'e', 'd', 'D', 'i', 'r', 'e', 'c', 't', 'o', 'r', 'y', '\022', '\033', '\n', '\004', 'p', 'a', 't', 'h', '\030', '\001', ' ', '\001', '(', 
+'\t', 'B', '\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\004', 'p', 'a', 't', 'h', '\"', '\266', '\001', '\n', '\n', 'D', 'a', 't', 'a', 
+'S', 'o', 'u', 'r', 'c', 'e', '\022', '%', '\n', '\010', 'f', 'i', 'l', 'e', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'B', 
+'\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'H', '\000', 'R', '\010', 'f', 'i', 'l', 'e', 'n', 'a', 'm', 'e', '\022', '#', '\n', '\014', 'i', 
+'n', 'l', 'i', 'n', 'e', '_', 'b', 'y', 't', 'e', 's', '\030', '\002', ' ', '\001', '(', '\014', 'H', '\000', 'R', '\013', 'i', 'n', 'l', 'i', 
+'n', 'e', 'B', 'y', 't', 'e', 's', '\022', '%', '\n', '\r', 'i', 'n', 'l', 'i', 'n', 'e', '_', 's', 't', 'r', 'i', 'n', 'g', '\030', 
+'\003', ' ', '\001', '(', '\t', 'H', '\000', 'R', '\014', 'i', 'n', 'l', 'i', 'n', 'e', 'S', 't', 'r', 'i', 'n', 'g', ':', '#', '\232', '\305', 
+'\210', '\036', '\036', '\n', '\034', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'c', 'o', 'r', 'e', '.', 'D', 'a', 
+'t', 'a', 'S', 'o', 'u', 'r', 'c', 'e', 'B', '\020', '\n', '\t', 's', 'p', 'e', 'c', 'i', 'f', 'i', 'e', 'r', '\022', '\003', '\370', 'B', 
+'\001', '\"', '\324', '\001', '\n', '\013', 'R', 'e', 't', 'r', 'y', 'P', 'o', 'l', 'i', 'c', 'y', '\022', 'K', '\n', '\016', 'r', 'e', 't', 'r', 
+'y', '_', 'b', 'a', 'c', 'k', '_', 'o', 'f', 'f', '\030', '\001', ' ', '\001', '(', '\013', '2', '%', '.', 'e', 'n', 'v', 'o', 'y', '.', 
+'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'B', 'a', 'c', 'k', 'o', 'f', 'f', 'S', 't', 'r', 
+'a', 't', 'e', 'g', 'y', 'R', '\014', 'r', 'e', 't', 'r', 'y', 'B', 'a', 'c', 'k', 'O', 'f', 'f', '\022', 'R', '\n', '\013', 'n', 'u', 
+'m', '_', 'r', 'e', 't', 'r', 'i', 'e', 's', '\030', '\002', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 
+'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'I', 'n', 't', '3', '2', 'V', 'a', 'l', 'u', 'e', 'B', '\023', '\362', '\230', '\376', 
+'\217', '\005', '\r', '\n', '\013', 'm', 'a', 'x', '_', 'r', 'e', 't', 'r', 'i', 'e', 's', 'R', '\n', 'n', 'u', 'm', 'R', 'e', 't', 'r', 
+'i', 'e', 's', ':', '$', '\232', '\305', '\210', '\036', '\037', '\n', '\035', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 
+'c', 'o', 'r', 'e', '.', 'R', 'e', 't', 'r', 'y', 'P', 'o', 'l', 'i', 'c', 'y', '\"', '\350', '\001', '\n', '\020', 'R', 'e', 'm', 'o', 
+'t', 'e', 'D', 'a', 't', 'a', 'S', 'o', 'u', 'r', 'c', 'e', '\022', 'B', '\n', '\010', 'h', 't', 't', 'p', '_', 'u', 'r', 'i', '\030', 
+'\001', ' ', '\001', '(', '\013', '2', '\035', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', 
+'.', 'v', '3', '.', 'H', 't', 't', 'p', 'U', 'r', 'i', 'B', '\010', '\372', 'B', '\005', '\212', '\001', '\002', '\020', '\001', 'R', '\007', 'h', 't', 
+'t', 'p', 'U', 'r', 'i', '\022', '\037', '\n', '\006', 's', 'h', 'a', '2', '5', '6', '\030', '\002', ' ', '\001', '(', '\t', 'B', '\007', '\372', 'B', 
+'\004', 'r', '\002', '\020', '\001', 'R', '\006', 's', 'h', 'a', '2', '5', '6', '\022', 'D', '\n', '\014', 'r', 'e', 't', 'r', 'y', '_', 'p', 'o', 
+'l', 'i', 'c', 'y', '\030', '\003', ' ', '\001', '(', '\013', '2', '!', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', 
+'.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'R', 'e', 't', 'r', 'y', 'P', 'o', 'l', 'i', 'c', 'y', 'R', '\013', 'r', 'e', 't', 
+'r', 'y', 'P', 'o', 'l', 'i', 'c', 'y', ':', ')', '\232', '\305', '\210', '\036', '$', '\n', '\"', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 
+'i', '.', 'v', '2', '.', 'c', 'o', 'r', 'e', '.', 'R', 'e', 'm', 'o', 't', 'e', 'D', 'a', 't', 'a', 'S', 'o', 'u', 'r', 'c', 
+'e', '\"', '\311', '\001', '\n', '\017', 'A', 's', 'y', 'n', 'c', 'D', 'a', 't', 'a', 'S', 'o', 'u', 'r', 'c', 'e', '\022', '8', '\n', '\005', 
+'l', 'o', 'c', 'a', 'l', '\030', '\001', ' ', '\001', '(', '\013', '2', ' ', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 
+'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'D', 'a', 't', 'a', 'S', 'o', 'u', 'r', 'c', 'e', 'H', '\000', 'R', '\005', 'l', 
+'o', 'c', 'a', 'l', '\022', '@', '\n', '\006', 'r', 'e', 'm', 'o', 't', 'e', '\030', '\002', ' ', '\001', '(', '\013', '2', '&', '.', 'e', 'n', 
+'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'R', 'e', 'm', 'o', 't', 'e', 
+'D', 'a', 't', 'a', 'S', 'o', 'u', 'r', 'c', 'e', 'H', '\000', 'R', '\006', 'r', 'e', 'm', 'o', 't', 'e', ':', '(', '\232', '\305', '\210', 
+'\036', '#', '\n', '!', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'c', 'o', 'r', 'e', '.', 'A', 's', 'y', 
+'n', 'c', 'D', 'a', 't', 'a', 'S', 'o', 'u', 'r', 'c', 'e', 'B', '\020', '\n', '\t', 's', 'p', 'e', 'c', 'i', 'f', 'i', 'e', 'r', 
+'\022', '\003', '\370', 'B', '\001', '\"', '\260', '\001', '\n', '\017', 'T', 'r', 'a', 'n', 's', 'p', 'o', 'r', 't', 'S', 'o', 'c', 'k', 'e', 't', 
+'\022', '\033', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\004', 
+'n', 'a', 'm', 'e', '\022', '9', '\n', '\014', 't', 'y', 'p', 'e', 'd', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\003', ' ', '\001', '(', 
+'\013', '2', '\024', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'A', 'n', 'y', 'H', '\000', 
+'R', '\013', 't', 'y', 'p', 'e', 'd', 'C', 'o', 'n', 'f', 'i', 'g', ':', '(', '\232', '\305', '\210', '\036', '#', '\n', '!', 'e', 'n', 'v', 
+'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'c', 'o', 'r', 'e', '.', 'T', 'r', 'a', 'n', 's', 'p', 'o', 'r', 't', 'S', 
+'o', 'c', 'k', 'e', 't', 'B', '\r', '\n', '\013', 'c', 'o', 'n', 'f', 'i', 'g', '_', 't', 'y', 'p', 'e', 'J', '\004', '\010', '\002', '\020', 
+'\003', 'R', '\006', 'c', 'o', 'n', 'f', 'i', 'g', '\"', '\277', '\001', '\n', '\030', 'R', 'u', 'n', 't', 'i', 'm', 'e', 'F', 'r', 'a', 'c', 
+'t', 'i', 'o', 'n', 'a', 'l', 'P', 'e', 'r', 'c', 'e', 'n', 't', '\022', 'O', '\n', '\r', 'd', 'e', 'f', 'a', 'u', 'l', 't', '_', 
+'v', 'a', 'l', 'u', 'e', '\030', '\001', ' ', '\001', '(', '\013', '2', ' ', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 
+'v', '3', '.', 'F', 'r', 'a', 'c', 't', 'i', 'o', 'n', 'a', 'l', 'P', 'e', 'r', 'c', 'e', 'n', 't', 'B', '\010', '\372', 'B', '\005', 
+'\212', '\001', '\002', '\020', '\001', 'R', '\014', 'd', 'e', 'f', 'a', 'u', 'l', 't', 'V', 'a', 'l', 'u', 'e', '\022', '\037', '\n', '\013', 'r', 'u', 
+'n', 't', 'i', 'm', 'e', '_', 'k', 'e', 'y', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\n', 'r', 'u', 'n', 't', 'i', 'm', 'e', 'K', 
+'e', 'y', ':', '1', '\232', '\305', '\210', '\036', ',', '\n', '*', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'c', 
+'o', 'r', 'e', '.', 'R', 'u', 'n', 't', 'i', 'm', 'e', 'F', 'r', 'a', 'c', 't', 'i', 'o', 'n', 'a', 'l', 'P', 'e', 'r', 'c', 
+'e', 'n', 't', '\"', 'U', '\n', '\014', 'C', 'o', 'n', 't', 'r', 'o', 'l', 'P', 'l', 'a', 'n', 'e', '\022', '\036', '\n', '\n', 'i', 'd', 
+'e', 'n', 't', 'i', 'f', 'i', 'e', 'r', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\n', 'i', 'd', 'e', 'n', 't', 'i', 'f', 'i', 'e', 
+'r', ':', '%', '\232', '\305', '\210', '\036', ' ', '\n', '\036', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'c', 'o', 
+'r', 'e', '.', 'C', 'o', 'n', 't', 'r', 'o', 'l', 'P', 'l', 'a', 'n', 'e', '*', '(', '\n', '\017', 'R', 'o', 'u', 't', 'i', 'n', 
+'g', 'P', 'r', 'i', 'o', 'r', 'i', 't', 'y', '\022', '\013', '\n', '\007', 'D', 'E', 'F', 'A', 'U', 'L', 'T', '\020', '\000', '\022', '\010', '\n', 
+'\004', 'H', 'I', 'G', 'H', '\020', '\001', '*', '\211', '\001', '\n', '\r', 'R', 'e', 'q', 'u', 'e', 's', 't', 'M', 'e', 't', 'h', 'o', 'd', 
+'\022', '\026', '\n', '\022', 'M', 'E', 'T', 'H', 'O', 'D', '_', 'U', 'N', 'S', 'P', 'E', 'C', 'I', 'F', 'I', 'E', 'D', '\020', '\000', '\022', 
+'\007', '\n', '\003', 'G', 'E', 'T', '\020', '\001', '\022', '\010', '\n', '\004', 'H', 'E', 'A', 'D', '\020', '\002', '\022', '\010', '\n', '\004', 'P', 'O', 'S', 
+'T', '\020', '\003', '\022', '\007', '\n', '\003', 'P', 'U', 'T', '\020', '\004', '\022', '\n', '\n', '\006', 'D', 'E', 'L', 'E', 'T', 'E', '\020', '\005', '\022', 
+'\013', '\n', '\007', 'C', 'O', 'N', 'N', 'E', 'C', 'T', '\020', '\006', '\022', '\013', '\n', '\007', 'O', 'P', 'T', 'I', 'O', 'N', 'S', '\020', '\007', 
+'\022', '\t', '\n', '\005', 'T', 'R', 'A', 'C', 'E', '\020', '\010', '\022', '\t', '\n', '\005', 'P', 'A', 'T', 'C', 'H', '\020', '\t', '*', '>', '\n', 
+'\020', 'T', 'r', 'a', 'f', 'f', 'i', 'c', 'D', 'i', 'r', 'e', 'c', 't', 'i', 'o', 'n', '\022', '\017', '\n', '\013', 'U', 'N', 'S', 'P', 
+'E', 'C', 'I', 'F', 'I', 'E', 'D', '\020', '\000', '\022', '\013', '\n', '\007', 'I', 'N', 'B', 'O', 'U', 'N', 'D', '\020', '\001', '\022', '\014', '\n', 
+'\010', 'O', 'U', 'T', 'B', 'O', 'U', 'N', 'D', '\020', '\002', 'B', '9', '\n', '\"', 'i', 'o', '.', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 
+'o', 'x', 'y', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', 'B', 
+'\t', 'B', 'a', 's', 'e', 'P', 'r', 'o', 't', 'o', 'P', '\001', '\272', '\200', '\310', '\321', '\006', '\002', '\020', '\002', 'b', '\006', 'p', 'r', 'o', 
+'t', 'o', '3', 
 };
 
 static upb_def_init *deps[15] = {
@@ -296,5 +309,5 @@ upb_def_init envoy_config_core_v3_base_proto_upbdefinit = {
   deps,
   layouts,
   "envoy/config/core/v3/base.proto",
-  UPB_STRVIEW_INIT(descriptor, 4952)
+  UPB_STRVIEW_INIT(descriptor, 5228)
 };
index dfe2c27..dd7ad08 100644 (file)
@@ -81,6 +81,11 @@ UPB_INLINE const upb_msgdef *envoy_config_core_v3_RuntimeFeatureFlag_getmsgdef(u
   return upb_symtab_lookupmsg(s, "envoy.config.core.v3.RuntimeFeatureFlag");
 }
 
+UPB_INLINE const upb_msgdef *envoy_config_core_v3_QueryParameter_getmsgdef(upb_symtab *s) {
+  _upb_symtab_loaddefinit(s, &envoy_config_core_v3_base_proto_upbdefinit);
+  return upb_symtab_lookupmsg(s, "envoy.config.core.v3.QueryParameter");
+}
+
 UPB_INLINE const upb_msgdef *envoy_config_core_v3_HeaderValue_getmsgdef(upb_symtab *s) {
   _upb_symtab_loaddefinit(s, &envoy_config_core_v3_base_proto_upbdefinit);
   return upb_symtab_lookupmsg(s, "envoy.config.core.v3.HeaderValue");
index 469acd3..2a52f8f 100644 (file)
@@ -41,7 +41,7 @@ static const upb_msglayout *layouts[8] = {
   &envoy_config_core_v3_HealthCheck_TlsOptions_msginit,
 };
 
-static const char descriptor[4147] = {'\n', '\'', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '/', 'h', 'e', 
+static const char descriptor[4221] = {'\n', '\'', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '/', 'h', 'e', 
 'a', 'l', 't', 'h', '_', 'c', 'h', 'e', 'c', 'k', '.', 'p', 'r', 'o', 't', 'o', '\022', '\024', 'e', 'n', 'v', 'o', 'y', '.', 'c', 
 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '\032', '\037', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 
 'i', 'g', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '/', 'b', 'a', 's', 'e', '.', 'p', 'r', 'o', 't', 'o', '\032', '/', 'e', 'n', 
@@ -58,7 +58,7 @@ static const char descriptor[4147] = {'\n', '\'', 'e', 'n', 'v', 'o', 'y', '/',
 'p', 'r', 'o', 't', 'o', '\032', '\035', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 's', 
 't', 'a', 't', 'u', 's', '.', 'p', 'r', 'o', 't', 'o', '\032', '!', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 
 'i', 'o', 'n', 's', '/', 'v', 'e', 'r', 's', 'i', 'o', 'n', 'i', 'n', 'g', '.', 'p', 'r', 'o', 't', 'o', '\032', '\027', 'v', 'a', 
-'l', 'i', 'd', 'a', 't', 'e', '/', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '.', 'p', 'r', 'o', 't', 'o', '\"', '\306', '\033', '\n', 
+'l', 'i', 'd', 'a', 't', 'e', '/', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '.', 'p', 'r', 'o', 't', 'o', '\"', '\220', '\034', '\n', 
 '\013', 'H', 'e', 'a', 'l', 't', 'h', 'C', 'h', 'e', 'c', 'k', '\022', '?', '\n', '\007', 't', 'i', 'm', 'e', 'o', 'u', 't', '\030', '\001', 
 ' ', '\001', '(', '\013', '2', '\031', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'u', 
 'r', 'a', 't', 'i', 'o', 'n', 'B', '\n', '\372', 'B', '\007', '\252', '\001', '\004', '\010', '\001', '*', '\000', 'R', '\007', 't', 'i', 'm', 'e', 'o', 
@@ -137,8 +137,8 @@ static const char descriptor[4147] = {'\n', '\'', 'e', 'n', 'v', 'o', 'y', '/',
 '\020', '\001', 'H', '\000', 'R', '\004', 't', 'e', 'x', 't', '\022', '\030', '\n', '\006', 'b', 'i', 'n', 'a', 'r', 'y', '\030', '\002', ' ', '\001', '(', 
 '\014', 'H', '\000', 'R', '\006', 'b', 'i', 'n', 'a', 'r', 'y', ':', ',', '\232', '\305', '\210', '\036', '\'', '\n', '%', 'e', 'n', 'v', 'o', 'y', 
 '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'c', 'o', 'r', 'e', '.', 'H', 'e', 'a', 'l', 't', 'h', 'C', 'h', 'e', 'c', 'k', '.', 
-'P', 'a', 'y', 'l', 'o', 'a', 'd', 'B', '\016', '\n', '\007', 'p', 'a', 'y', 'l', 'o', 'a', 'd', '\022', '\003', '\370', 'B', '\001', '\032', '\340', 
-'\005', '\n', '\017', 'H', 't', 't', 'p', 'H', 'e', 'a', 'l', 't', 'h', 'C', 'h', 'e', 'c', 'k', '\022', '\037', '\n', '\004', 'h', 'o', 's', 
+'P', 'a', 'y', 'l', 'o', 'a', 'd', 'B', '\016', '\n', '\007', 'p', 'a', 'y', 'l', 'o', 'a', 'd', '\022', '\003', '\370', 'B', '\001', '\032', '\252', 
+'\006', '\n', '\017', 'H', 't', 't', 'p', 'H', 'e', 'a', 'l', 't', 'h', 'C', 'h', 'e', 'c', 'k', '\022', '\037', '\n', '\004', 'h', 'o', 's', 
 't', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\013', '\372', 'B', '\010', 'r', '\006', '\300', '\001', '\002', '\310', '\001', '\000', 'R', '\004', 'h', 'o', 's', 
 't', '\022', '!', '\n', '\004', 'p', 'a', 't', 'h', '\030', '\002', ' ', '\001', '(', '\t', 'B', '\r', '\372', 'B', '\n', 'r', '\010', '\020', '\001', '\300', 
 '\001', '\002', '\310', '\001', '\000', 'R', '\004', 'p', 'a', 't', 'h', '\022', '=', '\n', '\004', 's', 'e', 'n', 'd', '\030', '\003', ' ', '\001', '(', '\013', 
@@ -156,57 +156,60 @@ static const char descriptor[4147] = {'\n', '\'', 'e', 'n', 'v', 'o', 'y', '/',
 '\000', 'R', '\026', 'r', 'e', 'q', 'u', 'e', 's', 't', 'H', 'e', 'a', 'd', 'e', 'r', 's', 'T', 'o', 'R', 'e', 'm', 'o', 'v', 'e', 
 '\022', 'F', '\n', '\021', 'e', 'x', 'p', 'e', 'c', 't', 'e', 'd', '_', 's', 't', 'a', 't', 'u', 's', 'e', 's', '\030', '\t', ' ', '\003', 
 '(', '\013', '2', '\031', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'v', '3', '.', 'I', 'n', 't', '6', '4', 'R', 
-'a', 'n', 'g', 'e', 'R', '\020', 'e', 'x', 'p', 'e', 'c', 't', 'e', 'd', 'S', 't', 'a', 't', 'u', 's', 'e', 's', '\022', 'T', '\n', 
-'\021', 'c', 'o', 'd', 'e', 'c', '_', 'c', 'l', 'i', 'e', 'n', 't', '_', 't', 'y', 'p', 'e', '\030', '\n', ' ', '\001', '(', '\016', '2', 
-'\036', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'v', '3', '.', 'C', 'o', 'd', 'e', 'c', 'C', 'l', 'i', 'e', 
-'n', 't', 'T', 'y', 'p', 'e', 'B', '\010', '\372', 'B', '\005', '\202', '\001', '\002', '\020', '\001', 'R', '\017', 'c', 'o', 'd', 'e', 'c', 'C', 'l', 
-'i', 'e', 'n', 't', 'T', 'y', 'p', 'e', '\022', 'V', '\n', '\024', 's', 'e', 'r', 'v', 'i', 'c', 'e', '_', 'n', 'a', 'm', 'e', '_', 
-'m', 'a', 't', 'c', 'h', 'e', 'r', '\030', '\013', ' ', '\001', '(', '\013', '2', '$', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 
-'e', '.', 'm', 'a', 't', 'c', 'h', 'e', 'r', '.', 'v', '3', '.', 'S', 't', 'r', 'i', 'n', 'g', 'M', 'a', 't', 'c', 'h', 'e', 
-'r', 'R', '\022', 's', 'e', 'r', 'v', 'i', 'c', 'e', 'N', 'a', 'm', 'e', 'M', 'a', 't', 'c', 'h', 'e', 'r', ':', '4', '\232', '\305', 
-'\210', '\036', '/', '\n', '-', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'c', 'o', 'r', 'e', '.', 'H', 'e', 
-'a', 'l', 't', 'h', 'C', 'h', 'e', 'c', 'k', '.', 'H', 't', 't', 'p', 'H', 'e', 'a', 'l', 't', 'h', 'C', 'h', 'e', 'c', 'k', 
-'J', '\004', '\010', '\005', '\020', '\006', 'J', '\004', '\010', '\007', '\020', '\010', 'R', '\014', 's', 'e', 'r', 'v', 'i', 'c', 'e', '_', 'n', 'a', 'm', 
-'e', 'R', '\t', 'u', 's', 'e', '_', 'h', 't', 't', 'p', '2', '\032', '\311', '\001', '\n', '\016', 'T', 'c', 'p', 'H', 'e', 'a', 'l', 't', 
-'h', 'C', 'h', 'e', 'c', 'k', '\022', '=', '\n', '\004', 's', 'e', 'n', 'd', '\030', '\001', ' ', '\001', '(', '\013', '2', ')', '.', 'e', 'n', 
-'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'H', 'e', 'a', 'l', 't', 'h', 
-'C', 'h', 'e', 'c', 'k', '.', 'P', 'a', 'y', 'l', 'o', 'a', 'd', 'R', '\004', 's', 'e', 'n', 'd', '\022', 'C', '\n', '\007', 'r', 'e', 
-'c', 'e', 'i', 'v', 'e', '\030', '\002', ' ', '\003', '(', '\013', '2', ')', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 
-'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'H', 'e', 'a', 'l', 't', 'h', 'C', 'h', 'e', 'c', 'k', '.', 'P', 'a', 'y', 
-'l', 'o', 'a', 'd', 'R', '\007', 'r', 'e', 'c', 'e', 'i', 'v', 'e', ':', '3', '\232', '\305', '\210', '\036', '.', '\n', ',', 'e', 'n', 'v', 
-'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'c', 'o', 'r', 'e', '.', 'H', 'e', 'a', 'l', 't', 'h', 'C', 'h', 'e', 'c', 
-'k', '.', 'T', 'c', 'p', 'H', 'e', 'a', 'l', 't', 'h', 'C', 'h', 'e', 'c', 'k', '\032', '[', '\n', '\020', 'R', 'e', 'd', 'i', 's', 
-'H', 'e', 'a', 'l', 't', 'h', 'C', 'h', 'e', 'c', 'k', '\022', '\020', '\n', '\003', 'k', 'e', 'y', '\030', '\001', ' ', '\001', '(', '\t', 'R', 
-'\003', 'k', 'e', 'y', ':', '5', '\232', '\305', '\210', '\036', '0', '\n', '.', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', 
-'.', 'c', 'o', 'r', 'e', '.', 'H', 'e', 'a', 'l', 't', 'h', 'C', 'h', 'e', 'c', 'k', '.', 'R', 'e', 'd', 'i', 's', 'H', 'e', 
-'a', 'l', 't', 'h', 'C', 'h', 'e', 'c', 'k', '\032', '\225', '\001', '\n', '\017', 'G', 'r', 'p', 'c', 'H', 'e', 'a', 'l', 't', 'h', 'C', 
-'h', 'e', 'c', 'k', '\022', '!', '\n', '\014', 's', 'e', 'r', 'v', 'i', 'c', 'e', '_', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', 
-'\t', 'R', '\013', 's', 'e', 'r', 'v', 'i', 'c', 'e', 'N', 'a', 'm', 'e', '\022', ')', '\n', '\t', 'a', 'u', 't', 'h', 'o', 'r', 'i', 
-'t', 'y', '\030', '\002', ' ', '\001', '(', '\t', 'B', '\013', '\372', 'B', '\010', 'r', '\006', '\300', '\001', '\002', '\310', '\001', '\000', 'R', '\t', 'a', 'u', 
-'t', 'h', 'o', 'r', 'i', 't', 'y', ':', '4', '\232', '\305', '\210', '\036', '/', '\n', '-', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', 
-'.', 'v', '2', '.', 'c', 'o', 'r', 'e', '.', 'H', 'e', 'a', 'l', 't', 'h', 'C', 'h', 'e', 'c', 'k', '.', 'G', 'r', 'p', 'c', 
-'H', 'e', 'a', 'l', 't', 'h', 'C', 'h', 'e', 'c', 'k', '\032', '\300', '\001', '\n', '\021', 'C', 'u', 's', 't', 'o', 'm', 'H', 'e', 'a', 
-'l', 't', 'h', 'C', 'h', 'e', 'c', 'k', '\022', '\033', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\007', '\372', 
-'B', '\004', 'r', '\002', '\020', '\001', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '9', '\n', '\014', 't', 'y', 'p', 'e', 'd', '_', 'c', 'o', 'n', 
-'f', 'i', 'g', '\030', '\003', ' ', '\001', '(', '\013', '2', '\024', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 
-'u', 'f', '.', 'A', 'n', 'y', 'H', '\000', 'R', '\013', 't', 'y', 'p', 'e', 'd', 'C', 'o', 'n', 'f', 'i', 'g', ':', '6', '\232', '\305', 
-'\210', '\036', '1', '\n', '/', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'c', 'o', 'r', 'e', '.', 'H', 'e', 
-'a', 'l', 't', 'h', 'C', 'h', 'e', 'c', 'k', '.', 'C', 'u', 's', 't', 'o', 'm', 'H', 'e', 'a', 'l', 't', 'h', 'C', 'h', 'e', 
-'c', 'k', 'B', '\r', '\n', '\013', 'c', 'o', 'n', 'f', 'i', 'g', '_', 't', 'y', 'p', 'e', 'J', '\004', '\010', '\002', '\020', '\003', 'R', '\006', 
-'c', 'o', 'n', 'f', 'i', 'g', '\032', 'd', '\n', '\n', 'T', 'l', 's', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', '%', '\n', '\016', 'a', 
-'l', 'p', 'n', '_', 'p', 'r', 'o', 't', 'o', 'c', 'o', 'l', 's', '\030', '\001', ' ', '\003', '(', '\t', 'R', '\r', 'a', 'l', 'p', 'n', 
-'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 's', ':', '/', '\232', '\305', '\210', '\036', '*', '\n', '(', 'e', 'n', 'v', 'o', 'y', '.', 'a', 
-'p', 'i', '.', 'v', '2', '.', 'c', 'o', 'r', 'e', '.', 'H', 'e', 'a', 'l', 't', 'h', 'C', 'h', 'e', 'c', 'k', '.', 'T', 'l', 
-'s', 'O', 'p', 't', 'i', 'o', 'n', 's', ':', '$', '\232', '\305', '\210', '\036', '\037', '\n', '\035', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 
-'i', '.', 'v', '2', '.', 'c', 'o', 'r', 'e', '.', 'H', 'e', 'a', 'l', 't', 'h', 'C', 'h', 'e', 'c', 'k', 'B', '\025', '\n', '\016', 
-'h', 'e', 'a', 'l', 't', 'h', '_', 'c', 'h', 'e', 'c', 'k', 'e', 'r', '\022', '\003', '\370', 'B', '\001', 'J', '\004', '\010', '\n', '\020', '\013', 
-'*', '`', '\n', '\014', 'H', 'e', 'a', 'l', 't', 'h', 'S', 't', 'a', 't', 'u', 's', '\022', '\013', '\n', '\007', 'U', 'N', 'K', 'N', 'O', 
-'W', 'N', '\020', '\000', '\022', '\013', '\n', '\007', 'H', 'E', 'A', 'L', 'T', 'H', 'Y', '\020', '\001', '\022', '\r', '\n', '\t', 'U', 'N', 'H', 'E', 
-'A', 'L', 'T', 'H', 'Y', '\020', '\002', '\022', '\014', '\n', '\010', 'D', 'R', 'A', 'I', 'N', 'I', 'N', 'G', '\020', '\003', '\022', '\013', '\n', '\007', 
-'T', 'I', 'M', 'E', 'O', 'U', 'T', '\020', '\004', '\022', '\014', '\n', '\010', 'D', 'E', 'G', 'R', 'A', 'D', 'E', 'D', '\020', '\005', 'B', '@', 
-'\n', '\"', 'i', 'o', '.', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 
-'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', 'B', '\020', 'H', 'e', 'a', 'l', 't', 'h', 'C', 'h', 'e', 'c', 'k', 'P', 
-'r', 'o', 't', 'o', 'P', '\001', '\272', '\200', '\310', '\321', '\006', '\002', '\020', '\002', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', 
+'a', 'n', 'g', 'e', 'R', '\020', 'e', 'x', 'p', 'e', 'c', 't', 'e', 'd', 'S', 't', 'a', 't', 'u', 's', 'e', 's', '\022', 'H', '\n', 
+'\022', 'r', 'e', 't', 'r', 'i', 'a', 'b', 'l', 'e', '_', 's', 't', 'a', 't', 'u', 's', 'e', 's', '\030', '\014', ' ', '\003', '(', '\013', 
+'2', '\031', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'v', '3', '.', 'I', 'n', 't', '6', '4', 'R', 'a', 'n', 
+'g', 'e', 'R', '\021', 'r', 'e', 't', 'r', 'i', 'a', 'b', 'l', 'e', 'S', 't', 'a', 't', 'u', 's', 'e', 's', '\022', 'T', '\n', '\021', 
+'c', 'o', 'd', 'e', 'c', '_', 'c', 'l', 'i', 'e', 'n', 't', '_', 't', 'y', 'p', 'e', '\030', '\n', ' ', '\001', '(', '\016', '2', '\036', 
+'.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'v', '3', '.', 'C', 'o', 'd', 'e', 'c', 'C', 'l', 'i', 'e', 'n', 
+'t', 'T', 'y', 'p', 'e', 'B', '\010', '\372', 'B', '\005', '\202', '\001', '\002', '\020', '\001', 'R', '\017', 'c', 'o', 'd', 'e', 'c', 'C', 'l', 'i', 
+'e', 'n', 't', 'T', 'y', 'p', 'e', '\022', 'V', '\n', '\024', 's', 'e', 'r', 'v', 'i', 'c', 'e', '_', 'n', 'a', 'm', 'e', '_', 'm', 
+'a', 't', 'c', 'h', 'e', 'r', '\030', '\013', ' ', '\001', '(', '\013', '2', '$', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', 
+'.', 'm', 'a', 't', 'c', 'h', 'e', 'r', '.', 'v', '3', '.', 'S', 't', 'r', 'i', 'n', 'g', 'M', 'a', 't', 'c', 'h', 'e', 'r', 
+'R', '\022', 's', 'e', 'r', 'v', 'i', 'c', 'e', 'N', 'a', 'm', 'e', 'M', 'a', 't', 'c', 'h', 'e', 'r', ':', '4', '\232', '\305', '\210', 
+'\036', '/', '\n', '-', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'c', 'o', 'r', 'e', '.', 'H', 'e', 'a', 
+'l', 't', 'h', 'C', 'h', 'e', 'c', 'k', '.', 'H', 't', 't', 'p', 'H', 'e', 'a', 'l', 't', 'h', 'C', 'h', 'e', 'c', 'k', 'J', 
+'\004', '\010', '\005', '\020', '\006', 'J', '\004', '\010', '\007', '\020', '\010', 'R', '\014', 's', 'e', 'r', 'v', 'i', 'c', 'e', '_', 'n', 'a', 'm', 'e', 
+'R', '\t', 'u', 's', 'e', '_', 'h', 't', 't', 'p', '2', '\032', '\311', '\001', '\n', '\016', 'T', 'c', 'p', 'H', 'e', 'a', 'l', 't', 'h', 
+'C', 'h', 'e', 'c', 'k', '\022', '=', '\n', '\004', 's', 'e', 'n', 'd', '\030', '\001', ' ', '\001', '(', '\013', '2', ')', '.', 'e', 'n', 'v', 
+'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'H', 'e', 'a', 'l', 't', 'h', 'C', 
+'h', 'e', 'c', 'k', '.', 'P', 'a', 'y', 'l', 'o', 'a', 'd', 'R', '\004', 's', 'e', 'n', 'd', '\022', 'C', '\n', '\007', 'r', 'e', 'c', 
+'e', 'i', 'v', 'e', '\030', '\002', ' ', '\003', '(', '\013', '2', ')', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', 
+'.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'H', 'e', 'a', 'l', 't', 'h', 'C', 'h', 'e', 'c', 'k', '.', 'P', 'a', 'y', 'l', 
+'o', 'a', 'd', 'R', '\007', 'r', 'e', 'c', 'e', 'i', 'v', 'e', ':', '3', '\232', '\305', '\210', '\036', '.', '\n', ',', 'e', 'n', 'v', 'o', 
+'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'c', 'o', 'r', 'e', '.', 'H', 'e', 'a', 'l', 't', 'h', 'C', 'h', 'e', 'c', 'k', 
+'.', 'T', 'c', 'p', 'H', 'e', 'a', 'l', 't', 'h', 'C', 'h', 'e', 'c', 'k', '\032', '[', '\n', '\020', 'R', 'e', 'd', 'i', 's', 'H', 
+'e', 'a', 'l', 't', 'h', 'C', 'h', 'e', 'c', 'k', '\022', '\020', '\n', '\003', 'k', 'e', 'y', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\003', 
+'k', 'e', 'y', ':', '5', '\232', '\305', '\210', '\036', '0', '\n', '.', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 
+'c', 'o', 'r', 'e', '.', 'H', 'e', 'a', 'l', 't', 'h', 'C', 'h', 'e', 'c', 'k', '.', 'R', 'e', 'd', 'i', 's', 'H', 'e', 'a', 
+'l', 't', 'h', 'C', 'h', 'e', 'c', 'k', '\032', '\225', '\001', '\n', '\017', 'G', 'r', 'p', 'c', 'H', 'e', 'a', 'l', 't', 'h', 'C', 'h', 
+'e', 'c', 'k', '\022', '!', '\n', '\014', 's', 'e', 'r', 'v', 'i', 'c', 'e', '_', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 
+'R', '\013', 's', 'e', 'r', 'v', 'i', 'c', 'e', 'N', 'a', 'm', 'e', '\022', ')', '\n', '\t', 'a', 'u', 't', 'h', 'o', 'r', 'i', 't', 
+'y', '\030', '\002', ' ', '\001', '(', '\t', 'B', '\013', '\372', 'B', '\010', 'r', '\006', '\300', '\001', '\002', '\310', '\001', '\000', 'R', '\t', 'a', 'u', 't', 
+'h', 'o', 'r', 'i', 't', 'y', ':', '4', '\232', '\305', '\210', '\036', '/', '\n', '-', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 
+'v', '2', '.', 'c', 'o', 'r', 'e', '.', 'H', 'e', 'a', 'l', 't', 'h', 'C', 'h', 'e', 'c', 'k', '.', 'G', 'r', 'p', 'c', 'H', 
+'e', 'a', 'l', 't', 'h', 'C', 'h', 'e', 'c', 'k', '\032', '\300', '\001', '\n', '\021', 'C', 'u', 's', 't', 'o', 'm', 'H', 'e', 'a', 'l', 
+'t', 'h', 'C', 'h', 'e', 'c', 'k', '\022', '\033', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\007', '\372', 'B', 
+'\004', 'r', '\002', '\020', '\001', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '9', '\n', '\014', 't', 'y', 'p', 'e', 'd', '_', 'c', 'o', 'n', 'f', 
+'i', 'g', '\030', '\003', ' ', '\001', '(', '\013', '2', '\024', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 
+'f', '.', 'A', 'n', 'y', 'H', '\000', 'R', '\013', 't', 'y', 'p', 'e', 'd', 'C', 'o', 'n', 'f', 'i', 'g', ':', '6', '\232', '\305', '\210', 
+'\036', '1', '\n', '/', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'c', 'o', 'r', 'e', '.', 'H', 'e', 'a', 
+'l', 't', 'h', 'C', 'h', 'e', 'c', 'k', '.', 'C', 'u', 's', 't', 'o', 'm', 'H', 'e', 'a', 'l', 't', 'h', 'C', 'h', 'e', 'c', 
+'k', 'B', '\r', '\n', '\013', 'c', 'o', 'n', 'f', 'i', 'g', '_', 't', 'y', 'p', 'e', 'J', '\004', '\010', '\002', '\020', '\003', 'R', '\006', 'c', 
+'o', 'n', 'f', 'i', 'g', '\032', 'd', '\n', '\n', 'T', 'l', 's', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', '%', '\n', '\016', 'a', 'l', 
+'p', 'n', '_', 'p', 'r', 'o', 't', 'o', 'c', 'o', 'l', 's', '\030', '\001', ' ', '\003', '(', '\t', 'R', '\r', 'a', 'l', 'p', 'n', 'P', 
+'r', 'o', 't', 'o', 'c', 'o', 'l', 's', ':', '/', '\232', '\305', '\210', '\036', '*', '\n', '(', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 
+'i', '.', 'v', '2', '.', 'c', 'o', 'r', 'e', '.', 'H', 'e', 'a', 'l', 't', 'h', 'C', 'h', 'e', 'c', 'k', '.', 'T', 'l', 's', 
+'O', 'p', 't', 'i', 'o', 'n', 's', ':', '$', '\232', '\305', '\210', '\036', '\037', '\n', '\035', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', 
+'.', 'v', '2', '.', 'c', 'o', 'r', 'e', '.', 'H', 'e', 'a', 'l', 't', 'h', 'C', 'h', 'e', 'c', 'k', 'B', '\025', '\n', '\016', 'h', 
+'e', 'a', 'l', 't', 'h', '_', 'c', 'h', 'e', 'c', 'k', 'e', 'r', '\022', '\003', '\370', 'B', '\001', 'J', '\004', '\010', '\n', '\020', '\013', '*', 
+'`', '\n', '\014', 'H', 'e', 'a', 'l', 't', 'h', 'S', 't', 'a', 't', 'u', 's', '\022', '\013', '\n', '\007', 'U', 'N', 'K', 'N', 'O', 'W', 
+'N', '\020', '\000', '\022', '\013', '\n', '\007', 'H', 'E', 'A', 'L', 'T', 'H', 'Y', '\020', '\001', '\022', '\r', '\n', '\t', 'U', 'N', 'H', 'E', 'A', 
+'L', 'T', 'H', 'Y', '\020', '\002', '\022', '\014', '\n', '\010', 'D', 'R', 'A', 'I', 'N', 'I', 'N', 'G', '\020', '\003', '\022', '\013', '\n', '\007', 'T', 
+'I', 'M', 'E', 'O', 'U', 'T', '\020', '\004', '\022', '\014', '\n', '\010', 'D', 'E', 'G', 'R', 'A', 'D', 'E', 'D', '\020', '\005', 'B', '@', '\n', 
+'\"', 'i', 'o', '.', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 
+'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', 'B', '\020', 'H', 'e', 'a', 'l', 't', 'h', 'C', 'h', 'e', 'c', 'k', 'P', 'r', 
+'o', 't', 'o', 'P', '\001', '\272', '\200', '\310', '\321', '\006', '\002', '\020', '\002', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', 
 };
 
 static upb_def_init *deps[13] = {
@@ -229,5 +232,5 @@ upb_def_init envoy_config_core_v3_health_check_proto_upbdefinit = {
   deps,
   layouts,
   "envoy/config/core/v3/health_check.proto",
-  UPB_STRVIEW_INIT(descriptor, 4147)
+  UPB_STRVIEW_INIT(descriptor, 4221)
 };
index f8481f7..6b09504 100644 (file)
@@ -13,6 +13,7 @@ extern upb_def_init envoy_config_core_v3_extension_proto_upbdefinit;
 extern upb_def_init envoy_type_v3_percent_proto_upbdefinit;
 extern upb_def_init google_protobuf_duration_proto_upbdefinit;
 extern upb_def_init google_protobuf_wrappers_proto_upbdefinit;
+extern upb_def_init xds_annotations_v3_status_proto_upbdefinit;
 extern upb_def_init envoy_annotations_deprecation_proto_upbdefinit;
 extern upb_def_init udpa_annotations_status_proto_upbdefinit;
 extern upb_def_init udpa_annotations_versioning_proto_upbdefinit;
@@ -49,47 +50,55 @@ static const upb_msglayout *layouts[14] = {
   &envoy_config_core_v3_SchemeHeaderTransformation_msginit,
 };
 
-static const char descriptor[5396] = {'\n', '#', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '/', 'p', 'r', 
+static const char descriptor[5660] = {'\n', '#', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '/', 'p', 'r', 
 'o', 't', 'o', 'c', 'o', 'l', '.', 'p', 'r', 'o', 't', 'o', '\022', '\024', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 
 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '\032', '$', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'c', 
 'o', 'r', 'e', '/', 'v', '3', '/', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', '.', 'p', 'r', 'o', 't', 'o', '\032', '\033', 'e', 
 'n', 'v', 'o', 'y', '/', 't', 'y', 'p', 'e', '/', 'v', '3', '/', 'p', 'e', 'r', 'c', 'e', 'n', 't', '.', 'p', 'r', 'o', 't', 
 'o', '\032', '\036', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 'd', 'u', 'r', 'a', 't', 'i', 
 'o', 'n', '.', 'p', 'r', 'o', 't', 'o', '\032', '\036', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', 
-'/', 'w', 'r', 'a', 'p', 'p', 'e', 'r', 's', '.', 'p', 'r', 'o', 't', 'o', '\032', '#', 'e', 'n', 'v', 'o', 'y', '/', 'a', 'n', 
-'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'i', 'o', 'n', '.', 'p', 'r', 'o', 
-'t', 'o', '\032', '\035', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 's', 't', 'a', 't', 
-'u', 's', '.', 'p', 'r', 'o', 't', 'o', '\032', '!', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 
-'s', '/', 'v', 'e', 'r', 's', 'i', 'o', 'n', 'i', 'n', 'g', '.', 'p', 'r', 'o', 't', 'o', '\032', '\027', 'v', 'a', 'l', 'i', 'd', 
-'a', 't', 'e', '/', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '.', 'p', 'r', 'o', 't', 'o', '\"', 'A', '\n', '\022', 'T', 'c', 'p', 
-'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'O', 'p', 't', 'i', 'o', 'n', 's', ':', '+', '\232', '\305', '\210', '\036', '&', '\n', '$', 'e', 
-'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'c', 'o', 'r', 'e', '.', 'T', 'c', 'p', 'P', 'r', 'o', 't', 'o', 
-'c', 'o', 'l', 'O', 'p', 't', 'i', 'o', 'n', 's', '\"', '\303', '\002', '\n', '\023', 'Q', 'u', 'i', 'c', 'P', 'r', 'o', 't', 'o', 'c', 
-'o', 'l', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', 'R', '\n', '\026', 'm', 'a', 'x', '_', 'c', 'o', 'n', 'c', 'u', 'r', 'r', 'e', 
-'n', 't', '_', 's', 't', 'r', 'e', 'a', 'm', 's', '\030', '\001', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', 
-'.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'I', 'n', 't', '3', '2', 'V', 'a', 'l', 'u', 'e', 'R', '\024', 'm', 'a', 
-'x', 'C', 'o', 'n', 'c', 'u', 'r', 'r', 'e', 'n', 't', 'S', 't', 'r', 'e', 'a', 'm', 's', '\022', 'g', '\n', '\032', 'i', 'n', 'i', 
-'t', 'i', 'a', 'l', '_', 's', 't', 'r', 'e', 'a', 'm', '_', 'w', 'i', 'n', 'd', 'o', 'w', '_', 's', 'i', 'z', 'e', '\030', '\002', 
-' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'I', 
-'n', 't', '3', '2', 'V', 'a', 'l', 'u', 'e', 'B', '\014', '\372', 'B', '\t', '*', '\007', '\030', '\200', '\200', '\200', '\010', '(', '\001', 'R', '\027', 
-'i', 'n', 'i', 't', 'i', 'a', 'l', 'S', 't', 'r', 'e', 'a', 'm', 'W', 'i', 'n', 'd', 'o', 'w', 'S', 'i', 'z', 'e', '\022', 'o', 
-'\n', '\036', 'i', 'n', 'i', 't', 'i', 'a', 'l', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '_', 'w', 'i', 'n', 'd', 
-'o', 'w', '_', 's', 'i', 'z', 'e', '\030', '\003', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 
-'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'I', 'n', 't', '3', '2', 'V', 'a', 'l', 'u', 'e', 'B', '\014', '\372', 'B', '\t', '*', '\007', 
-'\030', '\200', '\200', '\200', '\014', '(', '\001', 'R', '\033', 'i', 'n', 'i', 't', 'i', 'a', 'l', 'C', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 
-'n', 'W', 'i', 'n', 'd', 'o', 'w', 'S', 'i', 'z', 'e', '\"', '\236', '\001', '\n', '\033', 'U', 'p', 's', 't', 'r', 'e', 'a', 'm', 'H', 
-'t', 't', 'p', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', '\031', '\n', '\010', 'a', 'u', 't', 
-'o', '_', 's', 'n', 'i', '\030', '\001', ' ', '\001', '(', '\010', 'R', '\007', 'a', 'u', 't', 'o', 'S', 'n', 'i', '\022', '.', '\n', '\023', 'a', 
-'u', 't', 'o', '_', 's', 'a', 'n', '_', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'i', 'o', 'n', '\030', '\002', ' ', '\001', '(', '\010', 'R', 
-'\021', 'a', 'u', 't', 'o', 'S', 'a', 'n', 'V', 'a', 'l', 'i', 'd', 'a', 't', 'i', 'o', 'n', ':', '4', '\232', '\305', '\210', '\036', '/', 
-'\n', '-', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'c', 'o', 'r', 'e', '.', 'U', 'p', 's', 't', 'r', 
-'e', 'a', 'm', 'H', 't', 't', 'p', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'O', 'p', 't', 'i', 'o', 'n', 's', '\"', '\205', '\001', 
-'\n', '\036', 'A', 'l', 't', 'e', 'r', 'n', 'a', 't', 'e', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 's', 'C', 'a', 'c', 'h', 'e', 
-'O', 'p', 't', 'i', 'o', 'n', 's', '\022', '\033', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\007', '\372', 'B', 
-'\004', 'r', '\002', '\020', '\001', 'R', '\004', 'n', 'a', 'm', 'e', '\022', 'F', '\n', '\013', 'm', 'a', 'x', '_', 'e', 'n', 't', 'r', 'i', 'e', 
-'s', '\030', '\002', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', 
-'.', 'U', 'I', 'n', 't', '3', '2', 'V', 'a', 'l', 'u', 'e', 'B', '\007', '\372', 'B', '\004', '*', '\002', ' ', '\000', 'R', '\n', 'm', 'a', 
-'x', 'E', 'n', 't', 'r', 'i', 'e', 's', '\"', '\257', '\005', '\n', '\023', 'H', 't', 't', 'p', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 
+'/', 'w', 'r', 'a', 'p', 'p', 'e', 'r', 's', '.', 'p', 'r', 'o', 't', 'o', '\032', '\037', 'x', 'd', 's', '/', 'a', 'n', 'n', 'o', 
+'t', 'a', 't', 'i', 'o', 'n', 's', '/', 'v', '3', '/', 's', 't', 'a', 't', 'u', 's', '.', 'p', 'r', 'o', 't', 'o', '\032', '#', 
+'e', 'n', 'v', 'o', 'y', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 
+'t', 'i', 'o', 'n', '.', 'p', 'r', 'o', 't', 'o', '\032', '\035', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 
+'o', 'n', 's', '/', 's', 't', 'a', 't', 'u', 's', '.', 'p', 'r', 'o', 't', 'o', '\032', '!', 'u', 'd', 'p', 'a', '/', 'a', 'n', 
+'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 'v', 'e', 'r', 's', 'i', 'o', 'n', 'i', 'n', 'g', '.', 'p', 'r', 'o', 't', 
+'o', '\032', '\027', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '/', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '.', 'p', 'r', 'o', 't', 
+'o', '\"', 'A', '\n', '\022', 'T', 'c', 'p', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'O', 'p', 't', 'i', 'o', 'n', 's', ':', '+', 
+'\232', '\305', '\210', '\036', '&', '\n', '$', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'c', 'o', 'r', 'e', '.', 
+'T', 'c', 'p', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'O', 'p', 't', 'i', 'o', 'n', 's', '\"', '\303', '\002', '\n', '\023', 'Q', 'u', 
+'i', 'c', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', 'R', '\n', '\026', 'm', 'a', 'x', '_', 
+'c', 'o', 'n', 'c', 'u', 'r', 'r', 'e', 'n', 't', '_', 's', 't', 'r', 'e', 'a', 'm', 's', '\030', '\001', ' ', '\001', '(', '\013', '2', 
+'\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'I', 'n', 't', '3', '2', 'V', 
+'a', 'l', 'u', 'e', 'R', '\024', 'm', 'a', 'x', 'C', 'o', 'n', 'c', 'u', 'r', 'r', 'e', 'n', 't', 'S', 't', 'r', 'e', 'a', 'm', 
+'s', '\022', 'g', '\n', '\032', 'i', 'n', 'i', 't', 'i', 'a', 'l', '_', 's', 't', 'r', 'e', 'a', 'm', '_', 'w', 'i', 'n', 'd', 'o', 
+'w', '_', 's', 'i', 'z', 'e', '\030', '\002', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 
+'t', 'o', 'b', 'u', 'f', '.', 'U', 'I', 'n', 't', '3', '2', 'V', 'a', 'l', 'u', 'e', 'B', '\014', '\372', 'B', '\t', '*', '\007', '\030', 
+'\200', '\200', '\200', '\010', '(', '\001', 'R', '\027', 'i', 'n', 'i', 't', 'i', 'a', 'l', 'S', 't', 'r', 'e', 'a', 'm', 'W', 'i', 'n', 'd', 
+'o', 'w', 'S', 'i', 'z', 'e', '\022', 'o', '\n', '\036', 'i', 'n', 'i', 't', 'i', 'a', 'l', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 
+'i', 'o', 'n', '_', 'w', 'i', 'n', 'd', 'o', 'w', '_', 's', 'i', 'z', 'e', '\030', '\003', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 
+'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'I', 'n', 't', '3', '2', 'V', 'a', 'l', 'u', 
+'e', 'B', '\014', '\372', 'B', '\t', '*', '\007', '\030', '\200', '\200', '\200', '\014', '(', '\001', 'R', '\033', 'i', 'n', 'i', 't', 'i', 'a', 'l', 'C', 
+'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', 'W', 'i', 'n', 'd', 'o', 'w', 'S', 'i', 'z', 'e', '\"', '\344', '\001', '\n', '\033', 'U', 
+'p', 's', 't', 'r', 'e', 'a', 'm', 'H', 't', 't', 'p', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'O', 'p', 't', 'i', 'o', 'n', 
+'s', '\022', '\031', '\n', '\010', 'a', 'u', 't', 'o', '_', 's', 'n', 'i', '\030', '\001', ' ', '\001', '(', '\010', 'R', '\007', 'a', 'u', 't', 'o', 
+'S', 'n', 'i', '\022', '.', '\n', '\023', 'a', 'u', 't', 'o', '_', 's', 'a', 'n', '_', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'i', 'o', 
+'n', '\030', '\002', ' ', '\001', '(', '\010', 'R', '\021', 'a', 'u', 't', 'o', 'S', 'a', 'n', 'V', 'a', 'l', 'i', 'd', 'a', 't', 'i', 'o', 
+'n', '\022', 'D', '\n', '\030', 'o', 'v', 'e', 'r', 'r', 'i', 'd', 'e', '_', 'a', 'u', 't', 'o', '_', 's', 'n', 'i', '_', 'h', 'e', 
+'a', 'd', 'e', 'r', '\030', '\003', ' ', '\001', '(', '\t', 'B', '\013', '\372', 'B', '\010', 'r', '\006', '\300', '\001', '\001', '\320', '\001', '\001', 'R', '\025', 
+'o', 'v', 'e', 'r', 'r', 'i', 'd', 'e', 'A', 'u', 't', 'o', 'S', 'n', 'i', 'H', 'e', 'a', 'd', 'e', 'r', ':', '4', '\232', '\305', 
+'\210', '\036', '/', '\n', '-', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'c', 'o', 'r', 'e', '.', 'U', 'p', 
+'s', 't', 'r', 'e', 'a', 'm', 'H', 't', 't', 'p', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'O', 'p', 't', 'i', 'o', 'n', 's', 
+'\"', '\346', '\001', '\n', '\036', 'A', 'l', 't', 'e', 'r', 'n', 'a', 't', 'e', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 's', 'C', 'a', 
+'c', 'h', 'e', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', '\033', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'B', 
+'\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\004', 'n', 'a', 'm', 'e', '\022', 'F', '\n', '\013', 'm', 'a', 'x', '_', 'e', 'n', 't', 
+'r', 'i', 'e', 's', '\030', '\002', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 
+'b', 'u', 'f', '.', 'U', 'I', 'n', 't', '3', '2', 'V', 'a', 'l', 'u', 'e', 'B', '\007', '\372', 'B', '\004', '*', '\002', ' ', '\000', 'R', 
+'\n', 'm', 'a', 'x', 'E', 'n', 't', 'r', 'i', 'e', 's', '\022', '_', '\n', '\026', 'k', 'e', 'y', '_', 'v', 'a', 'l', 'u', 'e', '_', 
+'s', 't', 'o', 'r', 'e', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\003', ' ', '\001', '(', '\013', '2', '*', '.', 'e', 'n', 'v', 'o', 
+'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'T', 'y', 'p', 'e', 'd', 'E', 'x', 't', 
+'e', 'n', 's', 'i', 'o', 'n', 'C', 'o', 'n', 'f', 'i', 'g', 'R', '\023', 'k', 'e', 'y', 'V', 'a', 'l', 'u', 'e', 'S', 't', 'o', 
+'r', 'e', 'C', 'o', 'n', 'f', 'i', 'g', '\"', '\257', '\005', '\n', '\023', 'H', 't', 't', 'p', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 
 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', '<', '\n', '\014', 'i', 'd', 'l', 'e', '_', 't', 'i', 'm', 'e', 'o', 'u', 't', '\030', '\001', 
 ' ', '\001', '(', '\013', '2', '\031', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'u', 
 'r', 'a', 't', 'i', 'o', 'n', 'R', '\013', 'i', 'd', 'l', 'e', 'T', 'i', 'm', 'e', 'o', 'u', 't', '\022', 'Q', '\n', '\027', 'm', 'a', 
@@ -247,7 +256,7 @@ static const char descriptor[5396] = {'\n', '#', 'e', 'n', 'v', 'o', 'y', '/', '
 'H', 't', 't', 'p', '2', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'O', 'p', 't', 'i', 'o', 'n', 's', 'R', '\024', 'h', 't', 't', 
 'p', '2', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'O', 'p', 't', 'i', 'o', 'n', 's', ':', ',', '\232', '\305', '\210', '\036', '\'', '\n', 
 '%', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'c', 'o', 'r', 'e', '.', 'G', 'r', 'p', 'c', 'P', 'r', 
-'o', 't', 'o', 'c', 'o', 'l', 'O', 'p', 't', 'i', 'o', 'n', 's', '\"', '\361', '\001', '\n', '\024', 'H', 't', 't', 'p', '3', 'P', 'r', 
+'o', 't', 'o', 'c', 'o', 'l', 'O', 'p', 't', 'i', 'o', 'n', 's', '\"', '\261', '\002', '\n', '\024', 'H', 't', 't', 'p', '3', 'P', 'r', 
 'o', 't', 'o', 'c', 'o', 'l', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', ']', '\n', '\025', 'q', 'u', 'i', 'c', '_', 'p', 'r', 'o', 
 't', 'o', 'c', 'o', 'l', '_', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\001', ' ', '\001', '(', '\013', '2', ')', '.', 'e', 'n', 'v', 
 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'Q', 'u', 'i', 'c', 'P', 'r', 'o', 
@@ -257,21 +266,25 @@ static const char descriptor[5396] = {'\n', '#', 'e', 'n', 'v', 'o', 'y', '/', '
 'm', 'e', 's', 's', 'a', 'g', 'e', '\030', '\002', ' ', '\001', '(', '\013', '2', '\032', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 
 'o', 't', 'o', 'b', 'u', 'f', '.', 'B', 'o', 'o', 'l', 'V', 'a', 'l', 'u', 'e', 'R', '\'', 'o', 'v', 'e', 'r', 'r', 'i', 'd', 
 'e', 'S', 't', 'r', 'e', 'a', 'm', 'E', 'r', 'r', 'o', 'r', 'O', 'n', 'I', 'n', 'v', 'a', 'l', 'i', 'd', 'H', 't', 't', 'p', 
-'M', 'e', 's', 's', 'a', 'g', 'e', '\"', 't', '\n', '\032', 'S', 'c', 'h', 'e', 'm', 'e', 'H', 'e', 'a', 'd', 'e', 'r', 'T', 'r', 
-'a', 'n', 's', 'f', 'o', 'r', 'm', 'a', 't', 'i', 'o', 'n', '\022', 'D', '\n', '\023', 's', 'c', 'h', 'e', 'm', 'e', '_', 't', 'o', 
-'_', 'o', 'v', 'e', 'r', 'w', 'r', 'i', 't', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\022', '\372', 'B', '\017', 'r', '\r', 'R', '\004', 
-'h', 't', 't', 'p', 'R', '\005', 'h', 't', 't', 'p', 's', 'H', '\000', 'R', '\021', 's', 'c', 'h', 'e', 'm', 'e', 'T', 'o', 'O', 'v', 
-'e', 'r', 'w', 'r', 'i', 't', 'e', 'B', '\020', '\n', '\016', 't', 'r', 'a', 'n', 's', 'f', 'o', 'r', 'm', 'a', 't', 'i', 'o', 'n', 
-'B', '=', '\n', '\"', 'i', 'o', '.', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 
-'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', 'B', '\r', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'P', 'r', 
-'o', 't', 'o', 'P', '\001', '\272', '\200', '\310', '\321', '\006', '\002', '\020', '\002', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', 
+'M', 'e', 's', 's', 'a', 'g', 'e', '\022', '>', '\n', '\026', 'a', 'l', 'l', 'o', 'w', '_', 'e', 'x', 't', 'e', 'n', 'd', 'e', 'd', 
+'_', 'c', 'o', 'n', 'n', 'e', 'c', 't', '\030', '\005', ' ', '\001', '(', '\010', 'B', '\010', '\322', '\306', '\244', '\341', '\006', '\002', '\010', '\001', 'R', 
+'\024', 'a', 'l', 'l', 'o', 'w', 'E', 'x', 't', 'e', 'n', 'd', 'e', 'd', 'C', 'o', 'n', 'n', 'e', 'c', 't', '\"', 't', '\n', '\032', 
+'S', 'c', 'h', 'e', 'm', 'e', 'H', 'e', 'a', 'd', 'e', 'r', 'T', 'r', 'a', 'n', 's', 'f', 'o', 'r', 'm', 'a', 't', 'i', 'o', 
+'n', '\022', 'D', '\n', '\023', 's', 'c', 'h', 'e', 'm', 'e', '_', 't', 'o', '_', 'o', 'v', 'e', 'r', 'w', 'r', 'i', 't', 'e', '\030', 
+'\001', ' ', '\001', '(', '\t', 'B', '\022', '\372', 'B', '\017', 'r', '\r', 'R', '\004', 'h', 't', 't', 'p', 'R', '\005', 'h', 't', 't', 'p', 's', 
+'H', '\000', 'R', '\021', 's', 'c', 'h', 'e', 'm', 'e', 'T', 'o', 'O', 'v', 'e', 'r', 'w', 'r', 'i', 't', 'e', 'B', '\020', '\n', '\016', 
+'t', 'r', 'a', 'n', 's', 'f', 'o', 'r', 'm', 'a', 't', 'i', 'o', 'n', 'B', '=', '\n', '\"', 'i', 'o', '.', 'e', 'n', 'v', 'o', 
+'y', 'p', 'r', 'o', 'x', 'y', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 
+'v', '3', 'B', '\r', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'P', 'r', 'o', 't', 'o', 'P', '\001', '\272', '\200', '\310', '\321', '\006', '\002', 
+'\020', '\002', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', 
 };
 
-static upb_def_init *deps[9] = {
+static upb_def_init *deps[10] = {
   &envoy_config_core_v3_extension_proto_upbdefinit,
   &envoy_type_v3_percent_proto_upbdefinit,
   &google_protobuf_duration_proto_upbdefinit,
   &google_protobuf_wrappers_proto_upbdefinit,
+  &xds_annotations_v3_status_proto_upbdefinit,
   &envoy_annotations_deprecation_proto_upbdefinit,
   &udpa_annotations_status_proto_upbdefinit,
   &udpa_annotations_versioning_proto_upbdefinit,
@@ -283,5 +296,5 @@ upb_def_init envoy_config_core_v3_protocol_proto_upbdefinit = {
   deps,
   layouts,
   "envoy/config/core/v3/protocol.proto",
-  UPB_STRVIEW_INIT(descriptor, 5396)
+  UPB_STRVIEW_INIT(descriptor, 5660)
 };
index e9ab905..f1d8540 100644 (file)
@@ -14,7 +14,6 @@ extern upb_def_init envoy_config_core_v3_base_proto_upbdefinit;
 extern upb_def_init envoy_config_core_v3_config_source_proto_upbdefinit;
 extern upb_def_init envoy_config_core_v3_health_check_proto_upbdefinit;
 extern upb_def_init google_protobuf_wrappers_proto_upbdefinit;
-extern upb_def_init udpa_annotations_migrate_proto_upbdefinit;
 extern upb_def_init udpa_annotations_status_proto_upbdefinit;
 extern upb_def_init udpa_annotations_versioning_proto_upbdefinit;
 extern upb_def_init validate_validate_proto_upbdefinit;
@@ -34,7 +33,7 @@ static const upb_msglayout *layouts[6] = {
   &envoy_config_endpoint_v3_LocalityLbEndpoints_LbEndpointList_msginit,
 };
 
-static const char descriptor[2151] = {'\n', '2', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'e', 'n', 'd', 'p', 'o', 'i', 'n', 't', '/', 'v', 
+static const char descriptor[2119] = {'\n', '2', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'e', 'n', 'd', 'p', 'o', 'i', 'n', 't', '/', 'v', 
 '3', '/', 'e', 'n', 'd', 'p', 'o', 'i', 'n', 't', '_', 'c', 'o', 'm', 'p', 'o', 'n', 'e', 'n', 't', 's', '.', 'p', 'r', 'o', 
 't', 'o', '\022', '\030', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'e', 'n', 'd', 'p', 'o', 'i', 'n', 't', 
 '.', 'v', '3', '\032', '\"', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', 
@@ -44,92 +43,89 @@ static const char descriptor[2151] = {'\n', '2', 'e', 'n', 'v', 'o', 'y', '/', '
 'g', '_', 's', 'o', 'u', 'r', 'c', 'e', '.', 'p', 'r', 'o', 't', 'o', '\032', '\'', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 
 'f', 'i', 'g', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '/', 'h', 'e', 'a', 'l', 't', 'h', '_', 'c', 'h', 'e', 'c', 'k', '.', 
 'p', 'r', 'o', 't', 'o', '\032', '\036', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 'w', 'r', 
-'a', 'p', 'p', 'e', 'r', 's', '.', 'p', 'r', 'o', 't', 'o', '\032', '\036', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 
-'t', 'i', 'o', 'n', 's', '/', 'm', 'i', 'g', 'r', 'a', 't', 'e', '.', 'p', 'r', 'o', 't', 'o', '\032', '\035', 'u', 'd', 'p', 'a', 
-'/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 's', 't', 'a', 't', 'u', 's', '.', 'p', 'r', 'o', 't', 'o', 
-'\032', '!', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 'v', 'e', 'r', 's', 'i', 'o', 
-'n', 'i', 'n', 'g', '.', 'p', 'r', 'o', 't', 'o', '\032', '\027', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '/', 'v', 'a', 'l', 'i', 
-'d', 'a', 't', 'e', '.', 'p', 'r', 'o', 't', 'o', '\"', '\201', '\003', '\n', '\010', 'E', 'n', 'd', 'p', 'o', 'i', 'n', 't', '\022', '7', 
-'\n', '\007', 'a', 'd', 'd', 'r', 'e', 's', 's', '\030', '\001', ' ', '\001', '(', '\013', '2', '\035', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 
-'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'A', 'd', 'd', 'r', 'e', 's', 's', 'R', '\007', 'a', 'd', 
-'d', 'r', 'e', 's', 's', '\022', 'd', '\n', '\023', 'h', 'e', 'a', 'l', 't', 'h', '_', 'c', 'h', 'e', 'c', 'k', '_', 'c', 'o', 'n', 
-'f', 'i', 'g', '\030', '\002', ' ', '\001', '(', '\013', '2', '4', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 
-'e', 'n', 'd', 'p', 'o', 'i', 'n', 't', '.', 'v', '3', '.', 'E', 'n', 'd', 'p', 'o', 'i', 'n', 't', '.', 'H', 'e', 'a', 'l', 
-'t', 'h', 'C', 'h', 'e', 'c', 'k', 'C', 'o', 'n', 'f', 'i', 'g', 'R', '\021', 'h', 'e', 'a', 'l', 't', 'h', 'C', 'h', 'e', 'c', 
-'k', 'C', 'o', 'n', 'f', 'i', 'g', '\022', '\032', '\n', '\010', 'h', 'o', 's', 't', 'n', 'a', 'm', 'e', '\030', '\003', ' ', '\001', '(', '\t', 
-'R', '\010', 'h', 'o', 's', 't', 'n', 'a', 'm', 'e', '\032', '\222', '\001', '\n', '\021', 'H', 'e', 'a', 'l', 't', 'h', 'C', 'h', 'e', 'c', 
-'k', 'C', 'o', 'n', 'f', 'i', 'g', '\022', '(', '\n', '\n', 'p', 'o', 'r', 't', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\001', ' ', '\001', 
-'(', '\r', 'B', '\t', '\372', 'B', '\006', '*', '\004', '\030', '\377', '\377', '\003', 'R', '\t', 'p', 'o', 'r', 't', 'V', 'a', 'l', 'u', 'e', '\022', 
-'\032', '\n', '\010', 'h', 'o', 's', 't', 'n', 'a', 'm', 'e', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\010', 'h', 'o', 's', 't', 'n', 'a', 
-'m', 'e', ':', '7', '\232', '\305', '\210', '\036', '2', '\n', '0', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'e', 
-'n', 'd', 'p', 'o', 'i', 'n', 't', '.', 'E', 'n', 'd', 'p', 'o', 'i', 'n', 't', '.', 'H', 'e', 'a', 'l', 't', 'h', 'C', 'h', 
-'e', 'c', 'k', 'C', 'o', 'n', 'f', 'i', 'g', ':', '%', '\232', '\305', '\210', '\036', ' ', '\n', '\036', 'e', 'n', 'v', 'o', 'y', '.', 'a', 
-'p', 'i', '.', 'v', '2', '.', 'e', 'n', 'd', 'p', 'o', 'i', 'n', 't', '.', 'E', 'n', 'd', 'p', 'o', 'i', 'n', 't', '\"', '\221', 
-'\003', '\n', '\n', 'L', 'b', 'E', 'n', 'd', 'p', 'o', 'i', 'n', 't', '\022', '@', '\n', '\010', 'e', 'n', 'd', 'p', 'o', 'i', 'n', 't', 
-'\030', '\001', ' ', '\001', '(', '\013', '2', '\"', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'e', 'n', 'd', 
-'p', 'o', 'i', 'n', 't', '.', 'v', '3', '.', 'E', 'n', 'd', 'p', 'o', 'i', 'n', 't', 'H', '\000', 'R', '\010', 'e', 'n', 'd', 'p', 
-'o', 'i', 'n', 't', '\022', '%', '\n', '\r', 'e', 'n', 'd', 'p', 'o', 'i', 'n', 't', '_', 'n', 'a', 'm', 'e', '\030', '\005', ' ', '\001', 
-'(', '\t', 'H', '\000', 'R', '\014', 'e', 'n', 'd', 'p', 'o', 'i', 'n', 't', 'N', 'a', 'm', 'e', '\022', 'G', '\n', '\r', 'h', 'e', 'a', 
-'l', 't', 'h', '_', 's', 't', 'a', 't', 'u', 's', '\030', '\002', ' ', '\001', '(', '\016', '2', '\"', '.', 'e', 'n', 'v', 'o', 'y', '.', 
-'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'H', 'e', 'a', 'l', 't', 'h', 'S', 't', 'a', 't', 
-'u', 's', 'R', '\014', 'h', 'e', 'a', 'l', 't', 'h', 'S', 't', 'a', 't', 'u', 's', '\022', ':', '\n', '\010', 'm', 'e', 't', 'a', 'd', 
-'a', 't', 'a', '\030', '\003', ' ', '\001', '(', '\013', '2', '\036', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 
-'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'M', 'e', 't', 'a', 'd', 'a', 't', 'a', 'R', '\010', 'm', 'e', 't', 'a', 'd', 'a', 't', 
-'a', '\022', 'Y', '\n', '\025', 'l', 'o', 'a', 'd', '_', 'b', 'a', 'l', 'a', 'n', 'c', 'i', 'n', 'g', '_', 'w', 'e', 'i', 'g', 'h', 
-'t', '\030', '\004', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', 
-'.', 'U', 'I', 'n', 't', '3', '2', 'V', 'a', 'l', 'u', 'e', 'B', '\007', '\372', 'B', '\004', '*', '\002', '(', '\001', 'R', '\023', 'l', 'o', 
-'a', 'd', 'B', 'a', 'l', 'a', 'n', 'c', 'i', 'n', 'g', 'W', 'e', 'i', 'g', 'h', 't', ':', '\'', '\232', '\305', '\210', '\036', '\"', '\n', 
-' ', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'e', 'n', 'd', 'p', 'o', 'i', 'n', 't', '.', 'L', 'b', 
-'E', 'n', 'd', 'p', 'o', 'i', 'n', 't', 'B', '\021', '\n', '\017', 'h', 'o', 's', 't', '_', 'i', 'd', 'e', 'n', 't', 'i', 'f', 'i', 
-'e', 'r', '\"', '\222', '\001', '\n', '\031', 'L', 'e', 'd', 's', 'C', 'l', 'u', 's', 't', 'e', 'r', 'L', 'o', 'c', 'a', 'l', 'i', 't', 
-'y', 'C', 'o', 'n', 'f', 'i', 'g', '\022', 'C', '\n', '\013', 'l', 'e', 'd', 's', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\001', ' ', 
-'\001', '(', '\013', '2', '\"', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', 
-'3', '.', 'C', 'o', 'n', 'f', 'i', 'g', 'S', 'o', 'u', 'r', 'c', 'e', 'R', '\n', 'l', 'e', 'd', 's', 'C', 'o', 'n', 'f', 'i', 
-'g', '\022', '0', '\n', '\024', 'l', 'e', 'd', 's', '_', 'c', 'o', 'l', 'l', 'e', 'c', 't', 'i', 'o', 'n', '_', 'n', 'a', 'm', 'e', 
-'\030', '\002', ' ', '\001', '(', '\t', 'R', '\022', 'l', 'e', 'd', 's', 'C', 'o', 'l', 'l', 'e', 'c', 't', 'i', 'o', 'n', 'N', 'a', 'm', 
-'e', '\"', '\341', '\005', '\n', '\023', 'L', 'o', 'c', 'a', 'l', 'i', 't', 'y', 'L', 'b', 'E', 'n', 'd', 'p', 'o', 'i', 'n', 't', 's', 
-'\022', ':', '\n', '\010', 'l', 'o', 'c', 'a', 'l', 'i', 't', 'y', '\030', '\001', ' ', '\001', '(', '\013', '2', '\036', '.', 'e', 'n', 'v', 'o', 
-'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'L', 'o', 'c', 'a', 'l', 'i', 't', 'y', 
-'R', '\010', 'l', 'o', 'c', 'a', 'l', 'i', 't', 'y', '\022', 'G', '\n', '\014', 'l', 'b', '_', 'e', 'n', 'd', 'p', 'o', 'i', 'n', 't', 
-'s', '\030', '\002', ' ', '\003', '(', '\013', '2', '$', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'e', 'n', 
-'d', 'p', 'o', 'i', 'n', 't', '.', 'v', '3', '.', 'L', 'b', 'E', 'n', 'd', 'p', 'o', 'i', 'n', 't', 'R', '\013', 'l', 'b', 'E', 
-'n', 'd', 'p', 'o', 'i', 'n', 't', 's', '\022', 'v', '\n', '\027', 'l', 'o', 'a', 'd', '_', 'b', 'a', 'l', 'a', 'n', 'c', 'e', 'r', 
-'_', 'e', 'n', 'd', 'p', 'o', 'i', 'n', 't', 's', '\030', '\007', ' ', '\001', '(', '\013', '2', '<', '.', 'e', 'n', 'v', 'o', 'y', '.', 
-'c', 'o', 'n', 'f', 'i', 'g', '.', 'e', 'n', 'd', 'p', 'o', 'i', 'n', 't', '.', 'v', '3', '.', 'L', 'o', 'c', 'a', 'l', 'i', 
-'t', 'y', 'L', 'b', 'E', 'n', 'd', 'p', 'o', 'i', 'n', 't', 's', '.', 'L', 'b', 'E', 'n', 'd', 'p', 'o', 'i', 'n', 't', 'L', 
-'i', 's', 't', 'H', '\000', 'R', '\025', 'l', 'o', 'a', 'd', 'B', 'a', 'l', 'a', 'n', 'c', 'e', 'r', 'E', 'n', 'd', 'p', 'o', 'i', 
-'n', 't', 's', '\022', 'v', '\n', '\034', 'l', 'e', 'd', 's', '_', 'c', 'l', 'u', 's', 't', 'e', 'r', '_', 'l', 'o', 'c', 'a', 'l', 
-'i', 't', 'y', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\010', ' ', '\001', '(', '\013', '2', '3', '.', 'e', 'n', 'v', 'o', 'y', '.', 
-'c', 'o', 'n', 'f', 'i', 'g', '.', 'e', 'n', 'd', 'p', 'o', 'i', 'n', 't', '.', 'v', '3', '.', 'L', 'e', 'd', 's', 'C', 'l', 
-'u', 's', 't', 'e', 'r', 'L', 'o', 'c', 'a', 'l', 'i', 't', 'y', 'C', 'o', 'n', 'f', 'i', 'g', 'H', '\000', 'R', '\031', 'l', 'e', 
-'d', 's', 'C', 'l', 'u', 's', 't', 'e', 'r', 'L', 'o', 'c', 'a', 'l', 'i', 't', 'y', 'C', 'o', 'n', 'f', 'i', 'g', '\022', 'Y', 
-'\n', '\025', 'l', 'o', 'a', 'd', '_', 'b', 'a', 'l', 'a', 'n', 'c', 'i', 'n', 'g', '_', 'w', 'e', 'i', 'g', 'h', 't', '\030', '\003', 
-' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'I', 
-'n', 't', '3', '2', 'V', 'a', 'l', 'u', 'e', 'B', '\007', '\372', 'B', '\004', '*', '\002', '(', '\001', 'R', '\023', 'l', 'o', 'a', 'd', 'B', 
-'a', 'l', 'a', 'n', 'c', 'i', 'n', 'g', 'W', 'e', 'i', 'g', 'h', 't', '\022', '$', '\n', '\010', 'p', 'r', 'i', 'o', 'r', 'i', 't', 
-'y', '\030', '\005', ' ', '\001', '(', '\r', 'B', '\010', '\372', 'B', '\005', '*', '\003', '\030', '\200', '\001', 'R', '\010', 'p', 'r', 'i', 'o', 'r', 'i', 
-'t', 'y', '\022', ':', '\n', '\t', 'p', 'r', 'o', 'x', 'i', 'm', 'i', 't', 'y', '\030', '\006', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 
-'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'I', 'n', 't', '3', '2', 'V', 'a', 'l', 'u', 
-'e', 'R', '\t', 'p', 'r', 'o', 'x', 'i', 'm', 'i', 't', 'y', '\032', 'Y', '\n', '\016', 'L', 'b', 'E', 'n', 'd', 'p', 'o', 'i', 'n', 
-'t', 'L', 'i', 's', 't', '\022', 'G', '\n', '\014', 'l', 'b', '_', 'e', 'n', 'd', 'p', 'o', 'i', 'n', 't', 's', '\030', '\001', ' ', '\003', 
-'(', '\013', '2', '$', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'e', 'n', 'd', 'p', 'o', 'i', 'n', 
-'t', '.', 'v', '3', '.', 'L', 'b', 'E', 'n', 'd', 'p', 'o', 'i', 'n', 't', 'R', '\013', 'l', 'b', 'E', 'n', 'd', 'p', 'o', 'i', 
-'n', 't', 's', ':', '0', '\232', '\305', '\210', '\036', '+', '\n', ')', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 
-'e', 'n', 'd', 'p', 'o', 'i', 'n', 't', '.', 'L', 'o', 'c', 'a', 'l', 'i', 't', 'y', 'L', 'b', 'E', 'n', 'd', 'p', 'o', 'i', 
-'n', 't', 's', 'B', '\013', '\n', '\t', 'l', 'b', '_', 'c', 'o', 'n', 'f', 'i', 'g', 'B', 'K', '\n', '&', 'i', 'o', '.', 'e', 'n', 
-'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'e', 'n', 'd', 
-'p', 'o', 'i', 'n', 't', '.', 'v', '3', 'B', '\027', 'E', 'n', 'd', 'p', 'o', 'i', 'n', 't', 'C', 'o', 'm', 'p', 'o', 'n', 'e', 
-'n', 't', 's', 'P', 'r', 'o', 't', 'o', 'P', '\001', '\272', '\200', '\310', '\321', '\006', '\002', '\020', '\002', 'b', '\006', 'p', 'r', 'o', 't', 'o', 
-'3', 
+'a', 'p', 'p', 'e', 'r', 's', '.', 'p', 'r', 'o', 't', 'o', '\032', '\035', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 
+'t', 'i', 'o', 'n', 's', '/', 's', 't', 'a', 't', 'u', 's', '.', 'p', 'r', 'o', 't', 'o', '\032', '!', 'u', 'd', 'p', 'a', '/', 
+'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 'v', 'e', 'r', 's', 'i', 'o', 'n', 'i', 'n', 'g', '.', 'p', 'r', 
+'o', 't', 'o', '\032', '\027', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '/', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '.', 'p', 'r', 
+'o', 't', 'o', '\"', '\201', '\003', '\n', '\010', 'E', 'n', 'd', 'p', 'o', 'i', 'n', 't', '\022', '7', '\n', '\007', 'a', 'd', 'd', 'r', 'e', 
+'s', 's', '\030', '\001', ' ', '\001', '(', '\013', '2', '\035', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 
+'o', 'r', 'e', '.', 'v', '3', '.', 'A', 'd', 'd', 'r', 'e', 's', 's', 'R', '\007', 'a', 'd', 'd', 'r', 'e', 's', 's', '\022', 'd', 
+'\n', '\023', 'h', 'e', 'a', 'l', 't', 'h', '_', 'c', 'h', 'e', 'c', 'k', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\002', ' ', '\001', 
+'(', '\013', '2', '4', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'e', 'n', 'd', 'p', 'o', 'i', 'n', 
+'t', '.', 'v', '3', '.', 'E', 'n', 'd', 'p', 'o', 'i', 'n', 't', '.', 'H', 'e', 'a', 'l', 't', 'h', 'C', 'h', 'e', 'c', 'k', 
+'C', 'o', 'n', 'f', 'i', 'g', 'R', '\021', 'h', 'e', 'a', 'l', 't', 'h', 'C', 'h', 'e', 'c', 'k', 'C', 'o', 'n', 'f', 'i', 'g', 
+'\022', '\032', '\n', '\010', 'h', 'o', 's', 't', 'n', 'a', 'm', 'e', '\030', '\003', ' ', '\001', '(', '\t', 'R', '\010', 'h', 'o', 's', 't', 'n', 
+'a', 'm', 'e', '\032', '\222', '\001', '\n', '\021', 'H', 'e', 'a', 'l', 't', 'h', 'C', 'h', 'e', 'c', 'k', 'C', 'o', 'n', 'f', 'i', 'g', 
+'\022', '(', '\n', '\n', 'p', 'o', 'r', 't', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\001', ' ', '\001', '(', '\r', 'B', '\t', '\372', 'B', '\006', 
+'*', '\004', '\030', '\377', '\377', '\003', 'R', '\t', 'p', 'o', 'r', 't', 'V', 'a', 'l', 'u', 'e', '\022', '\032', '\n', '\010', 'h', 'o', 's', 't', 
+'n', 'a', 'm', 'e', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\010', 'h', 'o', 's', 't', 'n', 'a', 'm', 'e', ':', '7', '\232', '\305', '\210', 
+'\036', '2', '\n', '0', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'e', 'n', 'd', 'p', 'o', 'i', 'n', 't', 
+'.', 'E', 'n', 'd', 'p', 'o', 'i', 'n', 't', '.', 'H', 'e', 'a', 'l', 't', 'h', 'C', 'h', 'e', 'c', 'k', 'C', 'o', 'n', 'f', 
+'i', 'g', ':', '%', '\232', '\305', '\210', '\036', ' ', '\n', '\036', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'e', 
+'n', 'd', 'p', 'o', 'i', 'n', 't', '.', 'E', 'n', 'd', 'p', 'o', 'i', 'n', 't', '\"', '\221', '\003', '\n', '\n', 'L', 'b', 'E', 'n', 
+'d', 'p', 'o', 'i', 'n', 't', '\022', '@', '\n', '\010', 'e', 'n', 'd', 'p', 'o', 'i', 'n', 't', '\030', '\001', ' ', '\001', '(', '\013', '2', 
+'\"', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'e', 'n', 'd', 'p', 'o', 'i', 'n', 't', '.', 'v', 
+'3', '.', 'E', 'n', 'd', 'p', 'o', 'i', 'n', 't', 'H', '\000', 'R', '\010', 'e', 'n', 'd', 'p', 'o', 'i', 'n', 't', '\022', '%', '\n', 
+'\r', 'e', 'n', 'd', 'p', 'o', 'i', 'n', 't', '_', 'n', 'a', 'm', 'e', '\030', '\005', ' ', '\001', '(', '\t', 'H', '\000', 'R', '\014', 'e', 
+'n', 'd', 'p', 'o', 'i', 'n', 't', 'N', 'a', 'm', 'e', '\022', 'G', '\n', '\r', 'h', 'e', 'a', 'l', 't', 'h', '_', 's', 't', 'a', 
+'t', 'u', 's', '\030', '\002', ' ', '\001', '(', '\016', '2', '\"', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 
+'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'H', 'e', 'a', 'l', 't', 'h', 'S', 't', 'a', 't', 'u', 's', 'R', '\014', 'h', 'e', 'a', 
+'l', 't', 'h', 'S', 't', 'a', 't', 'u', 's', '\022', ':', '\n', '\010', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', '\030', '\003', ' ', '\001', 
+'(', '\013', '2', '\036', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', 
+'.', 'M', 'e', 't', 'a', 'd', 'a', 't', 'a', 'R', '\010', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', '\022', 'Y', '\n', '\025', 'l', 'o', 
+'a', 'd', '_', 'b', 'a', 'l', 'a', 'n', 'c', 'i', 'n', 'g', '_', 'w', 'e', 'i', 'g', 'h', 't', '\030', '\004', ' ', '\001', '(', '\013', 
+'2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'I', 'n', 't', '3', '2', 
+'V', 'a', 'l', 'u', 'e', 'B', '\007', '\372', 'B', '\004', '*', '\002', '(', '\001', 'R', '\023', 'l', 'o', 'a', 'd', 'B', 'a', 'l', 'a', 'n', 
+'c', 'i', 'n', 'g', 'W', 'e', 'i', 'g', 'h', 't', ':', '\'', '\232', '\305', '\210', '\036', '\"', '\n', ' ', 'e', 'n', 'v', 'o', 'y', '.', 
+'a', 'p', 'i', '.', 'v', '2', '.', 'e', 'n', 'd', 'p', 'o', 'i', 'n', 't', '.', 'L', 'b', 'E', 'n', 'd', 'p', 'o', 'i', 'n', 
+'t', 'B', '\021', '\n', '\017', 'h', 'o', 's', 't', '_', 'i', 'd', 'e', 'n', 't', 'i', 'f', 'i', 'e', 'r', '\"', '\222', '\001', '\n', '\031', 
+'L', 'e', 'd', 's', 'C', 'l', 'u', 's', 't', 'e', 'r', 'L', 'o', 'c', 'a', 'l', 'i', 't', 'y', 'C', 'o', 'n', 'f', 'i', 'g', 
+'\022', 'C', '\n', '\013', 'l', 'e', 'd', 's', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\001', ' ', '\001', '(', '\013', '2', '\"', '.', 'e', 
+'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'C', 'o', 'n', 'f', 'i', 
+'g', 'S', 'o', 'u', 'r', 'c', 'e', 'R', '\n', 'l', 'e', 'd', 's', 'C', 'o', 'n', 'f', 'i', 'g', '\022', '0', '\n', '\024', 'l', 'e', 
+'d', 's', '_', 'c', 'o', 'l', 'l', 'e', 'c', 't', 'i', 'o', 'n', '_', 'n', 'a', 'm', 'e', '\030', '\002', ' ', '\001', '(', '\t', 'R', 
+'\022', 'l', 'e', 'd', 's', 'C', 'o', 'l', 'l', 'e', 'c', 't', 'i', 'o', 'n', 'N', 'a', 'm', 'e', '\"', '\341', '\005', '\n', '\023', 'L', 
+'o', 'c', 'a', 'l', 'i', 't', 'y', 'L', 'b', 'E', 'n', 'd', 'p', 'o', 'i', 'n', 't', 's', '\022', ':', '\n', '\010', 'l', 'o', 'c', 
+'a', 'l', 'i', 't', 'y', '\030', '\001', ' ', '\001', '(', '\013', '2', '\036', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 
+'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'L', 'o', 'c', 'a', 'l', 'i', 't', 'y', 'R', '\010', 'l', 'o', 'c', 'a', 'l', 
+'i', 't', 'y', '\022', 'G', '\n', '\014', 'l', 'b', '_', 'e', 'n', 'd', 'p', 'o', 'i', 'n', 't', 's', '\030', '\002', ' ', '\003', '(', '\013', 
+'2', '$', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'e', 'n', 'd', 'p', 'o', 'i', 'n', 't', '.', 
+'v', '3', '.', 'L', 'b', 'E', 'n', 'd', 'p', 'o', 'i', 'n', 't', 'R', '\013', 'l', 'b', 'E', 'n', 'd', 'p', 'o', 'i', 'n', 't', 
+'s', '\022', 'v', '\n', '\027', 'l', 'o', 'a', 'd', '_', 'b', 'a', 'l', 'a', 'n', 'c', 'e', 'r', '_', 'e', 'n', 'd', 'p', 'o', 'i', 
+'n', 't', 's', '\030', '\007', ' ', '\001', '(', '\013', '2', '<', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 
+'e', 'n', 'd', 'p', 'o', 'i', 'n', 't', '.', 'v', '3', '.', 'L', 'o', 'c', 'a', 'l', 'i', 't', 'y', 'L', 'b', 'E', 'n', 'd', 
+'p', 'o', 'i', 'n', 't', 's', '.', 'L', 'b', 'E', 'n', 'd', 'p', 'o', 'i', 'n', 't', 'L', 'i', 's', 't', 'H', '\000', 'R', '\025', 
+'l', 'o', 'a', 'd', 'B', 'a', 'l', 'a', 'n', 'c', 'e', 'r', 'E', 'n', 'd', 'p', 'o', 'i', 'n', 't', 's', '\022', 'v', '\n', '\034', 
+'l', 'e', 'd', 's', '_', 'c', 'l', 'u', 's', 't', 'e', 'r', '_', 'l', 'o', 'c', 'a', 'l', 'i', 't', 'y', '_', 'c', 'o', 'n', 
+'f', 'i', 'g', '\030', '\010', ' ', '\001', '(', '\013', '2', '3', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 
+'e', 'n', 'd', 'p', 'o', 'i', 'n', 't', '.', 'v', '3', '.', 'L', 'e', 'd', 's', 'C', 'l', 'u', 's', 't', 'e', 'r', 'L', 'o', 
+'c', 'a', 'l', 'i', 't', 'y', 'C', 'o', 'n', 'f', 'i', 'g', 'H', '\000', 'R', '\031', 'l', 'e', 'd', 's', 'C', 'l', 'u', 's', 't', 
+'e', 'r', 'L', 'o', 'c', 'a', 'l', 'i', 't', 'y', 'C', 'o', 'n', 'f', 'i', 'g', '\022', 'Y', '\n', '\025', 'l', 'o', 'a', 'd', '_', 
+'b', 'a', 'l', 'a', 'n', 'c', 'i', 'n', 'g', '_', 'w', 'e', 'i', 'g', 'h', 't', '\030', '\003', ' ', '\001', '(', '\013', '2', '\034', '.', 
+'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'I', 'n', 't', '3', '2', 'V', 'a', 'l', 
+'u', 'e', 'B', '\007', '\372', 'B', '\004', '*', '\002', '(', '\001', 'R', '\023', 'l', 'o', 'a', 'd', 'B', 'a', 'l', 'a', 'n', 'c', 'i', 'n', 
+'g', 'W', 'e', 'i', 'g', 'h', 't', '\022', '$', '\n', '\010', 'p', 'r', 'i', 'o', 'r', 'i', 't', 'y', '\030', '\005', ' ', '\001', '(', '\r', 
+'B', '\010', '\372', 'B', '\005', '*', '\003', '\030', '\200', '\001', 'R', '\010', 'p', 'r', 'i', 'o', 'r', 'i', 't', 'y', '\022', ':', '\n', '\t', 'p', 
+'r', 'o', 'x', 'i', 'm', 'i', 't', 'y', '\030', '\006', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 
+'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'I', 'n', 't', '3', '2', 'V', 'a', 'l', 'u', 'e', 'R', '\t', 'p', 'r', 'o', 'x', 
+'i', 'm', 'i', 't', 'y', '\032', 'Y', '\n', '\016', 'L', 'b', 'E', 'n', 'd', 'p', 'o', 'i', 'n', 't', 'L', 'i', 's', 't', '\022', 'G', 
+'\n', '\014', 'l', 'b', '_', 'e', 'n', 'd', 'p', 'o', 'i', 'n', 't', 's', '\030', '\001', ' ', '\003', '(', '\013', '2', '$', '.', 'e', 'n', 
+'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'e', 'n', 'd', 'p', 'o', 'i', 'n', 't', '.', 'v', '3', '.', 'L', 'b', 
+'E', 'n', 'd', 'p', 'o', 'i', 'n', 't', 'R', '\013', 'l', 'b', 'E', 'n', 'd', 'p', 'o', 'i', 'n', 't', 's', ':', '0', '\232', '\305', 
+'\210', '\036', '+', '\n', ')', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'e', 'n', 'd', 'p', 'o', 'i', 'n', 
+'t', '.', 'L', 'o', 'c', 'a', 'l', 'i', 't', 'y', 'L', 'b', 'E', 'n', 'd', 'p', 'o', 'i', 'n', 't', 's', 'B', '\013', '\n', '\t', 
+'l', 'b', '_', 'c', 'o', 'n', 'f', 'i', 'g', 'B', 'K', '\n', '&', 'i', 'o', '.', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x', 
+'y', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'e', 'n', 'd', 'p', 'o', 'i', 'n', 't', '.', 'v', 
+'3', 'B', '\027', 'E', 'n', 'd', 'p', 'o', 'i', 'n', 't', 'C', 'o', 'm', 'p', 'o', 'n', 'e', 'n', 't', 's', 'P', 'r', 'o', 't', 
+'o', 'P', '\001', '\272', '\200', '\310', '\321', '\006', '\002', '\020', '\002', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', 
 };
 
-static upb_def_init *deps[10] = {
+static upb_def_init *deps[9] = {
   &envoy_config_core_v3_address_proto_upbdefinit,
   &envoy_config_core_v3_base_proto_upbdefinit,
   &envoy_config_core_v3_config_source_proto_upbdefinit,
   &envoy_config_core_v3_health_check_proto_upbdefinit,
   &google_protobuf_wrappers_proto_upbdefinit,
-  &udpa_annotations_migrate_proto_upbdefinit,
   &udpa_annotations_status_proto_upbdefinit,
   &udpa_annotations_versioning_proto_upbdefinit,
   &validate_validate_proto_upbdefinit,
@@ -140,5 +136,5 @@ upb_def_init envoy_config_endpoint_v3_endpoint_components_proto_upbdefinit = {
   deps,
   layouts,
   "envoy/config/endpoint/v3/endpoint_components.proto",
-  UPB_STRVIEW_INIT(descriptor, 2151)
+  UPB_STRVIEW_INIT(descriptor, 2119)
 };
index 39a554f..e0e4ec2 100644 (file)
@@ -10,6 +10,7 @@
 #include "envoy/config/rbac/v3/rbac.upbdefs.h"
 
 extern upb_def_init envoy_config_core_v3_address_proto_upbdefinit;
+extern upb_def_init envoy_config_core_v3_extension_proto_upbdefinit;
 extern upb_def_init envoy_config_route_v3_route_components_proto_upbdefinit;
 extern upb_def_init envoy_type_matcher_v3_metadata_proto_upbdefinit;
 extern upb_def_init envoy_type_matcher_v3_path_proto_upbdefinit;
@@ -42,141 +43,147 @@ static const upb_msglayout *layouts[8] = {
   &envoy_config_rbac_v3_Principal_Authenticated_msginit,
 };
 
-static const char descriptor[3268] = {'\n', '\037', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'r', 'b', 'a', 'c', '/', 'v', '3', '/', 'r', 'b', 
+static const char descriptor[3378] = {'\n', '\037', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'r', 'b', 'a', 'c', '/', 'v', '3', '/', 'r', 'b', 
 'a', 'c', '.', 'p', 'r', 'o', 't', 'o', '\022', '\024', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 
 'a', 'c', '.', 'v', '3', '\032', '\"', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'c', 'o', 'r', 'e', '/', 
-'v', '3', '/', 'a', 'd', 'd', 'r', 'e', 's', 's', '.', 'p', 'r', 'o', 't', 'o', '\032', ',', 'e', 'n', 'v', 'o', 'y', '/', 'c', 
-'o', 'n', 'f', 'i', 'g', '/', 'r', 'o', 'u', 't', 'e', '/', 'v', '3', '/', 'r', 'o', 'u', 't', 'e', '_', 'c', 'o', 'm', 'p', 
-'o', 'n', 'e', 'n', 't', 's', '.', 'p', 'r', 'o', 't', 'o', '\032', '$', 'e', 'n', 'v', 'o', 'y', '/', 't', 'y', 'p', 'e', '/', 
-'m', 'a', 't', 'c', 'h', 'e', 'r', '/', 'v', '3', '/', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', '.', 'p', 'r', 'o', 't', 'o', 
-'\032', ' ', 'e', 'n', 'v', 'o', 'y', '/', 't', 'y', 'p', 'e', '/', 'm', 'a', 't', 'c', 'h', 'e', 'r', '/', 'v', '3', '/', 'p', 
-'a', 't', 'h', '.', 'p', 'r', 'o', 't', 'o', '\032', '\"', 'e', 'n', 'v', 'o', 'y', '/', 't', 'y', 'p', 'e', '/', 'm', 'a', 't', 
-'c', 'h', 'e', 'r', '/', 'v', '3', '/', 's', 't', 'r', 'i', 'n', 'g', '.', 'p', 'r', 'o', 't', 'o', '\032', '\031', 'e', 'n', 'v', 
-'o', 'y', '/', 't', 'y', 'p', 'e', '/', 'v', '3', '/', 'r', 'a', 'n', 'g', 'e', '.', 'p', 'r', 'o', 't', 'o', '\032', '&', 'g', 
-'o', 'o', 'g', 'l', 'e', '/', 'a', 'p', 'i', '/', 'e', 'x', 'p', 'r', '/', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '/', 'c', 
-'h', 'e', 'c', 'k', 'e', 'd', '.', 'p', 'r', 'o', 't', 'o', '\032', '%', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'a', 'p', 'i', '/', 
-'e', 'x', 'p', 'r', '/', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '/', 's', 'y', 'n', 't', 'a', 'x', '.', 'p', 'r', 'o', 't', 
-'o', '\032', '#', 'e', 'n', 'v', 'o', 'y', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 'd', 'e', 'p', 'r', 
-'e', 'c', 'a', 't', 'i', 'o', 'n', '.', 'p', 'r', 'o', 't', 'o', '\032', '\036', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 
-'a', 't', 'i', 'o', 'n', 's', '/', 'm', 'i', 'g', 'r', 'a', 't', 'e', '.', 'p', 'r', 'o', 't', 'o', '\032', '\035', 'u', 'd', 'p', 
-'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 's', 't', 'a', 't', 'u', 's', '.', 'p', 'r', 'o', 't', 
-'o', '\032', '!', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 'v', 'e', 'r', 's', 'i', 
-'o', 'n', 'i', 'n', 'g', '.', 'p', 'r', 'o', 't', 'o', '\032', '\027', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '/', 'v', 'a', 'l', 
-'i', 'd', 'a', 't', 'e', '.', 'p', 'r', 'o', 't', 'o', '\"', '\266', '\002', '\n', '\004', 'R', 'B', 'A', 'C', '\022', 'C', '\n', '\006', 'a', 
-'c', 't', 'i', 'o', 'n', '\030', '\001', ' ', '\001', '(', '\016', '2', '!', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 
-'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'R', 'B', 'A', 'C', '.', 'A', 'c', 't', 'i', 'o', 'n', 'B', '\010', '\372', 'B', 
-'\005', '\202', '\001', '\002', '\020', '\001', 'R', '\006', 'a', 'c', 't', 'i', 'o', 'n', '\022', 'D', '\n', '\010', 'p', 'o', 'l', 'i', 'c', 'i', 'e', 
-'s', '\030', '\002', ' ', '\003', '(', '\013', '2', '(', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 
-'a', 'c', '.', 'v', '3', '.', 'R', 'B', 'A', 'C', '.', 'P', 'o', 'l', 'i', 'c', 'i', 'e', 's', 'E', 'n', 't', 'r', 'y', 'R', 
-'\010', 'p', 'o', 'l', 'i', 'c', 'i', 'e', 's', '\032', 'Y', '\n', '\r', 'P', 'o', 'l', 'i', 'c', 'i', 'e', 's', 'E', 'n', 't', 'r', 
-'y', '\022', '\020', '\n', '\003', 'k', 'e', 'y', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\003', 'k', 'e', 'y', '\022', '2', '\n', '\005', 'v', 'a', 
-'l', 'u', 'e', '\030', '\002', ' ', '\001', '(', '\013', '2', '\034', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 
-'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'P', 'o', 'l', 'i', 'c', 'y', 'R', '\005', 'v', 'a', 'l', 'u', 'e', ':', '\002', '8', '\001', 
-'\"', '&', '\n', '\006', 'A', 'c', 't', 'i', 'o', 'n', '\022', '\t', '\n', '\005', 'A', 'L', 'L', 'O', 'W', '\020', '\000', '\022', '\010', '\n', '\004', 
-'D', 'E', 'N', 'Y', '\020', '\001', '\022', '\007', '\n', '\003', 'L', 'O', 'G', '\020', '\002', ':', ' ', '\232', '\305', '\210', '\036', '\033', '\n', '\031', 'e', 
-'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '2', '.', 'R', 'B', 'A', 'C', '\"', 
-'\223', '\003', '\n', '\006', 'P', 'o', 'l', 'i', 'c', 'y', '\022', 'L', '\n', '\013', 'p', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 's', 
-'\030', '\001', ' ', '\003', '(', '\013', '2', ' ', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 
-'c', '.', 'v', '3', '.', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'B', '\010', '\372', 'B', '\005', '\222', '\001', '\002', '\010', '\001', 
-'R', '\013', 'p', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 's', '\022', 'I', '\n', '\n', 'p', 'r', 'i', 'n', 'c', 'i', 'p', 'a', 
-'l', 's', '\030', '\002', ' ', '\003', '(', '\013', '2', '\037', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 
+'v', '3', '/', 'a', 'd', 'd', 'r', 'e', 's', 's', '.', 'p', 'r', 'o', 't', 'o', '\032', '$', 'e', 'n', 'v', 'o', 'y', '/', 'c', 
+'o', 'n', 'f', 'i', 'g', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '/', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', '.', 'p', 
+'r', 'o', 't', 'o', '\032', ',', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'r', 'o', 'u', 't', 'e', '/', 
+'v', '3', '/', 'r', 'o', 'u', 't', 'e', '_', 'c', 'o', 'm', 'p', 'o', 'n', 'e', 'n', 't', 's', '.', 'p', 'r', 'o', 't', 'o', 
+'\032', '$', 'e', 'n', 'v', 'o', 'y', '/', 't', 'y', 'p', 'e', '/', 'm', 'a', 't', 'c', 'h', 'e', 'r', '/', 'v', '3', '/', 'm', 
+'e', 't', 'a', 'd', 'a', 't', 'a', '.', 'p', 'r', 'o', 't', 'o', '\032', ' ', 'e', 'n', 'v', 'o', 'y', '/', 't', 'y', 'p', 'e', 
+'/', 'm', 'a', 't', 'c', 'h', 'e', 'r', '/', 'v', '3', '/', 'p', 'a', 't', 'h', '.', 'p', 'r', 'o', 't', 'o', '\032', '\"', 'e', 
+'n', 'v', 'o', 'y', '/', 't', 'y', 'p', 'e', '/', 'm', 'a', 't', 'c', 'h', 'e', 'r', '/', 'v', '3', '/', 's', 't', 'r', 'i', 
+'n', 'g', '.', 'p', 'r', 'o', 't', 'o', '\032', '\031', 'e', 'n', 'v', 'o', 'y', '/', 't', 'y', 'p', 'e', '/', 'v', '3', '/', 'r', 
+'a', 'n', 'g', 'e', '.', 'p', 'r', 'o', 't', 'o', '\032', '&', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'a', 'p', 'i', '/', 'e', 'x', 
+'p', 'r', '/', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '/', 'c', 'h', 'e', 'c', 'k', 'e', 'd', '.', 'p', 'r', 'o', 't', 'o', 
+'\032', '%', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'a', 'p', 'i', '/', 'e', 'x', 'p', 'r', '/', 'v', '1', 'a', 'l', 'p', 'h', 'a', 
+'1', '/', 's', 'y', 'n', 't', 'a', 'x', '.', 'p', 'r', 'o', 't', 'o', '\032', '#', 'e', 'n', 'v', 'o', 'y', '/', 'a', 'n', 'n', 
+'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'i', 'o', 'n', '.', 'p', 'r', 'o', 't', 
+'o', '\032', '\036', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 'm', 'i', 'g', 'r', 'a', 
+'t', 'e', '.', 'p', 'r', 'o', 't', 'o', '\032', '\035', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 
+'s', '/', 's', 't', 'a', 't', 'u', 's', '.', 'p', 'r', 'o', 't', 'o', '\032', '!', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 
+'t', 'a', 't', 'i', 'o', 'n', 's', '/', 'v', 'e', 'r', 's', 'i', 'o', 'n', 'i', 'n', 'g', '.', 'p', 'r', 'o', 't', 'o', '\032', 
+'\027', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '/', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '.', 'p', 'r', 'o', 't', 'o', '\"', 
+'\266', '\002', '\n', '\004', 'R', 'B', 'A', 'C', '\022', 'C', '\n', '\006', 'a', 'c', 't', 'i', 'o', 'n', '\030', '\001', ' ', '\001', '(', '\016', '2', 
+'!', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'R', 'B', 
+'A', 'C', '.', 'A', 'c', 't', 'i', 'o', 'n', 'B', '\010', '\372', 'B', '\005', '\202', '\001', '\002', '\020', '\001', 'R', '\006', 'a', 'c', 't', 'i', 
+'o', 'n', '\022', 'D', '\n', '\010', 'p', 'o', 'l', 'i', 'c', 'i', 'e', 's', '\030', '\002', ' ', '\003', '(', '\013', '2', '(', '.', 'e', 'n', 
+'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'R', 'B', 'A', 'C', '.', 'P', 
+'o', 'l', 'i', 'c', 'i', 'e', 's', 'E', 'n', 't', 'r', 'y', 'R', '\010', 'p', 'o', 'l', 'i', 'c', 'i', 'e', 's', '\032', 'Y', '\n', 
+'\r', 'P', 'o', 'l', 'i', 'c', 'i', 'e', 's', 'E', 'n', 't', 'r', 'y', '\022', '\020', '\n', '\003', 'k', 'e', 'y', '\030', '\001', ' ', '\001', 
+'(', '\t', 'R', '\003', 'k', 'e', 'y', '\022', '2', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\001', '(', '\013', '2', '\034', '.', 
+'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'P', 'o', 'l', 'i', 
+'c', 'y', 'R', '\005', 'v', 'a', 'l', 'u', 'e', ':', '\002', '8', '\001', '\"', '&', '\n', '\006', 'A', 'c', 't', 'i', 'o', 'n', '\022', '\t', 
+'\n', '\005', 'A', 'L', 'L', 'O', 'W', '\020', '\000', '\022', '\010', '\n', '\004', 'D', 'E', 'N', 'Y', '\020', '\001', '\022', '\007', '\n', '\003', 'L', 'O', 
+'G', '\020', '\002', ':', ' ', '\232', '\305', '\210', '\036', '\033', '\n', '\031', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 
+'r', 'b', 'a', 'c', '.', 'v', '2', '.', 'R', 'B', 'A', 'C', '\"', '\223', '\003', '\n', '\006', 'P', 'o', 'l', 'i', 'c', 'y', '\022', 'L', 
+'\n', '\013', 'p', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 's', '\030', '\001', ' ', '\003', '(', '\013', '2', ' ', '.', 'e', 'n', 'v', 
+'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'P', 'e', 'r', 'm', 'i', 's', 's', 
+'i', 'o', 'n', 'B', '\010', '\372', 'B', '\005', '\222', '\001', '\002', '\010', '\001', 'R', '\013', 'p', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 
+'s', '\022', 'I', '\n', '\n', 'p', 'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', 's', '\030', '\002', ' ', '\003', '(', '\013', '2', '\037', '.', 'e', 
+'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'P', 'r', 'i', 'n', 'c', 
+'i', 'p', 'a', 'l', 'B', '\010', '\372', 'B', '\005', '\222', '\001', '\002', '\010', '\001', 'R', '\n', 'p', 'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', 
+'s', '\022', 'Z', '\n', '\t', 'c', 'o', 'n', 'd', 'i', 't', 'i', 'o', 'n', '\030', '\003', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 
+'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'E', 'x', 
+'p', 'r', 'B', '\034', '\362', '\230', '\376', '\217', '\005', '\026', '\022', '\024', 'e', 'x', 'p', 'r', 'e', 's', 's', 'i', 'o', 'n', '_', 's', 'p', 
+'e', 'c', 'i', 'f', 'i', 'e', 'r', 'R', '\t', 'c', 'o', 'n', 'd', 'i', 't', 'i', 'o', 'n', '\022', 'p', '\n', '\021', 'c', 'h', 'e', 
+'c', 'k', 'e', 'd', '_', 'c', 'o', 'n', 'd', 'i', 't', 'i', 'o', 'n', '\030', '\004', ' ', '\001', '(', '\013', '2', '%', '.', 'g', 'o', 
+'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'C', 'h', 
+'e', 'c', 'k', 'e', 'd', 'E', 'x', 'p', 'r', 'B', '\034', '\362', '\230', '\376', '\217', '\005', '\026', '\022', '\024', 'e', 'x', 'p', 'r', 'e', 's', 
+'s', 'i', 'o', 'n', '_', 's', 'p', 'e', 'c', 'i', 'f', 'i', 'e', 'r', 'R', '\020', 'c', 'h', 'e', 'c', 'k', 'e', 'd', 'C', 'o', 
+'n', 'd', 'i', 't', 'i', 'o', 'n', ':', '\"', '\232', '\305', '\210', '\036', '\035', '\n', '\033', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 
+'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '2', '.', 'P', 'o', 'l', 'i', 'c', 'y', '\"', '\332', '\007', '\n', '\n', 'P', 'e', 
+'r', 'm', 'i', 's', 's', 'i', 'o', 'n', '\022', 'C', '\n', '\t', 'a', 'n', 'd', '_', 'r', 'u', 'l', 'e', 's', '\030', '\001', ' ', '\001', 
+'(', '\013', '2', '$', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', 
+'.', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', '.', 'S', 'e', 't', 'H', '\000', 'R', '\010', 'a', 'n', 'd', 'R', 'u', 'l', 
+'e', 's', '\022', 'A', '\n', '\010', 'o', 'r', '_', 'r', 'u', 'l', 'e', 's', '\030', '\002', ' ', '\001', '(', '\013', '2', '$', '.', 'e', 'n', 
+'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'P', 'e', 'r', 'm', 'i', 's', 
+'s', 'i', 'o', 'n', '.', 'S', 'e', 't', 'H', '\000', 'R', '\007', 'o', 'r', 'R', 'u', 'l', 'e', 's', '\022', '\033', '\n', '\003', 'a', 'n', 
+'y', '\030', '\003', ' ', '\001', '(', '\010', 'B', '\007', '\372', 'B', '\004', 'j', '\002', '\010', '\001', 'H', '\000', 'R', '\003', 'a', 'n', 'y', '\022', '>', 
+'\n', '\006', 'h', 'e', 'a', 'd', 'e', 'r', '\030', '\004', ' ', '\001', '(', '\013', '2', '$', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 
+'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', '.', 'H', 'e', 'a', 'd', 'e', 'r', 'M', 'a', 't', 'c', 'h', 
+'e', 'r', 'H', '\000', 'R', '\006', 'h', 'e', 'a', 'd', 'e', 'r', '\022', '?', '\n', '\010', 'u', 'r', 'l', '_', 'p', 'a', 't', 'h', '\030', 
+'\n', ' ', '\001', '(', '\013', '2', '\"', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'a', 't', 'c', 'h', 'e', 
+'r', '.', 'v', '3', '.', 'P', 'a', 't', 'h', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'H', '\000', 'R', '\007', 'u', 'r', 'l', 'P', 'a', 
+'t', 'h', '\022', 'H', '\n', '\016', 'd', 'e', 's', 't', 'i', 'n', 'a', 't', 'i', 'o', 'n', '_', 'i', 'p', '\030', '\005', ' ', '\001', '(', 
+'\013', '2', '\037', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 
+'C', 'i', 'd', 'r', 'R', 'a', 'n', 'g', 'e', 'H', '\000', 'R', '\r', 'd', 'e', 's', 't', 'i', 'n', 'a', 't', 'i', 'o', 'n', 'I', 
+'p', '\022', '6', '\n', '\020', 'd', 'e', 's', 't', 'i', 'n', 'a', 't', 'i', 'o', 'n', '_', 'p', 'o', 'r', 't', '\030', '\006', ' ', '\001', 
+'(', '\r', 'B', '\t', '\372', 'B', '\006', '*', '\004', '\030', '\377', '\377', '\003', 'H', '\000', 'R', '\017', 'd', 'e', 's', 't', 'i', 'n', 'a', 't', 
+'i', 'o', 'n', 'P', 'o', 'r', 't', '\022', 'Q', '\n', '\026', 'd', 'e', 's', 't', 'i', 'n', 'a', 't', 'i', 'o', 'n', '_', 'p', 'o', 
+'r', 't', '_', 'r', 'a', 'n', 'g', 'e', '\030', '\013', ' ', '\001', '(', '\013', '2', '\031', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 
+'p', 'e', '.', 'v', '3', '.', 'I', 'n', 't', '3', '2', 'R', 'a', 'n', 'g', 'e', 'H', '\000', 'R', '\024', 'd', 'e', 's', 't', 'i', 
+'n', 'a', 't', 'i', 'o', 'n', 'P', 'o', 'r', 't', 'R', 'a', 'n', 'g', 'e', '\022', 'D', '\n', '\010', 'm', 'e', 't', 'a', 'd', 'a', 
+'t', 'a', '\030', '\007', ' ', '\001', '(', '\013', '2', '&', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'a', 't', 
+'c', 'h', 'e', 'r', '.', 'v', '3', '.', 'M', 'e', 't', 'a', 'd', 'a', 't', 'a', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'H', '\000', 
+'R', '\010', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', '\022', '=', '\n', '\010', 'n', 'o', 't', '_', 'r', 'u', 'l', 'e', '\030', '\010', ' ', 
+'\001', '(', '\013', '2', ' ', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', 
+'3', '.', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'H', '\000', 'R', '\007', 'n', 'o', 't', 'R', 'u', 'l', 'e', '\022', 'Z', 
+'\n', '\025', 'r', 'e', 'q', 'u', 'e', 's', 't', 'e', 'd', '_', 's', 'e', 'r', 'v', 'e', 'r', '_', 'n', 'a', 'm', 'e', '\030', '\t', 
+' ', '\001', '(', '\013', '2', '$', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'a', 't', 'c', 'h', 'e', 'r', 
+'.', 'v', '3', '.', 'S', 't', 'r', 'i', 'n', 'g', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'H', '\000', 'R', '\023', 'r', 'e', 'q', 'u', 
+'e', 's', 't', 'e', 'd', 'S', 'e', 'r', 'v', 'e', 'r', 'N', 'a', 'm', 'e', '\022', 'F', '\n', '\007', 'm', 'a', 't', 'c', 'h', 'e', 
+'r', '\030', '\014', ' ', '\001', '(', '\013', '2', '*', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 
+'r', 'e', '.', 'v', '3', '.', 'T', 'y', 'p', 'e', 'd', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'C', 'o', 'n', 'f', 'i', 
+'g', 'H', '\000', 'R', '\007', 'm', 'a', 't', 'c', 'h', 'e', 'r', '\032', 's', '\n', '\003', 'S', 'e', 't', '\022', '@', '\n', '\005', 'r', 'u', 
+'l', 'e', 's', '\030', '\001', ' ', '\003', '(', '\013', '2', ' ', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 
+'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'B', '\010', '\372', 'B', '\005', '\222', '\001', 
+'\002', '\010', '\001', 'R', '\005', 'r', 'u', 'l', 'e', 's', ':', '*', '\232', '\305', '\210', '\036', '%', '\n', '#', 'e', 'n', 'v', 'o', 'y', '.', 
+'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '2', '.', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 
+'.', 'S', 'e', 't', ':', '&', '\232', '\305', '\210', '\036', '!', '\n', '\037', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', 
+'.', 'r', 'b', 'a', 'c', '.', 'v', '2', '.', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'B', '\013', '\n', '\004', 'r', 'u', 
+'l', 'e', '\022', '\003', '\370', 'B', '\001', '\"', '\233', '\010', '\n', '\t', 'P', 'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', '\022', '>', '\n', '\007', 
+'a', 'n', 'd', '_', 'i', 'd', 's', '\030', '\001', ' ', '\001', '(', '\013', '2', '#', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 
+'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'P', 'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', '.', 'S', 'e', 't', 
+'H', '\000', 'R', '\006', 'a', 'n', 'd', 'I', 'd', 's', '\022', '<', '\n', '\006', 'o', 'r', '_', 'i', 'd', 's', '\030', '\002', ' ', '\001', '(', 
+'\013', '2', '#', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 
+'P', 'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', '.', 'S', 'e', 't', 'H', '\000', 'R', '\005', 'o', 'r', 'I', 'd', 's', '\022', '\033', '\n', 
+'\003', 'a', 'n', 'y', '\030', '\003', ' ', '\001', '(', '\010', 'B', '\007', '\372', 'B', '\004', 'j', '\002', '\010', '\001', 'H', '\000', 'R', '\003', 'a', 'n', 
+'y', '\022', 'U', '\n', '\r', 'a', 'u', 't', 'h', 'e', 'n', 't', 'i', 'c', 'a', 't', 'e', 'd', '\030', '\004', ' ', '\001', '(', '\013', '2', 
+'-', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'P', 'r', 
+'i', 'n', 'c', 'i', 'p', 'a', 'l', '.', 'A', 'u', 't', 'h', 'e', 'n', 't', 'i', 'c', 'a', 't', 'e', 'd', 'H', '\000', 'R', '\r', 
+'a', 'u', 't', 'h', 'e', 'n', 't', 'i', 'c', 'a', 't', 'e', 'd', '\022', 'K', '\n', '\t', 's', 'o', 'u', 'r', 'c', 'e', '_', 'i', 
+'p', '\030', '\005', ' ', '\001', '(', '\013', '2', '\037', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 
+'r', 'e', '.', 'v', '3', '.', 'C', 'i', 'd', 'r', 'R', 'a', 'n', 'g', 'e', 'B', '\013', '\030', '\001', '\222', '\307', '\206', '\330', '\004', '\003', 
+'3', '.', '0', 'H', '\000', 'R', '\010', 's', 'o', 'u', 'r', 'c', 'e', 'I', 'p', '\022', 'K', '\n', '\020', 'd', 'i', 'r', 'e', 'c', 't', 
+'_', 'r', 'e', 'm', 'o', 't', 'e', '_', 'i', 'p', '\030', '\n', ' ', '\001', '(', '\013', '2', '\037', '.', 'e', 'n', 'v', 'o', 'y', '.', 
+'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'C', 'i', 'd', 'r', 'R', 'a', 'n', 'g', 'e', 'H', 
+'\000', 'R', '\016', 'd', 'i', 'r', 'e', 'c', 't', 'R', 'e', 'm', 'o', 't', 'e', 'I', 'p', '\022', '>', '\n', '\t', 'r', 'e', 'm', 'o', 
+'t', 'e', '_', 'i', 'p', '\030', '\013', ' ', '\001', '(', '\013', '2', '\037', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 
+'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'C', 'i', 'd', 'r', 'R', 'a', 'n', 'g', 'e', 'H', '\000', 'R', '\010', 'r', 'e', 
+'m', 'o', 't', 'e', 'I', 'p', '\022', '>', '\n', '\006', 'h', 'e', 'a', 'd', 'e', 'r', '\030', '\006', ' ', '\001', '(', '\013', '2', '$', '.', 
+'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', '.', 'H', 'e', 'a', 
+'d', 'e', 'r', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'H', '\000', 'R', '\006', 'h', 'e', 'a', 'd', 'e', 'r', '\022', '?', '\n', '\010', 'u', 
+'r', 'l', '_', 'p', 'a', 't', 'h', '\030', '\t', ' ', '\001', '(', '\013', '2', '\"', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 
+'e', '.', 'm', 'a', 't', 'c', 'h', 'e', 'r', '.', 'v', '3', '.', 'P', 'a', 't', 'h', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'H', 
+'\000', 'R', '\007', 'u', 'r', 'l', 'P', 'a', 't', 'h', '\022', 'D', '\n', '\010', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', '\030', '\007', ' ', 
+'\001', '(', '\013', '2', '&', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'a', 't', 'c', 'h', 'e', 'r', '.', 
+'v', '3', '.', 'M', 'e', 't', 'a', 'd', 'a', 't', 'a', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'H', '\000', 'R', '\010', 'm', 'e', 't', 
+'a', 'd', 'a', 't', 'a', '\022', '8', '\n', '\006', 'n', 'o', 't', '_', 'i', 'd', '\030', '\010', ' ', '\001', '(', '\013', '2', '\037', '.', 'e', 
+'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'P', 'r', 'i', 'n', 'c', 
+'i', 'p', 'a', 'l', 'H', '\000', 'R', '\005', 'n', 'o', 't', 'I', 'd', '\032', 'm', '\n', '\003', 'S', 'e', 't', '\022', ';', '\n', '\003', 'i', 
+'d', 's', '\030', '\001', ' ', '\003', '(', '\013', '2', '\037', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 
 'b', 'a', 'c', '.', 'v', '3', '.', 'P', 'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', 'B', '\010', '\372', 'B', '\005', '\222', '\001', '\002', '\010', 
-'\001', 'R', '\n', 'p', 'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', 's', '\022', 'Z', '\n', '\t', 'c', 'o', 'n', 'd', 'i', 't', 'i', 'o', 
-'n', '\030', '\003', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', 
-'.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'E', 'x', 'p', 'r', 'B', '\034', '\362', '\230', '\376', '\217', '\005', '\026', '\022', '\024', 'e', 
-'x', 'p', 'r', 'e', 's', 's', 'i', 'o', 'n', '_', 's', 'p', 'e', 'c', 'i', 'f', 'i', 'e', 'r', 'R', '\t', 'c', 'o', 'n', 'd', 
-'i', 't', 'i', 'o', 'n', '\022', 'p', '\n', '\021', 'c', 'h', 'e', 'c', 'k', 'e', 'd', '_', 'c', 'o', 'n', 'd', 'i', 't', 'i', 'o', 
-'n', '\030', '\004', ' ', '\001', '(', '\013', '2', '%', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', 
-'.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'C', 'h', 'e', 'c', 'k', 'e', 'd', 'E', 'x', 'p', 'r', 'B', '\034', '\362', '\230', 
-'\376', '\217', '\005', '\026', '\022', '\024', 'e', 'x', 'p', 'r', 'e', 's', 's', 'i', 'o', 'n', '_', 's', 'p', 'e', 'c', 'i', 'f', 'i', 'e', 
-'r', 'R', '\020', 'c', 'h', 'e', 'c', 'k', 'e', 'd', 'C', 'o', 'n', 'd', 'i', 't', 'i', 'o', 'n', ':', '\"', '\232', '\305', '\210', '\036', 
-'\035', '\n', '\033', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '2', '.', 'P', 
-'o', 'l', 'i', 'c', 'y', '\"', '\222', '\007', '\n', '\n', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', '\022', 'C', '\n', '\t', 'a', 
-'n', 'd', '_', 'r', 'u', 'l', 'e', 's', '\030', '\001', ' ', '\001', '(', '\013', '2', '$', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 
-'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', '.', 'S', 
-'e', 't', 'H', '\000', 'R', '\010', 'a', 'n', 'd', 'R', 'u', 'l', 'e', 's', '\022', 'A', '\n', '\010', 'o', 'r', '_', 'r', 'u', 'l', 'e', 
-'s', '\030', '\002', ' ', '\001', '(', '\013', '2', '$', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 
-'a', 'c', '.', 'v', '3', '.', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', '.', 'S', 'e', 't', 'H', '\000', 'R', '\007', 'o', 
-'r', 'R', 'u', 'l', 'e', 's', '\022', '\033', '\n', '\003', 'a', 'n', 'y', '\030', '\003', ' ', '\001', '(', '\010', 'B', '\007', '\372', 'B', '\004', 'j', 
-'\002', '\010', '\001', 'H', '\000', 'R', '\003', 'a', 'n', 'y', '\022', '>', '\n', '\006', 'h', 'e', 'a', 'd', 'e', 'r', '\030', '\004', ' ', '\001', '(', 
-'\013', '2', '$', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', 
-'.', 'H', 'e', 'a', 'd', 'e', 'r', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'H', '\000', 'R', '\006', 'h', 'e', 'a', 'd', 'e', 'r', '\022', 
-'?', '\n', '\010', 'u', 'r', 'l', '_', 'p', 'a', 't', 'h', '\030', '\n', ' ', '\001', '(', '\013', '2', '\"', '.', 'e', 'n', 'v', 'o', 'y', 
-'.', 't', 'y', 'p', 'e', '.', 'm', 'a', 't', 'c', 'h', 'e', 'r', '.', 'v', '3', '.', 'P', 'a', 't', 'h', 'M', 'a', 't', 'c', 
-'h', 'e', 'r', 'H', '\000', 'R', '\007', 'u', 'r', 'l', 'P', 'a', 't', 'h', '\022', 'H', '\n', '\016', 'd', 'e', 's', 't', 'i', 'n', 'a', 
-'t', 'i', 'o', 'n', '_', 'i', 'p', '\030', '\005', ' ', '\001', '(', '\013', '2', '\037', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 
-'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'C', 'i', 'd', 'r', 'R', 'a', 'n', 'g', 'e', 'H', '\000', 'R', '\r', 
-'d', 'e', 's', 't', 'i', 'n', 'a', 't', 'i', 'o', 'n', 'I', 'p', '\022', '6', '\n', '\020', 'd', 'e', 's', 't', 'i', 'n', 'a', 't', 
-'i', 'o', 'n', '_', 'p', 'o', 'r', 't', '\030', '\006', ' ', '\001', '(', '\r', 'B', '\t', '\372', 'B', '\006', '*', '\004', '\030', '\377', '\377', '\003', 
-'H', '\000', 'R', '\017', 'd', 'e', 's', 't', 'i', 'n', 'a', 't', 'i', 'o', 'n', 'P', 'o', 'r', 't', '\022', 'Q', '\n', '\026', 'd', 'e', 
-'s', 't', 'i', 'n', 'a', 't', 'i', 'o', 'n', '_', 'p', 'o', 'r', 't', '_', 'r', 'a', 'n', 'g', 'e', '\030', '\013', ' ', '\001', '(', 
-'\013', '2', '\031', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'v', '3', '.', 'I', 'n', 't', '3', '2', 'R', 'a', 
-'n', 'g', 'e', 'H', '\000', 'R', '\024', 'd', 'e', 's', 't', 'i', 'n', 'a', 't', 'i', 'o', 'n', 'P', 'o', 'r', 't', 'R', 'a', 'n', 
-'g', 'e', '\022', 'D', '\n', '\010', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', '\030', '\007', ' ', '\001', '(', '\013', '2', '&', '.', 'e', 'n', 
-'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'a', 't', 'c', 'h', 'e', 'r', '.', 'v', '3', '.', 'M', 'e', 't', 'a', 'd', 
-'a', 't', 'a', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'H', '\000', 'R', '\010', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', '\022', '=', '\n', 
-'\010', 'n', 'o', 't', '_', 'r', 'u', 'l', 'e', '\030', '\010', ' ', '\001', '(', '\013', '2', ' ', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 
-'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'H', 
-'\000', 'R', '\007', 'n', 'o', 't', 'R', 'u', 'l', 'e', '\022', 'Z', '\n', '\025', 'r', 'e', 'q', 'u', 'e', 's', 't', 'e', 'd', '_', 's', 
-'e', 'r', 'v', 'e', 'r', '_', 'n', 'a', 'm', 'e', '\030', '\t', ' ', '\001', '(', '\013', '2', '$', '.', 'e', 'n', 'v', 'o', 'y', '.', 
+'\001', 'R', '\003', 'i', 'd', 's', ':', ')', '\232', '\305', '\210', '\036', '$', '\n', '\"', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 
+'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '2', '.', 'P', 'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', '.', 'S', 'e', 't', '\032', 
+'\227', '\001', '\n', '\r', 'A', 'u', 't', 'h', 'e', 'n', 't', 'i', 'c', 'a', 't', 'e', 'd', '\022', 'K', '\n', '\016', 'p', 'r', 'i', 'n', 
+'c', 'i', 'p', 'a', 'l', '_', 'n', 'a', 'm', 'e', '\030', '\002', ' ', '\001', '(', '\013', '2', '$', '.', 'e', 'n', 'v', 'o', 'y', '.', 
 't', 'y', 'p', 'e', '.', 'm', 'a', 't', 'c', 'h', 'e', 'r', '.', 'v', '3', '.', 'S', 't', 'r', 'i', 'n', 'g', 'M', 'a', 't', 
-'c', 'h', 'e', 'r', 'H', '\000', 'R', '\023', 'r', 'e', 'q', 'u', 'e', 's', 't', 'e', 'd', 'S', 'e', 'r', 'v', 'e', 'r', 'N', 'a', 
-'m', 'e', '\032', 's', '\n', '\003', 'S', 'e', 't', '\022', '@', '\n', '\005', 'r', 'u', 'l', 'e', 's', '\030', '\001', ' ', '\003', '(', '\013', '2', 
-' ', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'P', 'e', 
-'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'B', '\010', '\372', 'B', '\005', '\222', '\001', '\002', '\010', '\001', 'R', '\005', 'r', 'u', 'l', 'e', 's', 
-':', '*', '\232', '\305', '\210', '\036', '%', '\n', '#', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 
-'c', '.', 'v', '2', '.', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', '.', 'S', 'e', 't', ':', '&', '\232', '\305', '\210', '\036', 
-'!', '\n', '\037', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '2', '.', 'P', 
-'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'B', '\013', '\n', '\004', 'r', 'u', 'l', 'e', '\022', '\003', '\370', 'B', '\001', '\"', '\233', '\010', 
-'\n', '\t', 'P', 'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', '\022', '>', '\n', '\007', 'a', 'n', 'd', '_', 'i', 'd', 's', '\030', '\001', ' ', 
-'\001', '(', '\013', '2', '#', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', 
-'3', '.', 'P', 'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', '.', 'S', 'e', 't', 'H', '\000', 'R', '\006', 'a', 'n', 'd', 'I', 'd', 's', 
-'\022', '<', '\n', '\006', 'o', 'r', '_', 'i', 'd', 's', '\030', '\002', ' ', '\001', '(', '\013', '2', '#', '.', 'e', 'n', 'v', 'o', 'y', '.', 
-'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'P', 'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', '.', 
-'S', 'e', 't', 'H', '\000', 'R', '\005', 'o', 'r', 'I', 'd', 's', '\022', '\033', '\n', '\003', 'a', 'n', 'y', '\030', '\003', ' ', '\001', '(', '\010', 
-'B', '\007', '\372', 'B', '\004', 'j', '\002', '\010', '\001', 'H', '\000', 'R', '\003', 'a', 'n', 'y', '\022', 'U', '\n', '\r', 'a', 'u', 't', 'h', 'e', 
-'n', 't', 'i', 'c', 'a', 't', 'e', 'd', '\030', '\004', ' ', '\001', '(', '\013', '2', '-', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 
-'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'P', 'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', '.', 'A', 'u', 
-'t', 'h', 'e', 'n', 't', 'i', 'c', 'a', 't', 'e', 'd', 'H', '\000', 'R', '\r', 'a', 'u', 't', 'h', 'e', 'n', 't', 'i', 'c', 'a', 
-'t', 'e', 'd', '\022', 'K', '\n', '\t', 's', 'o', 'u', 'r', 'c', 'e', '_', 'i', 'p', '\030', '\005', ' ', '\001', '(', '\013', '2', '\037', '.', 
-'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'C', 'i', 'd', 'r', 
-'R', 'a', 'n', 'g', 'e', 'B', '\013', '\030', '\001', '\222', '\307', '\206', '\330', '\004', '\003', '3', '.', '0', 'H', '\000', 'R', '\010', 's', 'o', 'u', 
-'r', 'c', 'e', 'I', 'p', '\022', 'K', '\n', '\020', 'd', 'i', 'r', 'e', 'c', 't', '_', 'r', 'e', 'm', 'o', 't', 'e', '_', 'i', 'p', 
-'\030', '\n', ' ', '\001', '(', '\013', '2', '\037', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 
-'e', '.', 'v', '3', '.', 'C', 'i', 'd', 'r', 'R', 'a', 'n', 'g', 'e', 'H', '\000', 'R', '\016', 'd', 'i', 'r', 'e', 'c', 't', 'R', 
-'e', 'm', 'o', 't', 'e', 'I', 'p', '\022', '>', '\n', '\t', 'r', 'e', 'm', 'o', 't', 'e', '_', 'i', 'p', '\030', '\013', ' ', '\001', '(', 
-'\013', '2', '\037', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 
-'C', 'i', 'd', 'r', 'R', 'a', 'n', 'g', 'e', 'H', '\000', 'R', '\010', 'r', 'e', 'm', 'o', 't', 'e', 'I', 'p', '\022', '>', '\n', '\006', 
-'h', 'e', 'a', 'd', 'e', 'r', '\030', '\006', ' ', '\001', '(', '\013', '2', '$', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 
-'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', '.', 'H', 'e', 'a', 'd', 'e', 'r', 'M', 'a', 't', 'c', 'h', 'e', 'r', 
-'H', '\000', 'R', '\006', 'h', 'e', 'a', 'd', 'e', 'r', '\022', '?', '\n', '\010', 'u', 'r', 'l', '_', 'p', 'a', 't', 'h', '\030', '\t', ' ', 
-'\001', '(', '\013', '2', '\"', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'a', 't', 'c', 'h', 'e', 'r', '.', 
-'v', '3', '.', 'P', 'a', 't', 'h', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'H', '\000', 'R', '\007', 'u', 'r', 'l', 'P', 'a', 't', 'h', 
-'\022', 'D', '\n', '\010', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', '\030', '\007', ' ', '\001', '(', '\013', '2', '&', '.', 'e', 'n', 'v', 'o', 
-'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'a', 't', 'c', 'h', 'e', 'r', '.', 'v', '3', '.', 'M', 'e', 't', 'a', 'd', 'a', 't', 
-'a', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'H', '\000', 'R', '\010', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', '\022', '8', '\n', '\006', 'n', 
-'o', 't', '_', 'i', 'd', '\030', '\010', ' ', '\001', '(', '\013', '2', '\037', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 
-'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'P', 'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', 'H', '\000', 'R', '\005', 'n', 'o', 
-'t', 'I', 'd', '\032', 'm', '\n', '\003', 'S', 'e', 't', '\022', ';', '\n', '\003', 'i', 'd', 's', '\030', '\001', ' ', '\003', '(', '\013', '2', '\037', 
-'.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'P', 'r', 'i', 
-'n', 'c', 'i', 'p', 'a', 'l', 'B', '\010', '\372', 'B', '\005', '\222', '\001', '\002', '\010', '\001', 'R', '\003', 'i', 'd', 's', ':', ')', '\232', '\305', 
-'\210', '\036', '$', '\n', '\"', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '2', 
-'.', 'P', 'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', '.', 'S', 'e', 't', '\032', '\227', '\001', '\n', '\r', 'A', 'u', 't', 'h', 'e', 'n', 
-'t', 'i', 'c', 'a', 't', 'e', 'd', '\022', 'K', '\n', '\016', 'p', 'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', '_', 'n', 'a', 'm', 'e', 
-'\030', '\002', ' ', '\001', '(', '\013', '2', '$', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'a', 't', 'c', 'h', 
-'e', 'r', '.', 'v', '3', '.', 'S', 't', 'r', 'i', 'n', 'g', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'R', '\r', 'p', 'r', 'i', 'n', 
-'c', 'i', 'p', 'a', 'l', 'N', 'a', 'm', 'e', ':', '3', '\232', '\305', '\210', '\036', '.', '\n', ',', 'e', 'n', 'v', 'o', 'y', '.', 'c', 
-'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '2', '.', 'P', 'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', '.', 'A', 
-'u', 't', 'h', 'e', 'n', 't', 'i', 'c', 'a', 't', 'e', 'd', 'J', '\004', '\010', '\001', '\020', '\002', ':', '%', '\232', '\305', '\210', '\036', ' ', 
-'\n', '\036', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '2', '.', 'P', 'r', 
-'i', 'n', 'c', 'i', 'p', 'a', 'l', 'B', '\021', '\n', '\n', 'i', 'd', 'e', 'n', 't', 'i', 'f', 'i', 'e', 'r', '\022', '\003', '\370', 'B', 
-'\001', 'B', '9', '\n', '\"', 'i', 'o', '.', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '.', 'e', 'n', 'v', 'o', 'y', '.', 
-'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', 'B', '\t', 'R', 'b', 'a', 'c', 'P', 'r', 'o', 't', 'o', 
-'P', '\001', '\272', '\200', '\310', '\321', '\006', '\002', '\020', '\002', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', 
+'c', 'h', 'e', 'r', 'R', '\r', 'p', 'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', 'N', 'a', 'm', 'e', ':', '3', '\232', '\305', '\210', '\036', 
+'.', '\n', ',', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '2', '.', 'P', 
+'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', '.', 'A', 'u', 't', 'h', 'e', 'n', 't', 'i', 'c', 'a', 't', 'e', 'd', 'J', '\004', '\010', 
+'\001', '\020', '\002', ':', '%', '\232', '\305', '\210', '\036', ' ', '\n', '\036', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 
+'r', 'b', 'a', 'c', '.', 'v', '2', '.', 'P', 'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', 'B', '\021', '\n', '\n', 'i', 'd', 'e', 'n', 
+'t', 'i', 'f', 'i', 'e', 'r', '\022', '\003', '\370', 'B', '\001', 'B', '9', '\n', '\"', 'i', 'o', '.', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 
+'o', 'x', 'y', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', 'B', 
+'\t', 'R', 'b', 'a', 'c', 'P', 'r', 'o', 't', 'o', 'P', '\001', '\272', '\200', '\310', '\321', '\006', '\002', '\020', '\002', 'b', '\006', 'p', 'r', 'o', 
+'t', 'o', '3', 
 };
 
-static upb_def_init *deps[14] = {
+static upb_def_init *deps[15] = {
   &envoy_config_core_v3_address_proto_upbdefinit,
+  &envoy_config_core_v3_extension_proto_upbdefinit,
   &envoy_config_route_v3_route_components_proto_upbdefinit,
   &envoy_type_matcher_v3_metadata_proto_upbdefinit,
   &envoy_type_matcher_v3_path_proto_upbdefinit,
@@ -196,5 +203,5 @@ upb_def_init envoy_config_rbac_v3_rbac_proto_upbdefinit = {
   deps,
   layouts,
   "envoy/config/rbac/v3/rbac.proto",
-  UPB_STRVIEW_INIT(descriptor, 3268)
+  UPB_STRVIEW_INIT(descriptor, 3378)
 };
index 8b1559d..12a35e5 100644 (file)
@@ -137,7 +137,7 @@ static const upb_msglayout *layouts[53] = {
   &envoy_config_route_v3_FilterConfig_msginit,
 };
 
-static const char descriptor[20140] = {'\n', ',', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'r', 'o', 'u', 't', 'e', '/', 'v', '3', '/', 'r', 
+static const char descriptor[20318] = {'\n', ',', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'r', 'o', 'u', 't', 'e', '/', 'v', '3', '/', 'r', 
 'o', 'u', 't', 'e', '_', 'c', 'o', 'm', 'p', 'o', 'n', 'e', 'n', 't', 's', '.', 'p', 'r', 'o', 't', 'o', '\022', '\025', 'e', 'n', 
 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', '\032', '\037', 'e', 'n', 'v', 'o', 
 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '/', 'b', 'a', 's', 'e', '.', 'p', 'r', 'o', 
@@ -616,7 +616,7 @@ static const char descriptor[20140] = {'\n', ',', 'e', 'n', 'v', 'o', 'y', '/',
 'r', '\022', '\003', '\370', 'B', '\001', 'B', '\030', '\n', '\026', 'h', 'o', 's', 't', '_', 'r', 'e', 'w', 'r', 'i', 't', 'e', '_', 's', 'p', 
 'e', 'c', 'i', 'f', 'i', 'e', 'r', 'J', '\004', '\010', '\014', '\020', '\r', 'J', '\004', '\010', '\022', '\020', '\023', 'J', '\004', '\010', '\023', '\020', '\024', 
 'J', '\004', '\010', '\020', '\020', '\021', 'J', '\004', '\010', '\026', '\020', '\027', 'J', '\004', '\010', '\025', '\020', '\026', 'J', '\004', '\010', '\n', '\020', '\013', 'R', 
-'\025', 'r', 'e', 'q', 'u', 'e', 's', 't', '_', 'm', 'i', 'r', 'r', 'o', 'r', '_', 'p', 'o', 'l', 'i', 'c', 'y', '\"', '\215', '\017', 
+'\025', 'r', 'e', 'q', 'u', 'e', 's', 't', '_', 'm', 'i', 'r', 'r', 'o', 'r', '_', 'p', 'o', 'l', 'i', 'c', 'y', '\"', '\277', '\020', 
 '\n', '\013', 'R', 'e', 't', 'r', 'y', 'P', 'o', 'l', 'i', 'c', 'y', '\022', '\031', '\n', '\010', 'r', 'e', 't', 'r', 'y', '_', 'o', 'n', 
 '\030', '\001', ' ', '\001', '(', '\t', 'R', '\007', 'r', 'e', 't', 'r', 'y', 'O', 'n', '\022', 'R', '\n', '\013', 'n', 'u', 'm', '_', 'r', 'e', 
 't', 'r', 'i', 'e', 's', '\030', '\002', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 
@@ -624,325 +624,332 @@ static const char descriptor[20140] = {'\n', ',', 'e', 'n', 'v', 'o', 'y', '/',
 '\013', 'm', 'a', 'x', '_', 'r', 'e', 't', 'r', 'i', 'e', 's', 'R', '\n', 'n', 'u', 'm', 'R', 'e', 't', 'r', 'i', 'e', 's', '\022', 
 'A', '\n', '\017', 'p', 'e', 'r', '_', 't', 'r', 'y', '_', 't', 'i', 'm', 'e', 'o', 'u', 't', '\030', '\003', ' ', '\001', '(', '\013', '2', 
 '\031', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'u', 'r', 'a', 't', 'i', 'o', 
-'n', 'R', '\r', 'p', 'e', 'r', 'T', 'r', 'y', 'T', 'i', 'm', 'e', 'o', 'u', 't', '\022', 'W', '\n', '\016', 'r', 'e', 't', 'r', 'y', 
-'_', 'p', 'r', 'i', 'o', 'r', 'i', 't', 'y', '\030', '\004', ' ', '\001', '(', '\013', '2', '0', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 
+'n', 'R', '\r', 'p', 'e', 'r', 'T', 'r', 'y', 'T', 'i', 'm', 'e', 'o', 'u', 't', '\022', 'J', '\n', '\024', 'p', 'e', 'r', '_', 't', 
+'r', 'y', '_', 'i', 'd', 'l', 'e', '_', 't', 'i', 'm', 'e', 'o', 'u', 't', '\030', '\r', ' ', '\001', '(', '\013', '2', '\031', '.', 'g', 
+'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'u', 'r', 'a', 't', 'i', 'o', 'n', 'R', '\021', 
+'p', 'e', 'r', 'T', 'r', 'y', 'I', 'd', 'l', 'e', 'T', 'i', 'm', 'e', 'o', 'u', 't', '\022', 'W', '\n', '\016', 'r', 'e', 't', 'r', 
+'y', '_', 'p', 'r', 'i', 'o', 'r', 'i', 't', 'y', '\030', '\004', ' ', '\001', '(', '\013', '2', '0', '.', 'e', 'n', 'v', 'o', 'y', '.', 
+'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', '.', 'R', 'e', 't', 'r', 'y', 'P', 'o', 'l', 'i', 
+'c', 'y', '.', 'R', 'e', 't', 'r', 'y', 'P', 'r', 'i', 'o', 'r', 'i', 't', 'y', 'R', '\r', 'r', 'e', 't', 'r', 'y', 'P', 'r', 
+'i', 'o', 'r', 'i', 't', 'y', '\022', 'g', '\n', '\024', 'r', 'e', 't', 'r', 'y', '_', 'h', 'o', 's', 't', '_', 'p', 'r', 'e', 'd', 
+'i', 'c', 'a', 't', 'e', '\030', '\005', ' ', '\003', '(', '\013', '2', '5', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 
+'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', '.', 'R', 'e', 't', 'r', 'y', 'P', 'o', 'l', 'i', 'c', 'y', '.', 'R', 'e', 
+'t', 'r', 'y', 'H', 'o', 's', 't', 'P', 'r', 'e', 'd', 'i', 'c', 'a', 't', 'e', 'R', '\022', 'r', 'e', 't', 'r', 'y', 'H', 'o', 
+'s', 't', 'P', 'r', 'e', 'd', 'i', 'c', 'a', 't', 'e', '\022', 'd', '\n', '\030', 'r', 'e', 't', 'r', 'y', '_', 'o', 'p', 't', 'i', 
+'o', 'n', 's', '_', 'p', 'r', 'e', 'd', 'i', 'c', 'a', 't', 'e', 's', '\030', '\014', ' ', '\003', '(', '\013', '2', '*', '.', 'e', 'n', 
+'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'T', 'y', 'p', 'e', 'd', 'E', 
+'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'C', 'o', 'n', 'f', 'i', 'g', 'R', '\026', 'r', 'e', 't', 'r', 'y', 'O', 'p', 't', 'i', 
+'o', 'n', 's', 'P', 'r', 'e', 'd', 'i', 'c', 'a', 't', 'e', 's', '\022', 'H', '\n', '!', 'h', 'o', 's', 't', '_', 's', 'e', 'l', 
+'e', 'c', 't', 'i', 'o', 'n', '_', 'r', 'e', 't', 'r', 'y', '_', 'm', 'a', 'x', '_', 'a', 't', 't', 'e', 'm', 'p', 't', 's', 
+'\030', '\006', ' ', '\001', '(', '\003', 'R', '\035', 'h', 'o', 's', 't', 'S', 'e', 'l', 'e', 'c', 't', 'i', 'o', 'n', 'R', 'e', 't', 'r', 
+'y', 'M', 'a', 'x', 'A', 't', 't', 'e', 'm', 'p', 't', 's', '\022', '4', '\n', '\026', 'r', 'e', 't', 'r', 'i', 'a', 'b', 'l', 'e', 
+'_', 's', 't', 'a', 't', 'u', 's', '_', 'c', 'o', 'd', 'e', 's', '\030', '\007', ' ', '\003', '(', '\r', 'R', '\024', 'r', 'e', 't', 'r', 
+'i', 'a', 'b', 'l', 'e', 'S', 't', 'a', 't', 'u', 's', 'C', 'o', 'd', 'e', 's', '\022', 'U', '\n', '\016', 'r', 'e', 't', 'r', 'y', 
+'_', 'b', 'a', 'c', 'k', '_', 'o', 'f', 'f', '\030', '\010', ' ', '\001', '(', '\013', '2', '/', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 
 'o', 'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', '.', 'R', 'e', 't', 'r', 'y', 'P', 'o', 'l', 'i', 'c', 
-'y', '.', 'R', 'e', 't', 'r', 'y', 'P', 'r', 'i', 'o', 'r', 'i', 't', 'y', 'R', '\r', 'r', 'e', 't', 'r', 'y', 'P', 'r', 'i', 
-'o', 'r', 'i', 't', 'y', '\022', 'g', '\n', '\024', 'r', 'e', 't', 'r', 'y', '_', 'h', 'o', 's', 't', '_', 'p', 'r', 'e', 'd', 'i', 
-'c', 'a', 't', 'e', '\030', '\005', ' ', '\003', '(', '\013', '2', '5', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', 
-'.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', '.', 'R', 'e', 't', 'r', 'y', 'P', 'o', 'l', 'i', 'c', 'y', '.', 'R', 'e', 't', 
-'r', 'y', 'H', 'o', 's', 't', 'P', 'r', 'e', 'd', 'i', 'c', 'a', 't', 'e', 'R', '\022', 'r', 'e', 't', 'r', 'y', 'H', 'o', 's', 
-'t', 'P', 'r', 'e', 'd', 'i', 'c', 'a', 't', 'e', '\022', 'H', '\n', '!', 'h', 'o', 's', 't', '_', 's', 'e', 'l', 'e', 'c', 't', 
-'i', 'o', 'n', '_', 'r', 'e', 't', 'r', 'y', '_', 'm', 'a', 'x', '_', 'a', 't', 't', 'e', 'm', 'p', 't', 's', '\030', '\006', ' ', 
-'\001', '(', '\003', 'R', '\035', 'h', 'o', 's', 't', 'S', 'e', 'l', 'e', 'c', 't', 'i', 'o', 'n', 'R', 'e', 't', 'r', 'y', 'M', 'a', 
-'x', 'A', 't', 't', 'e', 'm', 'p', 't', 's', '\022', '4', '\n', '\026', 'r', 'e', 't', 'r', 'i', 'a', 'b', 'l', 'e', '_', 's', 't', 
-'a', 't', 'u', 's', '_', 'c', 'o', 'd', 'e', 's', '\030', '\007', ' ', '\003', '(', '\r', 'R', '\024', 'r', 'e', 't', 'r', 'i', 'a', 'b', 
-'l', 'e', 'S', 't', 'a', 't', 'u', 's', 'C', 'o', 'd', 'e', 's', '\022', 'U', '\n', '\016', 'r', 'e', 't', 'r', 'y', '_', 'b', 'a', 
-'c', 'k', '_', 'o', 'f', 'f', '\030', '\010', ' ', '\001', '(', '\013', '2', '/', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 
-'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', '.', 'R', 'e', 't', 'r', 'y', 'P', 'o', 'l', 'i', 'c', 'y', '.', 'R', 
-'e', 't', 'r', 'y', 'B', 'a', 'c', 'k', 'O', 'f', 'f', 'R', '\014', 'r', 'e', 't', 'r', 'y', 'B', 'a', 'c', 'k', 'O', 'f', 'f', 
-'\022', 'x', '\n', '\033', 'r', 'a', 't', 'e', '_', 'l', 'i', 'm', 'i', 't', 'e', 'd', '_', 'r', 'e', 't', 'r', 'y', '_', 'b', 'a', 
-'c', 'k', '_', 'o', 'f', 'f', '\030', '\013', ' ', '\001', '(', '\013', '2', ':', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 
-'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', '.', 'R', 'e', 't', 'r', 'y', 'P', 'o', 'l', 'i', 'c', 'y', '.', 'R', 
-'a', 't', 'e', 'L', 'i', 'm', 'i', 't', 'e', 'd', 'R', 'e', 't', 'r', 'y', 'B', 'a', 'c', 'k', 'O', 'f', 'f', 'R', '\027', 'r', 
-'a', 't', 'e', 'L', 'i', 'm', 'i', 't', 'e', 'd', 'R', 'e', 't', 'r', 'y', 'B', 'a', 'c', 'k', 'O', 'f', 'f', '\022', 'Q', '\n', 
-'\021', 'r', 'e', 't', 'r', 'i', 'a', 'b', 'l', 'e', '_', 'h', 'e', 'a', 'd', 'e', 'r', 's', '\030', '\t', ' ', '\003', '(', '\013', '2', 
+'y', '.', 'R', 'e', 't', 'r', 'y', 'B', 'a', 'c', 'k', 'O', 'f', 'f', 'R', '\014', 'r', 'e', 't', 'r', 'y', 'B', 'a', 'c', 'k', 
+'O', 'f', 'f', '\022', 'x', '\n', '\033', 'r', 'a', 't', 'e', '_', 'l', 'i', 'm', 'i', 't', 'e', 'd', '_', 'r', 'e', 't', 'r', 'y', 
+'_', 'b', 'a', 'c', 'k', '_', 'o', 'f', 'f', '\030', '\013', ' ', '\001', '(', '\013', '2', ':', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 
+'o', 'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', '.', 'R', 'e', 't', 'r', 'y', 'P', 'o', 'l', 'i', 'c', 
+'y', '.', 'R', 'a', 't', 'e', 'L', 'i', 'm', 'i', 't', 'e', 'd', 'R', 'e', 't', 'r', 'y', 'B', 'a', 'c', 'k', 'O', 'f', 'f', 
+'R', '\027', 'r', 'a', 't', 'e', 'L', 'i', 'm', 'i', 't', 'e', 'd', 'R', 'e', 't', 'r', 'y', 'B', 'a', 'c', 'k', 'O', 'f', 'f', 
+'\022', 'Q', '\n', '\021', 'r', 'e', 't', 'r', 'i', 'a', 'b', 'l', 'e', '_', 'h', 'e', 'a', 'd', 'e', 'r', 's', '\030', '\t', ' ', '\003', 
+'(', '\013', '2', '$', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', 
+'3', '.', 'H', 'e', 'a', 'd', 'e', 'r', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'R', '\020', 'r', 'e', 't', 'r', 'i', 'a', 'b', 'l', 
+'e', 'H', 'e', 'a', 'd', 'e', 'r', 's', '\022', '`', '\n', '\031', 'r', 'e', 't', 'r', 'i', 'a', 'b', 'l', 'e', '_', 'r', 'e', 'q', 
+'u', 'e', 's', 't', '_', 'h', 'e', 'a', 'd', 'e', 'r', 's', '\030', '\n', ' ', '\003', '(', '\013', '2', '$', '.', 'e', 'n', 'v', 'o', 
+'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', '.', 'H', 'e', 'a', 'd', 'e', 'r', 'M', 
+'a', 't', 'c', 'h', 'e', 'r', 'R', '\027', 'r', 'e', 't', 'r', 'i', 'a', 'b', 'l', 'e', 'R', 'e', 'q', 'u', 'e', 's', 't', 'H', 
+'e', 'a', 'd', 'e', 'r', 's', '\032', '\271', '\001', '\n', '\r', 'R', 'e', 't', 'r', 'y', 'P', 'r', 'i', 'o', 'r', 'i', 't', 'y', '\022', 
+'\033', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\004', 'n', 
+'a', 'm', 'e', '\022', '9', '\n', '\014', 't', 'y', 'p', 'e', 'd', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\003', ' ', '\001', '(', '\013', 
+'2', '\024', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'A', 'n', 'y', 'H', '\000', 'R', 
+'\013', 't', 'y', 'p', 'e', 'd', 'C', 'o', 'n', 'f', 'i', 'g', ':', '3', '\232', '\305', '\210', '\036', '.', '\n', ',', 'e', 'n', 'v', 'o', 
+'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'r', 'o', 'u', 't', 'e', '.', 'R', 'e', 't', 'r', 'y', 'P', 'o', 'l', 'i', 'c', 
+'y', '.', 'R', 'e', 't', 'r', 'y', 'P', 'r', 'i', 'o', 'r', 'i', 't', 'y', 'B', '\r', '\n', '\013', 'c', 'o', 'n', 'f', 'i', 'g', 
+'_', 't', 'y', 'p', 'e', 'J', '\004', '\010', '\002', '\020', '\003', 'R', '\006', 'c', 'o', 'n', 'f', 'i', 'g', '\032', '\303', '\001', '\n', '\022', 'R', 
+'e', 't', 'r', 'y', 'H', 'o', 's', 't', 'P', 'r', 'e', 'd', 'i', 'c', 'a', 't', 'e', '\022', '\033', '\n', '\004', 'n', 'a', 'm', 'e', 
+'\030', '\001', ' ', '\001', '(', '\t', 'B', '\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '9', '\n', '\014', 
+'t', 'y', 'p', 'e', 'd', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\003', ' ', '\001', '(', '\013', '2', '\024', '.', 'g', 'o', 'o', 'g', 
+'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'A', 'n', 'y', 'H', '\000', 'R', '\013', 't', 'y', 'p', 'e', 'd', 'C', 
+'o', 'n', 'f', 'i', 'g', ':', '8', '\232', '\305', '\210', '\036', '3', '\n', '1', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', 
+'2', '.', 'r', 'o', 'u', 't', 'e', '.', 'R', 'e', 't', 'r', 'y', 'P', 'o', 'l', 'i', 'c', 'y', '.', 'R', 'e', 't', 'r', 'y', 
+'H', 'o', 's', 't', 'P', 'r', 'e', 'd', 'i', 'c', 'a', 't', 'e', 'B', '\r', '\n', '\013', 'c', 'o', 'n', 'f', 'i', 'g', '_', 't', 
+'y', 'p', 'e', 'J', '\004', '\010', '\002', '\020', '\003', 'R', '\006', 'c', 'o', 'n', 'f', 'i', 'g', '\032', '\326', '\001', '\n', '\014', 'R', 'e', 't', 
+'r', 'y', 'B', 'a', 'c', 'k', 'O', 'f', 'f', '\022', 'J', '\n', '\r', 'b', 'a', 's', 'e', '_', 'i', 'n', 't', 'e', 'r', 'v', 'a', 
+'l', '\030', '\001', ' ', '\001', '(', '\013', '2', '\031', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', 
+'.', 'D', 'u', 'r', 'a', 't', 'i', 'o', 'n', 'B', '\n', '\372', 'B', '\007', '\252', '\001', '\004', '\010', '\001', '*', '\000', 'R', '\014', 'b', 'a', 
+'s', 'e', 'I', 'n', 't', 'e', 'r', 'v', 'a', 'l', '\022', 'F', '\n', '\014', 'm', 'a', 'x', '_', 'i', 'n', 't', 'e', 'r', 'v', 'a', 
+'l', '\030', '\002', ' ', '\001', '(', '\013', '2', '\031', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', 
+'.', 'D', 'u', 'r', 'a', 't', 'i', 'o', 'n', 'B', '\010', '\372', 'B', '\005', '\252', '\001', '\002', '*', '\000', 'R', '\013', 'm', 'a', 'x', 'I', 
+'n', 't', 'e', 'r', 'v', 'a', 'l', ':', '2', '\232', '\305', '\210', '\036', '-', '\n', '+', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', 
+'.', 'v', '2', '.', 'r', 'o', 'u', 't', 'e', '.', 'R', 'e', 't', 'r', 'y', 'P', 'o', 'l', 'i', 'c', 'y', '.', 'R', 'e', 't', 
+'r', 'y', 'B', 'a', 'c', 'k', 'O', 'f', 'f', '\032', '\210', '\001', '\n', '\013', 'R', 'e', 's', 'e', 't', 'H', 'e', 'a', 'd', 'e', 'r', 
+'\022', '!', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\r', '\372', 'B', '\n', 'r', '\010', '\020', '\001', '\300', '\001', 
+'\001', '\310', '\001', '\000', 'R', '\004', 'n', 'a', 'm', 'e', '\022', 'V', '\n', '\006', 'f', 'o', 'r', 'm', 'a', 't', '\030', '\002', ' ', '\001', '(', 
+'\016', '2', '4', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', 
+'.', 'R', 'e', 't', 'r', 'y', 'P', 'o', 'l', 'i', 'c', 'y', '.', 'R', 'e', 's', 'e', 't', 'H', 'e', 'a', 'd', 'e', 'r', 'F', 
+'o', 'r', 'm', 'a', 't', 'B', '\010', '\372', 'B', '\005', '\202', '\001', '\002', '\020', '\001', 'R', '\006', 'f', 'o', 'r', 'm', 'a', 't', '\032', '\300', 
+'\001', '\n', '\027', 'R', 'a', 't', 'e', 'L', 'i', 'm', 'i', 't', 'e', 'd', 'R', 'e', 't', 'r', 'y', 'B', 'a', 'c', 'k', 'O', 'f', 
+'f', '\022', ']', '\n', '\r', 'r', 'e', 's', 'e', 't', '_', 'h', 'e', 'a', 'd', 'e', 'r', 's', '\030', '\001', ' ', '\003', '(', '\013', '2', 
+'.', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', '.', 'R', 
+'e', 't', 'r', 'y', 'P', 'o', 'l', 'i', 'c', 'y', '.', 'R', 'e', 's', 'e', 't', 'H', 'e', 'a', 'd', 'e', 'r', 'B', '\010', '\372', 
+'B', '\005', '\222', '\001', '\002', '\010', '\001', 'R', '\014', 'r', 'e', 's', 'e', 't', 'H', 'e', 'a', 'd', 'e', 'r', 's', '\022', 'F', '\n', '\014', 
+'m', 'a', 'x', '_', 'i', 'n', 't', 'e', 'r', 'v', 'a', 'l', '\030', '\002', ' ', '\001', '(', '\013', '2', '\031', '.', 'g', 'o', 'o', 'g', 
+'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'u', 'r', 'a', 't', 'i', 'o', 'n', 'B', '\010', '\372', 'B', '\005', 
+'\252', '\001', '\002', '*', '\000', 'R', '\013', 'm', 'a', 'x', 'I', 'n', 't', 'e', 'r', 'v', 'a', 'l', '\"', '4', '\n', '\021', 'R', 'e', 's', 
+'e', 't', 'H', 'e', 'a', 'd', 'e', 'r', 'F', 'o', 'r', 'm', 'a', 't', '\022', '\013', '\n', '\007', 'S', 'E', 'C', 'O', 'N', 'D', 'S', 
+'\020', '\000', '\022', '\022', '\n', '\016', 'U', 'N', 'I', 'X', '_', 'T', 'I', 'M', 'E', 'S', 'T', 'A', 'M', 'P', '\020', '\001', ':', '%', '\232', 
+'\305', '\210', '\036', ' ', '\n', '\036', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'r', 'o', 'u', 't', 'e', '.', 
+'R', 'e', 't', 'r', 'y', 'P', 'o', 'l', 'i', 'c', 'y', '\"', '\234', '\002', '\n', '\013', 'H', 'e', 'd', 'g', 'e', 'P', 'o', 'l', 'i', 
+'c', 'y', '\022', 'P', '\n', '\020', 'i', 'n', 'i', 't', 'i', 'a', 'l', '_', 'r', 'e', 'q', 'u', 'e', 's', 't', 's', '\030', '\001', ' ', 
+'\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'I', 'n', 
+'t', '3', '2', 'V', 'a', 'l', 'u', 'e', 'B', '\007', '\372', 'B', '\004', '*', '\002', '(', '\001', 'R', '\017', 'i', 'n', 'i', 't', 'i', 'a', 
+'l', 'R', 'e', 'q', 'u', 'e', 's', 't', 's', '\022', '\\', '\n', '\031', 'a', 'd', 'd', 'i', 't', 'i', 'o', 'n', 'a', 'l', '_', 'r', 
+'e', 'q', 'u', 'e', 's', 't', '_', 'c', 'h', 'a', 'n', 'c', 'e', '\030', '\002', ' ', '\001', '(', '\013', '2', ' ', '.', 'e', 'n', 'v', 
+'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'v', '3', '.', 'F', 'r', 'a', 'c', 't', 'i', 'o', 'n', 'a', 'l', 'P', 'e', 'r', 'c', 
+'e', 'n', 't', 'R', '\027', 'a', 'd', 'd', 'i', 't', 'i', 'o', 'n', 'a', 'l', 'R', 'e', 'q', 'u', 'e', 's', 't', 'C', 'h', 'a', 
+'n', 'c', 'e', '\022', '6', '\n', '\030', 'h', 'e', 'd', 'g', 'e', '_', 'o', 'n', '_', 'p', 'e', 'r', '_', 't', 'r', 'y', '_', 't', 
+'i', 'm', 'e', 'o', 'u', 't', '\030', '\003', ' ', '\001', '(', '\010', 'R', '\024', 'h', 'e', 'd', 'g', 'e', 'O', 'n', 'P', 'e', 'r', 'T', 
+'r', 'y', 'T', 'i', 'm', 'e', 'o', 'u', 't', ':', '%', '\232', '\305', '\210', '\036', ' ', '\n', '\036', 'e', 'n', 'v', 'o', 'y', '.', 'a', 
+'p', 'i', '.', 'v', '2', '.', 'r', 'o', 'u', 't', 'e', '.', 'H', 'e', 'd', 'g', 'e', 'P', 'o', 'l', 'i', 'c', 'y', '\"', '\341', 
+'\005', '\n', '\016', 'R', 'e', 'd', 'i', 'r', 'e', 'c', 't', 'A', 'c', 't', 'i', 'o', 'n', '\022', '\'', '\n', '\016', 'h', 't', 't', 'p', 
+'s', '_', 'r', 'e', 'd', 'i', 'r', 'e', 'c', 't', '\030', '\004', ' ', '\001', '(', '\010', 'H', '\000', 'R', '\r', 'h', 't', 't', 'p', 's', 
+'R', 'e', 'd', 'i', 'r', 'e', 'c', 't', '\022', ')', '\n', '\017', 's', 'c', 'h', 'e', 'm', 'e', '_', 'r', 'e', 'd', 'i', 'r', 'e', 
+'c', 't', '\030', '\007', ' ', '\001', '(', '\t', 'H', '\000', 'R', '\016', 's', 'c', 'h', 'e', 'm', 'e', 'R', 'e', 'd', 'i', 'r', 'e', 'c', 
+'t', '\022', '0', '\n', '\r', 'h', 'o', 's', 't', '_', 'r', 'e', 'd', 'i', 'r', 'e', 'c', 't', '\030', '\001', ' ', '\001', '(', '\t', 'B', 
+'\013', '\372', 'B', '\010', 'r', '\006', '\300', '\001', '\002', '\310', '\001', '\000', 'R', '\014', 'h', 'o', 's', 't', 'R', 'e', 'd', 'i', 'r', 'e', 'c', 
+'t', '\022', '#', '\n', '\r', 'p', 'o', 'r', 't', '_', 'r', 'e', 'd', 'i', 'r', 'e', 'c', 't', '\030', '\010', ' ', '\001', '(', '\r', 'R', 
+'\014', 'p', 'o', 'r', 't', 'R', 'e', 'd', 'i', 'r', 'e', 'c', 't', '\022', '2', '\n', '\r', 'p', 'a', 't', 'h', '_', 'r', 'e', 'd', 
+'i', 'r', 'e', 'c', 't', '\030', '\002', ' ', '\001', '(', '\t', 'B', '\013', '\372', 'B', '\010', 'r', '\006', '\300', '\001', '\002', '\310', '\001', '\000', 'H', 
+'\001', 'R', '\014', 'p', 'a', 't', 'h', 'R', 'e', 'd', 'i', 'r', 'e', 'c', 't', '\022', '4', '\n', '\016', 'p', 'r', 'e', 'f', 'i', 'x', 
+'_', 'r', 'e', 'w', 'r', 'i', 't', 'e', '\030', '\005', ' ', '\001', '(', '\t', 'B', '\013', '\372', 'B', '\010', 'r', '\006', '\300', '\001', '\002', '\310', 
+'\001', '\000', 'H', '\001', 'R', '\r', 'p', 'r', 'e', 'f', 'i', 'x', 'R', 'e', 'w', 'r', 'i', 't', 'e', '\022', 'U', '\n', '\r', 'r', 'e', 
+'g', 'e', 'x', '_', 'r', 'e', 'w', 'r', 'i', 't', 'e', '\030', '\t', ' ', '\001', '(', '\013', '2', '.', '.', 'e', 'n', 'v', 'o', 'y', 
+'.', 't', 'y', 'p', 'e', '.', 'm', 'a', 't', 'c', 'h', 'e', 'r', '.', 'v', '3', '.', 'R', 'e', 'g', 'e', 'x', 'M', 'a', 't', 
+'c', 'h', 'A', 'n', 'd', 'S', 'u', 'b', 's', 't', 'i', 't', 'u', 't', 'e', 'H', '\001', 'R', '\014', 'r', 'e', 'g', 'e', 'x', 'R', 
+'e', 'w', 'r', 'i', 't', 'e', '\022', 'i', '\n', '\r', 'r', 'e', 's', 'p', 'o', 'n', 's', 'e', '_', 'c', 'o', 'd', 'e', '\030', '\003', 
+' ', '\001', '(', '\016', '2', ':', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', 
+'.', 'v', '3', '.', 'R', 'e', 'd', 'i', 'r', 'e', 'c', 't', 'A', 'c', 't', 'i', 'o', 'n', '.', 'R', 'e', 'd', 'i', 'r', 'e', 
+'c', 't', 'R', 'e', 's', 'p', 'o', 'n', 's', 'e', 'C', 'o', 'd', 'e', 'B', '\010', '\372', 'B', '\005', '\202', '\001', '\002', '\020', '\001', 'R', 
+'\014', 'r', 'e', 's', 'p', 'o', 'n', 's', 'e', 'C', 'o', 'd', 'e', '\022', '\037', '\n', '\013', 's', 't', 'r', 'i', 'p', '_', 'q', 'u', 
+'e', 'r', 'y', '\030', '\006', ' ', '\001', '(', '\010', 'R', '\n', 's', 't', 'r', 'i', 'p', 'Q', 'u', 'e', 'r', 'y', '\"', 'w', '\n', '\024', 
+'R', 'e', 'd', 'i', 'r', 'e', 'c', 't', 'R', 'e', 's', 'p', 'o', 'n', 's', 'e', 'C', 'o', 'd', 'e', '\022', '\025', '\n', '\021', 'M', 
+'O', 'V', 'E', 'D', '_', 'P', 'E', 'R', 'M', 'A', 'N', 'E', 'N', 'T', 'L', 'Y', '\020', '\000', '\022', '\t', '\n', '\005', 'F', 'O', 'U', 
+'N', 'D', '\020', '\001', '\022', '\r', '\n', '\t', 'S', 'E', 'E', '_', 'O', 'T', 'H', 'E', 'R', '\020', '\002', '\022', '\026', '\n', '\022', 'T', 'E', 
+'M', 'P', 'O', 'R', 'A', 'R', 'Y', '_', 'R', 'E', 'D', 'I', 'R', 'E', 'C', 'T', '\020', '\003', '\022', '\026', '\n', '\022', 'P', 'E', 'R', 
+'M', 'A', 'N', 'E', 'N', 'T', '_', 'R', 'E', 'D', 'I', 'R', 'E', 'C', 'T', '\020', '\004', ':', '(', '\232', '\305', '\210', '\036', '#', '\n', 
+'!', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'r', 'o', 'u', 't', 'e', '.', 'R', 'e', 'd', 'i', 'r', 
+'e', 'c', 't', 'A', 'c', 't', 'i', 'o', 'n', 'B', '\032', '\n', '\030', 's', 'c', 'h', 'e', 'm', 'e', '_', 'r', 'e', 'w', 'r', 'i', 
+'t', 'e', '_', 's', 'p', 'e', 'c', 'i', 'f', 'i', 'e', 'r', 'B', '\030', '\n', '\026', 'p', 'a', 't', 'h', '_', 'r', 'e', 'w', 'r', 
+'i', 't', 'e', '_', 's', 'p', 'e', 'c', 'i', 'f', 'i', 'e', 'r', '\"', '\240', '\001', '\n', '\024', 'D', 'i', 'r', 'e', 'c', 't', 'R', 
+'e', 's', 'p', 'o', 'n', 's', 'e', 'A', 'c', 't', 'i', 'o', 'n', '\022', '\"', '\n', '\006', 's', 't', 'a', 't', 'u', 's', '\030', '\001', 
+' ', '\001', '(', '\r', 'B', '\n', '\372', 'B', '\007', '*', '\005', '\020', '\330', '\004', '(', 'd', 'R', '\006', 's', 't', 'a', 't', 'u', 's', '\022', 
+'4', '\n', '\004', 'b', 'o', 'd', 'y', '\030', '\002', ' ', '\001', '(', '\013', '2', ' ', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 
+'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'D', 'a', 't', 'a', 'S', 'o', 'u', 'r', 'c', 'e', 'R', '\004', 'b', 
+'o', 'd', 'y', ':', '.', '\232', '\305', '\210', '\036', ')', '\n', '\'', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 
+'r', 'o', 'u', 't', 'e', '.', 'D', 'i', 'r', 'e', 'c', 't', 'R', 'e', 's', 'p', 'o', 'n', 's', 'e', 'A', 'c', 't', 'i', 'o', 
+'n', '\"', '\025', '\n', '\023', 'N', 'o', 'n', 'F', 'o', 'r', 'w', 'a', 'r', 'd', 'i', 'n', 'g', 'A', 'c', 't', 'i', 'o', 'n', '\"', 
+'\221', '\001', '\n', '\t', 'D', 'e', 'c', 'o', 'r', 'a', 't', 'o', 'r', '\022', '%', '\n', '\t', 'o', 'p', 'e', 'r', 'a', 't', 'i', 'o', 
+'n', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\t', 'o', 'p', 'e', 'r', 'a', 't', 'i', 
+'o', 'n', '\022', '8', '\n', '\t', 'p', 'r', 'o', 'p', 'a', 'g', 'a', 't', 'e', '\030', '\002', ' ', '\001', '(', '\013', '2', '\032', '.', 'g', 
+'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'B', 'o', 'o', 'l', 'V', 'a', 'l', 'u', 'e', 'R', 
+'\t', 'p', 'r', 'o', 'p', 'a', 'g', 'a', 't', 'e', ':', '#', '\232', '\305', '\210', '\036', '\036', '\n', '\034', 'e', 'n', 'v', 'o', 'y', '.', 
+'a', 'p', 'i', '.', 'v', '2', '.', 'r', 'o', 'u', 't', 'e', '.', 'D', 'e', 'c', 'o', 'r', 'a', 't', 'o', 'r', '\"', '\322', '\002', 
+'\n', '\007', 'T', 'r', 'a', 'c', 'i', 'n', 'g', '\022', 'I', '\n', '\017', 'c', 'l', 'i', 'e', 'n', 't', '_', 's', 'a', 'm', 'p', 'l', 
+'i', 'n', 'g', '\030', '\001', ' ', '\001', '(', '\013', '2', ' ', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'v', '3', 
+'.', 'F', 'r', 'a', 'c', 't', 'i', 'o', 'n', 'a', 'l', 'P', 'e', 'r', 'c', 'e', 'n', 't', 'R', '\016', 'c', 'l', 'i', 'e', 'n', 
+'t', 'S', 'a', 'm', 'p', 'l', 'i', 'n', 'g', '\022', 'I', '\n', '\017', 'r', 'a', 'n', 'd', 'o', 'm', '_', 's', 'a', 'm', 'p', 'l', 
+'i', 'n', 'g', '\030', '\002', ' ', '\001', '(', '\013', '2', ' ', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'v', '3', 
+'.', 'F', 'r', 'a', 'c', 't', 'i', 'o', 'n', 'a', 'l', 'P', 'e', 'r', 'c', 'e', 'n', 't', 'R', '\016', 'r', 'a', 'n', 'd', 'o', 
+'m', 'S', 'a', 'm', 'p', 'l', 'i', 'n', 'g', '\022', 'K', '\n', '\020', 'o', 'v', 'e', 'r', 'a', 'l', 'l', '_', 's', 'a', 'm', 'p', 
+'l', 'i', 'n', 'g', '\030', '\003', ' ', '\001', '(', '\013', '2', ' ', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'v', 
+'3', '.', 'F', 'r', 'a', 'c', 't', 'i', 'o', 'n', 'a', 'l', 'P', 'e', 'r', 'c', 'e', 'n', 't', 'R', '\017', 'o', 'v', 'e', 'r', 
+'a', 'l', 'l', 'S', 'a', 'm', 'p', 'l', 'i', 'n', 'g', '\022', 'A', '\n', '\013', 'c', 'u', 's', 't', 'o', 'm', '_', 't', 'a', 'g', 
+'s', '\030', '\004', ' ', '\003', '(', '\013', '2', ' ', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 't', 'r', 'a', 'c', 
+'i', 'n', 'g', '.', 'v', '3', '.', 'C', 'u', 's', 't', 'o', 'm', 'T', 'a', 'g', 'R', '\n', 'c', 'u', 's', 't', 'o', 'm', 'T', 
+'a', 'g', 's', ':', '!', '\232', '\305', '\210', '\036', '\034', '\n', '\032', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 
+'r', 'o', 'u', 't', 'e', '.', 'T', 'r', 'a', 'c', 'i', 'n', 'g', '\"', '\264', '\001', '\n', '\016', 'V', 'i', 'r', 't', 'u', 'a', 'l', 
+'C', 'l', 'u', 's', 't', 'e', 'r', '\022', '>', '\n', '\007', 'h', 'e', 'a', 'd', 'e', 'r', 's', '\030', '\004', ' ', '\003', '(', '\013', '2', 
 '$', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', '.', 'H', 
-'e', 'a', 'd', 'e', 'r', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'R', '\020', 'r', 'e', 't', 'r', 'i', 'a', 'b', 'l', 'e', 'H', 'e', 
-'a', 'd', 'e', 'r', 's', '\022', '`', '\n', '\031', 'r', 'e', 't', 'r', 'i', 'a', 'b', 'l', 'e', '_', 'r', 'e', 'q', 'u', 'e', 's', 
-'t', '_', 'h', 'e', 'a', 'd', 'e', 'r', 's', '\030', '\n', ' ', '\003', '(', '\013', '2', '$', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 
-'o', 'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', '.', 'H', 'e', 'a', 'd', 'e', 'r', 'M', 'a', 't', 'c', 
-'h', 'e', 'r', 'R', '\027', 'r', 'e', 't', 'r', 'i', 'a', 'b', 'l', 'e', 'R', 'e', 'q', 'u', 'e', 's', 't', 'H', 'e', 'a', 'd', 
-'e', 'r', 's', '\032', '\271', '\001', '\n', '\r', 'R', 'e', 't', 'r', 'y', 'P', 'r', 'i', 'o', 'r', 'i', 't', 'y', '\022', '\033', '\n', '\004', 
-'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\004', 'n', 'a', 'm', 'e', 
-'\022', '9', '\n', '\014', 't', 'y', 'p', 'e', 'd', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\003', ' ', '\001', '(', '\013', '2', '\024', '.', 
-'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'A', 'n', 'y', 'H', '\000', 'R', '\013', 't', 'y', 
-'p', 'e', 'd', 'C', 'o', 'n', 'f', 'i', 'g', ':', '3', '\232', '\305', '\210', '\036', '.', '\n', ',', 'e', 'n', 'v', 'o', 'y', '.', 'a', 
-'p', 'i', '.', 'v', '2', '.', 'r', 'o', 'u', 't', 'e', '.', 'R', 'e', 't', 'r', 'y', 'P', 'o', 'l', 'i', 'c', 'y', '.', 'R', 
-'e', 't', 'r', 'y', 'P', 'r', 'i', 'o', 'r', 'i', 't', 'y', 'B', '\r', '\n', '\013', 'c', 'o', 'n', 'f', 'i', 'g', '_', 't', 'y', 
-'p', 'e', 'J', '\004', '\010', '\002', '\020', '\003', 'R', '\006', 'c', 'o', 'n', 'f', 'i', 'g', '\032', '\303', '\001', '\n', '\022', 'R', 'e', 't', 'r', 
-'y', 'H', 'o', 's', 't', 'P', 'r', 'e', 'd', 'i', 'c', 'a', 't', 'e', '\022', '\033', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', 
-'\001', '(', '\t', 'B', '\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '9', '\n', '\014', 't', 'y', 'p', 
-'e', 'd', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\003', ' ', '\001', '(', '\013', '2', '\024', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 
-'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'A', 'n', 'y', 'H', '\000', 'R', '\013', 't', 'y', 'p', 'e', 'd', 'C', 'o', 'n', 'f', 
-'i', 'g', ':', '8', '\232', '\305', '\210', '\036', '3', '\n', '1', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'r', 
-'o', 'u', 't', 'e', '.', 'R', 'e', 't', 'r', 'y', 'P', 'o', 'l', 'i', 'c', 'y', '.', 'R', 'e', 't', 'r', 'y', 'H', 'o', 's', 
-'t', 'P', 'r', 'e', 'd', 'i', 'c', 'a', 't', 'e', 'B', '\r', '\n', '\013', 'c', 'o', 'n', 'f', 'i', 'g', '_', 't', 'y', 'p', 'e', 
-'J', '\004', '\010', '\002', '\020', '\003', 'R', '\006', 'c', 'o', 'n', 'f', 'i', 'g', '\032', '\326', '\001', '\n', '\014', 'R', 'e', 't', 'r', 'y', 'B', 
-'a', 'c', 'k', 'O', 'f', 'f', '\022', 'J', '\n', '\r', 'b', 'a', 's', 'e', '_', 'i', 'n', 't', 'e', 'r', 'v', 'a', 'l', '\030', '\001', 
-' ', '\001', '(', '\013', '2', '\031', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'u', 
-'r', 'a', 't', 'i', 'o', 'n', 'B', '\n', '\372', 'B', '\007', '\252', '\001', '\004', '\010', '\001', '*', '\000', 'R', '\014', 'b', 'a', 's', 'e', 'I', 
-'n', 't', 'e', 'r', 'v', 'a', 'l', '\022', 'F', '\n', '\014', 'm', 'a', 'x', '_', 'i', 'n', 't', 'e', 'r', 'v', 'a', 'l', '\030', '\002', 
-' ', '\001', '(', '\013', '2', '\031', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'u', 
-'r', 'a', 't', 'i', 'o', 'n', 'B', '\010', '\372', 'B', '\005', '\252', '\001', '\002', '*', '\000', 'R', '\013', 'm', 'a', 'x', 'I', 'n', 't', 'e', 
-'r', 'v', 'a', 'l', ':', '2', '\232', '\305', '\210', '\036', '-', '\n', '+', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', 
-'.', 'r', 'o', 'u', 't', 'e', '.', 'R', 'e', 't', 'r', 'y', 'P', 'o', 'l', 'i', 'c', 'y', '.', 'R', 'e', 't', 'r', 'y', 'B', 
-'a', 'c', 'k', 'O', 'f', 'f', '\032', '\210', '\001', '\n', '\013', 'R', 'e', 's', 'e', 't', 'H', 'e', 'a', 'd', 'e', 'r', '\022', '!', '\n', 
-'\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\r', '\372', 'B', '\n', 'r', '\010', '\020', '\001', '\300', '\001', '\001', '\310', '\001', 
-'\000', 'R', '\004', 'n', 'a', 'm', 'e', '\022', 'V', '\n', '\006', 'f', 'o', 'r', 'm', 'a', 't', '\030', '\002', ' ', '\001', '(', '\016', '2', '4', 
-'.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', '.', 'R', 'e', 
-'t', 'r', 'y', 'P', 'o', 'l', 'i', 'c', 'y', '.', 'R', 'e', 's', 'e', 't', 'H', 'e', 'a', 'd', 'e', 'r', 'F', 'o', 'r', 'm', 
-'a', 't', 'B', '\010', '\372', 'B', '\005', '\202', '\001', '\002', '\020', '\001', 'R', '\006', 'f', 'o', 'r', 'm', 'a', 't', '\032', '\300', '\001', '\n', '\027', 
-'R', 'a', 't', 'e', 'L', 'i', 'm', 'i', 't', 'e', 'd', 'R', 'e', 't', 'r', 'y', 'B', 'a', 'c', 'k', 'O', 'f', 'f', '\022', ']', 
-'\n', '\r', 'r', 'e', 's', 'e', 't', '_', 'h', 'e', 'a', 'd', 'e', 'r', 's', '\030', '\001', ' ', '\003', '(', '\013', '2', '.', '.', 'e', 
-'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', '.', 'R', 'e', 't', 'r', 
-'y', 'P', 'o', 'l', 'i', 'c', 'y', '.', 'R', 'e', 's', 'e', 't', 'H', 'e', 'a', 'd', 'e', 'r', 'B', '\010', '\372', 'B', '\005', '\222', 
-'\001', '\002', '\010', '\001', 'R', '\014', 'r', 'e', 's', 'e', 't', 'H', 'e', 'a', 'd', 'e', 'r', 's', '\022', 'F', '\n', '\014', 'm', 'a', 'x', 
-'_', 'i', 'n', 't', 'e', 'r', 'v', 'a', 'l', '\030', '\002', ' ', '\001', '(', '\013', '2', '\031', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 
-'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'u', 'r', 'a', 't', 'i', 'o', 'n', 'B', '\010', '\372', 'B', '\005', '\252', '\001', '\002', 
-'*', '\000', 'R', '\013', 'm', 'a', 'x', 'I', 'n', 't', 'e', 'r', 'v', 'a', 'l', '\"', '4', '\n', '\021', 'R', 'e', 's', 'e', 't', 'H', 
-'e', 'a', 'd', 'e', 'r', 'F', 'o', 'r', 'm', 'a', 't', '\022', '\013', '\n', '\007', 'S', 'E', 'C', 'O', 'N', 'D', 'S', '\020', '\000', '\022', 
-'\022', '\n', '\016', 'U', 'N', 'I', 'X', '_', 'T', 'I', 'M', 'E', 'S', 'T', 'A', 'M', 'P', '\020', '\001', ':', '%', '\232', '\305', '\210', '\036', 
-' ', '\n', '\036', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'r', 'o', 'u', 't', 'e', '.', 'R', 'e', 't', 
-'r', 'y', 'P', 'o', 'l', 'i', 'c', 'y', '\"', '\234', '\002', '\n', '\013', 'H', 'e', 'd', 'g', 'e', 'P', 'o', 'l', 'i', 'c', 'y', '\022', 
-'P', '\n', '\020', 'i', 'n', 'i', 't', 'i', 'a', 'l', '_', 'r', 'e', 'q', 'u', 'e', 's', 't', 's', '\030', '\001', ' ', '\001', '(', '\013', 
+'e', 'a', 'd', 'e', 'r', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'R', '\007', 'h', 'e', 'a', 'd', 'e', 'r', 's', '\022', '\033', '\n', '\004', 
+'n', 'a', 'm', 'e', '\030', '\002', ' ', '\001', '(', '\t', 'B', '\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\004', 'n', 'a', 'm', 'e', 
+':', '(', '\232', '\305', '\210', '\036', '#', '\n', '!', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'r', 'o', 'u', 
+'t', 'e', '.', 'V', 'i', 'r', 't', 'u', 'a', 'l', 'C', 'l', 'u', 's', 't', 'e', 'r', 'J', '\004', '\010', '\001', '\020', '\002', 'J', '\004', 
+'\010', '\003', '\020', '\004', 'R', '\007', 'p', 'a', 't', 't', 'e', 'r', 'n', 'R', '\006', 'm', 'e', 't', 'h', 'o', 'd', '\"', '\252', '\026', '\n', 
+'\t', 'R', 'a', 't', 'e', 'L', 'i', 'm', 'i', 't', '\022', ';', '\n', '\005', 's', 't', 'a', 'g', 'e', '\030', '\001', ' ', '\001', '(', '\013', 
 '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'I', 'n', 't', '3', '2', 
-'V', 'a', 'l', 'u', 'e', 'B', '\007', '\372', 'B', '\004', '*', '\002', '(', '\001', 'R', '\017', 'i', 'n', 'i', 't', 'i', 'a', 'l', 'R', 'e', 
-'q', 'u', 'e', 's', 't', 's', '\022', '\\', '\n', '\031', 'a', 'd', 'd', 'i', 't', 'i', 'o', 'n', 'a', 'l', '_', 'r', 'e', 'q', 'u', 
-'e', 's', 't', '_', 'c', 'h', 'a', 'n', 'c', 'e', '\030', '\002', ' ', '\001', '(', '\013', '2', ' ', '.', 'e', 'n', 'v', 'o', 'y', '.', 
-'t', 'y', 'p', 'e', '.', 'v', '3', '.', 'F', 'r', 'a', 'c', 't', 'i', 'o', 'n', 'a', 'l', 'P', 'e', 'r', 'c', 'e', 'n', 't', 
-'R', '\027', 'a', 'd', 'd', 'i', 't', 'i', 'o', 'n', 'a', 'l', 'R', 'e', 'q', 'u', 'e', 's', 't', 'C', 'h', 'a', 'n', 'c', 'e', 
-'\022', '6', '\n', '\030', 'h', 'e', 'd', 'g', 'e', '_', 'o', 'n', '_', 'p', 'e', 'r', '_', 't', 'r', 'y', '_', 't', 'i', 'm', 'e', 
-'o', 'u', 't', '\030', '\003', ' ', '\001', '(', '\010', 'R', '\024', 'h', 'e', 'd', 'g', 'e', 'O', 'n', 'P', 'e', 'r', 'T', 'r', 'y', 'T', 
-'i', 'm', 'e', 'o', 'u', 't', ':', '%', '\232', '\305', '\210', '\036', ' ', '\n', '\036', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 
-'v', '2', '.', 'r', 'o', 'u', 't', 'e', '.', 'H', 'e', 'd', 'g', 'e', 'P', 'o', 'l', 'i', 'c', 'y', '\"', '\341', '\005', '\n', '\016', 
-'R', 'e', 'd', 'i', 'r', 'e', 'c', 't', 'A', 'c', 't', 'i', 'o', 'n', '\022', '\'', '\n', '\016', 'h', 't', 't', 'p', 's', '_', 'r', 
-'e', 'd', 'i', 'r', 'e', 'c', 't', '\030', '\004', ' ', '\001', '(', '\010', 'H', '\000', 'R', '\r', 'h', 't', 't', 'p', 's', 'R', 'e', 'd', 
-'i', 'r', 'e', 'c', 't', '\022', ')', '\n', '\017', 's', 'c', 'h', 'e', 'm', 'e', '_', 'r', 'e', 'd', 'i', 'r', 'e', 'c', 't', '\030', 
-'\007', ' ', '\001', '(', '\t', 'H', '\000', 'R', '\016', 's', 'c', 'h', 'e', 'm', 'e', 'R', 'e', 'd', 'i', 'r', 'e', 'c', 't', '\022', '0', 
-'\n', '\r', 'h', 'o', 's', 't', '_', 'r', 'e', 'd', 'i', 'r', 'e', 'c', 't', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\013', '\372', 'B', 
-'\010', 'r', '\006', '\300', '\001', '\002', '\310', '\001', '\000', 'R', '\014', 'h', 'o', 's', 't', 'R', 'e', 'd', 'i', 'r', 'e', 'c', 't', '\022', '#', 
-'\n', '\r', 'p', 'o', 'r', 't', '_', 'r', 'e', 'd', 'i', 'r', 'e', 'c', 't', '\030', '\010', ' ', '\001', '(', '\r', 'R', '\014', 'p', 'o', 
-'r', 't', 'R', 'e', 'd', 'i', 'r', 'e', 'c', 't', '\022', '2', '\n', '\r', 'p', 'a', 't', 'h', '_', 'r', 'e', 'd', 'i', 'r', 'e', 
-'c', 't', '\030', '\002', ' ', '\001', '(', '\t', 'B', '\013', '\372', 'B', '\010', 'r', '\006', '\300', '\001', '\002', '\310', '\001', '\000', 'H', '\001', 'R', '\014', 
-'p', 'a', 't', 'h', 'R', 'e', 'd', 'i', 'r', 'e', 'c', 't', '\022', '4', '\n', '\016', 'p', 'r', 'e', 'f', 'i', 'x', '_', 'r', 'e', 
-'w', 'r', 'i', 't', 'e', '\030', '\005', ' ', '\001', '(', '\t', 'B', '\013', '\372', 'B', '\010', 'r', '\006', '\300', '\001', '\002', '\310', '\001', '\000', 'H', 
-'\001', 'R', '\r', 'p', 'r', 'e', 'f', 'i', 'x', 'R', 'e', 'w', 'r', 'i', 't', 'e', '\022', 'U', '\n', '\r', 'r', 'e', 'g', 'e', 'x', 
-'_', 'r', 'e', 'w', 'r', 'i', 't', 'e', '\030', '\t', ' ', '\001', '(', '\013', '2', '.', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 
-'p', 'e', '.', 'm', 'a', 't', 'c', 'h', 'e', 'r', '.', 'v', '3', '.', 'R', 'e', 'g', 'e', 'x', 'M', 'a', 't', 'c', 'h', 'A', 
-'n', 'd', 'S', 'u', 'b', 's', 't', 'i', 't', 'u', 't', 'e', 'H', '\001', 'R', '\014', 'r', 'e', 'g', 'e', 'x', 'R', 'e', 'w', 'r', 
-'i', 't', 'e', '\022', 'i', '\n', '\r', 'r', 'e', 's', 'p', 'o', 'n', 's', 'e', '_', 'c', 'o', 'd', 'e', '\030', '\003', ' ', '\001', '(', 
-'\016', '2', ':', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', 
-'.', 'R', 'e', 'd', 'i', 'r', 'e', 'c', 't', 'A', 'c', 't', 'i', 'o', 'n', '.', 'R', 'e', 'd', 'i', 'r', 'e', 'c', 't', 'R', 
-'e', 's', 'p', 'o', 'n', 's', 'e', 'C', 'o', 'd', 'e', 'B', '\010', '\372', 'B', '\005', '\202', '\001', '\002', '\020', '\001', 'R', '\014', 'r', 'e', 
-'s', 'p', 'o', 'n', 's', 'e', 'C', 'o', 'd', 'e', '\022', '\037', '\n', '\013', 's', 't', 'r', 'i', 'p', '_', 'q', 'u', 'e', 'r', 'y', 
-'\030', '\006', ' ', '\001', '(', '\010', 'R', '\n', 's', 't', 'r', 'i', 'p', 'Q', 'u', 'e', 'r', 'y', '\"', 'w', '\n', '\024', 'R', 'e', 'd', 
-'i', 'r', 'e', 'c', 't', 'R', 'e', 's', 'p', 'o', 'n', 's', 'e', 'C', 'o', 'd', 'e', '\022', '\025', '\n', '\021', 'M', 'O', 'V', 'E', 
-'D', '_', 'P', 'E', 'R', 'M', 'A', 'N', 'E', 'N', 'T', 'L', 'Y', '\020', '\000', '\022', '\t', '\n', '\005', 'F', 'O', 'U', 'N', 'D', '\020', 
-'\001', '\022', '\r', '\n', '\t', 'S', 'E', 'E', '_', 'O', 'T', 'H', 'E', 'R', '\020', '\002', '\022', '\026', '\n', '\022', 'T', 'E', 'M', 'P', 'O', 
-'R', 'A', 'R', 'Y', '_', 'R', 'E', 'D', 'I', 'R', 'E', 'C', 'T', '\020', '\003', '\022', '\026', '\n', '\022', 'P', 'E', 'R', 'M', 'A', 'N', 
-'E', 'N', 'T', '_', 'R', 'E', 'D', 'I', 'R', 'E', 'C', 'T', '\020', '\004', ':', '(', '\232', '\305', '\210', '\036', '#', '\n', '!', 'e', 'n', 
-'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'r', 'o', 'u', 't', 'e', '.', 'R', 'e', 'd', 'i', 'r', 'e', 'c', 't', 
-'A', 'c', 't', 'i', 'o', 'n', 'B', '\032', '\n', '\030', 's', 'c', 'h', 'e', 'm', 'e', '_', 'r', 'e', 'w', 'r', 'i', 't', 'e', '_', 
-'s', 'p', 'e', 'c', 'i', 'f', 'i', 'e', 'r', 'B', '\030', '\n', '\026', 'p', 'a', 't', 'h', '_', 'r', 'e', 'w', 'r', 'i', 't', 'e', 
-'_', 's', 'p', 'e', 'c', 'i', 'f', 'i', 'e', 'r', '\"', '\240', '\001', '\n', '\024', 'D', 'i', 'r', 'e', 'c', 't', 'R', 'e', 's', 'p', 
-'o', 'n', 's', 'e', 'A', 'c', 't', 'i', 'o', 'n', '\022', '\"', '\n', '\006', 's', 't', 'a', 't', 'u', 's', '\030', '\001', ' ', '\001', '(', 
-'\r', 'B', '\n', '\372', 'B', '\007', '*', '\005', '\020', '\330', '\004', '(', 'd', 'R', '\006', 's', 't', 'a', 't', 'u', 's', '\022', '4', '\n', '\004', 
-'b', 'o', 'd', 'y', '\030', '\002', ' ', '\001', '(', '\013', '2', ' ', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', 
-'.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'D', 'a', 't', 'a', 'S', 'o', 'u', 'r', 'c', 'e', 'R', '\004', 'b', 'o', 'd', 'y', 
-':', '.', '\232', '\305', '\210', '\036', ')', '\n', '\'', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'r', 'o', 'u', 
-'t', 'e', '.', 'D', 'i', 'r', 'e', 'c', 't', 'R', 'e', 's', 'p', 'o', 'n', 's', 'e', 'A', 'c', 't', 'i', 'o', 'n', '\"', '\025', 
-'\n', '\023', 'N', 'o', 'n', 'F', 'o', 'r', 'w', 'a', 'r', 'd', 'i', 'n', 'g', 'A', 'c', 't', 'i', 'o', 'n', '\"', '\221', '\001', '\n', 
-'\t', 'D', 'e', 'c', 'o', 'r', 'a', 't', 'o', 'r', '\022', '%', '\n', '\t', 'o', 'p', 'e', 'r', 'a', 't', 'i', 'o', 'n', '\030', '\001', 
-' ', '\001', '(', '\t', 'B', '\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\t', 'o', 'p', 'e', 'r', 'a', 't', 'i', 'o', 'n', '\022', 
-'8', '\n', '\t', 'p', 'r', 'o', 'p', 'a', 'g', 'a', 't', 'e', '\030', '\002', ' ', '\001', '(', '\013', '2', '\032', '.', 'g', 'o', 'o', 'g', 
-'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'B', 'o', 'o', 'l', 'V', 'a', 'l', 'u', 'e', 'R', '\t', 'p', 'r', 
-'o', 'p', 'a', 'g', 'a', 't', 'e', ':', '#', '\232', '\305', '\210', '\036', '\036', '\n', '\034', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', 
-'.', 'v', '2', '.', 'r', 'o', 'u', 't', 'e', '.', 'D', 'e', 'c', 'o', 'r', 'a', 't', 'o', 'r', '\"', '\322', '\002', '\n', '\007', 'T', 
-'r', 'a', 'c', 'i', 'n', 'g', '\022', 'I', '\n', '\017', 'c', 'l', 'i', 'e', 'n', 't', '_', 's', 'a', 'm', 'p', 'l', 'i', 'n', 'g', 
-'\030', '\001', ' ', '\001', '(', '\013', '2', ' ', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'v', '3', '.', 'F', 'r', 
-'a', 'c', 't', 'i', 'o', 'n', 'a', 'l', 'P', 'e', 'r', 'c', 'e', 'n', 't', 'R', '\016', 'c', 'l', 'i', 'e', 'n', 't', 'S', 'a', 
-'m', 'p', 'l', 'i', 'n', 'g', '\022', 'I', '\n', '\017', 'r', 'a', 'n', 'd', 'o', 'm', '_', 's', 'a', 'm', 'p', 'l', 'i', 'n', 'g', 
-'\030', '\002', ' ', '\001', '(', '\013', '2', ' ', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'v', '3', '.', 'F', 'r', 
-'a', 'c', 't', 'i', 'o', 'n', 'a', 'l', 'P', 'e', 'r', 'c', 'e', 'n', 't', 'R', '\016', 'r', 'a', 'n', 'd', 'o', 'm', 'S', 'a', 
-'m', 'p', 'l', 'i', 'n', 'g', '\022', 'K', '\n', '\020', 'o', 'v', 'e', 'r', 'a', 'l', 'l', '_', 's', 'a', 'm', 'p', 'l', 'i', 'n', 
-'g', '\030', '\003', ' ', '\001', '(', '\013', '2', ' ', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'v', '3', '.', 'F', 
-'r', 'a', 'c', 't', 'i', 'o', 'n', 'a', 'l', 'P', 'e', 'r', 'c', 'e', 'n', 't', 'R', '\017', 'o', 'v', 'e', 'r', 'a', 'l', 'l', 
-'S', 'a', 'm', 'p', 'l', 'i', 'n', 'g', '\022', 'A', '\n', '\013', 'c', 'u', 's', 't', 'o', 'm', '_', 't', 'a', 'g', 's', '\030', '\004', 
-' ', '\003', '(', '\013', '2', ' ', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 't', 'r', 'a', 'c', 'i', 'n', 'g', 
-'.', 'v', '3', '.', 'C', 'u', 's', 't', 'o', 'm', 'T', 'a', 'g', 'R', '\n', 'c', 'u', 's', 't', 'o', 'm', 'T', 'a', 'g', 's', 
-':', '!', '\232', '\305', '\210', '\036', '\034', '\n', '\032', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'r', 'o', 'u', 
-'t', 'e', '.', 'T', 'r', 'a', 'c', 'i', 'n', 'g', '\"', '\264', '\001', '\n', '\016', 'V', 'i', 'r', 't', 'u', 'a', 'l', 'C', 'l', 'u', 
-'s', 't', 'e', 'r', '\022', '>', '\n', '\007', 'h', 'e', 'a', 'd', 'e', 'r', 's', '\030', '\004', ' ', '\003', '(', '\013', '2', '$', '.', 'e', 
-'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', '.', 'H', 'e', 'a', 'd', 
-'e', 'r', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'R', '\007', 'h', 'e', 'a', 'd', 'e', 'r', 's', '\022', '\033', '\n', '\004', 'n', 'a', 'm', 
-'e', '\030', '\002', ' ', '\001', '(', '\t', 'B', '\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\004', 'n', 'a', 'm', 'e', ':', '(', '\232', 
-'\305', '\210', '\036', '#', '\n', '!', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'r', 'o', 'u', 't', 'e', '.', 
-'V', 'i', 'r', 't', 'u', 'a', 'l', 'C', 'l', 'u', 's', 't', 'e', 'r', 'J', '\004', '\010', '\001', '\020', '\002', 'J', '\004', '\010', '\003', '\020', 
-'\004', 'R', '\007', 'p', 'a', 't', 't', 'e', 'r', 'n', 'R', '\006', 'm', 'e', 't', 'h', 'o', 'd', '\"', '\252', '\026', '\n', '\t', 'R', 'a', 
-'t', 'e', 'L', 'i', 'm', 'i', 't', '\022', ';', '\n', '\005', 's', 't', 'a', 'g', 'e', '\030', '\001', ' ', '\001', '(', '\013', '2', '\034', '.', 
-'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'I', 'n', 't', '3', '2', 'V', 'a', 'l', 
-'u', 'e', 'B', '\007', '\372', 'B', '\004', '*', '\002', '\030', '\n', 'R', '\005', 's', 't', 'a', 'g', 'e', '\022', '\037', '\n', '\013', 'd', 'i', 's', 
-'a', 'b', 'l', 'e', '_', 'k', 'e', 'y', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\n', 'd', 'i', 's', 'a', 'b', 'l', 'e', 'K', 'e', 
-'y', '\022', 'K', '\n', '\007', 'a', 'c', 't', 'i', 'o', 'n', 's', '\030', '\003', ' ', '\003', '(', '\013', '2', '\'', '.', 'e', 'n', 'v', 'o', 
-'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', '.', 'R', 'a', 't', 'e', 'L', 'i', 'm', 
-'i', 't', '.', 'A', 'c', 't', 'i', 'o', 'n', 'B', '\010', '\372', 'B', '\005', '\222', '\001', '\002', '\010', '\001', 'R', '\007', 'a', 'c', 't', 'i', 
-'o', 'n', 's', '\022', '?', '\n', '\005', 'l', 'i', 'm', 'i', 't', '\030', '\004', ' ', '\001', '(', '\013', '2', ')', '.', 'e', 'n', 'v', 'o', 
-'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', '.', 'R', 'a', 't', 'e', 'L', 'i', 'm', 
-'i', 't', '.', 'O', 'v', 'e', 'r', 'r', 'i', 'd', 'e', 'R', '\005', 'l', 'i', 'm', 'i', 't', '\032', '\226', '\022', '\n', '\006', 'A', 'c', 
-'t', 'i', 'o', 'n', '\022', '^', '\n', '\016', 's', 'o', 'u', 'r', 'c', 'e', '_', 'c', 'l', 'u', 's', 't', 'e', 'r', '\030', '\001', ' ', 
-'\001', '(', '\013', '2', '5', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 
-'v', '3', '.', 'R', 'a', 't', 'e', 'L', 'i', 'm', 'i', 't', '.', 'A', 'c', 't', 'i', 'o', 'n', '.', 'S', 'o', 'u', 'r', 'c', 
-'e', 'C', 'l', 'u', 's', 't', 'e', 'r', 'H', '\000', 'R', '\r', 's', 'o', 'u', 'r', 'c', 'e', 'C', 'l', 'u', 's', 't', 'e', 'r', 
-'\022', 'm', '\n', '\023', 'd', 'e', 's', 't', 'i', 'n', 'a', 't', 'i', 'o', 'n', '_', 'c', 'l', 'u', 's', 't', 'e', 'r', '\030', '\002', 
-' ', '\001', '(', '\013', '2', ':', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', 
-'.', 'v', '3', '.', 'R', 'a', 't', 'e', 'L', 'i', 'm', 'i', 't', '.', 'A', 'c', 't', 'i', 'o', 'n', '.', 'D', 'e', 's', 't', 
-'i', 'n', 'a', 't', 'i', 'o', 'n', 'C', 'l', 'u', 's', 't', 'e', 'r', 'H', '\000', 'R', '\022', 'd', 'e', 's', 't', 'i', 'n', 'a', 
-'t', 'i', 'o', 'n', 'C', 'l', 'u', 's', 't', 'e', 'r', '\022', 'a', '\n', '\017', 'r', 'e', 'q', 'u', 'e', 's', 't', '_', 'h', 'e', 
-'a', 'd', 'e', 'r', 's', '\030', '\003', ' ', '\001', '(', '\013', '2', '6', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 
-'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', '.', 'R', 'a', 't', 'e', 'L', 'i', 'm', 'i', 't', '.', 'A', 'c', 't', 'i', 
-'o', 'n', '.', 'R', 'e', 'q', 'u', 'e', 's', 't', 'H', 'e', 'a', 'd', 'e', 'r', 's', 'H', '\000', 'R', '\016', 'r', 'e', 'q', 'u', 
-'e', 's', 't', 'H', 'e', 'a', 'd', 'e', 'r', 's', '\022', '^', '\n', '\016', 'r', 'e', 'm', 'o', 't', 'e', '_', 'a', 'd', 'd', 'r', 
-'e', 's', 's', '\030', '\004', ' ', '\001', '(', '\013', '2', '5', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 
-'r', 'o', 'u', 't', 'e', '.', 'v', '3', '.', 'R', 'a', 't', 'e', 'L', 'i', 'm', 'i', 't', '.', 'A', 'c', 't', 'i', 'o', 'n', 
-'.', 'R', 'e', 'm', 'o', 't', 'e', 'A', 'd', 'd', 'r', 'e', 's', 's', 'H', '\000', 'R', '\r', 'r', 'e', 'm', 'o', 't', 'e', 'A', 
-'d', 'd', 'r', 'e', 's', 's', '\022', 'U', '\n', '\013', 'g', 'e', 'n', 'e', 'r', 'i', 'c', '_', 'k', 'e', 'y', '\030', '\005', ' ', '\001', 
-'(', '\013', '2', '2', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', 
-'3', '.', 'R', 'a', 't', 'e', 'L', 'i', 'm', 'i', 't', '.', 'A', 'c', 't', 'i', 'o', 'n', '.', 'G', 'e', 'n', 'e', 'r', 'i', 
-'c', 'K', 'e', 'y', 'H', '\000', 'R', '\n', 'g', 'e', 'n', 'e', 'r', 'i', 'c', 'K', 'e', 'y', '\022', 'h', '\n', '\022', 'h', 'e', 'a', 
-'d', 'e', 'r', '_', 'v', 'a', 'l', 'u', 'e', '_', 'm', 'a', 't', 'c', 'h', '\030', '\006', ' ', '\001', '(', '\013', '2', '8', '.', 'e', 
+'V', 'a', 'l', 'u', 'e', 'B', '\007', '\372', 'B', '\004', '*', '\002', '\030', '\n', 'R', '\005', 's', 't', 'a', 'g', 'e', '\022', '\037', '\n', '\013', 
+'d', 'i', 's', 'a', 'b', 'l', 'e', '_', 'k', 'e', 'y', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\n', 'd', 'i', 's', 'a', 'b', 'l', 
+'e', 'K', 'e', 'y', '\022', 'K', '\n', '\007', 'a', 'c', 't', 'i', 'o', 'n', 's', '\030', '\003', ' ', '\003', '(', '\013', '2', '\'', '.', 'e', 
+'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', '.', 'R', 'a', 't', 'e', 
+'L', 'i', 'm', 'i', 't', '.', 'A', 'c', 't', 'i', 'o', 'n', 'B', '\010', '\372', 'B', '\005', '\222', '\001', '\002', '\010', '\001', 'R', '\007', 'a', 
+'c', 't', 'i', 'o', 'n', 's', '\022', '?', '\n', '\005', 'l', 'i', 'm', 'i', 't', '\030', '\004', ' ', '\001', '(', '\013', '2', ')', '.', 'e', 
 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', '.', 'R', 'a', 't', 'e', 
-'L', 'i', 'm', 'i', 't', '.', 'A', 'c', 't', 'i', 'o', 'n', '.', 'H', 'e', 'a', 'd', 'e', 'r', 'V', 'a', 'l', 'u', 'e', 'M', 
-'a', 't', 'c', 'h', 'H', '\000', 'R', '\020', 'h', 'e', 'a', 'd', 'e', 'r', 'V', 'a', 'l', 'u', 'e', 'M', 'a', 't', 'c', 'h', '\022', 
-'w', '\n', '\020', 'd', 'y', 'n', 'a', 'm', 'i', 'c', '_', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', '\030', '\007', ' ', '\001', '(', '\013', 
-'2', '7', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', '.', 
-'R', 'a', 't', 'e', 'L', 'i', 'm', 'i', 't', '.', 'A', 'c', 't', 'i', 'o', 'n', '.', 'D', 'y', 'n', 'a', 'm', 'i', 'c', 'M', 
-'e', 't', 'a', 'D', 'a', 't', 'a', 'B', '\021', '\030', '\001', '\222', '\307', '\206', '\330', '\004', '\003', '3', '.', '0', '\270', '\356', '\362', '\322', '\005', 
-'\001', 'H', '\000', 'R', '\017', 'd', 'y', 'n', 'a', 'm', 'i', 'c', 'M', 'e', 't', 'a', 'd', 'a', 't', 'a', '\022', 'N', '\n', '\010', 'm', 
-'e', 't', 'a', 'd', 'a', 't', 'a', '\030', '\010', ' ', '\001', '(', '\013', '2', '0', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 
-'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', '.', 'R', 'a', 't', 'e', 'L', 'i', 'm', 'i', 't', '.', 'A', 'c', 
-'t', 'i', 'o', 'n', '.', 'M', 'e', 't', 'a', 'D', 'a', 't', 'a', 'H', '\000', 'R', '\010', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', 
-'\022', 'J', '\n', '\t', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', '\030', '\t', ' ', '\001', '(', '\013', '2', '*', '.', 'e', 'n', 'v', 
-'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'T', 'y', 'p', 'e', 'd', 'E', 'x', 
-'t', 'e', 'n', 's', 'i', 'o', 'n', 'C', 'o', 'n', 'f', 'i', 'g', 'H', '\000', 'R', '\t', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 
-'n', '\032', 'I', '\n', '\r', 'S', 'o', 'u', 'r', 'c', 'e', 'C', 'l', 'u', 's', 't', 'e', 'r', ':', '8', '\232', '\305', '\210', '\036', '3', 
+'L', 'i', 'm', 'i', 't', '.', 'O', 'v', 'e', 'r', 'r', 'i', 'd', 'e', 'R', '\005', 'l', 'i', 'm', 'i', 't', '\032', '\226', '\022', '\n', 
+'\006', 'A', 'c', 't', 'i', 'o', 'n', '\022', '^', '\n', '\016', 's', 'o', 'u', 'r', 'c', 'e', '_', 'c', 'l', 'u', 's', 't', 'e', 'r', 
+'\030', '\001', ' ', '\001', '(', '\013', '2', '5', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 
+'t', 'e', '.', 'v', '3', '.', 'R', 'a', 't', 'e', 'L', 'i', 'm', 'i', 't', '.', 'A', 'c', 't', 'i', 'o', 'n', '.', 'S', 'o', 
+'u', 'r', 'c', 'e', 'C', 'l', 'u', 's', 't', 'e', 'r', 'H', '\000', 'R', '\r', 's', 'o', 'u', 'r', 'c', 'e', 'C', 'l', 'u', 's', 
+'t', 'e', 'r', '\022', 'm', '\n', '\023', 'd', 'e', 's', 't', 'i', 'n', 'a', 't', 'i', 'o', 'n', '_', 'c', 'l', 'u', 's', 't', 'e', 
+'r', '\030', '\002', ' ', '\001', '(', '\013', '2', ':', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'o', 
+'u', 't', 'e', '.', 'v', '3', '.', 'R', 'a', 't', 'e', 'L', 'i', 'm', 'i', 't', '.', 'A', 'c', 't', 'i', 'o', 'n', '.', 'D', 
+'e', 's', 't', 'i', 'n', 'a', 't', 'i', 'o', 'n', 'C', 'l', 'u', 's', 't', 'e', 'r', 'H', '\000', 'R', '\022', 'd', 'e', 's', 't', 
+'i', 'n', 'a', 't', 'i', 'o', 'n', 'C', 'l', 'u', 's', 't', 'e', 'r', '\022', 'a', '\n', '\017', 'r', 'e', 'q', 'u', 'e', 's', 't', 
+'_', 'h', 'e', 'a', 'd', 'e', 'r', 's', '\030', '\003', ' ', '\001', '(', '\013', '2', '6', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 
+'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', '.', 'R', 'a', 't', 'e', 'L', 'i', 'm', 'i', 't', '.', 'A', 
+'c', 't', 'i', 'o', 'n', '.', 'R', 'e', 'q', 'u', 'e', 's', 't', 'H', 'e', 'a', 'd', 'e', 'r', 's', 'H', '\000', 'R', '\016', 'r', 
+'e', 'q', 'u', 'e', 's', 't', 'H', 'e', 'a', 'd', 'e', 'r', 's', '\022', '^', '\n', '\016', 'r', 'e', 'm', 'o', 't', 'e', '_', 'a', 
+'d', 'd', 'r', 'e', 's', 's', '\030', '\004', ' ', '\001', '(', '\013', '2', '5', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 
+'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', '.', 'R', 'a', 't', 'e', 'L', 'i', 'm', 'i', 't', '.', 'A', 'c', 't', 
+'i', 'o', 'n', '.', 'R', 'e', 'm', 'o', 't', 'e', 'A', 'd', 'd', 'r', 'e', 's', 's', 'H', '\000', 'R', '\r', 'r', 'e', 'm', 'o', 
+'t', 'e', 'A', 'd', 'd', 'r', 'e', 's', 's', '\022', 'U', '\n', '\013', 'g', 'e', 'n', 'e', 'r', 'i', 'c', '_', 'k', 'e', 'y', '\030', 
+'\005', ' ', '\001', '(', '\013', '2', '2', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 
+'e', '.', 'v', '3', '.', 'R', 'a', 't', 'e', 'L', 'i', 'm', 'i', 't', '.', 'A', 'c', 't', 'i', 'o', 'n', '.', 'G', 'e', 'n', 
+'e', 'r', 'i', 'c', 'K', 'e', 'y', 'H', '\000', 'R', '\n', 'g', 'e', 'n', 'e', 'r', 'i', 'c', 'K', 'e', 'y', '\022', 'h', '\n', '\022', 
+'h', 'e', 'a', 'd', 'e', 'r', '_', 'v', 'a', 'l', 'u', 'e', '_', 'm', 'a', 't', 'c', 'h', '\030', '\006', ' ', '\001', '(', '\013', '2', 
+'8', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', '.', 'R', 
+'a', 't', 'e', 'L', 'i', 'm', 'i', 't', '.', 'A', 'c', 't', 'i', 'o', 'n', '.', 'H', 'e', 'a', 'd', 'e', 'r', 'V', 'a', 'l', 
+'u', 'e', 'M', 'a', 't', 'c', 'h', 'H', '\000', 'R', '\020', 'h', 'e', 'a', 'd', 'e', 'r', 'V', 'a', 'l', 'u', 'e', 'M', 'a', 't', 
+'c', 'h', '\022', 'w', '\n', '\020', 'd', 'y', 'n', 'a', 'm', 'i', 'c', '_', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', '\030', '\007', ' ', 
+'\001', '(', '\013', '2', '7', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 
+'v', '3', '.', 'R', 'a', 't', 'e', 'L', 'i', 'm', 'i', 't', '.', 'A', 'c', 't', 'i', 'o', 'n', '.', 'D', 'y', 'n', 'a', 'm', 
+'i', 'c', 'M', 'e', 't', 'a', 'D', 'a', 't', 'a', 'B', '\021', '\030', '\001', '\222', '\307', '\206', '\330', '\004', '\003', '3', '.', '0', '\270', '\356', 
+'\362', '\322', '\005', '\001', 'H', '\000', 'R', '\017', 'd', 'y', 'n', 'a', 'm', 'i', 'c', 'M', 'e', 't', 'a', 'd', 'a', 't', 'a', '\022', 'N', 
+'\n', '\010', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', '\030', '\010', ' ', '\001', '(', '\013', '2', '0', '.', 'e', 'n', 'v', 'o', 'y', '.', 
+'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', '.', 'R', 'a', 't', 'e', 'L', 'i', 'm', 'i', 't', 
+'.', 'A', 'c', 't', 'i', 'o', 'n', '.', 'M', 'e', 't', 'a', 'D', 'a', 't', 'a', 'H', '\000', 'R', '\010', 'm', 'e', 't', 'a', 'd', 
+'a', 't', 'a', '\022', 'J', '\n', '\t', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', '\030', '\t', ' ', '\001', '(', '\013', '2', '*', '.', 
+'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'T', 'y', 'p', 'e', 
+'d', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'C', 'o', 'n', 'f', 'i', 'g', 'H', '\000', 'R', '\t', 'e', 'x', 't', 'e', 'n', 
+'s', 'i', 'o', 'n', '\032', 'I', '\n', '\r', 'S', 'o', 'u', 'r', 'c', 'e', 'C', 'l', 'u', 's', 't', 'e', 'r', ':', '8', '\232', '\305', 
+'\210', '\036', '3', '\n', '1', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'r', 'o', 'u', 't', 'e', '.', 'R', 
+'a', 't', 'e', 'L', 'i', 'm', 'i', 't', '.', 'A', 'c', 't', 'i', 'o', 'n', '.', 'S', 'o', 'u', 'r', 'c', 'e', 'C', 'l', 'u', 
+'s', 't', 'e', 'r', '\032', 'S', '\n', '\022', 'D', 'e', 's', 't', 'i', 'n', 'a', 't', 'i', 'o', 'n', 'C', 'l', 'u', 's', 't', 'e', 
+'r', ':', '=', '\232', '\305', '\210', '\036', '8', '\n', '6', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'r', 'o', 
+'u', 't', 'e', '.', 'R', 'a', 't', 'e', 'L', 'i', 'm', 'i', 't', '.', 'A', 'c', 't', 'i', 'o', 'n', '.', 'D', 'e', 's', 't', 
+'i', 'n', 'a', 't', 'i', 'o', 'n', 'C', 'l', 'u', 's', 't', 'e', 'r', '\032', '\321', '\001', '\n', '\016', 'R', 'e', 'q', 'u', 'e', 's', 
+'t', 'H', 'e', 'a', 'd', 'e', 'r', 's', '\022', '.', '\n', '\013', 'h', 'e', 'a', 'd', 'e', 'r', '_', 'n', 'a', 'm', 'e', '\030', '\001', 
+' ', '\001', '(', '\t', 'B', '\r', '\372', 'B', '\n', 'r', '\010', '\020', '\001', '\300', '\001', '\001', '\310', '\001', '\000', 'R', '\n', 'h', 'e', 'a', 'd', 
+'e', 'r', 'N', 'a', 'm', 'e', '\022', '.', '\n', '\016', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', '_', 'k', 'e', 'y', '\030', 
+'\002', ' ', '\001', '(', '\t', 'B', '\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\r', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 
+'r', 'K', 'e', 'y', '\022', '$', '\n', '\016', 's', 'k', 'i', 'p', '_', 'i', 'f', '_', 'a', 'b', 's', 'e', 'n', 't', '\030', '\003', ' ', 
+'\001', '(', '\010', 'R', '\014', 's', 'k', 'i', 'p', 'I', 'f', 'A', 'b', 's', 'e', 'n', 't', ':', '9', '\232', '\305', '\210', '\036', '4', '\n', 
+'2', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'r', 'o', 'u', 't', 'e', '.', 'R', 'a', 't', 'e', 'L', 
+'i', 'm', 'i', 't', '.', 'A', 'c', 't', 'i', 'o', 'n', '.', 'R', 'e', 'q', 'u', 'e', 's', 't', 'H', 'e', 'a', 'd', 'e', 'r', 
+'s', '\032', 'I', '\n', '\r', 'R', 'e', 'm', 'o', 't', 'e', 'A', 'd', 'd', 'r', 'e', 's', 's', ':', '8', '\232', '\305', '\210', '\036', '3', 
 '\n', '1', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'r', 'o', 'u', 't', 'e', '.', 'R', 'a', 't', 'e', 
-'L', 'i', 'm', 'i', 't', '.', 'A', 'c', 't', 'i', 'o', 'n', '.', 'S', 'o', 'u', 'r', 'c', 'e', 'C', 'l', 'u', 's', 't', 'e', 
-'r', '\032', 'S', '\n', '\022', 'D', 'e', 's', 't', 'i', 'n', 'a', 't', 'i', 'o', 'n', 'C', 'l', 'u', 's', 't', 'e', 'r', ':', '=', 
-'\232', '\305', '\210', '\036', '8', '\n', '6', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'r', 'o', 'u', 't', 'e', 
-'.', 'R', 'a', 't', 'e', 'L', 'i', 'm', 'i', 't', '.', 'A', 'c', 't', 'i', 'o', 'n', '.', 'D', 'e', 's', 't', 'i', 'n', 'a', 
-'t', 'i', 'o', 'n', 'C', 'l', 'u', 's', 't', 'e', 'r', '\032', '\321', '\001', '\n', '\016', 'R', 'e', 'q', 'u', 'e', 's', 't', 'H', 'e', 
-'a', 'd', 'e', 'r', 's', '\022', '.', '\n', '\013', 'h', 'e', 'a', 'd', 'e', 'r', '_', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', 
-'\t', 'B', '\r', '\372', 'B', '\n', 'r', '\010', '\020', '\001', '\300', '\001', '\001', '\310', '\001', '\000', 'R', '\n', 'h', 'e', 'a', 'd', 'e', 'r', 'N', 
-'a', 'm', 'e', '\022', '.', '\n', '\016', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', '_', 'k', 'e', 'y', '\030', '\002', ' ', '\001', 
+'L', 'i', 'm', 'i', 't', '.', 'A', 'c', 't', 'i', 'o', 'n', '.', 'R', 'e', 'm', 'o', 't', 'e', 'A', 'd', 'd', 'r', 'e', 's', 
+'s', '\032', '\236', '\001', '\n', '\n', 'G', 'e', 'n', 'e', 'r', 'i', 'c', 'K', 'e', 'y', '\022', '2', '\n', '\020', 'd', 'e', 's', 'c', 'r', 
+'i', 'p', 't', 'o', 'r', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\007', '\372', 'B', '\004', 'r', '\002', '\020', 
+'\001', 'R', '\017', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'V', 'a', 'l', 'u', 'e', '\022', '%', '\n', '\016', 'd', 'e', 's', 
+'c', 'r', 'i', 'p', 't', 'o', 'r', '_', 'k', 'e', 'y', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\r', 'd', 'e', 's', 'c', 'r', 'i', 
+'p', 't', 'o', 'r', 'K', 'e', 'y', ':', '5', '\232', '\305', '\210', '\036', '0', '\n', '.', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', 
+'.', 'v', '2', '.', 'r', 'o', 'u', 't', 'e', '.', 'R', 'a', 't', 'e', 'L', 'i', 'm', 'i', 't', '.', 'A', 'c', 't', 'i', 'o', 
+'n', '.', 'G', 'e', 'n', 'e', 'r', 'i', 'c', 'K', 'e', 'y', '\032', '\214', '\002', '\n', '\020', 'H', 'e', 'a', 'd', 'e', 'r', 'V', 'a', 
+'l', 'u', 'e', 'M', 'a', 't', 'c', 'h', '\022', '2', '\n', '\020', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', '_', 'v', 'a', 
+'l', 'u', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\017', 'd', 'e', 's', 'c', 'r', 
+'i', 'p', 't', 'o', 'r', 'V', 'a', 'l', 'u', 'e', '\022', '=', '\n', '\014', 'e', 'x', 'p', 'e', 'c', 't', '_', 'm', 'a', 't', 'c', 
+'h', '\030', '\002', ' ', '\001', '(', '\013', '2', '\032', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', 
+'.', 'B', 'o', 'o', 'l', 'V', 'a', 'l', 'u', 'e', 'R', '\013', 'e', 'x', 'p', 'e', 'c', 't', 'M', 'a', 't', 'c', 'h', '\022', 'H', 
+'\n', '\007', 'h', 'e', 'a', 'd', 'e', 'r', 's', '\030', '\003', ' ', '\003', '(', '\013', '2', '$', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 
+'o', 'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', '.', 'H', 'e', 'a', 'd', 'e', 'r', 'M', 'a', 't', 'c', 
+'h', 'e', 'r', 'B', '\010', '\372', 'B', '\005', '\222', '\001', '\002', '\010', '\001', 'R', '\007', 'h', 'e', 'a', 'd', 'e', 'r', 's', ':', ';', '\232', 
+'\305', '\210', '\036', '6', '\n', '4', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'r', 'o', 'u', 't', 'e', '.', 
+'R', 'a', 't', 'e', 'L', 'i', 'm', 'i', 't', '.', 'A', 'c', 't', 'i', 'o', 'n', '.', 'H', 'e', 'a', 'd', 'e', 'r', 'V', 'a', 
+'l', 'u', 'e', 'M', 'a', 't', 'c', 'h', '\032', '\270', '\001', '\n', '\017', 'D', 'y', 'n', 'a', 'm', 'i', 'c', 'M', 'e', 't', 'a', 'D', 
+'a', 't', 'a', '\022', '.', '\n', '\016', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', '_', 'k', 'e', 'y', '\030', '\001', ' ', '\001', 
 '(', '\t', 'B', '\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\r', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'K', 'e', 
-'y', '\022', '$', '\n', '\016', 's', 'k', 'i', 'p', '_', 'i', 'f', '_', 'a', 'b', 's', 'e', 'n', 't', '\030', '\003', ' ', '\001', '(', '\010', 
-'R', '\014', 's', 'k', 'i', 'p', 'I', 'f', 'A', 'b', 's', 'e', 'n', 't', ':', '9', '\232', '\305', '\210', '\036', '4', '\n', '2', 'e', 'n', 
-'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'r', 'o', 'u', 't', 'e', '.', 'R', 'a', 't', 'e', 'L', 'i', 'm', 'i', 
-'t', '.', 'A', 'c', 't', 'i', 'o', 'n', '.', 'R', 'e', 'q', 'u', 'e', 's', 't', 'H', 'e', 'a', 'd', 'e', 'r', 's', '\032', 'I', 
-'\n', '\r', 'R', 'e', 'm', 'o', 't', 'e', 'A', 'd', 'd', 'r', 'e', 's', 's', ':', '8', '\232', '\305', '\210', '\036', '3', '\n', '1', 'e', 
-'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'r', 'o', 'u', 't', 'e', '.', 'R', 'a', 't', 'e', 'L', 'i', 'm', 
-'i', 't', '.', 'A', 'c', 't', 'i', 'o', 'n', '.', 'R', 'e', 'm', 'o', 't', 'e', 'A', 'd', 'd', 'r', 'e', 's', 's', '\032', '\236', 
-'\001', '\n', '\n', 'G', 'e', 'n', 'e', 'r', 'i', 'c', 'K', 'e', 'y', '\022', '2', '\n', '\020', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 
-'o', 'r', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\017', 
-'d', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'V', 'a', 'l', 'u', 'e', '\022', '%', '\n', '\016', 'd', 'e', 's', 'c', 'r', 'i', 
-'p', 't', 'o', 'r', '_', 'k', 'e', 'y', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\r', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 
-'r', 'K', 'e', 'y', ':', '5', '\232', '\305', '\210', '\036', '0', '\n', '.', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', 
-'.', 'r', 'o', 'u', 't', 'e', '.', 'R', 'a', 't', 'e', 'L', 'i', 'm', 'i', 't', '.', 'A', 'c', 't', 'i', 'o', 'n', '.', 'G', 
-'e', 'n', 'e', 'r', 'i', 'c', 'K', 'e', 'y', '\032', '\214', '\002', '\n', '\020', 'H', 'e', 'a', 'd', 'e', 'r', 'V', 'a', 'l', 'u', 'e', 
-'M', 'a', 't', 'c', 'h', '\022', '2', '\n', '\020', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', '_', 'v', 'a', 'l', 'u', 'e', 
-'\030', '\001', ' ', '\001', '(', '\t', 'B', '\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\017', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 
-'o', 'r', 'V', 'a', 'l', 'u', 'e', '\022', '=', '\n', '\014', 'e', 'x', 'p', 'e', 'c', 't', '_', 'm', 'a', 't', 'c', 'h', '\030', '\002', 
-' ', '\001', '(', '\013', '2', '\032', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'B', 'o', 
-'o', 'l', 'V', 'a', 'l', 'u', 'e', 'R', '\013', 'e', 'x', 'p', 'e', 'c', 't', 'M', 'a', 't', 'c', 'h', '\022', 'H', '\n', '\007', 'h', 
-'e', 'a', 'd', 'e', 'r', 's', '\030', '\003', ' ', '\003', '(', '\013', '2', '$', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 
-'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', '.', 'H', 'e', 'a', 'd', 'e', 'r', 'M', 'a', 't', 'c', 'h', 'e', 'r', 
-'B', '\010', '\372', 'B', '\005', '\222', '\001', '\002', '\010', '\001', 'R', '\007', 'h', 'e', 'a', 'd', 'e', 'r', 's', ':', ';', '\232', '\305', '\210', '\036', 
-'6', '\n', '4', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'r', 'o', 'u', 't', 'e', '.', 'R', 'a', 't', 
-'e', 'L', 'i', 'm', 'i', 't', '.', 'A', 'c', 't', 'i', 'o', 'n', '.', 'H', 'e', 'a', 'd', 'e', 'r', 'V', 'a', 'l', 'u', 'e', 
-'M', 'a', 't', 'c', 'h', '\032', '\270', '\001', '\n', '\017', 'D', 'y', 'n', 'a', 'm', 'i', 'c', 'M', 'e', 't', 'a', 'D', 'a', 't', 'a', 
-'\022', '.', '\n', '\016', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', '_', 'k', 'e', 'y', '\030', '\001', ' ', '\001', '(', '\t', 'B', 
-'\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\r', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'K', 'e', 'y', '\022', 'P', 
-'\n', '\014', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', '_', 'k', 'e', 'y', '\030', '\002', ' ', '\001', '(', '\013', '2', '#', '.', 'e', 'n', 
-'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', '.', 'v', '3', '.', 'M', 'e', 't', 'a', 
-'d', 'a', 't', 'a', 'K', 'e', 'y', 'B', '\010', '\372', 'B', '\005', '\212', '\001', '\002', '\020', '\001', 'R', '\013', 'm', 'e', 't', 'a', 'd', 'a', 
-'t', 'a', 'K', 'e', 'y', '\022', '#', '\n', '\r', 'd', 'e', 'f', 'a', 'u', 'l', 't', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\003', ' ', 
-'\001', '(', '\t', 'R', '\014', 'd', 'e', 'f', 'a', 'u', 'l', 't', 'V', 'a', 'l', 'u', 'e', '\032', '\264', '\002', '\n', '\010', 'M', 'e', 't', 
-'a', 'D', 'a', 't', 'a', '\022', '.', '\n', '\016', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', '_', 'k', 'e', 'y', '\030', '\001', 
-' ', '\001', '(', '\t', 'B', '\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\r', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 
-'K', 'e', 'y', '\022', 'P', '\n', '\014', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', '_', 'k', 'e', 'y', '\030', '\002', ' ', '\001', '(', '\013', 
-'2', '#', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', '.', 'v', '3', 
-'.', 'M', 'e', 't', 'a', 'd', 'a', 't', 'a', 'K', 'e', 'y', 'B', '\010', '\372', 'B', '\005', '\212', '\001', '\002', '\020', '\001', 'R', '\013', 'm', 
-'e', 't', 'a', 'd', 'a', 't', 'a', 'K', 'e', 'y', '\022', '#', '\n', '\r', 'd', 'e', 'f', 'a', 'u', 'l', 't', '_', 'v', 'a', 'l', 
-'u', 'e', '\030', '\003', ' ', '\001', '(', '\t', 'R', '\014', 'd', 'e', 'f', 'a', 'u', 'l', 't', 'V', 'a', 'l', 'u', 'e', '\022', 'Y', '\n', 
-'\006', 's', 'o', 'u', 'r', 'c', 'e', '\030', '\004', ' ', '\001', '(', '\016', '2', '7', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 
-'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', '.', 'R', 'a', 't', 'e', 'L', 'i', 'm', 'i', 't', '.', 'A', 'c', 
-'t', 'i', 'o', 'n', '.', 'M', 'e', 't', 'a', 'D', 'a', 't', 'a', '.', 'S', 'o', 'u', 'r', 'c', 'e', 'B', '\010', '\372', 'B', '\005', 
-'\202', '\001', '\002', '\020', '\001', 'R', '\006', 's', 'o', 'u', 'r', 'c', 'e', '\"', '&', '\n', '\006', 'S', 'o', 'u', 'r', 'c', 'e', '\022', '\013', 
-'\n', '\007', 'D', 'Y', 'N', 'A', 'M', 'I', 'C', '\020', '\000', '\022', '\017', '\n', '\013', 'R', 'O', 'U', 'T', 'E', '_', 'E', 'N', 'T', 'R', 
-'Y', '\020', '\001', ':', '*', '\232', '\305', '\210', '\036', '%', '\n', '#', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 
-'r', 'o', 'u', 't', 'e', '.', 'R', 'a', 't', 'e', 'L', 'i', 'm', 'i', 't', '.', 'A', 'c', 't', 'i', 'o', 'n', 'B', '\027', '\n', 
-'\020', 'a', 'c', 't', 'i', 'o', 'n', '_', 's', 'p', 'e', 'c', 'i', 'f', 'i', 'e', 'r', '\022', '\003', '\370', 'B', '\001', '\032', '\362', '\001', 
-'\n', '\010', 'O', 'v', 'e', 'r', 'r', 'i', 'd', 'e', '\022', 'f', '\n', '\020', 'd', 'y', 'n', 'a', 'm', 'i', 'c', '_', 'm', 'e', 't', 
-'a', 'd', 'a', 't', 'a', '\030', '\001', ' ', '\001', '(', '\013', '2', '9', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 
-'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', '.', 'R', 'a', 't', 'e', 'L', 'i', 'm', 'i', 't', '.', 'O', 'v', 'e', 'r', 
-'r', 'i', 'd', 'e', '.', 'D', 'y', 'n', 'a', 'm', 'i', 'c', 'M', 'e', 't', 'a', 'd', 'a', 't', 'a', 'H', '\000', 'R', '\017', 'd', 
-'y', 'n', 'a', 'm', 'i', 'c', 'M', 'e', 't', 'a', 'd', 'a', 't', 'a', '\032', 'c', '\n', '\017', 'D', 'y', 'n', 'a', 'm', 'i', 'c', 
-'M', 'e', 't', 'a', 'd', 'a', 't', 'a', '\022', 'P', '\n', '\014', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', '_', 'k', 'e', 'y', '\030', 
-'\001', ' ', '\001', '(', '\013', '2', '#', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'e', 't', 'a', 'd', 'a', 
-'t', 'a', '.', 'v', '3', '.', 'M', 'e', 't', 'a', 'd', 'a', 't', 'a', 'K', 'e', 'y', 'B', '\010', '\372', 'B', '\005', '\212', '\001', '\002', 
-'\020', '\001', 'R', '\013', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', 'K', 'e', 'y', 'B', '\031', '\n', '\022', 'o', 'v', 'e', 'r', 'r', 'i', 
-'d', 'e', '_', 's', 'p', 'e', 'c', 'i', 'f', 'i', 'e', 'r', '\022', '\003', '\370', 'B', '\001', ':', '#', '\232', '\305', '\210', '\036', '\036', '\n', 
-'\034', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'r', 'o', 'u', 't', 'e', '.', 'R', 'a', 't', 'e', 'L', 
-'i', 'm', 'i', 't', '\"', '\244', '\005', '\n', '\r', 'H', 'e', 'a', 'd', 'e', 'r', 'M', 'a', 't', 'c', 'h', 'e', 'r', '\022', '!', '\n', 
-'\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\r', '\372', 'B', '\n', 'r', '\010', '\020', '\001', '\300', '\001', '\001', '\310', '\001', 
-'\000', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '.', '\n', '\013', 'e', 'x', 'a', 'c', 't', '_', 'm', 'a', 't', 'c', 'h', '\030', '\004', ' ', 
-'\001', '(', '\t', 'B', '\013', '\030', '\001', '\222', '\307', '\206', '\330', '\004', '\003', '3', '.', '0', 'H', '\000', 'R', '\n', 'e', 'x', 'a', 'c', 't', 
-'M', 'a', 't', 'c', 'h', '\022', '\\', '\n', '\020', 's', 'a', 'f', 'e', '_', 'r', 'e', 'g', 'e', 'x', '_', 'm', 'a', 't', 'c', 'h', 
-'\030', '\013', ' ', '\001', '(', '\013', '2', '#', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'a', 't', 'c', 'h', 
-'e', 'r', '.', 'v', '3', '.', 'R', 'e', 'g', 'e', 'x', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'B', '\013', '\030', '\001', '\222', '\307', '\206', 
-'\330', '\004', '\003', '3', '.', '0', 'H', '\000', 'R', '\016', 's', 'a', 'f', 'e', 'R', 'e', 'g', 'e', 'x', 'M', 'a', 't', 'c', 'h', '\022', 
-'<', '\n', '\013', 'r', 'a', 'n', 'g', 'e', '_', 'm', 'a', 't', 'c', 'h', '\030', '\006', ' ', '\001', '(', '\013', '2', '\031', '.', 'e', 'n', 
-'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'v', '3', '.', 'I', 'n', 't', '6', '4', 'R', 'a', 'n', 'g', 'e', 'H', '\000', 'R', 
-'\n', 'r', 'a', 'n', 'g', 'e', 'M', 'a', 't', 'c', 'h', '\022', '%', '\n', '\r', 'p', 'r', 'e', 's', 'e', 'n', 't', '_', 'm', 'a', 
-'t', 'c', 'h', '\030', '\007', ' ', '\001', '(', '\010', 'H', '\000', 'R', '\014', 'p', 'r', 'e', 's', 'e', 'n', 't', 'M', 'a', 't', 'c', 'h', 
-'\022', '7', '\n', '\014', 'p', 'r', 'e', 'f', 'i', 'x', '_', 'm', 'a', 't', 'c', 'h', '\030', '\t', ' ', '\001', '(', '\t', 'B', '\022', '\030', 
-'\001', '\372', 'B', '\004', 'r', '\002', '\020', '\001', '\222', '\307', '\206', '\330', '\004', '\003', '3', '.', '0', 'H', '\000', 'R', '\013', 'p', 'r', 'e', 'f', 
-'i', 'x', 'M', 'a', 't', 'c', 'h', '\022', '7', '\n', '\014', 's', 'u', 'f', 'f', 'i', 'x', '_', 'm', 'a', 't', 'c', 'h', '\030', '\n', 
-' ', '\001', '(', '\t', 'B', '\022', '\030', '\001', '\372', 'B', '\004', 'r', '\002', '\020', '\001', '\222', '\307', '\206', '\330', '\004', '\003', '3', '.', '0', 'H', 
-'\000', 'R', '\013', 's', 'u', 'f', 'f', 'i', 'x', 'M', 'a', 't', 'c', 'h', '\022', ';', '\n', '\016', 'c', 'o', 'n', 't', 'a', 'i', 'n', 
-'s', '_', 'm', 'a', 't', 'c', 'h', '\030', '\014', ' ', '\001', '(', '\t', 'B', '\022', '\030', '\001', '\372', 'B', '\004', 'r', '\002', '\020', '\001', '\222', 
-'\307', '\206', '\330', '\004', '\003', '3', '.', '0', 'H', '\000', 'R', '\r', 'c', 'o', 'n', 't', 'a', 'i', 'n', 's', 'M', 'a', 't', 'c', 'h', 
-'\022', 'I', '\n', '\014', 's', 't', 'r', 'i', 'n', 'g', '_', 'm', 'a', 't', 'c', 'h', '\030', '\r', ' ', '\001', '(', '\013', '2', '$', '.', 
-'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'a', 't', 'c', 'h', 'e', 'r', '.', 'v', '3', '.', 'S', 't', 'r', 
-'i', 'n', 'g', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'H', '\000', 'R', '\013', 's', 't', 'r', 'i', 'n', 'g', 'M', 'a', 't', 'c', 'h', 
-'\022', '!', '\n', '\014', 'i', 'n', 'v', 'e', 'r', 't', '_', 'm', 'a', 't', 'c', 'h', '\030', '\010', ' ', '\001', '(', '\010', 'R', '\013', 'i', 
-'n', 'v', 'e', 'r', 't', 'M', 'a', 't', 'c', 'h', ':', '\'', '\232', '\305', '\210', '\036', '\"', '\n', ' ', 'e', 'n', 'v', 'o', 'y', '.', 
-'a', 'p', 'i', '.', 'v', '2', '.', 'r', 'o', 'u', 't', 'e', '.', 'H', 'e', 'a', 'd', 'e', 'r', 'M', 'a', 't', 'c', 'h', 'e', 
-'r', 'B', '\030', '\n', '\026', 'h', 'e', 'a', 'd', 'e', 'r', '_', 'm', 'a', 't', 'c', 'h', '_', 's', 'p', 'e', 'c', 'i', 'f', 'i', 
-'e', 'r', 'J', '\004', '\010', '\002', '\020', '\003', 'J', '\004', '\010', '\003', '\020', '\004', 'J', '\004', '\010', '\005', '\020', '\006', 'R', '\013', 'r', 'e', 'g', 
-'e', 'x', '_', 'm', 'a', 't', 'c', 'h', '\"', '\241', '\002', '\n', '\025', 'Q', 'u', 'e', 'r', 'y', 'P', 'a', 'r', 'a', 'm', 'e', 't', 
-'e', 'r', 'M', 'a', 't', 'c', 'h', 'e', 'r', '\022', '\036', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\n', 
-'\372', 'B', '\007', 'r', '\005', '\020', '\001', '(', '\200', '\010', 'R', '\004', 'n', 'a', 'm', 'e', '\022', 'S', '\n', '\014', 's', 't', 'r', 'i', 'n', 
-'g', '_', 'm', 'a', 't', 'c', 'h', '\030', '\005', ' ', '\001', '(', '\013', '2', '$', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 
-'e', '.', 'm', 'a', 't', 'c', 'h', 'e', 'r', '.', 'v', '3', '.', 'S', 't', 'r', 'i', 'n', 'g', 'M', 'a', 't', 'c', 'h', 'e', 
-'r', 'B', '\010', '\372', 'B', '\005', '\212', '\001', '\002', '\020', '\001', 'H', '\000', 'R', '\013', 's', 't', 'r', 'i', 'n', 'g', 'M', 'a', 't', 'c', 
-'h', '\022', '%', '\n', '\r', 'p', 'r', 'e', 's', 'e', 'n', 't', '_', 'm', 'a', 't', 'c', 'h', '\030', '\006', ' ', '\001', '(', '\010', 'H', 
-'\000', 'R', '\014', 'p', 'r', 'e', 's', 'e', 'n', 't', 'M', 'a', 't', 'c', 'h', ':', '/', '\232', '\305', '\210', '\036', '*', '\n', '(', 'e', 
-'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'r', 'o', 'u', 't', 'e', '.', 'Q', 'u', 'e', 'r', 'y', 'P', 'a', 
-'r', 'a', 'm', 'e', 't', 'e', 'r', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'B', '!', '\n', '\037', 'q', 'u', 'e', 'r', 'y', '_', 'p', 
-'a', 'r', 'a', 'm', 'e', 't', 'e', 'r', '_', 'm', 'a', 't', 'c', 'h', '_', 's', 'p', 'e', 'c', 'i', 'f', 'i', 'e', 'r', 'J', 
-'\004', '\010', '\003', '\020', '\004', 'J', '\004', '\010', '\004', '\020', '\005', 'R', '\005', 'v', 'a', 'l', 'u', 'e', 'R', '\005', 'r', 'e', 'g', 'e', 'x', 
-'\"', '\271', '\002', '\n', '\026', 'I', 'n', 't', 'e', 'r', 'n', 'a', 'l', 'R', 'e', 'd', 'i', 'r', 'e', 'c', 't', 'P', 'o', 'l', 'i', 
-'c', 'y', '\022', 'R', '\n', '\026', 'm', 'a', 'x', '_', 'i', 'n', 't', 'e', 'r', 'n', 'a', 'l', '_', 'r', 'e', 'd', 'i', 'r', 'e', 
-'c', 't', 's', '\030', '\001', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 
-'u', 'f', '.', 'U', 'I', 'n', 't', '3', '2', 'V', 'a', 'l', 'u', 'e', 'R', '\024', 'm', 'a', 'x', 'I', 'n', 't', 'e', 'r', 'n', 
-'a', 'l', 'R', 'e', 'd', 'i', 'r', 'e', 'c', 't', 's', '\022', '@', '\n', '\027', 'r', 'e', 'd', 'i', 'r', 'e', 'c', 't', '_', 'r', 
-'e', 's', 'p', 'o', 'n', 's', 'e', '_', 'c', 'o', 'd', 'e', 's', '\030', '\002', ' ', '\003', '(', '\r', 'B', '\010', '\372', 'B', '\005', '\222', 
-'\001', '\002', '\020', '\005', 'R', '\025', 'r', 'e', 'd', 'i', 'r', 'e', 'c', 't', 'R', 'e', 's', 'p', 'o', 'n', 's', 'e', 'C', 'o', 'd', 
-'e', 's', '\022', 'J', '\n', '\n', 'p', 'r', 'e', 'd', 'i', 'c', 'a', 't', 'e', 's', '\030', '\003', ' ', '\003', '(', '\013', '2', '*', '.', 
-'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'T', 'y', 'p', 'e', 
-'d', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'C', 'o', 'n', 'f', 'i', 'g', 'R', '\n', 'p', 'r', 'e', 'd', 'i', 'c', 'a', 
-'t', 'e', 's', '\022', '=', '\n', '\033', 'a', 'l', 'l', 'o', 'w', '_', 'c', 'r', 'o', 's', 's', '_', 's', 'c', 'h', 'e', 'm', 'e', 
-'_', 'r', 'e', 'd', 'i', 'r', 'e', 'c', 't', '\030', '\004', ' ', '\001', '(', '\010', 'R', '\030', 'a', 'l', 'l', 'o', 'w', 'C', 'r', 'o', 
-'s', 's', 'S', 'c', 'h', 'e', 'm', 'e', 'R', 'e', 'd', 'i', 'r', 'e', 'c', 't', '\"', ']', '\n', '\014', 'F', 'i', 'l', 't', 'e', 
-'r', 'C', 'o', 'n', 'f', 'i', 'g', '\022', ',', '\n', '\006', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\001', ' ', '\001', '(', '\013', '2', '\024', 
-'.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'A', 'n', 'y', 'R', '\006', 'c', 'o', 'n', 
-'f', 'i', 'g', '\022', '\037', '\n', '\013', 'i', 's', '_', 'o', 'p', 't', 'i', 'o', 'n', 'a', 'l', '\030', '\002', ' ', '\001', '(', '\010', 'R', 
-'\n', 'i', 's', 'O', 'p', 't', 'i', 'o', 'n', 'a', 'l', 'B', 'E', '\n', '#', 'i', 'o', '.', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 
-'o', 'x', 'y', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', 
-'B', '\024', 'R', 'o', 'u', 't', 'e', 'C', 'o', 'm', 'p', 'o', 'n', 'e', 'n', 't', 's', 'P', 'r', 'o', 't', 'o', 'P', '\001', '\272', 
-'\200', '\310', '\321', '\006', '\002', '\020', '\002', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', 
+'y', '\022', 'P', '\n', '\014', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', '_', 'k', 'e', 'y', '\030', '\002', ' ', '\001', '(', '\013', '2', '#', 
+'.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', '.', 'v', '3', '.', 'M', 
+'e', 't', 'a', 'd', 'a', 't', 'a', 'K', 'e', 'y', 'B', '\010', '\372', 'B', '\005', '\212', '\001', '\002', '\020', '\001', 'R', '\013', 'm', 'e', 't', 
+'a', 'd', 'a', 't', 'a', 'K', 'e', 'y', '\022', '#', '\n', '\r', 'd', 'e', 'f', 'a', 'u', 'l', 't', '_', 'v', 'a', 'l', 'u', 'e', 
+'\030', '\003', ' ', '\001', '(', '\t', 'R', '\014', 'd', 'e', 'f', 'a', 'u', 'l', 't', 'V', 'a', 'l', 'u', 'e', '\032', '\264', '\002', '\n', '\010', 
+'M', 'e', 't', 'a', 'D', 'a', 't', 'a', '\022', '.', '\n', '\016', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', '_', 'k', 'e', 
+'y', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\r', 'd', 'e', 's', 'c', 'r', 'i', 'p', 
+'t', 'o', 'r', 'K', 'e', 'y', '\022', 'P', '\n', '\014', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', '_', 'k', 'e', 'y', '\030', '\002', ' ', 
+'\001', '(', '\013', '2', '#', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', 
+'.', 'v', '3', '.', 'M', 'e', 't', 'a', 'd', 'a', 't', 'a', 'K', 'e', 'y', 'B', '\010', '\372', 'B', '\005', '\212', '\001', '\002', '\020', '\001', 
+'R', '\013', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', 'K', 'e', 'y', '\022', '#', '\n', '\r', 'd', 'e', 'f', 'a', 'u', 'l', 't', '_', 
+'v', 'a', 'l', 'u', 'e', '\030', '\003', ' ', '\001', '(', '\t', 'R', '\014', 'd', 'e', 'f', 'a', 'u', 'l', 't', 'V', 'a', 'l', 'u', 'e', 
+'\022', 'Y', '\n', '\006', 's', 'o', 'u', 'r', 'c', 'e', '\030', '\004', ' ', '\001', '(', '\016', '2', '7', '.', 'e', 'n', 'v', 'o', 'y', '.', 
+'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', '.', 'R', 'a', 't', 'e', 'L', 'i', 'm', 'i', 't', 
+'.', 'A', 'c', 't', 'i', 'o', 'n', '.', 'M', 'e', 't', 'a', 'D', 'a', 't', 'a', '.', 'S', 'o', 'u', 'r', 'c', 'e', 'B', '\010', 
+'\372', 'B', '\005', '\202', '\001', '\002', '\020', '\001', 'R', '\006', 's', 'o', 'u', 'r', 'c', 'e', '\"', '&', '\n', '\006', 'S', 'o', 'u', 'r', 'c', 
+'e', '\022', '\013', '\n', '\007', 'D', 'Y', 'N', 'A', 'M', 'I', 'C', '\020', '\000', '\022', '\017', '\n', '\013', 'R', 'O', 'U', 'T', 'E', '_', 'E', 
+'N', 'T', 'R', 'Y', '\020', '\001', ':', '*', '\232', '\305', '\210', '\036', '%', '\n', '#', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 
+'v', '2', '.', 'r', 'o', 'u', 't', 'e', '.', 'R', 'a', 't', 'e', 'L', 'i', 'm', 'i', 't', '.', 'A', 'c', 't', 'i', 'o', 'n', 
+'B', '\027', '\n', '\020', 'a', 'c', 't', 'i', 'o', 'n', '_', 's', 'p', 'e', 'c', 'i', 'f', 'i', 'e', 'r', '\022', '\003', '\370', 'B', '\001', 
+'\032', '\362', '\001', '\n', '\010', 'O', 'v', 'e', 'r', 'r', 'i', 'd', 'e', '\022', 'f', '\n', '\020', 'd', 'y', 'n', 'a', 'm', 'i', 'c', '_', 
+'m', 'e', 't', 'a', 'd', 'a', 't', 'a', '\030', '\001', ' ', '\001', '(', '\013', '2', '9', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 
+'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', '.', 'R', 'a', 't', 'e', 'L', 'i', 'm', 'i', 't', '.', 'O', 
+'v', 'e', 'r', 'r', 'i', 'd', 'e', '.', 'D', 'y', 'n', 'a', 'm', 'i', 'c', 'M', 'e', 't', 'a', 'd', 'a', 't', 'a', 'H', '\000', 
+'R', '\017', 'd', 'y', 'n', 'a', 'm', 'i', 'c', 'M', 'e', 't', 'a', 'd', 'a', 't', 'a', '\032', 'c', '\n', '\017', 'D', 'y', 'n', 'a', 
+'m', 'i', 'c', 'M', 'e', 't', 'a', 'd', 'a', 't', 'a', '\022', 'P', '\n', '\014', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', '_', 'k', 
+'e', 'y', '\030', '\001', ' ', '\001', '(', '\013', '2', '#', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'e', 't', 
+'a', 'd', 'a', 't', 'a', '.', 'v', '3', '.', 'M', 'e', 't', 'a', 'd', 'a', 't', 'a', 'K', 'e', 'y', 'B', '\010', '\372', 'B', '\005', 
+'\212', '\001', '\002', '\020', '\001', 'R', '\013', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', 'K', 'e', 'y', 'B', '\031', '\n', '\022', 'o', 'v', 'e', 
+'r', 'r', 'i', 'd', 'e', '_', 's', 'p', 'e', 'c', 'i', 'f', 'i', 'e', 'r', '\022', '\003', '\370', 'B', '\001', ':', '#', '\232', '\305', '\210', 
+'\036', '\036', '\n', '\034', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'r', 'o', 'u', 't', 'e', '.', 'R', 'a', 
+'t', 'e', 'L', 'i', 'm', 'i', 't', '\"', '\244', '\005', '\n', '\r', 'H', 'e', 'a', 'd', 'e', 'r', 'M', 'a', 't', 'c', 'h', 'e', 'r', 
+'\022', '!', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\r', '\372', 'B', '\n', 'r', '\010', '\020', '\001', '\300', '\001', 
+'\001', '\310', '\001', '\000', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '.', '\n', '\013', 'e', 'x', 'a', 'c', 't', '_', 'm', 'a', 't', 'c', 'h', 
+'\030', '\004', ' ', '\001', '(', '\t', 'B', '\013', '\030', '\001', '\222', '\307', '\206', '\330', '\004', '\003', '3', '.', '0', 'H', '\000', 'R', '\n', 'e', 'x', 
+'a', 'c', 't', 'M', 'a', 't', 'c', 'h', '\022', '\\', '\n', '\020', 's', 'a', 'f', 'e', '_', 'r', 'e', 'g', 'e', 'x', '_', 'm', 'a', 
+'t', 'c', 'h', '\030', '\013', ' ', '\001', '(', '\013', '2', '#', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'a', 
+'t', 'c', 'h', 'e', 'r', '.', 'v', '3', '.', 'R', 'e', 'g', 'e', 'x', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'B', '\013', '\030', '\001', 
+'\222', '\307', '\206', '\330', '\004', '\003', '3', '.', '0', 'H', '\000', 'R', '\016', 's', 'a', 'f', 'e', 'R', 'e', 'g', 'e', 'x', 'M', 'a', 't', 
+'c', 'h', '\022', '<', '\n', '\013', 'r', 'a', 'n', 'g', 'e', '_', 'm', 'a', 't', 'c', 'h', '\030', '\006', ' ', '\001', '(', '\013', '2', '\031', 
+'.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'v', '3', '.', 'I', 'n', 't', '6', '4', 'R', 'a', 'n', 'g', 'e', 
+'H', '\000', 'R', '\n', 'r', 'a', 'n', 'g', 'e', 'M', 'a', 't', 'c', 'h', '\022', '%', '\n', '\r', 'p', 'r', 'e', 's', 'e', 'n', 't', 
+'_', 'm', 'a', 't', 'c', 'h', '\030', '\007', ' ', '\001', '(', '\010', 'H', '\000', 'R', '\014', 'p', 'r', 'e', 's', 'e', 'n', 't', 'M', 'a', 
+'t', 'c', 'h', '\022', '7', '\n', '\014', 'p', 'r', 'e', 'f', 'i', 'x', '_', 'm', 'a', 't', 'c', 'h', '\030', '\t', ' ', '\001', '(', '\t', 
+'B', '\022', '\030', '\001', '\372', 'B', '\004', 'r', '\002', '\020', '\001', '\222', '\307', '\206', '\330', '\004', '\003', '3', '.', '0', 'H', '\000', 'R', '\013', 'p', 
+'r', 'e', 'f', 'i', 'x', 'M', 'a', 't', 'c', 'h', '\022', '7', '\n', '\014', 's', 'u', 'f', 'f', 'i', 'x', '_', 'm', 'a', 't', 'c', 
+'h', '\030', '\n', ' ', '\001', '(', '\t', 'B', '\022', '\030', '\001', '\372', 'B', '\004', 'r', '\002', '\020', '\001', '\222', '\307', '\206', '\330', '\004', '\003', '3', 
+'.', '0', 'H', '\000', 'R', '\013', 's', 'u', 'f', 'f', 'i', 'x', 'M', 'a', 't', 'c', 'h', '\022', ';', '\n', '\016', 'c', 'o', 'n', 't', 
+'a', 'i', 'n', 's', '_', 'm', 'a', 't', 'c', 'h', '\030', '\014', ' ', '\001', '(', '\t', 'B', '\022', '\030', '\001', '\372', 'B', '\004', 'r', '\002', 
+'\020', '\001', '\222', '\307', '\206', '\330', '\004', '\003', '3', '.', '0', 'H', '\000', 'R', '\r', 'c', 'o', 'n', 't', 'a', 'i', 'n', 's', 'M', 'a', 
+'t', 'c', 'h', '\022', 'I', '\n', '\014', 's', 't', 'r', 'i', 'n', 'g', '_', 'm', 'a', 't', 'c', 'h', '\030', '\r', ' ', '\001', '(', '\013', 
+'2', '$', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'a', 't', 'c', 'h', 'e', 'r', '.', 'v', '3', '.', 
+'S', 't', 'r', 'i', 'n', 'g', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'H', '\000', 'R', '\013', 's', 't', 'r', 'i', 'n', 'g', 'M', 'a', 
+'t', 'c', 'h', '\022', '!', '\n', '\014', 'i', 'n', 'v', 'e', 'r', 't', '_', 'm', 'a', 't', 'c', 'h', '\030', '\010', ' ', '\001', '(', '\010', 
+'R', '\013', 'i', 'n', 'v', 'e', 'r', 't', 'M', 'a', 't', 'c', 'h', ':', '\'', '\232', '\305', '\210', '\036', '\"', '\n', ' ', 'e', 'n', 'v', 
+'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'r', 'o', 'u', 't', 'e', '.', 'H', 'e', 'a', 'd', 'e', 'r', 'M', 'a', 't', 
+'c', 'h', 'e', 'r', 'B', '\030', '\n', '\026', 'h', 'e', 'a', 'd', 'e', 'r', '_', 'm', 'a', 't', 'c', 'h', '_', 's', 'p', 'e', 'c', 
+'i', 'f', 'i', 'e', 'r', 'J', '\004', '\010', '\002', '\020', '\003', 'J', '\004', '\010', '\003', '\020', '\004', 'J', '\004', '\010', '\005', '\020', '\006', 'R', '\013', 
+'r', 'e', 'g', 'e', 'x', '_', 'm', 'a', 't', 'c', 'h', '\"', '\241', '\002', '\n', '\025', 'Q', 'u', 'e', 'r', 'y', 'P', 'a', 'r', 'a', 
+'m', 'e', 't', 'e', 'r', 'M', 'a', 't', 'c', 'h', 'e', 'r', '\022', '\036', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', 
+'\t', 'B', '\n', '\372', 'B', '\007', 'r', '\005', '\020', '\001', '(', '\200', '\010', 'R', '\004', 'n', 'a', 'm', 'e', '\022', 'S', '\n', '\014', 's', 't', 
+'r', 'i', 'n', 'g', '_', 'm', 'a', 't', 'c', 'h', '\030', '\005', ' ', '\001', '(', '\013', '2', '$', '.', 'e', 'n', 'v', 'o', 'y', '.', 
+'t', 'y', 'p', 'e', '.', 'm', 'a', 't', 'c', 'h', 'e', 'r', '.', 'v', '3', '.', 'S', 't', 'r', 'i', 'n', 'g', 'M', 'a', 't', 
+'c', 'h', 'e', 'r', 'B', '\010', '\372', 'B', '\005', '\212', '\001', '\002', '\020', '\001', 'H', '\000', 'R', '\013', 's', 't', 'r', 'i', 'n', 'g', 'M', 
+'a', 't', 'c', 'h', '\022', '%', '\n', '\r', 'p', 'r', 'e', 's', 'e', 'n', 't', '_', 'm', 'a', 't', 'c', 'h', '\030', '\006', ' ', '\001', 
+'(', '\010', 'H', '\000', 'R', '\014', 'p', 'r', 'e', 's', 'e', 'n', 't', 'M', 'a', 't', 'c', 'h', ':', '/', '\232', '\305', '\210', '\036', '*', 
+'\n', '(', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'r', 'o', 'u', 't', 'e', '.', 'Q', 'u', 'e', 'r', 
+'y', 'P', 'a', 'r', 'a', 'm', 'e', 't', 'e', 'r', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'B', '!', '\n', '\037', 'q', 'u', 'e', 'r', 
+'y', '_', 'p', 'a', 'r', 'a', 'm', 'e', 't', 'e', 'r', '_', 'm', 'a', 't', 'c', 'h', '_', 's', 'p', 'e', 'c', 'i', 'f', 'i', 
+'e', 'r', 'J', '\004', '\010', '\003', '\020', '\004', 'J', '\004', '\010', '\004', '\020', '\005', 'R', '\005', 'v', 'a', 'l', 'u', 'e', 'R', '\005', 'r', 'e', 
+'g', 'e', 'x', '\"', '\271', '\002', '\n', '\026', 'I', 'n', 't', 'e', 'r', 'n', 'a', 'l', 'R', 'e', 'd', 'i', 'r', 'e', 'c', 't', 'P', 
+'o', 'l', 'i', 'c', 'y', '\022', 'R', '\n', '\026', 'm', 'a', 'x', '_', 'i', 'n', 't', 'e', 'r', 'n', 'a', 'l', '_', 'r', 'e', 'd', 
+'i', 'r', 'e', 'c', 't', 's', '\030', '\001', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 
+'t', 'o', 'b', 'u', 'f', '.', 'U', 'I', 'n', 't', '3', '2', 'V', 'a', 'l', 'u', 'e', 'R', '\024', 'm', 'a', 'x', 'I', 'n', 't', 
+'e', 'r', 'n', 'a', 'l', 'R', 'e', 'd', 'i', 'r', 'e', 'c', 't', 's', '\022', '@', '\n', '\027', 'r', 'e', 'd', 'i', 'r', 'e', 'c', 
+'t', '_', 'r', 'e', 's', 'p', 'o', 'n', 's', 'e', '_', 'c', 'o', 'd', 'e', 's', '\030', '\002', ' ', '\003', '(', '\r', 'B', '\010', '\372', 
+'B', '\005', '\222', '\001', '\002', '\020', '\005', 'R', '\025', 'r', 'e', 'd', 'i', 'r', 'e', 'c', 't', 'R', 'e', 's', 'p', 'o', 'n', 's', 'e', 
+'C', 'o', 'd', 'e', 's', '\022', 'J', '\n', '\n', 'p', 'r', 'e', 'd', 'i', 'c', 'a', 't', 'e', 's', '\030', '\003', ' ', '\003', '(', '\013', 
+'2', '*', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'T', 
+'y', 'p', 'e', 'd', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'C', 'o', 'n', 'f', 'i', 'g', 'R', '\n', 'p', 'r', 'e', 'd', 
+'i', 'c', 'a', 't', 'e', 's', '\022', '=', '\n', '\033', 'a', 'l', 'l', 'o', 'w', '_', 'c', 'r', 'o', 's', 's', '_', 's', 'c', 'h', 
+'e', 'm', 'e', '_', 'r', 'e', 'd', 'i', 'r', 'e', 'c', 't', '\030', '\004', ' ', '\001', '(', '\010', 'R', '\030', 'a', 'l', 'l', 'o', 'w', 
+'C', 'r', 'o', 's', 's', 'S', 'c', 'h', 'e', 'm', 'e', 'R', 'e', 'd', 'i', 'r', 'e', 'c', 't', '\"', ']', '\n', '\014', 'F', 'i', 
+'l', 't', 'e', 'r', 'C', 'o', 'n', 'f', 'i', 'g', '\022', ',', '\n', '\006', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\001', ' ', '\001', '(', 
+'\013', '2', '\024', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'A', 'n', 'y', 'R', '\006', 
+'c', 'o', 'n', 'f', 'i', 'g', '\022', '\037', '\n', '\013', 'i', 's', '_', 'o', 'p', 't', 'i', 'o', 'n', 'a', 'l', '\030', '\002', ' ', '\001', 
+'(', '\010', 'R', '\n', 'i', 's', 'O', 'p', 't', 'i', 'o', 'n', 'a', 'l', 'B', 'E', '\n', '#', 'i', 'o', '.', 'e', 'n', 'v', 'o', 
+'y', 'p', 'r', 'o', 'x', 'y', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', 
+'.', 'v', '3', 'B', '\024', 'R', 'o', 'u', 't', 'e', 'C', 'o', 'm', 'p', 'o', 'n', 'e', 'n', 't', 's', 'P', 'r', 'o', 't', 'o', 
+'P', '\001', '\272', '\200', '\310', '\321', '\006', '\002', '\020', '\002', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', 
 };
 
 static upb_def_init *deps[19] = {
@@ -971,5 +978,5 @@ upb_def_init envoy_config_route_v3_route_components_proto_upbdefinit = {
   deps,
   layouts,
   "envoy/config/route/v3/route_components.proto",
-  UPB_STRVIEW_INIT(descriptor, 20140)
+  UPB_STRVIEW_INIT(descriptor, 20318)
 };
diff --git a/src/core/ext/upbdefs-generated/src/proto/grpc/gcp/altscontext.upbdefs.c b/src/core/ext/upbdefs-generated/src/proto/grpc/gcp/altscontext.upbdefs.c
deleted file mode 100644 (file)
index c4fe57e..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/* This file was generated by upbc (the upb compiler) from the input
- * file:
- *
- *     src/proto/grpc/gcp/altscontext.proto
- *
- * Do not edit -- your changes will be discarded when the file is
- * regenerated. */
-
-#include "upb/def.h"
-#include "src/proto/grpc/gcp/altscontext.upbdefs.h"
-
-extern upb_def_init src_proto_grpc_gcp_transport_security_common_proto_upbdefinit;
-extern const upb_msglayout grpc_gcp_AltsContext_msginit;
-extern const upb_msglayout grpc_gcp_AltsContext_PeerAttributesEntry_msginit;
-
-static const upb_msglayout *layouts[2] = {
-  &grpc_gcp_AltsContext_msginit,
-  &grpc_gcp_AltsContext_PeerAttributesEntry_msginit,
-};
-
-static const char descriptor[718] = {'\n', '$', 's', 'r', 'c', '/', 'p', 'r', 'o', 't', 'o', '/', 'g', 'r', 'p', 'c', '/', 'g', 'c', 'p', '/', 'a', 'l', 't', 's', 
-'c', 'o', 'n', 't', 'e', 'x', 't', '.', 'p', 'r', 'o', 't', 'o', '\022', '\010', 'g', 'r', 'p', 'c', '.', 'g', 'c', 'p', '\032', '2', 
-'s', 'r', 'c', '/', 'p', 'r', 'o', 't', 'o', '/', 'g', 'r', 'p', 'c', '/', 'g', 'c', 'p', '/', 't', 'r', 'a', 'n', 's', 'p', 
-'o', 'r', 't', '_', 's', 'e', 'c', 'u', 'r', 'i', 't', 'y', '_', 'c', 'o', 'm', 'm', 'o', 'n', '.', 'p', 'r', 'o', 't', 'o', 
-'\"', '\361', '\003', '\n', '\013', 'A', 'l', 't', 's', 'C', 'o', 'n', 't', 'e', 'x', 't', '\022', '1', '\n', '\024', 'a', 'p', 'p', 'l', 'i', 
-'c', 'a', 't', 'i', 'o', 'n', '_', 'p', 'r', 'o', 't', 'o', 'c', 'o', 'l', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\023', 'a', 'p', 
-'p', 'l', 'i', 'c', 'a', 't', 'i', 'o', 'n', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', '\022', '\'', '\n', '\017', 'r', 'e', 'c', 'o', 
-'r', 'd', '_', 'p', 'r', 'o', 't', 'o', 'c', 'o', 'l', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\016', 'r', 'e', 'c', 'o', 'r', 'd', 
-'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', '\022', '>', '\n', '\016', 's', 'e', 'c', 'u', 'r', 'i', 't', 'y', '_', 'l', 'e', 'v', 'e', 
-'l', '\030', '\003', ' ', '\001', '(', '\016', '2', '\027', '.', 'g', 'r', 'p', 'c', '.', 'g', 'c', 'p', '.', 'S', 'e', 'c', 'u', 'r', 'i', 
-'t', 'y', 'L', 'e', 'v', 'e', 'l', 'R', '\r', 's', 'e', 'c', 'u', 'r', 'i', 't', 'y', 'L', 'e', 'v', 'e', 'l', '\022', '0', '\n', 
-'\024', 'p', 'e', 'e', 'r', '_', 's', 'e', 'r', 'v', 'i', 'c', 'e', '_', 'a', 'c', 'c', 'o', 'u', 'n', 't', '\030', '\004', ' ', '\001', 
-'(', '\t', 'R', '\022', 'p', 'e', 'e', 'r', 'S', 'e', 'r', 'v', 'i', 'c', 'e', 'A', 'c', 'c', 'o', 'u', 'n', 't', '\022', '2', '\n', 
-'\025', 'l', 'o', 'c', 'a', 'l', '_', 's', 'e', 'r', 'v', 'i', 'c', 'e', '_', 'a', 'c', 'c', 'o', 'u', 'n', 't', '\030', '\005', ' ', 
-'\001', '(', '\t', 'R', '\023', 'l', 'o', 'c', 'a', 'l', 'S', 'e', 'r', 'v', 'i', 'c', 'e', 'A', 'c', 'c', 'o', 'u', 'n', 't', '\022', 
-'I', '\n', '\021', 'p', 'e', 'e', 'r', '_', 'r', 'p', 'c', '_', 'v', 'e', 'r', 's', 'i', 'o', 'n', 's', '\030', '\006', ' ', '\001', '(', 
-'\013', '2', '\035', '.', 'g', 'r', 'p', 'c', '.', 'g', 'c', 'p', '.', 'R', 'p', 'c', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'V', 
-'e', 'r', 's', 'i', 'o', 'n', 's', 'R', '\017', 'p', 'e', 'e', 'r', 'R', 'p', 'c', 'V', 'e', 'r', 's', 'i', 'o', 'n', 's', '\022', 
-'R', '\n', '\017', 'p', 'e', 'e', 'r', '_', 'a', 't', 't', 'r', 'i', 'b', 'u', 't', 'e', 's', '\030', '\007', ' ', '\003', '(', '\013', '2', 
-')', '.', 'g', 'r', 'p', 'c', '.', 'g', 'c', 'p', '.', 'A', 'l', 't', 's', 'C', 'o', 'n', 't', 'e', 'x', 't', '.', 'P', 'e', 
-'e', 'r', 'A', 't', 't', 'r', 'i', 'b', 'u', 't', 'e', 's', 'E', 'n', 't', 'r', 'y', 'R', '\016', 'p', 'e', 'e', 'r', 'A', 't', 
-'t', 'r', 'i', 'b', 'u', 't', 'e', 's', '\032', 'A', '\n', '\023', 'P', 'e', 'e', 'r', 'A', 't', 't', 'r', 'i', 'b', 'u', 't', 'e', 
-'s', 'E', 'n', 't', 'r', 'y', '\022', '\020', '\n', '\003', 'k', 'e', 'y', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\003', 'k', 'e', 'y', '\022', 
-'\024', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\005', 'v', 'a', 'l', 'u', 'e', ':', '\002', '8', '\001', 
-'B', 'l', '\n', '\025', 'i', 'o', '.', 'g', 'r', 'p', 'c', '.', 'a', 'l', 't', 's', '.', 'i', 'n', 't', 'e', 'r', 'n', 'a', 'l', 
-'B', '\020', 'A', 'l', 't', 's', 'C', 'o', 'n', 't', 'e', 'x', 't', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', '?', 'g', 'o', 'o', 
-'g', 'l', 'e', '.', 'g', 'o', 'l', 'a', 'n', 'g', '.', 'o', 'r', 'g', '/', 'g', 'r', 'p', 'c', '/', 'c', 'r', 'e', 'd', 'e', 
-'n', 't', 'i', 'a', 'l', 's', '/', 'a', 'l', 't', 's', '/', 'i', 'n', 't', 'e', 'r', 'n', 'a', 'l', '/', 'p', 'r', 'o', 't', 
-'o', '/', 'g', 'r', 'p', 'c', '_', 'g', 'c', 'p', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', 
-};
-
-static upb_def_init *deps[2] = {
-  &src_proto_grpc_gcp_transport_security_common_proto_upbdefinit,
-  NULL
-};
-
-upb_def_init src_proto_grpc_gcp_altscontext_proto_upbdefinit = {
-  deps,
-  layouts,
-  "src/proto/grpc/gcp/altscontext.proto",
-  UPB_STRVIEW_INIT(descriptor, 718)
-};
diff --git a/src/core/ext/upbdefs-generated/src/proto/grpc/gcp/altscontext.upbdefs.h b/src/core/ext/upbdefs-generated/src/proto/grpc/gcp/altscontext.upbdefs.h
deleted file mode 100644 (file)
index 6c4d611..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/* This file was generated by upbc (the upb compiler) from the input
- * file:
- *
- *     src/proto/grpc/gcp/altscontext.proto
- *
- * Do not edit -- your changes will be discarded when the file is
- * regenerated. */
-
-#ifndef SRC_PROTO_GRPC_GCP_ALTSCONTEXT_PROTO_UPBDEFS_H_
-#define SRC_PROTO_GRPC_GCP_ALTSCONTEXT_PROTO_UPBDEFS_H_
-
-#include "upb/def.h"
-#include "upb/port_def.inc"
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "upb/def.h"
-
-#include "upb/port_def.inc"
-
-extern upb_def_init src_proto_grpc_gcp_altscontext_proto_upbdefinit;
-
-UPB_INLINE const upb_msgdef *grpc_gcp_AltsContext_getmsgdef(upb_symtab *s) {
-  _upb_symtab_loaddefinit(s, &src_proto_grpc_gcp_altscontext_proto_upbdefinit);
-  return upb_symtab_lookupmsg(s, "grpc.gcp.AltsContext");
-}
-
-UPB_INLINE const upb_msgdef *grpc_gcp_AltsContext_PeerAttributesEntry_getmsgdef(upb_symtab *s) {
-  _upb_symtab_loaddefinit(s, &src_proto_grpc_gcp_altscontext_proto_upbdefinit);
-  return upb_symtab_lookupmsg(s, "grpc.gcp.AltsContext.PeerAttributesEntry");
-}
-
-#ifdef __cplusplus
-}  /* extern "C" */
-#endif
-
-#include "upb/port_undef.inc"
-
-#endif  /* SRC_PROTO_GRPC_GCP_ALTSCONTEXT_PROTO_UPBDEFS_H_ */
diff --git a/src/core/ext/upbdefs-generated/src/proto/grpc/gcp/handshaker.upbdefs.c b/src/core/ext/upbdefs-generated/src/proto/grpc/gcp/handshaker.upbdefs.c
deleted file mode 100644 (file)
index e2f6945..0000000
+++ /dev/null
@@ -1,176 +0,0 @@
-/* This file was generated by upbc (the upb compiler) from the input
- * file:
- *
- *     src/proto/grpc/gcp/handshaker.proto
- *
- * Do not edit -- your changes will be discarded when the file is
- * regenerated. */
-
-#include "upb/def.h"
-#include "src/proto/grpc/gcp/handshaker.upbdefs.h"
-
-extern upb_def_init src_proto_grpc_gcp_transport_security_common_proto_upbdefinit;
-extern const upb_msglayout grpc_gcp_Endpoint_msginit;
-extern const upb_msglayout grpc_gcp_Identity_msginit;
-extern const upb_msglayout grpc_gcp_Identity_AttributesEntry_msginit;
-extern const upb_msglayout grpc_gcp_StartClientHandshakeReq_msginit;
-extern const upb_msglayout grpc_gcp_ServerHandshakeParameters_msginit;
-extern const upb_msglayout grpc_gcp_StartServerHandshakeReq_msginit;
-extern const upb_msglayout grpc_gcp_StartServerHandshakeReq_HandshakeParametersEntry_msginit;
-extern const upb_msglayout grpc_gcp_NextHandshakeMessageReq_msginit;
-extern const upb_msglayout grpc_gcp_HandshakerReq_msginit;
-extern const upb_msglayout grpc_gcp_HandshakerResult_msginit;
-extern const upb_msglayout grpc_gcp_HandshakerStatus_msginit;
-extern const upb_msglayout grpc_gcp_HandshakerResp_msginit;
-
-static const upb_msglayout *layouts[12] = {
-  &grpc_gcp_Endpoint_msginit,
-  &grpc_gcp_Identity_msginit,
-  &grpc_gcp_Identity_AttributesEntry_msginit,
-  &grpc_gcp_StartClientHandshakeReq_msginit,
-  &grpc_gcp_ServerHandshakeParameters_msginit,
-  &grpc_gcp_StartServerHandshakeReq_msginit,
-  &grpc_gcp_StartServerHandshakeReq_HandshakeParametersEntry_msginit,
-  &grpc_gcp_NextHandshakeMessageReq_msginit,
-  &grpc_gcp_HandshakerReq_msginit,
-  &grpc_gcp_HandshakerResult_msginit,
-  &grpc_gcp_HandshakerStatus_msginit,
-  &grpc_gcp_HandshakerResp_msginit,
-};
-
-static const char descriptor[3053] = {'\n', '#', 's', 'r', 'c', '/', 'p', 'r', 'o', 't', 'o', '/', 'g', 'r', 'p', 'c', '/', 'g', 'c', 'p', '/', 'h', 'a', 'n', 'd', 
-'s', 'h', 'a', 'k', 'e', 'r', '.', 'p', 'r', 'o', 't', 'o', '\022', '\010', 'g', 'r', 'p', 'c', '.', 'g', 'c', 'p', '\032', '2', 's', 
-'r', 'c', '/', 'p', 'r', 'o', 't', 'o', '/', 'g', 'r', 'p', 'c', '/', 'g', 'c', 'p', '/', 't', 'r', 'a', 'n', 's', 'p', 'o', 
-'r', 't', '_', 's', 'e', 'c', 'u', 'r', 'i', 't', 'y', '_', 'c', 'o', 'm', 'm', 'o', 'n', '.', 'p', 'r', 'o', 't', 'o', '\"', 
-'t', '\n', '\010', 'E', 'n', 'd', 'p', 'o', 'i', 'n', 't', '\022', '\035', '\n', '\n', 'i', 'p', '_', 'a', 'd', 'd', 'r', 'e', 's', 's', 
-'\030', '\001', ' ', '\001', '(', '\t', 'R', '\t', 'i', 'p', 'A', 'd', 'd', 'r', 'e', 's', 's', '\022', '\022', '\n', '\004', 'p', 'o', 'r', 't', 
-'\030', '\002', ' ', '\001', '(', '\005', 'R', '\004', 'p', 'o', 'r', 't', '\022', '5', '\n', '\010', 'p', 'r', 'o', 't', 'o', 'c', 'o', 'l', '\030', 
-'\003', ' ', '\001', '(', '\016', '2', '\031', '.', 'g', 'r', 'p', 'c', '.', 'g', 'c', 'p', '.', 'N', 'e', 't', 'w', 'o', 'r', 'k', 'P', 
-'r', 'o', 't', 'o', 'c', 'o', 'l', 'R', '\010', 'p', 'r', 'o', 't', 'o', 'c', 'o', 'l', '\"', '\350', '\001', '\n', '\010', 'I', 'd', 'e', 
-'n', 't', 'i', 't', 'y', '\022', ')', '\n', '\017', 's', 'e', 'r', 'v', 'i', 'c', 'e', '_', 'a', 'c', 'c', 'o', 'u', 'n', 't', '\030', 
-'\001', ' ', '\001', '(', '\t', 'H', '\000', 'R', '\016', 's', 'e', 'r', 'v', 'i', 'c', 'e', 'A', 'c', 'c', 'o', 'u', 'n', 't', '\022', '\034', 
-'\n', '\010', 'h', 'o', 's', 't', 'n', 'a', 'm', 'e', '\030', '\002', ' ', '\001', '(', '\t', 'H', '\000', 'R', '\010', 'h', 'o', 's', 't', 'n', 
-'a', 'm', 'e', '\022', 'B', '\n', '\n', 'a', 't', 't', 'r', 'i', 'b', 'u', 't', 'e', 's', '\030', '\003', ' ', '\003', '(', '\013', '2', '\"', 
-'.', 'g', 'r', 'p', 'c', '.', 'g', 'c', 'p', '.', 'I', 'd', 'e', 'n', 't', 'i', 't', 'y', '.', 'A', 't', 't', 'r', 'i', 'b', 
-'u', 't', 'e', 's', 'E', 'n', 't', 'r', 'y', 'R', '\n', 'a', 't', 't', 'r', 'i', 'b', 'u', 't', 'e', 's', '\032', '=', '\n', '\017', 
-'A', 't', 't', 'r', 'i', 'b', 'u', 't', 'e', 's', 'E', 'n', 't', 'r', 'y', '\022', '\020', '\n', '\003', 'k', 'e', 'y', '\030', '\001', ' ', 
-'\001', '(', '\t', 'R', '\003', 'k', 'e', 'y', '\022', '\024', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\005', 
-'v', 'a', 'l', 'u', 'e', ':', '\002', '8', '\001', 'B', '\020', '\n', '\016', 'i', 'd', 'e', 'n', 't', 'i', 't', 'y', '_', 'o', 'n', 'e', 
-'o', 'f', '\"', '\323', '\004', '\n', '\027', 'S', 't', 'a', 'r', 't', 'C', 'l', 'i', 'e', 'n', 't', 'H', 'a', 'n', 'd', 's', 'h', 'a', 
-'k', 'e', 'R', 'e', 'q', '\022', '[', '\n', '\033', 'h', 'a', 'n', 'd', 's', 'h', 'a', 'k', 'e', '_', 's', 'e', 'c', 'u', 'r', 'i', 
-'t', 'y', '_', 'p', 'r', 'o', 't', 'o', 'c', 'o', 'l', '\030', '\001', ' ', '\001', '(', '\016', '2', '\033', '.', 'g', 'r', 'p', 'c', '.', 
-'g', 'c', 'p', '.', 'H', 'a', 'n', 'd', 's', 'h', 'a', 'k', 'e', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'R', '\031', 'h', 'a', 
-'n', 'd', 's', 'h', 'a', 'k', 'e', 'S', 'e', 'c', 'u', 'r', 'i', 't', 'y', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', '\022', '3', 
-'\n', '\025', 'a', 'p', 'p', 'l', 'i', 'c', 'a', 't', 'i', 'o', 'n', '_', 'p', 'r', 'o', 't', 'o', 'c', 'o', 'l', 's', '\030', '\002', 
-' ', '\003', '(', '\t', 'R', '\024', 'a', 'p', 'p', 'l', 'i', 'c', 'a', 't', 'i', 'o', 'n', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 
-'s', '\022', ')', '\n', '\020', 'r', 'e', 'c', 'o', 'r', 'd', '_', 'p', 'r', 'o', 't', 'o', 'c', 'o', 'l', 's', '\030', '\003', ' ', '\003', 
-'(', '\t', 'R', '\017', 'r', 'e', 'c', 'o', 'r', 'd', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 's', '\022', '?', '\n', '\021', 't', 'a', 
-'r', 'g', 'e', 't', '_', 'i', 'd', 'e', 'n', 't', 'i', 't', 'i', 'e', 's', '\030', '\004', ' ', '\003', '(', '\013', '2', '\022', '.', 'g', 
-'r', 'p', 'c', '.', 'g', 'c', 'p', '.', 'I', 'd', 'e', 'n', 't', 'i', 't', 'y', 'R', '\020', 't', 'a', 'r', 'g', 'e', 't', 'I', 
-'d', 'e', 'n', 't', 'i', 't', 'i', 'e', 's', '\022', '9', '\n', '\016', 'l', 'o', 'c', 'a', 'l', '_', 'i', 'd', 'e', 'n', 't', 'i', 
-'t', 'y', '\030', '\005', ' ', '\001', '(', '\013', '2', '\022', '.', 'g', 'r', 'p', 'c', '.', 'g', 'c', 'p', '.', 'I', 'd', 'e', 'n', 't', 
-'i', 't', 'y', 'R', '\r', 'l', 'o', 'c', 'a', 'l', 'I', 'd', 'e', 'n', 't', 'i', 't', 'y', '\022', '9', '\n', '\016', 'l', 'o', 'c', 
-'a', 'l', '_', 'e', 'n', 'd', 'p', 'o', 'i', 'n', 't', '\030', '\006', ' ', '\001', '(', '\013', '2', '\022', '.', 'g', 'r', 'p', 'c', '.', 
-'g', 'c', 'p', '.', 'E', 'n', 'd', 'p', 'o', 'i', 'n', 't', 'R', '\r', 'l', 'o', 'c', 'a', 'l', 'E', 'n', 'd', 'p', 'o', 'i', 
-'n', 't', '\022', ';', '\n', '\017', 'r', 'e', 'm', 'o', 't', 'e', '_', 'e', 'n', 'd', 'p', 'o', 'i', 'n', 't', '\030', '\007', ' ', '\001', 
-'(', '\013', '2', '\022', '.', 'g', 'r', 'p', 'c', '.', 'g', 'c', 'p', '.', 'E', 'n', 'd', 'p', 'o', 'i', 'n', 't', 'R', '\016', 'r', 
-'e', 'm', 'o', 't', 'e', 'E', 'n', 'd', 'p', 'o', 'i', 'n', 't', '\022', '\037', '\n', '\013', 't', 'a', 'r', 'g', 'e', 't', '_', 'n', 
-'a', 'm', 'e', '\030', '\010', ' ', '\001', '(', '\t', 'R', '\n', 't', 'a', 'r', 'g', 'e', 't', 'N', 'a', 'm', 'e', '\022', '@', '\n', '\014', 
-'r', 'p', 'c', '_', 'v', 'e', 'r', 's', 'i', 'o', 'n', 's', '\030', '\t', ' ', '\001', '(', '\013', '2', '\035', '.', 'g', 'r', 'p', 'c', 
-'.', 'g', 'c', 'p', '.', 'R', 'p', 'c', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'V', 'e', 'r', 's', 'i', 'o', 'n', 's', 'R', 
-'\013', 'r', 'p', 'c', 'V', 'e', 'r', 's', 'i', 'o', 'n', 's', '\022', '$', '\n', '\016', 'm', 'a', 'x', '_', 'f', 'r', 'a', 'm', 'e', 
-'_', 's', 'i', 'z', 'e', '\030', '\n', ' ', '\001', '(', '\r', 'R', '\014', 'm', 'a', 'x', 'F', 'r', 'a', 'm', 'e', 'S', 'i', 'z', 'e', 
-'\"', '\205', '\001', '\n', '\031', 'S', 'e', 'r', 'v', 'e', 'r', 'H', 'a', 'n', 'd', 's', 'h', 'a', 'k', 'e', 'P', 'a', 'r', 'a', 'm', 
-'e', 't', 'e', 'r', 's', '\022', ')', '\n', '\020', 'r', 'e', 'c', 'o', 'r', 'd', '_', 'p', 'r', 'o', 't', 'o', 'c', 'o', 'l', 's', 
-'\030', '\001', ' ', '\003', '(', '\t', 'R', '\017', 'r', 'e', 'c', 'o', 'r', 'd', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 's', '\022', '=', 
-'\n', '\020', 'l', 'o', 'c', 'a', 'l', '_', 'i', 'd', 'e', 'n', 't', 'i', 't', 'i', 'e', 's', '\030', '\002', ' ', '\003', '(', '\013', '2', 
-'\022', '.', 'g', 'r', 'p', 'c', '.', 'g', 'c', 'p', '.', 'I', 'd', 'e', 'n', 't', 'i', 't', 'y', 'R', '\017', 'l', 'o', 'c', 'a', 
-'l', 'I', 'd', 'e', 'n', 't', 'i', 't', 'i', 'e', 's', '\"', '\245', '\004', '\n', '\027', 'S', 't', 'a', 'r', 't', 'S', 'e', 'r', 'v', 
-'e', 'r', 'H', 'a', 'n', 'd', 's', 'h', 'a', 'k', 'e', 'R', 'e', 'q', '\022', '3', '\n', '\025', 'a', 'p', 'p', 'l', 'i', 'c', 'a', 
-'t', 'i', 'o', 'n', '_', 'p', 'r', 'o', 't', 'o', 'c', 'o', 'l', 's', '\030', '\001', ' ', '\003', '(', '\t', 'R', '\024', 'a', 'p', 'p', 
-'l', 'i', 'c', 'a', 't', 'i', 'o', 'n', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 's', '\022', 'm', '\n', '\024', 'h', 'a', 'n', 'd', 
-'s', 'h', 'a', 'k', 'e', '_', 'p', 'a', 'r', 'a', 'm', 'e', 't', 'e', 'r', 's', '\030', '\002', ' ', '\003', '(', '\013', '2', ':', '.', 
-'g', 'r', 'p', 'c', '.', 'g', 'c', 'p', '.', 'S', 't', 'a', 'r', 't', 'S', 'e', 'r', 'v', 'e', 'r', 'H', 'a', 'n', 'd', 's', 
-'h', 'a', 'k', 'e', 'R', 'e', 'q', '.', 'H', 'a', 'n', 'd', 's', 'h', 'a', 'k', 'e', 'P', 'a', 'r', 'a', 'm', 'e', 't', 'e', 
-'r', 's', 'E', 'n', 't', 'r', 'y', 'R', '\023', 'h', 'a', 'n', 'd', 's', 'h', 'a', 'k', 'e', 'P', 'a', 'r', 'a', 'm', 'e', 't', 
-'e', 'r', 's', '\022', '\031', '\n', '\010', 'i', 'n', '_', 'b', 'y', 't', 'e', 's', '\030', '\003', ' ', '\001', '(', '\014', 'R', '\007', 'i', 'n', 
-'B', 'y', 't', 'e', 's', '\022', '9', '\n', '\016', 'l', 'o', 'c', 'a', 'l', '_', 'e', 'n', 'd', 'p', 'o', 'i', 'n', 't', '\030', '\004', 
-' ', '\001', '(', '\013', '2', '\022', '.', 'g', 'r', 'p', 'c', '.', 'g', 'c', 'p', '.', 'E', 'n', 'd', 'p', 'o', 'i', 'n', 't', 'R', 
-'\r', 'l', 'o', 'c', 'a', 'l', 'E', 'n', 'd', 'p', 'o', 'i', 'n', 't', '\022', ';', '\n', '\017', 'r', 'e', 'm', 'o', 't', 'e', '_', 
-'e', 'n', 'd', 'p', 'o', 'i', 'n', 't', '\030', '\005', ' ', '\001', '(', '\013', '2', '\022', '.', 'g', 'r', 'p', 'c', '.', 'g', 'c', 'p', 
-'.', 'E', 'n', 'd', 'p', 'o', 'i', 'n', 't', 'R', '\016', 'r', 'e', 'm', 'o', 't', 'e', 'E', 'n', 'd', 'p', 'o', 'i', 'n', 't', 
-'\022', '@', '\n', '\014', 'r', 'p', 'c', '_', 'v', 'e', 'r', 's', 'i', 'o', 'n', 's', '\030', '\006', ' ', '\001', '(', '\013', '2', '\035', '.', 
-'g', 'r', 'p', 'c', '.', 'g', 'c', 'p', '.', 'R', 'p', 'c', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'V', 'e', 'r', 's', 'i', 
-'o', 'n', 's', 'R', '\013', 'r', 'p', 'c', 'V', 'e', 'r', 's', 'i', 'o', 'n', 's', '\022', '$', '\n', '\016', 'm', 'a', 'x', '_', 'f', 
-'r', 'a', 'm', 'e', '_', 's', 'i', 'z', 'e', '\030', '\007', ' ', '\001', '(', '\r', 'R', '\014', 'm', 'a', 'x', 'F', 'r', 'a', 'm', 'e', 
-'S', 'i', 'z', 'e', '\032', 'k', '\n', '\030', 'H', 'a', 'n', 'd', 's', 'h', 'a', 'k', 'e', 'P', 'a', 'r', 'a', 'm', 'e', 't', 'e', 
-'r', 's', 'E', 'n', 't', 'r', 'y', '\022', '\020', '\n', '\003', 'k', 'e', 'y', '\030', '\001', ' ', '\001', '(', '\005', 'R', '\003', 'k', 'e', 'y', 
-'\022', '9', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\001', '(', '\013', '2', '#', '.', 'g', 'r', 'p', 'c', '.', 'g', 'c', 
-'p', '.', 'S', 'e', 'r', 'v', 'e', 'r', 'H', 'a', 'n', 'd', 's', 'h', 'a', 'k', 'e', 'P', 'a', 'r', 'a', 'm', 'e', 't', 'e', 
-'r', 's', 'R', '\005', 'v', 'a', 'l', 'u', 'e', ':', '\002', '8', '\001', '\"', '4', '\n', '\027', 'N', 'e', 'x', 't', 'H', 'a', 'n', 'd', 
-'s', 'h', 'a', 'k', 'e', 'M', 'e', 's', 's', 'a', 'g', 'e', 'R', 'e', 'q', '\022', '\031', '\n', '\010', 'i', 'n', '_', 'b', 'y', 't', 
-'e', 's', '\030', '\001', ' ', '\001', '(', '\014', 'R', '\007', 'i', 'n', 'B', 'y', 't', 'e', 's', '\"', '\345', '\001', '\n', '\r', 'H', 'a', 'n', 
-'d', 's', 'h', 'a', 'k', 'e', 'r', 'R', 'e', 'q', '\022', 'F', '\n', '\014', 'c', 'l', 'i', 'e', 'n', 't', '_', 's', 't', 'a', 'r', 
-'t', '\030', '\001', ' ', '\001', '(', '\013', '2', '!', '.', 'g', 'r', 'p', 'c', '.', 'g', 'c', 'p', '.', 'S', 't', 'a', 'r', 't', 'C', 
-'l', 'i', 'e', 'n', 't', 'H', 'a', 'n', 'd', 's', 'h', 'a', 'k', 'e', 'R', 'e', 'q', 'H', '\000', 'R', '\013', 'c', 'l', 'i', 'e', 
-'n', 't', 'S', 't', 'a', 'r', 't', '\022', 'F', '\n', '\014', 's', 'e', 'r', 'v', 'e', 'r', '_', 's', 't', 'a', 'r', 't', '\030', '\002', 
-' ', '\001', '(', '\013', '2', '!', '.', 'g', 'r', 'p', 'c', '.', 'g', 'c', 'p', '.', 'S', 't', 'a', 'r', 't', 'S', 'e', 'r', 'v', 
-'e', 'r', 'H', 'a', 'n', 'd', 's', 'h', 'a', 'k', 'e', 'R', 'e', 'q', 'H', '\000', 'R', '\013', 's', 'e', 'r', 'v', 'e', 'r', 'S', 
-'t', 'a', 'r', 't', '\022', '7', '\n', '\004', 'n', 'e', 'x', 't', '\030', '\003', ' ', '\001', '(', '\013', '2', '!', '.', 'g', 'r', 'p', 'c', 
-'.', 'g', 'c', 'p', '.', 'N', 'e', 'x', 't', 'H', 'a', 'n', 'd', 's', 'h', 'a', 'k', 'e', 'M', 'e', 's', 's', 'a', 'g', 'e', 
-'R', 'e', 'q', 'H', '\000', 'R', '\004', 'n', 'e', 'x', 't', 'B', '\013', '\n', '\t', 'r', 'e', 'q', '_', 'o', 'n', 'e', 'o', 'f', '\"', 
-'\232', '\003', '\n', '\020', 'H', 'a', 'n', 'd', 's', 'h', 'a', 'k', 'e', 'r', 'R', 'e', 's', 'u', 'l', 't', '\022', '1', '\n', '\024', 'a', 
-'p', 'p', 'l', 'i', 'c', 'a', 't', 'i', 'o', 'n', '_', 'p', 'r', 'o', 't', 'o', 'c', 'o', 'l', '\030', '\001', ' ', '\001', '(', '\t', 
-'R', '\023', 'a', 'p', 'p', 'l', 'i', 'c', 'a', 't', 'i', 'o', 'n', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', '\022', '\'', '\n', '\017', 
-'r', 'e', 'c', 'o', 'r', 'd', '_', 'p', 'r', 'o', 't', 'o', 'c', 'o', 'l', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\016', 'r', 'e', 
-'c', 'o', 'r', 'd', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', '\022', '\031', '\n', '\010', 'k', 'e', 'y', '_', 'd', 'a', 't', 'a', '\030', 
-'\003', ' ', '\001', '(', '\014', 'R', '\007', 'k', 'e', 'y', 'D', 'a', 't', 'a', '\022', '7', '\n', '\r', 'p', 'e', 'e', 'r', '_', 'i', 'd', 
-'e', 'n', 't', 'i', 't', 'y', '\030', '\004', ' ', '\001', '(', '\013', '2', '\022', '.', 'g', 'r', 'p', 'c', '.', 'g', 'c', 'p', '.', 'I', 
-'d', 'e', 'n', 't', 'i', 't', 'y', 'R', '\014', 'p', 'e', 'e', 'r', 'I', 'd', 'e', 'n', 't', 'i', 't', 'y', '\022', '9', '\n', '\016', 
-'l', 'o', 'c', 'a', 'l', '_', 'i', 'd', 'e', 'n', 't', 'i', 't', 'y', '\030', '\005', ' ', '\001', '(', '\013', '2', '\022', '.', 'g', 'r', 
-'p', 'c', '.', 'g', 'c', 'p', '.', 'I', 'd', 'e', 'n', 't', 'i', 't', 'y', 'R', '\r', 'l', 'o', 'c', 'a', 'l', 'I', 'd', 'e', 
-'n', 't', 'i', 't', 'y', '\022', '*', '\n', '\021', 'k', 'e', 'e', 'p', '_', 'c', 'h', 'a', 'n', 'n', 'e', 'l', '_', 'o', 'p', 'e', 
-'n', '\030', '\006', ' ', '\001', '(', '\010', 'R', '\017', 'k', 'e', 'e', 'p', 'C', 'h', 'a', 'n', 'n', 'e', 'l', 'O', 'p', 'e', 'n', '\022', 
-'I', '\n', '\021', 'p', 'e', 'e', 'r', '_', 'r', 'p', 'c', '_', 'v', 'e', 'r', 's', 'i', 'o', 'n', 's', '\030', '\007', ' ', '\001', '(', 
-'\013', '2', '\035', '.', 'g', 'r', 'p', 'c', '.', 'g', 'c', 'p', '.', 'R', 'p', 'c', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'V', 
-'e', 'r', 's', 'i', 'o', 'n', 's', 'R', '\017', 'p', 'e', 'e', 'r', 'R', 'p', 'c', 'V', 'e', 'r', 's', 'i', 'o', 'n', 's', '\022', 
-'$', '\n', '\016', 'm', 'a', 'x', '_', 'f', 'r', 'a', 'm', 'e', '_', 's', 'i', 'z', 'e', '\030', '\010', ' ', '\001', '(', '\r', 'R', '\014', 
-'m', 'a', 'x', 'F', 'r', 'a', 'm', 'e', 'S', 'i', 'z', 'e', '\"', '@', '\n', '\020', 'H', 'a', 'n', 'd', 's', 'h', 'a', 'k', 'e', 
-'r', 'S', 't', 'a', 't', 'u', 's', '\022', '\022', '\n', '\004', 'c', 'o', 'd', 'e', '\030', '\001', ' ', '\001', '(', '\r', 'R', '\004', 'c', 'o', 
-'d', 'e', '\022', '\030', '\n', '\007', 'd', 'e', 't', 'a', 'i', 'l', 's', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\007', 'd', 'e', 't', 'a', 
-'i', 'l', 's', '\"', '\276', '\001', '\n', '\016', 'H', 'a', 'n', 'd', 's', 'h', 'a', 'k', 'e', 'r', 'R', 'e', 's', 'p', '\022', '\035', '\n', 
-'\n', 'o', 'u', 't', '_', 'f', 'r', 'a', 'm', 'e', 's', '\030', '\001', ' ', '\001', '(', '\014', 'R', '\t', 'o', 'u', 't', 'F', 'r', 'a', 
-'m', 'e', 's', '\022', '%', '\n', '\016', 'b', 'y', 't', 'e', 's', '_', 'c', 'o', 'n', 's', 'u', 'm', 'e', 'd', '\030', '\002', ' ', '\001', 
-'(', '\r', 'R', '\r', 'b', 'y', 't', 'e', 's', 'C', 'o', 'n', 's', 'u', 'm', 'e', 'd', '\022', '2', '\n', '\006', 'r', 'e', 's', 'u', 
-'l', 't', '\030', '\003', ' ', '\001', '(', '\013', '2', '\032', '.', 'g', 'r', 'p', 'c', '.', 'g', 'c', 'p', '.', 'H', 'a', 'n', 'd', 's', 
-'h', 'a', 'k', 'e', 'r', 'R', 'e', 's', 'u', 'l', 't', 'R', '\006', 'r', 'e', 's', 'u', 'l', 't', '\022', '2', '\n', '\006', 's', 't', 
-'a', 't', 'u', 's', '\030', '\004', ' ', '\001', '(', '\013', '2', '\032', '.', 'g', 'r', 'p', 'c', '.', 'g', 'c', 'p', '.', 'H', 'a', 'n', 
-'d', 's', 'h', 'a', 'k', 'e', 'r', 'S', 't', 'a', 't', 'u', 's', 'R', '\006', 's', 't', 'a', 't', 'u', 's', '*', 'J', '\n', '\021', 
-'H', 'a', 'n', 'd', 's', 'h', 'a', 'k', 'e', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', '\022', '\"', '\n', '\036', 'H', 'A', 'N', 'D', 
-'S', 'H', 'A', 'K', 'E', '_', 'P', 'R', 'O', 'T', 'O', 'C', 'O', 'L', '_', 'U', 'N', 'S', 'P', 'E', 'C', 'I', 'F', 'I', 'E', 
-'D', '\020', '\000', '\022', '\007', '\n', '\003', 'T', 'L', 'S', '\020', '\001', '\022', '\010', '\n', '\004', 'A', 'L', 'T', 'S', '\020', '\002', '*', 'E', '\n', 
-'\017', 'N', 'e', 't', 'w', 'o', 'r', 'k', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', '\022', ' ', '\n', '\034', 'N', 'E', 'T', 'W', 'O', 
-'R', 'K', '_', 'P', 'R', 'O', 'T', 'O', 'C', 'O', 'L', '_', 'U', 'N', 'S', 'P', 'E', 'C', 'I', 'F', 'I', 'E', 'D', '\020', '\000', 
-'\022', '\007', '\n', '\003', 'T', 'C', 'P', '\020', '\001', '\022', '\007', '\n', '\003', 'U', 'D', 'P', '\020', '\002', '2', '[', '\n', '\021', 'H', 'a', 'n', 
-'d', 's', 'h', 'a', 'k', 'e', 'r', 'S', 'e', 'r', 'v', 'i', 'c', 'e', '\022', 'F', '\n', '\013', 'D', 'o', 'H', 'a', 'n', 'd', 's', 
-'h', 'a', 'k', 'e', '\022', '\027', '.', 'g', 'r', 'p', 'c', '.', 'g', 'c', 'p', '.', 'H', 'a', 'n', 'd', 's', 'h', 'a', 'k', 'e', 
-'r', 'R', 'e', 'q', '\032', '\030', '.', 'g', 'r', 'p', 'c', '.', 'g', 'c', 'p', '.', 'H', 'a', 'n', 'd', 's', 'h', 'a', 'k', 'e', 
-'r', 'R', 'e', 's', 'p', '\"', '\000', '(', '\001', '0', '\001', 'B', 'k', '\n', '\025', 'i', 'o', '.', 'g', 'r', 'p', 'c', '.', 'a', 'l', 
-'t', 's', '.', 'i', 'n', 't', 'e', 'r', 'n', 'a', 'l', 'B', '\017', 'H', 'a', 'n', 'd', 's', 'h', 'a', 'k', 'e', 'r', 'P', 'r', 
-'o', 't', 'o', 'P', '\001', 'Z', '?', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'g', 'o', 'l', 'a', 'n', 'g', '.', 'o', 'r', 'g', '/', 
-'g', 'r', 'p', 'c', '/', 'c', 'r', 'e', 'd', 'e', 'n', 't', 'i', 'a', 'l', 's', '/', 'a', 'l', 't', 's', '/', 'i', 'n', 't', 
-'e', 'r', 'n', 'a', 'l', '/', 'p', 'r', 'o', 't', 'o', '/', 'g', 'r', 'p', 'c', '_', 'g', 'c', 'p', 'b', '\006', 'p', 'r', 'o', 
-'t', 'o', '3', 
-};
-
-static upb_def_init *deps[2] = {
-  &src_proto_grpc_gcp_transport_security_common_proto_upbdefinit,
-  NULL
-};
-
-upb_def_init src_proto_grpc_gcp_handshaker_proto_upbdefinit = {
-  deps,
-  layouts,
-  "src/proto/grpc/gcp/handshaker.proto",
-  UPB_STRVIEW_INIT(descriptor, 3053)
-};
diff --git a/src/core/ext/upbdefs-generated/src/proto/grpc/gcp/handshaker.upbdefs.h b/src/core/ext/upbdefs-generated/src/proto/grpc/gcp/handshaker.upbdefs.h
deleted file mode 100644 (file)
index 41bf499..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-/* This file was generated by upbc (the upb compiler) from the input
- * file:
- *
- *     src/proto/grpc/gcp/handshaker.proto
- *
- * Do not edit -- your changes will be discarded when the file is
- * regenerated. */
-
-#ifndef SRC_PROTO_GRPC_GCP_HANDSHAKER_PROTO_UPBDEFS_H_
-#define SRC_PROTO_GRPC_GCP_HANDSHAKER_PROTO_UPBDEFS_H_
-
-#include "upb/def.h"
-#include "upb/port_def.inc"
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "upb/def.h"
-
-#include "upb/port_def.inc"
-
-extern upb_def_init src_proto_grpc_gcp_handshaker_proto_upbdefinit;
-
-UPB_INLINE const upb_msgdef *grpc_gcp_Endpoint_getmsgdef(upb_symtab *s) {
-  _upb_symtab_loaddefinit(s, &src_proto_grpc_gcp_handshaker_proto_upbdefinit);
-  return upb_symtab_lookupmsg(s, "grpc.gcp.Endpoint");
-}
-
-UPB_INLINE const upb_msgdef *grpc_gcp_Identity_getmsgdef(upb_symtab *s) {
-  _upb_symtab_loaddefinit(s, &src_proto_grpc_gcp_handshaker_proto_upbdefinit);
-  return upb_symtab_lookupmsg(s, "grpc.gcp.Identity");
-}
-
-UPB_INLINE const upb_msgdef *grpc_gcp_Identity_AttributesEntry_getmsgdef(upb_symtab *s) {
-  _upb_symtab_loaddefinit(s, &src_proto_grpc_gcp_handshaker_proto_upbdefinit);
-  return upb_symtab_lookupmsg(s, "grpc.gcp.Identity.AttributesEntry");
-}
-
-UPB_INLINE const upb_msgdef *grpc_gcp_StartClientHandshakeReq_getmsgdef(upb_symtab *s) {
-  _upb_symtab_loaddefinit(s, &src_proto_grpc_gcp_handshaker_proto_upbdefinit);
-  return upb_symtab_lookupmsg(s, "grpc.gcp.StartClientHandshakeReq");
-}
-
-UPB_INLINE const upb_msgdef *grpc_gcp_ServerHandshakeParameters_getmsgdef(upb_symtab *s) {
-  _upb_symtab_loaddefinit(s, &src_proto_grpc_gcp_handshaker_proto_upbdefinit);
-  return upb_symtab_lookupmsg(s, "grpc.gcp.ServerHandshakeParameters");
-}
-
-UPB_INLINE const upb_msgdef *grpc_gcp_StartServerHandshakeReq_getmsgdef(upb_symtab *s) {
-  _upb_symtab_loaddefinit(s, &src_proto_grpc_gcp_handshaker_proto_upbdefinit);
-  return upb_symtab_lookupmsg(s, "grpc.gcp.StartServerHandshakeReq");
-}
-
-UPB_INLINE const upb_msgdef *grpc_gcp_StartServerHandshakeReq_HandshakeParametersEntry_getmsgdef(upb_symtab *s) {
-  _upb_symtab_loaddefinit(s, &src_proto_grpc_gcp_handshaker_proto_upbdefinit);
-  return upb_symtab_lookupmsg(s, "grpc.gcp.StartServerHandshakeReq.HandshakeParametersEntry");
-}
-
-UPB_INLINE const upb_msgdef *grpc_gcp_NextHandshakeMessageReq_getmsgdef(upb_symtab *s) {
-  _upb_symtab_loaddefinit(s, &src_proto_grpc_gcp_handshaker_proto_upbdefinit);
-  return upb_symtab_lookupmsg(s, "grpc.gcp.NextHandshakeMessageReq");
-}
-
-UPB_INLINE const upb_msgdef *grpc_gcp_HandshakerReq_getmsgdef(upb_symtab *s) {
-  _upb_symtab_loaddefinit(s, &src_proto_grpc_gcp_handshaker_proto_upbdefinit);
-  return upb_symtab_lookupmsg(s, "grpc.gcp.HandshakerReq");
-}
-
-UPB_INLINE const upb_msgdef *grpc_gcp_HandshakerResult_getmsgdef(upb_symtab *s) {
-  _upb_symtab_loaddefinit(s, &src_proto_grpc_gcp_handshaker_proto_upbdefinit);
-  return upb_symtab_lookupmsg(s, "grpc.gcp.HandshakerResult");
-}
-
-UPB_INLINE const upb_msgdef *grpc_gcp_HandshakerStatus_getmsgdef(upb_symtab *s) {
-  _upb_symtab_loaddefinit(s, &src_proto_grpc_gcp_handshaker_proto_upbdefinit);
-  return upb_symtab_lookupmsg(s, "grpc.gcp.HandshakerStatus");
-}
-
-UPB_INLINE const upb_msgdef *grpc_gcp_HandshakerResp_getmsgdef(upb_symtab *s) {
-  _upb_symtab_loaddefinit(s, &src_proto_grpc_gcp_handshaker_proto_upbdefinit);
-  return upb_symtab_lookupmsg(s, "grpc.gcp.HandshakerResp");
-}
-
-#ifdef __cplusplus
-}  /* extern "C" */
-#endif
-
-#include "upb/port_undef.inc"
-
-#endif  /* SRC_PROTO_GRPC_GCP_HANDSHAKER_PROTO_UPBDEFS_H_ */
diff --git a/src/core/ext/upbdefs-generated/src/proto/grpc/gcp/transport_security_common.upbdefs.c b/src/core/ext/upbdefs-generated/src/proto/grpc/gcp/transport_security_common.upbdefs.c
deleted file mode 100644 (file)
index 0ae0baf..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/* This file was generated by upbc (the upb compiler) from the input
- * file:
- *
- *     src/proto/grpc/gcp/transport_security_common.proto
- *
- * Do not edit -- your changes will be discarded when the file is
- * regenerated. */
-
-#include "upb/def.h"
-#include "src/proto/grpc/gcp/transport_security_common.upbdefs.h"
-
-extern const upb_msglayout grpc_gcp_RpcProtocolVersions_msginit;
-extern const upb_msglayout grpc_gcp_RpcProtocolVersions_Version_msginit;
-
-static const upb_msglayout *layouts[2] = {
-  &grpc_gcp_RpcProtocolVersions_msginit,
-  &grpc_gcp_RpcProtocolVersions_Version_msginit,
-};
-
-static const char descriptor[512] = {'\n', '2', 's', 'r', 'c', '/', 'p', 'r', 'o', 't', 'o', '/', 'g', 'r', 'p', 'c', '/', 'g', 'c', 'p', '/', 't', 'r', 'a', 'n', 
-'s', 'p', 'o', 'r', 't', '_', 's', 'e', 'c', 'u', 'r', 'i', 't', 'y', '_', 'c', 'o', 'm', 'm', 'o', 'n', '.', 'p', 'r', 'o', 
-'t', 'o', '\022', '\010', 'g', 'r', 'p', 'c', '.', 'g', 'c', 'p', '\"', '\352', '\001', '\n', '\023', 'R', 'p', 'c', 'P', 'r', 'o', 't', 'o', 
-'c', 'o', 'l', 'V', 'e', 'r', 's', 'i', 'o', 'n', 's', '\022', 'M', '\n', '\017', 'm', 'a', 'x', '_', 'r', 'p', 'c', '_', 'v', 'e', 
-'r', 's', 'i', 'o', 'n', '\030', '\001', ' ', '\001', '(', '\013', '2', '%', '.', 'g', 'r', 'p', 'c', '.', 'g', 'c', 'p', '.', 'R', 'p', 
-'c', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'V', 'e', 'r', 's', 'i', 'o', 'n', 's', '.', 'V', 'e', 'r', 's', 'i', 'o', 'n', 
-'R', '\r', 'm', 'a', 'x', 'R', 'p', 'c', 'V', 'e', 'r', 's', 'i', 'o', 'n', '\022', 'M', '\n', '\017', 'm', 'i', 'n', '_', 'r', 'p', 
-'c', '_', 'v', 'e', 'r', 's', 'i', 'o', 'n', '\030', '\002', ' ', '\001', '(', '\013', '2', '%', '.', 'g', 'r', 'p', 'c', '.', 'g', 'c', 
-'p', '.', 'R', 'p', 'c', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'V', 'e', 'r', 's', 'i', 'o', 'n', 's', '.', 'V', 'e', 'r', 
-'s', 'i', 'o', 'n', 'R', '\r', 'm', 'i', 'n', 'R', 'p', 'c', 'V', 'e', 'r', 's', 'i', 'o', 'n', '\032', '5', '\n', '\007', 'V', 'e', 
-'r', 's', 'i', 'o', 'n', '\022', '\024', '\n', '\005', 'm', 'a', 'j', 'o', 'r', '\030', '\001', ' ', '\001', '(', '\r', 'R', '\005', 'm', 'a', 'j', 
-'o', 'r', '\022', '\024', '\n', '\005', 'm', 'i', 'n', 'o', 'r', '\030', '\002', ' ', '\001', '(', '\r', 'R', '\005', 'm', 'i', 'n', 'o', 'r', '*', 
-'Q', '\n', '\r', 'S', 'e', 'c', 'u', 'r', 'i', 't', 'y', 'L', 'e', 'v', 'e', 'l', '\022', '\021', '\n', '\r', 'S', 'E', 'C', 'U', 'R', 
-'I', 'T', 'Y', '_', 'N', 'O', 'N', 'E', '\020', '\000', '\022', '\022', '\n', '\016', 'I', 'N', 'T', 'E', 'G', 'R', 'I', 'T', 'Y', '_', 'O', 
-'N', 'L', 'Y', '\020', '\001', '\022', '\031', '\n', '\025', 'I', 'N', 'T', 'E', 'G', 'R', 'I', 'T', 'Y', '_', 'A', 'N', 'D', '_', 'P', 'R', 
-'I', 'V', 'A', 'C', 'Y', '\020', '\002', 'B', 'x', '\n', '\025', 'i', 'o', '.', 'g', 'r', 'p', 'c', '.', 'a', 'l', 't', 's', '.', 'i', 
-'n', 't', 'e', 'r', 'n', 'a', 'l', 'B', '\034', 'T', 'r', 'a', 'n', 's', 'p', 'o', 'r', 't', 'S', 'e', 'c', 'u', 'r', 'i', 't', 
-'y', 'C', 'o', 'm', 'm', 'o', 'n', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', '?', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'g', 'o', 
-'l', 'a', 'n', 'g', '.', 'o', 'r', 'g', '/', 'g', 'r', 'p', 'c', '/', 'c', 'r', 'e', 'd', 'e', 'n', 't', 'i', 'a', 'l', 's', 
-'/', 'a', 'l', 't', 's', '/', 'i', 'n', 't', 'e', 'r', 'n', 'a', 'l', '/', 'p', 'r', 'o', 't', 'o', '/', 'g', 'r', 'p', 'c', 
-'_', 'g', 'c', 'p', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', 
-};
-
-static upb_def_init *deps[1] = {
-  NULL
-};
-
-upb_def_init src_proto_grpc_gcp_transport_security_common_proto_upbdefinit = {
-  deps,
-  layouts,
-  "src/proto/grpc/gcp/transport_security_common.proto",
-  UPB_STRVIEW_INIT(descriptor, 512)
-};
diff --git a/src/core/ext/upbdefs-generated/src/proto/grpc/gcp/transport_security_common.upbdefs.h b/src/core/ext/upbdefs-generated/src/proto/grpc/gcp/transport_security_common.upbdefs.h
deleted file mode 100644 (file)
index cf79d2e..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/* This file was generated by upbc (the upb compiler) from the input
- * file:
- *
- *     src/proto/grpc/gcp/transport_security_common.proto
- *
- * Do not edit -- your changes will be discarded when the file is
- * regenerated. */
-
-#ifndef SRC_PROTO_GRPC_GCP_TRANSPORT_SECURITY_COMMON_PROTO_UPBDEFS_H_
-#define SRC_PROTO_GRPC_GCP_TRANSPORT_SECURITY_COMMON_PROTO_UPBDEFS_H_
-
-#include "upb/def.h"
-#include "upb/port_def.inc"
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "upb/def.h"
-
-#include "upb/port_def.inc"
-
-extern upb_def_init src_proto_grpc_gcp_transport_security_common_proto_upbdefinit;
-
-UPB_INLINE const upb_msgdef *grpc_gcp_RpcProtocolVersions_getmsgdef(upb_symtab *s) {
-  _upb_symtab_loaddefinit(s, &src_proto_grpc_gcp_transport_security_common_proto_upbdefinit);
-  return upb_symtab_lookupmsg(s, "grpc.gcp.RpcProtocolVersions");
-}
-
-UPB_INLINE const upb_msgdef *grpc_gcp_RpcProtocolVersions_Version_getmsgdef(upb_symtab *s) {
-  _upb_symtab_loaddefinit(s, &src_proto_grpc_gcp_transport_security_common_proto_upbdefinit);
-  return upb_symtab_lookupmsg(s, "grpc.gcp.RpcProtocolVersions.Version");
-}
-
-#ifdef __cplusplus
-}  /* extern "C" */
-#endif
-
-#include "upb/port_undef.inc"
-
-#endif  /* SRC_PROTO_GRPC_GCP_TRANSPORT_SECURITY_COMMON_PROTO_UPBDEFS_H_ */
diff --git a/src/core/ext/upbdefs-generated/src/proto/grpc/health/v1/health.upbdefs.c b/src/core/ext/upbdefs-generated/src/proto/grpc/health/v1/health.upbdefs.c
deleted file mode 100644 (file)
index 4f63972..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/* This file was generated by upbc (the upb compiler) from the input
- * file:
- *
- *     src/proto/grpc/health/v1/health.proto
- *
- * Do not edit -- your changes will be discarded when the file is
- * regenerated. */
-
-#include "upb/def.h"
-#include "src/proto/grpc/health/v1/health.upbdefs.h"
-
-extern const upb_msglayout grpc_health_v1_HealthCheckRequest_msginit;
-extern const upb_msglayout grpc_health_v1_HealthCheckResponse_msginit;
-
-static const upb_msglayout *layouts[2] = {
-  &grpc_health_v1_HealthCheckRequest_msginit,
-  &grpc_health_v1_HealthCheckResponse_msginit,
-};
-
-static const char descriptor[567] = {'\n', '%', 's', 'r', 'c', '/', 'p', 'r', 'o', 't', 'o', '/', 'g', 'r', 'p', 'c', '/', 'h', 'e', 'a', 'l', 't', 'h', '/', 'v', 
-'1', '/', 'h', 'e', 'a', 'l', 't', 'h', '.', 'p', 'r', 'o', 't', 'o', '\022', '\016', 'g', 'r', 'p', 'c', '.', 'h', 'e', 'a', 'l', 
-'t', 'h', '.', 'v', '1', '\"', '.', '\n', '\022', 'H', 'e', 'a', 'l', 't', 'h', 'C', 'h', 'e', 'c', 'k', 'R', 'e', 'q', 'u', 'e', 
-'s', 't', '\022', '\030', '\n', '\007', 's', 'e', 'r', 'v', 'i', 'c', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\007', 's', 'e', 'r', 'v', 
-'i', 'c', 'e', '\"', '\261', '\001', '\n', '\023', 'H', 'e', 'a', 'l', 't', 'h', 'C', 'h', 'e', 'c', 'k', 'R', 'e', 's', 'p', 'o', 'n', 
-'s', 'e', '\022', 'I', '\n', '\006', 's', 't', 'a', 't', 'u', 's', '\030', '\001', ' ', '\001', '(', '\016', '2', '1', '.', 'g', 'r', 'p', 'c', 
-'.', 'h', 'e', 'a', 'l', 't', 'h', '.', 'v', '1', '.', 'H', 'e', 'a', 'l', 't', 'h', 'C', 'h', 'e', 'c', 'k', 'R', 'e', 's', 
-'p', 'o', 'n', 's', 'e', '.', 'S', 'e', 'r', 'v', 'i', 'n', 'g', 'S', 't', 'a', 't', 'u', 's', 'R', '\006', 's', 't', 'a', 't', 
-'u', 's', '\"', 'O', '\n', '\r', 'S', 'e', 'r', 'v', 'i', 'n', 'g', 'S', 't', 'a', 't', 'u', 's', '\022', '\013', '\n', '\007', 'U', 'N', 
-'K', 'N', 'O', 'W', 'N', '\020', '\000', '\022', '\013', '\n', '\007', 'S', 'E', 'R', 'V', 'I', 'N', 'G', '\020', '\001', '\022', '\017', '\n', '\013', 'N', 
-'O', 'T', '_', 'S', 'E', 'R', 'V', 'I', 'N', 'G', '\020', '\002', '\022', '\023', '\n', '\017', 'S', 'E', 'R', 'V', 'I', 'C', 'E', '_', 'U', 
-'N', 'K', 'N', 'O', 'W', 'N', '\020', '\003', '2', '\256', '\001', '\n', '\006', 'H', 'e', 'a', 'l', 't', 'h', '\022', 'P', '\n', '\005', 'C', 'h', 
-'e', 'c', 'k', '\022', '\"', '.', 'g', 'r', 'p', 'c', '.', 'h', 'e', 'a', 'l', 't', 'h', '.', 'v', '1', '.', 'H', 'e', 'a', 'l', 
-'t', 'h', 'C', 'h', 'e', 'c', 'k', 'R', 'e', 'q', 'u', 'e', 's', 't', '\032', '#', '.', 'g', 'r', 'p', 'c', '.', 'h', 'e', 'a', 
-'l', 't', 'h', '.', 'v', '1', '.', 'H', 'e', 'a', 'l', 't', 'h', 'C', 'h', 'e', 'c', 'k', 'R', 'e', 's', 'p', 'o', 'n', 's', 
-'e', '\022', 'R', '\n', '\005', 'W', 'a', 't', 'c', 'h', '\022', '\"', '.', 'g', 'r', 'p', 'c', '.', 'h', 'e', 'a', 'l', 't', 'h', '.', 
-'v', '1', '.', 'H', 'e', 'a', 'l', 't', 'h', 'C', 'h', 'e', 'c', 'k', 'R', 'e', 'q', 'u', 'e', 's', 't', '\032', '#', '.', 'g', 
-'r', 'p', 'c', '.', 'h', 'e', 'a', 'l', 't', 'h', '.', 'v', '1', '.', 'H', 'e', 'a', 'l', 't', 'h', 'C', 'h', 'e', 'c', 'k', 
-'R', 'e', 's', 'p', 'o', 'n', 's', 'e', '0', '\001', 'B', 'a', '\n', '\021', 'i', 'o', '.', 'g', 'r', 'p', 'c', '.', 'h', 'e', 'a', 
-'l', 't', 'h', '.', 'v', '1', 'B', '\013', 'H', 'e', 'a', 'l', 't', 'h', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', ',', 'g', 'o', 
-'o', 'g', 'l', 'e', '.', 'g', 'o', 'l', 'a', 'n', 'g', '.', 'o', 'r', 'g', '/', 'g', 'r', 'p', 'c', '/', 'h', 'e', 'a', 'l', 
-'t', 'h', '/', 'g', 'r', 'p', 'c', '_', 'h', 'e', 'a', 'l', 't', 'h', '_', 'v', '1', '\252', '\002', '\016', 'G', 'r', 'p', 'c', '.', 
-'H', 'e', 'a', 'l', 't', 'h', '.', 'V', '1', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', 
-};
-
-static upb_def_init *deps[1] = {
-  NULL
-};
-
-upb_def_init src_proto_grpc_health_v1_health_proto_upbdefinit = {
-  deps,
-  layouts,
-  "src/proto/grpc/health/v1/health.proto",
-  UPB_STRVIEW_INIT(descriptor, 567)
-};
diff --git a/src/core/ext/upbdefs-generated/src/proto/grpc/health/v1/health.upbdefs.h b/src/core/ext/upbdefs-generated/src/proto/grpc/health/v1/health.upbdefs.h
deleted file mode 100644 (file)
index 50a1021..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/* This file was generated by upbc (the upb compiler) from the input
- * file:
- *
- *     src/proto/grpc/health/v1/health.proto
- *
- * Do not edit -- your changes will be discarded when the file is
- * regenerated. */
-
-#ifndef SRC_PROTO_GRPC_HEALTH_V1_HEALTH_PROTO_UPBDEFS_H_
-#define SRC_PROTO_GRPC_HEALTH_V1_HEALTH_PROTO_UPBDEFS_H_
-
-#include "upb/def.h"
-#include "upb/port_def.inc"
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "upb/def.h"
-
-#include "upb/port_def.inc"
-
-extern upb_def_init src_proto_grpc_health_v1_health_proto_upbdefinit;
-
-UPB_INLINE const upb_msgdef *grpc_health_v1_HealthCheckRequest_getmsgdef(upb_symtab *s) {
-  _upb_symtab_loaddefinit(s, &src_proto_grpc_health_v1_health_proto_upbdefinit);
-  return upb_symtab_lookupmsg(s, "grpc.health.v1.HealthCheckRequest");
-}
-
-UPB_INLINE const upb_msgdef *grpc_health_v1_HealthCheckResponse_getmsgdef(upb_symtab *s) {
-  _upb_symtab_loaddefinit(s, &src_proto_grpc_health_v1_health_proto_upbdefinit);
-  return upb_symtab_lookupmsg(s, "grpc.health.v1.HealthCheckResponse");
-}
-
-#ifdef __cplusplus
-}  /* extern "C" */
-#endif
-
-#include "upb/port_undef.inc"
-
-#endif  /* SRC_PROTO_GRPC_HEALTH_V1_HEALTH_PROTO_UPBDEFS_H_ */
diff --git a/src/core/ext/upbdefs-generated/src/proto/grpc/lb/v1/load_balancer.upbdefs.c b/src/core/ext/upbdefs-generated/src/proto/grpc/lb/v1/load_balancer.upbdefs.c
deleted file mode 100644 (file)
index 99b925c..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-/* This file was generated by upbc (the upb compiler) from the input
- * file:
- *
- *     src/proto/grpc/lb/v1/load_balancer.proto
- *
- * Do not edit -- your changes will be discarded when the file is
- * regenerated. */
-
-#include "upb/def.h"
-#include "src/proto/grpc/lb/v1/load_balancer.upbdefs.h"
-
-extern upb_def_init google_protobuf_duration_proto_upbdefinit;
-extern upb_def_init google_protobuf_timestamp_proto_upbdefinit;
-extern const upb_msglayout grpc_lb_v1_LoadBalanceRequest_msginit;
-extern const upb_msglayout grpc_lb_v1_InitialLoadBalanceRequest_msginit;
-extern const upb_msglayout grpc_lb_v1_ClientStatsPerToken_msginit;
-extern const upb_msglayout grpc_lb_v1_ClientStats_msginit;
-extern const upb_msglayout grpc_lb_v1_LoadBalanceResponse_msginit;
-extern const upb_msglayout grpc_lb_v1_InitialLoadBalanceResponse_msginit;
-extern const upb_msglayout grpc_lb_v1_ServerList_msginit;
-extern const upb_msglayout grpc_lb_v1_Server_msginit;
-extern const upb_msglayout grpc_lb_v1_FallbackResponse_msginit;
-
-static const upb_msglayout *layouts[9] = {
-  &grpc_lb_v1_LoadBalanceRequest_msginit,
-  &grpc_lb_v1_InitialLoadBalanceRequest_msginit,
-  &grpc_lb_v1_ClientStatsPerToken_msginit,
-  &grpc_lb_v1_ClientStats_msginit,
-  &grpc_lb_v1_LoadBalanceResponse_msginit,
-  &grpc_lb_v1_InitialLoadBalanceResponse_msginit,
-  &grpc_lb_v1_ServerList_msginit,
-  &grpc_lb_v1_Server_msginit,
-  &grpc_lb_v1_FallbackResponse_msginit,
-};
-
-static const char descriptor[1767] = {'\n', '(', 's', 'r', 'c', '/', 'p', 'r', 'o', 't', 'o', '/', 'g', 'r', 'p', 'c', '/', 'l', 'b', '/', 'v', '1', '/', 'l', 'o', 
-'a', 'd', '_', 'b', 'a', 'l', 'a', 'n', 'c', 'e', 'r', '.', 'p', 'r', 'o', 't', 'o', '\022', '\n', 'g', 'r', 'p', 'c', '.', 'l', 
-'b', '.', 'v', '1', '\032', '\036', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 'd', 'u', 'r', 
-'a', 't', 'i', 'o', 'n', '.', 'p', 'r', 'o', 't', 'o', '\032', '\037', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 
-'b', 'u', 'f', '/', 't', 'i', 'm', 'e', 's', 't', 'a', 'm', 'p', '.', 'p', 'r', 'o', 't', 'o', '\"', '\301', '\001', '\n', '\022', 'L', 
-'o', 'a', 'd', 'B', 'a', 'l', 'a', 'n', 'c', 'e', 'R', 'e', 'q', 'u', 'e', 's', 't', '\022', 'P', '\n', '\017', 'i', 'n', 'i', 't', 
-'i', 'a', 'l', '_', 'r', 'e', 'q', 'u', 'e', 's', 't', '\030', '\001', ' ', '\001', '(', '\013', '2', '%', '.', 'g', 'r', 'p', 'c', '.', 
-'l', 'b', '.', 'v', '1', '.', 'I', 'n', 'i', 't', 'i', 'a', 'l', 'L', 'o', 'a', 'd', 'B', 'a', 'l', 'a', 'n', 'c', 'e', 'R', 
-'e', 'q', 'u', 'e', 's', 't', 'H', '\000', 'R', '\016', 'i', 'n', 'i', 't', 'i', 'a', 'l', 'R', 'e', 'q', 'u', 'e', 's', 't', '\022', 
-'<', '\n', '\014', 'c', 'l', 'i', 'e', 'n', 't', '_', 's', 't', 'a', 't', 's', '\030', '\002', ' ', '\001', '(', '\013', '2', '\027', '.', 'g', 
-'r', 'p', 'c', '.', 'l', 'b', '.', 'v', '1', '.', 'C', 'l', 'i', 'e', 'n', 't', 'S', 't', 'a', 't', 's', 'H', '\000', 'R', '\013', 
-'c', 'l', 'i', 'e', 'n', 't', 'S', 't', 'a', 't', 's', 'B', '\033', '\n', '\031', 'l', 'o', 'a', 'd', '_', 'b', 'a', 'l', 'a', 'n', 
-'c', 'e', '_', 'r', 'e', 'q', 'u', 'e', 's', 't', '_', 't', 'y', 'p', 'e', '\"', '/', '\n', '\031', 'I', 'n', 'i', 't', 'i', 'a', 
-'l', 'L', 'o', 'a', 'd', 'B', 'a', 'l', 'a', 'n', 'c', 'e', 'R', 'e', 'q', 'u', 'e', 's', 't', '\022', '\022', '\n', '\004', 'n', 'a', 
-'m', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\004', 'n', 'a', 'm', 'e', '\"', '`', '\n', '\023', 'C', 'l', 'i', 'e', 'n', 't', 'S', 
-'t', 'a', 't', 's', 'P', 'e', 'r', 'T', 'o', 'k', 'e', 'n', '\022', ',', '\n', '\022', 'l', 'o', 'a', 'd', '_', 'b', 'a', 'l', 'a', 
-'n', 'c', 'e', '_', 't', 'o', 'k', 'e', 'n', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\020', 'l', 'o', 'a', 'd', 'B', 'a', 'l', 'a', 
-'n', 'c', 'e', 'T', 'o', 'k', 'e', 'n', '\022', '\033', '\n', '\t', 'n', 'u', 'm', '_', 'c', 'a', 'l', 'l', 's', '\030', '\002', ' ', '\001', 
-'(', '\003', 'R', '\010', 'n', 'u', 'm', 'C', 'a', 'l', 'l', 's', '\"', '\260', '\003', '\n', '\013', 'C', 'l', 'i', 'e', 'n', 't', 'S', 't', 
-'a', 't', 's', '\022', '8', '\n', '\t', 't', 'i', 'm', 'e', 's', 't', 'a', 'm', 'p', '\030', '\001', ' ', '\001', '(', '\013', '2', '\032', '.', 
-'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'T', 'i', 'm', 'e', 's', 't', 'a', 'm', 'p', 
-'R', '\t', 't', 'i', 'm', 'e', 's', 't', 'a', 'm', 'p', '\022', '*', '\n', '\021', 'n', 'u', 'm', '_', 'c', 'a', 'l', 'l', 's', '_', 
-'s', 't', 'a', 'r', 't', 'e', 'd', '\030', '\002', ' ', '\001', '(', '\003', 'R', '\017', 'n', 'u', 'm', 'C', 'a', 'l', 'l', 's', 'S', 't', 
-'a', 'r', 't', 'e', 'd', '\022', ',', '\n', '\022', 'n', 'u', 'm', '_', 'c', 'a', 'l', 'l', 's', '_', 'f', 'i', 'n', 'i', 's', 'h', 
-'e', 'd', '\030', '\003', ' ', '\001', '(', '\003', 'R', '\020', 'n', 'u', 'm', 'C', 'a', 'l', 'l', 's', 'F', 'i', 'n', 'i', 's', 'h', 'e', 
-'d', '\022', ']', '\n', '-', 'n', 'u', 'm', '_', 'c', 'a', 'l', 'l', 's', '_', 'f', 'i', 'n', 'i', 's', 'h', 'e', 'd', '_', 'w', 
-'i', 't', 'h', '_', 'c', 'l', 'i', 'e', 'n', 't', '_', 'f', 'a', 'i', 'l', 'e', 'd', '_', 't', 'o', '_', 's', 'e', 'n', 'd', 
-'\030', '\006', ' ', '\001', '(', '\003', 'R', '&', 'n', 'u', 'm', 'C', 'a', 'l', 'l', 's', 'F', 'i', 'n', 'i', 's', 'h', 'e', 'd', 'W', 
-'i', 't', 'h', 'C', 'l', 'i', 'e', 'n', 't', 'F', 'a', 'i', 'l', 'e', 'd', 'T', 'o', 'S', 'e', 'n', 'd', '\022', 'H', '\n', '!', 
-'n', 'u', 'm', '_', 'c', 'a', 'l', 'l', 's', '_', 'f', 'i', 'n', 'i', 's', 'h', 'e', 'd', '_', 'k', 'n', 'o', 'w', 'n', '_', 
-'r', 'e', 'c', 'e', 'i', 'v', 'e', 'd', '\030', '\007', ' ', '\001', '(', '\003', 'R', '\035', 'n', 'u', 'm', 'C', 'a', 'l', 'l', 's', 'F', 
-'i', 'n', 'i', 's', 'h', 'e', 'd', 'K', 'n', 'o', 'w', 'n', 'R', 'e', 'c', 'e', 'i', 'v', 'e', 'd', '\022', 'X', '\n', '\030', 'c', 
-'a', 'l', 'l', 's', '_', 'f', 'i', 'n', 'i', 's', 'h', 'e', 'd', '_', 'w', 'i', 't', 'h', '_', 'd', 'r', 'o', 'p', '\030', '\010', 
-' ', '\003', '(', '\013', '2', '\037', '.', 'g', 'r', 'p', 'c', '.', 'l', 'b', '.', 'v', '1', '.', 'C', 'l', 'i', 'e', 'n', 't', 'S', 
-'t', 'a', 't', 's', 'P', 'e', 'r', 'T', 'o', 'k', 'e', 'n', 'R', '\025', 'c', 'a', 'l', 'l', 's', 'F', 'i', 'n', 'i', 's', 'h', 
-'e', 'd', 'W', 'i', 't', 'h', 'D', 'r', 'o', 'p', 'J', '\004', '\010', '\004', '\020', '\005', 'J', '\004', '\010', '\005', '\020', '\006', '\"', '\220', '\002', 
-'\n', '\023', 'L', 'o', 'a', 'd', 'B', 'a', 'l', 'a', 'n', 'c', 'e', 'R', 'e', 's', 'p', 'o', 'n', 's', 'e', '\022', 'S', '\n', '\020', 
-'i', 'n', 'i', 't', 'i', 'a', 'l', '_', 'r', 'e', 's', 'p', 'o', 'n', 's', 'e', '\030', '\001', ' ', '\001', '(', '\013', '2', '&', '.', 
-'g', 'r', 'p', 'c', '.', 'l', 'b', '.', 'v', '1', '.', 'I', 'n', 'i', 't', 'i', 'a', 'l', 'L', 'o', 'a', 'd', 'B', 'a', 'l', 
-'a', 'n', 'c', 'e', 'R', 'e', 's', 'p', 'o', 'n', 's', 'e', 'H', '\000', 'R', '\017', 'i', 'n', 'i', 't', 'i', 'a', 'l', 'R', 'e', 
-'s', 'p', 'o', 'n', 's', 'e', '\022', '9', '\n', '\013', 's', 'e', 'r', 'v', 'e', 'r', '_', 'l', 'i', 's', 't', '\030', '\002', ' ', '\001', 
-'(', '\013', '2', '\026', '.', 'g', 'r', 'p', 'c', '.', 'l', 'b', '.', 'v', '1', '.', 'S', 'e', 'r', 'v', 'e', 'r', 'L', 'i', 's', 
-'t', 'H', '\000', 'R', '\n', 's', 'e', 'r', 'v', 'e', 'r', 'L', 'i', 's', 't', '\022', 'K', '\n', '\021', 'f', 'a', 'l', 'l', 'b', 'a', 
-'c', 'k', '_', 'r', 'e', 's', 'p', 'o', 'n', 's', 'e', '\030', '\003', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'r', 'p', 'c', '.', 
-'l', 'b', '.', 'v', '1', '.', 'F', 'a', 'l', 'l', 'b', 'a', 'c', 'k', 'R', 'e', 's', 'p', 'o', 'n', 's', 'e', 'H', '\000', 'R', 
-'\020', 'f', 'a', 'l', 'l', 'b', 'a', 'c', 'k', 'R', 'e', 's', 'p', 'o', 'n', 's', 'e', 'B', '\034', '\n', '\032', 'l', 'o', 'a', 'd', 
-'_', 'b', 'a', 'l', 'a', 'n', 'c', 'e', '_', 'r', 'e', 's', 'p', 'o', 'n', 's', 'e', '_', 't', 'y', 'p', 'e', '\"', '\256', '\001', 
-'\n', '\032', 'I', 'n', 'i', 't', 'i', 'a', 'l', 'L', 'o', 'a', 'd', 'B', 'a', 'l', 'a', 'n', 'c', 'e', 'R', 'e', 's', 'p', 'o', 
-'n', 's', 'e', '\022', '4', '\n', '\026', 'l', 'o', 'a', 'd', '_', 'b', 'a', 'l', 'a', 'n', 'c', 'e', 'r', '_', 'd', 'e', 'l', 'e', 
-'g', 'a', 't', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\024', 'l', 'o', 'a', 'd', 'B', 'a', 'l', 'a', 'n', 'c', 'e', 'r', 'D', 
-'e', 'l', 'e', 'g', 'a', 't', 'e', '\022', 'Z', '\n', '\034', 'c', 'l', 'i', 'e', 'n', 't', '_', 's', 't', 'a', 't', 's', '_', 'r', 
-'e', 'p', 'o', 'r', 't', '_', 'i', 'n', 't', 'e', 'r', 'v', 'a', 'l', '\030', '\002', ' ', '\001', '(', '\013', '2', '\031', '.', 'g', 'o', 
-'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'u', 'r', 'a', 't', 'i', 'o', 'n', 'R', '\031', 'c', 
-'l', 'i', 'e', 'n', 't', 'S', 't', 'a', 't', 's', 'R', 'e', 'p', 'o', 'r', 't', 'I', 'n', 't', 'e', 'r', 'v', 'a', 'l', '\"', 
-'@', '\n', '\n', 'S', 'e', 'r', 'v', 'e', 'r', 'L', 'i', 's', 't', '\022', ',', '\n', '\007', 's', 'e', 'r', 'v', 'e', 'r', 's', '\030', 
-'\001', ' ', '\003', '(', '\013', '2', '\022', '.', 'g', 'r', 'p', 'c', '.', 'l', 'b', '.', 'v', '1', '.', 'S', 'e', 'r', 'v', 'e', 'r', 
-'R', '\007', 's', 'e', 'r', 'v', 'e', 'r', 's', 'J', '\004', '\010', '\003', '\020', '\004', '\"', '\203', '\001', '\n', '\006', 'S', 'e', 'r', 'v', 'e', 
-'r', '\022', '\035', '\n', '\n', 'i', 'p', '_', 'a', 'd', 'd', 'r', 'e', 's', 's', '\030', '\001', ' ', '\001', '(', '\014', 'R', '\t', 'i', 'p', 
-'A', 'd', 'd', 'r', 'e', 's', 's', '\022', '\022', '\n', '\004', 'p', 'o', 'r', 't', '\030', '\002', ' ', '\001', '(', '\005', 'R', '\004', 'p', 'o', 
-'r', 't', '\022', ',', '\n', '\022', 'l', 'o', 'a', 'd', '_', 'b', 'a', 'l', 'a', 'n', 'c', 'e', '_', 't', 'o', 'k', 'e', 'n', '\030', 
-'\003', ' ', '\001', '(', '\t', 'R', '\020', 'l', 'o', 'a', 'd', 'B', 'a', 'l', 'a', 'n', 'c', 'e', 'T', 'o', 'k', 'e', 'n', '\022', '\022', 
-'\n', '\004', 'd', 'r', 'o', 'p', '\030', '\004', ' ', '\001', '(', '\010', 'R', '\004', 'd', 'r', 'o', 'p', 'J', '\004', '\010', '\005', '\020', '\006', '\"', 
-'\022', '\n', '\020', 'F', 'a', 'l', 'l', 'b', 'a', 'c', 'k', 'R', 'e', 's', 'p', 'o', 'n', 's', 'e', '2', 'b', '\n', '\014', 'L', 'o', 
-'a', 'd', 'B', 'a', 'l', 'a', 'n', 'c', 'e', 'r', '\022', 'R', '\n', '\013', 'B', 'a', 'l', 'a', 'n', 'c', 'e', 'L', 'o', 'a', 'd', 
-'\022', '\036', '.', 'g', 'r', 'p', 'c', '.', 'l', 'b', '.', 'v', '1', '.', 'L', 'o', 'a', 'd', 'B', 'a', 'l', 'a', 'n', 'c', 'e', 
-'R', 'e', 'q', 'u', 'e', 's', 't', '\032', '\037', '.', 'g', 'r', 'p', 'c', '.', 'l', 'b', '.', 'v', '1', '.', 'L', 'o', 'a', 'd', 
-'B', 'a', 'l', 'a', 'n', 'c', 'e', 'R', 'e', 's', 'p', 'o', 'n', 's', 'e', '(', '\001', '0', '\001', 'B', 'X', '\n', '\016', 'i', 'o', 
-'.', 'g', 'r', 'p', 'c', '.', 'g', 'r', 'p', 'c', 'l', 'b', 'B', '\021', 'L', 'o', 'a', 'd', 'B', 'a', 'l', 'a', 'n', 'c', 'e', 
-'r', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', '1', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'g', 'o', 'l', 'a', 'n', 'g', '.', 'o', 
-'r', 'g', '/', 'g', 'r', 'p', 'c', '/', 'b', 'a', 'l', 'a', 'n', 'c', 'e', 'r', '/', 'g', 'r', 'p', 'c', 'l', 'b', '/', 'g', 
-'r', 'p', 'c', '_', 'l', 'b', '_', 'v', '1', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', 
-};
-
-static upb_def_init *deps[3] = {
-  &google_protobuf_duration_proto_upbdefinit,
-  &google_protobuf_timestamp_proto_upbdefinit,
-  NULL
-};
-
-upb_def_init src_proto_grpc_lb_v1_load_balancer_proto_upbdefinit = {
-  deps,
-  layouts,
-  "src/proto/grpc/lb/v1/load_balancer.proto",
-  UPB_STRVIEW_INIT(descriptor, 1767)
-};
diff --git a/src/core/ext/upbdefs-generated/src/proto/grpc/lb/v1/load_balancer.upbdefs.h b/src/core/ext/upbdefs-generated/src/proto/grpc/lb/v1/load_balancer.upbdefs.h
deleted file mode 100644 (file)
index 87949a2..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/* This file was generated by upbc (the upb compiler) from the input
- * file:
- *
- *     src/proto/grpc/lb/v1/load_balancer.proto
- *
- * Do not edit -- your changes will be discarded when the file is
- * regenerated. */
-
-#ifndef SRC_PROTO_GRPC_LB_V1_LOAD_BALANCER_PROTO_UPBDEFS_H_
-#define SRC_PROTO_GRPC_LB_V1_LOAD_BALANCER_PROTO_UPBDEFS_H_
-
-#include "upb/def.h"
-#include "upb/port_def.inc"
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "upb/def.h"
-
-#include "upb/port_def.inc"
-
-extern upb_def_init src_proto_grpc_lb_v1_load_balancer_proto_upbdefinit;
-
-UPB_INLINE const upb_msgdef *grpc_lb_v1_LoadBalanceRequest_getmsgdef(upb_symtab *s) {
-  _upb_symtab_loaddefinit(s, &src_proto_grpc_lb_v1_load_balancer_proto_upbdefinit);
-  return upb_symtab_lookupmsg(s, "grpc.lb.v1.LoadBalanceRequest");
-}
-
-UPB_INLINE const upb_msgdef *grpc_lb_v1_InitialLoadBalanceRequest_getmsgdef(upb_symtab *s) {
-  _upb_symtab_loaddefinit(s, &src_proto_grpc_lb_v1_load_balancer_proto_upbdefinit);
-  return upb_symtab_lookupmsg(s, "grpc.lb.v1.InitialLoadBalanceRequest");
-}
-
-UPB_INLINE const upb_msgdef *grpc_lb_v1_ClientStatsPerToken_getmsgdef(upb_symtab *s) {
-  _upb_symtab_loaddefinit(s, &src_proto_grpc_lb_v1_load_balancer_proto_upbdefinit);
-  return upb_symtab_lookupmsg(s, "grpc.lb.v1.ClientStatsPerToken");
-}
-
-UPB_INLINE const upb_msgdef *grpc_lb_v1_ClientStats_getmsgdef(upb_symtab *s) {
-  _upb_symtab_loaddefinit(s, &src_proto_grpc_lb_v1_load_balancer_proto_upbdefinit);
-  return upb_symtab_lookupmsg(s, "grpc.lb.v1.ClientStats");
-}
-
-UPB_INLINE const upb_msgdef *grpc_lb_v1_LoadBalanceResponse_getmsgdef(upb_symtab *s) {
-  _upb_symtab_loaddefinit(s, &src_proto_grpc_lb_v1_load_balancer_proto_upbdefinit);
-  return upb_symtab_lookupmsg(s, "grpc.lb.v1.LoadBalanceResponse");
-}
-
-UPB_INLINE const upb_msgdef *grpc_lb_v1_InitialLoadBalanceResponse_getmsgdef(upb_symtab *s) {
-  _upb_symtab_loaddefinit(s, &src_proto_grpc_lb_v1_load_balancer_proto_upbdefinit);
-  return upb_symtab_lookupmsg(s, "grpc.lb.v1.InitialLoadBalanceResponse");
-}
-
-UPB_INLINE const upb_msgdef *grpc_lb_v1_ServerList_getmsgdef(upb_symtab *s) {
-  _upb_symtab_loaddefinit(s, &src_proto_grpc_lb_v1_load_balancer_proto_upbdefinit);
-  return upb_symtab_lookupmsg(s, "grpc.lb.v1.ServerList");
-}
-
-UPB_INLINE const upb_msgdef *grpc_lb_v1_Server_getmsgdef(upb_symtab *s) {
-  _upb_symtab_loaddefinit(s, &src_proto_grpc_lb_v1_load_balancer_proto_upbdefinit);
-  return upb_symtab_lookupmsg(s, "grpc.lb.v1.Server");
-}
-
-UPB_INLINE const upb_msgdef *grpc_lb_v1_FallbackResponse_getmsgdef(upb_symtab *s) {
-  _upb_symtab_loaddefinit(s, &src_proto_grpc_lb_v1_load_balancer_proto_upbdefinit);
-  return upb_symtab_lookupmsg(s, "grpc.lb.v1.FallbackResponse");
-}
-
-#ifdef __cplusplus
-}  /* extern "C" */
-#endif
-
-#include "upb/port_undef.inc"
-
-#endif  /* SRC_PROTO_GRPC_LB_V1_LOAD_BALANCER_PROTO_UPBDEFS_H_ */
index 6cfd7ee..44c9ba2 100644 (file)
@@ -20,7 +20,7 @@ static const upb_msglayout *layouts[3] = {
   &udpa_annotations_FileMigrateAnnotation_msginit,
 };
 
-static const char descriptor[855] = {'\n', '\036', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 'm', 'i', 'g', 'r', 'a', 't', 
+static const char descriptor[893] = {'\n', '\036', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 'm', 'i', 'g', 'r', 'a', 't', 
 'e', '.', 'p', 'r', 'o', 't', 'o', '\022', '\020', 'u', 'd', 'p', 'a', '.', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', 
 '\032', ' ', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 'd', 'e', 's', 'c', 'r', 'i', 'p', 
 't', 'o', 'r', '.', 'p', 'r', 'o', 't', 'o', '\"', '+', '\n', '\021', 'M', 'i', 'g', 'r', 'a', 't', 'e', 'A', 'n', 'n', 'o', 't', 
@@ -53,8 +53,9 @@ static const char descriptor[855] = {'\n', '\036', 'u', 'd', 'p', 'a', '/', 'a',
 'r', 'a', 't', 'e', '\022', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 
 'l', 'e', 'O', 'p', 't', 'i', 'o', 'n', 's', '\030', '\216', '\343', '\377', 'Q', ' ', '\001', '(', '\013', '2', '\'', '.', 'u', 'd', 'p', 'a', 
 '.', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '.', 'F', 'i', 'l', 'e', 'M', 'i', 'g', 'r', 'a', 't', 'e', 'A', 
-'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 'R', '\013', 'f', 'i', 'l', 'e', 'M', 'i', 'g', 'r', 'a', 't', 'e', 'b', '\006', 'p', 
-'r', 'o', 't', 'o', '3', 
+'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 'R', '\013', 'f', 'i', 'l', 'e', 'M', 'i', 'g', 'r', 'a', 't', 'e', 'B', '$', 'Z', 
+'\"', 'g', 'i', 't', 'h', 'u', 'b', '.', 'c', 'o', 'm', '/', 'c', 'n', 'c', 'f', '/', 'x', 'd', 's', '/', 'g', 'o', '/', 'a', 
+'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', 
 };
 
 static upb_def_init *deps[2] = {
@@ -66,5 +67,5 @@ upb_def_init udpa_annotations_migrate_proto_upbdefinit = {
   deps,
   layouts,
   "udpa/annotations/migrate.proto",
-  UPB_STRVIEW_INIT(descriptor, 855)
+  UPB_STRVIEW_INIT(descriptor, 893)
 };
index 6616936..521d2ed 100644 (file)
 #include "udpa/annotations/security.upbdefs.h"
 
 extern upb_def_init udpa_annotations_status_proto_upbdefinit;
-extern upb_def_init google_protobuf_any_proto_upbdefinit;
 extern upb_def_init google_protobuf_descriptor_proto_upbdefinit;
-extern upb_def_init validate_validate_proto_upbdefinit;
 extern const upb_msglayout udpa_annotations_FieldSecurityAnnotation_msginit;
 
 static const upb_msglayout *layouts[1] = {
   &udpa_annotations_FieldSecurityAnnotation_msginit,
 };
 
-static const char descriptor[469] = {'\n', '\037', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 's', 'e', 'c', 'u', 'r', 'i', 
+static const char descriptor[453] = {'\n', '\037', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 's', 'e', 'c', 'u', 'r', 'i', 
 't', 'y', '.', 'p', 'r', 'o', 't', 'o', '\022', '\020', 'u', 'd', 'p', 'a', '.', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 
 's', '\032', '\035', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 's', 't', 'a', 't', 'u', 
-'s', '.', 'p', 'r', 'o', 't', 'o', '\032', '\031', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 
-'a', 'n', 'y', '.', 'p', 'r', 'o', 't', 'o', '\032', ' ', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 
-'f', '/', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', '.', 'p', 'r', 'o', 't', 'o', '\032', '\027', 'v', 'a', 'l', 'i', 'd', 
-'a', 't', 'e', '/', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '.', 'p', 'r', 'o', 't', 'o', '\"', '\257', '\001', '\n', '\027', 'F', 'i', 
-'e', 'l', 'd', 'S', 'e', 'c', 'u', 'r', 'i', 't', 'y', 'A', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', '\022', 'K', '\n', '\"', 
-'c', 'o', 'n', 'f', 'i', 'g', 'u', 'r', 'e', '_', 'f', 'o', 'r', '_', 'u', 'n', 't', 'r', 'u', 's', 't', 'e', 'd', '_', 'd', 
-'o', 'w', 'n', 's', 't', 'r', 'e', 'a', 'm', '\030', '\001', ' ', '\001', '(', '\010', 'R', '\037', 'c', 'o', 'n', 'f', 'i', 'g', 'u', 'r', 
-'e', 'F', 'o', 'r', 'U', 'n', 't', 'r', 'u', 's', 't', 'e', 'd', 'D', 'o', 'w', 'n', 's', 't', 'r', 'e', 'a', 'm', '\022', 'G', 
-'\n', ' ', 'c', 'o', 'n', 'f', 'i', 'g', 'u', 'r', 'e', '_', 'f', 'o', 'r', '_', 'u', 'n', 't', 'r', 'u', 's', 't', 'e', 'd', 
-'_', 'u', 'p', 's', 't', 'r', 'e', 'a', 'm', '\030', '\002', ' ', '\001', '(', '\010', 'R', '\035', 'c', 'o', 'n', 'f', 'i', 'g', 'u', 'r', 
-'e', 'F', 'o', 'r', 'U', 'n', 't', 'r', 'u', 's', 't', 'e', 'd', 'U', 'p', 's', 't', 'r', 'e', 'a', 'm', ':', 'g', '\n', '\010', 
-'s', 'e', 'c', 'u', 'r', 'i', 't', 'y', '\022', '\035', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 
-'f', '.', 'F', 'i', 'e', 'l', 'd', 'O', 'p', 't', 'i', 'o', 'n', 's', '\030', '\261', '\362', '\246', '\005', ' ', '\001', '(', '\013', '2', ')', 
-'.', 'u', 'd', 'p', 'a', '.', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '.', 'F', 'i', 'e', 'l', 'd', 'S', 'e', 
-'c', 'u', 'r', 'i', 't', 'y', 'A', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 'R', '\010', 's', 'e', 'c', 'u', 'r', 'i', 't', 
-'y', 'B', '\010', '\272', '\200', '\310', '\321', '\006', '\002', '\010', '\001', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', 
+'s', '.', 'p', 'r', 'o', 't', 'o', '\032', ' ', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 
+'d', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', '.', 'p', 'r', 'o', 't', 'o', '\"', '\257', '\001', '\n', '\027', 'F', 'i', 'e', 'l', 
+'d', 'S', 'e', 'c', 'u', 'r', 'i', 't', 'y', 'A', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', '\022', 'K', '\n', '\"', 'c', 'o', 
+'n', 'f', 'i', 'g', 'u', 'r', 'e', '_', 'f', 'o', 'r', '_', 'u', 'n', 't', 'r', 'u', 's', 't', 'e', 'd', '_', 'd', 'o', 'w', 
+'n', 's', 't', 'r', 'e', 'a', 'm', '\030', '\001', ' ', '\001', '(', '\010', 'R', '\037', 'c', 'o', 'n', 'f', 'i', 'g', 'u', 'r', 'e', 'F', 
+'o', 'r', 'U', 'n', 't', 'r', 'u', 's', 't', 'e', 'd', 'D', 'o', 'w', 'n', 's', 't', 'r', 'e', 'a', 'm', '\022', 'G', '\n', ' ', 
+'c', 'o', 'n', 'f', 'i', 'g', 'u', 'r', 'e', '_', 'f', 'o', 'r', '_', 'u', 'n', 't', 'r', 'u', 's', 't', 'e', 'd', '_', 'u', 
+'p', 's', 't', 'r', 'e', 'a', 'm', '\030', '\002', ' ', '\001', '(', '\010', 'R', '\035', 'c', 'o', 'n', 'f', 'i', 'g', 'u', 'r', 'e', 'F', 
+'o', 'r', 'U', 'n', 't', 'r', 'u', 's', 't', 'e', 'd', 'U', 'p', 's', 't', 'r', 'e', 'a', 'm', ':', 'g', '\n', '\010', 's', 'e', 
+'c', 'u', 'r', 'i', 't', 'y', '\022', '\035', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 
+'F', 'i', 'e', 'l', 'd', 'O', 'p', 't', 'i', 'o', 'n', 's', '\030', '\261', '\362', '\246', '\005', ' ', '\001', '(', '\013', '2', ')', '.', 'u', 
+'d', 'p', 'a', '.', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '.', 'F', 'i', 'e', 'l', 'd', 'S', 'e', 'c', 'u', 
+'r', 'i', 't', 'y', 'A', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 'R', '\010', 's', 'e', 'c', 'u', 'r', 'i', 't', 'y', 'B', 
+',', 'Z', '\"', 'g', 'i', 't', 'h', 'u', 'b', '.', 'c', 'o', 'm', '/', 'c', 'n', 'c', 'f', '/', 'x', 'd', 's', '/', 'g', 'o', 
+'/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '\272', '\200', '\310', '\321', '\006', '\002', '\010', '\001', 'b', '\006', 'p', 'r', 'o', 
+'t', 'o', '3', 
 };
 
-static upb_def_init *deps[5] = {
+static upb_def_init *deps[3] = {
   &udpa_annotations_status_proto_upbdefinit,
-  &google_protobuf_any_proto_upbdefinit,
   &google_protobuf_descriptor_proto_upbdefinit,
-  &validate_validate_proto_upbdefinit,
   NULL
 };
 
@@ -52,5 +48,5 @@ upb_def_init udpa_annotations_security_proto_upbdefinit = {
   deps,
   layouts,
   "udpa/annotations/security.proto",
-  UPB_STRVIEW_INIT(descriptor, 469)
+  UPB_STRVIEW_INIT(descriptor, 453)
 };
index 4e6416b..c3a6e71 100644 (file)
 
 extern upb_def_init google_protobuf_descriptor_proto_upbdefinit;
 
-static const char descriptor[158] = {'\n', ' ', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 's', 'e', 'n', 's', 'i', 't', 
+static const char descriptor[196] = {'\n', ' ', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 's', 'e', 'n', 's', 'i', 't', 
 'i', 'v', 'e', '.', 'p', 'r', 'o', 't', 'o', '\022', '\020', 'u', 'd', 'p', 'a', '.', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 
 'n', 's', '\032', ' ', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 'd', 'e', 's', 'c', 'r', 
 'i', 'p', 't', 'o', 'r', '.', 'p', 'r', 'o', 't', 'o', ':', '>', '\n', '\t', 's', 'e', 'n', 's', 'i', 't', 'i', 'v', 'e', '\022', 
 '\035', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', 'd', 'O', 'p', 
 't', 'i', 'o', 'n', 's', '\030', '\367', '\266', '\301', '$', ' ', '\001', '(', '\010', 'R', '\t', 's', 'e', 'n', 's', 'i', 't', 'i', 'v', 'e', 
-'b', '\006', 'p', 'r', 'o', 't', 'o', '3', 
+'B', '$', 'Z', '\"', 'g', 'i', 't', 'h', 'u', 'b', '.', 'c', 'o', 'm', '/', 'c', 'n', 'c', 'f', '/', 'x', 'd', 's', '/', 'g', 
+'o', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', 
 };
 
 static upb_def_init *deps[2] = {
@@ -29,5 +30,5 @@ upb_def_init udpa_annotations_sensitive_proto_upbdefinit = {
   deps,
   NULL,
   "udpa/annotations/sensitive.proto",
-  UPB_STRVIEW_INIT(descriptor, 158)
+  UPB_STRVIEW_INIT(descriptor, 196)
 };
index f130145..72e114f 100644 (file)
@@ -16,7 +16,7 @@ static const upb_msglayout *layouts[1] = {
   &udpa_annotations_StatusAnnotation_msginit,
 };
 
-static const char descriptor[445] = {'\n', '\035', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 's', 't', 'a', 't', 'u', 's', 
+static const char descriptor[483] = {'\n', '\035', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 's', 't', 'a', 't', 'u', 's', 
 '.', 'p', 'r', 'o', 't', 'o', '\022', '\020', 'u', 'd', 'p', 'a', '.', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '\032', 
 ' ', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 
 'o', 'r', '.', 'p', 'r', 'o', 't', 'o', '\"', '\232', '\001', '\n', '\020', 'S', 't', 'a', 't', 'u', 's', 'A', 'n', 'n', 'o', 't', 'a', 
@@ -33,7 +33,9 @@ static const char descriptor[445] = {'\n', '\035', 'u', 'd', 'p', 'a', '/', 'a',
 '\022', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'l', 'e', 'O', 'p', 
 't', 'i', 'o', 'n', 's', '\030', '\207', '\200', '\231', 'j', ' ', '\001', '(', '\013', '2', '\"', '.', 'u', 'd', 'p', 'a', '.', 'a', 'n', 'n', 
 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '.', 'S', 't', 'a', 't', 'u', 's', 'A', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 
-'R', '\n', 'f', 'i', 'l', 'e', 'S', 't', 'a', 't', 'u', 's', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', 
+'R', '\n', 'f', 'i', 'l', 'e', 'S', 't', 'a', 't', 'u', 's', 'B', '$', 'Z', '\"', 'g', 'i', 't', 'h', 'u', 'b', '.', 'c', 'o', 
+'m', '/', 'c', 'n', 'c', 'f', '/', 'x', 'd', 's', '/', 'g', 'o', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', 
+'b', '\006', 'p', 'r', 'o', 't', 'o', '3', 
 };
 
 static upb_def_init *deps[2] = {
@@ -45,5 +47,5 @@ upb_def_init udpa_annotations_status_proto_upbdefinit = {
   deps,
   layouts,
   "udpa/annotations/status.proto",
-  UPB_STRVIEW_INIT(descriptor, 445)
+  UPB_STRVIEW_INIT(descriptor, 483)
 };
index b6de8fb..f15e63b 100644 (file)
@@ -16,7 +16,7 @@ static const upb_msglayout *layouts[1] = {
   &udpa_annotations_VersioningAnnotation_msginit,
 };
 
-static const char descriptor[279] = {'\n', '!', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 'v', 'e', 'r', 's', 'i', 'o', 
+static const char descriptor[317] = {'\n', '!', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 'v', 'e', 'r', 's', 'i', 'o', 
 'n', 'i', 'n', 'g', '.', 'p', 'r', 'o', 't', 'o', '\022', '\020', 'u', 'd', 'p', 'a', '.', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 
 'o', 'n', 's', '\032', ' ', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 'd', 'e', 's', 'c', 
 'r', 'i', 'p', 't', 'o', 'r', '.', 'p', 'r', 'o', 't', 'o', '\"', 'J', '\n', '\024', 'V', 'e', 'r', 's', 'i', 'o', 'n', 'i', 'n', 
@@ -26,8 +26,9 @@ static const char descriptor[279] = {'\n', '!', 'u', 'd', 'p', 'a', '/', 'a', 'n
 'n', 'g', '\022', '\037', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'M', 'e', 's', 's', 
 'a', 'g', 'e', 'O', 'p', 't', 'i', 'o', 'n', 's', '\030', '\323', '\210', '\341', '\003', ' ', '\001', '(', '\013', '2', '&', '.', 'u', 'd', 'p', 
 'a', '.', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '.', 'V', 'e', 'r', 's', 'i', 'o', 'n', 'i', 'n', 'g', 'A', 
-'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 'R', '\n', 'v', 'e', 'r', 's', 'i', 'o', 'n', 'i', 'n', 'g', 'b', '\006', 'p', 'r', 
-'o', 't', 'o', '3', 
+'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 'R', '\n', 'v', 'e', 'r', 's', 'i', 'o', 'n', 'i', 'n', 'g', 'B', '$', 'Z', '\"', 
+'g', 'i', 't', 'h', 'u', 'b', '.', 'c', 'o', 'm', '/', 'c', 'n', 'c', 'f', '/', 'x', 'd', 's', '/', 'g', 'o', '/', 'a', 'n', 
+'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', 
 };
 
 static upb_def_init *deps[2] = {
@@ -39,5 +40,5 @@ upb_def_init udpa_annotations_versioning_proto_upbdefinit = {
   deps,
   layouts,
   "udpa/annotations/versioning.proto",
-  UPB_STRVIEW_INIT(descriptor, 279)
+  UPB_STRVIEW_INIT(descriptor, 317)
 };
diff --git a/src/core/ext/upbdefs-generated/udpa/data/orca/v1/orca_load_report.upbdefs.c b/src/core/ext/upbdefs-generated/udpa/data/orca/v1/orca_load_report.upbdefs.c
deleted file mode 100644 (file)
index 86f430c..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/* This file was generated by upbc (the upb compiler) from the input
- * file:
- *
- *     udpa/data/orca/v1/orca_load_report.proto
- *
- * Do not edit -- your changes will be discarded when the file is
- * regenerated. */
-
-#include "upb/def.h"
-#include "udpa/data/orca/v1/orca_load_report.upbdefs.h"
-
-extern upb_def_init validate_validate_proto_upbdefinit;
-extern const upb_msglayout udpa_data_orca_v1_OrcaLoadReport_msginit;
-extern const upb_msglayout udpa_data_orca_v1_OrcaLoadReport_RequestCostEntry_msginit;
-extern const upb_msglayout udpa_data_orca_v1_OrcaLoadReport_UtilizationEntry_msginit;
-
-static const upb_msglayout *layouts[3] = {
-  &udpa_data_orca_v1_OrcaLoadReport_msginit,
-  &udpa_data_orca_v1_OrcaLoadReport_RequestCostEntry_msginit,
-  &udpa_data_orca_v1_OrcaLoadReport_UtilizationEntry_msginit,
-};
-
-static const char descriptor[674] = {'\n', '(', 'u', 'd', 'p', 'a', '/', 'd', 'a', 't', 'a', '/', 'o', 'r', 'c', 'a', '/', 'v', '1', '/', 'o', 'r', 'c', 'a', '_', 
-'l', 'o', 'a', 'd', '_', 'r', 'e', 'p', 'o', 'r', 't', '.', 'p', 'r', 'o', 't', 'o', '\022', '\021', 'u', 'd', 'p', 'a', '.', 'd', 
-'a', 't', 'a', '.', 'o', 'r', 'c', 'a', '.', 'v', '1', '\032', '\027', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '/', 'v', 'a', 'l', 
-'i', 'd', 'a', 't', 'e', '.', 'p', 'r', 'o', 't', 'o', '\"', '\205', '\004', '\n', '\016', 'O', 'r', 'c', 'a', 'L', 'o', 'a', 'd', 'R', 
-'e', 'p', 'o', 'r', 't', '\022', 'E', '\n', '\017', 'c', 'p', 'u', '_', 'u', 't', 'i', 'l', 'i', 'z', 'a', 't', 'i', 'o', 'n', '\030', 
-'\001', ' ', '\001', '(', '\001', 'B', '\034', '\372', 'B', '\013', '\022', '\t', ')', '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\372', 'B', '\013', '\022', 
-'\t', '\031', '\000', '\000', '\000', '\000', '\000', '\000', '\360', '?', 'R', '\016', 'c', 'p', 'u', 'U', 't', 'i', 'l', 'i', 'z', 'a', 't', 'i', 'o', 
-'n', '\022', 'E', '\n', '\017', 'm', 'e', 'm', '_', 'u', 't', 'i', 'l', 'i', 'z', 'a', 't', 'i', 'o', 'n', '\030', '\002', ' ', '\001', '(', 
-'\001', 'B', '\034', '\372', 'B', '\013', '\022', '\t', ')', '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\372', 'B', '\013', '\022', '\t', '\031', '\000', '\000', 
-'\000', '\000', '\000', '\000', '\360', '?', 'R', '\016', 'm', 'e', 'm', 'U', 't', 'i', 'l', 'i', 'z', 'a', 't', 'i', 'o', 'n', '\022', '\020', '\n', 
-'\003', 'r', 'p', 's', '\030', '\003', ' ', '\001', '(', '\004', 'R', '\003', 'r', 'p', 's', '\022', 'U', '\n', '\014', 'r', 'e', 'q', 'u', 'e', 's', 
-'t', '_', 'c', 'o', 's', 't', '\030', '\004', ' ', '\003', '(', '\013', '2', '2', '.', 'u', 'd', 'p', 'a', '.', 'd', 'a', 't', 'a', '.', 
-'o', 'r', 'c', 'a', '.', 'v', '1', '.', 'O', 'r', 'c', 'a', 'L', 'o', 'a', 'd', 'R', 'e', 'p', 'o', 'r', 't', '.', 'R', 'e', 
-'q', 'u', 'e', 's', 't', 'C', 'o', 's', 't', 'E', 'n', 't', 'r', 'y', 'R', '\013', 'r', 'e', 'q', 'u', 'e', 's', 't', 'C', 'o', 
-'s', 't', '\022', '|', '\n', '\013', 'u', 't', 'i', 'l', 'i', 'z', 'a', 't', 'i', 'o', 'n', '\030', '\005', ' ', '\003', '(', '\013', '2', '2', 
-'.', 'u', 'd', 'p', 'a', '.', 'd', 'a', 't', 'a', '.', 'o', 'r', 'c', 'a', '.', 'v', '1', '.', 'O', 'r', 'c', 'a', 'L', 'o', 
-'a', 'd', 'R', 'e', 'p', 'o', 'r', 't', '.', 'U', 't', 'i', 'l', 'i', 'z', 'a', 't', 'i', 'o', 'n', 'E', 'n', 't', 'r', 'y', 
-'B', '&', '\372', 'B', '\020', '\232', '\001', '\r', '*', '\013', '\022', '\t', ')', '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\372', 'B', '\020', '\232', 
-'\001', '\r', '*', '\013', '\022', '\t', '\031', '\000', '\000', '\000', '\000', '\000', '\000', '\360', '?', 'R', '\013', 'u', 't', 'i', 'l', 'i', 'z', 'a', 't', 
-'i', 'o', 'n', '\032', '>', '\n', '\020', 'R', 'e', 'q', 'u', 'e', 's', 't', 'C', 'o', 's', 't', 'E', 'n', 't', 'r', 'y', '\022', '\020', 
-'\n', '\003', 'k', 'e', 'y', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\003', 'k', 'e', 'y', '\022', '\024', '\n', '\005', 'v', 'a', 'l', 'u', 'e', 
-'\030', '\002', ' ', '\001', '(', '\001', 'R', '\005', 'v', 'a', 'l', 'u', 'e', ':', '\002', '8', '\001', '\032', '>', '\n', '\020', 'U', 't', 'i', 'l', 
-'i', 'z', 'a', 't', 'i', 'o', 'n', 'E', 'n', 't', 'r', 'y', '\022', '\020', '\n', '\003', 'k', 'e', 'y', '\030', '\001', ' ', '\001', '(', '\t', 
-'R', '\003', 'k', 'e', 'y', '\022', '\024', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\001', '(', '\001', 'R', '\005', 'v', 'a', 'l', 
-'u', 'e', ':', '\002', '8', '\001', 'B', ':', '\n', '!', 'c', 'o', 'm', '.', 'g', 'i', 't', 'h', 'u', 'b', '.', 'u', 'd', 'p', 'a', 
-'.', 'u', 'd', 'p', 'a', '.', 'd', 'a', 't', 'a', '.', 'o', 'r', 'c', 'a', '.', 'v', '1', 'B', '\023', 'O', 'r', 'c', 'a', 'L', 
-'o', 'a', 'd', 'R', 'e', 'p', 'o', 'r', 't', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', 
-};
-
-static upb_def_init *deps[2] = {
-  &validate_validate_proto_upbdefinit,
-  NULL
-};
-
-upb_def_init udpa_data_orca_v1_orca_load_report_proto_upbdefinit = {
-  deps,
-  layouts,
-  "udpa/data/orca/v1/orca_load_report.proto",
-  UPB_STRVIEW_INIT(descriptor, 674)
-};
diff --git a/src/core/ext/upbdefs-generated/udpa/data/orca/v1/orca_load_report.upbdefs.h b/src/core/ext/upbdefs-generated/udpa/data/orca/v1/orca_load_report.upbdefs.h
deleted file mode 100644 (file)
index f923742..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/* This file was generated by upbc (the upb compiler) from the input
- * file:
- *
- *     udpa/data/orca/v1/orca_load_report.proto
- *
- * Do not edit -- your changes will be discarded when the file is
- * regenerated. */
-
-#ifndef UDPA_DATA_ORCA_V1_ORCA_LOAD_REPORT_PROTO_UPBDEFS_H_
-#define UDPA_DATA_ORCA_V1_ORCA_LOAD_REPORT_PROTO_UPBDEFS_H_
-
-#include "upb/def.h"
-#include "upb/port_def.inc"
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "upb/def.h"
-
-#include "upb/port_def.inc"
-
-extern upb_def_init udpa_data_orca_v1_orca_load_report_proto_upbdefinit;
-
-UPB_INLINE const upb_msgdef *udpa_data_orca_v1_OrcaLoadReport_getmsgdef(upb_symtab *s) {
-  _upb_symtab_loaddefinit(s, &udpa_data_orca_v1_orca_load_report_proto_upbdefinit);
-  return upb_symtab_lookupmsg(s, "udpa.data.orca.v1.OrcaLoadReport");
-}
-
-UPB_INLINE const upb_msgdef *udpa_data_orca_v1_OrcaLoadReport_RequestCostEntry_getmsgdef(upb_symtab *s) {
-  _upb_symtab_loaddefinit(s, &udpa_data_orca_v1_orca_load_report_proto_upbdefinit);
-  return upb_symtab_lookupmsg(s, "udpa.data.orca.v1.OrcaLoadReport.RequestCostEntry");
-}
-
-UPB_INLINE const upb_msgdef *udpa_data_orca_v1_OrcaLoadReport_UtilizationEntry_getmsgdef(upb_symtab *s) {
-  _upb_symtab_loaddefinit(s, &udpa_data_orca_v1_orca_load_report_proto_upbdefinit);
-  return upb_symtab_lookupmsg(s, "udpa.data.orca.v1.OrcaLoadReport.UtilizationEntry");
-}
-
-#ifdef __cplusplus
-}  /* extern "C" */
-#endif
-
-#include "upb/port_undef.inc"
-
-#endif  /* UDPA_DATA_ORCA_V1_ORCA_LOAD_REPORT_PROTO_UPBDEFS_H_ */
diff --git a/src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.c b/src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.c
deleted file mode 100644 (file)
index f786bff..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/* This file was generated by upbc (the upb compiler) from the input
- * file:
- *
- *     udpa/type/v1/typed_struct.proto
- *
- * Do not edit -- your changes will be discarded when the file is
- * regenerated. */
-
-#include "upb/def.h"
-#include "udpa/type/v1/typed_struct.upbdefs.h"
-
-extern upb_def_init validate_validate_proto_upbdefinit;
-extern upb_def_init google_protobuf_struct_proto_upbdefinit;
-extern const upb_msglayout udpa_type_v1_TypedStruct_msginit;
-
-static const upb_msglayout *layouts[1] = {
-  &udpa_type_v1_TypedStruct_msginit,
-};
-
-static const char descriptor[251] = {'\n', '\037', 'u', 'd', 'p', 'a', '/', 't', 'y', 'p', 'e', '/', 'v', '1', '/', 't', 'y', 'p', 'e', 'd', '_', 's', 't', 'r', 'u', 
-'c', 't', '.', 'p', 'r', 'o', 't', 'o', '\022', '\014', 'u', 'd', 'p', 'a', '.', 't', 'y', 'p', 'e', '.', 'v', '1', '\032', '\027', 'v', 
-'a', 'l', 'i', 'd', 'a', 't', 'e', '/', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '.', 'p', 'r', 'o', 't', 'o', '\032', '\034', 'g', 
-'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 's', 't', 'r', 'u', 'c', 't', '.', 'p', 'r', 'o', 
-'t', 'o', '\"', 'W', '\n', '\013', 'T', 'y', 'p', 'e', 'd', 'S', 't', 'r', 'u', 'c', 't', '\022', '\031', '\n', '\010', 't', 'y', 'p', 'e', 
-'_', 'u', 'r', 'l', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\007', 't', 'y', 'p', 'e', 'U', 'r', 'l', '\022', '-', '\n', '\005', 'v', 'a', 
-'l', 'u', 'e', '\030', '\002', ' ', '\001', '(', '\013', '2', '\027', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 
-'u', 'f', '.', 'S', 't', 'r', 'u', 'c', 't', 'R', '\005', 'v', 'a', 'l', 'u', 'e', 'B', '2', '\n', '\034', 'c', 'o', 'm', '.', 'g', 
-'i', 't', 'h', 'u', 'b', '.', 'u', 'd', 'p', 'a', '.', 'u', 'd', 'p', 'a', '.', 't', 'y', 'p', 'e', '.', 'v', '1', 'B', '\020', 
-'T', 'y', 'p', 'e', 'd', 'S', 't', 'r', 'u', 'c', 't', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'b', '\006', 'p', 'r', 'o', 't', 'o', 
-'3', 
-};
-
-static upb_def_init *deps[3] = {
-  &validate_validate_proto_upbdefinit,
-  &google_protobuf_struct_proto_upbdefinit,
-  NULL
-};
-
-upb_def_init udpa_type_v1_typed_struct_proto_upbdefinit = {
-  deps,
-  layouts,
-  "udpa/type/v1/typed_struct.proto",
-  UPB_STRVIEW_INIT(descriptor, 251)
-};
diff --git a/src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.h b/src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.h
deleted file mode 100644 (file)
index d30baef..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/* This file was generated by upbc (the upb compiler) from the input
- * file:
- *
- *     udpa/type/v1/typed_struct.proto
- *
- * Do not edit -- your changes will be discarded when the file is
- * regenerated. */
-
-#ifndef UDPA_TYPE_V1_TYPED_STRUCT_PROTO_UPBDEFS_H_
-#define UDPA_TYPE_V1_TYPED_STRUCT_PROTO_UPBDEFS_H_
-
-#include "upb/def.h"
-#include "upb/port_def.inc"
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "upb/def.h"
-
-#include "upb/port_def.inc"
-
-extern upb_def_init udpa_type_v1_typed_struct_proto_upbdefinit;
-
-UPB_INLINE const upb_msgdef *udpa_type_v1_TypedStruct_getmsgdef(upb_symtab *s) {
-  _upb_symtab_loaddefinit(s, &udpa_type_v1_typed_struct_proto_upbdefinit);
-  return upb_symtab_lookupmsg(s, "udpa.type.v1.TypedStruct");
-}
-
-#ifdef __cplusplus
-}  /* extern "C" */
-#endif
-
-#include "upb/port_undef.inc"
-
-#endif  /* UDPA_TYPE_V1_TYPED_STRUCT_PROTO_UPBDEFS_H_ */
diff --git a/src/core/ext/upbdefs-generated/xds/annotations/v3/status.upbdefs.c b/src/core/ext/upbdefs-generated/xds/annotations/v3/status.upbdefs.c
new file mode 100644 (file)
index 0000000..125d2dd
--- /dev/null
@@ -0,0 +1,75 @@
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ *     xds/annotations/v3/status.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#include "upb/def.h"
+#include "xds/annotations/v3/status.upbdefs.h"
+
+extern upb_def_init google_protobuf_descriptor_proto_upbdefinit;
+extern const upb_msglayout xds_annotations_v3_FileStatusAnnotation_msginit;
+extern const upb_msglayout xds_annotations_v3_MessageStatusAnnotation_msginit;
+extern const upb_msglayout xds_annotations_v3_FieldStatusAnnotation_msginit;
+extern const upb_msglayout xds_annotations_v3_StatusAnnotation_msginit;
+
+static const upb_msglayout *layouts[4] = {
+  &xds_annotations_v3_FileStatusAnnotation_msginit,
+  &xds_annotations_v3_MessageStatusAnnotation_msginit,
+  &xds_annotations_v3_FieldStatusAnnotation_msginit,
+  &xds_annotations_v3_StatusAnnotation_msginit,
+};
+
+static const char descriptor[936] = {'\n', '\037', 'x', 'd', 's', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 'v', '3', '/', 's', 't', 'a', 't', 
+'u', 's', '.', 'p', 'r', 'o', 't', 'o', '\022', '\022', 'x', 'd', 's', '.', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', 
+'.', 'v', '3', '\032', ' ', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 'd', 'e', 's', 'c', 
+'r', 'i', 'p', 't', 'o', 'r', '.', 'p', 'r', 'o', 't', 'o', '\"', '@', '\n', '\024', 'F', 'i', 'l', 'e', 'S', 't', 'a', 't', 'u', 
+'s', 'A', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', '\022', '(', '\n', '\020', 'w', 'o', 'r', 'k', '_', 'i', 'n', '_', 'p', 'r', 
+'o', 'g', 'r', 'e', 's', 's', '\030', '\001', ' ', '\001', '(', '\010', 'R', '\016', 'w', 'o', 'r', 'k', 'I', 'n', 'P', 'r', 'o', 'g', 'r', 
+'e', 's', 's', '\"', 'C', '\n', '\027', 'M', 'e', 's', 's', 'a', 'g', 'e', 'S', 't', 'a', 't', 'u', 's', 'A', 'n', 'n', 'o', 't', 
+'a', 't', 'i', 'o', 'n', '\022', '(', '\n', '\020', 'w', 'o', 'r', 'k', '_', 'i', 'n', '_', 'p', 'r', 'o', 'g', 'r', 'e', 's', 's', 
+'\030', '\001', ' ', '\001', '(', '\010', 'R', '\016', 'w', 'o', 'r', 'k', 'I', 'n', 'P', 'r', 'o', 'g', 'r', 'e', 's', 's', '\"', 'A', '\n', 
+'\025', 'F', 'i', 'e', 'l', 'd', 'S', 't', 'a', 't', 'u', 's', 'A', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', '\022', '(', '\n', 
+'\020', 'w', 'o', 'r', 'k', '_', 'i', 'n', '_', 'p', 'r', 'o', 'g', 'r', 'e', 's', 's', '\030', '\001', ' ', '\001', '(', '\010', 'R', '\016', 
+'w', 'o', 'r', 'k', 'I', 'n', 'P', 'r', 'o', 'g', 'r', 'e', 's', 's', '\"', '\234', '\001', '\n', '\020', 'S', 't', 'a', 't', 'u', 's', 
+'A', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', '\022', '(', '\n', '\020', 'w', 'o', 'r', 'k', '_', 'i', 'n', '_', 'p', 'r', 'o', 
+'g', 'r', 'e', 's', 's', '\030', '\001', ' ', '\001', '(', '\010', 'R', '\016', 'w', 'o', 'r', 'k', 'I', 'n', 'P', 'r', 'o', 'g', 'r', 'e', 
+'s', 's', '\022', '^', '\n', '\026', 'p', 'a', 'c', 'k', 'a', 'g', 'e', '_', 'v', 'e', 'r', 's', 'i', 'o', 'n', '_', 's', 't', 'a', 
+'t', 'u', 's', '\030', '\002', ' ', '\001', '(', '\016', '2', '(', '.', 'x', 'd', 's', '.', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 
+'n', 's', '.', 'v', '3', '.', 'P', 'a', 'c', 'k', 'a', 'g', 'e', 'V', 'e', 'r', 's', 'i', 'o', 'n', 'S', 't', 'a', 't', 'u', 
+'s', 'R', '\024', 'p', 'a', 'c', 'k', 'a', 'g', 'e', 'V', 'e', 'r', 's', 'i', 'o', 'n', 'S', 't', 'a', 't', 'u', 's', '*', ']', 
+'\n', '\024', 'P', 'a', 'c', 'k', 'a', 'g', 'e', 'V', 'e', 'r', 's', 'i', 'o', 'n', 'S', 't', 'a', 't', 'u', 's', '\022', '\013', '\n', 
+'\007', 'U', 'N', 'K', 'N', 'O', 'W', 'N', '\020', '\000', '\022', '\n', '\n', '\006', 'F', 'R', 'O', 'Z', 'E', 'N', '\020', '\001', '\022', '\n', '\n', 
+'\006', 'A', 'C', 'T', 'I', 'V', 'E', '\020', '\002', '\022', ' ', '\n', '\034', 'N', 'E', 'X', 'T', '_', 'M', 'A', 'J', 'O', 'R', '_', 'V', 
+'E', 'R', 'S', 'I', 'O', 'N', '_', 'C', 'A', 'N', 'D', 'I', 'D', 'A', 'T', 'E', '\020', '\003', ':', 'j', '\n', '\013', 'f', 'i', 'l', 
+'e', '_', 's', 't', 'a', 't', 'u', 's', '\022', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 
+'f', '.', 'F', 'i', 'l', 'e', 'O', 'p', 't', 'i', 'o', 'n', 's', '\030', '\352', '\310', '\224', 'l', ' ', '\001', '(', '\013', '2', '(', '.', 
+'x', 'd', 's', '.', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '.', 'v', '3', '.', 'F', 'i', 'l', 'e', 'S', 't', 
+'a', 't', 'u', 's', 'A', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 'R', '\n', 'f', 'i', 'l', 'e', 'S', 't', 'a', 't', 'u', 
+'s', ':', 'v', '\n', '\016', 'm', 'e', 's', 's', 'a', 'g', 'e', '_', 's', 't', 'a', 't', 'u', 's', '\022', '\037', '.', 'g', 'o', 'o', 
+'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'M', 'e', 's', 's', 'a', 'g', 'e', 'O', 'p', 't', 'i', 'o', 
+'n', 's', '\030', '\352', '\310', '\224', 'l', ' ', '\001', '(', '\013', '2', '+', '.', 'x', 'd', 's', '.', 'a', 'n', 'n', 'o', 't', 'a', 't', 
+'i', 'o', 'n', 's', '.', 'v', '3', '.', 'M', 'e', 's', 's', 'a', 'g', 'e', 'S', 't', 'a', 't', 'u', 's', 'A', 'n', 'n', 'o', 
+'t', 'a', 't', 'i', 'o', 'n', 'R', '\r', 'm', 'e', 's', 's', 'a', 'g', 'e', 'S', 't', 'a', 't', 'u', 's', ':', 'n', '\n', '\014', 
+'f', 'i', 'e', 'l', 'd', '_', 's', 't', 'a', 't', 'u', 's', '\022', '\035', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 
+'t', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', 'd', 'O', 'p', 't', 'i', 'o', 'n', 's', '\030', '\352', '\310', '\224', 'l', ' ', '\001', 
+'(', '\013', '2', ')', '.', 'x', 'd', 's', '.', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '.', 'v', '3', '.', 'F', 
+'i', 'e', 'l', 'd', 'S', 't', 'a', 't', 'u', 's', 'A', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 'R', '\013', 'f', 'i', 'e', 
+'l', 'd', 'S', 't', 'a', 't', 'u', 's', 'B', '+', 'Z', ')', 'g', 'i', 't', 'h', 'u', 'b', '.', 'c', 'o', 'm', '/', 'c', 'n', 
+'c', 'f', '/', 'x', 'd', 's', '/', 'g', 'o', '/', 'x', 'd', 's', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', 
+'/', 'v', '3', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', 
+};
+
+static upb_def_init *deps[2] = {
+  &google_protobuf_descriptor_proto_upbdefinit,
+  NULL
+};
+
+upb_def_init xds_annotations_v3_status_proto_upbdefinit = {
+  deps,
+  layouts,
+  "xds/annotations/v3/status.proto",
+  UPB_STRVIEW_INIT(descriptor, 936)
+};
diff --git a/src/core/ext/upbdefs-generated/xds/annotations/v3/status.upbdefs.h b/src/core/ext/upbdefs-generated/xds/annotations/v3/status.upbdefs.h
new file mode 100644 (file)
index 0000000..03aefd2
--- /dev/null
@@ -0,0 +1,50 @@
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ *     xds/annotations/v3/status.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#ifndef XDS_ANNOTATIONS_V3_STATUS_PROTO_UPBDEFS_H_
+#define XDS_ANNOTATIONS_V3_STATUS_PROTO_UPBDEFS_H_
+
+#include "upb/def.h"
+#include "upb/port_def.inc"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "upb/def.h"
+
+#include "upb/port_def.inc"
+
+extern upb_def_init xds_annotations_v3_status_proto_upbdefinit;
+
+UPB_INLINE const upb_msgdef *xds_annotations_v3_FileStatusAnnotation_getmsgdef(upb_symtab *s) {
+  _upb_symtab_loaddefinit(s, &xds_annotations_v3_status_proto_upbdefinit);
+  return upb_symtab_lookupmsg(s, "xds.annotations.v3.FileStatusAnnotation");
+}
+
+UPB_INLINE const upb_msgdef *xds_annotations_v3_MessageStatusAnnotation_getmsgdef(upb_symtab *s) {
+  _upb_symtab_loaddefinit(s, &xds_annotations_v3_status_proto_upbdefinit);
+  return upb_symtab_lookupmsg(s, "xds.annotations.v3.MessageStatusAnnotation");
+}
+
+UPB_INLINE const upb_msgdef *xds_annotations_v3_FieldStatusAnnotation_getmsgdef(upb_symtab *s) {
+  _upb_symtab_loaddefinit(s, &xds_annotations_v3_status_proto_upbdefinit);
+  return upb_symtab_lookupmsg(s, "xds.annotations.v3.FieldStatusAnnotation");
+}
+
+UPB_INLINE const upb_msgdef *xds_annotations_v3_StatusAnnotation_getmsgdef(upb_symtab *s) {
+  _upb_symtab_loaddefinit(s, &xds_annotations_v3_status_proto_upbdefinit);
+  return upb_symtab_lookupmsg(s, "xds.annotations.v3.StatusAnnotation");
+}
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#include "upb/port_undef.inc"
+
+#endif  /* XDS_ANNOTATIONS_V3_STATUS_PROTO_UPBDEFS_H_ */
index 699ae7d..f0f3718 100644 (file)
@@ -9,7 +9,7 @@
 #include "upb/def.h"
 #include "xds/core/v3/authority.upbdefs.h"
 
-extern upb_def_init udpa_annotations_status_proto_upbdefinit;
+extern upb_def_init xds_annotations_v3_status_proto_upbdefinit;
 extern upb_def_init validate_validate_proto_upbdefinit;
 extern const upb_msglayout xds_core_v3_Authority_msginit;
 
@@ -17,19 +17,20 @@ static const upb_msglayout *layouts[1] = {
   &xds_core_v3_Authority_msginit,
 };
 
-static const char descriptor[205] = {'\n', '\033', 'x', 'd', 's', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '/', 'a', 'u', 't', 'h', 'o', 'r', 'i', 't', 'y', '.', 'p', 
-'r', 'o', 't', 'o', '\022', '\013', 'x', 'd', 's', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '\032', '\035', 'u', 'd', 'p', 'a', '/', 'a', 
-'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 's', 't', 'a', 't', 'u', 's', '.', 'p', 'r', 'o', 't', 'o', '\032', '\027', 
-'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '/', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '.', 'p', 'r', 'o', 't', 'o', '\"', '(', 
-'\n', '\t', 'A', 'u', 't', 'h', 'o', 'r', 'i', 't', 'y', '\022', '\033', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 
-'B', '\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\004', 'n', 'a', 'm', 'e', 'B', '7', '\n', '\033', 'c', 'o', 'm', '.', 'g', 'i', 
-'t', 'h', 'u', 'b', '.', 'u', 'd', 'p', 'a', '.', 'x', 'd', 's', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', 'B', '\016', 'A', 'u', 
-'t', 'h', 'o', 'r', 'i', 't', 'y', 'P', 'r', 'o', 't', 'o', 'P', '\001', '\272', '\200', '\310', '\321', '\006', '\002', '\010', '\001', 'b', '\006', 'p', 
-'r', 'o', 't', 'o', '3', 
+static const char descriptor[238] = {'\n', '\033', 'x', 'd', 's', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '/', 'a', 'u', 't', 'h', 'o', 'r', 'i', 't', 'y', '.', 'p', 
+'r', 'o', 't', 'o', '\022', '\013', 'x', 'd', 's', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '\032', '\037', 'x', 'd', 's', '/', 'a', 'n', 
+'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 'v', '3', '/', 's', 't', 'a', 't', 'u', 's', '.', 'p', 'r', 'o', 't', 'o', 
+'\032', '\027', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '/', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '.', 'p', 'r', 'o', 't', 'o', 
+'\"', '(', '\n', '\t', 'A', 'u', 't', 'h', 'o', 'r', 'i', 't', 'y', '\022', '\033', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', 
+'(', '\t', 'B', '\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\004', 'n', 'a', 'm', 'e', 'B', 'V', '\n', '\026', 'c', 'o', 'm', '.', 
+'g', 'i', 't', 'h', 'u', 'b', '.', 'x', 'd', 's', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', 'B', '\016', 'A', 'u', 't', 'h', 'o', 
+'r', 'i', 't', 'y', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', '\"', 'g', 'i', 't', 'h', 'u', 'b', '.', 'c', 'o', 'm', '/', 'c', 
+'n', 'c', 'f', '/', 'x', 'd', 's', '/', 'g', 'o', '/', 'x', 'd', 's', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '\322', '\306', '\244', 
+'\341', '\006', '\002', '\010', '\001', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', 
 };
 
 static upb_def_init *deps[3] = {
-  &udpa_annotations_status_proto_upbdefinit,
+  &xds_annotations_v3_status_proto_upbdefinit,
   &validate_validate_proto_upbdefinit,
   NULL
 };
@@ -38,5 +39,5 @@ upb_def_init xds_core_v3_authority_proto_upbdefinit = {
   deps,
   layouts,
   "xds/core/v3/authority.proto",
-  UPB_STRVIEW_INIT(descriptor, 205)
+  UPB_STRVIEW_INIT(descriptor, 238)
 };
index 93d0581..c1b69dc 100644 (file)
@@ -10,7 +10,7 @@
 #include "xds/core/v3/collection_entry.upbdefs.h"
 
 extern upb_def_init google_protobuf_any_proto_upbdefinit;
-extern upb_def_init udpa_annotations_status_proto_upbdefinit;
+extern upb_def_init xds_annotations_v3_status_proto_upbdefinit;
 extern upb_def_init xds_core_v3_resource_locator_proto_upbdefinit;
 extern upb_def_init validate_validate_proto_upbdefinit;
 extern const upb_msglayout xds_core_v3_CollectionEntry_msginit;
@@ -21,34 +21,35 @@ static const upb_msglayout *layouts[2] = {
   &xds_core_v3_CollectionEntry_InlineEntry_msginit,
 };
 
-static const char descriptor[565] = {'\n', '\"', 'x', 'd', 's', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '/', 'c', 'o', 'l', 'l', 'e', 'c', 't', 'i', 'o', 'n', '_', 
+static const char descriptor[598] = {'\n', '\"', 'x', 'd', 's', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '/', 'c', 'o', 'l', 'l', 'e', 'c', 't', 'i', 'o', 'n', '_', 
 'e', 'n', 't', 'r', 'y', '.', 'p', 'r', 'o', 't', 'o', '\022', '\013', 'x', 'd', 's', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '\032', 
 '\031', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 'a', 'n', 'y', '.', 'p', 'r', 'o', 't', 
-'o', '\032', '\035', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 's', 't', 'a', 't', 'u', 
-'s', '.', 'p', 'r', 'o', 't', 'o', '\032', '\"', 'x', 'd', 's', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '/', 'r', 'e', 's', 'o', 
-'u', 'r', 'c', 'e', '_', 'l', 'o', 'c', 'a', 't', 'o', 'r', '.', 'p', 'r', 'o', 't', 'o', '\032', '\027', 'v', 'a', 'l', 'i', 'd', 
-'a', 't', 'e', '/', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '.', 'p', 'r', 'o', 't', 'o', '\"', '\303', '\002', '\n', '\017', 'C', 'o', 
-'l', 'l', 'e', 'c', 't', 'i', 'o', 'n', 'E', 'n', 't', 'r', 'y', '\022', '8', '\n', '\007', 'l', 'o', 'c', 'a', 't', 'o', 'r', '\030', 
-'\001', ' ', '\001', '(', '\013', '2', '\034', '.', 'x', 'd', 's', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'R', 'e', 's', 'o', 'u', 
-'r', 'c', 'e', 'L', 'o', 'c', 'a', 't', 'o', 'r', 'H', '\000', 'R', '\007', 'l', 'o', 'c', 'a', 't', 'o', 'r', '\022', 'M', '\n', '\014', 
-'i', 'n', 'l', 'i', 'n', 'e', '_', 'e', 'n', 't', 'r', 'y', '\030', '\002', ' ', '\001', '(', '\013', '2', '(', '.', 'x', 'd', 's', '.', 
-'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'C', 'o', 'l', 'l', 'e', 'c', 't', 'i', 'o', 'n', 'E', 'n', 't', 'r', 'y', '.', 'I', 
-'n', 'l', 'i', 'n', 'e', 'E', 'n', 't', 'r', 'y', 'H', '\000', 'R', '\013', 'i', 'n', 'l', 'i', 'n', 'e', 'E', 'n', 't', 'r', 'y', 
-'\032', '\213', '\001', '\n', '\013', 'I', 'n', 'l', 'i', 'n', 'e', 'E', 'n', 't', 'r', 'y', '\022', '0', '\n', '\004', 'n', 'a', 'm', 'e', '\030', 
-'\001', ' ', '\001', '(', '\t', 'B', '\034', '\372', 'B', '\031', 'r', '\027', '2', '\025', '^', '[', '0', '-', '9', 'a', '-', 'z', 'A', '-', 'Z', 
-'_', '\\', '-', '\\', '.', '~', ':', ']', '+', '$', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '\030', '\n', '\007', 'v', 'e', 'r', 's', 'i', 
-'o', 'n', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\007', 'v', 'e', 'r', 's', 'i', 'o', 'n', '\022', '0', '\n', '\010', 'r', 'e', 's', 'o', 
-'u', 'r', 'c', 'e', '\030', '\003', ' ', '\001', '(', '\013', '2', '\024', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 
-'b', 'u', 'f', '.', 'A', 'n', 'y', 'R', '\010', 'r', 'e', 's', 'o', 'u', 'r', 'c', 'e', 'B', '\031', '\n', '\022', 'r', 'e', 's', 'o', 
-'u', 'r', 'c', 'e', '_', 's', 'p', 'e', 'c', 'i', 'f', 'i', 'e', 'r', '\022', '\003', '\370', 'B', '\001', 'B', '=', '\n', '\033', 'c', 'o', 
-'m', '.', 'g', 'i', 't', 'h', 'u', 'b', '.', 'u', 'd', 'p', 'a', '.', 'x', 'd', 's', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', 
-'B', '\024', 'C', 'o', 'l', 'l', 'e', 'c', 't', 'i', 'o', 'n', 'E', 'n', 't', 'r', 'y', 'P', 'r', 'o', 't', 'o', 'P', '\001', '\272', 
-'\200', '\310', '\321', '\006', '\002', '\010', '\001', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', 
+'o', '\032', '\037', 'x', 'd', 's', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 'v', '3', '/', 's', 't', 'a', 
+'t', 'u', 's', '.', 'p', 'r', 'o', 't', 'o', '\032', '\"', 'x', 'd', 's', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '/', 'r', 'e', 
+'s', 'o', 'u', 'r', 'c', 'e', '_', 'l', 'o', 'c', 'a', 't', 'o', 'r', '.', 'p', 'r', 'o', 't', 'o', '\032', '\027', 'v', 'a', 'l', 
+'i', 'd', 'a', 't', 'e', '/', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '.', 'p', 'r', 'o', 't', 'o', '\"', '\303', '\002', '\n', '\017', 
+'C', 'o', 'l', 'l', 'e', 'c', 't', 'i', 'o', 'n', 'E', 'n', 't', 'r', 'y', '\022', '8', '\n', '\007', 'l', 'o', 'c', 'a', 't', 'o', 
+'r', '\030', '\001', ' ', '\001', '(', '\013', '2', '\034', '.', 'x', 'd', 's', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'R', 'e', 's', 
+'o', 'u', 'r', 'c', 'e', 'L', 'o', 'c', 'a', 't', 'o', 'r', 'H', '\000', 'R', '\007', 'l', 'o', 'c', 'a', 't', 'o', 'r', '\022', 'M', 
+'\n', '\014', 'i', 'n', 'l', 'i', 'n', 'e', '_', 'e', 'n', 't', 'r', 'y', '\030', '\002', ' ', '\001', '(', '\013', '2', '(', '.', 'x', 'd', 
+'s', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'C', 'o', 'l', 'l', 'e', 'c', 't', 'i', 'o', 'n', 'E', 'n', 't', 'r', 'y', 
+'.', 'I', 'n', 'l', 'i', 'n', 'e', 'E', 'n', 't', 'r', 'y', 'H', '\000', 'R', '\013', 'i', 'n', 'l', 'i', 'n', 'e', 'E', 'n', 't', 
+'r', 'y', '\032', '\213', '\001', '\n', '\013', 'I', 'n', 'l', 'i', 'n', 'e', 'E', 'n', 't', 'r', 'y', '\022', '0', '\n', '\004', 'n', 'a', 'm', 
+'e', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\034', '\372', 'B', '\031', 'r', '\027', '2', '\025', '^', '[', '0', '-', '9', 'a', '-', 'z', 'A', 
+'-', 'Z', '_', '\\', '-', '\\', '.', '~', ':', ']', '+', '$', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '\030', '\n', '\007', 'v', 'e', 'r', 
+'s', 'i', 'o', 'n', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\007', 'v', 'e', 'r', 's', 'i', 'o', 'n', '\022', '0', '\n', '\010', 'r', 'e', 
+'s', 'o', 'u', 'r', 'c', 'e', '\030', '\003', ' ', '\001', '(', '\013', '2', '\024', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 
+'t', 'o', 'b', 'u', 'f', '.', 'A', 'n', 'y', 'R', '\010', 'r', 'e', 's', 'o', 'u', 'r', 'c', 'e', 'B', '\031', '\n', '\022', 'r', 'e', 
+'s', 'o', 'u', 'r', 'c', 'e', '_', 's', 'p', 'e', 'c', 'i', 'f', 'i', 'e', 'r', '\022', '\003', '\370', 'B', '\001', 'B', '\\', '\n', '\026', 
+'c', 'o', 'm', '.', 'g', 'i', 't', 'h', 'u', 'b', '.', 'x', 'd', 's', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', 'B', '\024', 'C', 
+'o', 'l', 'l', 'e', 'c', 't', 'i', 'o', 'n', 'E', 'n', 't', 'r', 'y', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', '\"', 'g', 'i', 
+'t', 'h', 'u', 'b', '.', 'c', 'o', 'm', '/', 'c', 'n', 'c', 'f', '/', 'x', 'd', 's', '/', 'g', 'o', '/', 'x', 'd', 's', '/', 
+'c', 'o', 'r', 'e', '/', 'v', '3', '\322', '\306', '\244', '\341', '\006', '\002', '\010', '\001', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', 
 };
 
 static upb_def_init *deps[5] = {
   &google_protobuf_any_proto_upbdefinit,
-  &udpa_annotations_status_proto_upbdefinit,
+  &xds_annotations_v3_status_proto_upbdefinit,
   &xds_core_v3_resource_locator_proto_upbdefinit,
   &validate_validate_proto_upbdefinit,
   NULL
@@ -58,5 +59,5 @@ upb_def_init xds_core_v3_collection_entry_proto_upbdefinit = {
   deps,
   layouts,
   "xds/core/v3/collection_entry.proto",
-  UPB_STRVIEW_INIT(descriptor, 565)
+  UPB_STRVIEW_INIT(descriptor, 598)
 };
index 0c6584b..8de973d 100644 (file)
@@ -9,7 +9,7 @@
 #include "upb/def.h"
 #include "xds/core/v3/context_params.upbdefs.h"
 
-extern upb_def_init udpa_annotations_status_proto_upbdefinit;
+extern upb_def_init xds_annotations_v3_status_proto_upbdefinit;
 extern const upb_msglayout xds_core_v3_ContextParams_msginit;
 extern const upb_msglayout xds_core_v3_ContextParams_ParamsEntry_msginit;
 
@@ -18,22 +18,23 @@ static const upb_msglayout *layouts[2] = {
   &xds_core_v3_ContextParams_ParamsEntry_msginit,
 };
 
-static const char descriptor[288] = {'\n', ' ', 'x', 'd', 's', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '/', 'c', 'o', 'n', 't', 'e', 'x', 't', '_', 'p', 'a', 'r', 
-'a', 'm', 's', '.', 'p', 'r', 'o', 't', 'o', '\022', '\013', 'x', 'd', 's', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '\032', '\035', 'u', 
-'d', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 's', 't', 'a', 't', 'u', 's', '.', 'p', 'r', 
-'o', 't', 'o', '\"', '\212', '\001', '\n', '\r', 'C', 'o', 'n', 't', 'e', 'x', 't', 'P', 'a', 'r', 'a', 'm', 's', '\022', '>', '\n', '\006', 
-'p', 'a', 'r', 'a', 'm', 's', '\030', '\001', ' ', '\003', '(', '\013', '2', '&', '.', 'x', 'd', 's', '.', 'c', 'o', 'r', 'e', '.', 'v', 
-'3', '.', 'C', 'o', 'n', 't', 'e', 'x', 't', 'P', 'a', 'r', 'a', 'm', 's', '.', 'P', 'a', 'r', 'a', 'm', 's', 'E', 'n', 't', 
-'r', 'y', 'R', '\006', 'p', 'a', 'r', 'a', 'm', 's', '\032', '9', '\n', '\013', 'P', 'a', 'r', 'a', 'm', 's', 'E', 'n', 't', 'r', 'y', 
-'\022', '\020', '\n', '\003', 'k', 'e', 'y', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\003', 'k', 'e', 'y', '\022', '\024', '\n', '\005', 'v', 'a', 'l', 
-'u', 'e', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\005', 'v', 'a', 'l', 'u', 'e', ':', '\002', '8', '\001', 'B', ';', '\n', '\033', 'c', 'o', 
-'m', '.', 'g', 'i', 't', 'h', 'u', 'b', '.', 'u', 'd', 'p', 'a', '.', 'x', 'd', 's', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', 
-'B', '\022', 'C', 'o', 'n', 't', 'e', 'x', 't', 'P', 'a', 'r', 'a', 'm', 's', 'P', 'r', 'o', 't', 'o', 'P', '\001', '\272', '\200', '\310', 
-'\321', '\006', '\002', '\010', '\001', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', 
+static const char descriptor[321] = {'\n', ' ', 'x', 'd', 's', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '/', 'c', 'o', 'n', 't', 'e', 'x', 't', '_', 'p', 'a', 'r', 
+'a', 'm', 's', '.', 'p', 'r', 'o', 't', 'o', '\022', '\013', 'x', 'd', 's', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '\032', '\037', 'x', 
+'d', 's', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 'v', '3', '/', 's', 't', 'a', 't', 'u', 's', '.', 
+'p', 'r', 'o', 't', 'o', '\"', '\212', '\001', '\n', '\r', 'C', 'o', 'n', 't', 'e', 'x', 't', 'P', 'a', 'r', 'a', 'm', 's', '\022', '>', 
+'\n', '\006', 'p', 'a', 'r', 'a', 'm', 's', '\030', '\001', ' ', '\003', '(', '\013', '2', '&', '.', 'x', 'd', 's', '.', 'c', 'o', 'r', 'e', 
+'.', 'v', '3', '.', 'C', 'o', 'n', 't', 'e', 'x', 't', 'P', 'a', 'r', 'a', 'm', 's', '.', 'P', 'a', 'r', 'a', 'm', 's', 'E', 
+'n', 't', 'r', 'y', 'R', '\006', 'p', 'a', 'r', 'a', 'm', 's', '\032', '9', '\n', '\013', 'P', 'a', 'r', 'a', 'm', 's', 'E', 'n', 't', 
+'r', 'y', '\022', '\020', '\n', '\003', 'k', 'e', 'y', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\003', 'k', 'e', 'y', '\022', '\024', '\n', '\005', 'v', 
+'a', 'l', 'u', 'e', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\005', 'v', 'a', 'l', 'u', 'e', ':', '\002', '8', '\001', 'B', 'Z', '\n', '\026', 
+'c', 'o', 'm', '.', 'g', 'i', 't', 'h', 'u', 'b', '.', 'x', 'd', 's', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', 'B', '\022', 'C', 
+'o', 'n', 't', 'e', 'x', 't', 'P', 'a', 'r', 'a', 'm', 's', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', '\"', 'g', 'i', 't', 'h', 
+'u', 'b', '.', 'c', 'o', 'm', '/', 'c', 'n', 'c', 'f', '/', 'x', 'd', 's', '/', 'g', 'o', '/', 'x', 'd', 's', '/', 'c', 'o', 
+'r', 'e', '/', 'v', '3', '\322', '\306', '\244', '\341', '\006', '\002', '\010', '\001', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', 
 };
 
 static upb_def_init *deps[2] = {
-  &udpa_annotations_status_proto_upbdefinit,
+  &xds_annotations_v3_status_proto_upbdefinit,
   NULL
 };
 
@@ -41,5 +42,5 @@ upb_def_init xds_core_v3_context_params_proto_upbdefinit = {
   deps,
   layouts,
   "xds/core/v3/context_params.proto",
-  UPB_STRVIEW_INIT(descriptor, 288)
+  UPB_STRVIEW_INIT(descriptor, 321)
 };
index d299981..079995b 100644 (file)
@@ -10,7 +10,7 @@
 #include "xds/core/v3/resource.upbdefs.h"
 
 extern upb_def_init google_protobuf_any_proto_upbdefinit;
-extern upb_def_init udpa_annotations_status_proto_upbdefinit;
+extern upb_def_init xds_annotations_v3_status_proto_upbdefinit;
 extern upb_def_init xds_core_v3_resource_name_proto_upbdefinit;
 extern const upb_msglayout xds_core_v3_Resource_msginit;
 
@@ -18,25 +18,26 @@ static const upb_msglayout *layouts[1] = {
   &xds_core_v3_Resource_msginit,
 };
 
-static const char descriptor[332] = {'\n', '\032', 'x', 'd', 's', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '/', 'r', 'e', 's', 'o', 'u', 'r', 'c', 'e', '.', 'p', 'r', 
+static const char descriptor[365] = {'\n', '\032', 'x', 'd', 's', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '/', 'r', 'e', 's', 'o', 'u', 'r', 'c', 'e', '.', 'p', 'r', 
 'o', 't', 'o', '\022', '\013', 'x', 'd', 's', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '\032', '\031', 'g', 'o', 'o', 'g', 'l', 'e', '/', 
-'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 'a', 'n', 'y', '.', 'p', 'r', 'o', 't', 'o', '\032', '\035', 'u', 'd', 'p', 'a', '/', 
-'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 's', 't', 'a', 't', 'u', 's', '.', 'p', 'r', 'o', 't', 'o', '\032', 
-'\037', 'x', 'd', 's', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '/', 'r', 'e', 's', 'o', 'u', 'r', 'c', 'e', '_', 'n', 'a', 'm', 
-'e', '.', 'p', 'r', 'o', 't', 'o', '\"', '\205', '\001', '\n', '\010', 'R', 'e', 's', 'o', 'u', 'r', 'c', 'e', '\022', '-', '\n', '\004', 'n', 
-'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\013', '2', '\031', '.', 'x', 'd', 's', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'R', 
-'e', 's', 'o', 'u', 'r', 'c', 'e', 'N', 'a', 'm', 'e', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '\030', '\n', '\007', 'v', 'e', 'r', 's', 
-'i', 'o', 'n', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\007', 'v', 'e', 'r', 's', 'i', 'o', 'n', '\022', '0', '\n', '\010', 'r', 'e', 's', 
-'o', 'u', 'r', 'c', 'e', '\030', '\003', ' ', '\001', '(', '\013', '2', '\024', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 
-'o', 'b', 'u', 'f', '.', 'A', 'n', 'y', 'R', '\010', 'r', 'e', 's', 'o', 'u', 'r', 'c', 'e', 'B', '6', '\n', '\033', 'c', 'o', 'm', 
-'.', 'g', 'i', 't', 'h', 'u', 'b', '.', 'u', 'd', 'p', 'a', '.', 'x', 'd', 's', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', 'B', 
-'\r', 'R', 'e', 's', 'o', 'u', 'r', 'c', 'e', 'P', 'r', 'o', 't', 'o', 'P', '\001', '\272', '\200', '\310', '\321', '\006', '\002', '\010', '\001', 'b', 
-'\006', 'p', 'r', 'o', 't', 'o', '3', 
+'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 'a', 'n', 'y', '.', 'p', 'r', 'o', 't', 'o', '\032', '\037', 'x', 'd', 's', '/', 'a', 
+'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 'v', '3', '/', 's', 't', 'a', 't', 'u', 's', '.', 'p', 'r', 'o', 't', 
+'o', '\032', '\037', 'x', 'd', 's', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '/', 'r', 'e', 's', 'o', 'u', 'r', 'c', 'e', '_', 'n', 
+'a', 'm', 'e', '.', 'p', 'r', 'o', 't', 'o', '\"', '\205', '\001', '\n', '\010', 'R', 'e', 's', 'o', 'u', 'r', 'c', 'e', '\022', '-', '\n', 
+'\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\013', '2', '\031', '.', 'x', 'd', 's', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', 
+'.', 'R', 'e', 's', 'o', 'u', 'r', 'c', 'e', 'N', 'a', 'm', 'e', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '\030', '\n', '\007', 'v', 'e', 
+'r', 's', 'i', 'o', 'n', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\007', 'v', 'e', 'r', 's', 'i', 'o', 'n', '\022', '0', '\n', '\010', 'r', 
+'e', 's', 'o', 'u', 'r', 'c', 'e', '\030', '\003', ' ', '\001', '(', '\013', '2', '\024', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 
+'o', 't', 'o', 'b', 'u', 'f', '.', 'A', 'n', 'y', 'R', '\010', 'r', 'e', 's', 'o', 'u', 'r', 'c', 'e', 'B', 'U', '\n', '\026', 'c', 
+'o', 'm', '.', 'g', 'i', 't', 'h', 'u', 'b', '.', 'x', 'd', 's', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', 'B', '\r', 'R', 'e', 
+'s', 'o', 'u', 'r', 'c', 'e', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', '\"', 'g', 'i', 't', 'h', 'u', 'b', '.', 'c', 'o', 'm', 
+'/', 'c', 'n', 'c', 'f', '/', 'x', 'd', 's', '/', 'g', 'o', '/', 'x', 'd', 's', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '\322', 
+'\306', '\244', '\341', '\006', '\002', '\010', '\001', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', 
 };
 
 static upb_def_init *deps[4] = {
   &google_protobuf_any_proto_upbdefinit,
-  &udpa_annotations_status_proto_upbdefinit,
+  &xds_annotations_v3_status_proto_upbdefinit,
   &xds_core_v3_resource_name_proto_upbdefinit,
   NULL
 };
@@ -45,5 +46,5 @@ upb_def_init xds_core_v3_resource_proto_upbdefinit = {
   deps,
   layouts,
   "xds/core/v3/resource.proto",
-  UPB_STRVIEW_INIT(descriptor, 332)
+  UPB_STRVIEW_INIT(descriptor, 365)
 };
index fefa5a2..e123454 100644 (file)
@@ -9,7 +9,7 @@
 #include "upb/def.h"
 #include "xds/core/v3/resource_locator.upbdefs.h"
 
-extern upb_def_init udpa_annotations_status_proto_upbdefinit;
+extern upb_def_init xds_annotations_v3_status_proto_upbdefinit;
 extern upb_def_init xds_core_v3_context_params_proto_upbdefinit;
 extern upb_def_init validate_validate_proto_upbdefinit;
 extern const upb_msglayout xds_core_v3_ResourceLocator_msginit;
@@ -20,40 +20,41 @@ static const upb_msglayout *layouts[2] = {
   &xds_core_v3_ResourceLocator_Directive_msginit,
 };
 
-static const char descriptor[739] = {'\n', '\"', 'x', 'd', 's', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '/', 'r', 'e', 's', 'o', 'u', 'r', 'c', 'e', '_', 'l', 'o', 
+static const char descriptor[772] = {'\n', '\"', 'x', 'd', 's', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '/', 'r', 'e', 's', 'o', 'u', 'r', 'c', 'e', '_', 'l', 'o', 
 'c', 'a', 't', 'o', 'r', '.', 'p', 'r', 'o', 't', 'o', '\022', '\013', 'x', 'd', 's', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '\032', 
-'\035', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 's', 't', 'a', 't', 'u', 's', '.', 
-'p', 'r', 'o', 't', 'o', '\032', ' ', 'x', 'd', 's', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '/', 'c', 'o', 'n', 't', 'e', 'x', 
-'t', '_', 'p', 'a', 'r', 'a', 'm', 's', '.', 'p', 'r', 'o', 't', 'o', '\032', '\027', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '/', 
-'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '.', 'p', 'r', 'o', 't', 'o', '\"', '\216', '\004', '\n', '\017', 'R', 'e', 's', 'o', 'u', 'r', 
-'c', 'e', 'L', 'o', 'c', 'a', 't', 'o', 'r', '\022', 'E', '\n', '\006', 's', 'c', 'h', 'e', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\016', 
-'2', '#', '.', 'x', 'd', 's', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'R', 'e', 's', 'o', 'u', 'r', 'c', 'e', 'L', 'o', 
-'c', 'a', 't', 'o', 'r', '.', 'S', 'c', 'h', 'e', 'm', 'e', 'B', '\010', '\372', 'B', '\005', '\202', '\001', '\002', '\020', '\001', 'R', '\006', 's', 
-'c', 'h', 'e', 'm', 'e', '\022', '\016', '\n', '\002', 'i', 'd', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\002', 'i', 'd', '\022', '\034', '\n', '\t', 
-'a', 'u', 't', 'h', 'o', 'r', 'i', 't', 'y', '\030', '\003', ' ', '\001', '(', '\t', 'R', '\t', 'a', 'u', 't', 'h', 'o', 'r', 'i', 't', 
-'y', '\022', ',', '\n', '\r', 'r', 'e', 's', 'o', 'u', 'r', 'c', 'e', '_', 't', 'y', 'p', 'e', '\030', '\004', ' ', '\001', '(', '\t', 'B', 
-'\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\014', 'r', 'e', 's', 'o', 'u', 'r', 'c', 'e', 'T', 'y', 'p', 'e', '\022', 'A', '\n', 
-'\r', 'e', 'x', 'a', 'c', 't', '_', 'c', 'o', 'n', 't', 'e', 'x', 't', '\030', '\005', ' ', '\001', '(', '\013', '2', '\032', '.', 'x', 'd', 
-'s', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'C', 'o', 'n', 't', 'e', 'x', 't', 'P', 'a', 'r', 'a', 'm', 's', 'H', '\000', 
-'R', '\014', 'e', 'x', 'a', 'c', 't', 'C', 'o', 'n', 't', 'e', 'x', 't', '\022', 'F', '\n', '\n', 'd', 'i', 'r', 'e', 'c', 't', 'i', 
-'v', 'e', 's', '\030', '\006', ' ', '\003', '(', '\013', '2', '&', '.', 'x', 'd', 's', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'R', 
-'e', 's', 'o', 'u', 'r', 'c', 'e', 'L', 'o', 'c', 'a', 't', 'o', 'r', '.', 'D', 'i', 'r', 'e', 'c', 't', 'i', 'v', 'e', 'R', 
-'\n', 'd', 'i', 'r', 'e', 'c', 't', 'i', 'v', 'e', 's', '\032', '\210', '\001', '\n', '\t', 'D', 'i', 'r', 'e', 'c', 't', 'i', 'v', 'e', 
-'\022', '0', '\n', '\003', 'a', 'l', 't', '\030', '\001', ' ', '\001', '(', '\013', '2', '\034', '.', 'x', 'd', 's', '.', 'c', 'o', 'r', 'e', '.', 
-'v', '3', '.', 'R', 'e', 's', 'o', 'u', 'r', 'c', 'e', 'L', 'o', 'c', 'a', 't', 'o', 'r', 'H', '\000', 'R', '\003', 'a', 'l', 't', 
-'\022', '7', '\n', '\005', 'e', 'n', 't', 'r', 'y', '\030', '\002', ' ', '\001', '(', '\t', 'B', '\037', '\372', 'B', '\034', 'r', '\032', '\020', '\001', '2', 
-'\026', '^', '[', '0', '-', '9', 'a', '-', 'z', 'A', '-', 'Z', '_', '\\', '-', '\\', '.', '/', '~', ':', ']', '+', '$', 'H', '\000', 
-'R', '\005', 'e', 'n', 't', 'r', 'y', 'B', '\020', '\n', '\t', 'd', 'i', 'r', 'e', 'c', 't', 'i', 'v', 'e', '\022', '\003', '\370', 'B', '\001', 
-'\"', '\'', '\n', '\006', 'S', 'c', 'h', 'e', 'm', 'e', '\022', '\t', '\n', '\005', 'X', 'D', 'S', 'T', 'P', '\020', '\000', '\022', '\010', '\n', '\004', 
-'H', 'T', 'T', 'P', '\020', '\001', '\022', '\010', '\n', '\004', 'F', 'I', 'L', 'E', '\020', '\002', 'B', '\031', '\n', '\027', 'c', 'o', 'n', 't', 'e', 
-'x', 't', '_', 'p', 'a', 'r', 'a', 'm', '_', 's', 'p', 'e', 'c', 'i', 'f', 'i', 'e', 'r', 'B', '=', '\n', '\033', 'c', 'o', 'm', 
-'.', 'g', 'i', 't', 'h', 'u', 'b', '.', 'u', 'd', 'p', 'a', '.', 'x', 'd', 's', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', 'B', 
-'\024', 'R', 'e', 's', 'o', 'u', 'r', 'c', 'e', 'L', 'o', 'c', 'a', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 'P', '\001', '\272', '\200', 
-'\310', '\321', '\006', '\002', '\010', '\001', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', 
+'\037', 'x', 'd', 's', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 'v', '3', '/', 's', 't', 'a', 't', 'u', 
+'s', '.', 'p', 'r', 'o', 't', 'o', '\032', ' ', 'x', 'd', 's', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '/', 'c', 'o', 'n', 't', 
+'e', 'x', 't', '_', 'p', 'a', 'r', 'a', 'm', 's', '.', 'p', 'r', 'o', 't', 'o', '\032', '\027', 'v', 'a', 'l', 'i', 'd', 'a', 't', 
+'e', '/', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '.', 'p', 'r', 'o', 't', 'o', '\"', '\216', '\004', '\n', '\017', 'R', 'e', 's', 'o', 
+'u', 'r', 'c', 'e', 'L', 'o', 'c', 'a', 't', 'o', 'r', '\022', 'E', '\n', '\006', 's', 'c', 'h', 'e', 'm', 'e', '\030', '\001', ' ', '\001', 
+'(', '\016', '2', '#', '.', 'x', 'd', 's', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'R', 'e', 's', 'o', 'u', 'r', 'c', 'e', 
+'L', 'o', 'c', 'a', 't', 'o', 'r', '.', 'S', 'c', 'h', 'e', 'm', 'e', 'B', '\010', '\372', 'B', '\005', '\202', '\001', '\002', '\020', '\001', 'R', 
+'\006', 's', 'c', 'h', 'e', 'm', 'e', '\022', '\016', '\n', '\002', 'i', 'd', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\002', 'i', 'd', '\022', '\034', 
+'\n', '\t', 'a', 'u', 't', 'h', 'o', 'r', 'i', 't', 'y', '\030', '\003', ' ', '\001', '(', '\t', 'R', '\t', 'a', 'u', 't', 'h', 'o', 'r', 
+'i', 't', 'y', '\022', ',', '\n', '\r', 'r', 'e', 's', 'o', 'u', 'r', 'c', 'e', '_', 't', 'y', 'p', 'e', '\030', '\004', ' ', '\001', '(', 
+'\t', 'B', '\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\014', 'r', 'e', 's', 'o', 'u', 'r', 'c', 'e', 'T', 'y', 'p', 'e', '\022', 
+'A', '\n', '\r', 'e', 'x', 'a', 'c', 't', '_', 'c', 'o', 'n', 't', 'e', 'x', 't', '\030', '\005', ' ', '\001', '(', '\013', '2', '\032', '.', 
+'x', 'd', 's', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'C', 'o', 'n', 't', 'e', 'x', 't', 'P', 'a', 'r', 'a', 'm', 's', 
+'H', '\000', 'R', '\014', 'e', 'x', 'a', 'c', 't', 'C', 'o', 'n', 't', 'e', 'x', 't', '\022', 'F', '\n', '\n', 'd', 'i', 'r', 'e', 'c', 
+'t', 'i', 'v', 'e', 's', '\030', '\006', ' ', '\003', '(', '\013', '2', '&', '.', 'x', 'd', 's', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', 
+'.', 'R', 'e', 's', 'o', 'u', 'r', 'c', 'e', 'L', 'o', 'c', 'a', 't', 'o', 'r', '.', 'D', 'i', 'r', 'e', 'c', 't', 'i', 'v', 
+'e', 'R', '\n', 'd', 'i', 'r', 'e', 'c', 't', 'i', 'v', 'e', 's', '\032', '\210', '\001', '\n', '\t', 'D', 'i', 'r', 'e', 'c', 't', 'i', 
+'v', 'e', '\022', '0', '\n', '\003', 'a', 'l', 't', '\030', '\001', ' ', '\001', '(', '\013', '2', '\034', '.', 'x', 'd', 's', '.', 'c', 'o', 'r', 
+'e', '.', 'v', '3', '.', 'R', 'e', 's', 'o', 'u', 'r', 'c', 'e', 'L', 'o', 'c', 'a', 't', 'o', 'r', 'H', '\000', 'R', '\003', 'a', 
+'l', 't', '\022', '7', '\n', '\005', 'e', 'n', 't', 'r', 'y', '\030', '\002', ' ', '\001', '(', '\t', 'B', '\037', '\372', 'B', '\034', 'r', '\032', '\020', 
+'\001', '2', '\026', '^', '[', '0', '-', '9', 'a', '-', 'z', 'A', '-', 'Z', '_', '\\', '-', '\\', '.', '/', '~', ':', ']', '+', '$', 
+'H', '\000', 'R', '\005', 'e', 'n', 't', 'r', 'y', 'B', '\020', '\n', '\t', 'd', 'i', 'r', 'e', 'c', 't', 'i', 'v', 'e', '\022', '\003', '\370', 
+'B', '\001', '\"', '\'', '\n', '\006', 'S', 'c', 'h', 'e', 'm', 'e', '\022', '\t', '\n', '\005', 'X', 'D', 'S', 'T', 'P', '\020', '\000', '\022', '\010', 
+'\n', '\004', 'H', 'T', 'T', 'P', '\020', '\001', '\022', '\010', '\n', '\004', 'F', 'I', 'L', 'E', '\020', '\002', 'B', '\031', '\n', '\027', 'c', 'o', 'n', 
+'t', 'e', 'x', 't', '_', 'p', 'a', 'r', 'a', 'm', '_', 's', 'p', 'e', 'c', 'i', 'f', 'i', 'e', 'r', 'B', '\\', '\n', '\026', 'c', 
+'o', 'm', '.', 'g', 'i', 't', 'h', 'u', 'b', '.', 'x', 'd', 's', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', 'B', '\024', 'R', 'e', 
+'s', 'o', 'u', 'r', 'c', 'e', 'L', 'o', 'c', 'a', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', '\"', 'g', 'i', 't', 
+'h', 'u', 'b', '.', 'c', 'o', 'm', '/', 'c', 'n', 'c', 'f', '/', 'x', 'd', 's', '/', 'g', 'o', '/', 'x', 'd', 's', '/', 'c', 
+'o', 'r', 'e', '/', 'v', '3', '\322', '\306', '\244', '\341', '\006', '\002', '\010', '\001', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', 
 };
 
 static upb_def_init *deps[4] = {
-  &udpa_annotations_status_proto_upbdefinit,
+  &xds_annotations_v3_status_proto_upbdefinit,
   &xds_core_v3_context_params_proto_upbdefinit,
   &validate_validate_proto_upbdefinit,
   NULL
@@ -63,5 +64,5 @@ upb_def_init xds_core_v3_resource_locator_proto_upbdefinit = {
   deps,
   layouts,
   "xds/core/v3/resource_locator.proto",
-  UPB_STRVIEW_INIT(descriptor, 739)
+  UPB_STRVIEW_INIT(descriptor, 772)
 };
index 7b27e3d..6175b63 100644 (file)
@@ -9,7 +9,7 @@
 #include "upb/def.h"
 #include "xds/core/v3/resource_name.upbdefs.h"
 
-extern upb_def_init udpa_annotations_status_proto_upbdefinit;
+extern upb_def_init xds_annotations_v3_status_proto_upbdefinit;
 extern upb_def_init xds_core_v3_context_params_proto_upbdefinit;
 extern upb_def_init validate_validate_proto_upbdefinit;
 extern const upb_msglayout xds_core_v3_ResourceName_msginit;
@@ -18,25 +18,26 @@ static const upb_msglayout *layouts[1] = {
   &xds_core_v3_ResourceName_msginit,
 };
 
-static const char descriptor[367] = {'\n', '\037', 'x', 'd', 's', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '/', 'r', 'e', 's', 'o', 'u', 'r', 'c', 'e', '_', 'n', 'a', 
-'m', 'e', '.', 'p', 'r', 'o', 't', 'o', '\022', '\013', 'x', 'd', 's', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '\032', '\035', 'u', 'd', 
-'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 's', 't', 'a', 't', 'u', 's', '.', 'p', 'r', 'o', 
-'t', 'o', '\032', ' ', 'x', 'd', 's', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '/', 'c', 'o', 'n', 't', 'e', 'x', 't', '_', 'p', 
-'a', 'r', 'a', 'm', 's', '.', 'p', 'r', 'o', 't', 'o', '\032', '\027', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '/', 'v', 'a', 'l', 
-'i', 'd', 'a', 't', 'e', '.', 'p', 'r', 'o', 't', 'o', '\"', '\240', '\001', '\n', '\014', 'R', 'e', 's', 'o', 'u', 'r', 'c', 'e', 'N', 
-'a', 'm', 'e', '\022', '\016', '\n', '\002', 'i', 'd', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\002', 'i', 'd', '\022', '\034', '\n', '\t', 'a', 'u', 
-'t', 'h', 'o', 'r', 'i', 't', 'y', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\t', 'a', 'u', 't', 'h', 'o', 'r', 'i', 't', 'y', '\022', 
-',', '\n', '\r', 'r', 'e', 's', 'o', 'u', 'r', 'c', 'e', '_', 't', 'y', 'p', 'e', '\030', '\003', ' ', '\001', '(', '\t', 'B', '\007', '\372', 
-'B', '\004', 'r', '\002', '\020', '\001', 'R', '\014', 'r', 'e', 's', 'o', 'u', 'r', 'c', 'e', 'T', 'y', 'p', 'e', '\022', '4', '\n', '\007', 'c', 
-'o', 'n', 't', 'e', 'x', 't', '\030', '\004', ' ', '\001', '(', '\013', '2', '\032', '.', 'x', 'd', 's', '.', 'c', 'o', 'r', 'e', '.', 'v', 
-'3', '.', 'C', 'o', 'n', 't', 'e', 'x', 't', 'P', 'a', 'r', 'a', 'm', 's', 'R', '\007', 'c', 'o', 'n', 't', 'e', 'x', 't', 'B', 
-':', '\n', '\033', 'c', 'o', 'm', '.', 'g', 'i', 't', 'h', 'u', 'b', '.', 'u', 'd', 'p', 'a', '.', 'x', 'd', 's', '.', 'c', 'o', 
-'r', 'e', '.', 'v', '3', 'B', '\021', 'R', 'e', 's', 'o', 'u', 'r', 'c', 'e', 'N', 'a', 'm', 'e', 'P', 'r', 'o', 't', 'o', 'P', 
-'\001', '\272', '\200', '\310', '\321', '\006', '\002', '\010', '\001', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', 
+static const char descriptor[400] = {'\n', '\037', 'x', 'd', 's', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '/', 'r', 'e', 's', 'o', 'u', 'r', 'c', 'e', '_', 'n', 'a', 
+'m', 'e', '.', 'p', 'r', 'o', 't', 'o', '\022', '\013', 'x', 'd', 's', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '\032', '\037', 'x', 'd', 
+'s', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 'v', '3', '/', 's', 't', 'a', 't', 'u', 's', '.', 'p', 
+'r', 'o', 't', 'o', '\032', ' ', 'x', 'd', 's', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '/', 'c', 'o', 'n', 't', 'e', 'x', 't', 
+'_', 'p', 'a', 'r', 'a', 'm', 's', '.', 'p', 'r', 'o', 't', 'o', '\032', '\027', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '/', 'v', 
+'a', 'l', 'i', 'd', 'a', 't', 'e', '.', 'p', 'r', 'o', 't', 'o', '\"', '\240', '\001', '\n', '\014', 'R', 'e', 's', 'o', 'u', 'r', 'c', 
+'e', 'N', 'a', 'm', 'e', '\022', '\016', '\n', '\002', 'i', 'd', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\002', 'i', 'd', '\022', '\034', '\n', '\t', 
+'a', 'u', 't', 'h', 'o', 'r', 'i', 't', 'y', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\t', 'a', 'u', 't', 'h', 'o', 'r', 'i', 't', 
+'y', '\022', ',', '\n', '\r', 'r', 'e', 's', 'o', 'u', 'r', 'c', 'e', '_', 't', 'y', 'p', 'e', '\030', '\003', ' ', '\001', '(', '\t', 'B', 
+'\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\014', 'r', 'e', 's', 'o', 'u', 'r', 'c', 'e', 'T', 'y', 'p', 'e', '\022', '4', '\n', 
+'\007', 'c', 'o', 'n', 't', 'e', 'x', 't', '\030', '\004', ' ', '\001', '(', '\013', '2', '\032', '.', 'x', 'd', 's', '.', 'c', 'o', 'r', 'e', 
+'.', 'v', '3', '.', 'C', 'o', 'n', 't', 'e', 'x', 't', 'P', 'a', 'r', 'a', 'm', 's', 'R', '\007', 'c', 'o', 'n', 't', 'e', 'x', 
+'t', 'B', 'Y', '\n', '\026', 'c', 'o', 'm', '.', 'g', 'i', 't', 'h', 'u', 'b', '.', 'x', 'd', 's', '.', 'c', 'o', 'r', 'e', '.', 
+'v', '3', 'B', '\021', 'R', 'e', 's', 'o', 'u', 'r', 'c', 'e', 'N', 'a', 'm', 'e', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', '\"', 
+'g', 'i', 't', 'h', 'u', 'b', '.', 'c', 'o', 'm', '/', 'c', 'n', 'c', 'f', '/', 'x', 'd', 's', '/', 'g', 'o', '/', 'x', 'd', 
+'s', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '\322', '\306', '\244', '\341', '\006', '\002', '\010', '\001', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', 
 };
 
 static upb_def_init *deps[4] = {
-  &udpa_annotations_status_proto_upbdefinit,
+  &xds_annotations_v3_status_proto_upbdefinit,
   &xds_core_v3_context_params_proto_upbdefinit,
   &validate_validate_proto_upbdefinit,
   NULL
@@ -46,5 +47,5 @@ upb_def_init xds_core_v3_resource_name_proto_upbdefinit = {
   deps,
   layouts,
   "xds/core/v3/resource_name.proto",
-  UPB_STRVIEW_INIT(descriptor, 367)
+  UPB_STRVIEW_INIT(descriptor, 400)
 };
diff --git a/src/core/ext/upbdefs-generated/xds/data/orca/v3/orca_load_report.upbdefs.c b/src/core/ext/upbdefs-generated/xds/data/orca/v3/orca_load_report.upbdefs.c
new file mode 100644 (file)
index 0000000..d91c7b5
--- /dev/null
@@ -0,0 +1,64 @@
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ *     xds/data/orca/v3/orca_load_report.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#include "upb/def.h"
+#include "xds/data/orca/v3/orca_load_report.upbdefs.h"
+
+extern upb_def_init validate_validate_proto_upbdefinit;
+extern const upb_msglayout xds_data_orca_v3_OrcaLoadReport_msginit;
+extern const upb_msglayout xds_data_orca_v3_OrcaLoadReport_RequestCostEntry_msginit;
+extern const upb_msglayout xds_data_orca_v3_OrcaLoadReport_UtilizationEntry_msginit;
+
+static const upb_msglayout *layouts[3] = {
+  &xds_data_orca_v3_OrcaLoadReport_msginit,
+  &xds_data_orca_v3_OrcaLoadReport_RequestCostEntry_msginit,
+  &xds_data_orca_v3_OrcaLoadReport_UtilizationEntry_msginit,
+};
+
+static const char descriptor[705] = {'\n', '\'', 'x', 'd', 's', '/', 'd', 'a', 't', 'a', '/', 'o', 'r', 'c', 'a', '/', 'v', '3', '/', 'o', 'r', 'c', 'a', '_', 'l', 
+'o', 'a', 'd', '_', 'r', 'e', 'p', 'o', 'r', 't', '.', 'p', 'r', 'o', 't', 'o', '\022', '\020', 'x', 'd', 's', '.', 'd', 'a', 't', 
+'a', '.', 'o', 'r', 'c', 'a', '.', 'v', '3', '\032', '\027', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '/', 'v', 'a', 'l', 'i', 'd', 
+'a', 't', 'e', '.', 'p', 'r', 'o', 't', 'o', '\"', '\203', '\004', '\n', '\016', 'O', 'r', 'c', 'a', 'L', 'o', 'a', 'd', 'R', 'e', 'p', 
+'o', 'r', 't', '\022', 'E', '\n', '\017', 'c', 'p', 'u', '_', 'u', 't', 'i', 'l', 'i', 'z', 'a', 't', 'i', 'o', 'n', '\030', '\001', ' ', 
+'\001', '(', '\001', 'B', '\034', '\372', 'B', '\013', '\022', '\t', ')', '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\372', 'B', '\013', '\022', '\t', '\031', 
+'\000', '\000', '\000', '\000', '\000', '\000', '\360', '?', 'R', '\016', 'c', 'p', 'u', 'U', 't', 'i', 'l', 'i', 'z', 'a', 't', 'i', 'o', 'n', '\022', 
+'E', '\n', '\017', 'm', 'e', 'm', '_', 'u', 't', 'i', 'l', 'i', 'z', 'a', 't', 'i', 'o', 'n', '\030', '\002', ' ', '\001', '(', '\001', 'B', 
+'\034', '\372', 'B', '\013', '\022', '\t', ')', '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\372', 'B', '\013', '\022', '\t', '\031', '\000', '\000', '\000', '\000', 
+'\000', '\000', '\360', '?', 'R', '\016', 'm', 'e', 'm', 'U', 't', 'i', 'l', 'i', 'z', 'a', 't', 'i', 'o', 'n', '\022', '\020', '\n', '\003', 'r', 
+'p', 's', '\030', '\003', ' ', '\001', '(', '\004', 'R', '\003', 'r', 'p', 's', '\022', 'T', '\n', '\014', 'r', 'e', 'q', 'u', 'e', 's', 't', '_', 
+'c', 'o', 's', 't', '\030', '\004', ' ', '\003', '(', '\013', '2', '1', '.', 'x', 'd', 's', '.', 'd', 'a', 't', 'a', '.', 'o', 'r', 'c', 
+'a', '.', 'v', '3', '.', 'O', 'r', 'c', 'a', 'L', 'o', 'a', 'd', 'R', 'e', 'p', 'o', 'r', 't', '.', 'R', 'e', 'q', 'u', 'e', 
+'s', 't', 'C', 'o', 's', 't', 'E', 'n', 't', 'r', 'y', 'R', '\013', 'r', 'e', 'q', 'u', 'e', 's', 't', 'C', 'o', 's', 't', '\022', 
+'{', '\n', '\013', 'u', 't', 'i', 'l', 'i', 'z', 'a', 't', 'i', 'o', 'n', '\030', '\005', ' ', '\003', '(', '\013', '2', '1', '.', 'x', 'd', 
+'s', '.', 'd', 'a', 't', 'a', '.', 'o', 'r', 'c', 'a', '.', 'v', '3', '.', 'O', 'r', 'c', 'a', 'L', 'o', 'a', 'd', 'R', 'e', 
+'p', 'o', 'r', 't', '.', 'U', 't', 'i', 'l', 'i', 'z', 'a', 't', 'i', 'o', 'n', 'E', 'n', 't', 'r', 'y', 'B', '&', '\372', 'B', 
+'\020', '\232', '\001', '\r', '*', '\013', '\022', '\t', ')', '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\372', 'B', '\020', '\232', '\001', '\r', '*', '\013', 
+'\022', '\t', '\031', '\000', '\000', '\000', '\000', '\000', '\000', '\360', '?', 'R', '\013', 'u', 't', 'i', 'l', 'i', 'z', 'a', 't', 'i', 'o', 'n', '\032', 
+'>', '\n', '\020', 'R', 'e', 'q', 'u', 'e', 's', 't', 'C', 'o', 's', 't', 'E', 'n', 't', 'r', 'y', '\022', '\020', '\n', '\003', 'k', 'e', 
+'y', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\003', 'k', 'e', 'y', '\022', '\024', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\001', 
+'(', '\001', 'R', '\005', 'v', 'a', 'l', 'u', 'e', ':', '\002', '8', '\001', '\032', '>', '\n', '\020', 'U', 't', 'i', 'l', 'i', 'z', 'a', 't', 
+'i', 'o', 'n', 'E', 'n', 't', 'r', 'y', '\022', '\020', '\n', '\003', 'k', 'e', 'y', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\003', 'k', 'e', 
+'y', '\022', '\024', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\001', '(', '\001', 'R', '\005', 'v', 'a', 'l', 'u', 'e', ':', '\002', 
+'8', '\001', 'B', ']', '\n', '\033', 'c', 'o', 'm', '.', 'g', 'i', 't', 'h', 'u', 'b', '.', 'x', 'd', 's', '.', 'd', 'a', 't', 'a', 
+'.', 'o', 'r', 'c', 'a', '.', 'v', '3', 'B', '\023', 'O', 'r', 'c', 'a', 'L', 'o', 'a', 'd', 'R', 'e', 'p', 'o', 'r', 't', 'P', 
+'r', 'o', 't', 'o', 'P', '\001', 'Z', '\'', 'g', 'i', 't', 'h', 'u', 'b', '.', 'c', 'o', 'm', '/', 'c', 'n', 'c', 'f', '/', 'x', 
+'d', 's', '/', 'g', 'o', '/', 'x', 'd', 's', '/', 'd', 'a', 't', 'a', '/', 'o', 'r', 'c', 'a', '/', 'v', '3', 'b', '\006', 'p', 
+'r', 'o', 't', 'o', '3', 
+};
+
+static upb_def_init *deps[2] = {
+  &validate_validate_proto_upbdefinit,
+  NULL
+};
+
+upb_def_init xds_data_orca_v3_orca_load_report_proto_upbdefinit = {
+  deps,
+  layouts,
+  "xds/data/orca/v3/orca_load_report.proto",
+  UPB_STRVIEW_INIT(descriptor, 705)
+};
diff --git a/src/core/ext/upbdefs-generated/xds/data/orca/v3/orca_load_report.upbdefs.h b/src/core/ext/upbdefs-generated/xds/data/orca/v3/orca_load_report.upbdefs.h
new file mode 100644 (file)
index 0000000..93488e5
--- /dev/null
@@ -0,0 +1,45 @@
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ *     xds/data/orca/v3/orca_load_report.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#ifndef XDS_DATA_ORCA_V3_ORCA_LOAD_REPORT_PROTO_UPBDEFS_H_
+#define XDS_DATA_ORCA_V3_ORCA_LOAD_REPORT_PROTO_UPBDEFS_H_
+
+#include "upb/def.h"
+#include "upb/port_def.inc"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "upb/def.h"
+
+#include "upb/port_def.inc"
+
+extern upb_def_init xds_data_orca_v3_orca_load_report_proto_upbdefinit;
+
+UPB_INLINE const upb_msgdef *xds_data_orca_v3_OrcaLoadReport_getmsgdef(upb_symtab *s) {
+  _upb_symtab_loaddefinit(s, &xds_data_orca_v3_orca_load_report_proto_upbdefinit);
+  return upb_symtab_lookupmsg(s, "xds.data.orca.v3.OrcaLoadReport");
+}
+
+UPB_INLINE const upb_msgdef *xds_data_orca_v3_OrcaLoadReport_RequestCostEntry_getmsgdef(upb_symtab *s) {
+  _upb_symtab_loaddefinit(s, &xds_data_orca_v3_orca_load_report_proto_upbdefinit);
+  return upb_symtab_lookupmsg(s, "xds.data.orca.v3.OrcaLoadReport.RequestCostEntry");
+}
+
+UPB_INLINE const upb_msgdef *xds_data_orca_v3_OrcaLoadReport_UtilizationEntry_getmsgdef(upb_symtab *s) {
+  _upb_symtab_loaddefinit(s, &xds_data_orca_v3_orca_load_report_proto_upbdefinit);
+  return upb_symtab_lookupmsg(s, "xds.data.orca.v3.OrcaLoadReport.UtilizationEntry");
+}
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#include "upb/port_undef.inc"
+
+#endif  /* XDS_DATA_ORCA_V3_ORCA_LOAD_REPORT_PROTO_UPBDEFS_H_ */
diff --git a/src/core/ext/upbdefs-generated/xds/type/v3/typed_struct.upbdefs.c b/src/core/ext/upbdefs-generated/xds/type/v3/typed_struct.upbdefs.c
new file mode 100644 (file)
index 0000000..3506104
--- /dev/null
@@ -0,0 +1,45 @@
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ *     xds/type/v3/typed_struct.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#include "upb/def.h"
+#include "xds/type/v3/typed_struct.upbdefs.h"
+
+extern upb_def_init validate_validate_proto_upbdefinit;
+extern upb_def_init google_protobuf_struct_proto_upbdefinit;
+extern const upb_msglayout xds_type_v3_TypedStruct_msginit;
+
+static const upb_msglayout *layouts[1] = {
+  &xds_type_v3_TypedStruct_msginit,
+};
+
+static const char descriptor[279] = {'\n', '\036', 'x', 'd', 's', '/', 't', 'y', 'p', 'e', '/', 'v', '3', '/', 't', 'y', 'p', 'e', 'd', '_', 's', 't', 'r', 'u', 'c', 
+'t', '.', 'p', 'r', 'o', 't', 'o', '\022', '\013', 'x', 'd', 's', '.', 't', 'y', 'p', 'e', '.', 'v', '3', '\032', '\027', 'v', 'a', 'l', 
+'i', 'd', 'a', 't', 'e', '/', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '.', 'p', 'r', 'o', 't', 'o', '\032', '\034', 'g', 'o', 'o', 
+'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 's', 't', 'r', 'u', 'c', 't', '.', 'p', 'r', 'o', 't', 'o', 
+'\"', 'W', '\n', '\013', 'T', 'y', 'p', 'e', 'd', 'S', 't', 'r', 'u', 'c', 't', '\022', '\031', '\n', '\010', 't', 'y', 'p', 'e', '_', 'u', 
+'r', 'l', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\007', 't', 'y', 'p', 'e', 'U', 'r', 'l', '\022', '-', '\n', '\005', 'v', 'a', 'l', 'u', 
+'e', '\030', '\002', ' ', '\001', '(', '\013', '2', '\027', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', 
+'.', 'S', 't', 'r', 'u', 'c', 't', 'R', '\005', 'v', 'a', 'l', 'u', 'e', 'B', 'P', '\n', '\026', 'c', 'o', 'm', '.', 'g', 'i', 't', 
+'h', 'u', 'b', '.', 'x', 'd', 's', '.', 't', 'y', 'p', 'e', '.', 'v', '3', 'B', '\020', 'T', 'y', 'p', 'e', 'd', 'S', 't', 'r', 
+'u', 'c', 't', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', '\"', 'g', 'i', 't', 'h', 'u', 'b', '.', 'c', 'o', 'm', '/', 'c', 'n', 
+'c', 'f', '/', 'x', 'd', 's', '/', 'g', 'o', '/', 'x', 'd', 's', '/', 't', 'y', 'p', 'e', '/', 'v', '3', 'b', '\006', 'p', 'r', 
+'o', 't', 'o', '3', 
+};
+
+static upb_def_init *deps[3] = {
+  &validate_validate_proto_upbdefinit,
+  &google_protobuf_struct_proto_upbdefinit,
+  NULL
+};
+
+upb_def_init xds_type_v3_typed_struct_proto_upbdefinit = {
+  deps,
+  layouts,
+  "xds/type/v3/typed_struct.proto",
+  UPB_STRVIEW_INIT(descriptor, 279)
+};
diff --git a/src/core/ext/upbdefs-generated/xds/type/v3/typed_struct.upbdefs.h b/src/core/ext/upbdefs-generated/xds/type/v3/typed_struct.upbdefs.h
new file mode 100644 (file)
index 0000000..ac43a97
--- /dev/null
@@ -0,0 +1,35 @@
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ *     xds/type/v3/typed_struct.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#ifndef XDS_TYPE_V3_TYPED_STRUCT_PROTO_UPBDEFS_H_
+#define XDS_TYPE_V3_TYPED_STRUCT_PROTO_UPBDEFS_H_
+
+#include "upb/def.h"
+#include "upb/port_def.inc"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "upb/def.h"
+
+#include "upb/port_def.inc"
+
+extern upb_def_init xds_type_v3_typed_struct_proto_upbdefinit;
+
+UPB_INLINE const upb_msgdef *xds_type_v3_TypedStruct_getmsgdef(upb_symtab *s) {
+  _upb_symtab_loaddefinit(s, &xds_type_v3_typed_struct_proto_upbdefinit);
+  return upb_symtab_lookupmsg(s, "xds.type.v3.TypedStruct");
+}
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#include "upb/port_undef.inc"
+
+#endif  /* XDS_TYPE_V3_TYPED_STRUCT_PROTO_UPBDEFS_H_ */
index c321a92..4bc15ef 100644 (file)
 #include "google/protobuf/timestamp.upb.h"
 #include "google/protobuf/wrappers.upb.h"
 #include "google/rpc/status.upb.h"
-#include "udpa/type/v1/typed_struct.upb.h"
 #include "upb/text_encode.h"
 #include "upb/upb.h"
 #include "upb/upb.hpp"
+#include "xds/type/v3/typed_struct.upb.h"
 
 #include <grpc/impl/codegen/log.h>
 #include <grpc/support/alloc.h>
 #include "src/core/lib/address_utils/sockaddr_utils.h"
 #include "src/core/lib/gpr/env.h"
 #include "src/core/lib/gpr/string.h"
-#include "src/core/lib/gpr/useful.h"
 #include "src/core/lib/gprpp/host_port.h"
 #include "src/core/lib/iomgr/error.h"
 #include "src/core/lib/iomgr/sockaddr.h"
 #include "src/core/lib/iomgr/socket_utils.h"
 #include "src/core/lib/slice/slice_utils.h"
+#include "src/core/lib/uri/uri_parser.h"
 
 namespace grpc_core {
 
@@ -116,11 +116,58 @@ bool XdsAggregateAndLogicalDnsClusterEnabled() {
   return parse_succeeded && parsed_value;
 }
 
+// TODO(yashykt): Remove once RBAC is no longer experimental
+bool XdsRbacEnabled() {
+  char* value = gpr_getenv("GRPC_XDS_EXPERIMENTAL_RBAC");
+  bool parsed_value;
+  bool parse_succeeded = gpr_parse_bool_value(value, &parsed_value);
+  gpr_free(value);
+  return parse_succeeded && parsed_value;
+}
+
+//
+// XdsApi::RetryPolicy
+//
+
+std::string XdsApi::RetryPolicy::RetryBackOff::ToString() const {
+  std::vector<std::string> contents;
+  contents.push_back(
+      absl::StrCat("RetryBackOff Base: ", base_interval.ToString()));
+  contents.push_back(
+      absl::StrCat("RetryBackOff max: ", max_interval.ToString()));
+  return absl::StrJoin(contents, ",");
+}
+
+std::string XdsApi::RetryPolicy::ToString() const {
+  std::vector<std::string> contents;
+  contents.push_back(absl::StrFormat("num_retries=%d", num_retries));
+  contents.push_back(retry_back_off.ToString());
+  return absl::StrCat("{", absl::StrJoin(contents, ","), "}");
+}
+
+//
+// XdsApi::Route::Matchers
+//
+
+std::string XdsApi::Route::Matchers::ToString() const {
+  std::vector<std::string> contents;
+  contents.push_back(
+      absl::StrFormat("PathMatcher{%s}", path_matcher.ToString()));
+  for (const HeaderMatcher& header_matcher : header_matchers) {
+    contents.push_back(header_matcher.ToString());
+  }
+  if (fraction_per_million.has_value()) {
+    contents.push_back(absl::StrFormat("Fraction Per Million %d",
+                                       fraction_per_million.value()));
+  }
+  return absl::StrJoin(contents, "\n");
+}
+
 //
-// XdsApi::Route::HashPolicy
+// XdsApi::Route::RouteAction::HashPolicy
 //
 
-XdsApi::Route::HashPolicy::HashPolicy(const HashPolicy& other)
+XdsApi::Route::RouteAction::HashPolicy::HashPolicy(const HashPolicy& other)
     : type(other.type),
       header_name(other.header_name),
       regex_substitution(other.regex_substitution) {
@@ -130,8 +177,8 @@ XdsApi::Route::HashPolicy::HashPolicy(const HashPolicy& other)
   }
 }
 
-XdsApi::Route::HashPolicy& XdsApi::Route::HashPolicy::operator=(
-    const HashPolicy& other) {
+XdsApi::Route::RouteAction::HashPolicy&
+XdsApi::Route::RouteAction::HashPolicy::operator=(const HashPolicy& other) {
   type = other.type;
   header_name = other.header_name;
   if (other.regex != nullptr) {
@@ -142,14 +189,14 @@ XdsApi::Route::HashPolicy& XdsApi::Route::HashPolicy::operator=(
   return *this;
 }
 
-XdsApi::Route::HashPolicy::HashPolicy(HashPolicy&& other) noexcept
+XdsApi::Route::RouteAction::HashPolicy::HashPolicy(HashPolicy&& other) noexcept
     : type(other.type),
       header_name(std::move(other.header_name)),
       regex(std::move(other.regex)),
       regex_substitution(std::move(other.regex_substitution)) {}
 
-XdsApi::Route::HashPolicy& XdsApi::Route::HashPolicy::operator=(
-    HashPolicy&& other) noexcept {
+XdsApi::Route::RouteAction::HashPolicy&
+XdsApi::Route::RouteAction::HashPolicy::operator=(HashPolicy&& other) noexcept {
   type = other.type;
   header_name = std::move(other.header_name);
   regex = std::move(other.regex);
@@ -157,7 +204,7 @@ XdsApi::Route::HashPolicy& XdsApi::Route::HashPolicy::operator=(
   return *this;
 }
 
-bool XdsApi::Route::HashPolicy::HashPolicy::operator==(
+bool XdsApi::Route::RouteAction::HashPolicy::HashPolicy::operator==(
     const HashPolicy& other) const {
   if (type != other.type) return false;
   if (type == Type::HEADER) {
@@ -173,7 +220,7 @@ bool XdsApi::Route::HashPolicy::HashPolicy::operator==(
   return true;
 }
 
-std::string XdsApi::Route::HashPolicy::ToString() const {
+std::string XdsApi::Route::RouteAction::HashPolicy::ToString() const {
   std::vector<std::string> contents;
   switch (type) {
     case Type::HEADER:
@@ -194,43 +241,10 @@ std::string XdsApi::Route::HashPolicy::ToString() const {
 }
 
 //
-// XdsApi::Route::RetryPolicy
-//
-std::string XdsApi::Route::RetryPolicy::RetryBackOff::ToString() const {
-  std::vector<std::string> contents;
-  contents.push_back(
-      absl::StrCat("RetryBackOff Base: ", base_interval.ToString()));
-  contents.push_back(
-      absl::StrCat("RetryBackOff max: ", max_interval.ToString()));
-  return absl::StrJoin(contents, ",");
-}
-
-std::string XdsApi::Route::RetryPolicy::ToString() const {
-  std::vector<std::string> contents;
-  contents.push_back(absl::StrFormat("num_retries=%d", num_retries));
-  contents.push_back(retry_back_off.ToString());
-  return absl::StrJoin(contents, ",");
-}
-
-//
-// XdsApi::Route
+// XdsApi::Route::RouteAction::ClusterWeight
 //
 
-std::string XdsApi::Route::Matchers::ToString() const {
-  std::vector<std::string> contents;
-  contents.push_back(
-      absl::StrFormat("PathMatcher{%s}", path_matcher.ToString()));
-  for (const HeaderMatcher& header_matcher : header_matchers) {
-    contents.push_back(header_matcher.ToString());
-  }
-  if (fraction_per_million.has_value()) {
-    contents.push_back(absl::StrFormat("Fraction Per Million %d",
-                                       fraction_per_million.value()));
-  }
-  return absl::StrJoin(contents, "\n");
-}
-
-std::string XdsApi::Route::ClusterWeight::ToString() const {
+std::string XdsApi::Route::RouteAction::ClusterWeight::ToString() const {
   std::vector<std::string> contents;
   contents.push_back(absl::StrCat("cluster=", name));
   contents.push_back(absl::StrCat("weight=", weight));
@@ -247,15 +261,17 @@ std::string XdsApi::Route::ClusterWeight::ToString() const {
   return absl::StrCat("{", absl::StrJoin(contents, ", "), "}");
 }
 
-std::string XdsApi::Route::ToString() const {
+//
+// XdsApi::Route::RouteAction
+//
+
+std::string XdsApi::Route::RouteAction::ToString() const {
   std::vector<std::string> contents;
-  contents.push_back(matchers.ToString());
   for (const HashPolicy& hash_policy : hash_policies) {
     contents.push_back(absl::StrCat("hash_policy=", hash_policy.ToString()));
   }
   if (retry_policy.has_value()) {
-    contents.push_back(
-        absl::StrCat("retry_policy={", retry_policy->ToString(), "}"));
+    contents.push_back(absl::StrCat("retry_policy=", retry_policy->ToString()));
   }
   if (!cluster_name.empty()) {
     contents.push_back(absl::StrFormat("Cluster name: %s", cluster_name));
@@ -266,6 +282,25 @@ std::string XdsApi::Route::ToString() const {
   if (max_stream_duration.has_value()) {
     contents.push_back(max_stream_duration->ToString());
   }
+  return absl::StrCat("{", absl::StrJoin(contents, ", "), "}");
+}
+
+//
+// XdsApi::Route
+//
+
+std::string XdsApi::Route::ToString() const {
+  std::vector<std::string> contents;
+  contents.push_back(matchers.ToString());
+  auto* route_action = absl::get_if<XdsApi::Route::RouteAction>(&action);
+  if (route_action != nullptr) {
+    contents.push_back(absl::StrCat("route=", route_action->ToString()));
+  } else if (absl::holds_alternative<XdsApi::Route::NonForwardingAction>(
+                 action)) {
+    contents.push_back("non_forwarding_action={}");
+  } else {
+    contents.push_back("unknown_action={}");
+  }
   if (!typed_per_filter_config.empty()) {
     contents.push_back("typed_per_filter_config={");
     for (const auto& p : typed_per_filter_config) {
@@ -804,7 +839,7 @@ const char* kCdsV2TypeUrl = "type.googleapis.com/envoy.api.v2.Cluster";
 const char* kEdsV2TypeUrl =
     "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment";
 
-bool IsLds(absl::string_view type_url, bool* is_v2 = nullptr) {
+bool IsLdsInternal(absl::string_view type_url, bool* is_v2 = nullptr) {
   if (type_url == XdsApi::kLdsTypeUrl) return true;
   if (type_url == kLdsV2TypeUrl) {
     if (is_v2 != nullptr) *is_v2 = true;
@@ -813,18 +848,46 @@ bool IsLds(absl::string_view type_url, bool* is_v2 = nullptr) {
   return false;
 }
 
-bool IsRds(absl::string_view type_url, bool* /*is_v2*/ = nullptr) {
+bool IsRdsInternal(absl::string_view type_url, bool* /*is_v2*/ = nullptr) {
   return type_url == XdsApi::kRdsTypeUrl || type_url == kRdsV2TypeUrl;
 }
 
-bool IsCds(absl::string_view type_url, bool* /*is_v2*/ = nullptr) {
+bool IsCdsInternal(absl::string_view type_url, bool* /*is_v2*/ = nullptr) {
   return type_url == XdsApi::kCdsTypeUrl || type_url == kCdsV2TypeUrl;
 }
 
-bool IsEds(absl::string_view type_url, bool* /*is_v2*/ = nullptr) {
+bool IsEdsInternal(absl::string_view type_url, bool* /*is_v2*/ = nullptr) {
   return type_url == XdsApi::kEdsTypeUrl || type_url == kEdsV2TypeUrl;
 }
 
+absl::StatusOr<XdsApi::ResourceName> ParseResourceNameInternal(
+    absl::string_view name,
+    std::function<bool(absl::string_view, bool*)> is_expected_type) {
+  // Old-style names use the empty string for authority.
+  // ID is prefixed with "old:" to indicate that it's an old-style name.
+  if (!absl::StartsWith(name, "xdstp:")) {
+    return XdsApi::ResourceName{"", absl::StrCat("old:", name)};
+  }
+  // New style name.  Parse URI.
+  auto uri = URI::Parse(name);
+  if (!uri.ok()) return uri.status();
+  // Split the resource type off of the path to get the id.
+  std::pair<absl::string_view, absl::string_view> path_parts =
+      absl::StrSplit(uri->path(), absl::MaxSplits('/', 1));
+  if (!is_expected_type(path_parts.first, nullptr)) {
+    return absl::InvalidArgumentError(
+        "xdstp URI path must indicate valid xDS resource type");
+  }
+  std::vector<std::pair<absl::string_view, absl::string_view>> query_parameters(
+      uri->query_parameter_map().begin(), uri->query_parameter_map().end());
+  std::sort(query_parameters.begin(), query_parameters.end());
+  return XdsApi::ResourceName{
+      uri->authority(),
+      absl::StrCat(
+          "xdstp:", path_parts.second, (query_parameters.empty() ? "?" : ""),
+          absl::StrJoin(query_parameters, "&", absl::PairFormatter("=")))};
+}
+
 }  // namespace
 
 // If gRPC is built with -DGRPC_XDS_USER_AGENT_NAME_SUFFIX="...", that string
@@ -881,6 +944,41 @@ XdsApi::XdsApi(XdsClient* client, TraceFlag* tracer,
   XdsHttpFilterRegistry::PopulateSymtab(symtab_.ptr());
 }
 
+bool XdsApi::IsLds(absl::string_view type_url) {
+  return IsLdsInternal(type_url);
+}
+
+bool XdsApi::IsRds(absl::string_view type_url) {
+  return IsRdsInternal(type_url);
+}
+
+bool XdsApi::IsCds(absl::string_view type_url) {
+  return IsCdsInternal(type_url);
+}
+
+bool XdsApi::IsEds(absl::string_view type_url) {
+  return IsEdsInternal(type_url);
+}
+
+absl::StatusOr<XdsApi::ResourceName> XdsApi::ParseResourceName(
+    absl::string_view name, bool (*is_expected_type)(absl::string_view)) {
+  return ParseResourceNameInternal(
+      name, [is_expected_type](absl::string_view type, bool*) {
+        return is_expected_type(type);
+      });
+}
+
+std::string XdsApi::ConstructFullResourceName(absl::string_view authority,
+                                              absl::string_view resource_type,
+                                              absl::string_view name) {
+  if (absl::StartsWith(name, "xdstp:")) {
+    return absl::StrCat("xdstp://", authority, "/", resource_type,
+                        absl::StripPrefix(name, "xdstp:"));
+  } else {
+    return std::string(absl::StripPrefix(name, "old:"));
+  }
+}
+
 namespace {
 
 struct EncodingContext {
@@ -1095,7 +1193,8 @@ absl::string_view TypeUrlExternalToInternal(bool use_v3,
 
 grpc_slice XdsApi::CreateAdsRequest(
     const XdsBootstrap::XdsServer& server, const std::string& type_url,
-    const std::set<absl::string_view>& resource_names,
+    const std::map<absl::string_view /*authority*/,
+                   std::set<absl::string_view /*name*/>>& resource_names,
     const std::string& version, const std::string& nonce,
     grpc_error_handle error, bool populate_node) {
   upb::Arena arena;
@@ -1148,10 +1247,27 @@ grpc_slice XdsApi::CreateAdsRequest(
     PopulateNode(context, node_, build_version_, user_agent_name_,
                  user_agent_version_, node_msg);
   }
+  // A vector for temporary local storage of resource name strings.
+  std::vector<std::string> resource_name_storage;
+  // Make sure the vector is sized right up-front, so that reallocations
+  // don't move the strings out from under the upb proto object that
+  // points to them.
+  size_t size = 0;
+  for (const auto& p : resource_names) {
+    size += p.second.size();
+  }
+  resource_name_storage.reserve(size);
   // Add resource_names.
-  for (const auto& resource_name : resource_names) {
-    envoy_service_discovery_v3_DiscoveryRequest_add_resource_names(
-        request, StdStringToUpbString(resource_name), arena.ptr());
+  for (const auto& a : resource_names) {
+    absl::string_view authority = a.first;
+    for (const auto& p : a.second) {
+      absl::string_view resource_id = p;
+      resource_name_storage.push_back(
+          ConstructFullResourceName(authority, type_url, resource_id));
+      envoy_service_discovery_v3_DiscoveryRequest_add_resource_names(
+          request, StdStringToUpbString(resource_name_storage.back()),
+          arena.ptr());
+    }
   }
   MaybeLogDiscoveryRequest(context, request);
   return SerializeDiscoveryRequest(context, request);
@@ -1438,16 +1554,17 @@ grpc_error_handle ExtractHttpFilterTypeName(const EncodingContext& context,
                                             const google_protobuf_Any* any,
                                             absl::string_view* filter_type) {
   *filter_type = UpbStringToAbsl(google_protobuf_Any_type_url(any));
-  if (*filter_type == "type.googleapis.com/udpa.type.v1.TypedStruct") {
+  if (*filter_type == "type.googleapis.com/xds.type.v3.TypedStruct" ||
+      *filter_type == "type.googleapis.com/udpa.type.v1.TypedStruct") {
     upb_strview any_value = google_protobuf_Any_value(any);
-    const auto* typed_struct = udpa_type_v1_TypedStruct_parse(
+    const auto* typed_struct = xds_type_v3_TypedStruct_parse(
         any_value.data, any_value.size, context.arena);
     if (typed_struct == nullptr) {
       return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
           "could not parse TypedStruct from filter config");
     }
     *filter_type =
-        UpbStringToAbsl(udpa_type_v1_TypedStruct_type_url(typed_struct));
+        UpbStringToAbsl(xds_type_v3_TypedStruct_type_url(typed_struct));
   }
   *filter_type = absl::StripPrefix(*filter_type, "type.googleapis.com/");
   return GRPC_ERROR_NONE;
@@ -1528,9 +1645,9 @@ XdsApi::Duration DurationParse(const google_protobuf_Duration* proto_duration) {
 grpc_error_handle RetryPolicyParse(
     const EncodingContext& context,
     const envoy_config_route_v3_RetryPolicy* retry_policy,
-    absl::optional<XdsApi::Route::RetryPolicy>* retry) {
+    absl::optional<XdsApi::RetryPolicy>* retry) {
   std::vector<grpc_error_handle> errors;
-  XdsApi::Route::RetryPolicy retry_to_return;
+  XdsApi::RetryPolicy retry_to_return;
   auto retry_on = UpbStringToStdString(
       envoy_config_route_v3_RetryPolicy_retry_on(retry_policy));
   std::vector<absl::string_view> codes = absl::StrSplit(retry_on, ',');
@@ -1552,10 +1669,6 @@ grpc_error_handle RetryPolicyParse(
       }
     }
   }
-  // TODO(donnadionne): when we add support for per_try_timeout, we will need to
-  // return a policy if per_try_timeout is set even if retry_on specified no
-  // supported policies.
-  if (retry_to_return.retry_on.Empty()) return GRPC_ERROR_NONE;
   const google_protobuf_UInt32Value* num_retries =
       envoy_config_route_v3_RetryPolicy_num_retries(retry_policy);
   if (num_retries != nullptr) {
@@ -1614,11 +1727,8 @@ grpc_error_handle RetryPolicyParse(
 
 grpc_error_handle RouteActionParse(const EncodingContext& context,
                                    const envoy_config_route_v3_Route* route_msg,
-                                   XdsApi::Route* route, bool* ignore_route) {
-  if (!envoy_config_route_v3_Route_has_route(route_msg)) {
-    return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
-        "No RouteAction found in route.");
-  }
+                                   XdsApi::Route::RouteAction* route,
+                                   bool* ignore_route) {
   const envoy_config_route_v3_RouteAction* route_action =
       envoy_config_route_v3_Route_route(route_msg);
   // Get the cluster or weighted_clusters in the RouteAction.
@@ -1647,7 +1757,7 @@ grpc_error_handle RouteActionParse(const EncodingContext& context,
     for (size_t j = 0; j < clusters_size; ++j) {
       const envoy_config_route_v3_WeightedCluster_ClusterWeight*
           cluster_weight = clusters[j];
-      XdsApi::Route::ClusterWeight cluster;
+      XdsApi::Route::RouteAction::ClusterWeight cluster;
       cluster.name = UpbStringToStdString(
           envoy_config_route_v3_WeightedCluster_ClusterWeight_name(
               cluster_weight));
@@ -1716,7 +1826,7 @@ grpc_error_handle RouteActionParse(const EncodingContext& context,
   for (size_t i = 0; i < size; ++i) {
     const envoy_config_route_v3_RouteAction_HashPolicy* hash_policy =
         hash_policies[i];
-    XdsApi::Route::HashPolicy policy;
+    XdsApi::Route::RouteAction::HashPolicy policy;
     policy.terminal =
         envoy_config_route_v3_RouteAction_HashPolicy_terminal(hash_policy);
     const envoy_config_route_v3_RouteAction_HashPolicy_Header* header;
@@ -1724,7 +1834,7 @@ grpc_error_handle RouteActionParse(const EncodingContext& context,
         filter_state;
     if ((header = envoy_config_route_v3_RouteAction_HashPolicy_header(
              hash_policy)) != nullptr) {
-      policy.type = XdsApi::Route::HashPolicy::Type::HEADER;
+      policy.type = XdsApi::Route::RouteAction::HashPolicy::Type::HEADER;
       policy.header_name = UpbStringToStdString(
           envoy_config_route_v3_RouteAction_HashPolicy_Header_header_name(
               header));
@@ -1768,7 +1878,7 @@ grpc_error_handle RouteActionParse(const EncodingContext& context,
           envoy_config_route_v3_RouteAction_HashPolicy_FilterState_key(
               filter_state));
       if (key == "io.grpc.channel_id") {
-        policy.type = XdsApi::Route::HashPolicy::Type::CHANNEL_ID;
+        policy.type = XdsApi::Route::RouteAction::HashPolicy::Type::CHANNEL_ID;
       } else {
         gpr_log(GPR_DEBUG,
                 "RouteAction HashPolicy contains policy specifier "
@@ -1787,7 +1897,7 @@ grpc_error_handle RouteActionParse(const EncodingContext& context,
   const envoy_config_route_v3_RetryPolicy* retry_policy =
       envoy_config_route_v3_RouteAction_retry_policy(route_action);
   if (retry_policy != nullptr) {
-    absl::optional<XdsApi::Route::RetryPolicy> retry;
+    absl::optional<XdsApi::RetryPolicy> retry;
     grpc_error_handle error = RetryPolicyParse(context, retry_policy, &retry);
     if (error != GRPC_ERROR_NONE) return error;
     route->retry_policy = retry;
@@ -1837,7 +1947,7 @@ grpc_error_handle RouteConfigParse(
       if (error != GRPC_ERROR_NONE) return error;
     }
     // Parse retry policy.
-    absl::optional<XdsApi::Route::RetryPolicy> virtual_host_retry_policy;
+    absl::optional<XdsApi::RetryPolicy> virtual_host_retry_policy;
     const envoy_config_route_v3_RetryPolicy* retry_policy =
         envoy_config_route_v3_VirtualHost_retry_policy(virtual_hosts[i]);
     if (retry_policy != nullptr) {
@@ -1876,11 +1986,21 @@ grpc_error_handle RouteConfigParse(
       if (error != GRPC_ERROR_NONE) return error;
       error = RouteRuntimeFractionParse(match, &route);
       if (error != GRPC_ERROR_NONE) return error;
-      error = RouteActionParse(context, routes[j], &route, &ignore_route);
-      if (error != GRPC_ERROR_NONE) return error;
-      if (ignore_route) continue;
-      if (route.retry_policy == absl::nullopt && retry_policy != nullptr) {
-        route.retry_policy = virtual_host_retry_policy;
+      if (envoy_config_route_v3_Route_has_route(routes[j])) {
+        route.action.emplace<XdsApi::Route::RouteAction>();
+        auto& route_action =
+            absl::get<XdsApi::Route::RouteAction>(route.action);
+        error =
+            RouteActionParse(context, routes[j], &route_action, &ignore_route);
+        if (error != GRPC_ERROR_NONE) return error;
+        if (ignore_route) continue;
+        if (route_action.retry_policy == absl::nullopt &&
+            retry_policy != nullptr) {
+          route_action.retry_policy = virtual_host_retry_policy;
+        }
+      } else if (envoy_config_route_v3_Route_has_non_forwarding_action(
+                     routes[j])) {
+        route.action.emplace<XdsApi::Route::NonForwardingAction>();
       }
       if (context.use_v3) {
         grpc_error_handle error = ParseTypedPerFilterConfig<
@@ -2237,32 +2357,47 @@ grpc_error_handle HttpConnectionManagerParse(
             absl::StrFormat("Filter %s is not supported on %s", filter_type,
                             is_client ? "clients" : "servers"));
       }
-      if (i < num_filters - 1) {
+      absl::StatusOr<XdsHttpFilterImpl::FilterConfig> filter_config =
+          filter_impl->GenerateFilterConfig(google_protobuf_Any_value(any),
+                                            context.arena);
+      if (!filter_config.ok()) {
+        return GRPC_ERROR_CREATE_FROM_CPP_STRING(absl::StrCat(
+            "filter config for type ", filter_type,
+            " failed to parse: ", filter_config.status().ToString()));
+      }
+      http_connection_manager->http_filters.emplace_back(
+          XdsApi::LdsUpdate::HttpConnectionManager::HttpFilter{
+              std::string(name), std::move(*filter_config)});
+    }
+    if (http_connection_manager->http_filters.empty()) {
+      return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+          "Expected at least one HTTP filter");
+    }
+    // Make sure that the last filter is terminal and non-last filters are
+    // non-terminal. Note that this check is being performed in a separate loop
+    // to take care of the case where there are two terminal filters in the list
+    // out of which only one gets added in the final list.
+    for (const auto& http_filter : http_connection_manager->http_filters) {
+      const XdsHttpFilterImpl* filter_impl =
+          XdsHttpFilterRegistry::GetFilterForType(
+              http_filter.config.config_proto_type_name);
+      if (&http_filter != &http_connection_manager->http_filters.back()) {
         // Filters before the last filter must not be terminal.
         if (filter_impl->IsTerminalFilter()) {
           return GRPC_ERROR_CREATE_FROM_CPP_STRING(
-              absl::StrCat("terminal filter for config type ", filter_type,
+              absl::StrCat("terminal filter for config type ",
+                           http_filter.config.config_proto_type_name,
                            " must be the last filter in the chain"));
         }
       } else {
         // The last filter must be terminal.
         if (!filter_impl->IsTerminalFilter()) {
           return GRPC_ERROR_CREATE_FROM_CPP_STRING(
-              absl::StrCat("non-terminal filter for config type ", filter_type,
+              absl::StrCat("non-terminal filter for config type ",
+                           http_filter.config.config_proto_type_name,
                            " is the last filter in the chain"));
         }
       }
-      absl::StatusOr<XdsHttpFilterImpl::FilterConfig> filter_config =
-          filter_impl->GenerateFilterConfig(google_protobuf_Any_value(any),
-                                            context.arena);
-      if (!filter_config.ok()) {
-        return GRPC_ERROR_CREATE_FROM_CPP_STRING(absl::StrCat(
-            "filter config for type ", filter_type,
-            " failed to parse: ", filter_config.status().ToString()));
-      }
-      http_connection_manager->http_filters.emplace_back(
-          XdsApi::LdsUpdate::HttpConnectionManager::HttpFilter{
-              std::string(name), std::move(*filter_config)});
     }
   } else {
     // If using a v2 config, we just hard-code a list containing only the
@@ -2273,7 +2408,10 @@ grpc_error_handle HttpConnectionManagerParse(
         XdsApi::LdsUpdate::HttpConnectionManager::HttpFilter{
             "router", {kXdsHttpRouterFilterConfigName, Json()}});
   }
-  if (is_client) {
+  // Guarding parsing of RouteConfig on the server side with the environmental
+  // variable since that's the first feature on the server side that will be
+  // using this.
+  if (is_client || XdsRbacEnabled()) {
     // Found inlined route_config. Parse it to find the cluster_name.
     if (envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_has_route_config(
             http_connection_manager_proto)) {
@@ -2508,6 +2646,8 @@ grpc_error_handle FilterChainParse(
         filter_chain_match, &filter_chain->filter_chain_match);
     if (error != GRPC_ERROR_NONE) errors.push_back(error);
   }
+  filter_chain->filter_chain_data =
+      std::make_shared<XdsApi::LdsUpdate::FilterChainData>();
   // Parse the filters list. Currently we only support HttpConnectionManager.
   size_t size = 0;
   auto* filters =
@@ -2543,8 +2683,6 @@ grpc_error_handle FilterChainParse(
               "Could not parse HttpConnectionManager config from filter "
               "typed_config"));
         } else {
-          filter_chain->filter_chain_data =
-              std::make_shared<XdsApi::LdsUpdate::FilterChainData>();
           grpc_error_handle error = HttpConnectionManagerParse(
               false /* is_client */, context, http_connection_manager, is_v2,
               &filter_chain->filter_chain_data->http_connection_manager);
@@ -3277,7 +3415,7 @@ grpc_error_handle DropParseAndAppend(
       return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Unknown denominator type");
   }
   // Cap numerator to 1000000.
-  numerator = GPR_MIN(numerator, 1000000);
+  numerator = std::min(numerator, 1000000u);
   drop_config->AddCategory(std::move(category), numerator);
   return GRPC_ERROR_NONE;
 }
@@ -3351,10 +3489,13 @@ grpc_error_handle AdsResponseParse(
     ResourceTypeSelectorFunction resource_type_selector_function,
     ProtoLogFunction proto_log_function,
     ResourceParseFunction resource_parse_function,
-    const envoy_service_discovery_v3_DiscoveryResponse* response,
     const char* resource_type_string,
-    const std::set<absl::string_view>& expected_resource_names,
-    UpdateMap* update_map, std::set<std::string>* resource_names_failed) {
+    const envoy_service_discovery_v3_DiscoveryResponse* response,
+    const std::map<absl::string_view /*authority*/,
+                   std::set<absl::string_view /*name*/>>&
+        subscribed_resource_names,
+    UpdateMap* update_map,
+    std::set<XdsApi::ResourceName>* resource_names_failed) {
   std::vector<grpc_error_handle> errors;
   // Get the resources from the response.
   size_t size;
@@ -3385,15 +3526,23 @@ grpc_error_handle AdsResponseParse(
     // Check the resource name.  Ignore unexpected names.
     std::string resource_name =
         UpbStringToStdString(proto_resource_name_function(resource));
-    if (expected_resource_names.find(resource_name) ==
-        expected_resource_names.end()) {
+    auto resource_name_status = ParseResourceNameInternal(
+        resource_name, resource_type_selector_function);
+    if (!resource_name_status.ok()) {
+      errors.push_back(GRPC_ERROR_CREATE_FROM_CPP_STRING(absl::StrCat(
+          "Cannot parse xDS resource name \"", resource_name, "\"")));
+      continue;
+    }
+    auto iter = subscribed_resource_names.find(resource_name_status->authority);
+    if (iter == subscribed_resource_names.end() ||
+        iter->second.find(resource_name_status->id) == iter->second.end()) {
       continue;
     }
     // Fail on duplicate resources.
-    if (update_map->find(resource_name) != update_map->end()) {
+    if (update_map->find(*resource_name_status) != update_map->end()) {
       errors.push_back(GRPC_ERROR_CREATE_FROM_CPP_STRING(
           absl::StrCat("duplicate resource name \"", resource_name, "\"")));
-      resource_names_failed->insert(resource_name);
+      resource_names_failed->insert(*resource_name_status);
       continue;
     }
     // Validate resource.
@@ -3405,10 +3554,10 @@ grpc_error_handle AdsResponseParse(
           grpc_error_add_child(GRPC_ERROR_CREATE_FROM_CPP_STRING(absl::StrCat(
                                    resource_name, ": validation error")),
                                error));
-      resource_names_failed->insert(resource_name);
+      resource_names_failed->insert(*resource_name_status);
     } else {
       // Store result in update map, in both validated and serialized form.
-      auto& resource_data = (*update_map)[resource_name];
+      auto& resource_data = (*update_map)[*resource_name_status];
       resource_data.resource = std::move(update);
       resource_data.serialized_proto =
           UpbStringToStdString(serialized_resource);
@@ -3455,10 +3604,18 @@ upb_strview EdsResourceName(
 
 XdsApi::AdsParseResult XdsApi::ParseAdsResponse(
     const XdsBootstrap::XdsServer& server, const grpc_slice& encoded_response,
-    const std::set<absl::string_view>& expected_listener_names,
-    const std::set<absl::string_view>& expected_route_configuration_names,
-    const std::set<absl::string_view>& expected_cluster_names,
-    const std::set<absl::string_view>& expected_eds_service_names) {
+    const std::map<absl::string_view /*authority*/,
+                   std::set<absl::string_view /*name*/>>&
+        subscribed_listener_names,
+    const std::map<absl::string_view /*authority*/,
+                   std::set<absl::string_view /*name*/>>&
+        subscribed_route_config_names,
+    const std::map<absl::string_view /*authority*/,
+                   std::set<absl::string_view /*name*/>>&
+        subscribed_cluster_names,
+    const std::map<absl::string_view /*authority*/,
+                   std::set<absl::string_view /*name*/>>&
+        subscribed_eds_service_names) {
   AdsParseResult result;
   upb::Arena arena;
   const EncodingContext context = {client_,
@@ -3493,27 +3650,27 @@ XdsApi::AdsParseResult XdsApi::ParseAdsResponse(
   if (IsLds(result.type_url)) {
     result.parse_error = AdsResponseParse(
         context, envoy_config_listener_v3_Listener_parse, LdsResourceName,
-        IsLds, MaybeLogListener, LdsResourceParse, response, "LDS",
-        expected_listener_names, &result.lds_update_map,
+        IsLdsInternal, MaybeLogListener, LdsResourceParse, "LDS", response,
+        subscribed_listener_names, &result.lds_update_map,
         &result.resource_names_failed);
   } else if (IsRds(result.type_url)) {
     result.parse_error = AdsResponseParse(
         context, envoy_config_route_v3_RouteConfiguration_parse,
-        RdsResourceName, IsRds, MaybeLogRouteConfiguration, RouteConfigParse,
-        response, "RDS", expected_route_configuration_names,
+        RdsResourceName, IsRdsInternal, MaybeLogRouteConfiguration,
+        RouteConfigParse, "RDS", response, subscribed_route_config_names,
         &result.rds_update_map, &result.resource_names_failed);
   } else if (IsCds(result.type_url)) {
     result.parse_error = AdsResponseParse(
-        context, envoy_config_cluster_v3_Cluster_parse, CdsResourceName, IsCds,
-        MaybeLogCluster, CdsResourceParse, response, "CDS",
-        expected_cluster_names, &result.cds_update_map,
+        context, envoy_config_cluster_v3_Cluster_parse, CdsResourceName,
+        IsCdsInternal, MaybeLogCluster, CdsResourceParse, "CDS", response,
+        subscribed_cluster_names, &result.cds_update_map,
         &result.resource_names_failed);
   } else if (IsEds(result.type_url)) {
     result.parse_error = AdsResponseParse(
         context, envoy_config_endpoint_v3_ClusterLoadAssignment_parse,
-        EdsResourceName, IsEds, MaybeLogClusterLoadAssignment, EdsResourceParse,
-        response, "EDS", expected_eds_service_names, &result.eds_update_map,
-        &result.resource_names_failed);
+        EdsResourceName, IsEdsInternal, MaybeLogClusterLoadAssignment,
+        EdsResourceParse, "EDS", response, subscribed_eds_service_names,
+        &result.eds_update_map, &result.resource_names_failed);
   }
   return result;
 }
@@ -3726,6 +3883,7 @@ grpc_error_handle XdsApi::ParseLrsResponse(
 }
 
 namespace {
+
 google_protobuf_Timestamp* GrpcMillisToTimestamp(const EncodingContext& context,
                                                  grpc_millis value) {
   google_protobuf_Timestamp* timestamp =
@@ -3736,218 +3894,6 @@ google_protobuf_Timestamp* GrpcMillisToTimestamp(const EncodingContext& context,
   return timestamp;
 }
 
-envoy_admin_v3_UpdateFailureState* CreateUpdateFailureStateUpb(
-    const EncodingContext& context,
-    const XdsApi::ResourceMetadata* resource_metadata) {
-  auto* update_failure_state =
-      envoy_admin_v3_UpdateFailureState_new(context.arena);
-  envoy_admin_v3_UpdateFailureState_set_details(
-      update_failure_state,
-      StdStringToUpbString(resource_metadata->failed_details));
-  envoy_admin_v3_UpdateFailureState_set_version_info(
-      update_failure_state,
-      StdStringToUpbString(resource_metadata->failed_version));
-  envoy_admin_v3_UpdateFailureState_set_last_update_attempt(
-      update_failure_state,
-      GrpcMillisToTimestamp(context, resource_metadata->failed_update_time));
-  return update_failure_state;
-}
-
-void DumpLdsConfig(const EncodingContext& context,
-                   const XdsApi::ResourceTypeMetadata& resource_type_metadata,
-                   envoy_service_status_v3_PerXdsConfig* per_xds_config) {
-  upb_strview kLdsTypeUrlUpb = upb_strview_makez(XdsApi::kLdsTypeUrl);
-  auto* listener_config_dump =
-      envoy_service_status_v3_PerXdsConfig_mutable_listener_config(
-          per_xds_config, context.arena);
-  envoy_admin_v3_ListenersConfigDump_set_version_info(
-      listener_config_dump,
-      StdStringToUpbString(resource_type_metadata.version));
-  for (auto& p : resource_type_metadata.resource_metadata_map) {
-    absl::string_view name = p.first;
-    const XdsApi::ResourceMetadata* meta = p.second;
-    const upb_strview name_upb = StdStringToUpbString(name);
-    auto* dynamic_listener =
-        envoy_admin_v3_ListenersConfigDump_add_dynamic_listeners(
-            listener_config_dump, context.arena);
-    envoy_admin_v3_ListenersConfigDump_DynamicListener_set_name(
-        dynamic_listener, name_upb);
-    envoy_admin_v3_ListenersConfigDump_DynamicListener_set_client_status(
-        dynamic_listener, meta->client_status);
-    if (!meta->serialized_proto.empty()) {
-      // Set in-effective listeners
-      auto* dynamic_listener_state =
-          envoy_admin_v3_ListenersConfigDump_DynamicListener_mutable_active_state(
-              dynamic_listener, context.arena);
-      envoy_admin_v3_ListenersConfigDump_DynamicListenerState_set_version_info(
-          dynamic_listener_state, StdStringToUpbString(meta->version));
-      envoy_admin_v3_ListenersConfigDump_DynamicListenerState_set_last_updated(
-          dynamic_listener_state,
-          GrpcMillisToTimestamp(context, meta->update_time));
-      auto* listener_any =
-          envoy_admin_v3_ListenersConfigDump_DynamicListenerState_mutable_listener(
-              dynamic_listener_state, context.arena);
-      google_protobuf_Any_set_type_url(listener_any, kLdsTypeUrlUpb);
-      google_protobuf_Any_set_value(
-          listener_any, StdStringToUpbString(meta->serialized_proto));
-    }
-    if (meta->client_status == XdsApi::ResourceMetadata::NACKED) {
-      // Set error_state if NACKED
-      envoy_admin_v3_ListenersConfigDump_DynamicListener_set_error_state(
-          dynamic_listener, CreateUpdateFailureStateUpb(context, meta));
-    }
-  }
-}
-
-void DumpRdsConfig(const EncodingContext& context,
-                   const XdsApi::ResourceTypeMetadata& resource_type_metadata,
-                   envoy_service_status_v3_PerXdsConfig* per_xds_config) {
-  upb_strview kRdsTypeUrlUpb = upb_strview_makez(XdsApi::kRdsTypeUrl);
-  auto* route_config_dump =
-      envoy_service_status_v3_PerXdsConfig_mutable_route_config(per_xds_config,
-                                                                context.arena);
-  for (auto& p : resource_type_metadata.resource_metadata_map) {
-    absl::string_view name = p.first;
-    const XdsApi::ResourceMetadata* meta = p.second;
-    const upb_strview name_upb = StdStringToUpbString(name);
-    auto* dynamic_route_config =
-        envoy_admin_v3_RoutesConfigDump_add_dynamic_route_configs(
-            route_config_dump, context.arena);
-    envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_set_client_status(
-        dynamic_route_config, meta->client_status);
-    auto* route_config_any =
-        envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_mutable_route_config(
-            dynamic_route_config, context.arena);
-    if (!meta->serialized_proto.empty()) {
-      // Set in-effective route configs
-      envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_set_version_info(
-          dynamic_route_config, StdStringToUpbString(meta->version));
-      envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_set_last_updated(
-          dynamic_route_config,
-          GrpcMillisToTimestamp(context, meta->update_time));
-      google_protobuf_Any_set_type_url(route_config_any, kRdsTypeUrlUpb);
-      google_protobuf_Any_set_value(
-          route_config_any, StdStringToUpbString(meta->serialized_proto));
-    } else {
-      // If there isn't a working route config, we still need to print the
-      // name.
-      auto* route_config =
-          envoy_config_route_v3_RouteConfiguration_new(context.arena);
-      envoy_config_route_v3_RouteConfiguration_set_name(route_config, name_upb);
-      size_t length;
-      char* bytes = envoy_config_route_v3_RouteConfiguration_serialize(
-          route_config, context.arena, &length);
-      google_protobuf_Any_set_type_url(route_config_any, kRdsTypeUrlUpb);
-      google_protobuf_Any_set_value(route_config_any,
-                                    upb_strview_make(bytes, length));
-    }
-    if (meta->client_status == XdsApi::ResourceMetadata::NACKED) {
-      // Set error_state if NACKED
-      envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_set_error_state(
-          dynamic_route_config, CreateUpdateFailureStateUpb(context, meta));
-    }
-  }
-}
-
-void DumpCdsConfig(const EncodingContext& context,
-                   const XdsApi::ResourceTypeMetadata& resource_type_metadata,
-                   envoy_service_status_v3_PerXdsConfig* per_xds_config) {
-  upb_strview kCdsTypeUrlUpb = upb_strview_makez(XdsApi::kCdsTypeUrl);
-  auto* cluster_config_dump =
-      envoy_service_status_v3_PerXdsConfig_mutable_cluster_config(
-          per_xds_config, context.arena);
-  envoy_admin_v3_ClustersConfigDump_set_version_info(
-      cluster_config_dump,
-      StdStringToUpbString(resource_type_metadata.version));
-  for (auto& p : resource_type_metadata.resource_metadata_map) {
-    absl::string_view name = p.first;
-    const XdsApi::ResourceMetadata* meta = p.second;
-    const upb_strview name_upb = StdStringToUpbString(name);
-    auto* dynamic_cluster =
-        envoy_admin_v3_ClustersConfigDump_add_dynamic_active_clusters(
-            cluster_config_dump, context.arena);
-    envoy_admin_v3_ClustersConfigDump_DynamicCluster_set_client_status(
-        dynamic_cluster, meta->client_status);
-    auto* cluster_any =
-        envoy_admin_v3_ClustersConfigDump_DynamicCluster_mutable_cluster(
-            dynamic_cluster, context.arena);
-    if (!meta->serialized_proto.empty()) {
-      // Set in-effective clusters
-      envoy_admin_v3_ClustersConfigDump_DynamicCluster_set_version_info(
-          dynamic_cluster, StdStringToUpbString(meta->version));
-      envoy_admin_v3_ClustersConfigDump_DynamicCluster_set_last_updated(
-          dynamic_cluster, GrpcMillisToTimestamp(context, meta->update_time));
-      google_protobuf_Any_set_type_url(cluster_any, kCdsTypeUrlUpb);
-      google_protobuf_Any_set_value(
-          cluster_any, StdStringToUpbString(meta->serialized_proto));
-    } else {
-      // If there isn't a working cluster, we still need to print the name.
-      auto* cluster = envoy_config_cluster_v3_Cluster_new(context.arena);
-      envoy_config_cluster_v3_Cluster_set_name(cluster, name_upb);
-      size_t length;
-      char* bytes = envoy_config_cluster_v3_Cluster_serialize(
-          cluster, context.arena, &length);
-      google_protobuf_Any_set_type_url(cluster_any, kCdsTypeUrlUpb);
-      google_protobuf_Any_set_value(cluster_any,
-                                    upb_strview_make(bytes, length));
-    }
-    if (meta->client_status == XdsApi::ResourceMetadata::NACKED) {
-      // Set error_state if NACKED
-      envoy_admin_v3_ClustersConfigDump_DynamicCluster_set_error_state(
-          dynamic_cluster, CreateUpdateFailureStateUpb(context, meta));
-    }
-  }
-}
-
-void DumpEdsConfig(const EncodingContext& context,
-                   const XdsApi::ResourceTypeMetadata& resource_type_metadata,
-                   envoy_service_status_v3_PerXdsConfig* per_xds_config) {
-  upb_strview kEdsTypeUrlUpb = upb_strview_makez(XdsApi::kEdsTypeUrl);
-  auto* endpoint_config_dump =
-      envoy_service_status_v3_PerXdsConfig_mutable_endpoint_config(
-          per_xds_config, context.arena);
-  for (auto& p : resource_type_metadata.resource_metadata_map) {
-    absl::string_view name = p.first;
-    const XdsApi::ResourceMetadata* meta = p.second;
-    const upb_strview name_upb = StdStringToUpbString(name);
-    auto* dynamic_endpoint =
-        envoy_admin_v3_EndpointsConfigDump_add_dynamic_endpoint_configs(
-            endpoint_config_dump, context.arena);
-    envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_set_client_status(
-        dynamic_endpoint, meta->client_status);
-    auto* endpoint_any =
-        envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_mutable_endpoint_config(
-            dynamic_endpoint, context.arena);
-    if (!meta->serialized_proto.empty()) {
-      // Set in-effective endpoints
-      envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_set_version_info(
-          dynamic_endpoint, StdStringToUpbString(meta->version));
-      envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_set_last_updated(
-          dynamic_endpoint, GrpcMillisToTimestamp(context, meta->update_time));
-      google_protobuf_Any_set_type_url(endpoint_any, kEdsTypeUrlUpb);
-      google_protobuf_Any_set_value(
-          endpoint_any, StdStringToUpbString(meta->serialized_proto));
-    } else {
-      // If there isn't a working endpoint, we still need to print the name.
-      auto* cluster_load_assignment =
-          envoy_config_endpoint_v3_ClusterLoadAssignment_new(context.arena);
-      envoy_config_endpoint_v3_ClusterLoadAssignment_set_cluster_name(
-          cluster_load_assignment, name_upb);
-      size_t length;
-      char* bytes = envoy_config_endpoint_v3_ClusterLoadAssignment_serialize(
-          cluster_load_assignment, context.arena, &length);
-      google_protobuf_Any_set_type_url(endpoint_any, kEdsTypeUrlUpb);
-      google_protobuf_Any_set_value(endpoint_any,
-                                    upb_strview_make(bytes, length));
-    }
-    if (meta->client_status == XdsApi::ResourceMetadata::NACKED) {
-      // Set error_state if NACKED
-      envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_set_error_state(
-          dynamic_endpoint, CreateUpdateFailureStateUpb(context, meta));
-    }
-  }
-}
-
 }  // namespace
 
 std::string XdsApi::AssembleClientConfig(
@@ -3963,33 +3909,50 @@ std::string XdsApi::AssembleClientConfig(
       arena.ptr(), true,    certificate_provider_definition_map_};
   PopulateNode(context, node_, build_version_, user_agent_name_,
                user_agent_version_, node);
-  // Dump each xDS-type config into PerXdsConfig
-  for (auto& p : resource_type_metadata_map) {
+  // Dump each resource.
+  for (const auto& p : resource_type_metadata_map) {
     absl::string_view type_url = p.first;
-    const ResourceTypeMetadata& resource_type_metadata = p.second;
-    if (type_url == kLdsTypeUrl) {
-      auto* per_xds_config =
-          envoy_service_status_v3_ClientConfig_add_xds_config(client_config,
-                                                              context.arena);
-      DumpLdsConfig(context, resource_type_metadata, per_xds_config);
-    } else if (type_url == kRdsTypeUrl) {
-      auto* per_xds_config =
-          envoy_service_status_v3_ClientConfig_add_xds_config(client_config,
-                                                              context.arena);
-      DumpRdsConfig(context, resource_type_metadata, per_xds_config);
-    } else if (type_url == kCdsTypeUrl) {
-      auto* per_xds_config =
-          envoy_service_status_v3_ClientConfig_add_xds_config(client_config,
-                                                              context.arena);
-      DumpCdsConfig(context, resource_type_metadata, per_xds_config);
-    } else if (type_url == kEdsTypeUrl) {
-      auto* per_xds_config =
-          envoy_service_status_v3_ClientConfig_add_xds_config(client_config,
-                                                              context.arena);
-      DumpEdsConfig(context, resource_type_metadata, per_xds_config);
-    } else {
-      gpr_log(GPR_ERROR, "invalid type_url %s", std::string(type_url).c_str());
-      return "";
+    const ResourceMetadataMap& resource_metadata_map = p.second;
+    for (const auto& q : resource_metadata_map) {
+      absl::string_view resource_name = q.first;
+      const ResourceMetadata& metadata = *q.second;
+      auto* entry =
+          envoy_service_status_v3_ClientConfig_add_generic_xds_configs(
+              client_config, context.arena);
+      envoy_service_status_v3_ClientConfig_GenericXdsConfig_set_type_url(
+          entry, StdStringToUpbString(type_url));
+      envoy_service_status_v3_ClientConfig_GenericXdsConfig_set_name(
+          entry, StdStringToUpbString(resource_name));
+      envoy_service_status_v3_ClientConfig_GenericXdsConfig_set_client_status(
+          entry, metadata.client_status);
+      if (!metadata.serialized_proto.empty()) {
+        envoy_service_status_v3_ClientConfig_GenericXdsConfig_set_version_info(
+            entry, StdStringToUpbString(metadata.version));
+        envoy_service_status_v3_ClientConfig_GenericXdsConfig_set_last_updated(
+            entry, GrpcMillisToTimestamp(context, metadata.update_time));
+        auto* any_field =
+            envoy_service_status_v3_ClientConfig_GenericXdsConfig_mutable_xds_config(
+                entry, context.arena);
+        google_protobuf_Any_set_type_url(any_field,
+                                         StdStringToUpbString(type_url));
+        google_protobuf_Any_set_value(
+            any_field, StdStringToUpbString(metadata.serialized_proto));
+      }
+      if (metadata.client_status == XdsApi::ResourceMetadata::NACKED) {
+        auto* update_failure_state =
+            envoy_admin_v3_UpdateFailureState_new(context.arena);
+        envoy_admin_v3_UpdateFailureState_set_details(
+            update_failure_state,
+            StdStringToUpbString(metadata.failed_details));
+        envoy_admin_v3_UpdateFailureState_set_version_info(
+            update_failure_state,
+            StdStringToUpbString(metadata.failed_version));
+        envoy_admin_v3_UpdateFailureState_set_last_update_attempt(
+            update_failure_state,
+            GrpcMillisToTimestamp(context, metadata.failed_update_time));
+        envoy_service_status_v3_ClientConfig_GenericXdsConfig_set_error_state(
+            entry, update_failure_state);
+      }
     }
   }
   // Serialize the upb message to bytes
index 50d8b7e..f521f5a 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "absl/container/inlined_vector.h"
 #include "absl/types/optional.h"
+#include "absl/types/variant.h"
 #include "envoy/admin/v3/config_dump.upb.h"
 #include "re2/re2.h"
 #include "upb/def.hpp"
@@ -65,6 +66,29 @@ class XdsApi {
   using TypedPerFilterConfig =
       std::map<std::string, XdsHttpFilterImpl::FilterConfig>;
 
+  struct RetryPolicy {
+    internal::StatusCodeSet retry_on;
+    uint32_t num_retries;
+
+    struct RetryBackOff {
+      Duration base_interval;
+      Duration max_interval;
+
+      bool operator==(const RetryBackOff& other) const {
+        return base_interval == other.base_interval &&
+               max_interval == other.max_interval;
+      }
+      std::string ToString() const;
+    };
+    RetryBackOff retry_back_off;
+
+    bool operator==(const RetryPolicy& other) const {
+      return (retry_on == other.retry_on && num_retries == other.num_retries &&
+              retry_back_off == other.retry_back_off);
+    }
+    std::string ToString() const;
+  };
+
   // TODO(donnadionne): When we can use absl::variant<>, consider using that
   // for: PathMatcher, HeaderMatcher, cluster_name and weighted_clusters
   struct Route {
@@ -82,85 +106,83 @@ class XdsApi {
       std::string ToString() const;
     };
 
-    struct HashPolicy {
-      enum Type { HEADER, CHANNEL_ID };
-      Type type;
-      bool terminal = false;
-      // Fields used for type HEADER.
-      std::string header_name;
-      std::unique_ptr<RE2> regex = nullptr;
-      std::string regex_substitution;
+    Matchers matchers;
 
-      HashPolicy() {}
+    struct UnknownAction {
+      bool operator==(const UnknownAction& /* other */) const { return true; }
+    };
 
-      // Copyable.
-      HashPolicy(const HashPolicy& other);
-      HashPolicy& operator=(const HashPolicy& other);
+    struct RouteAction {
+      struct HashPolicy {
+        enum Type { HEADER, CHANNEL_ID };
+        Type type;
+        bool terminal = false;
+        // Fields used for type HEADER.
+        std::string header_name;
+        std::unique_ptr<RE2> regex = nullptr;
+        std::string regex_substitution;
 
-      // Moveable.
-      HashPolicy(HashPolicy&& other) noexcept;
-      HashPolicy& operator=(HashPolicy&& other) noexcept;
+        HashPolicy() {}
 
-      bool operator==(const HashPolicy& other) const;
-      std::string ToString() const;
-    };
-    Matchers matchers;
-    std::vector<HashPolicy> hash_policies;
+        // Copyable.
+        HashPolicy(const HashPolicy& other);
+        HashPolicy& operator=(const HashPolicy& other);
 
-    struct RetryPolicy {
-      internal::StatusCodeSet retry_on;
-      uint32_t num_retries;
+        // Moveable.
+        HashPolicy(HashPolicy&& other) noexcept;
+        HashPolicy& operator=(HashPolicy&& other) noexcept;
 
-      struct RetryBackOff {
-        Duration base_interval;
-        Duration max_interval;
+        bool operator==(const HashPolicy& other) const;
+        std::string ToString() const;
+      };
+
+      struct ClusterWeight {
+        std::string name;
+        uint32_t weight;
+        TypedPerFilterConfig typed_per_filter_config;
 
-        bool operator==(const RetryBackOff& other) const {
-          return base_interval == other.base_interval &&
-                 max_interval == other.max_interval;
+        bool operator==(const ClusterWeight& other) const {
+          return name == other.name && weight == other.weight &&
+                 typed_per_filter_config == other.typed_per_filter_config;
         }
         std::string ToString() const;
       };
-      RetryBackOff retry_back_off;
 
-      bool operator==(const RetryPolicy& other) const {
-        return (retry_on == other.retry_on &&
-                num_retries == other.num_retries &&
-                retry_back_off == other.retry_back_off);
+      std::vector<HashPolicy> hash_policies;
+      absl::optional<RetryPolicy> retry_policy;
+
+      // Action for this route.
+      // TODO(roth): When we can use absl::variant<>, consider using that
+      // here, to enforce the fact that only one of the two fields can be set.
+      std::string cluster_name;
+      std::vector<ClusterWeight> weighted_clusters;
+      // Storing the timeout duration from route action:
+      // RouteAction.max_stream_duration.grpc_timeout_header_max or
+      // RouteAction.max_stream_duration.max_stream_duration if the former is
+      // not set.
+      absl::optional<Duration> max_stream_duration;
+
+      bool operator==(const RouteAction& other) const {
+        return hash_policies == other.hash_policies &&
+               retry_policy == other.retry_policy &&
+               cluster_name == other.cluster_name &&
+               weighted_clusters == other.weighted_clusters &&
+               max_stream_duration == other.max_stream_duration;
       }
       std::string ToString() const;
     };
-    absl::optional<RetryPolicy> retry_policy;
-
-    // Action for this route.
-    // TODO(roth): When we can use absl::variant<>, consider using that
-    // here, to enforce the fact that only one of the two fields can be set.
-    std::string cluster_name;
-    struct ClusterWeight {
-      std::string name;
-      uint32_t weight;
-      TypedPerFilterConfig typed_per_filter_config;
 
-      bool operator==(const ClusterWeight& other) const {
-        return name == other.name && weight == other.weight &&
-               typed_per_filter_config == other.typed_per_filter_config;
+    struct NonForwardingAction {
+      bool operator==(const NonForwardingAction& /* other */) const {
+        return true;
       }
-      std::string ToString() const;
     };
-    std::vector<ClusterWeight> weighted_clusters;
-    // Storing the timeout duration from route action:
-    // RouteAction.max_stream_duration.grpc_timeout_header_max or
-    // RouteAction.max_stream_duration.max_stream_duration if the former is
-    // not set.
-    absl::optional<Duration> max_stream_duration;
 
+    absl::variant<UnknownAction, RouteAction, NonForwardingAction> action;
     TypedPerFilterConfig typed_per_filter_config;
 
     bool operator==(const Route& other) const {
-      return matchers == other.matchers && cluster_name == other.cluster_name &&
-             retry_policy == other.retry_policy &&
-             weighted_clusters == other.weighted_clusters &&
-             max_stream_duration == other.max_stream_duration &&
+      return matchers == other.matchers && action == other.action &&
              typed_per_filter_config == other.typed_per_filter_config;
     }
     std::string ToString() const;
@@ -301,7 +323,7 @@ class XdsApi {
       }
 
       std::string ToString() const;
-    } filter_chain_data;
+    };
 
     // A multi-level map used to determine which filter chain to use for a given
     // incoming connection. Determining the right filter chain for a given
@@ -386,20 +408,30 @@ class XdsApi {
     std::string ToString() const;
   };
 
+  struct ResourceName {
+    std::string authority;
+    std::string id;
+
+    bool operator<(const ResourceName& other) const {
+      if (authority < other.authority) return true;
+      if (id < other.id) return true;
+      return false;
+    }
+  };
+
   struct LdsResourceData {
     LdsUpdate resource;
     std::string serialized_proto;
   };
 
-  using LdsUpdateMap = std::map<std::string /*server_name*/, LdsResourceData>;
+  using LdsUpdateMap = std::map<ResourceName, LdsResourceData>;
 
   struct RdsResourceData {
     RdsUpdate resource;
     std::string serialized_proto;
   };
 
-  using RdsUpdateMap =
-      std::map<std::string /*route_config_name*/, RdsResourceData>;
+  using RdsUpdateMap = std::map<ResourceName, RdsResourceData>;
 
   struct CdsUpdate {
     enum ClusterType { EDS, LOGICAL_DNS, AGGREGATE };
@@ -455,7 +487,7 @@ class XdsApi {
     std::string serialized_proto;
   };
 
-  using CdsUpdateMap = std::map<std::string /*cluster_name*/, CdsResourceData>;
+  using CdsUpdateMap = std::map<ResourceName, CdsResourceData>;
 
   struct EdsUpdate {
     struct Priority {
@@ -544,8 +576,7 @@ class XdsApi {
     std::string serialized_proto;
   };
 
-  using EdsUpdateMap =
-      std::map<std::string /*eds_service_name*/, EdsResourceData>;
+  using EdsUpdateMap = std::map<ResourceName, EdsResourceData>;
 
   struct ClusterLoadReport {
     XdsClusterDropStats::Snapshot dropped_requests;
@@ -594,13 +625,9 @@ class XdsApi {
     grpc_millis failed_update_time = 0;
   };
   using ResourceMetadataMap =
-      std::map<absl::string_view /*resource_name*/, const ResourceMetadata*>;
-  struct ResourceTypeMetadata {
-    absl::string_view version;
-    ResourceMetadataMap resource_metadata_map;
-  };
+      std::map<std::string /*resource_name*/, const ResourceMetadata*>;
   using ResourceTypeMetadataMap =
-      std::map<absl::string_view /*type_url*/, ResourceTypeMetadata>;
+      std::map<absl::string_view /*type_url*/, ResourceMetadataMap>;
   static_assert(static_cast<ResourceMetadata::ClientResourceStatus>(
                     envoy_admin_v3_REQUESTED) ==
                     ResourceMetadata::ClientResourceStatus::REQUESTED,
@@ -634,28 +661,53 @@ class XdsApi {
     RdsUpdateMap rds_update_map;
     CdsUpdateMap cds_update_map;
     EdsUpdateMap eds_update_map;
-    std::set<std::string> resource_names_failed;
+    std::set<ResourceName> resource_names_failed;
   };
 
   XdsApi(XdsClient* client, TraceFlag* tracer, const XdsBootstrap::Node* node,
          const CertificateProviderStore::PluginDefinitionMap* map);
 
+  static bool IsLds(absl::string_view type_url);
+  static bool IsRds(absl::string_view type_url);
+  static bool IsCds(absl::string_view type_url);
+  static bool IsEds(absl::string_view type_url);
+
+  // A helper method to parse the resource name and return back a ResourceName
+  // struct.  Optionally the parser can check the resource type portion of the
+  // resource name.
+  static absl::StatusOr<ResourceName> ParseResourceName(
+      absl::string_view name,
+      bool (*is_expected_type)(absl::string_view) = nullptr);
+
+  // A helper method to construct the resource name from parts.
+  static std::string ConstructFullResourceName(absl::string_view authority,
+                                               absl::string_view resource_type,
+                                               absl::string_view name);
+
   // Creates an ADS request.
   // Takes ownership of \a error.
-  grpc_slice CreateAdsRequest(const XdsBootstrap::XdsServer& server,
-                              const std::string& type_url,
-                              const std::set<absl::string_view>& resource_names,
-                              const std::string& version,
-                              const std::string& nonce, grpc_error_handle error,
-                              bool populate_node);
+  grpc_slice CreateAdsRequest(
+      const XdsBootstrap::XdsServer& server, const std::string& type_url,
+      const std::map<absl::string_view /*authority*/,
+                     std::set<absl::string_view /*name*/>>& resource_names,
+      const std::string& version, const std::string& nonce,
+      grpc_error_handle error, bool populate_node);
 
   // Parses an ADS response.
   AdsParseResult ParseAdsResponse(
       const XdsBootstrap::XdsServer& server, const grpc_slice& encoded_response,
-      const std::set<absl::string_view>& expected_listener_names,
-      const std::set<absl::string_view>& expected_route_configuration_names,
-      const std::set<absl::string_view>& expected_cluster_names,
-      const std::set<absl::string_view>& expected_eds_service_names);
+      const std::map<absl::string_view /*authority*/,
+                     std::set<absl::string_view /*name*/>>&
+          subscribed_listener_names,
+      const std::map<absl::string_view /*authority*/,
+                     std::set<absl::string_view /*name*/>>&
+          subscribed_route_config_names,
+      const std::map<absl::string_view /*authority*/,
+                     std::set<absl::string_view /*name*/>>&
+          subscribed_cluster_names,
+      const std::map<absl::string_view /*authority*/,
+                     std::set<absl::string_view /*name*/>>&
+          subscribed_eds_service_names);
 
   // Creates an initial LRS request.
   grpc_slice CreateLrsInitialRequest(const XdsBootstrap::XdsServer& server);
index eff5e7a..8878bd8 100644 (file)
@@ -64,6 +64,16 @@ class XdsBootstrap {
     Json channel_creds_config;
     std::set<std::string> server_features;
 
+    bool operator<(const XdsServer& other) const {
+      if (server_uri < other.server_uri) return true;
+      if (channel_creds_type < other.channel_creds_type) return true;
+      if (channel_creds_config.Dump() < other.channel_creds_config.Dump()) {
+        return true;
+      }
+      if (server_features < other.server_features) return true;
+      return false;
+    }
+
     bool ShouldUseV3() const;
   };
 
index ce1ba67..1b9ca75 100644 (file)
@@ -23,8 +23,6 @@
 #include "absl/functional/bind_front.h"
 #include "absl/strings/str_cat.h"
 
-#include "src/core/lib/gpr/useful.h"
-
 namespace grpc_core {
 
 namespace {
@@ -379,7 +377,9 @@ void XdsCertificateProviderArgDestroy(void* p) {
   xds_certificate_provider->Unref();
 }
 
-int XdsCertificateProviderArgCmp(void* p, void* q) { return GPR_ICMP(p, q); }
+int XdsCertificateProviderArgCmp(void* p, void* q) {
+  return QsortCompare(p, q);
+}
 
 const grpc_arg_pointer_vtable kChannelArgVtable = {
     XdsCertificateProviderArgCopy, XdsCertificateProviderArgDestroy,
diff --git a/src/core/ext/xds/xds_channel_stack_modifier.cc b/src/core/ext/xds/xds_channel_stack_modifier.cc
new file mode 100644 (file)
index 0000000..3fd5c58
--- /dev/null
@@ -0,0 +1,113 @@
+//
+//
+// 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 <grpc/support/port_platform.h>
+
+#include "src/core/ext/xds/xds_channel_stack_modifier.h"
+
+#include "src/core/lib/config/core_configuration.h"
+#include "src/core/lib/surface/channel_init.h"
+
+namespace grpc_core {
+namespace {
+
+void* XdsChannelStackModifierArgCopy(void* p) {
+  XdsChannelStackModifier* arg = static_cast<XdsChannelStackModifier*>(p);
+  return arg->Ref().release();
+}
+
+void XdsChannelStackModifierArgDestroy(void* p) {
+  XdsChannelStackModifier* arg = static_cast<XdsChannelStackModifier*>(p);
+  arg->Unref();
+}
+
+int XdsChannelStackModifierArgCmp(void* p, void* q) {
+  return QsortCompare(p, q);
+}
+
+const grpc_arg_pointer_vtable kChannelArgVtable = {
+    XdsChannelStackModifierArgCopy, XdsChannelStackModifierArgDestroy,
+    XdsChannelStackModifierArgCmp};
+
+const char* kXdsChannelStackModifierChannelArgName =
+    "grpc.internal.xds_channel_stack_modifier";
+
+}  // namespace
+
+bool XdsChannelStackModifier::ModifyChannelStack(
+    grpc_channel_stack_builder* builder) {
+  // Insert the filters after the census filter if present.
+  grpc_channel_stack_builder_iterator* it =
+      grpc_channel_stack_builder_create_iterator_at_first(builder);
+  while (grpc_channel_stack_builder_move_next(it)) {
+    if (grpc_channel_stack_builder_iterator_is_end(it)) break;
+    const char* filter_name_at_it =
+        grpc_channel_stack_builder_iterator_filter_name(it);
+    if (strcmp("census_server", filter_name_at_it) == 0 ||
+        strcmp("opencensus_server", filter_name_at_it) == 0) {
+      break;
+    }
+  }
+  if (grpc_channel_stack_builder_iterator_is_end(it)) {
+    // No census filter found. Reset iterator to the beginning. This will result
+    // in prepending the list of xDS HTTP filters to the current stack. Note
+    // that this stage is run before the stage that adds the top server filter,
+    // resulting in these filters being finally placed after the `server`
+    // filter.
+    grpc_channel_stack_builder_iterator_destroy(it);
+    it = grpc_channel_stack_builder_create_iterator_at_first(builder);
+  }
+  GPR_ASSERT(grpc_channel_stack_builder_move_next(it));
+  for (const grpc_channel_filter* filter : filters_) {
+    GPR_ASSERT(grpc_channel_stack_builder_add_filter_before(it, filter, nullptr,
+                                                            nullptr));
+  }
+  grpc_channel_stack_builder_iterator_destroy(it);
+  return true;
+}
+
+grpc_arg XdsChannelStackModifier::MakeChannelArg() const {
+  return grpc_channel_arg_pointer_create(
+      const_cast<char*>(kXdsChannelStackModifierChannelArgName),
+      const_cast<XdsChannelStackModifier*>(this), &kChannelArgVtable);
+}
+
+RefCountedPtr<XdsChannelStackModifier>
+XdsChannelStackModifier::GetFromChannelArgs(const grpc_channel_args& args) {
+  XdsChannelStackModifier* config_selector_provider =
+      grpc_channel_args_find_pointer<XdsChannelStackModifier>(
+          &args, kXdsChannelStackModifierChannelArgName);
+  return config_selector_provider != nullptr ? config_selector_provider->Ref()
+                                             : nullptr;
+}
+
+void RegisterXdsChannelStackModifier(CoreConfiguration::Builder* builder) {
+  builder->channel_init()->RegisterStage(
+      GRPC_SERVER_CHANNEL, INT_MAX, [](grpc_channel_stack_builder* builder) {
+        grpc_core::RefCountedPtr<XdsChannelStackModifier>
+            channel_stack_modifier =
+                XdsChannelStackModifier::GetFromChannelArgs(
+                    *grpc_channel_stack_builder_get_channel_arguments(builder));
+        if (channel_stack_modifier != nullptr) {
+          return channel_stack_modifier->ModifyChannelStack(builder);
+        }
+        return true;
+      });
+}
+
+}  // namespace grpc_core
diff --git a/src/core/ext/xds/xds_channel_stack_modifier.h b/src/core/ext/xds/xds_channel_stack_modifier.h
new file mode 100644 (file)
index 0000000..bf6d2ff
--- /dev/null
@@ -0,0 +1,52 @@
+//
+//
+// 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.
+//
+//
+
+#ifndef GRPC_CORE_EXT_XDS_XDS_CHANNEL_STACK_MODIFIER_H
+#define GRPC_CORE_EXT_XDS_XDS_CHANNEL_STACK_MODIFIER_H
+
+#include <grpc/support/port_platform.h>
+
+#include <vector>
+
+#include "src/core/lib/channel/channel_stack.h"
+#include "src/core/lib/channel/channel_stack_builder.h"
+#include "src/core/lib/gprpp/ref_counted.h"
+
+namespace grpc_core {
+
+// XdsChannelStackModifier allows for inserting xDS HTTP filters into the
+// channel stack. It is registered to mutate the `grpc_channel_stack_builder`
+// object via ChannelInit::Builder::RegisterStage.
+class XdsChannelStackModifier : public RefCounted<XdsChannelStackModifier> {
+ public:
+  explicit XdsChannelStackModifier(
+      std::vector<const grpc_channel_filter*> filters)
+      : filters_(std::move(filters)) {}
+  // Returns true on success, false otherwise.
+  bool ModifyChannelStack(grpc_channel_stack_builder* builder);
+  grpc_arg MakeChannelArg() const;
+  static RefCountedPtr<XdsChannelStackModifier> GetFromChannelArgs(
+      const grpc_channel_args& args);
+
+ private:
+  std::vector<const grpc_channel_filter*> filters_;
+};
+
+}  // namespace grpc_core
+
+#endif /* GRPC_CORE_EXT_XDS_XDS_CHANNEL_STACK_MODIFIER_H */
index 78de195..4e94198 100644 (file)
@@ -33,7 +33,6 @@
 #include <grpc/support/time.h>
 
 #include "src/core/ext/filters/client_channel/client_channel.h"
-#include "src/core/ext/filters/client_channel/service_config.h"
 #include "src/core/ext/xds/xds_api.h"
 #include "src/core/ext/xds/xds_bootstrap.h"
 #include "src/core/ext/xds/xds_channel_args.h"
@@ -55,8 +54,8 @@
 #include "src/core/lib/slice/slice_string_helpers.h"
 #include "src/core/lib/surface/call.h"
 #include "src/core/lib/surface/channel.h"
-#include "src/core/lib/surface/channel_init.h"
 #include "src/core/lib/transport/static_metadata.h"
+#include "src/core/lib/uri/uri_parser.h"
 
 #define GRPC_XDS_INITIAL_CONNECT_BACKOFF_SECONDS 1
 #define GRPC_XDS_RECONNECT_BACKOFF_MULTIPLIER 1.6
@@ -72,6 +71,7 @@ TraceFlag grpc_xds_client_refcount_trace(false, "xds_client_refcount");
 namespace {
 
 Mutex* g_mu = nullptr;
+
 const grpc_channel_args* g_channel_args ABSL_GUARDED_BY(*g_mu) = nullptr;
 XdsClient* g_xds_client ABSL_GUARDED_BY(*g_mu) = nullptr;
 char* g_fallback_bootstrap_config ABSL_GUARDED_BY(*g_mu) = nullptr;
@@ -88,7 +88,7 @@ template <typename T>
 class XdsClient::ChannelState::RetryableCall
     : public InternallyRefCounted<RetryableCall<T>> {
  public:
-  explicit RetryableCall(RefCountedPtr<ChannelState> chand);
+  explicit RetryableCall(WeakRefCountedPtr<ChannelState> chand);
 
   void Orphan() override;
 
@@ -109,7 +109,7 @@ class XdsClient::ChannelState::RetryableCall
   // every time we start a new call. It's null during call retry backoff.
   OrphanablePtr<T> calld_;
   // The owning xds channel.
-  RefCountedPtr<ChannelState> chand_;
+  WeakRefCountedPtr<ChannelState> chand_;
 
   // Retry state.
   BackOff backoff_;
@@ -135,9 +135,11 @@ class XdsClient::ChannelState::AdsCallState
   XdsClient* xds_client() const { return chand()->xds_client(); }
   bool seen_response() const { return seen_response_; }
 
-  void SubscribeLocked(const std::string& type_url, const std::string& name)
+  void SubscribeLocked(const std::string& type_url,
+                       const XdsApi::ResourceName& resource)
       ABSL_EXCLUSIVE_LOCKS_REQUIRED(&XdsClient::mu_);
-  void UnsubscribeLocked(const std::string& type_url, const std::string& name,
+  void UnsubscribeLocked(const std::string& type_url,
+                         const XdsApi::ResourceName& resource,
                          bool delay_unsubscription)
       ABSL_EXCLUSIVE_LOCKS_REQUIRED(&XdsClient::mu_);
 
@@ -146,10 +148,11 @@ class XdsClient::ChannelState::AdsCallState
  private:
   class ResourceState : public InternallyRefCounted<ResourceState> {
    public:
-    ResourceState(const std::string& type_url, const std::string& name,
+    ResourceState(const std::string& type_url,
+                  const XdsApi::ResourceName& resource,
                   bool sent_initial_request)
         : type_url_(type_url),
-          name_(name),
+          resource_(resource),
           sent_initial_request_(sent_initial_request) {
       GRPC_CLOSURE_INIT(&timer_callback_, OnTimer, this,
                         grpc_schedule_on_exec_ctx);
@@ -197,34 +200,38 @@ class XdsClient::ChannelState::AdsCallState
         grpc_error_handle watcher_error =
             GRPC_ERROR_CREATE_FROM_CPP_STRING(absl::StrFormat(
                 "timeout obtaining resource {type=%s name=%s} from xds server",
-                type_url_, name_));
+                type_url_,
+                XdsApi::ConstructFullResourceName(resource_.authority,
+                                                  type_url_, resource_.id)));
         watcher_error = grpc_error_set_int(
             watcher_error, GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
         if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
           gpr_log(GPR_INFO, "[xds_client %p] %s", ads_calld_->xds_client(),
                   grpc_error_std_string(watcher_error).c_str());
         }
+        auto& authority_state =
+            ads_calld_->xds_client()->authority_state_map_[resource_.authority];
         if (type_url_ == XdsApi::kLdsTypeUrl) {
-          ListenerState& state = ads_calld_->xds_client()->listener_map_[name_];
+          ListenerState& state = authority_state.listener_map[resource_.id];
           state.meta.client_status = XdsApi::ResourceMetadata::DOES_NOT_EXIST;
           for (const auto& p : state.watchers) {
             p.first->OnError(GRPC_ERROR_REF(watcher_error));
           }
         } else if (type_url_ == XdsApi::kRdsTypeUrl) {
           RouteConfigState& state =
-              ads_calld_->xds_client()->route_config_map_[name_];
+              authority_state.route_config_map[resource_.id];
           state.meta.client_status = XdsApi::ResourceMetadata::DOES_NOT_EXIST;
           for (const auto& p : state.watchers) {
             p.first->OnError(GRPC_ERROR_REF(watcher_error));
           }
         } else if (type_url_ == XdsApi::kCdsTypeUrl) {
-          ClusterState& state = ads_calld_->xds_client()->cluster_map_[name_];
+          ClusterState& state = authority_state.cluster_map[resource_.id];
           state.meta.client_status = XdsApi::ResourceMetadata::DOES_NOT_EXIST;
           for (const auto& p : state.watchers) {
             p.first->OnError(GRPC_ERROR_REF(watcher_error));
           }
         } else if (type_url_ == XdsApi::kEdsTypeUrl) {
-          EndpointState& state = ads_calld_->xds_client()->endpoint_map_[name_];
+          EndpointState& state = authority_state.endpoint_map[resource_.id];
           state.meta.client_status = XdsApi::ResourceMetadata::DOES_NOT_EXIST;
           for (const auto& p : state.watchers) {
             p.first->OnError(GRPC_ERROR_REF(watcher_error));
@@ -238,7 +245,7 @@ class XdsClient::ChannelState::AdsCallState
     }
 
     const std::string type_url_;
-    const std::string name_;
+    const XdsApi::ResourceName resource_;
 
     RefCountedPtr<AdsCallState> ads_calld_;
     bool sent_initial_request_;
@@ -255,32 +262,41 @@ class XdsClient::ChannelState::AdsCallState
     grpc_error_handle error = GRPC_ERROR_NONE;
 
     // Subscribed resources of this type.
-    std::map<std::string /* name */, OrphanablePtr<ResourceState>>
+    std::map<std::string /*authority*/,
+             std::map<std::string /*name*/, OrphanablePtr<ResourceState>>>
         subscribed_resources;
   };
 
   void SendMessageLocked(const std::string& type_url)
       ABSL_EXCLUSIVE_LOCKS_REQUIRED(&XdsClient::mu_);
 
-  void AcceptLdsUpdateLocked(std::string version, grpc_millis update_time,
-                             XdsApi::LdsUpdateMap lds_update_map,
-                             const std::set<std::string>& resource_names_failed)
+  void AcceptLdsUpdateLocked(
+      std::string version, grpc_millis update_time,
+      XdsApi::LdsUpdateMap lds_update_map,
+      const std::set<XdsApi::ResourceName>& resource_names_failed)
       ABSL_EXCLUSIVE_LOCKS_REQUIRED(&XdsClient::mu_);
   void AcceptRdsUpdateLocked(std::string version, grpc_millis update_time,
                              XdsApi::RdsUpdateMap rds_update_map)
       ABSL_EXCLUSIVE_LOCKS_REQUIRED(&XdsClient::mu_);
-  void AcceptCdsUpdateLocked(std::string version, grpc_millis update_time,
-                             XdsApi::CdsUpdateMap cds_update_map,
-                             const std::set<std::string>& resource_names_failed)
+  void AcceptCdsUpdateLocked(
+      std::string version, grpc_millis update_time,
+      XdsApi::CdsUpdateMap cds_update_map,
+      const std::set<XdsApi::ResourceName>& resource_names_failed)
       ABSL_EXCLUSIVE_LOCKS_REQUIRED(&XdsClient::mu_);
   void AcceptEdsUpdateLocked(std::string version, grpc_millis update_time,
                              XdsApi::EdsUpdateMap eds_update_map)
       ABSL_EXCLUSIVE_LOCKS_REQUIRED(&XdsClient::mu_);
 
   template <typename StateMap>
+  void RejectAdsUpdateHelperLocked(const std::string& resource_name,
+                                   grpc_millis update_time,
+                                   const XdsApi::AdsParseResult& result,
+                                   const std::string& error_details,
+                                   StateMap* state_map)
+      ABSL_EXCLUSIVE_LOCKS_REQUIRED(&XdsClient::mu_);
+
   void RejectAdsUpdateLocked(grpc_millis update_time,
-                             const XdsApi::AdsParseResult& result,
-                             StateMap* state_map)
+                             const XdsApi::AdsParseResult& result)
       ABSL_EXCLUSIVE_LOCKS_REQUIRED(&XdsClient::mu_);
 
   static void OnRequestSent(void* arg, grpc_error_handle error);
@@ -295,8 +311,9 @@ class XdsClient::ChannelState::AdsCallState
 
   bool IsCurrentCallOnChannel() const;
 
-  std::set<absl::string_view> ResourceNamesForRequest(
-      const std::string& type_url);
+  std::map<absl::string_view /*authority*/,
+           std::set<absl::string_view /*name*/>>
+  ResourceNamesForRequest(const std::string& type_url);
 
   // The owning RetryableCall<>.
   RefCountedPtr<RetryableCall<AdsCallState>> parent_;
@@ -441,7 +458,7 @@ class XdsClient::ChannelState::LrsCallState
 class XdsClient::ChannelState::StateWatcher
     : public AsyncConnectivityStateWatcherInterface {
  public:
-  explicit StateWatcher(RefCountedPtr<ChannelState> parent)
+  explicit StateWatcher(WeakRefCountedPtr<ChannelState> parent)
       : parent_(std::move(parent)) {}
 
  private:
@@ -461,7 +478,7 @@ class XdsClient::ChannelState::StateWatcher
     }
   }
 
-  RefCountedPtr<ChannelState> parent_;
+  WeakRefCountedPtr<ChannelState> parent_;
 };
 
 //
@@ -483,7 +500,7 @@ grpc_channel* CreateXdsChannel(grpc_channel_args* args,
 
 XdsClient::ChannelState::ChannelState(WeakRefCountedPtr<XdsClient> xds_client,
                                       const XdsBootstrap::XdsServer& server)
-    : InternallyRefCounted<ChannelState>(
+    : DualRefCounted<ChannelState>(
           GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_refcount_trace)
               ? "ChannelState"
               : nullptr),
@@ -507,12 +524,19 @@ XdsClient::ChannelState::~ChannelState() {
   xds_client_.reset(DEBUG_LOCATION, "ChannelState");
 }
 
-void XdsClient::ChannelState::Orphan() {
+// This method should only ever be called when holding the lock, but we can't
+// use a ABSL_EXCLUSIVE_LOCKS_REQUIRED annotation, because Orphan() will be
+// called from DualRefCounted::Unref, which cannot have a lock annotation for a
+// lock in this subclass.
+void XdsClient::ChannelState::Orphan() ABSL_NO_THREAD_SAFETY_ANALYSIS {
   shutting_down_ = true;
   CancelConnectivityWatchLocked();
+  // At this time, all strong refs are removed, remove from channel map to
+  // prevent subsequent subscription from trying to use this ChannelState as it
+  // is shutting down.
+  xds_client_->xds_server_channel_map_.erase(server_);
   ads_calld_.reset();
   lrs_calld_.reset();
-  Unref(DEBUG_LOCATION, "ChannelState+orphaned");
 }
 
 XdsClient::ChannelState::AdsCallState* XdsClient::ChannelState::ads_calld()
@@ -531,8 +555,8 @@ bool XdsClient::ChannelState::HasActiveAdsCall() const {
 
 void XdsClient::ChannelState::MaybeStartLrsCall() {
   if (lrs_calld_ != nullptr) return;
-  lrs_calld_.reset(
-      new RetryableCall<LrsCallState>(Ref(DEBUG_LOCATION, "ChannelState+lrs")));
+  lrs_calld_.reset(new RetryableCall<LrsCallState>(
+      WeakRef(DEBUG_LOCATION, "ChannelState+lrs")));
 }
 
 void XdsClient::ChannelState::StopLrsCall() { lrs_calld_.reset(); }
@@ -540,7 +564,7 @@ void XdsClient::ChannelState::StopLrsCall() { lrs_calld_.reset(); }
 void XdsClient::ChannelState::StartConnectivityWatchLocked() {
   ClientChannel* client_channel = ClientChannel::GetFromChannel(channel_);
   GPR_ASSERT(client_channel != nullptr);
-  watcher_ = new StateWatcher(Ref(DEBUG_LOCATION, "ChannelState+watch"));
+  watcher_ = new StateWatcher(WeakRef(DEBUG_LOCATION, "ChannelState+watch"));
   client_channel->AddConnectivityWatcher(
       GRPC_CHANNEL_IDLE,
       OrphanablePtr<AsyncConnectivityStateWatcherInterface>(watcher_));
@@ -552,12 +576,12 @@ void XdsClient::ChannelState::CancelConnectivityWatchLocked() {
   client_channel->RemoveConnectivityWatcher(watcher_);
 }
 
-void XdsClient::ChannelState::SubscribeLocked(const std::string& type_url,
-                                              const std::string& name) {
+void XdsClient::ChannelState::SubscribeLocked(
+    const std::string& type_url, const XdsApi::ResourceName& resource) {
   if (ads_calld_ == nullptr) {
     // Start the ADS call if this is the first request.
     ads_calld_.reset(new RetryableCall<AdsCallState>(
-        Ref(DEBUG_LOCATION, "ChannelState+ads")));
+        WeakRef(DEBUG_LOCATION, "ChannelState+ads")));
     // Note: AdsCallState's ctor will automatically subscribe to all
     // resources that the XdsClient already has watchers for, so we can
     // return here.
@@ -567,17 +591,19 @@ void XdsClient::ChannelState::SubscribeLocked(const std::string& type_url,
   // because when the call is restarted it will resend all necessary requests.
   if (ads_calld() == nullptr) return;
   // Subscribe to this resource if the ADS call is active.
-  ads_calld()->SubscribeLocked(type_url, name);
+  ads_calld()->SubscribeLocked(type_url, resource);
 }
 
-void XdsClient::ChannelState::UnsubscribeLocked(const std::string& type_url,
-                                                const std::string& name,
-                                                bool delay_unsubscription) {
+void XdsClient::ChannelState::UnsubscribeLocked(
+    const std::string& type_url, const XdsApi::ResourceName& resource,
+    bool delay_unsubscription) {
   if (ads_calld_ != nullptr) {
     auto* calld = ads_calld_->calld();
     if (calld != nullptr) {
-      calld->UnsubscribeLocked(type_url, name, delay_unsubscription);
-      if (!calld->HasSubscribedResources()) ads_calld_.reset();
+      calld->UnsubscribeLocked(type_url, resource, delay_unsubscription);
+      if (!calld->HasSubscribedResources()) {
+        ads_calld_.reset();
+      }
     }
   }
 }
@@ -588,7 +614,7 @@ void XdsClient::ChannelState::UnsubscribeLocked(const std::string& type_url,
 
 template <typename T>
 XdsClient::ChannelState::RetryableCall<T>::RetryableCall(
-    RefCountedPtr<ChannelState> chand)
+    WeakRefCountedPtr<ChannelState> chand)
     : chand_(std::move(chand)),
       backoff_(
           BackOff::Options()
@@ -646,7 +672,8 @@ void XdsClient::ChannelState::RetryableCall<T>::StartRetryTimerLocked() {
   if (shutting_down_) return;
   const grpc_millis next_attempt_time = backoff_.NextAttemptTime();
   if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
-    grpc_millis timeout = GPR_MAX(next_attempt_time - ExecCtx::Get()->Now(), 0);
+    grpc_millis timeout =
+        std::max(next_attempt_time - ExecCtx::Get()->Now(), grpc_millis(0));
     gpr_log(GPR_INFO,
             "[xds_client %p] Failed to connect to xds server (chand: %p) "
             "retry timer will fire in %" PRId64 "ms.",
@@ -737,17 +764,26 @@ XdsClient::ChannelState::AdsCallState::AdsCallState(
   // Op: send request message.
   GRPC_CLOSURE_INIT(&on_request_sent_, OnRequestSent, this,
                     grpc_schedule_on_exec_ctx);
-  for (const auto& p : xds_client()->listener_map_) {
-    SubscribeLocked(XdsApi::kLdsTypeUrl, std::string(p.first));
-  }
-  for (const auto& p : xds_client()->route_config_map_) {
-    SubscribeLocked(XdsApi::kRdsTypeUrl, std::string(p.first));
-  }
-  for (const auto& p : xds_client()->cluster_map_) {
-    SubscribeLocked(XdsApi::kCdsTypeUrl, std::string(p.first));
-  }
-  for (const auto& p : xds_client()->endpoint_map_) {
-    SubscribeLocked(XdsApi::kEdsTypeUrl, std::string(p.first));
+  for (const auto& a : xds_client()->authority_state_map_) {
+    const std::string& authority = a.first;
+    // Skip authorities that are not using this xDS channel.
+    if (a.second.channel_state != chand()) continue;
+    for (const auto& l : a.second.listener_map) {
+      const std::string& listener_name = l.first;
+      SubscribeLocked(XdsApi::kLdsTypeUrl, {authority, listener_name});
+    }
+    for (const auto& r : a.second.route_config_map) {
+      const std::string& route_config_name = r.first;
+      SubscribeLocked(XdsApi::kRdsTypeUrl, {authority, route_config_name});
+    }
+    for (const auto& c : a.second.cluster_map) {
+      const std::string& cluster_name = c.first;
+      SubscribeLocked(XdsApi::kCdsTypeUrl, {authority, cluster_name});
+    }
+    for (const auto& e : a.second.endpoint_map) {
+      const std::string& endpoint_name = e.first;
+      SubscribeLocked(XdsApi::kEdsTypeUrl, {authority, endpoint_name});
+    }
   }
   // Op: recv initial metadata.
   op = ops;
@@ -820,11 +856,12 @@ void XdsClient::ChannelState::AdsCallState::SendMessageLocked(
   }
   auto& state = state_map_[type_url];
   grpc_slice request_payload_slice;
-  std::set<absl::string_view> resource_names =
-      ResourceNamesForRequest(type_url);
+  std::map<absl::string_view /*authority*/,
+           std::set<absl::string_view /*name*/>>
+      resource_map = ResourceNamesForRequest(type_url);
   request_payload_slice = xds_client()->api_.CreateAdsRequest(
-      chand()->server_, type_url, resource_names,
-      xds_client()->resource_version_map_[type_url], state.nonce,
+      chand()->server_, type_url, resource_map,
+      chand()->resource_type_version_map_[type_url], state.nonce,
       GRPC_ERROR_REF(state.error), !sent_initial_message_);
   if (type_url != XdsApi::kLdsTypeUrl && type_url != XdsApi::kRdsTypeUrl &&
       type_url != XdsApi::kCdsTypeUrl && type_url != XdsApi::kEdsTypeUrl) {
@@ -834,11 +871,10 @@ void XdsClient::ChannelState::AdsCallState::SendMessageLocked(
   if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
     gpr_log(GPR_INFO,
             "[xds_client %p] sending ADS request: type=%s version=%s nonce=%s "
-            "error=%s resources=%s",
+            "error=%s",
             xds_client(), type_url.c_str(),
-            xds_client()->resource_version_map_[type_url].c_str(),
-            state.nonce.c_str(), grpc_error_std_string(state.error).c_str(),
-            absl::StrJoin(resource_names, " ").c_str());
+            chand()->resource_type_version_map_[type_url].c_str(),
+            state.nonce.c_str(), grpc_error_std_string(state.error).c_str());
   }
   GRPC_ERROR_UNREF(state.error);
   state.error = GRPC_ERROR_NONE;
@@ -865,19 +901,26 @@ void XdsClient::ChannelState::AdsCallState::SendMessageLocked(
 }
 
 void XdsClient::ChannelState::AdsCallState::SubscribeLocked(
-    const std::string& type_url, const std::string& name) {
-  auto& state = state_map_[type_url].subscribed_resources[name];
+    const std::string& type_url, const XdsApi::ResourceName& resource) {
+  auto& state = state_map_[type_url]
+                    .subscribed_resources[resource.authority][resource.id];
   if (state == nullptr) {
     state = MakeOrphanable<ResourceState>(
-        type_url, name, !xds_client()->resource_version_map_[type_url].empty());
+        type_url, resource,
+        !chand()->resource_type_version_map_[type_url].empty());
     SendMessageLocked(type_url);
   }
 }
 
 void XdsClient::ChannelState::AdsCallState::UnsubscribeLocked(
-    const std::string& type_url, const std::string& name,
+    const std::string& type_url, const XdsApi::ResourceName& resource,
     bool delay_unsubscription) {
-  state_map_[type_url].subscribed_resources.erase(name);
+  auto& type_state_map = state_map_[type_url];
+  auto& authority_map = type_state_map.subscribed_resources[resource.authority];
+  authority_map.erase(resource.id);
+  if (authority_map.empty()) {
+    type_state_map.subscribed_resources.erase(resource.authority);
+  }
   if (!delay_unsubscription) SendMessageLocked(type_url);
 }
 
@@ -907,7 +950,7 @@ XdsApi::ResourceMetadata CreateResourceMetadataAcked(
 void XdsClient::ChannelState::AdsCallState::AcceptLdsUpdateLocked(
     std::string version, grpc_millis update_time,
     XdsApi::LdsUpdateMap lds_update_map,
-    const std::set<std::string>& resource_names_failed) {
+    const std::set<XdsApi::ResourceName>& resource_names_failed) {
   if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
     gpr_log(GPR_INFO,
             "[xds_client %p] LDS update received containing %" PRIuPTR
@@ -917,28 +960,38 @@ void XdsClient::ChannelState::AdsCallState::AcceptLdsUpdateLocked(
   auto& lds_state = state_map_[XdsApi::kLdsTypeUrl];
   std::set<std::string> rds_resource_names_seen;
   for (auto& p : lds_update_map) {
-    const std::string& listener_name = p.first;
+    const XdsApi::ResourceName& resource = p.first;
     XdsApi::LdsUpdate& lds_update = p.second.resource;
-    auto& state = lds_state.subscribed_resources[listener_name];
+    auto& state =
+        lds_state.subscribed_resources[resource.authority][resource.id];
     if (state != nullptr) state->Finish();
     if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
       gpr_log(GPR_INFO, "[xds_client %p] LDS resource %s: %s", xds_client(),
-              listener_name.c_str(), lds_update.ToString().c_str());
+              XdsApi::ConstructFullResourceName(
+                  resource.authority, XdsApi::kLdsTypeUrl, resource.id)
+                  .c_str(),
+              lds_update.ToString().c_str());
     }
     // Record the RDS resource names seen.
     if (!lds_update.http_connection_manager.route_config_name.empty()) {
       rds_resource_names_seen.insert(
           lds_update.http_connection_manager.route_config_name);
     }
+    ListenerState& listener_state =
+        xds_client()
+            ->authority_state_map_[resource.authority]
+            .listener_map[resource.id];
     // Ignore identical update.
-    ListenerState& listener_state = xds_client()->listener_map_[listener_name];
     if (listener_state.update.has_value() &&
         *listener_state.update == lds_update) {
       if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
         gpr_log(GPR_INFO,
                 "[xds_client %p] LDS update for %s identical to current, "
                 "ignoring.",
-                xds_client(), listener_name.c_str());
+                xds_client(),
+                XdsApi::ConstructFullResourceName(
+                    resource.authority, XdsApi::kLdsTypeUrl, resource.id)
+                    .c_str());
       }
       continue;
     }
@@ -954,35 +1007,43 @@ void XdsClient::ChannelState::AdsCallState::AcceptLdsUpdateLocked(
   // For invalid resources in the update, if they are already in the
   // cache, pretend that they are present in the update, so that we
   // don't incorrectly consider them deleted below.
-  for (const std::string& listener_name : resource_names_failed) {
-    auto it = xds_client()->listener_map_.find(listener_name);
-    if (it != xds_client()->listener_map_.end()) {
-      auto& resource = it->second.update;
-      if (!resource.has_value()) continue;
-      lds_update_map[listener_name];
-      if (!resource->http_connection_manager.route_config_name.empty()) {
+  for (const auto& resource : resource_names_failed) {
+    auto& listener_map =
+        xds_client()->authority_state_map_[resource.authority].listener_map;
+    auto it = listener_map.find(resource.id);
+    if (it != listener_map.end()) {
+      auto& update = it->second.update;
+      if (!update.has_value()) continue;
+      lds_update_map[resource];
+      if (!update->http_connection_manager.route_config_name.empty()) {
         rds_resource_names_seen.insert(
-            resource->http_connection_manager.route_config_name);
+            update->http_connection_manager.route_config_name);
       }
     }
   }
   // For any subscribed resource that is not present in the update,
   // remove it from the cache and notify watchers that it does not exist.
-  for (const auto& p : lds_state.subscribed_resources) {
-    const std::string& listener_name = p.first;
-    if (lds_update_map.find(listener_name) == lds_update_map.end()) {
-      ListenerState& listener_state =
-          xds_client()->listener_map_[listener_name];
-      // If the resource was newly requested but has not yet been received,
-      // we don't want to generate an error for the watchers, because this LDS
-      // response may be in reaction to an earlier request that did not yet
-      // request the new resource, so its absence from the response does not
-      // necessarily indicate that the resource does not exist.
-      // For that case, we rely on the request timeout instead.
-      if (!listener_state.update.has_value()) continue;
-      listener_state.update.reset();
-      for (const auto& p : listener_state.watchers) {
-        p.first->OnResourceDoesNotExist();
+  for (const auto& a : lds_state.subscribed_resources) {
+    const std::string& authority_name = a.first;
+    for (const auto& p : a.second) {
+      const std::string& listener_name = p.first;
+      if (lds_update_map.find({authority_name, listener_name}) ==
+          lds_update_map.end()) {
+        ListenerState& listener_state =
+            xds_client()
+                ->authority_state_map_[authority_name]
+                .listener_map[listener_name];
+        // If the resource was newly requested but has not yet been received,
+        // we don't want to generate an error for the watchers, because this LDS
+        // response may be in reaction to an earlier request that did not yet
+        // request the new resource, so its absence from the response does not
+        // necessarily indicate that the resource does not exist.
+        // For that case, we rely on the request timeout instead.
+        if (!listener_state.update.has_value()) continue;
+        listener_state.update.reset();
+        for (const auto& p : listener_state.watchers) {
+          p.first->OnResourceDoesNotExist();
+        }
       }
     }
   }
@@ -990,15 +1051,21 @@ void XdsClient::ChannelState::AdsCallState::AcceptLdsUpdateLocked(
   // resources, remove it from the cache and notify watchers that it
   // does not exist.
   auto& rds_state = state_map_[XdsApi::kRdsTypeUrl];
-  for (const auto& p : rds_state.subscribed_resources) {
-    const std::string& rds_resource_name = p.first;
-    if (rds_resource_names_seen.find(rds_resource_name) ==
-        rds_resource_names_seen.end()) {
-      RouteConfigState& route_config_state =
-          xds_client()->route_config_map_[rds_resource_name];
-      route_config_state.update.reset();
-      for (const auto& p : route_config_state.watchers) {
-        p.first->OnResourceDoesNotExist();
+  for (const auto& a : rds_state.subscribed_resources) {
+    const std::string& authority_name = a.first;
+    for (const auto& p : a.second) {
+      const std::string& listener_name = p.first;
+      if (rds_resource_names_seen.find(XdsApi::ConstructFullResourceName(
+              authority_name, XdsApi::kRdsTypeUrl, listener_name)) ==
+          rds_resource_names_seen.end()) {
+        RouteConfigState& route_config_state =
+            xds_client()
+                ->authority_state_map_[authority_name]
+                .route_config_map[listener_name];
+        route_config_state.update.reset();
+        for (const auto& p : route_config_state.watchers) {
+          p.first->OnResourceDoesNotExist();
+        }
       }
     }
   }
@@ -1015,16 +1082,19 @@ void XdsClient::ChannelState::AdsCallState::AcceptRdsUpdateLocked(
   }
   auto& rds_state = state_map_[XdsApi::kRdsTypeUrl];
   for (auto& p : rds_update_map) {
-    const std::string& route_config_name = p.first;
+    const XdsApi::ResourceName& resource = p.first;
     XdsApi::RdsUpdate& rds_update = p.second.resource;
-    auto& state = rds_state.subscribed_resources[route_config_name];
+    auto& state =
+        rds_state.subscribed_resources[resource.authority][resource.id];
     if (state != nullptr) state->Finish();
     if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
       gpr_log(GPR_INFO, "[xds_client %p] RDS resource:\n%s", xds_client(),
               rds_update.ToString().c_str());
     }
     RouteConfigState& route_config_state =
-        xds_client()->route_config_map_[route_config_name];
+        xds_client()
+            ->authority_state_map_[resource.authority]
+            .route_config_map[resource.id];
     // Ignore identical update.
     if (route_config_state.update.has_value() &&
         *route_config_state.update == rds_update) {
@@ -1049,7 +1119,7 @@ void XdsClient::ChannelState::AdsCallState::AcceptRdsUpdateLocked(
 void XdsClient::ChannelState::AdsCallState::AcceptCdsUpdateLocked(
     std::string version, grpc_millis update_time,
     XdsApi::CdsUpdateMap cds_update_map,
-    const std::set<std::string>& resource_names_failed) {
+    const std::set<XdsApi::ResourceName>& resource_names_failed) {
   if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
     gpr_log(GPR_INFO,
             "[xds_client %p] CDS update received containing %" PRIuPTR
@@ -1059,20 +1129,28 @@ void XdsClient::ChannelState::AdsCallState::AcceptCdsUpdateLocked(
   auto& cds_state = state_map_[XdsApi::kCdsTypeUrl];
   std::set<std::string> eds_resource_names_seen;
   for (auto& p : cds_update_map) {
-    const char* cluster_name = p.first.c_str();
+    const XdsApi::ResourceName& resource = p.first;
     XdsApi::CdsUpdate& cds_update = p.second.resource;
-    auto& state = cds_state.subscribed_resources[cluster_name];
+    auto& state =
+        cds_state.subscribed_resources[resource.authority][resource.id];
     if (state != nullptr) state->Finish();
     if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
       gpr_log(GPR_INFO, "[xds_client %p] cluster=%s: %s", xds_client(),
-              cluster_name, cds_update.ToString().c_str());
+              XdsApi::ConstructFullResourceName(
+                  resource.authority, XdsApi::kCdsTypeUrl, resource.id)
+                  .c_str(),
+              cds_update.ToString().c_str());
     }
     // Record the EDS resource names seen.
-    eds_resource_names_seen.insert(cds_update.eds_service_name.empty()
-                                       ? cluster_name
-                                       : cds_update.eds_service_name);
+    eds_resource_names_seen.insert(
+        cds_update.eds_service_name.empty()
+            ? XdsApi::ConstructFullResourceName(
+                  resource.authority, XdsApi::kCdsTypeUrl, resource.id)
+            : cds_update.eds_service_name);
+    ClusterState& cluster_state = xds_client()
+                                      ->authority_state_map_[resource.authority]
+                                      .cluster_map[resource.id];
     // Ignore identical update.
-    ClusterState& cluster_state = xds_client()->cluster_map_[cluster_name];
     if (cluster_state.update.has_value() &&
         *cluster_state.update == cds_update) {
       if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
@@ -1094,33 +1172,43 @@ void XdsClient::ChannelState::AdsCallState::AcceptCdsUpdateLocked(
   // For invalid resources in the update, if they are already in the
   // cache, pretend that they are present in the update, so that we
   // don't incorrectly consider them deleted below.
-  for (const std::string& cluster_name : resource_names_failed) {
-    auto it = xds_client()->cluster_map_.find(cluster_name);
-    if (it != xds_client()->cluster_map_.end()) {
-      auto& resource = it->second.update;
-      if (!resource.has_value()) continue;
-      cds_update_map[cluster_name];
-      eds_resource_names_seen.insert(resource->eds_service_name.empty()
-                                         ? cluster_name
-                                         : resource->eds_service_name);
+  for (const auto& resource : resource_names_failed) {
+    auto& cluster_map =
+        xds_client()->authority_state_map_[resource.authority].cluster_map;
+    auto it = cluster_map.find(resource.id);
+    if (it != cluster_map.end()) {
+      auto& update = it->second.update;
+      if (!update.has_value()) continue;
+      cds_update_map[resource];
+      eds_resource_names_seen.insert(
+          update->eds_service_name.empty()
+              ? XdsApi::ConstructFullResourceName(
+                    resource.authority, XdsApi::kCdsTypeUrl, resource.id)
+              : update->eds_service_name);
     }
   }
   // For any subscribed resource that is not present in the update,
   // remove it from the cache and notify watchers that it does not exist.
-  for (const auto& p : cds_state.subscribed_resources) {
-    const std::string& cluster_name = p.first;
-    if (cds_update_map.find(cluster_name) == cds_update_map.end()) {
-      ClusterState& cluster_state = xds_client()->cluster_map_[cluster_name];
-      // If the resource was newly requested but has not yet been received,
-      // we don't want to generate an error for the watchers, because this CDS
-      // response may be in reaction to an earlier request that did not yet
-      // request the new resource, so its absence from the response does not
-      // necessarily indicate that the resource does not exist.
-      // For that case, we rely on the request timeout instead.
-      if (!cluster_state.update.has_value()) continue;
-      cluster_state.update.reset();
-      for (const auto& p : cluster_state.watchers) {
-        p.first->OnResourceDoesNotExist();
+  for (const auto& a : cds_state.subscribed_resources) {
+    const std::string& authority = a.first;
+    for (const auto& p : a.second) {
+      const std::string& cluster_name = p.first;
+      if (cds_update_map.find({authority, cluster_name}) ==
+          cds_update_map.end()) {
+        ClusterState& cluster_state = xds_client()
+                                          ->authority_state_map_[authority]
+                                          .cluster_map[cluster_name];
+        // If the resource was newly requested but has not yet been received,
+        // we don't want to generate an error for the watchers, because this CDS
+        // response may be in reaction to an earlier request that did not yet
+        // request the new resource, so its absence from the response does not
+        // necessarily indicate that the resource does not exist.
+        // For that case, we rely on the request timeout instead.
+        if (!cluster_state.update.has_value()) continue;
+        cluster_state.update.reset();
+        for (const auto& p : cluster_state.watchers) {
+          p.first->OnResourceDoesNotExist();
+        }
       }
     }
   }
@@ -1128,15 +1216,20 @@ void XdsClient::ChannelState::AdsCallState::AcceptCdsUpdateLocked(
   // resources, remove it from the cache and notify watchers that it
   // does not exist.
   auto& eds_state = state_map_[XdsApi::kEdsTypeUrl];
-  for (const auto& p : eds_state.subscribed_resources) {
-    const std::string& eds_resource_name = p.first;
-    if (eds_resource_names_seen.find(eds_resource_name) ==
-        eds_resource_names_seen.end()) {
-      EndpointState& endpoint_state =
-          xds_client()->endpoint_map_[eds_resource_name];
-      endpoint_state.update.reset();
-      for (const auto& p : endpoint_state.watchers) {
-        p.first->OnResourceDoesNotExist();
+  for (const auto& a : eds_state.subscribed_resources) {
+    const std::string& authority = a.first;
+    for (const auto& p : a.second) {
+      const std::string& eds_resource_name = p.first;
+      if (eds_resource_names_seen.find(XdsApi::ConstructFullResourceName(
+              authority, XdsApi::kEdsTypeUrl, eds_resource_name)) ==
+          eds_resource_names_seen.end()) {
+        EndpointState& endpoint_state = xds_client()
+                                            ->authority_state_map_[authority]
+                                            .endpoint_map[eds_resource_name];
+        endpoint_state.update.reset();
+        for (const auto& p : endpoint_state.watchers) {
+          p.first->OnResourceDoesNotExist();
+        }
       }
     }
   }
@@ -1153,16 +1246,22 @@ void XdsClient::ChannelState::AdsCallState::AcceptEdsUpdateLocked(
   }
   auto& eds_state = state_map_[XdsApi::kEdsTypeUrl];
   for (auto& p : eds_update_map) {
-    const char* eds_service_name = p.first.c_str();
+    const XdsApi::ResourceName& resource = p.first;
     XdsApi::EdsUpdate& eds_update = p.second.resource;
-    auto& state = eds_state.subscribed_resources[eds_service_name];
+    auto& state =
+        eds_state.subscribed_resources[resource.authority][resource.id];
     if (state != nullptr) state->Finish();
     if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
       gpr_log(GPR_INFO, "[xds_client %p] EDS resource %s: %s", xds_client(),
-              eds_service_name, eds_update.ToString().c_str());
+              XdsApi::ConstructFullResourceName(
+                  resource.authority, XdsApi::kCdsTypeUrl, resource.id)
+                  .c_str(),
+              eds_update.ToString().c_str());
     }
     EndpointState& endpoint_state =
-        xds_client()->endpoint_map_[eds_service_name];
+        xds_client()
+            ->authority_state_map_[resource.authority]
+            .endpoint_map[resource.id];
     // Ignore identical update.
     if (endpoint_state.update.has_value() &&
         *endpoint_state.update == eds_update) {
@@ -1200,9 +1299,22 @@ void UpdateResourceMetadataNacked(const std::string& version,
 }  // namespace
 
 template <typename StateMap>
-void XdsClient::ChannelState::AdsCallState::RejectAdsUpdateLocked(
-    grpc_millis update_time, const XdsApi::AdsParseResult& result,
+void XdsClient::ChannelState::AdsCallState::RejectAdsUpdateHelperLocked(
+    const std::string& resource_name, grpc_millis update_time,
+    const XdsApi::AdsParseResult& result, const std::string& error_details,
     StateMap* state_map) {
+  auto it = state_map->find(resource_name);
+  if (it == state_map->end()) return;
+  auto& state = it->second;
+  for (const auto& p : state.watchers) {
+    p.first->OnError(GRPC_ERROR_REF(result.parse_error));
+  }
+  UpdateResourceMetadataNacked(result.version, error_details, update_time,
+                               &state.meta);
+}
+
+void XdsClient::ChannelState::AdsCallState::RejectAdsUpdateLocked(
+    grpc_millis update_time, const XdsApi::AdsParseResult& result) {
   if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
     gpr_log(GPR_INFO,
             "[xds_client %p] %s update NACKed containing %" PRIuPTR
@@ -1211,17 +1323,26 @@ void XdsClient::ChannelState::AdsCallState::RejectAdsUpdateLocked(
             result.resource_names_failed.size());
   }
   std::string details = grpc_error_std_string(result.parse_error);
-  for (auto& name : result.resource_names_failed) {
-    auto it = state_map->find(name);
-    if (it == state_map->end()) continue;
-    auto& state = it->second;
-    // Notify watchers of error.
-    for (const auto& p : state.watchers) {
-      p.first->OnError(GRPC_ERROR_REF(result.parse_error));
+  for (auto& resource : result.resource_names_failed) {
+    auto authority_it =
+        xds_client()->authority_state_map_.find(resource.authority);
+    if (authority_it == xds_client()->authority_state_map_.end()) continue;
+    AuthorityState& authority_state = authority_it->second;
+    if (result.type_url == XdsApi::kLdsTypeUrl) {
+      RejectAdsUpdateHelperLocked(resource.id, update_time, result, details,
+                                  &authority_state.listener_map);
+    } else if (result.type_url == XdsApi::kRdsTypeUrl) {
+      RejectAdsUpdateHelperLocked(resource.id, update_time, result, details,
+                                  &authority_state.route_config_map);
+    } else if (result.type_url == XdsApi::kCdsTypeUrl) {
+      RejectAdsUpdateHelperLocked(resource.id, update_time, result, details,
+                                  &authority_state.cluster_map);
+    } else if (result.type_url == XdsApi::kEdsTypeUrl) {
+      RejectAdsUpdateHelperLocked(resource.id, update_time, result, details,
+                                  &authority_state.endpoint_map);
+    } else {
+      GPR_ASSERT(0);
     }
-    // Update resource metadata for CSDS.
-    UpdateResourceMetadataNacked(result.version, details, update_time,
-                                 &state.meta);
   }
 }
 
@@ -1314,18 +1435,7 @@ bool XdsClient::ChannelState::AdsCallState::OnResponseReceivedLocked() {
                              GRPC_STATUS_UNAVAILABLE);
       GRPC_ERROR_UNREF(state.error);
       state.error = result.parse_error;
-      if (result.type_url == XdsApi::kLdsTypeUrl) {
-        RejectAdsUpdateLocked(update_time, result,
-                              &xds_client()->listener_map_);
-      } else if (result.type_url == XdsApi::kRdsTypeUrl) {
-        RejectAdsUpdateLocked(update_time, result,
-                              &xds_client()->route_config_map_);
-      } else if (result.type_url == XdsApi::kCdsTypeUrl) {
-        RejectAdsUpdateLocked(update_time, result, &xds_client()->cluster_map_);
-      } else if (result.type_url == XdsApi::kEdsTypeUrl) {
-        RejectAdsUpdateLocked(update_time, result,
-                              &xds_client()->endpoint_map_);
-      }
+      RejectAdsUpdateLocked(update_time, result);
     }
     // Process any valid resources.
     bool have_valid_resources = false;
@@ -1350,8 +1460,7 @@ bool XdsClient::ChannelState::AdsCallState::OnResponseReceivedLocked() {
     }
     if (have_valid_resources) {
       seen_response_ = true;
-      xds_client()->resource_version_map_[result.type_url] =
-          std::move(result.version);
+      chand()->resource_type_version_map_[result.type_url] = result.version;
       // Start load reporting if needed.
       auto& lrs_call = chand()->lrs_calld_;
       if (lrs_call != nullptr) {
@@ -1417,19 +1526,23 @@ bool XdsClient::ChannelState::AdsCallState::IsCurrentCallOnChannel() const {
   return this == chand()->ads_calld_->calld();
 }
 
-std::set<absl::string_view>
+std::map<absl::string_view /*authority*/, std::set<absl::string_view /*name*/>>
 XdsClient::ChannelState::AdsCallState::ResourceNamesForRequest(
     const std::string& type_url) {
-  std::set<absl::string_view> resource_names;
+  std::map<absl::string_view /*authority*/,
+           std::set<absl::string_view /*name*/>>
+      resource_map;
   auto it = state_map_.find(type_url);
   if (it != state_map_.end()) {
-    for (auto& p : it->second.subscribed_resources) {
-      resource_names.insert(p.first);
-      OrphanablePtr<ResourceState>& state = p.second;
-      state->Start(Ref(DEBUG_LOCATION, "ResourceState"));
+    for (auto& a : it->second.subscribed_resources) {
+      for (auto& p : a.second) {
+        resource_map[a.first].insert(p.first);
+        OrphanablePtr<ResourceState>& state = p.second;
+        state->Start(Ref(DEBUG_LOCATION, "ResourceState"));
+      }
     }
   }
-  return resource_names;
+  return resource_map;
 }
 
 //
@@ -1878,12 +1991,10 @@ grpc_millis GetRequestTimeout(const grpc_channel_args* args) {
 }
 
 grpc_channel_args* ModifyChannelArgs(const grpc_channel_args* args) {
-  absl::InlinedVector<grpc_arg, 2> args_to_add = {
+  absl::InlinedVector<grpc_arg, 1> args_to_add = {
       grpc_channel_arg_integer_create(
           const_cast<char*>(GRPC_ARG_KEEPALIVE_TIME_MS),
           5 * 60 * GPR_MS_PER_SEC),
-      grpc_channel_arg_integer_create(
-          const_cast<char*>(GRPC_ARG_CHANNELZ_IS_INTERNAL_CHANNEL), 1),
   };
   return grpc_channel_args_copy_and_add(args, args_to_add.data(),
                                         args_to_add.size());
@@ -1907,9 +2018,9 @@ XdsClient::XdsClient(std::unique_ptr<XdsBootstrap> bootstrap,
   if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
     gpr_log(GPR_INFO, "[xds_client %p] creating xds client", this);
   }
-  // Create ChannelState object.
-  chand_ = MakeOrphanable<ChannelState>(
-      WeakRef(DEBUG_LOCATION, "XdsClient+ChannelState"), bootstrap_->server());
+  // Calling grpc_init to ensure gRPC does not shut down until the XdsClient is
+  // destroyed.
+  grpc_init();
 }
 
 XdsClient::~XdsClient() {
@@ -1918,26 +2029,9 @@ XdsClient::~XdsClient() {
   }
   grpc_channel_args_destroy(args_);
   grpc_pollset_set_destroy(interested_parties_);
-}
-
-void XdsClient::AddChannelzLinkage(
-    channelz::ChannelNode* parent_channelz_node) {
-  MutexLock lock(&mu_);
-  channelz::ChannelNode* xds_channelz_node =
-      grpc_channel_get_channelz_node(chand_->channel());
-  if (xds_channelz_node != nullptr) {
-    parent_channelz_node->AddChildChannel(xds_channelz_node->uuid());
-  }
-}
-
-void XdsClient::RemoveChannelzLinkage(
-    channelz::ChannelNode* parent_channelz_node) {
-  MutexLock lock(&mu_);
-  channelz::ChannelNode* xds_channelz_node =
-      grpc_channel_get_channelz_node(chand_->channel());
-  if (xds_channelz_node != nullptr) {
-    parent_channelz_node->RemoveChildChannel(xds_channelz_node->uuid());
-  }
+  // Calling grpc_shutdown to ensure gRPC does not shut down until the XdsClient
+  // is destroyed.
+  grpc_shutdown();
 }
 
 void XdsClient::Orphan() {
@@ -1951,28 +2045,56 @@ void XdsClient::Orphan() {
   {
     MutexLock lock(&mu_);
     shutting_down_ = true;
-    // Orphan ChannelState object.
-    chand_.reset();
     // We do not clear cluster_map_ and endpoint_map_ if the xds client was
     // created by the XdsResolver because the maps contain refs for watchers
     // which in turn hold refs to the loadbalancing policies. At this point, it
     // is possible for ADS calls to be in progress. Unreffing the loadbalancing
     // policies before those calls are done would lead to issues such as
     // https://github.com/grpc/grpc/issues/20928.
-    if (!listener_map_.empty()) {
-      cluster_map_.clear();
-      endpoint_map_.clear();
+    for (auto& a : authority_state_map_) {
+      a.second.channel_state.reset();
+      if (!a.second.listener_map.empty()) {
+        a.second.cluster_map.clear();
+        a.second.endpoint_map.clear();
+      }
     }
+    // We clear these invalid resource  watchers as cancel never came.
+    invalid_listener_watchers_.clear();
+    invalid_route_config_watchers_.clear();
+    invalid_cluster_watchers_.clear();
+    invalid_endpoint_watchers_.clear();
   }
 }
 
+RefCountedPtr<XdsClient::ChannelState> XdsClient::GetOrCreateChannelStateLocked(
+    const XdsBootstrap::XdsServer& server) {
+  auto it = xds_server_channel_map_.find(server);
+  if (it != xds_server_channel_map_.end()) {
+    return it->second->Ref(DEBUG_LOCATION, "Authority");
+  }
+  // Channel not found, so create a new one.
+  auto channel_state = MakeRefCounted<ChannelState>(
+      WeakRef(DEBUG_LOCATION, "ChannelState"), server);
+  xds_server_channel_map_[server] = channel_state.get();
+  return channel_state;
+}
+
 void XdsClient::WatchListenerData(
     absl::string_view listener_name,
     std::unique_ptr<ListenerWatcherInterface> watcher) {
   std::string listener_name_str = std::string(listener_name);
   MutexLock lock(&mu_);
-  ListenerState& listener_state = listener_map_[listener_name_str];
   ListenerWatcherInterface* w = watcher.get();
+  auto resource = XdsApi::ParseResourceName(listener_name, XdsApi::IsLds);
+  if (!resource.ok()) {
+    invalid_listener_watchers_[w] = std::move(watcher);
+    grpc_error_handle error = GRPC_ERROR_CREATE_FROM_CPP_STRING(absl::StrFormat(
+        "Unable to parse resource name for listener %s", listener_name));
+    w->OnError(GRPC_ERROR_REF(error));
+    return;
+  }
+  AuthorityState& authority_state = authority_state_map_[resource->authority];
+  ListenerState& listener_state = authority_state.listener_map[resource->id];
   listener_state.watchers[w] = std::move(watcher);
   // If we've already received an LDS update, notify the new watcher
   // immediately.
@@ -1983,7 +2105,13 @@ void XdsClient::WatchListenerData(
     }
     w->OnListenerChanged(*listener_state.update);
   }
-  chand_->SubscribeLocked(XdsApi::kLdsTypeUrl, listener_name_str);
+  // If the authority doesn't yet have a channel, set it, creating it if needed.
+  if (authority_state.channel_state == nullptr) {
+    authority_state.channel_state =
+        GetOrCreateChannelStateLocked(bootstrap_->server());
+  }
+  authority_state.channel_state->SubscribeLocked(XdsApi::kLdsTypeUrl,
+                                                 *resource);
 }
 
 void XdsClient::CancelListenerDataWatch(absl::string_view listener_name,
@@ -1991,16 +2119,22 @@ void XdsClient::CancelListenerDataWatch(absl::string_view listener_name,
                                         bool delay_unsubscription) {
   MutexLock lock(&mu_);
   if (shutting_down_) return;
-  std::string listener_name_str = std::string(listener_name);
-  ListenerState& listener_state = listener_map_[listener_name_str];
+  auto resource = XdsApi::ParseResourceName(listener_name, XdsApi::IsLds);
+  if (!resource.ok()) return;
+  auto& authority_state = authority_state_map_[resource->authority];
+  ListenerState& listener_state = authority_state.listener_map[resource->id];
   auto it = listener_state.watchers.find(watcher);
-  if (it != listener_state.watchers.end()) {
-    listener_state.watchers.erase(it);
-    if (listener_state.watchers.empty()) {
-      listener_map_.erase(listener_name_str);
-      chand_->UnsubscribeLocked(XdsApi::kLdsTypeUrl, listener_name_str,
-                                delay_unsubscription);
-    }
+  if (it == listener_state.watchers.end()) {
+    invalid_listener_watchers_.erase(watcher);
+    return;
+  }
+  listener_state.watchers.erase(it);
+  if (!listener_state.watchers.empty()) return;
+  authority_state.listener_map.erase(resource->id);
+  xds_server_channel_map_[bootstrap_->server()]->UnsubscribeLocked(
+      XdsApi::kLdsTypeUrl, *resource, delay_unsubscription);
+  if (!authority_state.HasSubscribedResources()) {
+    authority_state.channel_state.reset();
   }
 }
 
@@ -2009,9 +2143,19 @@ void XdsClient::WatchRouteConfigData(
     std::unique_ptr<RouteConfigWatcherInterface> watcher) {
   std::string route_config_name_str = std::string(route_config_name);
   MutexLock lock(&mu_);
-  RouteConfigState& route_config_state =
-      route_config_map_[route_config_name_str];
   RouteConfigWatcherInterface* w = watcher.get();
+  auto resource = XdsApi::ParseResourceName(route_config_name, XdsApi::IsRds);
+  if (!resource.ok()) {
+    invalid_route_config_watchers_[w] = std::move(watcher);
+    grpc_error_handle error = GRPC_ERROR_CREATE_FROM_CPP_STRING(
+        absl::StrFormat("Unable to parse resource name for route config %s",
+                        route_config_name));
+    w->OnError(GRPC_ERROR_REF(error));
+    return;
+  }
+  auto& authority_state = authority_state_map_[resource->authority];
+  RouteConfigState& route_config_state =
+      authority_state.route_config_map[resource->id];
   route_config_state.watchers[w] = std::move(watcher);
   // If we've already received an RDS update, notify the new watcher
   // immediately.
@@ -2023,7 +2167,13 @@ void XdsClient::WatchRouteConfigData(
     }
     w->OnRouteConfigChanged(*route_config_state.update);
   }
-  chand_->SubscribeLocked(XdsApi::kRdsTypeUrl, route_config_name_str);
+  // If the authority doesn't yet have a channel, set it, creating it if needed.
+  if (authority_state.channel_state == nullptr) {
+    authority_state.channel_state =
+        GetOrCreateChannelStateLocked(bootstrap_->server());
+  }
+  authority_state.channel_state->SubscribeLocked(XdsApi::kRdsTypeUrl,
+                                                 *resource);
 }
 
 void XdsClient::CancelRouteConfigDataWatch(absl::string_view route_config_name,
@@ -2031,17 +2181,23 @@ void XdsClient::CancelRouteConfigDataWatch(absl::string_view route_config_name,
                                            bool delay_unsubscription) {
   MutexLock lock(&mu_);
   if (shutting_down_) return;
-  std::string route_config_name_str = std::string(route_config_name);
+  auto resource = XdsApi::ParseResourceName(route_config_name, XdsApi::IsRds);
+  if (!resource.ok()) return;
+  auto& authority_state = authority_state_map_[resource->authority];
   RouteConfigState& route_config_state =
-      route_config_map_[route_config_name_str];
+      authority_state.route_config_map[resource->id];
   auto it = route_config_state.watchers.find(watcher);
-  if (it != route_config_state.watchers.end()) {
-    route_config_state.watchers.erase(it);
-    if (route_config_state.watchers.empty()) {
-      route_config_map_.erase(route_config_name_str);
-      chand_->UnsubscribeLocked(XdsApi::kRdsTypeUrl, route_config_name_str,
-                                delay_unsubscription);
-    }
+  if (it == route_config_state.watchers.end()) {
+    invalid_route_config_watchers_.erase(watcher);
+    return;
+  }
+  route_config_state.watchers.erase(it);
+  if (!route_config_state.watchers.empty()) return;
+  authority_state.route_config_map.erase(resource->id);
+  xds_server_channel_map_[bootstrap_->server()]->UnsubscribeLocked(
+      XdsApi::kRdsTypeUrl, *resource, delay_unsubscription);
+  if (!authority_state.HasSubscribedResources()) {
+    authority_state.channel_state.reset();
   }
 }
 
@@ -2050,8 +2206,17 @@ void XdsClient::WatchClusterData(
     std::unique_ptr<ClusterWatcherInterface> watcher) {
   std::string cluster_name_str = std::string(cluster_name);
   MutexLock lock(&mu_);
-  ClusterState& cluster_state = cluster_map_[cluster_name_str];
   ClusterWatcherInterface* w = watcher.get();
+  auto resource = XdsApi::ParseResourceName(cluster_name, XdsApi::IsCds);
+  if (!resource.ok()) {
+    invalid_cluster_watchers_[w] = std::move(watcher);
+    grpc_error_handle error = GRPC_ERROR_CREATE_FROM_CPP_STRING(absl::StrFormat(
+        "Unable to parse resource name for cluster %s", cluster_name));
+    w->OnError(GRPC_ERROR_REF(error));
+    return;
+  }
+  auto& authority_state = authority_state_map_[resource->authority];
+  ClusterState& cluster_state = authority_state.cluster_map[resource->id];
   cluster_state.watchers[w] = std::move(watcher);
   // If we've already received a CDS update, notify the new watcher
   // immediately.
@@ -2062,7 +2227,13 @@ void XdsClient::WatchClusterData(
     }
     w->OnClusterChanged(cluster_state.update.value());
   }
-  chand_->SubscribeLocked(XdsApi::kCdsTypeUrl, cluster_name_str);
+  // If the authority doesn't yet have a channel, set it, creating it if needed.
+  if (authority_state.channel_state == nullptr) {
+    authority_state.channel_state =
+        GetOrCreateChannelStateLocked(bootstrap_->server());
+  }
+  authority_state.channel_state->SubscribeLocked(XdsApi::kCdsTypeUrl,
+                                                 *resource);
 }
 
 void XdsClient::CancelClusterDataWatch(absl::string_view cluster_name,
@@ -2070,16 +2241,22 @@ void XdsClient::CancelClusterDataWatch(absl::string_view cluster_name,
                                        bool delay_unsubscription) {
   MutexLock lock(&mu_);
   if (shutting_down_) return;
-  std::string cluster_name_str = std::string(cluster_name);
-  ClusterState& cluster_state = cluster_map_[cluster_name_str];
+  auto resource = XdsApi::ParseResourceName(cluster_name, XdsApi::IsCds);
+  if (!resource.ok()) return;
+  auto& authority_state = authority_state_map_[resource->authority];
+  ClusterState& cluster_state = authority_state.cluster_map[resource->id];
   auto it = cluster_state.watchers.find(watcher);
-  if (it != cluster_state.watchers.end()) {
-    cluster_state.watchers.erase(it);
-    if (cluster_state.watchers.empty()) {
-      cluster_map_.erase(cluster_name_str);
-      chand_->UnsubscribeLocked(XdsApi::kCdsTypeUrl, cluster_name_str,
-                                delay_unsubscription);
-    }
+  if (it == cluster_state.watchers.end()) {
+    invalid_cluster_watchers_.erase(watcher);
+    return;
+  }
+  cluster_state.watchers.erase(it);
+  if (!cluster_state.watchers.empty()) return;
+  authority_state.cluster_map.erase(resource->id);
+  xds_server_channel_map_[bootstrap_->server()]->UnsubscribeLocked(
+      XdsApi::kCdsTypeUrl, *resource, delay_unsubscription);
+  if (!authority_state.HasSubscribedResources()) {
+    authority_state.channel_state.reset();
   }
 }
 
@@ -2088,8 +2265,18 @@ void XdsClient::WatchEndpointData(
     std::unique_ptr<EndpointWatcherInterface> watcher) {
   std::string eds_service_name_str = std::string(eds_service_name);
   MutexLock lock(&mu_);
-  EndpointState& endpoint_state = endpoint_map_[eds_service_name_str];
   EndpointWatcherInterface* w = watcher.get();
+  auto resource = XdsApi::ParseResourceName(eds_service_name, XdsApi::IsEds);
+  if (!resource.ok()) {
+    invalid_endpoint_watchers_[w] = std::move(watcher);
+    grpc_error_handle error = GRPC_ERROR_CREATE_FROM_CPP_STRING(
+        absl::StrFormat("Unable to parse resource name for endpoint service %s",
+                        eds_service_name));
+    w->OnError(GRPC_ERROR_REF(error));
+    return;
+  }
+  auto& authority_state = authority_state_map_[resource->authority];
+  EndpointState& endpoint_state = authority_state.endpoint_map[resource->id];
   endpoint_state.watchers[w] = std::move(watcher);
   // If we've already received an EDS update, notify the new watcher
   // immediately.
@@ -2100,7 +2287,13 @@ void XdsClient::WatchEndpointData(
     }
     w->OnEndpointChanged(endpoint_state.update.value());
   }
-  chand_->SubscribeLocked(XdsApi::kEdsTypeUrl, eds_service_name_str);
+  // If the authority doesn't yet have a channel, set it, creating it if needed.
+  if (authority_state.channel_state == nullptr) {
+    authority_state.channel_state =
+        GetOrCreateChannelStateLocked(bootstrap_->server());
+  }
+  authority_state.channel_state->SubscribeLocked(XdsApi::kEdsTypeUrl,
+                                                 *resource);
 }
 
 void XdsClient::CancelEndpointDataWatch(absl::string_view eds_service_name,
@@ -2108,16 +2301,22 @@ void XdsClient::CancelEndpointDataWatch(absl::string_view eds_service_name,
                                         bool delay_unsubscription) {
   MutexLock lock(&mu_);
   if (shutting_down_) return;
-  std::string eds_service_name_str = std::string(eds_service_name);
-  EndpointState& endpoint_state = endpoint_map_[eds_service_name_str];
+  auto resource = XdsApi::ParseResourceName(eds_service_name, XdsApi::IsEds);
+  if (!resource.ok()) return;
+  auto& authority_state = authority_state_map_[resource->authority];
+  EndpointState& endpoint_state = authority_state.endpoint_map[resource->id];
   auto it = endpoint_state.watchers.find(watcher);
-  if (it != endpoint_state.watchers.end()) {
-    endpoint_state.watchers.erase(it);
-    if (endpoint_state.watchers.empty()) {
-      endpoint_map_.erase(eds_service_name_str);
-      chand_->UnsubscribeLocked(XdsApi::kEdsTypeUrl, eds_service_name_str,
-                                delay_unsubscription);
-    }
+  if (it == endpoint_state.watchers.end()) {
+    invalid_endpoint_watchers_.erase(watcher);
+    return;
+  }
+  endpoint_state.watchers.erase(it);
+  if (!endpoint_state.watchers.empty()) return;
+  authority_state.endpoint_map.erase(resource->id);
+  xds_server_channel_map_[bootstrap_->server()]->UnsubscribeLocked(
+      XdsApi::kEdsTypeUrl, *resource, delay_unsubscription);
+  if (!authority_state.HasSubscribedResources()) {
+    authority_state.channel_state.reset();
   }
 }
 
@@ -2151,7 +2350,12 @@ RefCountedPtr<XdsClusterDropStats> XdsClient::AddClusterDropStats(
         it->first.second /*eds_service_name*/);
     load_report_state.drop_stats = cluster_drop_stats.get();
   }
-  chand_->MaybeStartLrsCall();
+  auto resource = XdsApi::ParseResourceName(cluster_name, XdsApi::IsCds);
+  GPR_ASSERT(resource.ok());
+  auto a = authority_state_map_.find(resource->authority);
+  if (a != authority_state_map_.end()) {
+    a->second.channel_state->MaybeStartLrsCall();
+  }
   return cluster_drop_stats;
 }
 
@@ -2208,7 +2412,12 @@ RefCountedPtr<XdsClusterLocalityStats> XdsClient::AddClusterLocalityStats(
         std::move(locality));
     locality_state.locality_stats = cluster_locality_stats.get();
   }
-  chand_->MaybeStartLrsCall();
+  auto resource = XdsApi::ParseResourceName(cluster_name, XdsApi::IsCds);
+  GPR_ASSERT(resource.ok());
+  auto a = authority_state_map_.find(resource->authority);
+  if (a != authority_state_map_.end()) {
+    a->second.channel_state->MaybeStartLrsCall();
+  }
   return cluster_locality_stats;
 }
 
@@ -2238,34 +2447,36 @@ void XdsClient::RemoveClusterLocalityStats(
 
 void XdsClient::ResetBackoff() {
   MutexLock lock(&mu_);
-  if (chand_ != nullptr) {
-    grpc_channel_reset_connect_backoff(chand_->channel());
+  for (auto& p : xds_server_channel_map_) {
+    grpc_channel_reset_connect_backoff(p.second->channel());
   }
 }
 
 void XdsClient::NotifyOnErrorLocked(grpc_error_handle error) {
-  for (const auto& p : listener_map_) {
-    const ListenerState& listener_state = p.second;
-    for (const auto& p : listener_state.watchers) {
-      p.first->OnError(GRPC_ERROR_REF(error));
+  for (const auto& a : authority_state_map_) {
+    for (const auto& p : a.second.listener_map) {
+      const ListenerState& listener_state = p.second;
+      for (const auto& p : listener_state.watchers) {
+        p.first->OnError(GRPC_ERROR_REF(error));
+      }
     }
-  }
-  for (const auto& p : route_config_map_) {
-    const RouteConfigState& route_config_state = p.second;
-    for (const auto& p : route_config_state.watchers) {
-      p.first->OnError(GRPC_ERROR_REF(error));
+    for (const auto& p : a.second.route_config_map) {
+      const RouteConfigState& route_config_state = p.second;
+      for (const auto& p : route_config_state.watchers) {
+        p.first->OnError(GRPC_ERROR_REF(error));
+      }
     }
-  }
-  for (const auto& p : cluster_map_) {
-    const ClusterState& cluster_state = p.second;
-    for (const auto& p : cluster_state.watchers) {
-      p.first->OnError(GRPC_ERROR_REF(error));
+    for (const auto& p : a.second.cluster_map) {
+      const ClusterState& cluster_state = p.second;
+      for (const auto& p : cluster_state.watchers) {
+        p.first->OnError(GRPC_ERROR_REF(error));
+      }
     }
-  }
-  for (const auto& p : endpoint_map_) {
-    const EndpointState& endpoint_state = p.second;
-    for (const auto& p : endpoint_state.watchers) {
-      p.first->OnError(GRPC_ERROR_REF(error));
+    for (const auto& p : a.second.endpoint_map) {
+      const EndpointState& endpoint_state = p.second;
+      for (const auto& p : endpoint_state.watchers) {
+        p.first->OnError(GRPC_ERROR_REF(error));
+      }
     }
   }
   GRPC_ERROR_UNREF(error);
@@ -2355,34 +2566,36 @@ XdsApi::ClusterLoadReportMap XdsClient::BuildLoadReportSnapshotLocked(
 std::string XdsClient::DumpClientConfigBinary() {
   MutexLock lock(&mu_);
   XdsApi::ResourceTypeMetadataMap resource_type_metadata_map;
-  // Update per-xds-type version if available, this version corresponding to the
-  // last successful ADS update version.
-  for (auto& p : resource_version_map_) {
-    resource_type_metadata_map[p.first].version = p.second;
-  }
-  // Collect resource metadata from listeners
-  auto& lds_map =
-      resource_type_metadata_map[XdsApi::kLdsTypeUrl].resource_metadata_map;
-  for (auto& p : listener_map_) {
-    lds_map[p.first] = &p.second.meta;
-  }
-  // Collect resource metadata from route configs
-  auto& rds_map =
-      resource_type_metadata_map[XdsApi::kRdsTypeUrl].resource_metadata_map;
-  for (auto& p : route_config_map_) {
-    rds_map[p.first] = &p.second.meta;
-  }
-  // Collect resource metadata from clusters
-  auto& cds_map =
-      resource_type_metadata_map[XdsApi::kCdsTypeUrl].resource_metadata_map;
-  for (auto& p : cluster_map_) {
-    cds_map[p.first] = &p.second.meta;
-  }
-  // Collect resource metadata from endpoints
-  auto& eds_map =
-      resource_type_metadata_map[XdsApi::kEdsTypeUrl].resource_metadata_map;
-  for (auto& p : endpoint_map_) {
-    eds_map[p.first] = &p.second.meta;
+  auto& lds_map = resource_type_metadata_map[XdsApi::kLdsTypeUrl];
+  auto& rds_map = resource_type_metadata_map[XdsApi::kRdsTypeUrl];
+  auto& cds_map = resource_type_metadata_map[XdsApi::kCdsTypeUrl];
+  auto& eds_map = resource_type_metadata_map[XdsApi::kEdsTypeUrl];
+  for (auto& a : authority_state_map_) {
+    const std::string& authority = a.first;
+    // Collect resource metadata from listeners
+    for (auto& p : a.second.listener_map) {
+      const std::string& listener_name = p.first;
+      lds_map[XdsApi::ConstructFullResourceName(
+          authority, XdsApi::kLdsTypeUrl, listener_name)] = &p.second.meta;
+    }
+    // Collect resource metadata from route configs
+    for (auto& p : a.second.route_config_map) {
+      const std::string& route_config_name = p.first;
+      rds_map[XdsApi::ConstructFullResourceName(
+          authority, XdsApi::kRdsTypeUrl, route_config_name)] = &p.second.meta;
+    }
+    // Collect resource metadata from clusters
+    for (auto& p : a.second.cluster_map) {
+      const std::string& cluster_name = p.first;
+      cds_map[XdsApi::ConstructFullResourceName(authority, XdsApi::kCdsTypeUrl,
+                                                cluster_name)] = &p.second.meta;
+    }
+    // Collect resource metadata from endpoints
+    for (auto& p : a.second.endpoint_map) {
+      const std::string& endpoint_name = p.first;
+      eds_map[XdsApi::ConstructFullResourceName(
+          authority, XdsApi::kEdsTypeUrl, endpoint_name)] = &p.second.meta;
+    }
   }
   // Assemble config dump messages
   return api_.AssembleClientConfig(resource_type_metadata_map);
@@ -2540,7 +2753,7 @@ void XdsClientArgDestroy(void* p) {
   xds_client->Unref(DEBUG_LOCATION, "channel arg");
 }
 
-int XdsClientArgCmp(void* p, void* q) { return GPR_ICMP(p, q); }
+int XdsClientArgCmp(void* p, void* q) { return QsortCompare(p, q); }
 
 const grpc_arg_pointer_vtable kXdsClientArgVtable = {
     XdsClientArgCopy, XdsClientArgDestroy, XdsClientArgCmp};
index 27796f4..dfcee72 100644 (file)
@@ -102,18 +102,6 @@ class XdsClient : public DualRefCounted<XdsClient> {
 
   grpc_pollset_set* interested_parties() const { return interested_parties_; }
 
-  // TODO(roth): When we add federation, there will be multiple channels
-  // inside the XdsClient, and the set of channels may change over time,
-  // but not every channel may use every one of the child channels, so
-  // this API will need to change.  At minumum, we will need to hold a
-  // ref to the parent channelz node so that we can update its list of
-  // children as the set of xDS channels changes.  However, we may also
-  // want to make this a bit more selective such that only those
-  // channels on which a given parent channel is actually requesting
-  // resources will actually be marked as its children.
-  void AddChannelzLinkage(channelz::ChannelNode* parent_channelz_node);
-  void RemoveChannelzLinkage(channelz::ChannelNode* parent_channelz_node);
-
   void Orphan() override;
 
   // Start and cancel listener data watch for a listener.
@@ -210,12 +198,7 @@ class XdsClient : public DualRefCounted<XdsClient> {
  private:
   // Contains a channel to the xds server and all the data related to the
   // channel.  Holds a ref to the xds client object.
-  //
-  // Currently, there is only one ChannelState object per XdsClient
-  // object, and it has essentially the same lifetime.  But in the
-  // future, when we add federation support, a single XdsClient may have
-  // multiple underlying channels to talk to different xDS servers.
-  class ChannelState : public InternallyRefCounted<ChannelState> {
+  class ChannelState : public DualRefCounted<ChannelState> {
    public:
     template <typename T>
     class RetryableCall;
@@ -243,9 +226,11 @@ class XdsClient : public DualRefCounted<XdsClient> {
     void StartConnectivityWatchLocked();
     void CancelConnectivityWatchLocked();
 
-    void SubscribeLocked(const std::string& type_url, const std::string& name)
+    void SubscribeLocked(const std::string& type_url,
+                         const XdsApi::ResourceName& resource)
         ABSL_EXCLUSIVE_LOCKS_REQUIRED(&XdsClient::mu_);
-    void UnsubscribeLocked(const std::string& type_url, const std::string& name,
+    void UnsubscribeLocked(const std::string& type_url,
+                           const XdsApi::ResourceName& resource,
                            bool delay_unsubscription)
         ABSL_EXCLUSIVE_LOCKS_REQUIRED(&XdsClient::mu_);
 
@@ -260,11 +245,15 @@ class XdsClient : public DualRefCounted<XdsClient> {
     // The channel and its status.
     grpc_channel* channel_;
     bool shutting_down_ = false;
-    StateWatcher* watcher_ = nullptr;
+    StateWatcher* watcher_;
 
     // The retryable XDS calls.
     OrphanablePtr<RetryableCall<AdsCallState>> ads_calld_;
     OrphanablePtr<RetryableCall<LrsCallState>> lrs_calld_;
+
+    // Stores the most recent accepted resource version for each resource type.
+    std::map<std::string /*type*/, std::string /*version*/>
+        resource_type_version_map_;
   };
 
   struct ListenerState {
@@ -302,6 +291,20 @@ class XdsClient : public DualRefCounted<XdsClient> {
     XdsApi::ResourceMetadata meta;
   };
 
+  struct AuthorityState {
+    RefCountedPtr<ChannelState> channel_state;
+    std::map<std::string /*listener_name*/, ListenerState> listener_map;
+    std::map<std::string /*route_config_name*/, RouteConfigState>
+        route_config_map;
+    std::map<std::string /*cluster_name*/, ClusterState> cluster_map;
+    std::map<std::string /*eds_service_name*/, EndpointState> endpoint_map;
+
+    bool HasSubscribedResources() {
+      return !listener_map.empty() || !route_config_map.empty() ||
+             !cluster_map.empty() || !endpoint_map.empty();
+    }
+  };
+
   struct LoadReportState {
     struct LocalityState {
       XdsClusterLocalityStats* locality_stats = nullptr;
@@ -324,6 +327,9 @@ class XdsClient : public DualRefCounted<XdsClient> {
       bool send_all_clusters, const std::set<std::string>& clusters)
       ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
 
+  RefCountedPtr<ChannelState> GetOrCreateChannelStateLocked(
+      const XdsBootstrap::XdsServer& server) ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
+
   std::unique_ptr<XdsBootstrap> bootstrap_;
   grpc_channel_args* args_;
   const grpc_millis request_timeout_;
@@ -333,20 +339,11 @@ class XdsClient : public DualRefCounted<XdsClient> {
 
   Mutex mu_;
 
-  // The channel for communicating with the xds server.
-  OrphanablePtr<ChannelState> chand_ ABSL_GUARDED_BY(mu_);
-
-  // One entry for each watched LDS resource.
-  std::map<std::string /*listener_name*/, ListenerState> listener_map_
-      ABSL_GUARDED_BY(mu_);
-  // One entry for each watched RDS resource.
-  std::map<std::string /*route_config_name*/, RouteConfigState>
-      route_config_map_ ABSL_GUARDED_BY(mu_);
-  // One entry for each watched CDS resource.
-  std::map<std::string /*cluster_name*/, ClusterState> cluster_map_
+  //  Map of existing xDS server channels.
+  std::map<XdsBootstrap::XdsServer, ChannelState*> xds_server_channel_map_
       ABSL_GUARDED_BY(mu_);
-  // One entry for each watched EDS resource.
-  std::map<std::string /*eds_service_name*/, EndpointState> endpoint_map_
+
+  std::map<std::string /*authority*/, AuthorityState> authority_state_map_
       ABSL_GUARDED_BY(mu_);
 
   // Load report data.
@@ -355,9 +352,17 @@ class XdsClient : public DualRefCounted<XdsClient> {
       LoadReportState>
       load_report_map_ ABSL_GUARDED_BY(mu_);
 
-  // Stores the most recent accepted resource version for each resource type.
-  std::map<std::string /*type*/, std::string /*version*/> resource_version_map_
-      ABSL_GUARDED_BY(mu_);
+  // Stores started watchers whose resource name was not parsed successfully,
+  // waiting to be cancelled or reset in Orphan().
+  std::map<ListenerWatcherInterface*, std::unique_ptr<ListenerWatcherInterface>>
+      invalid_listener_watchers_ ABSL_GUARDED_BY(mu_);
+  std::map<RouteConfigWatcherInterface*,
+           std::unique_ptr<RouteConfigWatcherInterface>>
+      invalid_route_config_watchers_ ABSL_GUARDED_BY(mu_);
+  std::map<ClusterWatcherInterface*, std::unique_ptr<ClusterWatcherInterface>>
+      invalid_cluster_watchers_ ABSL_GUARDED_BY(mu_);
+  std::map<EndpointWatcherInterface*, std::unique_ptr<EndpointWatcherInterface>>
+      invalid_endpoint_watchers_ ABSL_GUARDED_BY(mu_);
 
   bool shutting_down_ ABSL_GUARDED_BY(mu_) = false;
 };
index 31dbb46..7c12391 100644 (file)
@@ -46,7 +46,7 @@ class XdsLocalityName : public RefCounted<XdsLocalityName> {
   struct Less {
     bool operator()(const XdsLocalityName* lhs,
                     const XdsLocalityName* rhs) const {
-      if (lhs == nullptr || rhs == nullptr) return GPR_ICMP(lhs, rhs);
+      if (lhs == nullptr || rhs == nullptr) return QsortCompare(lhs, rhs);
       return lhs->Compare(*rhs) < 0;
     }
 
index fe010cf..aed2f2d 100644 (file)
@@ -353,12 +353,12 @@ class XdsServerConfigFetcher : public grpc_server_config_fetcher {
     GPR_ASSERT(xds_client_ != nullptr);
   }
 
-  void StartWatch(std::string listening_address, grpc_channel_args* args,
+  void StartWatch(std::string listening_address,
                   std::unique_ptr<grpc_server_config_fetcher::WatcherInterface>
                       watcher) override {
     grpc_server_config_fetcher::WatcherInterface* watcher_ptr = watcher.get();
     auto listener_watcher = absl::make_unique<ListenerWatcher>(
-        std::move(watcher), args, xds_client_, serving_status_notifier_,
+        std::move(watcher), xds_client_, serving_status_notifier_,
         listening_address);
     auto* listener_watcher_ptr = listener_watcher.get();
     listening_address = absl::StrReplaceAll(
@@ -396,17 +396,14 @@ class XdsServerConfigFetcher : public grpc_server_config_fetcher {
     explicit ListenerWatcher(
         std::unique_ptr<grpc_server_config_fetcher::WatcherInterface>
             server_config_watcher,
-        grpc_channel_args* args, RefCountedPtr<XdsClient> xds_client,
+        RefCountedPtr<XdsClient> xds_client,
         grpc_server_xds_status_notifier serving_status_notifier,
         std::string listening_address)
         : server_config_watcher_(std::move(server_config_watcher)),
-          args_(args),
           xds_client_(std::move(xds_client)),
           serving_status_notifier_(serving_status_notifier),
           listening_address_(std::move(listening_address)) {}
 
-    ~ListenerWatcher() override { grpc_channel_args_destroy(args_); }
-
     // Deleted due to special handling required for args_. Copy the channel args
     // if we ever need these.
     ListenerWatcher(const ListenerWatcher&) = delete;
@@ -498,7 +495,6 @@ class XdsServerConfigFetcher : public grpc_server_config_fetcher {
    private:
     std::unique_ptr<grpc_server_config_fetcher::WatcherInterface>
         server_config_watcher_;
-    grpc_channel_args* args_;
     RefCountedPtr<XdsClient> xds_client_;
     grpc_server_xds_status_notifier serving_status_notifier_;
     std::string listening_address_;
@@ -524,10 +520,12 @@ grpc_server_config_fetcher* grpc_server_config_fetcher_xds_create(
     grpc_server_xds_status_notifier notifier, const grpc_channel_args* args) {
   grpc_core::ApplicationCallbackExecCtx callback_exec_ctx;
   grpc_core::ExecCtx exec_ctx;
+  args = grpc_channel_args_remove_grpc_internal(args);
   GRPC_API_TRACE("grpc_server_config_fetcher_xds_create()", 0, ());
   grpc_error_handle error = GRPC_ERROR_NONE;
   grpc_core::RefCountedPtr<grpc_core::XdsClient> xds_client =
       grpc_core::XdsClient::GetOrCreate(args, &error);
+  grpc_channel_args_destroy(args);
   if (error != GRPC_ERROR_NONE) {
     gpr_log(GPR_ERROR, "Failed to create xds client: %s",
             grpc_error_std_string(error).c_str());
index a621514..c254d2e 100644 (file)
@@ -83,6 +83,7 @@ namespace grpc_core {
 
 grpc_error_handle UnixSockaddrPopulate(absl::string_view path,
                                        grpc_resolved_address* resolved_addr) {
+  memset(resolved_addr, 0, sizeof(*resolved_addr));
   struct sockaddr_un* un =
       reinterpret_cast<struct sockaddr_un*>(resolved_addr->addr);
   const size_t maxlen = sizeof(un->sun_path) - 1;
@@ -99,6 +100,7 @@ grpc_error_handle UnixSockaddrPopulate(absl::string_view path,
 
 grpc_error_handle UnixAbstractSockaddrPopulate(
     absl::string_view path, grpc_resolved_address* resolved_addr) {
+  memset(resolved_addr, 0, sizeof(*resolved_addr));
   struct sockaddr_un* un =
       reinterpret_cast<struct sockaddr_un*>(resolved_addr->addr);
   const size_t maxlen = sizeof(un->sun_path) - 1;
index e04fe35..cd1b940 100644 (file)
 #include <assert.h>
 #include <stdlib.h>
 
+#include <algorithm>
+
 #include <grpc/support/alloc.h>
 #include <grpc/support/string_util.h>
 
-#include "src/core/lib/gpr/useful.h"
-
 grpc_avl grpc_avl_create(const grpc_avl_vtable* vtable) {
   grpc_avl out;
   out.vtable = vtable;
@@ -63,8 +63,8 @@ static long node_height(grpc_avl_node* node) {
 #ifndef NDEBUG
 static long calculate_height(grpc_avl_node* node) {
   return node == nullptr ? 0
-                         : 1 + GPR_MAX(calculate_height(node->left),
-                                       calculate_height(node->right));
+                         : 1 + std::max(calculate_height(node->left),
+                                        calculate_height(node->right));
 }
 
 static grpc_avl_node* assert_invariants(grpc_avl_node* n) {
@@ -87,7 +87,7 @@ grpc_avl_node* new_node(void* key, void* value, grpc_avl_node* left,
   node->value = value;
   node->left = assert_invariants(left);
   node->right = assert_invariants(right);
-  node->height = 1 + GPR_MAX(node_height(left), node_height(right));
+  node->height = 1 + std::max(node_height(left), node_height(right));
   return node;
 }
 
index e536abd..68bef77 100644 (file)
@@ -39,7 +39,7 @@ double generate_uniform_random_number(uint32_t* rng_state) {
 double generate_uniform_random_number_between(uint32_t* rng_state, double a,
                                               double b) {
   if (a == b) return a;
-  if (a > b) GPR_SWAP(double, a, b);  // make sure a < b
+  if (a > b) std::swap(a, b);  // make sure a < b
   const double range = b - a;
   return a + generate_uniform_random_number(rng_state) * range;
 }
index a1da9c3..4cd015b 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <vector>
 
+#include "absl/strings/match.h"
 #include "absl/strings/str_format.h"
 #include "absl/strings/str_join.h"
 
@@ -72,6 +73,22 @@ grpc_channel_args* grpc_channel_args_copy_and_remove(
                                                    num_to_remove, nullptr, 0);
 }
 
+grpc_channel_args* grpc_channel_args_remove_grpc_internal(
+    const grpc_channel_args* src) {
+  if (src == nullptr) return nullptr;
+  // Create result.
+  grpc_channel_args* dst =
+      static_cast<grpc_channel_args*>(gpr_malloc(sizeof(grpc_channel_args)));
+  dst->args =
+      static_cast<grpc_arg*>(gpr_malloc(sizeof(grpc_arg) * src->num_args));
+  dst->num_args = 0;
+  for (size_t i = 0; i < src->num_args; ++i) {
+    if (absl::StartsWith(src->args[i].key, "grpc.internal.")) continue;
+    dst->args[dst->num_args++] = copy_arg(&src->args[i]);
+  }
+  return dst;
+}
+
 static bool should_remove_arg(const grpc_arg* arg, const char** to_remove,
                               size_t num_to_remove) {
   for (size_t i = 0; i < num_to_remove; ++i) {
@@ -146,7 +163,7 @@ grpc_channel_args* grpc_channel_args_union(const grpc_channel_args* a,
 }
 
 static int cmp_arg(const grpc_arg* a, const grpc_arg* b) {
-  int c = GPR_ICMP(a->type, b->type);
+  int c = grpc_core::QsortCompare(a->type, b->type);
   if (c != 0) return c;
   c = strcmp(a->key, b->key);
   if (c != 0) return c;
@@ -154,11 +171,12 @@ static int cmp_arg(const grpc_arg* a, const grpc_arg* b) {
     case GRPC_ARG_STRING:
       return strcmp(a->value.string, b->value.string);
     case GRPC_ARG_INTEGER:
-      return GPR_ICMP(a->value.integer, b->value.integer);
+      return grpc_core::QsortCompare(a->value.integer, b->value.integer);
     case GRPC_ARG_POINTER:
-      c = GPR_ICMP(a->value.pointer.p, b->value.pointer.p);
+      c = grpc_core::QsortCompare(a->value.pointer.p, b->value.pointer.p);
       if (c != 0) {
-        c = GPR_ICMP(a->value.pointer.vtable, b->value.pointer.vtable);
+        c = grpc_core::QsortCompare(a->value.pointer.vtable,
+                                    b->value.pointer.vtable);
         if (c == 0) {
           c = a->value.pointer.vtable->cmp(a->value.pointer.p,
                                            b->value.pointer.p);
@@ -175,7 +193,7 @@ static int cmp_key_stable(const void* ap, const void* bp) {
   const grpc_arg* const* a = static_cast<const grpc_arg* const*>(ap);
   const grpc_arg* const* b = static_cast<const grpc_arg* const*>(bp);
   int c = strcmp((*a)->key, (*b)->key);
-  if (c == 0) c = GPR_ICMP(*a, *b);
+  if (c == 0) c = grpc_core::QsortCompare(*a, *b);
   return c;
 }
 
@@ -225,7 +243,7 @@ int grpc_channel_args_compare(const grpc_channel_args* a,
                               const grpc_channel_args* b) {
   if (a == nullptr && b == nullptr) return 0;
   if (a == nullptr || b == nullptr) return a == nullptr ? -1 : 1;
-  int c = GPR_ICMP(a->num_args, b->num_args);
+  int c = grpc_core::QsortCompare(a->num_args, b->num_args);
   if (c != 0) return c;
   for (size_t i = 0; i < a->num_args; i++) {
     c = cmp_arg(&a->args[i], &b->args[i]);
index d95ae60..436e798 100644 (file)
@@ -41,6 +41,15 @@ grpc_channel_args* grpc_channel_args_copy_and_add(const grpc_channel_args* src,
                                                   const grpc_arg* to_add,
                                                   size_t num_to_add);
 
+/** Remove any channel args prefixed with 'grpc.internal.'
+ *  These are used for internal implementation details and are not intended to
+ *  be exposed to users.
+ *  Returns a new channel args instance.
+ *  Does not take ownership of \a src.
+ *  Should be called by any public API that receives channel args. */
+grpc_channel_args* grpc_channel_args_remove_grpc_internal(
+    const grpc_channel_args* src);
+
 /** Copies the arguments in \a src except for those whose keys are in
     \a to_remove. */
 grpc_channel_args* grpc_channel_args_copy_and_remove(
index 41ea9b5..186cad3 100644 (file)
@@ -25,6 +25,8 @@
 #include <grpc/support/alloc.h>
 #include <grpc/support/string_util.h>
 
+#include "src/core/lib/gprpp/memory.h"
+
 typedef struct filter_node {
   struct filter_node* next;
   struct filter_node* prev;
@@ -53,15 +55,13 @@ struct grpc_channel_stack_builder_iterator {
 
 grpc_channel_stack_builder* grpc_channel_stack_builder_create(void) {
   grpc_channel_stack_builder* b =
-      static_cast<grpc_channel_stack_builder*>(gpr_zalloc(sizeof(*b)));
-
+      grpc_core::Zalloc<grpc_channel_stack_builder>();
   b->begin.filter = nullptr;
   b->end.filter = nullptr;
   b->begin.next = &b->end;
   b->begin.prev = &b->end;
   b->end.next = &b->begin;
   b->end.prev = &b->begin;
-
   return b;
 }
 
index 50f7e19..f5a825c 100644 (file)
@@ -16,7 +16,7 @@
  *
  */
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include "src/core/lib/channel/channel_trace.h"
 
index 663f29e..deff60a 100644 (file)
@@ -19,7 +19,7 @@
 #ifndef GRPC_CORE_LIB_CHANNEL_CHANNEL_TRACE_H
 #define GRPC_CORE_LIB_CHANNEL_CHANNEL_TRACE_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include <grpc/grpc.h>
 
index 6aaf557..37dca3e 100644 (file)
@@ -16,7 +16,7 @@
  *
  */
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include "src/core/lib/channel/channelz.h"
 
@@ -77,7 +77,7 @@ std::string BaseNode::RenderJsonString() {
 //
 
 CallCountingHelper::CallCountingHelper() {
-  num_cores_ = GPR_MAX(1, gpr_cpu_num_cores());
+  num_cores_ = std::max(1u, gpr_cpu_num_cores());
   per_cpu_counter_data_storage_.reserve(num_cores_);
   for (size_t i = 0; i < num_cores_; ++i) {
     per_cpu_counter_data_storage_.emplace_back();
@@ -398,7 +398,7 @@ void SecurityArgDestroy(void* p) {
   xds_certificate_provider->Unref();
 }
 
-int SecurityArgCmp(void* p, void* q) { return GPR_ICMP(p, q); }
+int SecurityArgCmp(void* p, void* q) { return grpc_core::QsortCompare(p, q); }
 
 const grpc_arg_pointer_vtable kChannelArgVtable = {
     SecurityArgCopy, SecurityArgDestroy, SecurityArgCmp};
index e518862..2852e09 100644 (file)
@@ -19,7 +19,7 @@
 #ifndef GRPC_CORE_LIB_CHANNEL_CHANNELZ_H
 #define GRPC_CORE_LIB_CHANNEL_CHANNELZ_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include <atomic>
 #include <set>
@@ -41,7 +41,7 @@
 #include "src/core/lib/json/json.h"
 
 // Channel arg key for channelz node.
-#define GRPC_ARG_CHANNELZ_CHANNEL_NODE "grpc.channelz_channel_node"
+#define GRPC_ARG_CHANNELZ_CHANNEL_NODE "grpc.internal.channelz_channel_node"
 
 // Channel arg key for indicating an internal channel.
 #define GRPC_ARG_CHANNELZ_IS_INTERNAL_CHANNEL \
index d801600..3ef2479 100644 (file)
@@ -16,7 +16,7 @@
  *
  */
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include "src/core/lib/channel/channelz_registry.h"
 
index 8fcb7d8..8fd19f9 100644 (file)
@@ -19,7 +19,7 @@
 #ifndef GRPC_CORE_LIB_CHANNEL_CHANNELZ_REGISTRY_H
 #define GRPC_CORE_LIB_CHANNEL_CHANNELZ_REGISTRY_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include <stdint.h>
 
index 2d4eace..2a03c9c 100644 (file)
@@ -232,9 +232,7 @@ static void bind_transport(grpc_channel_stack* channel_stack,
       grpc_transport_stream_size(static_cast<grpc_transport*>(t));
 }
 
-bool grpc_add_connected_filter(grpc_channel_stack_builder* builder,
-                               void* arg_must_be_null) {
-  GPR_ASSERT(arg_must_be_null == nullptr);
+bool grpc_add_connected_filter(grpc_channel_stack_builder* builder) {
   grpc_transport* t = grpc_channel_stack_builder_get_transport(builder);
   GPR_ASSERT(t != nullptr);
   return grpc_channel_stack_builder_append_filter(
index faa1c73..1aa35d7 100644 (file)
@@ -25,8 +25,7 @@
 
 extern const grpc_channel_filter grpc_connected_filter;
 
-bool grpc_add_connected_filter(grpc_channel_stack_builder* builder,
-                               void* arg_must_be_null);
+bool grpc_add_connected_filter(grpc_channel_stack_builder* builder);
 
 /* Debug helper to dig the transport stream out of a call element */
 grpc_stream* grpc_connected_channel_get_stream(grpc_call_element* elem);
index d14b738..3d5d11f 100644 (file)
@@ -116,12 +116,12 @@ void grpc_compression_options_init(grpc_compression_options* opts) {
 
 void grpc_compression_options_enable_algorithm(
     grpc_compression_options* opts, grpc_compression_algorithm algorithm) {
-  GPR_BITSET(&opts->enabled_algorithms_bitset, algorithm);
+  grpc_core::SetBit(&opts->enabled_algorithms_bitset, algorithm);
 }
 
 void grpc_compression_options_disable_algorithm(
     grpc_compression_options* opts, grpc_compression_algorithm algorithm) {
-  GPR_BITCLEAR(&opts->enabled_algorithms_bitset, algorithm);
+  grpc_core::ClearBit(&opts->enabled_algorithms_bitset, algorithm);
 }
 
 int grpc_compression_options_is_algorithm_enabled(
index 90aa578..ee55c2f 100644 (file)
@@ -101,9 +101,9 @@ grpc_channel_args* grpc_channel_args_compression_algorithm_set_state(
             algo_name);
   } else if (states_arg_found) {
     if (state != 0) {
-      GPR_BITSET((unsigned*)states_arg, algorithm);
+      grpc_core::SetBit(reinterpret_cast<unsigned*>(states_arg), algorithm);
     } else if (algorithm != GRPC_COMPRESS_NONE) {
-      GPR_BITCLEAR((unsigned*)states_arg, algorithm);
+      grpc_core::ClearBit(reinterpret_cast<unsigned*>(states_arg), algorithm);
     }
   } else {
     /* create a new arg */
@@ -114,9 +114,11 @@ grpc_channel_args* grpc_channel_args_compression_algorithm_set_state(
     /* all enabled by default */
     tmp.value.integer = (1u << GRPC_COMPRESS_ALGORITHMS_COUNT) - 1;
     if (state != 0) {
-      GPR_BITSET((unsigned*)&tmp.value.integer, algorithm);
+      grpc_core::SetBit(reinterpret_cast<unsigned*>(&tmp.value.integer),
+                        algorithm);
     } else if (algorithm != GRPC_COMPRESS_NONE) {
-      GPR_BITCLEAR((unsigned*)&tmp.value.integer, algorithm);
+      grpc_core::ClearBit(reinterpret_cast<unsigned*>(&tmp.value.integer),
+                          algorithm);
     }
     result = grpc_channel_args_copy_and_add(*a, &tmp, 1);
     grpc_channel_args_destroy(*a);
index cce8ddc..ae2d745 100644 (file)
@@ -207,7 +207,7 @@ grpc_message_compression_algorithm grpc_message_compression_algorithm_for_level(
   }
 
   const size_t num_supported =
-      GPR_BITCOUNT(accepted_encodings) - 1; /* discard NONE */
+      grpc_core::BitCount(accepted_encodings) - 1; /* discard NONE */
   if (level == GRPC_COMPRESS_LEVEL_NONE || num_supported == 0) {
     return GRPC_MESSAGE_COMPRESS_NONE;
   }
@@ -228,7 +228,7 @@ grpc_message_compression_algorithm grpc_message_compression_algorithm_for_level(
   for (size_t i = 0; i < GPR_ARRAY_SIZE(algos_ranking); i++) {
     const grpc_message_compression_algorithm alg = algos_ranking[i];
     for (size_t j = 0; j < num_supported; j++) {
-      if (GPR_BITGET(accepted_encodings, alg) == 1) {
+      if (grpc_core::GetBit(accepted_encodings, alg) == 1) {
         /* if \a alg in supported */
         sorted_supported_algos[algos_supported_idx++] = alg;
         break;
index 22977f7..6e1f51a 100644 (file)
@@ -91,7 +91,7 @@ int grpc_stream_compression_algorithm_parse(
 inline int grpc_compression_options_is_algorithm_enabled_internal(
     const grpc_compression_options* opts,
     grpc_compression_algorithm algorithm) {
-  return GPR_BITGET(opts->enabled_algorithms_bitset, algorithm);
+  return grpc_core::GetBit(opts->enabled_algorithms_bitset, algorithm);
 }
 
 #endif /* GRPC_CORE_LIB_COMPRESSION_COMPRESSION_INTERNAL_H */
index 61f29e1..f37672d 100644 (file)
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include "src/core/lib/config/core_configuration.h"
 
+#include <grpc/support/log.h>
+
 namespace grpc_core {
 
 std::atomic<CoreConfiguration*> CoreConfiguration::config_{nullptr};
+std::atomic<CoreConfiguration::RegisteredBuilder*> CoreConfiguration::builders_{
+    nullptr};
 
 CoreConfiguration::Builder::Builder() = default;
 
@@ -27,11 +31,42 @@ CoreConfiguration* CoreConfiguration::Builder::Build() {
 }
 
 CoreConfiguration::CoreConfiguration(Builder* builder)
-    : handshaker_registry_(builder->handshaker_registry_.Build()) {}
+    : channel_init_(builder->channel_init_.Build()),
+      handshaker_registry_(builder->handshaker_registry_.Build()) {}
+
+void CoreConfiguration::RegisterBuilder(std::function<void(Builder*)> builder) {
+  GPR_ASSERT(config_.load(std::memory_order_relaxed) == nullptr &&
+             "CoreConfiguration was already instantiated before builder "
+             "registration was completed");
+  RegisteredBuilder* n = new RegisteredBuilder();
+  n->builder = std::move(builder);
+  n->next = builders_.load(std::memory_order_relaxed);
+  while (!builders_.compare_exchange_weak(n->next, n, std::memory_order_acq_rel,
+                                          std::memory_order_relaxed)) {
+  }
+  GPR_ASSERT(config_.load(std::memory_order_relaxed) == nullptr &&
+             "CoreConfiguration was already instantiated before builder "
+             "registration was completed");
+}
 
 const CoreConfiguration& CoreConfiguration::BuildNewAndMaybeSet() {
   // Construct builder, pass it up to code that knows about build configuration
   Builder builder;
+  // The linked list of builders stores things in reverse registration order.
+  // To get things registered as systems relying on this expect however, we
+  // actually need to run things in forward registration order, so we iterate
+  // once over the linked list to build a vector of builders, and then iterate
+  // over said vector in reverse to actually run the builders.
+  std::vector<RegisteredBuilder*> registered_builders;
+  for (RegisteredBuilder* b = builders_.load(std::memory_order_acquire);
+       b != nullptr; b = b->next) {
+    registered_builders.push_back(b);
+  }
+  for (auto it = registered_builders.rbegin(); it != registered_builders.rend();
+       ++it) {
+    (*it)->builder(&builder);
+  }
+  // Finally, call the built in configuration builder.
   BuildCoreConfiguration(&builder);
   // Use builder to construct a confguration
   CoreConfiguration* p = builder.Build();
@@ -49,6 +84,13 @@ const CoreConfiguration& CoreConfiguration::BuildNewAndMaybeSet() {
 
 void CoreConfiguration::Reset() {
   delete config_.exchange(nullptr, std::memory_order_acquire);
+  RegisteredBuilder* builder =
+      builders_.exchange(nullptr, std::memory_order_acquire);
+  while (builder != nullptr) {
+    RegisteredBuilder* next = builder->next;
+    delete builder;
+    builder = next;
+  }
 }
 
 }  // namespace grpc_core
index db8530b..0247d8b 100644 (file)
 #ifndef GRPC_CORE_LIB_CONFIG_CORE_CONFIGURATION_H
 #define GRPC_CORE_LIB_CONFIG_CORE_CONFIGURATION_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include <atomic>
 
 #include "src/core/lib/channel/handshaker_registry.h"
+#include "src/core/lib/surface/channel_init.h"
 
 namespace grpc_core {
 
@@ -34,6 +35,8 @@ class CoreConfiguration {
   // their configuration and assemble the published CoreConfiguration.
   class Builder {
    public:
+    ChannelInit::Builder* channel_init() { return &channel_init_; }
+
     HandshakerRegistry::Builder* handshaker_registry() {
       return &handshaker_registry_;
     }
@@ -41,6 +44,7 @@ class CoreConfiguration {
    private:
     friend class CoreConfiguration;
 
+    ChannelInit::Builder channel_init_;
     HandshakerRegistry::Builder handshaker_registry_;
 
     Builder();
@@ -77,13 +81,38 @@ class CoreConfiguration {
     delete config_.exchange(p, std::memory_order_release);
   }
 
+  // Attach a registration function globally.
+  // Each registration function is called *in addition to*
+  // BuildCoreConfiguration for the default core configuration. When using
+  // BuildSpecialConfiguration, one can use CallRegisteredBuilders to call them.
+  // Must be called before a configuration is built.
+  static void RegisterBuilder(std::function<void(Builder*)> builder);
+
+  // Call all registered builders.
+  // See RegisterBuilder for why you might want to call this.
+  static void CallRegisteredBuilders(Builder* builder);
+
   // Drop the core configuration. Users must ensure no other threads are
   // accessing the configuration.
   // Clears any dynamically registered builders.
   static void Reset();
 
+  // Helper for tests: Reset the configuration, build a special one, run some
+  // code, and then reset the configuration again.
+  // Templatized to be sure no codegen in normal builds.
+  template <typename BuildFunc, typename RunFunc>
+  static void RunWithSpecialConfiguration(BuildFunc build_configuration,
+                                          RunFunc code_to_run) {
+    Reset();
+    BuildSpecialConfiguration(build_configuration);
+    code_to_run();
+    Reset();
+  }
+
   // Accessors
 
+  const ChannelInit& channel_init() const { return channel_init_; }
+
   const HandshakerRegistry& handshaker_registry() const {
     return handshaker_registry_;
   }
@@ -91,13 +120,22 @@ class CoreConfiguration {
  private:
   explicit CoreConfiguration(Builder* builder);
 
+  // Stores a builder for RegisterBuilder
+  struct RegisteredBuilder {
+    std::function<void(Builder*)> builder;
+    RegisteredBuilder* next;
+  };
+
   // Create a new CoreConfiguration, and either set it or throw it away.
   // We allow multiple CoreConfiguration's to be created in parallel.
   static const CoreConfiguration& BuildNewAndMaybeSet();
 
   // The configuration
   static std::atomic<CoreConfiguration*> config_;
+  // Extra registered builders
+  static std::atomic<RegisteredBuilder*> builders_;
 
+  ChannelInit channel_init_;
   HandshakerRegistry handshaker_registry_;
 };
 
index 7f602b6..a0292e3 100644 (file)
@@ -38,7 +38,7 @@ grpc_stats_data* grpc_stats_per_cpu_storage = nullptr;
 static size_t g_num_cores;
 
 void grpc_stats_init(void) {
-  g_num_cores = GPR_MAX(1, gpr_cpu_num_cores());
+  g_num_cores = std::max(1u, gpr_cpu_num_cores());
   grpc_stats_per_cpu_storage = static_cast<grpc_stats_data*>(
       gpr_zalloc(sizeof(grpc_stats_data) * g_num_cores));
 }
index 31bd742..21e27f2 100644 (file)
@@ -353,7 +353,7 @@ const uint8_t grpc_stats_table_7[102] = {
 const int grpc_stats_table_8[9] = {0, 1, 2, 4, 7, 13, 23, 39, 64};
 const uint8_t grpc_stats_table_9[9] = {0, 0, 1, 2, 2, 3, 4, 4, 5};
 void grpc_stats_inc_call_initial_size(int value) {
-  value = GPR_CLAMP(value, 0, 262144);
+  value = grpc_core::Clamp(value, 0, 262144);
   if (value < 6) {
     GRPC_STATS_INC_HISTOGRAM(GRPC_STATS_HISTOGRAM_CALL_INITIAL_SIZE, value);
     return;
@@ -376,7 +376,7 @@ void grpc_stats_inc_call_initial_size(int value) {
       grpc_stats_histo_find_bucket_slow(value, grpc_stats_table_0, 64));
 }
 void grpc_stats_inc_poll_events_returned(int value) {
-  value = GPR_CLAMP(value, 0, 1024);
+  value = grpc_core::Clamp(value, 0, 1024);
   if (value < 29) {
     GRPC_STATS_INC_HISTOGRAM(GRPC_STATS_HISTOGRAM_POLL_EVENTS_RETURNED, value);
     return;
@@ -399,7 +399,7 @@ void grpc_stats_inc_poll_events_returned(int value) {
       grpc_stats_histo_find_bucket_slow(value, grpc_stats_table_2, 128));
 }
 void grpc_stats_inc_tcp_write_size(int value) {
-  value = GPR_CLAMP(value, 0, 16777216);
+  value = grpc_core::Clamp(value, 0, 16777216);
   if (value < 5) {
     GRPC_STATS_INC_HISTOGRAM(GRPC_STATS_HISTOGRAM_TCP_WRITE_SIZE, value);
     return;
@@ -422,7 +422,7 @@ void grpc_stats_inc_tcp_write_size(int value) {
       grpc_stats_histo_find_bucket_slow(value, grpc_stats_table_4, 64));
 }
 void grpc_stats_inc_tcp_write_iov_size(int value) {
-  value = GPR_CLAMP(value, 0, 1024);
+  value = grpc_core::Clamp(value, 0, 1024);
   if (value < 13) {
     GRPC_STATS_INC_HISTOGRAM(GRPC_STATS_HISTOGRAM_TCP_WRITE_IOV_SIZE, value);
     return;
@@ -445,7 +445,7 @@ void grpc_stats_inc_tcp_write_iov_size(int value) {
       grpc_stats_histo_find_bucket_slow(value, grpc_stats_table_6, 64));
 }
 void grpc_stats_inc_tcp_read_size(int value) {
-  value = GPR_CLAMP(value, 0, 16777216);
+  value = grpc_core::Clamp(value, 0, 16777216);
   if (value < 5) {
     GRPC_STATS_INC_HISTOGRAM(GRPC_STATS_HISTOGRAM_TCP_READ_SIZE, value);
     return;
@@ -468,7 +468,7 @@ void grpc_stats_inc_tcp_read_size(int value) {
       grpc_stats_histo_find_bucket_slow(value, grpc_stats_table_4, 64));
 }
 void grpc_stats_inc_tcp_read_offer(int value) {
-  value = GPR_CLAMP(value, 0, 16777216);
+  value = grpc_core::Clamp(value, 0, 16777216);
   if (value < 5) {
     GRPC_STATS_INC_HISTOGRAM(GRPC_STATS_HISTOGRAM_TCP_READ_OFFER, value);
     return;
@@ -491,7 +491,7 @@ void grpc_stats_inc_tcp_read_offer(int value) {
       grpc_stats_histo_find_bucket_slow(value, grpc_stats_table_4, 64));
 }
 void grpc_stats_inc_tcp_read_offer_iov_size(int value) {
-  value = GPR_CLAMP(value, 0, 1024);
+  value = grpc_core::Clamp(value, 0, 1024);
   if (value < 13) {
     GRPC_STATS_INC_HISTOGRAM(GRPC_STATS_HISTOGRAM_TCP_READ_OFFER_IOV_SIZE,
                              value);
@@ -516,7 +516,7 @@ void grpc_stats_inc_tcp_read_offer_iov_size(int value) {
       grpc_stats_histo_find_bucket_slow(value, grpc_stats_table_6, 64));
 }
 void grpc_stats_inc_http2_send_message_size(int value) {
-  value = GPR_CLAMP(value, 0, 16777216);
+  value = grpc_core::Clamp(value, 0, 16777216);
   if (value < 5) {
     GRPC_STATS_INC_HISTOGRAM(GRPC_STATS_HISTOGRAM_HTTP2_SEND_MESSAGE_SIZE,
                              value);
@@ -541,7 +541,7 @@ void grpc_stats_inc_http2_send_message_size(int value) {
       grpc_stats_histo_find_bucket_slow(value, grpc_stats_table_4, 64));
 }
 void grpc_stats_inc_http2_send_initial_metadata_per_write(int value) {
-  value = GPR_CLAMP(value, 0, 1024);
+  value = grpc_core::Clamp(value, 0, 1024);
   if (value < 13) {
     GRPC_STATS_INC_HISTOGRAM(
         GRPC_STATS_HISTOGRAM_HTTP2_SEND_INITIAL_METADATA_PER_WRITE, value);
@@ -566,7 +566,7 @@ void grpc_stats_inc_http2_send_initial_metadata_per_write(int value) {
       grpc_stats_histo_find_bucket_slow(value, grpc_stats_table_6, 64));
 }
 void grpc_stats_inc_http2_send_message_per_write(int value) {
-  value = GPR_CLAMP(value, 0, 1024);
+  value = grpc_core::Clamp(value, 0, 1024);
   if (value < 13) {
     GRPC_STATS_INC_HISTOGRAM(GRPC_STATS_HISTOGRAM_HTTP2_SEND_MESSAGE_PER_WRITE,
                              value);
@@ -591,7 +591,7 @@ void grpc_stats_inc_http2_send_message_per_write(int value) {
       grpc_stats_histo_find_bucket_slow(value, grpc_stats_table_6, 64));
 }
 void grpc_stats_inc_http2_send_trailing_metadata_per_write(int value) {
-  value = GPR_CLAMP(value, 0, 1024);
+  value = grpc_core::Clamp(value, 0, 1024);
   if (value < 13) {
     GRPC_STATS_INC_HISTOGRAM(
         GRPC_STATS_HISTOGRAM_HTTP2_SEND_TRAILING_METADATA_PER_WRITE, value);
@@ -616,7 +616,7 @@ void grpc_stats_inc_http2_send_trailing_metadata_per_write(int value) {
       grpc_stats_histo_find_bucket_slow(value, grpc_stats_table_6, 64));
 }
 void grpc_stats_inc_http2_send_flowctl_per_write(int value) {
-  value = GPR_CLAMP(value, 0, 1024);
+  value = grpc_core::Clamp(value, 0, 1024);
   if (value < 13) {
     GRPC_STATS_INC_HISTOGRAM(GRPC_STATS_HISTOGRAM_HTTP2_SEND_FLOWCTL_PER_WRITE,
                              value);
@@ -641,7 +641,7 @@ void grpc_stats_inc_http2_send_flowctl_per_write(int value) {
       grpc_stats_histo_find_bucket_slow(value, grpc_stats_table_6, 64));
 }
 void grpc_stats_inc_server_cqs_checked(int value) {
-  value = GPR_CLAMP(value, 0, 64);
+  value = grpc_core::Clamp(value, 0, 64);
   if (value < 3) {
     GRPC_STATS_INC_HISTOGRAM(GRPC_STATS_HISTOGRAM_SERVER_CQS_CHECKED, value);
     return;
diff --git a/src/core/lib/event_engine/memory_allocator.cc b/src/core/lib/event_engine/memory_allocator.cc
new file mode 100644 (file)
index 0000000..ea2a3c2
--- /dev/null
@@ -0,0 +1,70 @@
+// 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 <grpc/support/port_platform.h>
+
+#include <grpc/event_engine/memory_allocator.h>
+
+#include "src/core/lib/gprpp/ref_counted.h"
+#include "src/core/lib/slice/slice_refcount.h"
+
+namespace grpc_event_engine {
+namespace experimental {
+
+namespace {
+
+// Reference count for a slice allocated by MemoryAllocator::MakeSlice.
+// Takes care of releasing memory back when the slice is destroyed.
+class SliceRefCount {
+ public:
+  static void Destroy(void* p) {
+    auto* rc = static_cast<SliceRefCount*>(p);
+    rc->~SliceRefCount();
+    gpr_free(rc);
+  }
+  SliceRefCount(std::shared_ptr<internal::MemoryAllocatorImpl> allocator,
+                size_t size)
+      : base_(grpc_slice_refcount::Type::REGULAR, &refs_, Destroy, this,
+              &base_),
+        allocator_(std::move(allocator)),
+        size_(size) {
+    // Nothing to do here.
+  }
+  ~SliceRefCount() { allocator_->Release(size_); }
+
+  grpc_slice_refcount* base_refcount() { return &base_; }
+
+ private:
+  grpc_slice_refcount base_;
+  grpc_core::RefCount refs_;
+  std::shared_ptr<internal::MemoryAllocatorImpl> allocator_;
+  size_t size_;
+};
+
+}  // namespace
+
+grpc_slice MemoryAllocator::MakeSlice(MemoryRequest request) {
+  auto size = Reserve(request.Increase(sizeof(SliceRefCount)));
+  void* p = gpr_malloc(size);
+  new (p) SliceRefCount(allocator_, size);
+  grpc_slice slice;
+  slice.refcount = static_cast<SliceRefCount*>(p)->base_refcount();
+  slice.data.refcounted.bytes =
+      static_cast<uint8_t*>(p) + sizeof(SliceRefCount);
+  slice.data.refcounted.length = size - sizeof(SliceRefCount);
+  return slice;
+}
+
+}  // namespace experimental
+}  // namespace grpc_event_engine
index 649d400..c40e97e 100644 (file)
@@ -28,7 +28,7 @@ gpr_atm gpr_atm_no_barrier_clamped_add(gpr_atm* value, gpr_atm delta,
   gpr_atm new_value;
   do {
     current_value = gpr_atm_no_barrier_load(value);
-    new_value = GPR_CLAMP(current_value + delta, min, max);
+    new_value = grpc_core::Clamp(current_value + delta, min, max);
     if (new_value == current_value) break;
   } while (!gpr_atm_no_barrier_cas(value, current_value, new_value));
   return new_value;
index 982ccbd..7a1d546 100644 (file)
@@ -77,7 +77,7 @@ unsigned gpr_cpu_current_cpu(void) {
     pthread_setspecific(thread_id_key, thread_id);
   }
 
-  return (unsigned)GPR_HASH_POINTER(thread_id, gpr_cpu_num_cores());
+  return (unsigned)grpc_core::HashPointer(thread_id, gpr_cpu_num_cores());
 }
 
 #endif /* GPR_CPU_POSIX */
index cbafdfc..9f12ed4 100644 (file)
@@ -89,7 +89,7 @@ static dump_out dump_out_create(void) {
 
 static void dump_out_append(dump_out* out, char c) {
   if (out->length == out->capacity) {
-    out->capacity = GPR_MAX(8, 2 * out->capacity);
+    out->capacity = std::max(size_t(8), 2 * out->capacity);
     out->data = static_cast<char*>(gpr_realloc(out->data, out->capacity));
   }
   out->data[out->length++] = c;
@@ -290,7 +290,7 @@ static void add_string_to_split(const char* beg, const char* end, char*** strs,
   memcpy(out, beg, static_cast<size_t>(end - beg));
   out[end - beg] = 0;
   if (*nstrs == *capstrs) {
-    *capstrs = GPR_MAX(8, 2 * *capstrs);
+    *capstrs = std::max(size_t(8), 2 * *capstrs);
     *strs = static_cast<char**>(gpr_realloc(*strs, sizeof(*strs) * *capstrs));
   }
   (*strs)[*nstrs] = out;
index 32add50..5c9b69e 100644 (file)
@@ -19,7 +19,7 @@
 #ifndef GRPC_CORE_LIB_GPR_TLS_H
 #define GRPC_CORE_LIB_GPR_TLS_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include <type_traits>
 
index 8382a50..2e00257 100644 (file)
 #ifndef GRPC_CORE_LIB_GPR_USEFUL_H
 #define GRPC_CORE_LIB_GPR_USEFUL_H
 
-/** useful macros that don't belong anywhere else */
+#include <grpc/support/port_platform.h>
+
+#include <cstddef>
+
+/** useful utilities that don't belong anywhere else */
+
+namespace grpc_core {
+
+template <typename T>
+T Clamp(T val, T min, T max) {
+  if (val < min) return min;
+  if (max < val) return max;
+  return val;
+}
 
-#define GPR_MIN(a, b) ((a) < (b) ? (a) : (b))
-#define GPR_MAX(a, b) ((a) > (b) ? (a) : (b))
-#define GPR_CLAMP(a, min, max) ((a) < (min) ? (min) : (a) > (max) ? (max) : (a))
 /** rotl, rotr assume x is unsigned */
-#define GPR_ROTL(x, n) (((x) << (n)) | ((x) >> (sizeof(x) * 8 - (n))))
-#define GPR_ROTR(x, n) (((x) >> (n)) | ((x) << (sizeof(x) * 8 - (n))))
+template <typename T>
+constexpr T RotateLeft(T x, T n) {
+  return ((x << n) | (x >> (sizeof(x) * 8 - n)));
+}
+template <typename T>
+constexpr T RotateRight(T x, T n) {
+  return ((x >> n) | (x << (sizeof(x) * 8 - n)));
+}
 
-#define GPR_ARRAY_SIZE(array) (sizeof(array) / sizeof(*(array)))
+// Set the n-th bit of i
+template <typename T>
+T SetBit(T* i, size_t n) {
+  return *i |= (T(1) << n);
+}
+
+// Clear the n-th bit of i
+template <typename T>
+T ClearBit(T* i, size_t n) {
+  return *i &= ~(T(1) << n);
+}
 
-#define GPR_SWAP(type, a, b) \
-  do {                       \
-    type x = a;              \
-    (a) = b;                 \
-    (b) = x;                 \
-  } while (0)
+// Get the n-th bit of i
+template <typename T>
+bool GetBit(T i, size_t n) {
+  return (i & (T(1) << n)) != 0;
+}
 
-/** Set the \a n-th bit of \a i (a mutable pointer). */
-#define GPR_BITSET(i, n) ((*(i)) |= (1u << (n)))
+namespace useful_detail {
+inline constexpr uint32_t HexdigitBitcount(uint32_t x) {
+  return (x - ((x >> 1) & 0x77777777) - ((x >> 2) & 0x33333333) -
+          ((x >> 3) & 0x11111111));
+}
+}  // namespace useful_detail
 
-/** Clear the \a n-th bit of \a i (a mutable pointer). */
-#define GPR_BITCLEAR(i, n) ((*(i)) &= ~(1u << (n)))
+inline constexpr uint32_t BitCount(uint32_t i) {
+  return (((useful_detail::HexdigitBitcount(i) +
+            (useful_detail::HexdigitBitcount(i) >> 4)) &
+           0x0f0f0f0f) %
+          255);
+}
 
-/** Get the \a n-th bit of \a i */
-#define GPR_BITGET(i, n) (((i) & (1u << (n))) != 0)
+inline constexpr uint32_t BitCount(uint64_t i) {
+  return BitCount(uint32_t(i)) + BitCount(uint32_t(i >> 32));
+}
 
-#define GPR_INTERNAL_HEXDIGIT_BITCOUNT(x)                        \
-  ((x) - (((x) >> 1) & 0x77777777) - (((x) >> 2) & 0x33333333) - \
-   (((x) >> 3) & 0x11111111))
+inline constexpr uint32_t BitCount(uint16_t i) { return BitCount(uint32_t(i)); }
+inline constexpr uint32_t BitCount(uint8_t i) { return BitCount(uint32_t(i)); }
+inline constexpr uint32_t BitCount(int64_t i) { return BitCount(uint64_t(i)); }
+inline constexpr uint32_t BitCount(int32_t i) { return BitCount(uint32_t(i)); }
+inline constexpr uint32_t BitCount(int16_t i) { return BitCount(uint16_t(i)); }
+inline constexpr uint32_t BitCount(int8_t i) { return BitCount(uint8_t(i)); }
 
-/** Returns number of bits set in bitset \a i */
-#define GPR_BITCOUNT(i)                          \
-  (((GPR_INTERNAL_HEXDIGIT_BITCOUNT(i) +         \
-     (GPR_INTERNAL_HEXDIGIT_BITCOUNT(i) >> 4)) & \
-    0x0f0f0f0f) %                                \
-   255)
+// This function uses operator< to implement a qsort-style comparison, whereby:
+// if a is smaller than b, a number smaller than 0 is returned.
+// if a is bigger than b, a number greater than 0 is returned.
+// if a is neither smaller nor bigger than b, 0 is returned.
+template <typename T>
+int QsortCompare(const T& a, const T& b) {
+  if (a < b) return -1;
+  if (b < a) return 1;
+  return 0;
+}
 
-#define GPR_ICMP(a, b) ((a) < (b) ? -1 : ((a) > (b) ? 1 : 0))
+template <typename T>
+constexpr size_t HashPointer(T* p, size_t range) {
+  return (((reinterpret_cast<size_t>(p)) >> 4) ^
+          ((reinterpret_cast<size_t>(p)) >> 9) ^
+          ((reinterpret_cast<size_t>(p)) >> 14)) %
+         range;
+}
 
-#define GPR_HASH_POINTER(x, range)                                         \
-  (((((size_t)(x)) >> 4) ^ (((size_t)(x)) >> 9) ^ (((size_t)(x)) >> 14)) % \
-   (range))
+}  // namespace grpc_core
+
+#define GPR_ARRAY_SIZE(array) (sizeof(array) / sizeof(*(array)))
 
 #endif /* GRPC_CORE_LIB_GPR_USEFUL_H */
index 0c45fa6..3967f2f 100644 (file)
@@ -30,6 +30,7 @@
 #include <stddef.h>
 
 #include <atomic>
+#include <memory>
 #include <new>
 #include <utility>
 
@@ -116,6 +117,15 @@ class Arena {
   Zone* last_zone_ = nullptr;
 };
 
+// Smart pointer for arenas when the final size is not required.
+struct ScopedArenaDeleter {
+  void operator()(Arena* arena) { arena->Destroy(); }
+};
+using ScopedArenaPtr = std::unique_ptr<Arena, ScopedArenaDeleter>;
+inline ScopedArenaPtr MakeScopedArena(size_t initial_size) {
+  return ScopedArenaPtr(Arena::Create(initial_size));
+}
+
 }  // namespace grpc_core
 
 #endif /* GRPC_CORE_LIB_GPRPP_ARENA_H */
index 4577af3..1732f4e 100644 (file)
 #ifndef GRPC_CORE_LIB_GPRPP_BITSET_H
 #define GRPC_CORE_LIB_GPRPP_BITSET_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include <utility>
 
+#include "src/core/lib/gpr/useful.h"
+
 #if __cplusplus > 201103l
 #define GRPC_BITSET_CONSTEXPR_MUTATOR constexpr
 #else
@@ -29,7 +31,7 @@ namespace grpc_core {
 
 // Given a bit count as an integer, vend as member type `Type` a type with
 // exactly that number of bits. Undefined if that bit count is not available.
-template <std::size_t kBits>
+template <size_t kBits>
 struct UintSelector;
 template <>
 struct UintSelector<8> {
@@ -49,7 +51,7 @@ struct UintSelector<64> {
 };
 
 // An unsigned integer of some number of bits.
-template <std::size_t kBits>
+template <size_t kBits>
 using Uint = typename UintSelector<kBits>::Type;
 
 // Given the total number of bits that need to be stored, choose the size of
@@ -58,7 +60,7 @@ using Uint = typename UintSelector<kBits>::Type;
 // size and performance
 // - the details will likely be tweaked into the future.
 // Once we get over 96 bits, we just use uint64_t for everything.
-constexpr std::size_t ChooseUnitBitsForBitSet(std::size_t total_bits) {
+constexpr size_t ChooseUnitBitsForBitSet(size_t total_bits) {
   return total_bits <= 8    ? 8
          : total_bits <= 16 ? 16
          : total_bits <= 24 ? 8
@@ -74,11 +76,10 @@ constexpr std::size_t ChooseUnitBitsForBitSet(std::size_t total_bits) {
 // kUnitBits. e.g. to store 72 bits in 8 bit chunks, we'd say BitSet<72, 8>.
 // Since most users shouldn't care about the size of unit used, we default
 // kUnitBits to whatever is selected by ChooseUnitBitsForBitSet
-template <std::size_t kTotalBits,
-          std::size_t kUnitBits = ChooseUnitBitsForBitSet(kTotalBits)>
+template <size_t kTotalBits,
+          size_t kUnitBits = ChooseUnitBitsForBitSet(kTotalBits)>
 class BitSet {
-  static constexpr std::size_t kUnits =
-      (kTotalBits + kUnitBits - 1) / kUnitBits;
+  static constexpr size_t kUnits = (kTotalBits + kUnitBits - 1) / kUnitBits;
 
  public:
   // Initialize to all bits false
@@ -113,7 +114,7 @@ class BitSet {
     if (kTotalBits % kUnitBits == 0) {
       // kTotalBits is a multiple of kUnitBits ==> we can just check for all
       // ones in each unit.
-      for (std::size_t i = 0; i < kUnits; i++) {
+      for (size_t i = 0; i < kUnits; i++) {
         if (units_[i] != all_ones()) return false;
       }
       return true;
@@ -121,7 +122,7 @@ class BitSet {
       // kTotalBits is not a multiple of kUnitBits ==> we need special handling
       // for checking partial filling of the last unit (since not all of its
       // bits are used!)
-      for (std::size_t i = 0; i < kUnits - 1; i++) {
+      for (size_t i = 0; i < kUnits - 1; i++) {
         if (units_[i] != all_ones()) return false;
       }
       return units_[kUnits - 1] == n_ones(kTotalBits % kUnitBits);
@@ -130,20 +131,27 @@ class BitSet {
 
   // Return true if *no* bits are set.
   bool none() const {
-    for (std::size_t i = 0; i < kUnits; i++) {
+    for (size_t i = 0; i < kUnits; i++) {
       if (units_[i] != 0) return false;
     }
     return true;
   }
 
+  // Return a count of how many bits are set.
+  uint32_t count() const {
+    uint32_t count = 0;
+    for (size_t i = 0; i < kUnits; i++) {
+      count += BitCount(units_[i]);
+    }
+    return count;
+  }
+
  private:
   // Given a bit index, return which unit it's stored in.
-  static constexpr std::size_t unit_for(std::size_t bit) {
-    return bit / kUnitBits;
-  }
+  static constexpr size_t unit_for(size_t bit) { return bit / kUnitBits; }
 
   // Given a bit index, return a mask to access that bit within it's unit.
-  static constexpr Uint<kUnitBits> mask_for(std::size_t bit) {
+  static constexpr Uint<kUnitBits> mask_for(size_t bit) {
     return Uint<kUnitBits>{1} << (bit % kUnitBits);
   }
 
@@ -153,7 +161,7 @@ class BitSet {
   }
 
   // Return a value with n bottom bits ones
-  static constexpr Uint<kUnitBits> n_ones(std::size_t n) {
+  static constexpr Uint<kUnitBits> n_ones(size_t n) {
     return n == kUnitBits ? all_ones() : (Uint<kUnitBits>(1) << n) - 1;
   }
 
@@ -161,6 +169,20 @@ class BitSet {
   Uint<kUnitBits> units_[kUnits];
 };
 
+// Zero-size specialization of BitSet.
+// Useful for generic programming.
+// Make a compile time error out of get/set type accesses, and hard-codes
+// queries that do make sense.
+template <>
+class BitSet<0> {
+ public:
+  constexpr BitSet() {}
+
+  bool all() const { return true; }
+  bool none() const { return true; }
+  uint32_t count() const { return 0; }
+};
+
 }  // namespace grpc_core
 
 #endif  // GRPC_CORE_LIB_GPRPP_BITSET_H
index 860bfe4..d673642 100644 (file)
@@ -15,7 +15,7 @@
 #ifndef GRPC_CORE_LIB_GPRPP_CAPTURE_H
 #define GRPC_CORE_LIB_GPRPP_CAPTURE_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include <tuple>
 #include <utility>
diff --git a/src/core/lib/gprpp/chunked_vector.h b/src/core/lib/gprpp/chunked_vector.h
new file mode 100644 (file)
index 0000000..256fa90
--- /dev/null
@@ -0,0 +1,211 @@
+// 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.
+
+#ifndef GRPC_CORE_LIB_GPRPP_CHUNKED_VECTOR_H
+#define GRPC_CORE_LIB_GPRPP_CHUNKED_VECTOR_H
+
+#include <grpc/support/port_platform.h>
+
+#include "src/core/lib/gprpp/arena.h"
+#include "src/core/lib/gprpp/manual_constructor.h"
+
+namespace grpc_core {
+
+// Arena-friendly vector type.
+// This "vector" allocates non-contiguous runs of kChunkSize T's at a time.
+// Expectation is that most usage will fit in one chunk, sometimes two will be
+// needed, and very rarely three. Appending is constant time, calculating the
+// size is O(n_chunks).
+template <typename T, size_t kChunkSize>
+class ChunkedVector {
+ private:
+  // One chunk of allocated memory.
+  struct Chunk {
+    Chunk() = default;
+    Chunk* next = nullptr;
+    size_t count = 0;
+    ManualConstructor<T> data[kChunkSize];
+  };
+
+ public:
+  explicit ChunkedVector(Arena* arena) : arena_(arena) {}
+  template <class Iterator>
+  ChunkedVector(Arena* arena, Iterator begin, Iterator end) : arena_(arena) {
+    for (; begin != end; ++begin) {
+      EmplaceBack(*begin);
+    }
+  }
+  ChunkedVector(const ChunkedVector& other)
+      : ChunkedVector(other.arena_, other.begin(), other.end()) {}
+  ChunkedVector& operator=(ChunkedVector other) {
+    Swap(&other);
+    return *this;
+  }
+  ChunkedVector(ChunkedVector&& other) noexcept
+      : arena_(other.arena_), first_(other.first_), append_(other.append_) {
+    other.first_ = nullptr;
+    other.append_ = nullptr;
+  }
+  ChunkedVector& operator=(ChunkedVector&& other) noexcept {
+    Swap(&other);
+    return *this;
+  }
+  ~ChunkedVector() { Clear(); }
+  void Swap(ChunkedVector* other) {
+    std::swap(other->arena_, arena_);
+    std::swap(other->first_, first_);
+    std::swap(other->append_, append_);
+  }
+
+  Arena* arena() const { return arena_; }
+
+  // Append a new element to the end of the vector.
+  template <typename... Args>
+  T* EmplaceBack(Args&&... args) {
+    auto* p = AppendSlot();
+    p->Init(std::forward<Args>(args)...);
+    return &**p;
+  }
+
+  // Remove the last element and return it.
+  T PopBack() {
+    GPR_ASSERT(append_ != nullptr);
+    if (append_->count == 0) {
+      GPR_ASSERT(first_ != append_);
+      Chunk* chunk = first_;
+      while (chunk->next != append_) {
+        chunk = chunk->next;
+      }
+      append_ = chunk;
+    }
+    const auto last = append_->count - 1;
+    T result = std::move(*append_->data[last]);
+    append_->data[last].Destroy();
+    append_->count = last;
+    return result;
+  }
+
+  void Clear() {
+    Chunk* chunk = first_;
+    while (chunk != nullptr && chunk->count != 0) {
+      for (size_t i = 0; i < chunk->count; i++) {
+        chunk->data[i].Destroy();
+      }
+      chunk->count = 0;
+      chunk = chunk->next;
+    }
+    append_ = first_;
+  }
+
+  // Forward-only iterator.
+  class ForwardIterator {
+   public:
+    ForwardIterator(Chunk* chunk, size_t n) : chunk_(chunk), n_(n) {}
+
+    T& operator*() const { return *chunk_->data[n_]; }
+    T* operator->() const { return &*chunk_->data[n_]; }
+    ForwardIterator& operator++() {
+      ++n_;
+      while (chunk_ != nullptr && n_ == chunk_->count) {
+        chunk_ = chunk_->next;
+        n_ = 0;
+      }
+      return *this;
+    }
+    bool operator==(const ForwardIterator& other) const {
+      return chunk_ == other.chunk_ && n_ == other.n_;
+    }
+    bool operator!=(const ForwardIterator& other) const {
+      return !(*this == other);
+    }
+
+   private:
+    Chunk* chunk_;
+    size_t n_;
+  };
+
+  // Const Forward-only iterator.
+  class ConstForwardIterator {
+   public:
+    ConstForwardIterator(const Chunk* chunk, size_t n) : chunk_(chunk), n_(n) {}
+
+    const T& operator*() const { return *chunk_->data[n_]; }
+    const T* operator->() const { return &*chunk_->data[n_]; }
+    ConstForwardIterator& operator++() {
+      ++n_;
+      while (chunk_ != nullptr && n_ == chunk_->count) {
+        chunk_ = chunk_->next;
+        n_ = 0;
+      }
+      return *this;
+    }
+    bool operator==(const ConstForwardIterator& other) const {
+      return chunk_ == other.chunk_ && n_ == other.n_;
+    }
+    bool operator!=(const ConstForwardIterator& other) const {
+      return !(*this == other);
+    }
+
+   private:
+    const Chunk* chunk_;
+    size_t n_;
+  };
+
+  ForwardIterator begin() {
+    if (first_ != nullptr && first_->count == 0) return end();
+    return ForwardIterator(first_, 0);
+  }
+  ForwardIterator end() { return ForwardIterator(nullptr, 0); }
+
+  ConstForwardIterator begin() const {
+    if (first_ != nullptr && first_->count == 0) return cend();
+    return ConstForwardIterator(first_, 0);
+  }
+  ConstForwardIterator end() const { return ConstForwardIterator(nullptr, 0); }
+
+  ConstForwardIterator cbegin() const { return begin(); }
+  ConstForwardIterator cend() const { return end(); }
+
+  // Count the number of elements in the vector.
+  size_t size() const {
+    size_t n = 0;
+    for (const Chunk* chunk = first_; chunk != nullptr; chunk = chunk->next) {
+      n += chunk->count;
+    }
+    return n;
+  }
+
+ private:
+  ManualConstructor<T>* AppendSlot() {
+    if (append_ == nullptr) {
+      GPR_ASSERT(first_ == nullptr);
+      first_ = arena_->New<Chunk>();
+      append_ = first_;
+    } else if (append_->count == kChunkSize) {
+      if (append_->next == nullptr) {
+        append_->next = arena_->New<Chunk>();
+      }
+      append_ = append_->next;
+    }
+    return &append_->data[append_->count++];
+  }
+
+  Arena* arena_;
+  Chunk* first_ = nullptr;
+  Chunk* append_ = nullptr;
+};
+
+}  // namespace grpc_core
+
+#endif  // GRPC_CORE_LIB_GPRPP_CHUNKED_VECTOR_H
index ad1949f..73fdb1f 100644 (file)
@@ -15,7 +15,7 @@
 #ifndef GRPC_CORE_LIB_GPRPP_CONSTRUCT_DESTRUCT_H
 #define GRPC_CORE_LIB_GPRPP_CONSTRUCT_DESTRUCT_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include <utility>
 
index 1a405d4..55c95b9 100644 (file)
@@ -15,7 +15,7 @@
 #ifndef GRPC_CORE_LIB_GPRPP_MATCH_H
 #define GRPC_CORE_LIB_GPRPP_MATCH_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include "absl/types/variant.h"
 
index 00e24ae..dc0a6ea 100644 (file)
@@ -46,6 +46,12 @@ class DefaultDeleteChar {
 template <typename T>
 using UniquePtr = std::unique_ptr<T, DefaultDeleteChar>;
 
+template <class T>
+T* Zalloc() {
+  static_assert(std::is_trivial<T>::value, "Type should be trivial");
+  return static_cast<T*>(gpr_zalloc(sizeof(T)));
+}
+
 }  // namespace grpc_core
 
 #endif /* GRPC_CORE_LIB_GPRPP_MEMORY_H */
index d2f7be7..c243a8c 100644 (file)
@@ -15,7 +15,7 @@
 #ifndef GRPC_CORE_LIB_GPRPP_OVERLOAD_H
 #define GRPC_CORE_LIB_GPRPP_OVERLOAD_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include <utility>
 
index f13cd40..fa538dc 100644 (file)
@@ -131,8 +131,9 @@ void EncodeUInt32ToBytes(uint32_t v, char* buf) {
 }
 
 uint32_t DecodeUInt32FromBytes(const char* buf) {
-  return buf[0] | (uint32_t(buf[1]) << 8) | (uint32_t(buf[2]) << 16) |
-         (uint32_t(buf[3]) << 24);
+  const unsigned char* ubuf = reinterpret_cast<const unsigned char*>(buf);
+  return ubuf[0] | (uint32_t(ubuf[1]) << 8) | (uint32_t(ubuf[2]) << 16) |
+         (uint32_t(ubuf[3]) << 24);
 }
 
 std::vector<absl::Status> ParseChildren(absl::Cord children) {
@@ -330,7 +331,7 @@ std::string StatusToString(const absl::Status& status) {
 
 namespace internal {
 
-google_rpc_Status* StatusToProto(absl::Status status, upb_arena* arena) {
+google_rpc_Status* StatusToProto(const absl::Status& status, upb_arena* arena) {
   google_rpc_Status* msg = google_rpc_Status_new(arena);
   google_rpc_Status_set_code(msg, int32_t(status.code()));
   google_rpc_Status_set_message(
@@ -402,6 +403,25 @@ absl::Status StatusGetFromPtr(uintptr_t ptr) {
   return *reinterpret_cast<absl::Status*>(&ptr);
 }
 
+uintptr_t StatusAllocHeapPtr(absl::Status s) {
+  if (s.ok()) return kOkStatusPtr;
+  absl::Status* ptr = new absl::Status(s);
+  return reinterpret_cast<uintptr_t>(ptr);
+}
+
+void StatusFreeHeapPtr(uintptr_t ptr) {
+  absl::Status* s = reinterpret_cast<absl::Status*>(ptr);
+  delete s;
+}
+
+absl::Status StatusGetFromHeapPtr(uintptr_t ptr) {
+  if (ptr == kOkStatusPtr) {
+    return absl::OkStatus();
+  } else {
+    return *reinterpret_cast<absl::Status*>(ptr);
+  }
+}
+
 }  // namespace internal
 
 }  // namespace grpc_core
index d06f32c..a670432 100644 (file)
@@ -153,7 +153,7 @@ namespace internal {
 
 /// Builds a upb message, google_rpc_Status from a status
 /// This is for internal implementation & test only
-google_rpc_Status* StatusToProto(absl::Status status,
+google_rpc_Status* StatusToProto(const absl::Status& status,
                                  upb_arena* arena) GRPC_MUST_USE_RESULT;
 
 /// Builds a status from a upb message, google_rpc_Status
@@ -176,6 +176,17 @@ void StatusFreePtr(uintptr_t ptr);
 /// This shouldn't be used except migration purpose.
 absl::Status StatusGetFromPtr(uintptr_t ptr);
 
+/// Returns ptr that is allocated in the heap memory and the given status is
+/// copied into. This ptr can be used to get Status later and should be
+/// freed by StatusFreeHeapPtr. This can be 0 in case of OkStatus.
+uintptr_t StatusAllocHeapPtr(absl::Status s);
+
+/// Frees the allocated status at heap ptr.
+void StatusFreeHeapPtr(uintptr_t ptr);
+
+/// Get the status from a heap ptr.
+absl::Status StatusGetFromHeapPtr(uintptr_t ptr);
+
 }  // namespace internal
 
 }  // namespace grpc_core
index be1222f..b91b0c0 100644 (file)
@@ -15,7 +15,7 @@
 #ifndef GRPC_CORE_LIB_GPRPP_TABLE_H
 #define GRPC_CORE_LIB_GPRPP_TABLE_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include <utility>
 
@@ -290,6 +290,15 @@ class Table {
     }
   }
 
+  // Iterate through each set field in the table
+  template <typename F>
+  void ForEach(F f) const {
+    ForEachImpl(std::move(f), absl::make_index_sequence<sizeof...(Ts)>());
+  }
+
+  // Count the number of set fields in the table
+  size_t count() const { return present_bits_.count(); }
+
  private:
   // Bit field for which elements of the table are set (true) or un-set (false,
   // the default) -- one bit for each type in Ts.
@@ -354,11 +363,19 @@ class Table {
     }
   }
 
+  // Call (*f)(value) if that value is in the table.
+  template <size_t I, typename F>
+  void CallIf(F* f) const {
+    if (auto* p = get<I>()) {
+      (*f)(*p);
+    }
+  }
+
   // For each field (element I=0, 1, ...) if that field is present, call its
   // destructor.
   template <size_t... I>
   void Destruct(absl::index_sequence<I...>) {
-    table_detail::do_these_things(
+    table_detail::do_these_things<int>(
         {(table_detail::DestructIfNotNull(get<I>()), 1)...});
   }
 
@@ -366,17 +383,23 @@ class Table {
   // or_clear as per CopyIf().
   template <bool or_clear, size_t... I>
   void Copy(absl::index_sequence<I...>, const Table& rhs) {
-    table_detail::do_these_things({(CopyIf<or_clear, I>(rhs), 1)...});
+    table_detail::do_these_things<int>({(CopyIf<or_clear, I>(rhs), 1)...});
   }
 
   // For each field (element I=0, 1, ...) move that field into this table -
   // or_clear as per MoveIf().
   template <bool or_clear, size_t... I>
   void Move(absl::index_sequence<I...>, Table&& rhs) {
-    table_detail::do_these_things(
+    table_detail::do_these_things<int>(
         {(MoveIf<or_clear, I>(std::forward<Table>(rhs)), 1)...});
   }
 
+  // For each field (element I=0, 1, ...) if that field is present, call f.
+  template <typename F, size_t... I>
+  void ForEachImpl(F f, absl::index_sequence<I...>) const {
+    table_detail::do_these_things<int>({(CallIf<I>(&f), 1)...});
+  }
+
   // Bit field indicating which elements are set.
   GPR_NO_UNIQUE_ADDRESS PresentBits present_bits_;
   // The memory to store the elements themselves.
index 722cd57..ab4431e 100644 (file)
@@ -25,6 +25,7 @@
 #include <string>
 
 #include "absl/strings/str_format.h"
+#include "absl/strings/string_view.h"
 
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include "src/core/lib/iomgr/tcp_client.h"
 #include "src/core/lib/slice/slice_internal.h"
 
-struct internal_request {
-  grpc_slice request_text;
-  grpc_http_parser parser;
-  grpc_resolved_addresses* addresses;
-  size_t next_address;
-  grpc_endpoint* ep;
-  grpc_resource_quota* resource_quota;
-  char* host;
-  char* ssl_host_override;
-  grpc_millis deadline;
-  int have_read_byte;
-  const grpc_httpcli_handshaker* handshaker;
-  grpc_closure* on_done;
-  grpc_httpcli_context* context;
-  grpc_polling_entity* pollent;
-  grpc_iomgr_object iomgr_obj;
-  grpc_slice_buffer incoming;
-  grpc_slice_buffer outgoing;
-  grpc_closure on_read;
-  grpc_closure done_write;
-  grpc_closure connected;
-  grpc_error_handle overall_error;
-};
-static grpc_httpcli_get_override g_get_override = nullptr;
-static grpc_httpcli_post_override g_post_override = nullptr;
-
-static void plaintext_handshake(void* arg, grpc_endpoint* endpoint,
-                                const char* /*host*/, grpc_millis /*deadline*/,
-                                void (*on_done)(void* arg,
-                                                grpc_endpoint* endpoint)) {
-  on_done(arg, endpoint);
-}
-
-const grpc_httpcli_handshaker grpc_httpcli_plaintext = {"http",
-                                                        plaintext_handshake};
+namespace grpc_core {
+namespace {
+
+class InternalRequest {
+ public:
+  InternalRequest(const grpc_slice& request_text,
+                  grpc_httpcli_response* response,
+                  grpc_resource_quota* resource_quota, absl::string_view host,
+                  absl::string_view ssl_host_override, grpc_millis deadline,
+                  const grpc_httpcli_handshaker* handshaker,
+                  grpc_closure* on_done, grpc_httpcli_context* context,
+                  grpc_polling_entity* pollent, const char* name)
+      : request_text_(request_text),
+        resource_quota_(resource_quota),
+        host_(host),
+        ssl_host_override_(ssl_host_override),
+        deadline_(deadline),
+        handshaker_(handshaker),
+        on_done_(on_done),
+        context_(context),
+        pollent_(pollent) {
+    grpc_http_parser_init(&parser_, GRPC_HTTP_RESPONSE, response);
+    grpc_slice_buffer_init(&incoming_);
+    grpc_slice_buffer_init(&outgoing_);
+    grpc_iomgr_register_object(&iomgr_obj_, name);
+
+    GRPC_CLOSURE_INIT(&on_read_, OnRead, this, grpc_schedule_on_exec_ctx);
+    GRPC_CLOSURE_INIT(&done_write_, DoneWrite, this, grpc_schedule_on_exec_ctx);
+    GPR_ASSERT(pollent);
+    grpc_polling_entity_add_to_pollset_set(pollent_, context->pollset_set);
+    grpc_resolve_address(
+        host_.c_str(), handshaker_->default_port, context_->pollset_set,
+        GRPC_CLOSURE_CREATE(OnResolved, this, grpc_schedule_on_exec_ctx),
+        &addresses_);
+  }
 
-void grpc_httpcli_context_init(grpc_httpcli_context* context) {
-  context->pollset_set = grpc_pollset_set_create();
-}
+  ~InternalRequest() {
+    grpc_http_parser_destroy(&parser_);
+    if (addresses_ != nullptr) {
+      grpc_resolved_addresses_destroy(addresses_);
+    }
+    if (ep_ != nullptr) {
+      grpc_endpoint_destroy(ep_);
+    }
+    grpc_slice_unref_internal(request_text_);
+    grpc_iomgr_unregister_object(&iomgr_obj_);
+    grpc_slice_buffer_destroy_internal(&incoming_);
+    grpc_slice_buffer_destroy_internal(&outgoing_);
+    GRPC_ERROR_UNREF(overall_error_);
+    grpc_resource_quota_unref_internal(resource_quota_);
+  }
 
-void grpc_httpcli_context_destroy(grpc_httpcli_context* context) {
-  grpc_pollset_set_destroy(context->pollset_set);
-}
+ private:
+  void Finish(grpc_error_handle error) {
+    grpc_polling_entity_del_from_pollset_set(pollent_, context_->pollset_set);
+    grpc_core::ExecCtx::Run(DEBUG_LOCATION, on_done_, error);
+    delete this;
+  }
 
-static void next_address(internal_request* req, grpc_error_handle due_to_error);
+  void AppendError(grpc_error_handle error) {
+    if (overall_error_ == GRPC_ERROR_NONE) {
+      overall_error_ =
+          GRPC_ERROR_CREATE_FROM_STATIC_STRING("Failed HTTP/1 client request");
+    }
+    grpc_resolved_address* addr = &addresses_->addrs[next_address_ - 1];
+    std::string addr_text = grpc_sockaddr_to_uri(addr);
+    overall_error_ = grpc_error_add_child(
+        overall_error_,
+        grpc_error_set_str(error, GRPC_ERROR_STR_TARGET_ADDRESS, addr_text));
+  }
 
-static void finish(internal_request* req, grpc_error_handle error) {
-  grpc_polling_entity_del_from_pollset_set(req->pollent,
-                                           req->context->pollset_set);
-  grpc_core::ExecCtx::Run(DEBUG_LOCATION, req->on_done, error);
-  grpc_http_parser_destroy(&req->parser);
-  if (req->addresses != nullptr) {
-    grpc_resolved_addresses_destroy(req->addresses);
+  void DoRead() {
+    grpc_endpoint_read(ep_, &incoming_, &on_read_, /*urgent=*/true);
   }
-  if (req->ep != nullptr) {
-    grpc_endpoint_destroy(req->ep);
+
+  static void OnRead(void* user_data, grpc_error_handle error) {
+    InternalRequest* req = static_cast<InternalRequest*>(user_data);
+    req->OnReadInternal(error);
   }
-  grpc_slice_unref_internal(req->request_text);
-  gpr_free(req->host);
-  gpr_free(req->ssl_host_override);
-  grpc_iomgr_unregister_object(&req->iomgr_obj);
-  grpc_slice_buffer_destroy_internal(&req->incoming);
-  grpc_slice_buffer_destroy_internal(&req->outgoing);
-  GRPC_ERROR_UNREF(req->overall_error);
-  grpc_resource_quota_unref_internal(req->resource_quota);
-  gpr_free(req);
-}
 
-static void append_error(internal_request* req, grpc_error_handle error) {
-  if (req->overall_error == GRPC_ERROR_NONE) {
-    req->overall_error =
-        GRPC_ERROR_CREATE_FROM_STATIC_STRING("Failed HTTP/1 client request");
+  void OnReadInternal(grpc_error_handle error) {
+    size_t i;
+
+    for (i = 0; i < incoming_.count; i++) {
+      if (GRPC_SLICE_LENGTH(incoming_.slices[i])) {
+        have_read_byte_ = 1;
+        grpc_error_handle err =
+            grpc_http_parser_parse(&parser_, incoming_.slices[i], nullptr);
+        if (err != GRPC_ERROR_NONE) {
+          Finish(err);
+          return;
+        }
+      }
+    }
+
+    if (error == GRPC_ERROR_NONE) {
+      DoRead();
+    } else if (!have_read_byte_) {
+      NextAddress(GRPC_ERROR_REF(error));
+    } else {
+      Finish(grpc_http_parser_eof(&parser_));
+    }
   }
-  grpc_resolved_address* addr = &req->addresses->addrs[req->next_address - 1];
-  std::string addr_text = grpc_sockaddr_to_uri(addr);
-  req->overall_error = grpc_error_add_child(
-      req->overall_error,
-      grpc_error_set_str(error, GRPC_ERROR_STR_TARGET_ADDRESS,
-                         grpc_slice_from_cpp_string(std::move(addr_text))));
-}
 
-static void do_read(internal_request* req) {
-  grpc_endpoint_read(req->ep, &req->incoming, &req->on_read, /*urgent=*/true);
-}
+  void OnWritten() { DoRead(); }
 
-static void on_read(void* user_data, grpc_error_handle error) {
-  internal_request* req = static_cast<internal_request*>(user_data);
-  size_t i;
-
-  for (i = 0; i < req->incoming.count; i++) {
-    if (GRPC_SLICE_LENGTH(req->incoming.slices[i])) {
-      req->have_read_byte = 1;
-      grpc_error_handle err = grpc_http_parser_parse(
-          &req->parser, req->incoming.slices[i], nullptr);
-      if (err != GRPC_ERROR_NONE) {
-        finish(req, err);
-        return;
-      }
+  static void DoneWrite(void* arg, grpc_error_handle error) {
+    InternalRequest* req = static_cast<InternalRequest*>(arg);
+    if (error == GRPC_ERROR_NONE) {
+      req->OnWritten();
+    } else {
+      req->NextAddress(GRPC_ERROR_REF(error));
     }
   }
 
-  if (error == GRPC_ERROR_NONE) {
-    do_read(req);
-  } else if (!req->have_read_byte) {
-    next_address(req, GRPC_ERROR_REF(error));
-  } else {
-    finish(req, grpc_http_parser_eof(&req->parser));
+  void StartWrite() {
+    grpc_slice_ref_internal(request_text_);
+    grpc_slice_buffer_add(&outgoing_, request_text_);
+    grpc_endpoint_write(ep_, &outgoing_, &done_write_, nullptr);
   }
-}
 
-static void on_written(internal_request* req) { do_read(req); }
+  static void OnHandshakeDone(void* arg, grpc_endpoint* ep) {
+    InternalRequest* req = static_cast<InternalRequest*>(arg);
 
-static void done_write(void* arg, grpc_error_handle error) {
-  internal_request* req = static_cast<internal_request*>(arg);
-  if (error == GRPC_ERROR_NONE) {
-    on_written(req);
-  } else {
-    next_address(req, GRPC_ERROR_REF(error));
+    if (!ep) {
+      req->NextAddress(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+          "Unexplained handshake failure"));
+      return;
+    }
+
+    req->ep_ = ep;
+    req->StartWrite();
   }
-}
 
-static void start_write(internal_request* req) {
-  grpc_slice_ref_internal(req->request_text);
-  grpc_slice_buffer_add(&req->outgoing, req->request_text);
-  grpc_endpoint_write(req->ep, &req->outgoing, &req->done_write, nullptr);
-}
+  static void OnConnected(void* arg, grpc_error_handle error) {
+    InternalRequest* req = static_cast<InternalRequest*>(arg);
 
-static void on_handshake_done(void* arg, grpc_endpoint* ep) {
-  internal_request* req = static_cast<internal_request*>(arg);
+    if (!req->ep_) {
+      req->NextAddress(GRPC_ERROR_REF(error));
+      return;
+    }
+    req->handshaker_->handshake(req, req->ep_,
+                                req->ssl_host_override_.empty()
+                                    ? req->host_.c_str()
+                                    : req->ssl_host_override_.c_str(),
+                                req->deadline_, OnHandshakeDone);
+  }
 
-  if (!ep) {
-    next_address(req, GRPC_ERROR_CREATE_FROM_STATIC_STRING(
-                          "Unexplained handshake failure"));
-    return;
+  void NextAddress(grpc_error_handle error) {
+    grpc_resolved_address* addr;
+    if (error != GRPC_ERROR_NONE) {
+      AppendError(error);
+    }
+    if (next_address_ == addresses_->naddrs) {
+      Finish(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
+          "Failed HTTP requests to all targets", &overall_error_, 1));
+      return;
+    }
+    addr = &addresses_->addrs[next_address_++];
+    GRPC_CLOSURE_INIT(&connected_, OnConnected, this,
+                      grpc_schedule_on_exec_ctx);
+    grpc_tcp_client_connect(&connected_, &ep_,
+                            grpc_slice_allocator_create(
+                                resource_quota_, grpc_sockaddr_to_uri(addr)),
+                            context_->pollset_set, nullptr, addr, deadline_);
   }
 
-  req->ep = ep;
-  start_write(req);
-}
+  static void OnResolved(void* arg, grpc_error_handle error) {
+    InternalRequest* req = static_cast<InternalRequest*>(arg);
+    if (error != GRPC_ERROR_NONE) {
+      req->Finish(GRPC_ERROR_REF(error));
+      return;
+    }
+    req->next_address_ = 0;
+    req->NextAddress(GRPC_ERROR_NONE);
+  }
 
-static void on_connected(void* arg, grpc_error_handle error) {
-  internal_request* req = static_cast<internal_request*>(arg);
+  grpc_slice request_text_;
+  grpc_http_parser parser_;
+  grpc_resolved_addresses* addresses_ = nullptr;
+  size_t next_address_ = 0;
+  grpc_endpoint* ep_ = nullptr;
+  grpc_resource_quota* resource_quota_;
+  std::string host_;
+  std::string ssl_host_override_;
+  grpc_millis deadline_;
+  int have_read_byte_ = 0;
+  const grpc_httpcli_handshaker* handshaker_;
+  grpc_closure* on_done_;
+  grpc_httpcli_context* context_;
+  grpc_polling_entity* pollent_;
+  grpc_iomgr_object iomgr_obj_;
+  grpc_slice_buffer incoming_;
+  grpc_slice_buffer outgoing_;
+  grpc_closure on_read_;
+  grpc_closure done_write_;
+  grpc_closure connected_;
+  grpc_error_handle overall_error_ = GRPC_ERROR_NONE;
+};
 
-  if (!req->ep) {
-    next_address(req, GRPC_ERROR_REF(error));
-    return;
-  }
-  req->handshaker->handshake(
-      req, req->ep, req->ssl_host_override ? req->ssl_host_override : req->host,
-      req->deadline, on_handshake_done);
+}  // namespace
+}  // namespace grpc_core
+
+static grpc_httpcli_get_override g_get_override = nullptr;
+static grpc_httpcli_post_override g_post_override = nullptr;
+
+static void plaintext_handshake(void* arg, grpc_endpoint* endpoint,
+                                const char* /*host*/, grpc_millis /*deadline*/,
+                                void (*on_done)(void* arg,
+                                                grpc_endpoint* endpoint)) {
+  on_done(arg, endpoint);
 }
 
-static void next_address(internal_request* req, grpc_error_handle error) {
-  grpc_resolved_address* addr;
-  if (error != GRPC_ERROR_NONE) {
-    append_error(req, error);
-  }
-  if (req->next_address == req->addresses->naddrs) {
-    finish(req,
-           GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
-               "Failed HTTP requests to all targets", &req->overall_error, 1));
-    return;
-  }
-  addr = &req->addresses->addrs[req->next_address++];
-  GRPC_CLOSURE_INIT(&req->connected, on_connected, req,
-                    grpc_schedule_on_exec_ctx);
-  grpc_tcp_client_connect(&req->connected, &req->ep,
-                          grpc_slice_allocator_create(
-                              req->resource_quota, grpc_sockaddr_to_uri(addr)),
-                          req->context->pollset_set, nullptr, addr,
-                          req->deadline);
+const grpc_httpcli_handshaker grpc_httpcli_plaintext = {"http",
+                                                        plaintext_handshake};
+
+void grpc_httpcli_context_init(grpc_httpcli_context* context) {
+  context->pollset_set = grpc_pollset_set_create();
 }
 
-static void on_resolved(void* arg, grpc_error_handle error) {
-  internal_request* req = static_cast<internal_request*>(arg);
-  if (error != GRPC_ERROR_NONE) {
-    finish(req, GRPC_ERROR_REF(error));
-    return;
-  }
-  req->next_address = 0;
-  next_address(req, GRPC_ERROR_NONE);
+void grpc_httpcli_context_destroy(grpc_httpcli_context* context) {
+  grpc_pollset_set_destroy(context->pollset_set);
 }
 
 static void internal_request_begin(grpc_httpcli_context* context,
@@ -232,35 +274,11 @@ static void internal_request_begin(grpc_httpcli_context* context,
                                    grpc_httpcli_response* response,
                                    const char* name,
                                    const grpc_slice& request_text) {
-  internal_request* req =
-      static_cast<internal_request*>(gpr_malloc(sizeof(internal_request)));
-  memset(req, 0, sizeof(*req));
-  req->request_text = request_text;
-  grpc_http_parser_init(&req->parser, GRPC_HTTP_RESPONSE, response);
-  req->on_done = on_done;
-  req->deadline = deadline;
-  req->handshaker =
-      request->handshaker ? request->handshaker : &grpc_httpcli_plaintext;
-  req->context = context;
-  req->pollent = pollent;
-  req->overall_error = GRPC_ERROR_NONE;
-  req->resource_quota = resource_quota;
-  GRPC_CLOSURE_INIT(&req->on_read, on_read, req, grpc_schedule_on_exec_ctx);
-  GRPC_CLOSURE_INIT(&req->done_write, done_write, req,
-                    grpc_schedule_on_exec_ctx);
-  grpc_slice_buffer_init(&req->incoming);
-  grpc_slice_buffer_init(&req->outgoing);
-  grpc_iomgr_register_object(&req->iomgr_obj, name);
-  req->host = gpr_strdup(request->host);
-  req->ssl_host_override = gpr_strdup(request->ssl_host_override);
-
-  GPR_ASSERT(pollent);
-  grpc_polling_entity_add_to_pollset_set(req->pollent,
-                                         req->context->pollset_set);
-  grpc_resolve_address(
-      request->host, req->handshaker->default_port, req->context->pollset_set,
-      GRPC_CLOSURE_CREATE(on_resolved, req, grpc_schedule_on_exec_ctx),
-      &req->addresses);
+  new grpc_core::InternalRequest(
+      request_text, response, resource_quota, request->host,
+      request->ssl_host_override, deadline,
+      request->handshaker ? request->handshaker : &grpc_httpcli_plaintext,
+      on_done, context, pollent, name);
 }
 
 void grpc_httpcli_get(grpc_httpcli_context* context,
index c47a017..d88ebdb 100644 (file)
@@ -221,7 +221,7 @@ static grpc_error_handle add_header(grpc_http_parser* parser) {
 
   if (*hdr_count == parser->hdr_capacity) {
     parser->hdr_capacity =
-        GPR_MAX(parser->hdr_capacity + 1, parser->hdr_capacity * 3 / 2);
+        std::max(parser->hdr_capacity + 1, parser->hdr_capacity * 3 / 2);
     *hdrs = static_cast<grpc_http_header*>(
         gpr_realloc(*hdrs, parser->hdr_capacity * sizeof(**hdrs)));
   }
@@ -280,7 +280,7 @@ static grpc_error_handle addbyte_body(grpc_http_parser* parser, uint8_t byte) {
   }
 
   if (*body_length == parser->body_capacity) {
-    parser->body_capacity = GPR_MAX(8, parser->body_capacity * 3 / 2);
+    parser->body_capacity = std::max(size_t(8), parser->body_capacity * 3 / 2);
     *body = static_cast<char*>(gpr_realloc(*body, parser->body_capacity));
   }
   (*body)[*body_length] = static_cast<char>(byte);
index 945e835..7137bca 100644 (file)
@@ -33,18 +33,20 @@ DebugOnlyTraceFlag grpc_call_combiner_trace(false, "call_combiner");
 
 namespace {
 
+// grpc_error LSB can be used
+constexpr static intptr_t kErrorBit = 1;
+
 grpc_error_handle DecodeCancelStateError(gpr_atm cancel_state) {
-  if (cancel_state & 1) {
-    return reinterpret_cast<grpc_error_handle>(cancel_state &
-                                               ~static_cast<gpr_atm>(1));
+  if (cancel_state & kErrorBit) {
+#ifdef GRPC_ERROR_IS_ABSEIL_STATUS
+    return internal::StatusGetFromHeapPtr(cancel_state & ~kErrorBit);
+#else
+    return reinterpret_cast<grpc_error_handle>(cancel_state & ~kErrorBit);
+#endif
   }
   return GRPC_ERROR_NONE;
 }
 
-gpr_atm EncodeCancelStateError(grpc_error_handle error) {
-  return static_cast<gpr_atm>(1) | reinterpret_cast<gpr_atm>(error);
-}
-
 }  // namespace
 
 CallCombiner::CallCombiner() {
@@ -57,7 +59,14 @@ CallCombiner::CallCombiner() {
 }
 
 CallCombiner::~CallCombiner() {
-  GRPC_ERROR_UNREF(DecodeCancelStateError(cancel_state_));
+  if (cancel_state_ & kErrorBit) {
+#ifdef GRPC_ERROR_IS_ABSEIL_STATUS
+    internal::StatusFreeHeapPtr(cancel_state_ & ~kErrorBit);
+#else
+    GRPC_ERROR_UNREF(reinterpret_cast<grpc_error_handle>(
+        cancel_state_ & ~static_cast<gpr_atm>(kErrorBit)));
+#endif
+  }
 }
 
 #ifdef GRPC_TSAN_ENABLED
@@ -235,15 +244,24 @@ void CallCombiner::SetNotifyOnCancel(grpc_closure* closure) {
 
 void CallCombiner::Cancel(grpc_error_handle error) {
   GRPC_STATS_INC_CALL_COMBINER_CANCELLED();
+#ifdef GRPC_ERROR_IS_ABSEIL_STATUS
+  intptr_t status_ptr = internal::StatusAllocHeapPtr(error);
+  gpr_atm new_state = kErrorBit | status_ptr;
+#else
+  gpr_atm new_state = kErrorBit | reinterpret_cast<gpr_atm>(error);
+#endif
   while (true) {
     gpr_atm original_state = gpr_atm_acq_load(&cancel_state_);
     grpc_error_handle original_error = DecodeCancelStateError(original_state);
     if (original_error != GRPC_ERROR_NONE) {
+#ifdef GRPC_ERROR_IS_ABSEIL_STATUS
+      internal::StatusFreeHeapPtr(status_ptr);
+#else
       GRPC_ERROR_UNREF(error);
+#endif
       break;
     }
-    if (gpr_atm_full_cas(&cancel_state_, original_state,
-                         EncodeCancelStateError(error))) {
+    if (gpr_atm_full_cas(&cancel_state_, original_state, new_state)) {
       if (original_state != 0) {
         grpc_closure* notify_on_cancel =
             reinterpret_cast<grpc_closure*>(original_state);
index 6835313..1b5add8 100644 (file)
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 
-#include "src/core/lib/debug/stats.h"
 #include "src/core/lib/gprpp/mpscq.h"
 #include "src/core/lib/iomgr/executor.h"
-#include "src/core/lib/iomgr/iomgr.h"
-#include "src/core/lib/profiling/timers.h"
+#include "src/core/lib/iomgr/iomgr_internal.h"
 
 grpc_core::DebugOnlyTraceFlag grpc_combiner_trace(false, "combiner");
 
@@ -128,15 +126,11 @@ static void push_first_on_exec_ctx(grpc_core::Combiner* lock) {
 
 static void combiner_exec(grpc_core::Combiner* lock, grpc_closure* cl,
                           grpc_error_handle error) {
-  GPR_TIMER_SCOPE("combiner.execute", 0);
-  GRPC_STATS_INC_COMBINER_LOCKS_SCHEDULED_ITEMS();
   gpr_atm last = gpr_atm_full_fetch_add(&lock->state, STATE_ELEM_COUNT_LOW_BIT);
   GRPC_COMBINER_TRACE(gpr_log(GPR_INFO,
                               "C:%p grpc_combiner_execute c=%p last=%" PRIdPTR,
                               lock, cl, last));
   if (last == 1) {
-    GRPC_STATS_INC_COMBINER_LOCKS_INITIATED();
-    GPR_TIMER_MARK("combiner.initiated", 0);
     gpr_atm_no_barrier_store(
         &lock->initiating_exec_ctx_or_null,
         reinterpret_cast<gpr_atm>(grpc_core::ExecCtx::Get()));
@@ -175,14 +169,12 @@ static void offload(void* arg, grpc_error_handle /*error*/) {
 }
 
 static void queue_offload(grpc_core::Combiner* lock) {
-  GRPC_STATS_INC_COMBINER_LOCKS_OFFLOADED();
   move_next();
   GRPC_COMBINER_TRACE(gpr_log(GPR_INFO, "C:%p queue_offload", lock));
   grpc_core::Executor::Run(&lock->offload, GRPC_ERROR_NONE);
 }
 
 bool grpc_combiner_continue_exec_ctx() {
-  GPR_TIMER_SCOPE("combiner.continue_exec_ctx", 0);
   grpc_core::Combiner* lock =
       grpc_core::ExecCtx::Get()->combiner_data()->active_combiner;
   if (lock == nullptr) {
@@ -207,9 +199,8 @@ bool grpc_combiner_continue_exec_ctx() {
   // 3. the current thread is not a worker for any background poller
   // 4. the DEFAULT executor is threaded
   if (contended && grpc_core::ExecCtx::Get()->IsReadyToFinish() &&
-      !grpc_iomgr_is_any_background_poller_thread() &&
+      !grpc_iomgr_platform_is_any_background_poller_thread() &&
       grpc_core::Executor::IsThreadedDefault()) {
-    GPR_TIMER_MARK("offload_from_finished_exec_ctx", 0);
     // this execution context wants to move on: schedule remaining work to be
     // picked up on the executor
     queue_offload(lock);
@@ -226,11 +217,9 @@ bool grpc_combiner_continue_exec_ctx() {
     if (n == nullptr) {
       // queue is in an inconsistent state: use this as a cue that we should
       // go off and do something else for a while (and come back later)
-      GPR_TIMER_MARK("delay_busy", 0);
       queue_offload(lock);
       return true;
     }
-    GPR_TIMER_SCOPE("combiner.exec1", 0);
     grpc_closure* cl = reinterpret_cast<grpc_closure*>(n);
     grpc_error_handle cl_err = cl->error_data.error;
 #ifndef NDEBUG
@@ -244,7 +233,6 @@ bool grpc_combiner_continue_exec_ctx() {
     grpc_closure_list_init(&lock->final_list);
     int loops = 0;
     while (c != nullptr) {
-      GPR_TIMER_SCOPE("combiner.exec_1final", 0);
       GRPC_COMBINER_TRACE(
           gpr_log(GPR_INFO, "C:%p execute_final[%d] c=%p", lock, loops, c));
       grpc_closure* next = c->next_data.next;
@@ -258,7 +246,6 @@ bool grpc_combiner_continue_exec_ctx() {
     }
   }
 
-  GPR_TIMER_MARK("unref", 0);
   move_next();
   lock->time_to_execute_final_list = false;
   gpr_atm old_state =
@@ -305,13 +292,10 @@ static void combiner_finally_exec(grpc_core::Combiner* lock,
                                   grpc_closure* closure,
                                   grpc_error_handle error) {
   GPR_ASSERT(lock != nullptr);
-  GPR_TIMER_SCOPE("combiner.execute_finally", 0);
-  GRPC_STATS_INC_COMBINER_LOCKS_SCHEDULED_FINAL_ITEMS();
   GRPC_COMBINER_TRACE(gpr_log(
       GPR_INFO, "C:%p grpc_combiner_execute_finally c=%p; ac=%p", lock, closure,
       grpc_core::ExecCtx::Get()->combiner_data()->active_combiner));
   if (grpc_core::ExecCtx::Get()->combiner_data()->active_combiner != lock) {
-    GPR_TIMER_MARK("slowpath", 0);
     // Using error_data.scratch to store the combiner so that it can be accessed
     // in enqueue_finally.
     closure->error_data.scratch = reinterpret_cast<uintptr_t>(lock);
@@ -327,9 +311,10 @@ static void combiner_finally_exec(grpc_core::Combiner* lock,
 
 static void enqueue_finally(void* closure, grpc_error_handle error) {
   grpc_closure* cl = static_cast<grpc_closure*>(closure);
-  combiner_finally_exec(
-      reinterpret_cast<grpc_core::Combiner*>(cl->error_data.scratch), cl,
-      GRPC_ERROR_REF(error));
+  grpc_core::Combiner* lock =
+      reinterpret_cast<grpc_core::Combiner*>(cl->error_data.scratch);
+  cl->error_data.scratch = 0;
+  combiner_finally_exec(lock, cl, GRPC_ERROR_REF(error));
 }
 
 namespace grpc_core {
index 0cc341b..224e276 100644 (file)
@@ -110,8 +110,7 @@ static grpc_error_handle CFStreamAnnotateError(grpc_error_handle src_error,
   return grpc_error_set_str(
       grpc_error_set_int(src_error, GRPC_ERROR_INT_GRPC_STATUS,
                          GRPC_STATUS_UNAVAILABLE),
-      GRPC_ERROR_STR_TARGET_ADDRESS,
-      grpc_slice_from_copied_string(ep->peer_string.c_str()));
+      GRPC_ERROR_STR_TARGET_ADDRESS, ep->peer_string);
 }
 
 static void CallReadCb(CFStreamEndpoint* ep, grpc_error_handle error) {
@@ -150,7 +149,7 @@ static void CallWriteCb(CFStreamEndpoint* ep, grpc_error_handle error) {
 static void ReadAction(void* arg, grpc_error_handle error) {
   CFStreamEndpoint* ep = static_cast<CFStreamEndpoint*>(arg);
   GPR_ASSERT(ep->read_cb != nullptr);
-  if (error) {
+  if (error != GRPC_ERROR_NONE) {
     grpc_slice_buffer_reset_and_unref_internal(ep->read_slices);
     CallReadCb(ep, GRPC_ERROR_REF(error));
     EP_UNREF(ep, "read");
@@ -192,7 +191,7 @@ static void ReadAction(void* arg, grpc_error_handle error) {
 static void WriteAction(void* arg, grpc_error_handle error) {
   CFStreamEndpoint* ep = static_cast<CFStreamEndpoint*>(arg);
   GPR_ASSERT(ep->write_cb != nullptr);
-  if (error) {
+  if (error != GRPC_ERROR_NONE) {
     grpc_slice_buffer_reset_and_unref_internal(ep->write_slices);
     CallWriteCb(ep, GRPC_ERROR_REF(error));
     EP_UNREF(ep, "write");
@@ -287,13 +286,15 @@ static void CFStreamWrite(grpc_endpoint* ep, grpc_slice_buffer* slices,
 void CFStreamShutdown(grpc_endpoint* ep, grpc_error_handle why) {
   CFStreamEndpoint* ep_impl = reinterpret_cast<CFStreamEndpoint*>(ep);
   if (grpc_tcp_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "CFStream endpoint:%p shutdown (%p)", ep_impl, why);
+    gpr_log(GPR_DEBUG, "CFStream endpoint:%p shutdown (%s)", ep_impl,
+            grpc_error_std_string(why).c_str());
   }
   CFReadStreamClose(ep_impl->read_stream);
   CFWriteStreamClose(ep_impl->write_stream);
   ep_impl->stream_sync->Shutdown(why);
   if (grpc_tcp_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "CFStream endpoint:%p shutdown DONE (%p)", ep_impl, why);
+    gpr_log(GPR_DEBUG, "CFStream endpoint:%p shutdown DONE (%s)", ep_impl,
+            grpc_error_std_string(why).c_str());
   }
 }
 
index c47c792..2bf0d72 100644 (file)
@@ -22,7 +22,7 @@
 #include <inttypes.h>
 #include <string.h>
 
-#include <grpc/status.h>
+#include <grpc/impl/codegen/status.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
@@ -34,8 +34,8 @@
 #include "src/core/lib/debug/trace.h"
 #include "src/core/lib/gpr/useful.h"
 #include "src/core/lib/iomgr/error_internal.h"
-#include "src/core/lib/profiling/timers.h"
 #include "src/core/lib/slice/slice_internal.h"
+#include "src/core/lib/slice/slice_utils.h"
 
 grpc_core::DebugOnlyTraceFlag grpc_trace_error_refcount(false,
                                                         "error_refcount");
@@ -65,7 +65,7 @@ absl::Status grpc_status_create(absl::StatusCode code, absl::string_view msg,
   return s;
 }
 
-std::string grpc_error_std_string(const absl::Status& error) {
+std::string grpc_error_std_string(absl::Status error) {
   return grpc_core::StatusToString(error);
 }
 
@@ -87,14 +87,20 @@ absl::Status grpc_wsa_error(const grpc_core::DebugLocation& location, int err,
   char* utf8_message = gpr_format_message(err);
   absl::Status s =
       StatusCreate(absl::StatusCode::kUnknown, "WSA Error", location, {});
-  StatusSetInt(&s, StatusIntProperty::WSA_ERROR, err);
-  StatusSetStr(&s, StatusStrProperty::OS_ERROR, utf8_message);
-  StatusSetStr(&s, StatusStrProperty::SYSCALL, call_name);
+  StatusSetInt(&s, grpc_core::StatusIntProperty::kWsaError, err);
+  StatusSetStr(&s, grpc_core::StatusStrProperty::kOsError, utf8_message);
+  StatusSetStr(&s, grpc_core::StatusStrProperty::kSyscall, call_name);
+  return s;
 }
 #endif
 
 grpc_error_handle grpc_error_set_int(grpc_error_handle src,
                                      grpc_error_ints which, intptr_t value) {
+  if (src == GRPC_ERROR_NONE) {
+    src = absl::UnknownError("");
+    StatusSetInt(&src, grpc_core::StatusIntProperty::kRpcStatus,
+                 GRPC_STATUS_OK);
+  }
   grpc_core::StatusSetInt(
       &src, static_cast<grpc_core::StatusIntProperty>(which), value);
   return src;
@@ -108,36 +114,100 @@ bool grpc_error_get_int(grpc_error_handle error, grpc_error_ints which,
     *p = *value;
     return true;
   } else {
+    // TODO(veblush): Remove this once absl::Status migration is done
+    if (which == GRPC_ERROR_INT_GRPC_STATUS) {
+      switch (error.code()) {
+        case absl::StatusCode::kOk:
+          *p = GRPC_STATUS_OK;
+          return true;
+        case absl::StatusCode::kResourceExhausted:
+          *p = GRPC_STATUS_RESOURCE_EXHAUSTED;
+          return true;
+        case absl::StatusCode::kCancelled:
+          *p = GRPC_STATUS_CANCELLED;
+          return true;
+        default:
+          break;
+      }
+    }
     return false;
   }
 }
 
 grpc_error_handle grpc_error_set_str(grpc_error_handle src,
                                      grpc_error_strs which,
-                                     const grpc_slice& str) {
-  grpc_core::StatusSetStr(
-      &src, static_cast<grpc_core::StatusStrProperty>(which),
-      std::string(reinterpret_cast<const char*>(GRPC_SLICE_START_PTR(str)),
-                  GRPC_SLICE_LENGTH(str)));
+                                     absl::string_view str) {
+  if (src == GRPC_ERROR_NONE) {
+    src = absl::UnknownError("");
+    StatusSetInt(&src, grpc_core::StatusIntProperty::kRpcStatus,
+                 GRPC_STATUS_OK);
+  }
+  if (which == GRPC_ERROR_STR_DESCRIPTION) {
+    // To change the message of absl::Status, a new instance should be created
+    // with a code and payload because it doesn't have a setter for it.
+    absl::Status s = absl::Status(src.code(), str);
+    src.ForEachPayload(
+        [&](absl::string_view type_url, const absl::Cord& payload) {
+          s.SetPayload(type_url, payload);
+        });
+    return s;
+  } else {
+    grpc_core::StatusSetStr(
+        &src, static_cast<grpc_core::StatusStrProperty>(which), str);
+  }
   return src;
 }
 
 bool grpc_error_get_str(grpc_error_handle error, grpc_error_strs which,
-                        grpc_slice* s) {
-  absl::optional<std::string> value = grpc_core::StatusGetStr(
-      error, static_cast<grpc_core::StatusStrProperty>(which));
-  if (value.has_value()) {
-    *s = grpc_slice_from_copied_buffer(value->c_str(), value->size());
-    return true;
+                        std::string* s) {
+  if (which == GRPC_ERROR_STR_DESCRIPTION) {
+    // absl::Status uses the message field for GRPC_ERROR_STR_DESCRIPTION
+    // instead of using payload.
+    absl::string_view msg = error.message();
+    if (msg.empty()) {
+      return false;
+    } else {
+      *s = std::string(msg);
+      return true;
+    }
   } else {
-    return false;
+    absl::optional<std::string> value = grpc_core::StatusGetStr(
+        error, static_cast<grpc_core::StatusStrProperty>(which));
+    if (value.has_value()) {
+      *s = std::move(*value);
+      return true;
+    } else {
+      // TODO(veblush): Remove this once absl::Status migration is done
+      if (which == GRPC_ERROR_STR_GRPC_MESSAGE) {
+        switch (error.code()) {
+          case absl::StatusCode::kOk:
+            *s = "";
+            return true;
+          case absl::StatusCode::kResourceExhausted:
+            *s = "RESOURCE_EXHAUSTED";
+            return true;
+          case absl::StatusCode::kCancelled:
+            *s = "CANCELLED";
+            return true;
+          default:
+            break;
+        }
+      }
+      return false;
+    }
   }
 }
 
 grpc_error_handle grpc_error_add_child(grpc_error_handle src,
                                        grpc_error_handle child) {
-  grpc_core::StatusAddChild(&src, child);
-  return src;
+  if (src.ok()) {
+    return child;
+  } else {
+    if (!child.ok()) {
+      grpc_core::StatusAddChild(&src, child);
+    }
+    return src;
+  }
 }
 
 bool grpc_log_error(const char* what, grpc_error_handle error, const char* file,
@@ -300,8 +370,8 @@ static uint8_t get_placement(grpc_error_handle* err, size_t size) {
   GPR_ASSERT(*err);
   uint8_t slots = static_cast<uint8_t>(size / sizeof(intptr_t));
   if ((*err)->arena_size + slots > (*err)->arena_capacity) {
-    (*err)->arena_capacity = static_cast<uint8_t> GPR_MIN(
-        UINT8_MAX - 1, (3 * (*err)->arena_capacity / 2));
+    (*err)->arena_capacity = static_cast<uint8_t>(std::min(
+        size_t(UINT8_MAX - 1), size_t(3 * (*err)->arena_capacity / 2)));
     if ((*err)->arena_size + slots > (*err)->arena_capacity) {
       return UINT8_MAX;
     }
@@ -417,7 +487,6 @@ grpc_error_handle grpc_error_create(const char* file, int line,
                                     const grpc_slice& desc,
                                     grpc_error_handle* referencing,
                                     size_t num_referencing) {
-  GPR_TIMER_SCOPE("grpc_error_create", 0);
   uint8_t initial_arena_capacity = static_cast<uint8_t>(
       DEFAULT_ERROR_CAPACITY +
       static_cast<uint8_t>(num_referencing * SLOTS_PER_LINKED_ERROR) +
@@ -483,13 +552,12 @@ static void ref_errs(grpc_error_handle err) {
   while (slot != UINT8_MAX) {
     grpc_linked_error* lerr =
         reinterpret_cast<grpc_linked_error*>(err->arena + slot);
-    GRPC_ERROR_REF(lerr->err);
+    (void)GRPC_ERROR_REF(lerr->err);
     slot = lerr->next;
   }
 }
 
 static grpc_error_handle copy_error_and_unref(grpc_error_handle in) {
-  GPR_TIMER_SCOPE("copy_error_and_unref", 0);
   grpc_error_handle out;
   if (grpc_error_is_special(in)) {
     out = GRPC_ERROR_CREATE_FROM_STATIC_STRING("unknown");
@@ -541,7 +609,6 @@ static grpc_error_handle copy_error_and_unref(grpc_error_handle in) {
 
 grpc_error_handle grpc_error_set_int(grpc_error_handle src,
                                      grpc_error_ints which, intptr_t value) {
-  GPR_TIMER_SCOPE("grpc_error_set_int", 0);
   grpc_error_handle new_err = copy_error_and_unref(src);
   internal_set_int(&new_err, which, value);
   return new_err;
@@ -555,16 +622,15 @@ struct special_error_status_map {
 const special_error_status_map error_status_map[] = {
     {GRPC_STATUS_OK, "", 0},                // GRPC_ERROR_NONE
     {GRPC_STATUS_INVALID_ARGUMENT, "", 0},  // GRPC_ERROR_RESERVED_1
-    {GRPC_STATUS_RESOURCE_EXHAUSTED, "Out of memory",
-     strlen("Out of memory")},              // GRPC_ERROR_OOM
+    {GRPC_STATUS_RESOURCE_EXHAUSTED, "RESOURCE_EXHAUSTED",
+     strlen("RESOURCE_EXHAUSTED")},         // GRPC_ERROR_OOM
     {GRPC_STATUS_INVALID_ARGUMENT, "", 0},  // GRPC_ERROR_RESERVED_2
-    {GRPC_STATUS_CANCELLED, "Cancelled",
-     strlen("Cancelled")},  // GRPC_ERROR_CANCELLED
+    {GRPC_STATUS_CANCELLED, "CANCELLED",
+     strlen("CANCELLED")},  // GRPC_ERROR_CANCELLED
 };
 
 bool grpc_error_get_int(grpc_error_handle err, grpc_error_ints which,
                         intptr_t* p) {
-  GPR_TIMER_SCOPE("grpc_error_get_int", 0);
   if (grpc_error_is_special(err)) {
     if (which != GRPC_ERROR_INT_GRPC_STATUS) return false;
     *p = error_status_map[reinterpret_cast<size_t>(err)].code;
@@ -580,28 +646,26 @@ bool grpc_error_get_int(grpc_error_handle err, grpc_error_ints which,
 
 grpc_error_handle grpc_error_set_str(grpc_error_handle src,
                                      grpc_error_strs which,
-                                     const grpc_slice& str) {
-  GPR_TIMER_SCOPE("grpc_error_set_str", 0);
+                                     absl::string_view str) {
   grpc_error_handle new_err = copy_error_and_unref(src);
-  internal_set_str(&new_err, which, str);
+  internal_set_str(&new_err, which,
+                   grpc_slice_from_copied_buffer(str.data(), str.length()));
   return new_err;
 }
 
 bool grpc_error_get_str(grpc_error_handle err, grpc_error_strs which,
-                        grpc_slice* str) {
+                        std::string* s) {
   if (grpc_error_is_special(err)) {
     if (which != GRPC_ERROR_STR_GRPC_MESSAGE) return false;
     const special_error_status_map& msg =
         error_status_map[reinterpret_cast<size_t>(err)];
-    str->refcount = &grpc_core::kNoopRefcount;
-    str->data.refcounted.bytes =
-        reinterpret_cast<uint8_t*>(const_cast<char*>(msg.msg));
-    str->data.refcounted.length = msg.len;
+    *s = std::string(msg.msg, msg.len);
     return true;
   }
   uint8_t slot = err->strs[which];
   if (slot != UINT8_MAX) {
-    *str = *reinterpret_cast<grpc_slice*>(err->arena + slot);
+    grpc_slice* slice = reinterpret_cast<grpc_slice*>(err->arena + slot);
+    *s = std::string(grpc_core::StringViewFromSlice(*slice));
     return true;
   } else {
     return false;
@@ -610,7 +674,6 @@ bool grpc_error_get_str(grpc_error_handle err, grpc_error_strs which,
 
 grpc_error_handle grpc_error_add_child(grpc_error_handle src,
                                        grpc_error_handle child) {
-  GPR_TIMER_SCOPE("grpc_error_add_child", 0);
   if (src != GRPC_ERROR_NONE) {
     if (child == GRPC_ERROR_NONE) {
       /* \a child is empty. Simply return the ref to \a src */
@@ -631,9 +694,9 @@ grpc_error_handle grpc_error_add_child(grpc_error_handle src,
   }
 }
 
-static const char* no_error_string = "\"No Error\"";
-static const char* oom_error_string = "\"Out of memory\"";
-static const char* cancelled_error_string = "\"Cancelled\"";
+static const char* no_error_string = "\"OK\"";
+static const char* oom_error_string = "\"RESOURCE_EXHAUSTED\"";
+static const char* cancelled_error_string = "\"CANCELLED\"";
 
 struct kv_pair {
   char* key;
@@ -646,7 +709,7 @@ struct kv_pairs {
 };
 static void append_chr(char c, char** s, size_t* sz, size_t* cap) {
   if (*sz == *cap) {
-    *cap = GPR_MAX(8, 3 * *cap / 2);
+    *cap = std::max(size_t(8), 3 * *cap / 2);
     *s = static_cast<char*>(gpr_realloc(*s, *cap));
   }
   (*s)[(*sz)++] = c;
@@ -698,7 +761,7 @@ static void append_esc_str(const uint8_t* str, size_t len, char** s, size_t* sz,
 
 static void append_kv(kv_pairs* kvs, char* key, char* value) {
   if (kvs->num_kvs == kvs->cap_kvs) {
-    kvs->cap_kvs = GPR_MAX(3 * kvs->cap_kvs / 2, 4);
+    kvs->cap_kvs = std::max(3 * kvs->cap_kvs / 2, size_t(4));
     kvs->kvs = static_cast<kv_pair*>(
         gpr_realloc(kvs->kvs, sizeof(*kvs->kvs) * kvs->cap_kvs));
   }
@@ -842,7 +905,6 @@ static char* finish_kvs(kv_pairs* kvs) {
 }
 
 const char* grpc_error_string(grpc_error_handle err) {
-  GPR_TIMER_SCOPE("grpc_error_string", 0);
   if (err == GRPC_ERROR_NONE) return no_error_string;
   if (err == GRPC_ERROR_OOM) return oom_error_string;
   if (err == GRPC_ERROR_CANCELLED) return cancelled_error_string;
@@ -889,9 +951,8 @@ grpc_error_handle grpc_os_error(const char* file, int line, int err,
                                 grpc_slice_from_static_string(strerror(err)),
                                 nullptr, 0),
               GRPC_ERROR_INT_ERRNO, err),
-          GRPC_ERROR_STR_OS_ERROR,
-          grpc_slice_from_static_string(strerror(err))),
-      GRPC_ERROR_STR_SYSCALL, grpc_slice_from_copied_string(call_name));
+          GRPC_ERROR_STR_OS_ERROR, strerror(err)),
+      GRPC_ERROR_STR_SYSCALL, call_name);
 }
 
 #ifdef GPR_WINDOWS
@@ -905,8 +966,8 @@ grpc_error_handle grpc_wsa_error(const char* file, int line, int err,
                                 grpc_slice_from_static_string("OS Error"), NULL,
                                 0),
               GRPC_ERROR_INT_WSA_ERROR, err),
-          GRPC_ERROR_STR_OS_ERROR, grpc_slice_from_copied_string(utf8_message)),
-      GRPC_ERROR_STR_SYSCALL, grpc_slice_from_static_string(call_name));
+          GRPC_ERROR_STR_OS_ERROR, utf8_message),
+      GRPC_ERROR_STR_SYSCALL, call_name);
   gpr_free(utf8_message);
   return error;
 }
index cd68014..06c0e7d 100644 (file)
@@ -32,6 +32,7 @@
 #include <grpc/support/time.h>
 
 #include "src/core/lib/debug/trace.h"
+#include "src/core/lib/gpr/spinlock.h"
 #include "src/core/lib/gprpp/status_helper.h"
 #include "src/core/lib/slice/slice_internal.h"
 
@@ -156,11 +157,11 @@ void grpc_enable_error_creation();
 #ifdef GRPC_ERROR_IS_ABSEIL_STATUS
 
 #define GRPC_ERROR_NONE absl::OkStatus()
-#define GRPC_ERROR_OOM absl::Status(absl::ResourceExhaustedError)
+#define GRPC_ERROR_OOM absl::Status(absl::ResourceExhaustedError(""))
 #define GRPC_ERROR_CANCELLED absl::CancelledError()
 
 #define GRPC_ERROR_REF(err) (err)
-#define GRPC_ERROR_UNREF(err)
+#define GRPC_ERROR_UNREF(err) (void)(err)
 
 #define GRPC_ERROR_CREATE_FROM_STATIC_STRING(desc) \
   StatusCreate(absl::StatusCode::kUnknown, desc, DEBUG_LOCATION, {})
@@ -189,11 +190,11 @@ absl::Status grpc_status_create(absl::StatusCode code, absl::string_view msg,
 // them. If the vector is empty, return GRPC_ERROR_NONE.
 template <typename VectorType>
 static absl::Status grpc_status_create_from_vector(
-    const grpc_core::DebugLocation& location, const char* desc,
+    const grpc_core::DebugLocation& location, absl::string_view desc,
     VectorType* error_list) {
   absl::Status error = GRPC_ERROR_NONE;
   if (error_list->size() != 0) {
-    error = grpc_status_create(absl::StatusCode::kUnknown, desc, DEBUG_LOCATION,
+    error = grpc_status_create(absl::StatusCode::kUnknown, desc, location,
                                error_list->size(), error_list->data());
     error_list->clear();
   }
@@ -363,15 +364,12 @@ grpc_error_handle grpc_error_set_int(grpc_error_handle src,
 /// intptr_t for `p`, even if the value of `p` is not used.
 bool grpc_error_get_int(grpc_error_handle error, grpc_error_ints which,
                         intptr_t* p);
-/// This call takes ownership of the slice; the error is responsible for
-/// eventually unref-ing it.
 grpc_error_handle grpc_error_set_str(
     grpc_error_handle src, grpc_error_strs which,
-    const grpc_slice& str) GRPC_MUST_USE_RESULT;
+    absl::string_view str) GRPC_MUST_USE_RESULT;
 /// Returns false if the specified string is not set.
-/// Caller does NOT own the slice.
 bool grpc_error_get_str(grpc_error_handle error, grpc_error_strs which,
-                        grpc_slice* s);
+                        std::string* str);
 
 /// Add a child error: an error that is believed to have contributed to this
 /// error occurring. Allows root causing high level errors from lower level
@@ -398,4 +396,47 @@ inline bool grpc_log_if_error(const char* what, grpc_error_handle error,
 #define GRPC_LOG_IF_ERROR(what, error) \
   (grpc_log_if_error((what), (error), __FILE__, __LINE__))
 
+/// Helper class to get & set grpc_error_handle in a thread-safe fashion.
+/// This could be considered as atomic<grpc_error_handle>.
+class AtomicError {
+ public:
+  AtomicError() {
+    error_ = GRPC_ERROR_NONE;
+    lock_ = GPR_SPINLOCK_STATIC_INITIALIZER;
+  }
+  explicit AtomicError(grpc_error_handle error) {
+    error_ = GRPC_ERROR_REF(error);
+  }
+  ~AtomicError() { GRPC_ERROR_UNREF(error_); }
+
+  AtomicError(const AtomicError&) = delete;
+  AtomicError& operator=(const AtomicError&) = delete;
+
+  /// returns get() == GRPC_ERROR_NONE
+  bool ok() {
+    gpr_spinlock_lock(&lock_);
+    bool ret = error_ == GRPC_ERROR_NONE;
+    gpr_spinlock_unlock(&lock_);
+    return ret;
+  }
+
+  grpc_error_handle get() {
+    gpr_spinlock_lock(&lock_);
+    grpc_error_handle ret = error_;
+    gpr_spinlock_unlock(&lock_);
+    return ret;
+  }
+
+  void set(grpc_error_handle error) {
+    gpr_spinlock_lock(&lock_);
+    GRPC_ERROR_UNREF(error_);
+    error_ = GRPC_ERROR_REF(error);
+    gpr_spinlock_unlock(&lock_);
+  }
+
+ private:
+  grpc_error_handle error_;
+  gpr_spinlock lock_;
+};
+
 #endif /* GRPC_CORE_LIB_IOMGR_ERROR_H */
index 9c93dde..84052aa 100644 (file)
@@ -48,7 +48,12 @@ grpc_error_handle grpc_error_create_from_cferror(const char* file, int line,
       absl::StrFormat("%s (error domain:%s, code:%ld, description:%s)",
                       custom_desc, buf_domain, code, buf_desc);
   CFRelease(desc);
+#ifdef GRPC_ERROR_IS_ABSEIL_STATUS
+  return StatusCreate(absl::StatusCode::kUnknown, error_msg,
+                      grpc_core::DebugLocation(file, line), {});
+#else
   return grpc_error_create(
       file, line, grpc_slice_from_copied_string(error_msg.c_str()), NULL, 0);
+#endif
 }
 #endif /* GRPC_CFSTREAM */
index 9180563..cecf15c 100644 (file)
@@ -195,7 +195,7 @@ struct grpc_pollset_worker {
     (worker)->kick_state_mutator = __LINE__; \
   } while (false)
 
-#define MAX_NEIGHBORHOODS 1024
+#define MAX_NEIGHBORHOODS 1024u
 
 typedef struct pollset_neighborhood {
   union {
@@ -525,7 +525,8 @@ static grpc_error_handle pollset_global_init(void) {
                 &ev) != 0) {
     return GRPC_OS_ERROR(errno, "epoll_ctl");
   }
-  g_num_neighborhoods = GPR_CLAMP(gpr_cpu_num_cores(), 1, MAX_NEIGHBORHOODS);
+  g_num_neighborhoods =
+      grpc_core::Clamp(gpr_cpu_num_cores(), 1u, MAX_NEIGHBORHOODS);
   g_neighborhoods = static_cast<pollset_neighborhood*>(
       gpr_zalloc(sizeof(*g_neighborhoods) * g_num_neighborhoods));
   for (size_t i = 0; i < g_num_neighborhoods; i++) {
index 2da53d2..38e79bc 100644 (file)
@@ -1071,7 +1071,7 @@ static void end_worker(grpc_pollset* pollset, grpc_pollset_worker* worker,
     case WRR_EMPTIED:
       if (pollset->active_pollable != worker->pollable_obj) {
         // pollable no longer being polled: flush events
-        pollable_process_events(pollset, worker->pollable_obj, true);
+        (void)pollable_process_events(pollset, worker->pollable_obj, true);
       }
       break;
     case WRR_REMOVED:
@@ -1357,7 +1357,7 @@ static void pollset_set_add_fd(grpc_pollset_set* pss, grpc_fd* fd) {
                  err_desc);
   }
   if (pss->fd_count == pss->fd_capacity) {
-    pss->fd_capacity = GPR_MAX(pss->fd_capacity * 2, 8);
+    pss->fd_capacity = std::max(pss->fd_capacity * 2, size_t(8));
     pss->fds = static_cast<grpc_fd**>(
         gpr_realloc(pss->fds, pss->fd_capacity * sizeof(*pss->fds)));
   }
@@ -1467,7 +1467,7 @@ static void pollset_set_add_pollset(grpc_pollset_set* pss, grpc_pollset* ps) {
                                    pss->fds, &pss->fd_count),
                err_desc);
   if (pss->pollset_count == pss->pollset_capacity) {
-    pss->pollset_capacity = GPR_MAX(pss->pollset_capacity * 2, 8);
+    pss->pollset_capacity = std::max(pss->pollset_capacity * 2, size_t(8));
     pss->pollsets = static_cast<grpc_pollset**>(gpr_realloc(
         pss->pollsets, pss->pollset_capacity * sizeof(*pss->pollsets)));
   }
@@ -1492,7 +1492,7 @@ static void pollset_set_add_pollset_set(grpc_pollset_set* a,
       return;
     }
     if (a > b) {
-      GPR_SWAP(grpc_pollset_set*, a, b);
+      std::swap(a, b);
     }
     gpr_mu* a_mu = &a->mu;
     gpr_mu* b_mu = &b->mu;
@@ -1513,7 +1513,7 @@ static void pollset_set_add_pollset_set(grpc_pollset_set* a,
   const size_t a_size = a->fd_count + a->pollset_count;
   const size_t b_size = b->fd_count + b->pollset_count;
   if (b_size > a_size) {
-    GPR_SWAP(grpc_pollset_set*, a, b);
+    std::swap(a, b);
   }
   if (GRPC_TRACE_FLAG_ENABLED(grpc_polling_trace)) {
     gpr_log(GPR_INFO, "PSS: parent %p to %p", b, a);
@@ -1521,7 +1521,7 @@ static void pollset_set_add_pollset_set(grpc_pollset_set* a,
   a->refs.Ref();
   b->parent = a;
   if (a->fd_capacity < a->fd_count + b->fd_count) {
-    a->fd_capacity = GPR_MAX(2 * a->fd_capacity, a->fd_count + b->fd_count);
+    a->fd_capacity = std::max(2 * a->fd_capacity, a->fd_count + b->fd_count);
     a->fds = static_cast<grpc_fd**>(
         gpr_realloc(a->fds, a->fd_capacity * sizeof(*a->fds)));
   }
@@ -1539,7 +1539,7 @@ static void pollset_set_add_pollset_set(grpc_pollset_set* a,
       err_desc);
   if (a->pollset_capacity < a->pollset_count + b->pollset_count) {
     a->pollset_capacity =
-        GPR_MAX(2 * a->pollset_capacity, a->pollset_count + b->pollset_count);
+        std::max(2 * a->pollset_capacity, a->pollset_count + b->pollset_count);
     a->pollsets = static_cast<grpc_pollset**>(
         gpr_realloc(a->pollsets, a->pollset_capacity * sizeof(*a->pollsets)));
   }
index cd22b60..03dec3f 100644 (file)
@@ -357,7 +357,12 @@ static void unref_by(grpc_fd* fd, int n) {
     gpr_mu_destroy(&fd->mu);
     grpc_iomgr_unregister_object(&fd->iomgr_object);
     fork_fd_list_remove_node(fd->fork_fd_list);
-    if (fd->shutdown) GRPC_ERROR_UNREF(fd->shutdown_error);
+    if (fd->shutdown) {
+      GRPC_ERROR_UNREF(fd->shutdown_error);
+    }
+#ifdef GRPC_ERROR_IS_ABSEIL_STATUS
+    fd->shutdown_error.~Status();
+#endif
     gpr_free(fd);
   } else {
     GPR_ASSERT(old > n);
@@ -372,6 +377,9 @@ static grpc_fd* fd_create(int fd, const char* name, bool track_err) {
   gpr_mu_init(&r->mu);
   gpr_atm_rel_store(&r->refst, 1);
   r->shutdown = 0;
+#ifdef GRPC_ERROR_IS_ABSEIL_STATUS
+  new (&r->shutdown_error) absl::Status();
+#endif
   r->read_closure = CLOSURE_NOT_READY;
   r->write_closure = CLOSURE_NOT_READY;
   r->fd = fd;
@@ -405,11 +413,11 @@ static grpc_error_handle pollset_kick_locked(grpc_fd_watcher* watcher) {
 
 static void maybe_wake_one_watcher_locked(grpc_fd* fd) {
   if (fd->inactive_watcher_root.next != &fd->inactive_watcher_root) {
-    pollset_kick_locked(fd->inactive_watcher_root.next);
+    (void)pollset_kick_locked(fd->inactive_watcher_root.next);
   } else if (fd->read_watcher) {
-    pollset_kick_locked(fd->read_watcher);
+    (void)pollset_kick_locked(fd->read_watcher);
   } else if (fd->write_watcher) {
-    pollset_kick_locked(fd->write_watcher);
+    (void)pollset_kick_locked(fd->write_watcher);
   }
 }
 
@@ -417,13 +425,13 @@ static void wake_all_watchers_locked(grpc_fd* fd) {
   grpc_fd_watcher* watcher;
   for (watcher = fd->inactive_watcher_root.next;
        watcher != &fd->inactive_watcher_root; watcher = watcher->next) {
-    pollset_kick_locked(watcher);
+    (void)pollset_kick_locked(watcher);
   }
   if (fd->read_watcher) {
-    pollset_kick_locked(fd->read_watcher);
+    (void)pollset_kick_locked(fd->read_watcher);
   }
   if (fd->write_watcher && fd->write_watcher != fd->read_watcher) {
-    pollset_kick_locked(fd->write_watcher);
+    (void)pollset_kick_locked(fd->write_watcher);
   }
 }
 
@@ -873,13 +881,13 @@ static void pollset_add_fd(grpc_pollset* pollset, grpc_fd* fd) {
   }
   if (pollset->fd_count == pollset->fd_capacity) {
     pollset->fd_capacity =
-        GPR_MAX(pollset->fd_capacity + 8, pollset->fd_count * 3 / 2);
+        std::max(pollset->fd_capacity + 8, pollset->fd_count * 3 / 2);
     pollset->fds = static_cast<grpc_fd**>(
         gpr_realloc(pollset->fds, sizeof(grpc_fd*) * pollset->fd_capacity));
   }
   pollset->fds[pollset->fd_count++] = fd;
   GRPC_FD_REF(fd, "multipoller");
-  pollset_kick(pollset, nullptr);
+  (void)pollset_kick(pollset, nullptr);
 exit:
   gpr_mu_unlock(&pollset->mu);
 }
@@ -1114,7 +1122,7 @@ static grpc_error_handle pollset_work(grpc_pollset* pollset,
   /* check shutdown conditions */
   if (pollset->shutting_down) {
     if (pollset_has_workers(pollset)) {
-      pollset_kick(pollset, nullptr);
+      (void)pollset_kick(pollset, nullptr);
     } else if (!pollset->called_shutdown && !pollset_has_observers(pollset)) {
       pollset->called_shutdown = 1;
       gpr_mu_unlock(&pollset->mu);
@@ -1136,7 +1144,7 @@ static void pollset_shutdown(grpc_pollset* pollset, grpc_closure* closure) {
   GPR_ASSERT(!pollset->shutting_down);
   pollset->shutting_down = 1;
   pollset->shutdown_done = closure;
-  pollset_kick(pollset, GRPC_POLLSET_KICK_BROADCAST);
+  (void)pollset_kick(pollset, GRPC_POLLSET_KICK_BROADCAST);
   if (!pollset->called_shutdown && !pollset_has_observers(pollset)) {
     pollset->called_shutdown = 1;
     finish_shutdown(pollset);
@@ -1198,7 +1206,7 @@ static void pollset_set_add_pollset(grpc_pollset_set* pollset_set,
   gpr_mu_lock(&pollset_set->mu);
   if (pollset_set->pollset_count == pollset_set->pollset_capacity) {
     pollset_set->pollset_capacity =
-        GPR_MAX(8, 2 * pollset_set->pollset_capacity);
+        std::max(size_t(8), 2 * pollset_set->pollset_capacity);
     pollset_set->pollsets = static_cast<grpc_pollset**>(gpr_realloc(
         pollset_set->pollsets,
         pollset_set->pollset_capacity * sizeof(*pollset_set->pollsets)));
@@ -1223,8 +1231,8 @@ static void pollset_set_del_pollset(grpc_pollset_set* pollset_set,
   for (i = 0; i < pollset_set->pollset_count; i++) {
     if (pollset_set->pollsets[i] == pollset) {
       pollset_set->pollset_count--;
-      GPR_SWAP(grpc_pollset*, pollset_set->pollsets[i],
-               pollset_set->pollsets[pollset_set->pollset_count]);
+      std::swap(pollset_set->pollsets[i],
+                pollset_set->pollsets[pollset_set->pollset_count]);
       break;
     }
   }
@@ -1247,7 +1255,8 @@ static void pollset_set_add_pollset_set(grpc_pollset_set* bag,
   size_t i, j;
   gpr_mu_lock(&bag->mu);
   if (bag->pollset_set_count == bag->pollset_set_capacity) {
-    bag->pollset_set_capacity = GPR_MAX(8, 2 * bag->pollset_set_capacity);
+    bag->pollset_set_capacity =
+        std::max(size_t(8), 2 * bag->pollset_set_capacity);
     bag->pollset_sets = static_cast<grpc_pollset_set**>(
         gpr_realloc(bag->pollset_sets,
                     bag->pollset_set_capacity * sizeof(*bag->pollset_sets)));
@@ -1272,8 +1281,8 @@ static void pollset_set_del_pollset_set(grpc_pollset_set* bag,
   for (i = 0; i < bag->pollset_set_count; i++) {
     if (bag->pollset_sets[i] == item) {
       bag->pollset_set_count--;
-      GPR_SWAP(grpc_pollset_set*, bag->pollset_sets[i],
-               bag->pollset_sets[bag->pollset_set_count]);
+      std::swap(bag->pollset_sets[i],
+                bag->pollset_sets[bag->pollset_set_count]);
       break;
     }
   }
@@ -1284,7 +1293,8 @@ static void pollset_set_add_fd(grpc_pollset_set* pollset_set, grpc_fd* fd) {
   size_t i;
   gpr_mu_lock(&pollset_set->mu);
   if (pollset_set->fd_count == pollset_set->fd_capacity) {
-    pollset_set->fd_capacity = GPR_MAX(8, 2 * pollset_set->fd_capacity);
+    pollset_set->fd_capacity =
+        std::max(size_t(8), 2 * pollset_set->fd_capacity);
     pollset_set->fds = static_cast<grpc_fd**>(
         gpr_realloc(pollset_set->fds,
                     pollset_set->fd_capacity * sizeof(*pollset_set->fds)));
@@ -1306,8 +1316,7 @@ static void pollset_set_del_fd(grpc_pollset_set* pollset_set, grpc_fd* fd) {
   for (i = 0; i < pollset_set->fd_count; i++) {
     if (pollset_set->fds[i] == fd) {
       pollset_set->fd_count--;
-      GPR_SWAP(grpc_fd*, pollset_set->fds[i],
-               pollset_set->fds[pollset_set->fd_count]);
+      std::swap(pollset_set->fds[i], pollset_set->fds[pollset_set->fd_count]);
       GRPC_FD_UNREF(fd, "pollset_set");
       break;
     }
index d9d0394..e2afe8a 100644 (file)
 #include <grpc/event_engine/event_engine.h>
 
 #include "src/core/lib/iomgr/closure.h"
+#include "src/core/lib/iomgr/event_engine/closure.h"
 #include "src/core/lib/iomgr/event_engine/pollset.h"
 #include "src/core/lib/transport/error_utils.h"
 
 namespace grpc_event_engine {
 namespace experimental {
 
-EventEngine::Callback GrpcClosureToCallback(grpc_closure* closure,
-                                            grpc_error_handle error) {
-  return [closure, error](absl::Status status) {
-    grpc_error_handle new_error =
-        grpc_error_add_child(error, absl_status_to_grpc_error(status));
+namespace {
+
+void RunClosure(grpc_closure* closure, grpc_error_handle error) {
+  GPR_ASSERT(closure != nullptr);
 #ifndef NDEBUG
-    closure->scheduled = false;
-    if (grpc_trace_closure.enabled()) {
-      gpr_log(GPR_DEBUG,
-              "EventEngine: running closure %p: created [%s:%d]: %s [%s:%d]",
-              closure, closure->file_created, closure->line_created,
-              closure->run ? "run" : "scheduled", closure->file_initiated,
-              closure->line_initiated);
-    }
+  closure->scheduled = false;
+  if (grpc_trace_closure.enabled()) {
+    gpr_log(GPR_DEBUG,
+            "EventEngine: running closure %p: created [%s:%d]: %s [%s:%d]",
+            closure, closure->file_created, closure->line_created,
+            closure->run ? "run" : "scheduled", closure->file_initiated,
+            closure->line_initiated);
+  }
 #endif
-    closure->cb(closure->cb_arg, new_error);
+  closure->cb(closure->cb_arg, error);
 #ifndef NDEBUG
-    if (grpc_trace_closure.enabled()) {
-      gpr_log(GPR_DEBUG, "EventEngine: closure %p finished", closure);
-    }
+  if (grpc_trace_closure.enabled()) {
+    gpr_log(GPR_DEBUG, "EventEngine: closure %p finished", closure);
+  }
 #endif
-    GRPC_ERROR_UNREF(error);
+}
+
+}  // namespace
+
+std::function<void(absl::Status)> GrpcClosureToStatusCallback(
+    grpc_closure* closure) {
+  return [closure](absl::Status status) {
+    RunClosure(closure, absl_status_to_grpc_error(status));
+    grpc_pollset_ee_broadcast_event();
+  };
+}
+
+std::function<void()> GrpcClosureToCallback(grpc_closure* closure) {
+  return [closure]() {
+    RunClosure(closure, GRPC_ERROR_NONE);
+    grpc_pollset_ee_broadcast_event();
+  };
+}
+
+std::function<void()> GrpcClosureToCallback(grpc_closure* closure,
+                                            grpc_error_handle error) {
+  return [closure, error]() {
+    RunClosure(closure, error);
     grpc_pollset_ee_broadcast_event();
   };
 }
 
 }  // namespace experimental
 }  // namespace grpc_event_engine
+
 #endif  // GRPC_USE_EVENT_ENGINE
index f1b4f76..ecb332b 100644 (file)
 namespace grpc_event_engine {
 namespace experimental {
 
-EventEngine::Callback GrpcClosureToCallback(grpc_closure* closure,
+/// Creates a callback that takes an error status argument.
+std::function<void(absl::Status)> GrpcClosureToStatusCallback(
+    grpc_closure* closure);
+
+/// Create a callback that *does not* take an error status argument.
+std::function<void()> GrpcClosureToCallback(grpc_closure* closure);
+
+/// Creates a callback that *does not* take an error status argument.
+/// This version has a pre-bound error.
+std::function<void()> GrpcClosureToCallback(grpc_closure* closure,
                                             grpc_error_handle error);
 
 }  // namespace experimental
index c8e2feb..6ddbbb3 100644 (file)
@@ -96,12 +96,12 @@ void endpoint_delete_from_pollset_set(grpc_endpoint* /* ep */,
 /// and will return some kind of sane default (empty strings, nullptrs, etc). It
 /// is the caller's responsibility to ensure that calls to endpoint_shutdown are
 /// synchronized.
-void endpoint_shutdown(grpc_endpoint* ep, grpc_error* why) {
+void endpoint_shutdown(grpc_endpoint* ep, grpc_error_handle why) {
   auto* eeep = reinterpret_cast<grpc_event_engine_endpoint*>(ep);
   if (GRPC_TRACE_FLAG_ENABLED(grpc_tcp_trace)) {
-    const char* str = grpc_error_string(why);
+    std::string str = grpc_error_std_string(why);
     gpr_log(GPR_INFO, "TCP Endpoint %p shutdown why=%s", eeep->endpoint.get(),
-            str);
+            str.c_str());
   }
   eeep->endpoint.reset();
 }
index 6a5a798..2720432 100644 (file)
@@ -60,7 +60,7 @@ bool iomgr_platform_is_any_background_poller_thread(void) {
 }
 
 bool iomgr_platform_add_closure_to_background_poller(
-    grpc_closure* /* closure */, grpc_error* /* error */) {
+    grpc_closure* /* closure */, grpc_error_handle /* error */) {
   return false;
 }
 
index e635539..b8e08d0 100644 (file)
@@ -40,15 +40,16 @@ void pollset_shutdown(grpc_pollset* pollset, grpc_closure* closure) {
   grpc_core::ExecCtx::Run(DEBUG_LOCATION, closure, GRPC_ERROR_NONE);
 }
 void pollset_destroy(grpc_pollset* pollset) {}
-grpc_error* pollset_work(grpc_pollset* pollset, grpc_pollset_worker** worker,
-                         grpc_millis deadline) {
+grpc_error_handle pollset_work(grpc_pollset* pollset,
+                               grpc_pollset_worker** worker,
+                               grpc_millis deadline) {
   (void)worker;
   gpr_cv_wait(&g_cv, &g_mu,
               grpc_millis_to_timespec(deadline, GPR_CLOCK_REALTIME));
   return GRPC_ERROR_NONE;
 }
-grpc_error* pollset_kick(grpc_pollset* pollset,
-                         grpc_pollset_worker* specific_worker) {
+grpc_error_handle pollset_kick(grpc_pollset* pollset,
+                               grpc_pollset_worker* specific_worker) {
   (void)pollset;
   (void)specific_worker;
   return GRPC_ERROR_NONE;
index ea0528f..628c305 100644 (file)
@@ -79,13 +79,15 @@ void resolve_address(const char* addr, const char* default_port,
                      grpc_pollset_set* /* interested_parties */,
                      grpc_closure* on_done,
                      grpc_resolved_addresses** addresses) {
-  auto dns_resolver = grpc_iomgr_event_engine()->GetDNSResolver();
-  if (!dns_resolver.ok()) {
-    grpc_core::ExecCtx::Run(DEBUG_LOCATION, on_done,
-                            absl_status_to_grpc_error(dns_resolver.status()));
+  std::unique_ptr<EventEngine::DNSResolver> dns_resolver =
+      grpc_iomgr_event_engine()->GetDNSResolver();
+  if (dns_resolver == nullptr) {
+    grpc_core::ExecCtx::Run(
+        DEBUG_LOCATION, on_done,
+        GRPC_ERROR_CREATE_FROM_STATIC_STRING("Failed to get DNS Resolver."));
     return;
   }
-  new DnsRequest(std::move(*dns_resolver), addr, default_port, on_done,
+  new DnsRequest(std::move(dns_resolver), addr, default_port, on_done,
                  addresses);
 }
 
@@ -93,8 +95,9 @@ void blocking_handle_async_resolve_done(void* arg, grpc_error_handle error) {
   static_cast<Promise<grpc_error_handle>*>(arg)->Set(std::move(error));
 }
 
-grpc_error* blocking_resolve_address(const char* name, const char* default_port,
-                                     grpc_resolved_addresses** addresses) {
+grpc_error_handle blocking_resolve_address(
+    const char* name, const char* default_port,
+    grpc_resolved_addresses** addresses) {
   grpc_closure on_done;
   Promise<grpc_error_handle> evt;
   GRPC_CLOSURE_INIT(&on_done, blocking_handle_async_resolve_done, &evt,
index 6eb2691..04f6216 100644 (file)
@@ -35,7 +35,7 @@ extern grpc_core::TraceFlag grpc_tcp_trace;
 namespace {
 using ::grpc_event_engine::experimental::ChannelArgsEndpointConfig;
 using ::grpc_event_engine::experimental::EventEngine;
-using ::grpc_event_engine::experimental::GrpcClosureToCallback;
+using ::grpc_event_engine::experimental::GrpcClosureToStatusCallback;
 using ::grpc_event_engine::experimental::SliceAllocator;
 using ::grpc_event_engine::experimental::SliceAllocatorFactory;
 using ::grpc_event_engine::experimental::SliceBuffer;
@@ -164,7 +164,7 @@ void tcp_connect(grpc_closure* on_connect, grpc_endpoint** endpoint,
   }
 }
 
-grpc_error* tcp_server_create(
+grpc_error_handle tcp_server_create(
     grpc_closure* shutdown_complete, const grpc_channel_args* args,
     grpc_slice_allocator_factory* slice_allocator_factory,
     grpc_tcp_server** server) {
@@ -175,7 +175,8 @@ grpc_error* tcp_server_create(
   EventEngine* event_engine = grpc_iomgr_event_engine();
   absl::StatusOr<std::unique_ptr<EventEngine::Listener>> listener =
       event_engine->CreateListener(
-          [server](std::unique_ptr<EventEngine::Endpoint> ee_endpoint) {
+          [server](std::unique_ptr<EventEngine::Endpoint> ee_endpoint,
+                   const SliceAllocator& /*slice_allocator*/) {
             grpc_core::ExecCtx exec_ctx;
             GPR_ASSERT((*server)->on_accept_internal != nullptr);
             grpc_event_engine_endpoint* iomgr_endpoint =
@@ -191,8 +192,8 @@ grpc_error* tcp_server_create(
             exec_ctx.Flush();
             grpc_pollset_ee_broadcast_event();
           },
-          GrpcClosureToCallback(shutdown_complete, GRPC_ERROR_NONE),
-          endpoint_config, std::move(ee_slice_allocator_factory));
+          GrpcClosureToStatusCallback(shutdown_complete), endpoint_config,
+          std::move(ee_slice_allocator_factory));
   if (!listener.ok()) {
     return absl_status_to_grpc_error(listener.status());
   }
@@ -210,9 +211,9 @@ void tcp_server_start(grpc_tcp_server* server,
   GPR_ASSERT(server->listener->Start().ok());
 }
 
-grpc_error* tcp_server_add_port(grpc_tcp_server* s,
-                                const grpc_resolved_address* addr,
-                                int* out_port) {
+grpc_error_handle tcp_server_add_port(grpc_tcp_server* s,
+                                      const grpc_resolved_address* addr,
+                                      int* out_port) {
   EventEngine::ResolvedAddress ra(reinterpret_cast<const sockaddr*>(addr->addr),
                                   addr->len);
   auto port = s->listener->Bind(ra);
index b0a0047..bb7dbfb 100644 (file)
@@ -19,6 +19,7 @@
 #include "src/core/lib/iomgr/error.h"
 #include "src/core/lib/iomgr/event_engine/closure.h"
 #include "src/core/lib/iomgr/event_engine/iomgr.h"
+#include "src/core/lib/iomgr/exec_ctx.h"
 #include "src/core/lib/iomgr/timer.h"
 #include "src/core/lib/surface/init.h"
 #include "src/core/lib/transport/error_utils.h"
@@ -32,12 +33,16 @@ void timer_init(grpc_timer* timer, grpc_millis deadline,
   timer->ee_task_handle = grpc_iomgr_event_engine()->RunAt(
       grpc_core::ToAbslTime(
           grpc_millis_to_timespec(deadline, GPR_CLOCK_REALTIME)),
-      GrpcClosureToCallback(closure, GRPC_ERROR_NONE), {});
+      GrpcClosureToCallback(closure));
+  timer->closure = closure;
 }
 
 void timer_cancel(grpc_timer* timer) {
   auto handle = timer->ee_task_handle;
-  grpc_iomgr_event_engine()->TryCancel(handle);
+  if (!grpc_iomgr_event_engine()->Cancel(handle)) {
+    grpc_core::ExecCtx::Run(DEBUG_LOCATION, timer->closure,
+                            GRPC_ERROR_CANCELLED);
+  }
 }
 
 /* Internal API */
index b551106..ed480d8 100644 (file)
 
 #include "src/core/lib/iomgr/exec_ctx.h"
 
-#include <grpc/event_engine/event_engine.h>
 #include <grpc/support/log.h>
 #include <grpc/support/sync.h>
 
-#include "src/core/lib/gprpp/thd.h"
 #include "src/core/lib/iomgr/combiner.h"
-#include "src/core/lib/iomgr/event_engine/closure.h"
-#include "src/core/lib/iomgr/event_engine/iomgr.h"
+#include "src/core/lib/iomgr/error.h"
 #include "src/core/lib/profiling/timers.h"
 
 static void exec_ctx_run(grpc_closure* closure, grpc_error_handle error) {
@@ -50,13 +47,8 @@ static void exec_ctx_run(grpc_closure* closure, grpc_error_handle error) {
 }
 
 static void exec_ctx_sched(grpc_closure* closure, grpc_error_handle error) {
-#if defined(GRPC_USE_EVENT_ENGINE) && \
-    defined(GRPC_EVENT_ENGINE_REPLACE_EXEC_CTX)
-  grpc_iomgr_event_engine()->Run(GrpcClosureToCallback(closure, error), {});
-#else
   grpc_closure_list_append(grpc_core::ExecCtx::Get()->closure_list(), closure,
                            error);
-#endif
 }
 
 static gpr_timespec g_start_time;
index 50edabf..4ef0c34 100644 (file)
 #include <grpc/support/log.h>
 #include <grpc/support/sync.h>
 
-#include "src/core/lib/debug/stats.h"
 #include "src/core/lib/gpr/tls.h"
 #include "src/core/lib/gpr/useful.h"
 #include "src/core/lib/gprpp/memory.h"
 #include "src/core/lib/iomgr/exec_ctx.h"
-#include "src/core/lib/iomgr/iomgr.h"
+#include "src/core/lib/iomgr/iomgr_internal.h"
 
 #define MAX_DEPTH 2
 
@@ -92,7 +91,7 @@ TraceFlag executor_trace(false, "executor");
 Executor::Executor(const char* name) : name_(name) {
   adding_thread_lock_ = GPR_SPINLOCK_STATIC_INITIALIZER;
   gpr_atm_rel_store(&num_threads_, 0);
-  max_threads_ = GPR_MAX(1, 2 * gpr_cpu_num_cores());
+  max_threads_ = std::max(1u, 2 * gpr_cpu_num_cores());
 }
 
 void Executor::Init() { SetThreading(true); }
@@ -204,7 +203,7 @@ void Executor::SetThreading(bool threading) {
     // an application.
     // TODO(guantaol): create another method to finish all the pending closures
     // registered in the background poller by grpc_core::Executor.
-    grpc_iomgr_shutdown_background_closure();
+    grpc_iomgr_platform_shutdown_background_closure();
   }
 
   EXECUTOR_TRACE("(%s) SetThreading(%d) done", name_, threading);
@@ -237,7 +236,6 @@ void Executor::ThreadMain(void* arg) {
       break;
     }
 
-    GRPC_STATS_INC_EXECUTOR_QUEUE_DRAINED();
     grpc_closure_list closures = ts->elems;
     ts->elems = GRPC_CLOSURE_LIST_INIT;
     gpr_mu_unlock(&ts->mu);
@@ -254,11 +252,6 @@ void Executor::ThreadMain(void* arg) {
 void Executor::Enqueue(grpc_closure* closure, grpc_error_handle error,
                        bool is_short) {
   bool retry_push;
-  if (is_short) {
-    GRPC_STATS_INC_EXECUTOR_SCHEDULED_SHORT_ITEMS();
-  } else {
-    GRPC_STATS_INC_EXECUTOR_SCHEDULED_LONG_ITEMS();
-  }
 
   do {
     retry_push = false;
@@ -279,16 +272,14 @@ void Executor::Enqueue(grpc_closure* closure, grpc_error_handle error,
       return;
     }
 
-    if (grpc_iomgr_add_closure_to_background_poller(closure, error)) {
+    if (grpc_iomgr_platform_add_closure_to_background_poller(closure, error)) {
       return;
     }
 
     ThreadState* ts = g_this_thread_state;
     if (ts == nullptr) {
-      ts = &thd_state_[GPR_HASH_POINTER(grpc_core::ExecCtx::Get(),
-                                        cur_thread_count)];
-    } else {
-      GRPC_STATS_INC_EXECUTOR_SCHEDULED_TO_SELF();
+      ts = &thd_state_[grpc_core::HashPointer(grpc_core::ExecCtx::Get(),
+                                              cur_thread_count)];
     }
 
     ThreadState* orig_ts = ts;
@@ -341,7 +332,6 @@ void Executor::Enqueue(grpc_closure* closure, grpc_error_handle error,
       // - Note that gpr_cv_signal() won't immediately wakeup the thread. That
       //   happens after we release the mutex &ts->mu a few lines below
       if (grpc_closure_list_empty(ts->elems) && !ts->shutdown) {
-        GRPC_STATS_INC_EXECUTOR_WAKEUP_INITIATED();
         gpr_cv_signal(&ts->cv);
       }
 
@@ -372,10 +362,6 @@ void Executor::Enqueue(grpc_closure* closure, grpc_error_handle error,
       }
       gpr_spinlock_unlock(&adding_thread_lock_);
     }
-
-    if (retry_push) {
-      GRPC_STATS_INC_EXECUTOR_PUSH_RETRIES();
-    }
   } while (retry_push);
 }
 
index ab2e9c1..e4d9d21 100644 (file)
@@ -67,7 +67,7 @@ inline void* InfLenFIFOQueue::PopFront() {
 
 InfLenFIFOQueue::Node* InfLenFIFOQueue::AllocateNodes(int num) {
   num_nodes_ = num_nodes_ + num;
-  Node* new_chunk = static_cast<Node*>(gpr_zalloc(sizeof(Node) * num));
+  Node* new_chunk = new Node[num];
   new_chunk[0].next = &new_chunk[1];
   new_chunk[num - 1].prev = &new_chunk[num - 2];
   for (int i = 1; i < num - 1; ++i) {
@@ -79,8 +79,7 @@ InfLenFIFOQueue::Node* InfLenFIFOQueue::AllocateNodes(int num) {
 
 InfLenFIFOQueue::InfLenFIFOQueue() {
   delete_list_size_ = kDeleteListInitSize;
-  delete_list_ =
-      static_cast<Node**>(gpr_zalloc(sizeof(Node*) * delete_list_size_));
+  delete_list_ = new Node*[delete_list_size_];
 
   Node* new_chunk = AllocateNodes(kQueueInitNumNodes);
   delete_list_[delete_list_count_++] = new_chunk;
@@ -95,9 +94,9 @@ InfLenFIFOQueue::InfLenFIFOQueue() {
 InfLenFIFOQueue::~InfLenFIFOQueue() {
   GPR_ASSERT(count_.load(std::memory_order_relaxed) == 0);
   for (size_t i = 0; i < delete_list_count_; ++i) {
-    gpr_free(delete_list_[i]);
+    delete[] delete_list_[i];
   }
-  gpr_free(delete_list_);
+  delete[] delete_list_;
 }
 
 void InfLenFIFOQueue::Put(void* elem) {
@@ -112,8 +111,7 @@ void InfLenFIFOQueue::Put(void* elem) {
     // Expands delete list on full.
     if (delete_list_count_ == delete_list_size_) {
       delete_list_size_ = delete_list_size_ * 2;
-      delete_list_ = static_cast<Node**>(
-          gpr_realloc(delete_list_, sizeof(Node*) * delete_list_size_));
+      delete_list_ = new Node*[delete_list_size_];
     }
     new_chunk[0].prev = queue_tail_->prev;
     new_chunk[curr_count - 1].next = queue_head_;
index c3ee759..f3bc346 100644 (file)
@@ -74,15 +74,10 @@ class InfLenFIFOQueue : public MPMCQueueInterface {
   int count() const override { return count_.load(std::memory_order_relaxed); }
 
   struct Node {
-    Node* next;  // Linking
-    Node* prev;
-    void* content;             // Points to actual element
+    Node* next = nullptr;  // Linking
+    Node* prev = nullptr;
+    void* content = nullptr;   // Points to actual element
     gpr_timespec insert_time;  // Time for stats
-
-    Node() {
-      next = prev = nullptr;
-      content = nullptr;
-    }
   };
 
   // For test purpose only. Returns number of nodes allocated in queue.
index 01d3a53..8bfcebf 100644 (file)
@@ -53,7 +53,9 @@ static bool g_grpc_abort_on_leaks;
 
 void grpc_iomgr_init() {
   grpc_core::ExecCtx exec_ctx;
-  grpc_determine_iomgr_platform();
+  if (!grpc_have_determined_iomgr_platform()) {
+    grpc_set_default_iomgr_platform();
+  }
   g_shutdown = 0;
   gpr_mu_init(&g_mu);
   gpr_cv_init(&g_rcv);
index eb527f7..87ec71a 100644 (file)
 
 #include <stddef.h>
 
-#include "src/core/lib/iomgr/timer.h"
-#include "src/core/lib/iomgr/timer_manager.h"
-
 static grpc_iomgr_platform_vtable* iomgr_platform_vtable = nullptr;
 
-void grpc_set_iomgr_platform_vtable(grpc_iomgr_platform_vtable* vtable) {
-  iomgr_platform_vtable = vtable;
+bool grpc_have_determined_iomgr_platform() {
+  return iomgr_platform_vtable != nullptr;
 }
 
-void grpc_determine_iomgr_platform() {
-  if (iomgr_platform_vtable == nullptr) {
-    grpc_set_default_iomgr_platform();
-  }
+void grpc_set_iomgr_platform_vtable(grpc_iomgr_platform_vtable* vtable) {
+  iomgr_platform_vtable = vtable;
 }
 
 void grpc_iomgr_platform_init() { iomgr_platform_vtable->init(); }
index 01cd248..b9e7eac 100644 (file)
@@ -23,7 +23,8 @@
 
 #include <stdbool.h>
 
-#include "src/core/lib/iomgr/iomgr.h"
+#include "src/core/lib/iomgr/closure.h"
+#include "src/core/lib/iomgr/error.h"
 
 typedef struct grpc_iomgr_object {
   char* name;
@@ -44,7 +45,7 @@ typedef struct grpc_iomgr_platform_vtable {
 void grpc_iomgr_register_object(grpc_iomgr_object* obj, const char* name);
 void grpc_iomgr_unregister_object(grpc_iomgr_object* obj);
 
-void grpc_determine_iomgr_platform();
+bool grpc_have_determined_iomgr_platform();
 
 void grpc_set_iomgr_platform_vtable(grpc_iomgr_platform_vtable* vtable);
 
index a187822..9068670 100644 (file)
@@ -71,8 +71,8 @@ end:
         grpc_error_set_str(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
                                "Failed to load file", &error, 1),
                            GRPC_ERROR_STR_FILENAME,
-                           grpc_slice_from_copied_string(
-                               filename));  // TODO(ncteisen), always static?
+
+                           filename);
     GRPC_ERROR_UNREF(error);
     error = error_out;
   }
index fa21406..d41e502 100644 (file)
@@ -77,7 +77,11 @@ void LockfreeEvent::DestroyEvent() {
   do {
     curr = gpr_atm_no_barrier_load(&state_);
     if (curr & kShutdownBit) {
+#ifdef GRPC_ERROR_IS_ABSEIL_STATUS
+      internal::StatusFreeHeapPtr(curr & ~kShutdownBit);
+#else
       GRPC_ERROR_UNREF((grpc_error_handle)(curr & ~kShutdownBit));
+#endif
     } else {
       GPR_ASSERT(curr == kClosureNotReady || curr == kClosureReady);
     }
@@ -139,8 +143,13 @@ void LockfreeEvent::NotifyOn(grpc_closure* closure) {
            contains a pointer to the shutdown-error). If the fd is shutdown,
            schedule the closure with the shutdown error */
         if ((curr & kShutdownBit) > 0) {
+#ifdef GRPC_ERROR_IS_ABSEIL_STATUS
+          grpc_error_handle shutdown_err =
+              internal::StatusGetFromHeapPtr(curr & ~kShutdownBit);
+#else
           grpc_error_handle shutdown_err =
               reinterpret_cast<grpc_error_handle>(curr & ~kShutdownBit);
+#endif
           ExecCtx::Run(DEBUG_LOCATION, closure,
                        GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
                            "FD Shutdown", &shutdown_err, 1));
@@ -160,7 +169,12 @@ void LockfreeEvent::NotifyOn(grpc_closure* closure) {
 }
 
 bool LockfreeEvent::SetShutdown(grpc_error_handle shutdown_error) {
+#ifdef GRPC_ERROR_IS_ABSEIL_STATUS
+  intptr_t status_ptr = internal::StatusAllocHeapPtr(shutdown_error);
+  gpr_atm new_state = status_ptr | kShutdownBit;
+#else
   gpr_atm new_state = reinterpret_cast<gpr_atm>(shutdown_error) | kShutdownBit;
+#endif
 
   while (true) {
     gpr_atm curr = gpr_atm_no_barrier_load(&state_);
@@ -184,7 +198,11 @@ bool LockfreeEvent::SetShutdown(grpc_error_handle shutdown_error) {
 
         /* If fd is already shutdown, we are done */
         if ((curr & kShutdownBit) > 0) {
+#ifdef GRPC_ERROR_IS_ABSEIL_STATUS
+          internal::StatusFreeHeapPtr(status_ptr);
+#else
           GRPC_ERROR_UNREF(shutdown_error);
+#endif
           return false;
         }
 
index bad30fb..f70c2bc 100644 (file)
@@ -76,7 +76,7 @@ static grpc_error_handle pollset_work(grpc_pollset* pollset,
   // control back to the application
   grpc_core::ExecCtx* curr = grpc_core::ExecCtx::Get();
   grpc_core::ExecCtx::Set(nullptr);
-  grpc_error* err = poller_vtable->poll(static_cast<size_t>(timeout));
+  grpc_error_handle err = poller_vtable->poll(static_cast<size_t>(timeout));
   grpc_core::ExecCtx::Set(curr);
   grpc_core::ExecCtx::Get()->InvalidateNow();
   if (grpc_core::ExecCtx::Get()->HasWork()) {
index 4e6f382..f5c836e 100644 (file)
@@ -27,7 +27,7 @@
 
 typedef struct grpc_custom_poller_vtable {
   void (*init)();
-  grpc_error* (*poll)(size_t timeout_ms);
+  grpc_error_handle (*poll)(size_t timeout_ms);
   void (*kick)();
   void (*shutdown)();
 } grpc_custom_poller_vtable;
index 32816fe..1427cbd 100644 (file)
@@ -57,7 +57,7 @@ static grpc_error_handle posix_blocking_resolve_address(
   if (host.empty()) {
     err = grpc_error_set_str(
         GRPC_ERROR_CREATE_FROM_STATIC_STRING("unparseable host:port"),
-        GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(name));
+        GRPC_ERROR_STR_TARGET_ADDRESS, name);
     goto done;
   }
 
@@ -65,7 +65,7 @@ static grpc_error_handle posix_blocking_resolve_address(
     if (default_port == nullptr) {
       err = grpc_error_set_str(
           GRPC_ERROR_CREATE_FROM_STATIC_STRING("no port in name"),
-          GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(name));
+          GRPC_ERROR_STR_TARGET_ADDRESS, name);
       goto done;
     }
     port = default_port;
@@ -101,11 +101,9 @@ static grpc_error_handle posix_blocking_resolve_address(
                 grpc_error_set_int(
                     GRPC_ERROR_CREATE_FROM_STATIC_STRING(gai_strerror(s)),
                     GRPC_ERROR_INT_ERRNO, s),
-                GRPC_ERROR_STR_OS_ERROR,
-                grpc_slice_from_static_string(gai_strerror(s))),
-            GRPC_ERROR_STR_SYSCALL,
-            grpc_slice_from_static_string("getaddrinfo")),
-        GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(name));
+                GRPC_ERROR_STR_OS_ERROR, gai_strerror(s)),
+            GRPC_ERROR_STR_SYSCALL, "getaddrinfo"),
+        GRPC_ERROR_STR_TARGET_ADDRESS, name);
     goto done;
   }
 
index 838c62e..9f1ed40 100644 (file)
@@ -305,11 +305,12 @@ static void rq_step_sched(grpc_resource_quota* resource_quota) {
 static void rq_update_estimate(grpc_resource_quota* resource_quota) {
   gpr_atm memory_usage_estimation = MEMORY_USAGE_ESTIMATION_MAX;
   if (resource_quota->size != 0) {
-    memory_usage_estimation =
-        GPR_CLAMP((gpr_atm)((1.0 - ((double)resource_quota->free_pool) /
-                                       ((double)resource_quota->size)) *
-                            MEMORY_USAGE_ESTIMATION_MAX),
-                  0, MEMORY_USAGE_ESTIMATION_MAX);
+    memory_usage_estimation = grpc_core::Clamp(
+        static_cast<gpr_atm>(
+            (1.0 - (static_cast<double>(resource_quota->free_pool)) /
+                       (static_cast<double>(resource_quota->size))) *
+            MEMORY_USAGE_ESTIMATION_MAX),
+        gpr_atm(0), gpr_atm(MEMORY_USAGE_ESTIMATION_MAX));
   }
   gpr_atm_no_barrier_store(&resource_quota->memory_usage_estimation,
                            memory_usage_estimation);
@@ -729,7 +730,7 @@ void grpc_resource_quota_resize(grpc_resource_quota* resource_quota,
   a->resource_quota = grpc_resource_quota_ref_internal(resource_quota);
   a->size = static_cast<int64_t>(size);
   gpr_atm_no_barrier_store(&resource_quota->last_size,
-                           (gpr_atm)GPR_MIN((size_t)GPR_ATM_MAX, size));
+                           (gpr_atm)std::min((size_t)GPR_ATM_MAX, size));
   GRPC_CLOSURE_INIT(&a->closure, rq_resize, a, grpc_schedule_on_exec_ctx);
   grpc_core::ExecCtx::Run(DEBUG_LOCATION, &a->closure, GRPC_ERROR_NONE);
 }
@@ -762,7 +763,7 @@ static void rq_destroy(void* rq) {
   grpc_resource_quota_unref_internal(static_cast<grpc_resource_quota*>(rq));
 }
 
-static int rq_cmp(void* a, void* b) { return GPR_ICMP(a, b); }
+static int rq_cmp(void* a, void* b) { return grpc_core::QsortCompare(a, b); }
 
 const grpc_arg_pointer_vtable* grpc_resource_quota_arg_vtable(void) {
   static const grpc_arg_pointer_vtable vtable = {rq_copy, rq_destroy, rq_cmp};
@@ -1035,10 +1036,11 @@ static size_t grpc_slice_allocator_adjust_allocation_length(
   size_t target =
       requested_length * (pressure > 0.8 ? (1.0 - pressure) / 0.2 : 1.0);
   // Target will be some multiple of 8 bytes, rounded up
-  target = ((static_cast<size_t> GPR_CLAMP(target, slice_allocator->min_length,
-                                           slice_allocator->max_length)) +
-            255) &
-           ~static_cast<size_t>(255);
+  target =
+      (static_cast<size_t>(grpc_core::Clamp(target, slice_allocator->min_length,
+                                            slice_allocator->max_length)) +
+       255) &
+      ~static_cast<size_t>(255);
   // Don't use more than 1/16th of the overall resource quota for a single
   // read alloc
   size_t rqmax = grpc_resource_quota_peek_size(
index 50fb2ef..11f8656 100644 (file)
@@ -47,11 +47,11 @@ int grpc_socket_factory_bind(grpc_socket_factory* factory, int sockfd,
 
 int grpc_socket_factory_compare(grpc_socket_factory* a,
                                 grpc_socket_factory* b) {
-  int c = GPR_ICMP(a, b);
+  int c = grpc_core::QsortCompare(a, b);
   if (c != 0) {
     grpc_socket_factory* sma = a;
     grpc_socket_factory* smb = b;
-    c = GPR_ICMP(sma->vtable, smb->vtable);
+    c = grpc_core::QsortCompare(sma->vtable, smb->vtable);
     if (c == 0) {
       c = sma->vtable->compare(sma, smb);
     }
index b11d204..b908e22 100644 (file)
@@ -56,11 +56,11 @@ bool grpc_socket_mutator_mutate_fd(grpc_socket_mutator* mutator, int fd,
 
 int grpc_socket_mutator_compare(grpc_socket_mutator* a,
                                 grpc_socket_mutator* b) {
-  int c = GPR_ICMP(a, b);
+  int c = grpc_core::QsortCompare(a, b);
   if (c != 0) {
     grpc_socket_mutator* sma = a;
     grpc_socket_mutator* smb = b;
-    c = GPR_ICMP(sma->vtable, smb->vtable);
+    c = grpc_core::QsortCompare(sma->vtable, smb->vtable);
     if (c == 0) {
       c = sma->vtable->compare(sma, smb);
     }
index 53df6d6..7c6706b 100644 (file)
@@ -443,8 +443,7 @@ static grpc_error_handle error_for_fd(int fd,
   if (fd >= 0) return GRPC_ERROR_NONE;
   std::string addr_str = grpc_sockaddr_to_string(addr, false);
   grpc_error_handle err = grpc_error_set_str(
-      GRPC_OS_ERROR(errno, "socket"), GRPC_ERROR_STR_TARGET_ADDRESS,
-      grpc_slice_from_copied_string(addr_str.c_str()));
+      GRPC_OS_ERROR(errno, "socket"), GRPC_ERROR_STR_TARGET_ADDRESS, addr_str);
   return err;
 }
 
index d329f8d..5292e23 100644 (file)
@@ -81,7 +81,8 @@ static void CFStreamConnectCleanup(CFStreamConnect* connect) {
 static void OnAlarm(void* arg, grpc_error_handle error) {
   CFStreamConnect* connect = static_cast<CFStreamConnect*>(arg);
   if (grpc_tcp_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "CLIENT_CONNECT :%p OnAlarm, error:%p", connect, error);
+    gpr_log(GPR_DEBUG, "CLIENT_CONNECT :%p OnAlarm, error:%s", connect,
+            grpc_error_std_string(error).c_str());
   }
   gpr_mu_lock(&connect->mu);
   grpc_closure* closure = connect->closure;
@@ -102,7 +103,8 @@ static void OnAlarm(void* arg, grpc_error_handle error) {
 static void OnOpen(void* arg, grpc_error_handle error) {
   CFStreamConnect* connect = static_cast<CFStreamConnect*>(arg);
   if (grpc_tcp_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "CLIENT_CONNECT :%p OnOpen, error:%p", connect, error);
+    gpr_log(GPR_DEBUG, "CLIENT_CONNECT :%p OnOpen, error:%s", connect,
+            grpc_error_std_string(error).c_str());
   }
   gpr_mu_lock(&connect->mu);
   grpc_timer_cancel(&connect->alarm);
@@ -135,7 +137,7 @@ static void OnOpen(void* arg, grpc_error_handle error) {
         connect->slice_allocator = nullptr;
       }
     } else {
-      GRPC_ERROR_REF(error);
+      (void)GRPC_ERROR_REF(error);
     }
     gpr_mu_unlock(&connect->mu);
     grpc_core::ExecCtx::Run(DEBUG_LOCATION, closure, error);
index fea2522..363a492 100644 (file)
@@ -124,7 +124,7 @@ static void tcp_connect(grpc_closure* closure, grpc_endpoint** ep,
   grpc_custom_socket* socket =
       static_cast<grpc_custom_socket*>(gpr_malloc(sizeof(grpc_custom_socket)));
   socket->refs = 2;
-  grpc_custom_socket_vtable->init(socket, GRPC_AF_UNSPEC);
+  (void)grpc_custom_socket_vtable->init(socket, GRPC_AF_UNSPEC);
   grpc_custom_tcp_connect* connect = new grpc_custom_tcp_connect();
   connect->closure = closure;
   connect->endpoint = ep;
index 3e8d20a..f763cfe 100644 (file)
@@ -142,7 +142,7 @@ static void on_writable(void* acp, grpc_error_handle error) {
   grpc_closure* closure = ac->closure;
   grpc_fd* fd;
 
-  GRPC_ERROR_REF(error);
+  (void)GRPC_ERROR_REF(error);
 
   if (GRPC_TRACE_FLAG_ENABLED(grpc_tcp_trace)) {
     gpr_log(GPR_INFO, "CLIENT_CONNECT: %s: on_writable: error=%s",
@@ -160,8 +160,7 @@ static void on_writable(void* acp, grpc_error_handle error) {
   gpr_mu_lock(&ac->mu);
   if (error != GRPC_ERROR_NONE) {
     error =
-        grpc_error_set_str(error, GRPC_ERROR_STR_OS_ERROR,
-                           grpc_slice_from_static_string("Timeout occurred"));
+        grpc_error_set_str(error, GRPC_ERROR_STR_OS_ERROR, "Timeout occurred");
     goto finish;
   }
 
@@ -220,23 +219,16 @@ finish:
     fd = nullptr;
   }
   done = (--ac->refs == 0);
-  // Create a copy of the data from "ac" to be accessed after the unlock, as
-  // "ac" and its contents may be deallocated by the time they are read.
-  const grpc_slice addr_str_slice = grpc_slice_from_cpp_string(ac->addr_str);
   gpr_mu_unlock(&ac->mu);
   if (error != GRPC_ERROR_NONE) {
-    grpc_slice str;
+    std::string str;
     bool ret = grpc_error_get_str(error, GRPC_ERROR_STR_DESCRIPTION, &str);
     GPR_ASSERT(ret);
-    std::string description = absl::StrCat("Failed to connect to remote host: ",
-                                           grpc_core::StringViewFromSlice(str));
+    std::string description =
+        absl::StrCat("Failed to connect to remote host: ", str);
+    error = grpc_error_set_str(error, GRPC_ERROR_STR_DESCRIPTION, description);
     error =
-        grpc_error_set_str(error, GRPC_ERROR_STR_DESCRIPTION,
-                           grpc_slice_from_cpp_string(std::move(description)));
-    error = grpc_error_set_str(error, GRPC_ERROR_STR_TARGET_ADDRESS,
-                               addr_str_slice /* takes ownership */);
-  } else {
-    grpc_slice_unref_internal(addr_str_slice);
+        grpc_error_set_str(error, GRPC_ERROR_STR_TARGET_ADDRESS, ac->addr_str);
   }
   if (done) {
     // This is safe even outside the lock, because "done", the sentinel, is
@@ -309,9 +301,8 @@ void grpc_tcp_client_create_from_prepared_fd(
   if (errno != EWOULDBLOCK && errno != EINPROGRESS) {
     grpc_slice_allocator_destroy(slice_allocator);
     grpc_error_handle error = GRPC_OS_ERROR(errno, "connect");
-    error = grpc_error_set_str(
-        error, GRPC_ERROR_STR_TARGET_ADDRESS,
-        grpc_slice_from_cpp_string(grpc_sockaddr_to_uri(addr)));
+    error = grpc_error_set_str(error, GRPC_ERROR_STR_TARGET_ADDRESS,
+                               grpc_sockaddr_to_uri(addr));
     grpc_fd_orphan(fdobj, nullptr, nullptr, "tcp_client_connect_error");
     grpc_core::ExecCtx::Run(DEBUG_LOCATION, closure, error);
     return;
index 5138b88..7d20104 100644 (file)
@@ -86,7 +86,7 @@ static void on_connect(void* acp, grpc_error_handle error) {
   GPR_ASSERT(*ep == NULL);
   grpc_closure* on_done = ac->on_done;
 
-  GRPC_ERROR_REF(error);
+  (void)GRPC_ERROR_REF(error);
 
   gpr_mu_lock(&ac->mu);
   grpc_winsocket* socket = ac->socket;
@@ -225,8 +225,7 @@ failure:
   grpc_error_handle final_error =
       grpc_error_set_str(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
                              "Failed to connect", &error, 1),
-                         GRPC_ERROR_STR_TARGET_ADDRESS,
-                         grpc_slice_from_cpp_string(std::move(target_uri)));
+                         GRPC_ERROR_STR_TARGET_ADDRESS, target_uri);
   GRPC_ERROR_UNREF(error);
   grpc_slice_allocator_destroy(slice_allocator);
   if (socket != NULL) {
index 9d00000..a3e312b 100644 (file)
@@ -576,7 +576,7 @@ static void finish_estimate(grpc_tcp* tcp) {
      value */
   if (tcp->bytes_read_this_round > tcp->target_length * 0.8) {
     tcp->target_length =
-        GPR_MAX(2 * tcp->target_length, tcp->bytes_read_this_round);
+        std::max(2 * tcp->target_length, tcp->bytes_read_this_round);
   } else {
     tcp->target_length =
         0.99 * tcp->target_length + 0.01 * tcp->bytes_read_this_round;
@@ -592,8 +592,7 @@ static grpc_error_handle tcp_annotate_error(grpc_error_handle src_error,
           /* All tcp errors are marked with UNAVAILABLE so that application may
            * choose to retry. */
           GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE),
-      GRPC_ERROR_STR_TARGET_ADDRESS,
-      grpc_slice_from_copied_string(tcp->peer_string.c_str()));
+      GRPC_ERROR_STR_TARGET_ADDRESS, tcp->peer_string);
 }
 
 static void tcp_handle_read(void* arg /* grpc_tcp */, grpc_error_handle error);
@@ -1722,8 +1721,8 @@ grpc_endpoint* grpc_tcp_create(grpc_fd* em_fd,
   if (tcp_min_read_chunk_size > tcp_max_read_chunk_size) {
     tcp_min_read_chunk_size = tcp_max_read_chunk_size;
   }
-  tcp_read_chunk_size = GPR_CLAMP(tcp_read_chunk_size, tcp_min_read_chunk_size,
-                                  tcp_max_read_chunk_size);
+  tcp_read_chunk_size = grpc_core::Clamp(
+      tcp_read_chunk_size, tcp_min_read_chunk_size, tcp_max_read_chunk_size);
 
   grpc_tcp* tcp = new grpc_tcp(tcp_tx_zerocopy_max_simult_sends,
                                tcp_tx_zerocopy_send_bytes_thresh);
index cb622c0..a75b2cd 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "src/core/lib/address_utils/sockaddr_utils.h"
 #include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/gprpp/memory.h"
 #include "src/core/lib/iomgr/error.h"
 #include "src/core/lib/iomgr/exec_ctx.h"
 #include "src/core/lib/iomgr/iomgr_custom.h"
@@ -303,7 +304,7 @@ static grpc_error_handle add_socket_to_server(grpc_tcp_server* s,
 
   GPR_ASSERT(port >= 0);
   GPR_ASSERT(!s->on_accept_cb && "must add ports before starting server");
-  sp = static_cast<grpc_tcp_listener*>(gpr_zalloc(sizeof(grpc_tcp_listener)));
+  sp = grpc_core::Zalloc<grpc_tcp_listener>();
   sp->next = nullptr;
   if (s->head == nullptr) {
     s->head = sp;
index 73a118c..fc8ff01 100644 (file)
@@ -64,8 +64,7 @@ static grpc_error_handle tcp_server_create(
     grpc_closure* shutdown_complete, const grpc_channel_args* args,
     grpc_slice_allocator_factory* slice_allocator_factory,
     grpc_tcp_server** server) {
-  grpc_tcp_server* s =
-      static_cast<grpc_tcp_server*>(gpr_zalloc(sizeof(grpc_tcp_server)));
+  grpc_tcp_server* s = grpc_core::Zalloc<grpc_tcp_server>();
   s->so_reuseport = grpc_is_socket_reuse_port_supported();
   s->expand_wildcard_addrs = false;
   for (size_t i = 0; i < (args == nullptr ? 0 : args->num_args); i++) {
@@ -236,7 +235,7 @@ static void on_read(void* arg, grpc_error_handle err) {
       }
     }
 
-    grpc_set_socket_no_sigpipe_if_possible(fd);
+    (void)grpc_set_socket_no_sigpipe_if_possible(fd);
 
     err = grpc_apply_socket_mutator_in_args(fd, GRPC_FD_SERVER_CONNECTION_USAGE,
                                             sp->server->channel_args);
@@ -595,7 +594,7 @@ class ExternalConnectionHandler : public grpc_core::TcpServerFdHandler {
       close(fd);
       return;
     }
-    grpc_set_socket_no_sigpipe_if_possible(fd);
+    (void)grpc_set_socket_no_sigpipe_if_possible(fd);
     std::string addr_str = grpc_sockaddr_to_uri(&addr);
     if (grpc_tcp_trace.enabled()) {
       gpr_log(GPR_INFO, "SERVER_CONNECT: incoming external connection: %s",
index 80f4d35..e853c4f 100644 (file)
@@ -230,11 +230,10 @@ static grpc_error_handle prepare_socket(SOCKET sock,
 failure:
   GPR_ASSERT(error != GRPC_ERROR_NONE);
   grpc_error_set_int(
-      grpc_error_set_str(
-          GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
-              "Failed to prepare server socket", &error, 1),
-          GRPC_ERROR_STR_TARGET_ADDRESS,
-          grpc_slice_from_cpp_string(grpc_sockaddr_to_uri(addr))),
+      grpc_error_set_str(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
+                             "Failed to prepare server socket", &error, 1),
+                         GRPC_ERROR_STR_TARGET_ADDRESS,
+                         grpc_sockaddr_to_uri(addr)),
       GRPC_ERROR_INT_FD, (intptr_t)sock);
   GRPC_ERROR_UNREF(error);
   if (sock != INVALID_SOCKET) closesocket(sock);
index d0bca6b..4f2c151 100644 (file)
@@ -186,7 +186,7 @@ static void on_read(void* tcpp, grpc_error_handle error) {
     gpr_log(GPR_INFO, "TCP:%p on_read", tcp);
   }
 
-  GRPC_ERROR_REF(error);
+  (void)GRPC_ERROR_REF(error);
 
   if (error == GRPC_ERROR_NONE) {
     if (info->wsa_error != 0 && !tcp->shutting_down) {
@@ -322,7 +322,7 @@ static void on_write(void* tcpp, grpc_error_handle error) {
     gpr_log(GPR_INFO, "TCP:%p on_write", tcp);
   }
 
-  GRPC_ERROR_REF(error);
+  (void)GRPC_ERROR_REF(error);
 
   gpr_mu_lock(&tcp->mu);
   cb = tcp->write_cb;
index 109de1b..74761e2 100644 (file)
@@ -43,7 +43,7 @@
 
 #define ADD_DEADLINE_SCALE 0.33
 #define MIN_QUEUE_WINDOW_DURATION 0.01
-#define MAX_QUEUE_WINDOW_DURATION 1
+#define MAX_QUEUE_WINDOW_DURATION 1.0
 
 grpc_core::TraceFlag grpc_timer_trace(false, "timer");
 grpc_core::TraceFlag grpc_timer_check_trace(false, "timer_check");
@@ -105,7 +105,7 @@ static void destroy_timer_ht() {
 }
 
 static bool is_in_ht(grpc_timer* t) {
-  size_t i = GPR_HASH_POINTER(t, NUM_HASH_BUCKETS);
+  size_t i = grpc_core::HashPointer(t, NUM_HASH_BUCKETS);
 
   gpr_mu_lock(&g_hash_mu[i]);
   grpc_timer* p = g_timer_ht[i];
@@ -119,7 +119,7 @@ static bool is_in_ht(grpc_timer* t) {
 
 static void add_to_ht(grpc_timer* t) {
   GPR_ASSERT(!t->hash_table_next);
-  size_t i = GPR_HASH_POINTER(t, NUM_HASH_BUCKETS);
+  size_t i = grpc_core::HashPointer(t, NUM_HASH_BUCKETS);
 
   gpr_mu_lock(&g_hash_mu[i]);
   grpc_timer* p = g_timer_ht[i];
@@ -144,7 +144,7 @@ static void add_to_ht(grpc_timer* t) {
 }
 
 static void remove_from_ht(grpc_timer* t) {
-  size_t i = GPR_HASH_POINTER(t, NUM_HASH_BUCKETS);
+  size_t i = grpc_core::HashPointer(t, NUM_HASH_BUCKETS);
   bool removed = false;
 
   gpr_mu_lock(&g_hash_mu[i]);
@@ -248,7 +248,7 @@ static grpc_millis compute_min_deadline(timer_shard* shard) {
 static void timer_list_init() {
   uint32_t i;
 
-  g_num_shards = GPR_CLAMP(2 * gpr_cpu_num_cores(), 1, 32);
+  g_num_shards = grpc_core::Clamp(2 * gpr_cpu_num_cores(), 1u, 32u);
   g_shards =
       static_cast<timer_shard*>(gpr_zalloc(g_num_shards * sizeof(*g_shards)));
   g_shard_queue = static_cast<timer_shard**>(
@@ -337,7 +337,7 @@ void grpc_timer_init_unset(grpc_timer* timer) { timer->pending = false; }
 static void timer_init(grpc_timer* timer, grpc_millis deadline,
                        grpc_closure* closure) {
   int is_first_timer = 0;
-  timer_shard* shard = &g_shards[GPR_HASH_POINTER(timer, g_num_shards)];
+  timer_shard* shard = &g_shards[grpc_core::HashPointer(timer, g_num_shards)];
   timer->closure = closure;
   timer->deadline = deadline;
 
@@ -444,7 +444,7 @@ static void timer_cancel(grpc_timer* timer) {
     return;
   }
 
-  timer_shard* shard = &g_shards[GPR_HASH_POINTER(timer, g_num_shards)];
+  timer_shard* shard = &g_shards[grpc_core::HashPointer(timer, g_num_shards)];
   gpr_mu_lock(&shard->mu);
   if (GRPC_TRACE_FLAG_ENABLED(grpc_timer_trace)) {
     gpr_log(GPR_INFO, "TIMER %p: CANCEL pending=%s", timer,
@@ -479,13 +479,13 @@ static bool refill_heap(timer_shard* shard, grpc_millis now) {
       grpc_time_averaged_stats_update_average(&shard->stats) *
       ADD_DEADLINE_SCALE;
   double deadline_delta =
-      GPR_CLAMP(computed_deadline_delta, MIN_QUEUE_WINDOW_DURATION,
-                MAX_QUEUE_WINDOW_DURATION);
+      grpc_core::Clamp(computed_deadline_delta, MIN_QUEUE_WINDOW_DURATION,
+                       MAX_QUEUE_WINDOW_DURATION);
   grpc_timer *timer, *next;
 
   /* Compute the new cap and put all timers under it into the queue: */
   shard->queue_deadline_cap =
-      saturating_add(GPR_MAX(now, shard->queue_deadline_cap),
+      saturating_add(std::max(now, shard->queue_deadline_cap),
                      static_cast<grpc_millis>(deadline_delta * 1000.0));
 
   if (GRPC_TRACE_FLAG_ENABLED(grpc_timer_check_trace)) {
@@ -583,7 +583,7 @@ static grpc_timer_check_result run_some_expired_timers(
   g_last_seen_min_timer = min_timer;
 
   if (now < min_timer) {
-    if (next != nullptr) *next = GPR_MIN(*next, min_timer);
+    if (next != nullptr) *next = std::min(*next, min_timer);
     return GRPC_TIMERS_CHECKED_AND_EMPTY;
   }
 
@@ -628,7 +628,7 @@ static grpc_timer_check_result run_some_expired_timers(
     }
 
     if (next) {
-      *next = GPR_MIN(*next, g_shard_queue[0]->min_deadline);
+      *next = std::min(*next, g_shard_queue[0]->min_deadline);
     }
 
 #if GPR_ARCH_64
@@ -663,7 +663,7 @@ static grpc_timer_check_result timer_check(grpc_millis* next) {
 
   if (now < min_timer) {
     if (next != nullptr) {
-      *next = GPR_MIN(*next, min_timer);
+      *next = std::min(*next, min_timer);
     }
     if (GRPC_TRACE_FLAG_ENABLED(grpc_timer_check_trace)) {
       gpr_log(GPR_INFO, "TIMER CHECK SKIP: now=%" PRId64 " min_timer=%" PRId64,
index 5c53fad..604bfe1 100644 (file)
@@ -97,7 +97,7 @@ void grpc_timer_heap_destroy(grpc_timer_heap* heap) { gpr_free(heap->timers); }
 bool grpc_timer_heap_add(grpc_timer_heap* heap, grpc_timer* timer) {
   if (heap->timer_count == heap->timer_capacity) {
     heap->timer_capacity =
-        GPR_MAX(heap->timer_capacity + 1, heap->timer_capacity * 3 / 2);
+        std::max(heap->timer_capacity + 1, heap->timer_capacity * 3 / 2);
     heap->timers = static_cast<grpc_timer**>(
         gpr_realloc(heap->timers, heap->timer_capacity * sizeof(grpc_timer*)));
   }
diff --git a/src/core/lib/iomgr/udp_server.cc b/src/core/lib/iomgr/udp_server.cc
deleted file mode 100644 (file)
index 653e78e..0000000
+++ /dev/null
@@ -1,747 +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.
- *
- */
-
-/* FIXME: "posix" files shouldn't be depending on _GNU_SOURCE */
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
-#ifndef SO_RXQ_OVFL
-#define SO_RXQ_OVFL 40
-#endif
-
-#include <grpc/support/port_platform.h>
-
-#include "src/core/lib/iomgr/port.h"
-
-#ifdef GRPC_POSIX_SOCKET_UDP_SERVER
-
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <string>
-#include <vector>
-
-#include "absl/container/inlined_vector.h"
-#include "absl/strings/str_cat.h"
-
-#include <grpc/grpc.h>
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-#include <grpc/support/sync.h>
-#include <grpc/support/time.h>
-
-#include "src/core/lib/address_utils/sockaddr_utils.h"
-#include "src/core/lib/channel/channel_args.h"
-#include "src/core/lib/gpr/string.h"
-#include "src/core/lib/gprpp/memory.h"
-#include "src/core/lib/iomgr/error.h"
-#include "src/core/lib/iomgr/ev_posix.h"
-#include "src/core/lib/iomgr/executor.h"
-#include "src/core/lib/iomgr/resolve_address.h"
-#include "src/core/lib/iomgr/sockaddr.h"
-#include "src/core/lib/iomgr/socket_factory_posix.h"
-#include "src/core/lib/iomgr/socket_utils_posix.h"
-#include "src/core/lib/iomgr/udp_server.h"
-#include "src/core/lib/iomgr/unix_sockets_posix.h"
-
-/* A listener which implements basic features of Listening on a port for
- * I/O events*/
-class GrpcUdpListener {
- public:
-  GrpcUdpListener(grpc_udp_server* server, int fd,
-                  const grpc_resolved_address* addr);
-  ~GrpcUdpListener();
-
-  /* Called when grpc server starts to listening on the grpc_fd. */
-  void StartListening(const std::vector<grpc_pollset*>* pollsets,
-                      GrpcUdpHandlerFactory* handler_factory);
-
-  /* Called when data is available to read from the socket.
-   * Return true if there is more data to read from fd. */
-  void OnRead(grpc_error_handle error, void* do_read_arg);
-
-  /* Called when the socket is writeable. The given closure should be scheduled
-   * when the socket becomes blocked next time. */
-  void OnCanWrite(grpc_error_handle error, void* do_write_arg);
-
-  /* Called when the grpc_fd is about to be orphaned (and the FD closed). */
-  void OnFdAboutToOrphan();
-
-  /* Called to orphan fd of this listener.*/
-  void OrphanFd();
-
-  /* Called when this listener is going to be destroyed. */
-  void OnDestroy();
-
-  int fd() const { return fd_; }
-
- protected:
-  grpc_fd* emfd() const { return emfd_; }
-
-  gpr_mu* mutex() { return &mutex_; }
-
- private:
-  /* event manager callback when reads are ready */
-  static void on_read(void* arg, grpc_error_handle error);
-  static void on_write(void* arg, grpc_error_handle error);
-
-  static void do_read(void* arg, grpc_error_handle error);
-  static void do_write(void* arg, grpc_error_handle error);
-  // Wrapper of grpc_fd_notify_on_write() with a grpc_closure callback
-  // interface.
-  static void fd_notify_on_write_wrapper(void* arg, grpc_error_handle error);
-
-  static void shutdown_fd(void* args, grpc_error_handle error);
-
-  int fd_;
-  grpc_fd* emfd_;
-  grpc_udp_server* server_;
-  grpc_resolved_address addr_;
-  grpc_closure read_closure_;
-  grpc_closure write_closure_;
-  // To be called when corresponding QuicGrpcServer closes all active
-  // connections.
-  grpc_closure orphan_fd_closure_;
-  grpc_closure destroyed_closure_;
-  // To be scheduled on another thread to actually read/write.
-  grpc_closure do_read_closure_;
-  grpc_closure do_write_closure_;
-  grpc_closure notify_on_write_closure_;
-  // True if orphan_cb is trigered.
-  bool orphan_notified_;
-  // True if grpc_fd_notify_on_write() is called after on_write() call.
-  bool notify_on_write_armed_;
-  // True if fd has been shutdown.
-  bool already_shutdown_;
-  // Object actually handles I/O events. Assigned in StartListening().
-  GrpcUdpHandler* udp_handler_ = nullptr;
-  // To be notified on destruction.
-  GrpcUdpHandlerFactory* handler_factory_ = nullptr;
-  // Required to access above fields.
-  gpr_mu mutex_;
-};
-
-GrpcUdpListener::GrpcUdpListener(grpc_udp_server* server, int fd,
-                                 const grpc_resolved_address* addr)
-    : fd_(fd),
-      server_(server),
-      orphan_notified_(false),
-      already_shutdown_(false) {
-  std::string addr_str = grpc_sockaddr_to_string(addr, true);
-  std::string name = absl::StrCat("udp-server-listener:", addr_str);
-  emfd_ = grpc_fd_create(fd, name.c_str(), true);
-  memcpy(&addr_, addr, sizeof(grpc_resolved_address));
-  GPR_ASSERT(emfd_);
-  gpr_mu_init(&mutex_);
-}
-
-GrpcUdpListener::~GrpcUdpListener() { gpr_mu_destroy(&mutex_); }
-
-/* the overall server */
-struct grpc_udp_server {
-  gpr_mu mu;
-
-  /* factory to use for creating and binding sockets, or NULL */
-  grpc_socket_factory* socket_factory;
-
-  /* active port count: how many ports are actually still listening */
-  size_t active_ports;
-  /* destroyed port count: how many ports are completely destroyed */
-  size_t destroyed_ports;
-
-  /* is this server shutting down? (boolean) */
-  int shutdown;
-
-  /* An array of listeners */
-  absl::InlinedVector<GrpcUdpListener, 16> listeners;
-
-  /* factory for use to create udp listeners */
-  GrpcUdpHandlerFactory* handler_factory;
-
-  /* shutdown callback */
-  grpc_closure* shutdown_complete;
-
-  /* all pollsets interested in new connections. The object pointed at is not
-   * owned by this struct. */
-  const std::vector<grpc_pollset*>* pollsets;
-  /* opaque object to pass to callbacks */
-  void* user_data;
-
-  /* latch has_so_reuseport during server creation */
-  bool so_reuseport;
-};
-
-static grpc_socket_factory* get_socket_factory(const grpc_channel_args* args) {
-  if (args) {
-    const grpc_arg* arg = grpc_channel_args_find(args, GRPC_ARG_SOCKET_FACTORY);
-    if (arg) {
-      GPR_ASSERT(arg->type == GRPC_ARG_POINTER);
-      return static_cast<grpc_socket_factory*>(arg->value.pointer.p);
-    }
-  }
-  return nullptr;
-}
-
-grpc_udp_server* grpc_udp_server_create(const grpc_channel_args* args) {
-  grpc_udp_server* s = new grpc_udp_server();
-  gpr_mu_init(&s->mu);
-  s->socket_factory = get_socket_factory(args);
-  if (s->socket_factory) {
-    grpc_socket_factory_ref(s->socket_factory);
-  }
-  s->active_ports = 0;
-  s->destroyed_ports = 0;
-  s->shutdown = 0;
-  s->so_reuseport = grpc_is_socket_reuse_port_supported();
-  return s;
-}
-
-// static
-void GrpcUdpListener::shutdown_fd(void* args, grpc_error_handle error) {
-  if (args == nullptr) {
-    // No-op if shutdown args are null.
-    return;
-  }
-  auto sp = static_cast<GrpcUdpListener*>(args);
-  gpr_mu_lock(sp->mutex());
-  gpr_log(GPR_DEBUG, "shutdown fd %d", sp->fd_);
-  grpc_fd_shutdown(sp->emfd_, GRPC_ERROR_REF(error));
-  sp->already_shutdown_ = true;
-  if (!sp->notify_on_write_armed_) {
-    // Re-arm write notification to notify listener with error. This is
-    // necessary to decrement active_ports.
-    sp->notify_on_write_armed_ = true;
-    grpc_fd_notify_on_write(sp->emfd_, &sp->write_closure_);
-  }
-  gpr_mu_unlock(sp->mutex());
-}
-
-static void finish_shutdown(grpc_udp_server* s) {
-  if (s->shutdown_complete != nullptr) {
-    grpc_core::ExecCtx::Run(DEBUG_LOCATION, s->shutdown_complete,
-                            GRPC_ERROR_NONE);
-  }
-
-  gpr_mu_destroy(&s->mu);
-
-  gpr_log(GPR_DEBUG, "Destroy all listeners.");
-  for (size_t i = 0; i < s->listeners.size(); ++i) {
-    s->listeners[i].OnDestroy();
-  }
-
-  if (s->socket_factory) {
-    grpc_socket_factory_unref(s->socket_factory);
-  }
-
-  delete s;
-}
-
-static void destroyed_port(void* server, grpc_error_handle /*error*/) {
-  grpc_udp_server* s = static_cast<grpc_udp_server*>(server);
-  gpr_mu_lock(&s->mu);
-  s->destroyed_ports++;
-  if (s->destroyed_ports == s->listeners.size()) {
-    gpr_mu_unlock(&s->mu);
-    finish_shutdown(s);
-  } else {
-    gpr_mu_unlock(&s->mu);
-  }
-}
-
-/* called when all listening endpoints have been shutdown, so no further
-   events will be received on them - at this point it's safe to destroy
-   things */
-static void deactivated_all_ports(grpc_udp_server* s) {
-  /* delete ALL the things */
-  gpr_mu_lock(&s->mu);
-
-  GPR_ASSERT(s->shutdown);
-
-  if (s->listeners.empty()) {
-    gpr_mu_unlock(&s->mu);
-    finish_shutdown(s);
-    return;
-  }
-  for (size_t i = 0; i < s->listeners.size(); ++i) {
-    s->listeners[i].OrphanFd();
-  }
-  gpr_mu_unlock(&s->mu);
-}
-
-void GrpcUdpListener::OrphanFd() {
-  gpr_log(GPR_DEBUG, "Orphan fd %d, emfd %p", fd_, emfd_);
-  grpc_unlink_if_unix_domain_socket(&addr_);
-
-  GRPC_CLOSURE_INIT(&destroyed_closure_, destroyed_port, server_,
-                    grpc_schedule_on_exec_ctx);
-  /* Because at this point, all listening sockets have been shutdown already, no
-   * need to call OnFdAboutToOrphan() to notify the handler again. */
-  grpc_fd_orphan(emfd_, &destroyed_closure_, nullptr, "udp_listener_shutdown");
-}
-
-void grpc_udp_server_destroy(grpc_udp_server* s, grpc_closure* on_done) {
-  gpr_mu_lock(&s->mu);
-
-  GPR_ASSERT(!s->shutdown);
-  s->shutdown = 1;
-
-  s->shutdown_complete = on_done;
-
-  gpr_log(GPR_DEBUG, "start to destroy udp_server");
-  /* shutdown all fd's */
-  if (s->active_ports) {
-    for (size_t i = 0; i < s->listeners.size(); ++i) {
-      GrpcUdpListener* sp = &s->listeners[i];
-      sp->OnFdAboutToOrphan();
-    }
-    gpr_mu_unlock(&s->mu);
-  } else {
-    gpr_mu_unlock(&s->mu);
-    deactivated_all_ports(s);
-  }
-}
-
-void GrpcUdpListener::OnFdAboutToOrphan() {
-  gpr_mu_lock(&mutex_);
-  grpc_unlink_if_unix_domain_socket(&addr_);
-
-  GRPC_CLOSURE_INIT(&destroyed_closure_, destroyed_port, server_,
-                    grpc_schedule_on_exec_ctx);
-  if (!orphan_notified_ && udp_handler_ != nullptr) {
-    /* Signals udp_handler that the FD is about to be closed and
-     * should no longer be used. */
-    GRPC_CLOSURE_INIT(&orphan_fd_closure_, shutdown_fd, this,
-                      grpc_schedule_on_exec_ctx);
-    gpr_log(GPR_DEBUG, "fd %d about to be orphaned", fd_);
-    udp_handler_->OnFdAboutToOrphan(&orphan_fd_closure_, server_->user_data);
-    orphan_notified_ = true;
-  }
-  gpr_mu_unlock(&mutex_);
-}
-
-static int bind_socket(grpc_socket_factory* socket_factory, int sockfd,
-                       const grpc_resolved_address* addr) {
-  return (socket_factory != nullptr)
-             ? grpc_socket_factory_bind(socket_factory, sockfd, addr)
-             : bind(sockfd,
-                    reinterpret_cast<grpc_sockaddr*>(
-                        const_cast<char*>(addr->addr)),
-                    addr->len);
-}
-
-/* Prepare a recently-created socket for listening. */
-static int prepare_socket(grpc_socket_factory* socket_factory, int fd,
-                          const grpc_resolved_address* addr, int rcv_buf_size,
-                          int snd_buf_size, bool so_reuseport) {
-  grpc_resolved_address sockname_temp;
-  grpc_sockaddr* addr_ptr =
-      reinterpret_cast<grpc_sockaddr*>(const_cast<char*>(addr->addr));
-
-  if (fd < 0) {
-    goto error;
-  }
-
-  if (grpc_set_socket_nonblocking(fd, 1) != GRPC_ERROR_NONE) {
-    gpr_log(GPR_ERROR, "Unable to set nonblocking %d: %s", fd, strerror(errno));
-    goto error;
-  }
-  if (grpc_set_socket_cloexec(fd, 1) != GRPC_ERROR_NONE) {
-    gpr_log(GPR_ERROR, "Unable to set cloexec %d: %s", fd, strerror(errno));
-    goto error;
-  }
-
-  if (grpc_set_socket_ip_pktinfo_if_possible(fd) != GRPC_ERROR_NONE) {
-    gpr_log(GPR_ERROR, "Unable to set ip_pktinfo.");
-    goto error;
-  } else if (addr_ptr->sa_family == AF_INET6) {
-    if (grpc_set_socket_ipv6_recvpktinfo_if_possible(fd) != GRPC_ERROR_NONE) {
-      gpr_log(GPR_ERROR, "Unable to set ipv6_recvpktinfo.");
-      goto error;
-    }
-  }
-
-  if (grpc_set_socket_sndbuf(fd, snd_buf_size) != GRPC_ERROR_NONE) {
-    gpr_log(GPR_ERROR, "Failed to set send buffer size to %d bytes",
-            snd_buf_size);
-    goto error;
-  }
-
-  if (grpc_set_socket_rcvbuf(fd, rcv_buf_size) != GRPC_ERROR_NONE) {
-    gpr_log(GPR_ERROR, "Failed to set receive buffer size to %d bytes",
-            rcv_buf_size);
-    goto error;
-  }
-
-  {
-    int get_overflow = 1;
-    if (0 != setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, &get_overflow,
-                        sizeof(get_overflow))) {
-      gpr_log(GPR_INFO, "Failed to set socket overflow support");
-    }
-  }
-
-  if (so_reuseport && !grpc_is_unix_socket(addr) &&
-      grpc_set_socket_reuse_port(fd, 1) != GRPC_ERROR_NONE) {
-    gpr_log(GPR_ERROR, "Failed to set SO_REUSEPORT for fd %d", fd);
-    goto error;
-  }
-
-  if (bind_socket(socket_factory, fd, addr) < 0) {
-    std::string addr_str = grpc_sockaddr_to_string(addr, false);
-    gpr_log(GPR_ERROR, "bind addr=%s: %s", addr_str.c_str(), strerror(errno));
-    goto error;
-  }
-
-  sockname_temp.len = static_cast<socklen_t>(sizeof(struct sockaddr_storage));
-
-  if (getsockname(fd, reinterpret_cast<grpc_sockaddr*>(sockname_temp.addr),
-                  &sockname_temp.len) < 0) {
-    gpr_log(GPR_ERROR, "Unable to get the address socket %d is bound to: %s",
-            fd, strerror(errno));
-    goto error;
-  }
-
-  return grpc_sockaddr_get_port(&sockname_temp);
-
-error:
-  if (fd >= 0) {
-    close(fd);
-  }
-  return -1;
-}
-
-// static
-void GrpcUdpListener::do_read(void* arg, grpc_error_handle error) {
-  GrpcUdpListener* sp = static_cast<GrpcUdpListener*>(arg);
-  GPR_ASSERT(error == GRPC_ERROR_NONE);
-  /* TODO: the reason we hold server->mu here is merely to prevent fd
-   * shutdown while we are reading. However, it blocks do_write(). Switch to
-   * read lock if available. */
-  gpr_mu_lock(sp->mutex());
-  /* Tell the registered callback that data is available to read. */
-  if (!sp->already_shutdown_ && sp->udp_handler_->Read()) {
-    /* There maybe more packets to read. Schedule read_more_cb_ closure to run
-     * after finishing this event loop. */
-    grpc_core::Executor::Run(&sp->do_read_closure_, GRPC_ERROR_NONE,
-                             grpc_core::ExecutorType::DEFAULT,
-                             grpc_core::ExecutorJobType::LONG);
-  } else {
-    /* Finish reading all the packets, re-arm the notification event so we can
-     * get another chance to read. Or fd already shutdown, re-arm to get a
-     * notification with shutdown error. */
-    grpc_fd_notify_on_read(sp->emfd_, &sp->read_closure_);
-  }
-  gpr_mu_unlock(sp->mutex());
-}
-
-// static
-void GrpcUdpListener::on_read(void* arg, grpc_error_handle error) {
-  GrpcUdpListener* sp = static_cast<GrpcUdpListener*>(arg);
-  sp->OnRead(error, arg);
-}
-
-void GrpcUdpListener::OnRead(grpc_error_handle error, void* do_read_arg) {
-  if (error != GRPC_ERROR_NONE) {
-    gpr_mu_lock(&server_->mu);
-    if (0 == --server_->active_ports && server_->shutdown) {
-      gpr_mu_unlock(&server_->mu);
-      deactivated_all_ports(server_);
-    } else {
-      gpr_mu_unlock(&server_->mu);
-    }
-    return;
-  }
-
-  /* Read once. If there is more data to read, off load the work to another
-   * thread to finish. */
-  if (udp_handler_->Read()) {
-    /* There maybe more packets to read. Schedule read_more_cb_ closure to run
-     * after finishing this event loop. */
-    GRPC_CLOSURE_INIT(&do_read_closure_, do_read, do_read_arg, nullptr);
-    grpc_core::Executor::Run(&do_read_closure_, GRPC_ERROR_NONE,
-                             grpc_core::ExecutorType::DEFAULT,
-                             grpc_core::ExecutorJobType::LONG);
-  } else {
-    /* Finish reading all the packets, re-arm the notification event so we can
-     * get another chance to read. Or fd already shutdown, re-arm to get a
-     * notification with shutdown error. */
-    grpc_fd_notify_on_read(emfd_, &read_closure_);
-  }
-}
-
-// static
-// Wrapper of grpc_fd_notify_on_write() with a grpc_closure callback interface.
-void GrpcUdpListener::fd_notify_on_write_wrapper(void* arg,
-                                                 grpc_error_handle /*error*/) {
-  GrpcUdpListener* sp = static_cast<GrpcUdpListener*>(arg);
-  gpr_mu_lock(sp->mutex());
-  if (!sp->notify_on_write_armed_) {
-    grpc_fd_notify_on_write(sp->emfd_, &sp->write_closure_);
-    sp->notify_on_write_armed_ = true;
-  }
-  gpr_mu_unlock(sp->mutex());
-}
-
-// static
-void GrpcUdpListener::do_write(void* arg, grpc_error_handle error) {
-  GrpcUdpListener* sp = static_cast<GrpcUdpListener*>(arg);
-  gpr_mu_lock(sp->mutex());
-  if (sp->already_shutdown_) {
-    // If fd has been shutdown, don't write any more and re-arm notification.
-    grpc_fd_notify_on_write(sp->emfd_, &sp->write_closure_);
-  } else {
-    sp->notify_on_write_armed_ = false;
-    /* Tell the registered callback that the socket is writeable. */
-    GPR_ASSERT(error == GRPC_ERROR_NONE);
-    GRPC_CLOSURE_INIT(&sp->notify_on_write_closure_, fd_notify_on_write_wrapper,
-                      arg, grpc_schedule_on_exec_ctx);
-    sp->udp_handler_->OnCanWrite(sp->server_->user_data,
-                                 &sp->notify_on_write_closure_);
-  }
-  gpr_mu_unlock(sp->mutex());
-}
-
-// static
-void GrpcUdpListener::on_write(void* arg, grpc_error_handle error) {
-  GrpcUdpListener* sp = static_cast<GrpcUdpListener*>(arg);
-  sp->OnCanWrite(error, arg);
-}
-
-void GrpcUdpListener::OnCanWrite(grpc_error_handle error, void* do_write_arg) {
-  if (error != GRPC_ERROR_NONE) {
-    gpr_mu_lock(&server_->mu);
-    if (0 == --server_->active_ports && server_->shutdown) {
-      gpr_mu_unlock(&server_->mu);
-      deactivated_all_ports(server_);
-    } else {
-      gpr_mu_unlock(&server_->mu);
-    }
-    return;
-  }
-
-  /* Schedule actual write in another thread. */
-  GRPC_CLOSURE_INIT(&do_write_closure_, do_write, do_write_arg, nullptr);
-
-  grpc_core::Executor::Run(&do_write_closure_, GRPC_ERROR_NONE,
-                           grpc_core::ExecutorType::DEFAULT,
-                           grpc_core::ExecutorJobType::LONG);
-}
-
-static int add_socket_to_server(grpc_udp_server* s, int fd,
-                                const grpc_resolved_address* addr,
-                                int rcv_buf_size, int snd_buf_size) {
-  gpr_log(GPR_DEBUG, "add socket %d to server", fd);
-
-  int port = prepare_socket(s->socket_factory, fd, addr, rcv_buf_size,
-                            snd_buf_size, s->so_reuseport);
-  if (port >= 0) {
-    gpr_mu_lock(&s->mu);
-    s->listeners.emplace_back(s, fd, addr);
-    gpr_log(GPR_DEBUG,
-            "add socket %d to server for port %d, %zu listener(s) in total", fd,
-            port, s->listeners.size());
-    gpr_mu_unlock(&s->mu);
-  }
-  return port;
-}
-
-int grpc_udp_server_add_port(grpc_udp_server* s, grpc_resolved_address* addr,
-                             int rcv_buf_size, int snd_buf_size,
-                             GrpcUdpHandlerFactory* handler_factory,
-                             size_t num_listeners) {
-  if (num_listeners > 1 && !s->so_reuseport) {
-    gpr_log(GPR_ERROR,
-            "Try to have multiple listeners on same port, but SO_REUSEPORT is "
-            "not supported. Only create 1 listener.");
-  }
-  std::string addr_str = grpc_sockaddr_to_string(addr, true);
-  gpr_log(GPR_DEBUG, "add address: %s to server", addr_str.c_str());
-
-  int allocated_port1 = -1;
-  int allocated_port2 = -1;
-  int fd;
-  grpc_dualstack_mode dsmode;
-  grpc_resolved_address addr6_v4mapped;
-  grpc_resolved_address wild4;
-  grpc_resolved_address wild6;
-  grpc_resolved_address addr4_copy;
-  grpc_resolved_address* allocated_addr = nullptr;
-  grpc_resolved_address sockname_temp;
-  int port = 0;
-
-  /* Check if this is a wildcard port, and if so, try to keep the port the same
-     as some previously created listener. */
-  if (grpc_sockaddr_get_port(addr) == 0) {
-    /* Loop through existing listeners to find the port in use. */
-    for (size_t i = 0; i < s->listeners.size(); ++i) {
-      sockname_temp.len =
-          static_cast<socklen_t>(sizeof(struct sockaddr_storage));
-      if (0 == getsockname(s->listeners[i].fd(),
-                           reinterpret_cast<grpc_sockaddr*>(sockname_temp.addr),
-                           &sockname_temp.len)) {
-        port = grpc_sockaddr_get_port(&sockname_temp);
-        if (port > 0) {
-          /* Found such a port, update |addr| to reflects this port. */
-          allocated_addr = static_cast<grpc_resolved_address*>(
-              gpr_malloc(sizeof(grpc_resolved_address)));
-          memcpy(allocated_addr, addr, sizeof(grpc_resolved_address));
-          grpc_sockaddr_set_port(allocated_addr, port);
-          addr = allocated_addr;
-          break;
-        }
-      }
-    }
-  }
-
-  if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
-    addr = &addr6_v4mapped;
-  }
-
-  s->handler_factory = handler_factory;
-  for (size_t i = 0; i < num_listeners; ++i) {
-    /* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */
-    if (grpc_sockaddr_is_wildcard(addr, &port)) {
-      grpc_sockaddr_make_wildcards(port, &wild4, &wild6);
-
-      /* Try listening on IPv6 first. */
-      addr = &wild6;
-      // TODO(rjshade): Test and propagate the returned grpc_error_handle:
-      GRPC_ERROR_UNREF(grpc_create_dualstack_socket_using_factory(
-          s->socket_factory, addr, SOCK_DGRAM, IPPROTO_UDP, &dsmode, &fd));
-      allocated_port1 =
-          add_socket_to_server(s, fd, addr, rcv_buf_size, snd_buf_size);
-      if (fd >= 0 && dsmode == GRPC_DSMODE_DUALSTACK) {
-        if (port == 0) {
-          /* This is the first time to bind to |addr|. If its port is still
-           * wildcard port, update |addr| with the ephermeral port returned by
-           * kernel. Thus |addr| can have a specific port in following
-           * iterations. */
-          grpc_sockaddr_set_port(addr, allocated_port1);
-          port = allocated_port1;
-        } else if (allocated_port1 >= 0) {
-          /* The following successfully created socket should have same port as
-           * the first one. */
-          GPR_ASSERT(port == allocated_port1);
-        }
-        /* A dualstack socket is created, no need to create corresponding IPV4
-         * socket. */
-        continue;
-      }
-
-      /* If we didn't get a dualstack socket, also listen on 0.0.0.0. */
-      if (port == 0 && allocated_port1 > 0) {
-        /* |port| hasn't been assigned to an emphemeral port yet, |wild4| must
-         * have a wildcard port. Update it with the emphemeral port created
-         * during binding.*/
-        grpc_sockaddr_set_port(&wild4, allocated_port1);
-        port = allocated_port1;
-      }
-      /* |wild4| should have been updated with an emphemeral port by now. Use
-       * this IPV4 address to create a IPV4 socket. */
-      addr = &wild4;
-    }
-
-    // TODO(rjshade): Test and propagate the returned grpc_error_handle:
-    GRPC_ERROR_UNREF(grpc_create_dualstack_socket_using_factory(
-        s->socket_factory, addr, SOCK_DGRAM, IPPROTO_UDP, &dsmode, &fd));
-    if (fd < 0) {
-      gpr_log(GPR_ERROR, "Unable to create socket: %s", strerror(errno));
-    }
-    if (dsmode == GRPC_DSMODE_IPV4 &&
-        grpc_sockaddr_is_v4mapped(addr, &addr4_copy)) {
-      addr = &addr4_copy;
-    }
-    allocated_port2 =
-        add_socket_to_server(s, fd, addr, rcv_buf_size, snd_buf_size);
-    if (port == 0) {
-      /* Update |addr| with the ephermeral port returned by kernel. So |addr|
-       * can have a specific port in following iterations. */
-      grpc_sockaddr_set_port(addr, allocated_port2);
-      port = allocated_port2;
-    } else if (allocated_port2 >= 0) {
-      GPR_ASSERT(port == allocated_port2);
-    }
-  }
-
-  gpr_free(allocated_addr);
-  return port;
-}
-
-int grpc_udp_server_get_fd(grpc_udp_server* s, unsigned port_index) {
-  if (port_index >= s->listeners.size()) {
-    return -1;
-  }
-
-  return s->listeners[port_index].fd();
-}
-
-void grpc_udp_server_start(grpc_udp_server* udp_server,
-                           const std::vector<grpc_pollset*>* pollsets,
-                           void* user_data) {
-  gpr_log(GPR_DEBUG, "grpc_udp_server_start");
-  gpr_mu_lock(&udp_server->mu);
-  GPR_ASSERT(udp_server->active_ports == 0);
-  udp_server->pollsets = pollsets;
-  udp_server->user_data = user_data;
-
-  for (auto& listener : udp_server->listeners) {
-    listener.StartListening(pollsets, udp_server->handler_factory);
-  }
-
-  gpr_mu_unlock(&udp_server->mu);
-}
-
-void GrpcUdpListener::StartListening(const std::vector<grpc_pollset*>* pollsets,
-                                     GrpcUdpHandlerFactory* handler_factory) {
-  gpr_mu_lock(&mutex_);
-  handler_factory_ = handler_factory;
-  udp_handler_ = handler_factory->CreateUdpHandler(emfd_, server_->user_data);
-  for (grpc_pollset* pollset : *pollsets) {
-    grpc_pollset_add_fd(pollset, emfd_);
-  }
-  GRPC_CLOSURE_INIT(&read_closure_, on_read, this, grpc_schedule_on_exec_ctx);
-  grpc_fd_notify_on_read(emfd_, &read_closure_);
-
-  GRPC_CLOSURE_INIT(&write_closure_, on_write, this, grpc_schedule_on_exec_ctx);
-  notify_on_write_armed_ = true;
-  grpc_fd_notify_on_write(emfd_, &write_closure_);
-
-  /* Registered for both read and write callbacks: increment active_ports
-   * twice to account for this, and delay free-ing of memory until both
-   * on_read and on_write have fired. */
-  server_->active_ports += 2;
-  gpr_mu_unlock(&mutex_);
-}
-
-void GrpcUdpListener::OnDestroy() {
-  if (udp_handler_ != nullptr) {
-    handler_factory_->DestroyUdpHandler(udp_handler_);
-  }
-}
-
-#endif
diff --git a/src/core/lib/iomgr/udp_server.h b/src/core/lib/iomgr/udp_server.h
deleted file mode 100644 (file)
index ba7acbb..0000000
+++ /dev/null
@@ -1,103 +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.
- *
- */
-
-#ifndef GRPC_CORE_LIB_IOMGR_UDP_SERVER_H
-#define GRPC_CORE_LIB_IOMGR_UDP_SERVER_H
-
-#include <grpc/support/port_platform.h>
-
-#include <vector>
-
-#include "src/core/lib/iomgr/endpoint.h"
-#include "src/core/lib/iomgr/ev_posix.h"
-#include "src/core/lib/iomgr/resolve_address.h"
-
-/* Forward decl of struct grpc_server */
-/* This is not typedef'ed to avoid a typedef-redefinition error */
-struct grpc_server;
-
-/* Forward decl of grpc_udp_server */
-typedef struct grpc_udp_server grpc_udp_server;
-
-/* An interface associated with a socket. udp server delivers I/O event on that
- * socket to the subclass of this interface which is created through
- * GrpcUdpHandlerFactory.
- * Its implementation should do the real IO work, e.g. read packet and write. */
-class GrpcUdpHandler {
- public:
-  GrpcUdpHandler(grpc_fd* /* emfd */, void* /* user_data */) {}
-  virtual ~GrpcUdpHandler() {}
-
-  // Interfaces to be implemented by subclasses to do the actual setup/tear down
-  // or I/O.
-
-  // Called when data is available to read from the socket. Returns true if
-  // there is more data to read after this call.
-  virtual bool Read() = 0;
-  // Called when socket becomes write unblocked. The given closure should be
-  // scheduled when the socket becomes blocked next time.
-  virtual void OnCanWrite(void* user_data,
-                          grpc_closure* notify_on_write_closure) = 0;
-  // Called before the gRPC FD is orphaned. Notify udp server to continue
-  // orphaning fd by scheduling the given closure, afterwards the associated fd
-  // will be closed.
-  virtual void OnFdAboutToOrphan(grpc_closure* orphan_fd_closure,
-                                 void* user_data) = 0;
-};
-
-class GrpcUdpHandlerFactory {
- public:
-  virtual ~GrpcUdpHandlerFactory() {}
-  /* Called when start to listen on a socket.
-   * Return an instance of the implementation of GrpcUdpHandler interface which
-   * will process I/O events for this socket from now on. */
-  virtual GrpcUdpHandler* CreateUdpHandler(grpc_fd* emfd, void* user_data) = 0;
-  virtual void DestroyUdpHandler(GrpcUdpHandler* handler) = 0;
-};
-
-/* Create a server, initially not bound to any ports */
-grpc_udp_server* grpc_udp_server_create(const grpc_channel_args* args);
-
-/* Start listening to bound ports. user_data is passed to callbacks. */
-void grpc_udp_server_start(grpc_udp_server* udp_server,
-                           const std::vector<grpc_pollset*>* pollsets,
-                           void* user_data);
-
-int grpc_udp_server_get_fd(grpc_udp_server* s, unsigned port_index);
-
-/* Add a port to the server, returning port number on success, or negative
-   on failure.
-
-   Create |num_listeners| sockets for given address to listen on using
-   SO_REUSEPORT if supported.
-
-   The :: and 0.0.0.0 wildcard addresses are treated identically, accepting
-   both IPv4 and IPv6 connections, but :: is the preferred style. This usually
-   creates |num_listeners| sockets, but possibly 2 * |num_listeners| on systems
-   which support IPv6, but not dualstack sockets. */
-
-/* TODO(ctiller): deprecate this, and make grpc_udp_server_add_ports to handle
-                  all of the multiple socket port matching logic in one place */
-int grpc_udp_server_add_port(grpc_udp_server* s, grpc_resolved_address* addr,
-                             int rcv_buf_size, int snd_buf_size,
-                             GrpcUdpHandlerFactory* handler_factory,
-                             size_t num_listeners);
-
-void grpc_udp_server_destroy(grpc_udp_server* server, grpc_closure* on_done);
-
-#endif /* GRPC_CORE_LIB_IOMGR_UDP_SERVER_H */
index 1c90aeb..ed1de9a 100644 (file)
@@ -55,4 +55,72 @@ bool ParseDurationFromJson(const Json& field, grpc_millis* duration) {
   return true;
 }
 
+bool ExtractJsonBool(const Json& json, absl::string_view field_name,
+                     bool* output, std::vector<grpc_error_handle>* error_list) {
+  switch (json.type()) {
+    case Json::Type::JSON_TRUE:
+      *output = true;
+      return true;
+    case Json::Type::JSON_FALSE:
+      *output = false;
+      return true;
+    default:
+      error_list->push_back(GRPC_ERROR_CREATE_FROM_CPP_STRING(
+          absl::StrCat("field:", field_name, " error:type should be BOOLEAN")));
+      return false;
+  }
+}
+
+bool ExtractJsonArray(const Json& json, absl::string_view field_name,
+                      const Json::Array** output,
+                      std::vector<grpc_error_handle>* error_list) {
+  if (json.type() != Json::Type::ARRAY) {
+    *output = nullptr;
+    error_list->push_back(GRPC_ERROR_CREATE_FROM_CPP_STRING(
+        absl::StrCat("field:", field_name, " error:type should be ARRAY")));
+    return false;
+  }
+  *output = &json.array_value();
+  return true;
+}
+
+bool ExtractJsonObject(const Json& json, absl::string_view field_name,
+                       const Json::Object** output,
+                       std::vector<grpc_error_handle>* error_list) {
+  if (json.type() != Json::Type::OBJECT) {
+    *output = nullptr;
+    error_list->push_back(GRPC_ERROR_CREATE_FROM_CPP_STRING(
+        absl::StrCat("field:", field_name, " error:type should be OBJECT")));
+    return false;
+  }
+  *output = &json.object_value();
+  return true;
+}
+
+bool ParseJsonObjectFieldAsDuration(const Json::Object& object,
+                                    absl::string_view field_name,
+                                    grpc_millis* output,
+                                    std::vector<grpc_error_handle>* error_list,
+                                    bool required) {
+  // TODO(roth): Once we can use C++14 heterogenous lookups, stop
+  // creating a std::string here.
+  auto it = object.find(std::string(field_name));
+  if (it == object.end()) {
+    if (required) {
+      error_list->push_back(GRPC_ERROR_CREATE_FROM_CPP_STRING(
+          absl::StrCat("field:", field_name, " error:does not exist.")));
+    }
+    return false;
+  }
+  if (!ParseDurationFromJson(it->second, output)) {
+    *output = GRPC_MILLIS_INF_PAST;
+    error_list->push_back(GRPC_ERROR_CREATE_FROM_CPP_STRING(
+        absl::StrCat("field:", field_name,
+                     " error:type should be STRING of the form given by "
+                     "google.proto.Duration.")));
+    return false;
+  }
+  return true;
+}
+
 }  // namespace grpc_core
index f77febd..7b9fddd 100644 (file)
@@ -40,10 +40,10 @@ bool ParseDurationFromJson(const Json& field, grpc_millis* duration);
 // Return true on success, false otherwise. If an error is encountered during
 // parsing, a descriptive error is appended to \a error_list.
 //
-template <typename NumericType, typename ErrorVectorType>
-inline bool ExtractJsonNumber(const Json& json, const std::string& field_name,
-                              NumericType* output,
-                              ErrorVectorType* error_list) {
+template <typename NumericType>
+bool ExtractJsonNumber(const Json& json, absl::string_view field_name,
+                       NumericType* output,
+                       std::vector<grpc_error_handle>* error_list) {
   static_assert(std::is_integral<NumericType>::value, "Integral required");
   if (json.type() != Json::Type::NUMBER) {
     error_list->push_back(GRPC_ERROR_CREATE_FROM_CPP_STRING(
@@ -58,27 +58,14 @@ inline bool ExtractJsonNumber(const Json& json, const std::string& field_name,
   return true;
 }
 
-template <typename ErrorVectorType>
-inline bool ExtractJsonBool(const Json& json, const std::string& field_name,
-                            bool* output, ErrorVectorType* error_list) {
-  switch (json.type()) {
-    case Json::Type::JSON_TRUE:
-      *output = true;
-      return true;
-    case Json::Type::JSON_FALSE:
-      *output = false;
-      return true;
-    default:
-      error_list->push_back(GRPC_ERROR_CREATE_FROM_CPP_STRING(
-          absl::StrCat("field:", field_name, " error:type should be BOOLEAN")));
-      return false;
-  }
-}
+bool ExtractJsonBool(const Json& json, absl::string_view field_name,
+                     bool* output, std::vector<grpc_error_handle>* error_list);
 
-template <typename ErrorVectorType>
-inline bool ExtractJsonString(const Json& json, const std::string& field_name,
-                              std::string* output,
-                              ErrorVectorType* error_list) {
+// OutputType can be std::string or absl::string_view.
+template <typename OutputType>
+bool ExtractJsonString(const Json& json, absl::string_view field_name,
+                       OutputType* output,
+                       std::vector<grpc_error_handle>* error_list) {
   if (json.type() != Json::Type::STRING) {
     *output = "";
     error_list->push_back(GRPC_ERROR_CREATE_FROM_CPP_STRING(
@@ -89,72 +76,61 @@ inline bool ExtractJsonString(const Json& json, const std::string& field_name,
   return true;
 }
 
-template <typename ErrorVectorType>
-inline bool ExtractJsonArray(const Json& json, const std::string& field_name,
-                             const Json::Array** output,
-                             ErrorVectorType* error_list) {
-  if (json.type() != Json::Type::ARRAY) {
-    *output = nullptr;
-    error_list->push_back(GRPC_ERROR_CREATE_FROM_CPP_STRING(
-        absl::StrCat("field:", field_name, " error:type should be ARRAY")));
-    return false;
-  }
-  *output = &json.array_value();
-  return true;
-}
+bool ExtractJsonArray(const Json& json, absl::string_view field_name,
+                      const Json::Array** output,
+                      std::vector<grpc_error_handle>* error_list);
 
-template <typename ErrorVectorType>
-inline bool ExtractJsonObject(const Json& json, const std::string& field_name,
-                              const Json::Object** output,
-                              ErrorVectorType* error_list) {
-  if (json.type() != Json::Type::OBJECT) {
-    *output = nullptr;
-    error_list->push_back(GRPC_ERROR_CREATE_FROM_CPP_STRING(
-        absl::StrCat("field:", field_name, " error:type should be OBJECT")));
-    return false;
-  }
-  *output = &json.object_value();
-  return true;
-}
+bool ExtractJsonObject(const Json& json, absl::string_view field_name,
+                       const Json::Object** output,
+                       std::vector<grpc_error_handle>* error_list);
 
-template <typename NumericType, typename ErrorVectorType>
-inline bool ExtractJsonType(const Json& json, const std::string& field_name,
-                            NumericType* output, ErrorVectorType* error_list) {
+// Wrappers for automatically choosing one of the above functions based
+// on output parameter type.
+template <typename NumericType>
+inline bool ExtractJsonType(const Json& json, absl::string_view field_name,
+                            NumericType* output,
+                            std::vector<grpc_error_handle>* error_list) {
   return ExtractJsonNumber(json, field_name, output, error_list);
 }
-
-template <typename ErrorVectorType>
-inline bool ExtractJsonType(const Json& json, const std::string& field_name,
-                            bool* output, ErrorVectorType* error_list) {
+inline bool ExtractJsonType(const Json& json, absl::string_view field_name,
+                            bool* output,
+                            std::vector<grpc_error_handle>* error_list) {
   return ExtractJsonBool(json, field_name, output, error_list);
 }
-
-template <typename ErrorVectorType>
-inline bool ExtractJsonType(const Json& json, const std::string& field_name,
-                            std::string* output, ErrorVectorType* error_list) {
+inline bool ExtractJsonType(const Json& json, absl::string_view field_name,
+                            std::string* output,
+                            std::vector<grpc_error_handle>* error_list) {
   return ExtractJsonString(json, field_name, output, error_list);
 }
-
-template <typename ErrorVectorType>
-inline bool ExtractJsonType(const Json& json, const std::string& field_name,
+inline bool ExtractJsonType(const Json& json, absl::string_view field_name,
+                            absl::string_view* output,
+                            std::vector<grpc_error_handle>* error_list) {
+  return ExtractJsonString(json, field_name, output, error_list);
+}
+inline bool ExtractJsonType(const Json& json, absl::string_view field_name,
                             const Json::Array** output,
-                            ErrorVectorType* error_list) {
+                            std::vector<grpc_error_handle>* error_list) {
   return ExtractJsonArray(json, field_name, output, error_list);
 }
-
-template <typename ErrorVectorType>
-inline bool ExtractJsonType(const Json& json, const std::string& field_name,
+inline bool ExtractJsonType(const Json& json, absl::string_view field_name,
                             const Json::Object** output,
-                            ErrorVectorType* error_list) {
+                            std::vector<grpc_error_handle>* error_list) {
   return ExtractJsonObject(json, field_name, output, error_list);
 }
 
-template <typename T, typename ErrorVectorType>
-inline bool ParseJsonObjectField(const Json::Object& object,
-                                 const std::string& field_name, T* output,
-                                 ErrorVectorType* error_list,
-                                 bool required = true) {
-  auto it = object.find(field_name);
+// Extracts a field from a JSON object, automatically selecting the type
+// of parsing based on the output parameter type.
+// If the field is not present, returns false, and if required is true,
+// adds an error to error_list.
+// Upon any other error, adds an error to error_list and returns false.
+template <typename T>
+bool ParseJsonObjectField(const Json::Object& object,
+                          absl::string_view field_name, T* output,
+                          std::vector<grpc_error_handle>* error_list,
+                          bool required = true) {
+  // TODO(roth): Once we can use C++14 heterogenous lookups, stop
+  // creating a std::string here.
+  auto it = object.find(std::string(field_name));
   if (it == object.end()) {
     if (required) {
       error_list->push_back(GRPC_ERROR_CREATE_FROM_CPP_STRING(
@@ -166,30 +142,12 @@ inline bool ParseJsonObjectField(const Json::Object& object,
   return ExtractJsonType(child_object_json, field_name, output, error_list);
 }
 
-template <typename ErrorVectorType>
-inline bool ParseJsonObjectFieldAsDuration(const Json::Object& object,
-                                           const std::string& field_name,
-                                           grpc_millis* output,
-                                           ErrorVectorType* error_list,
-                                           bool required = true) {
-  auto it = object.find(field_name);
-  if (it == object.end()) {
-    if (required) {
-      error_list->push_back(GRPC_ERROR_CREATE_FROM_CPP_STRING(
-          absl::StrCat("field:", field_name, " error:does not exist.")));
-    }
-    return false;
-  }
-  if (!ParseDurationFromJson(it->second, output)) {
-    *output = GRPC_MILLIS_INF_PAST;
-    error_list->push_back(GRPC_ERROR_CREATE_FROM_CPP_STRING(
-        absl::StrCat("field:", field_name,
-                     " error:type should be STRING of the form given by "
-                     "google.proto.Duration.")));
-    return false;
-  }
-  return true;
-}
+// Alternative to ParseJsonObjectField() for duration-value fields.
+bool ParseJsonObjectFieldAsDuration(const Json::Object& object,
+                                    absl::string_view field_name,
+                                    grpc_millis* output,
+                                    std::vector<grpc_error_handle>* error_list,
+                                    bool required = true);
 
 }  // namespace grpc_core
 
index 74d0cf5..7522802 100644 (file)
@@ -23,9 +23,6 @@
 
 #include "absl/strings/string_view.h"
 
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-
 #include "src/core/lib/json/json.h"
 
 namespace grpc_core {
index a8d4715..979d085 100644 (file)
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include "src/core/lib/promise/activity.h"
 
index 6941d98..b1d62f4 100644 (file)
@@ -15,7 +15,7 @@
 #ifndef GRPC_CORE_LIB_PROMISE_ACTIVITY_H
 #define GRPC_CORE_LIB_PROMISE_ACTIVITY_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include <functional>
 
@@ -78,7 +78,7 @@ class Waker {
  private:
   class Unwakeable final : public Wakeable {
    public:
-    void Wakeup() final { abort(); }
+    void Wakeup() final {}
     void Drop() final {}
   };
 
@@ -95,8 +95,6 @@ class Waker {
 // Activity execution may be cancelled by simply deleting the activity. In such
 // a case, if execution had not already finished, the done callback would be
 // called with absl::CancelledError().
-// Activity also takes a CallbackScheduler instance on which to schedule
-// callbacks to itself in a lock-clean environment.
 class Activity : private Wakeable {
  public:
   // Cancel execution of the underlying promise.
@@ -113,9 +111,18 @@ class Activity : private Wakeable {
   // Fetch the size of the implementation of this activity.
   virtual size_t Size() = 0;
 
+  // Force wakeup from the outside.
+  // This should be rarely needed, and usages should be accompanied with a note
+  // on why it's not possible to wakeup with a Waker object.
+  // Nevertheless, it's sometimes useful for integrations with Activity to force
+  // an Activity to repoll.
+  void ForceWakeup() { MakeOwningWaker().Wakeup(); }
+
   // Wakeup the current threads activity - will force a subsequent poll after
   // the one that's running.
-  static void WakeupCurrent() { current()->got_wakeup_during_run_ = true; }
+  static void WakeupCurrent() {
+    current()->SetActionDuringRun(ActionDuringRun::kWakeup);
+  }
 
   // Return the current activity.
   // Additionally:
@@ -147,6 +154,15 @@ class Activity : private Wakeable {
   Waker MakeNonOwningWaker() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
 
  protected:
+  // Action received during a run, in priority order.
+  // If more than one action is received during a run, we use max() to resolve
+  // which one to report (so Cancel overrides Wakeup).
+  enum class ActionDuringRun : uint8_t {
+    kNone,    // No action occured during run.
+    kWakeup,  // A wakeup occured during run.
+    kCancel,  // Cancel was called during run.
+  };
+
   inline virtual ~Activity() {
     if (handle_) {
       DropHandle();
@@ -163,8 +179,8 @@ class Activity : private Wakeable {
   static bool have_current() { return g_current_activity_ != nullptr; }
   // Check if we got an internal wakeup since the last time this function was
   // called.
-  bool got_wakeup() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) {
-    return absl::exchange(got_wakeup_during_run_, false);
+  ActionDuringRun GotActionDuringRun() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) {
+    return absl::exchange(action_during_run_, ActionDuringRun::kNone);
   }
 
   // Set the current activity at construction, clean it up at destruction.
@@ -183,6 +199,12 @@ class Activity : private Wakeable {
   // completed.
   void WakeupComplete() { Unref(); }
 
+  // Mark the current activity as being cancelled (so we can actually cancel it
+  // after polling).
+  void CancelCurrent() {
+    current()->SetActionDuringRun(ActionDuringRun::kCancel);
+  }
+
  private:
   class Handle;
 
@@ -201,12 +223,20 @@ class Activity : private Wakeable {
   bool RefIfNonzero();
   // Drop the (proved existing) wait handle.
   void DropHandle() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
+  // Set the action that occured during this run.
+  // We use max to combine actions so that cancellation overrides wakeups.
+  void SetActionDuringRun(ActionDuringRun action)
+      ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) {
+    action_during_run_ = std::max(action_during_run_, action);
+  }
 
   // Current refcount.
   std::atomic<uint32_t> refs_{1};
-  // If wakeup is called during Promise polling, we raise this flag and repoll
-  // until things settle out.
-  bool got_wakeup_during_run_ ABSL_GUARDED_BY(mu_) = false;
+  // If wakeup is called during Promise polling, we set this to Wakeup and
+  // repoll. If cancel is called during Promise polling, we set this to Cancel
+  // and cancel at the end of polling.
+  ActionDuringRun action_during_run_ ABSL_GUARDED_BY(mu_) =
+      ActionDuringRun::kNone;
   // Handle for long waits. Allows a very small weak pointer type object to
   // queue for wakeups while Activity may be deleted earlier.
   Handle* handle_ ABSL_GUARDED_BY(mu_) = nullptr;
@@ -248,17 +278,27 @@ class EnterContexts : public promise_detail::Context<Contexts>... {
 };
 
 // Implementation details for an Activity of an arbitrary type of promise.
-template <class F, class CallbackScheduler, class OnDone, typename... Contexts>
+// There should exist a static function:
+// struct WakeupScheduler {
+//   template <typename ActivityType>
+//   void ScheduleWakeup(ActivityType* activity);
+// };
+// This function should arrange that activity->RunScheduledWakeup() be invoked
+// at the earliest opportunity.
+// It can assume that activity will remain live until RunScheduledWakeup() is
+// invoked, and that a given activity will not be concurrently scheduled again
+// until its RunScheduledWakeup() has been invoked.
+template <class F, class WakeupScheduler, class OnDone, typename... Contexts>
 class PromiseActivity final
     : public Activity,
       private promise_detail::ContextHolder<Contexts>... {
  public:
   using Factory = PromiseFactory<void, F>;
-  PromiseActivity(F promise_factory, CallbackScheduler callback_scheduler,
+  PromiseActivity(F promise_factory, WakeupScheduler wakeup_scheduler,
                   OnDone on_done, Contexts... contexts)
       : Activity(),
         ContextHolder<Contexts>(std::move(contexts))...,
-        callback_scheduler_(std::move(callback_scheduler)),
+        wakeup_scheduler_(std::move(wakeup_scheduler)),
         on_done_(std::move(on_done)) {
     // Lock, construct an initial promise from the factory, and step it.
     // This may hit a waiter, which could expose our this pointer to other
@@ -283,6 +323,10 @@ class PromiseActivity final
   size_t Size() override { return sizeof(*this); }
 
   void Cancel() final {
+    if (Activity::is_current()) {
+      CancelCurrent();
+      return;
+    }
     bool was_done;
     {
       MutexLock lock(&mu_);
@@ -296,6 +340,12 @@ class PromiseActivity final
     }
   }
 
+  void RunScheduledWakeup() {
+    GPR_ASSERT(wakeup_scheduled_.exchange(false, std::memory_order_acq_rel));
+    Step();
+    WakeupComplete();
+  }
+
  private:
   // Wakeup this activity. Arrange to poll the activity again at a convenient
   // time: this could be inline if it's deemed safe, or it could be by passing
@@ -303,12 +353,6 @@ class PromiseActivity final
   // running on this thread, a note is taken of such and the activity is
   // repolled if it doesn't complete.
   void Wakeup() final {
-    // If there's no active activity, we can just run inline.
-    if (!Activity::have_current()) {
-      Step();
-      WakeupComplete();
-      return;
-    }
     // If there is an active activity, but hey it's us, flag that and we'll loop
     // in RunLoop (that's calling from above here!).
     if (Activity::is_current()) {
@@ -316,11 +360,13 @@ class PromiseActivity final
       WakeupComplete();
       return;
     }
-    // Can't safely run, so ask to run later.
-    callback_scheduler_([this]() {
-      this->Step();
-      this->WakeupComplete();
-    });
+    if (!wakeup_scheduled_.exchange(true, std::memory_order_acq_rel)) {
+      // Can't safely run, so ask to run later.
+      wakeup_scheduler_.ScheduleWakeup(this);
+    } else {
+      // Already a wakeup scheduled for later, drop ref.
+      WakeupComplete();
+    }
   }
 
   // Drop a wakeup
@@ -376,7 +422,7 @@ class PromiseActivity final
   // the promise.
   absl::optional<absl::Status> StepLoop() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) {
     GPR_ASSERT(is_current());
-    do {
+    while (true) {
       // Run the promise.
       GPR_ASSERT(!done_);
       auto r = promise_holder_.promise();
@@ -386,11 +432,27 @@ class PromiseActivity final
         return IntoStatus(status);
       }
       // Continue looping til no wakeups occur.
-    } while (got_wakeup());
-    return {};
+      switch (GotActionDuringRun()) {
+        case ActionDuringRun::kNone:
+          return {};
+        case ActionDuringRun::kWakeup:
+          break;
+        case ActionDuringRun::kCancel:
+          MarkDone();
+          return absl::CancelledError();
+      }
+    }
   }
 
   using Promise = typename Factory::Promise;
+  // Scheduler for wakeups
+  GPR_NO_UNIQUE_ADDRESS WakeupScheduler wakeup_scheduler_;
+  // Callback on completion of the promise.
+  GPR_NO_UNIQUE_ADDRESS OnDone on_done_;
+  // Has execution completed?
+  GPR_NO_UNIQUE_ADDRESS bool done_ ABSL_GUARDED_BY(mu_) = false;
+  // Is there a wakeup scheduled?
+  GPR_NO_UNIQUE_ADDRESS std::atomic<bool> wakeup_scheduled_{false};
   // We wrap the promise in a union to allow control over the construction
   // simultaneously with annotating mutex requirements and noting that the
   // promise contained may not use any memory.
@@ -400,38 +462,24 @@ class PromiseActivity final
     GPR_NO_UNIQUE_ADDRESS Promise promise;
   };
   GPR_NO_UNIQUE_ADDRESS PromiseHolder promise_holder_ ABSL_GUARDED_BY(mu_);
-  // Schedule callbacks on some external executor.
-  GPR_NO_UNIQUE_ADDRESS CallbackScheduler callback_scheduler_;
-  // Callback on completion of the promise.
-  GPR_NO_UNIQUE_ADDRESS OnDone on_done_;
-  // Has execution completed?
-  GPR_NO_UNIQUE_ADDRESS bool done_ ABSL_GUARDED_BY(mu_) = false;
 };
 
 }  // namespace promise_detail
 
 // Given a functor that returns a promise (a promise factory), a callback for
 // completion, and a callback scheduler, construct an activity.
-template <typename Factory, typename CallbackScheduler, typename OnDone,
+template <typename Factory, typename WakeupScheduler, typename OnDone,
           typename... Contexts>
 ActivityPtr MakeActivity(Factory promise_factory,
-                         CallbackScheduler callback_scheduler, OnDone on_done,
+                         WakeupScheduler wakeup_scheduler, OnDone on_done,
                          Contexts... contexts) {
   return ActivityPtr(
-      new promise_detail::PromiseActivity<Factory, CallbackScheduler, OnDone,
+      new promise_detail::PromiseActivity<Factory, WakeupScheduler, OnDone,
                                           Contexts...>(
-          std::move(promise_factory), std::move(callback_scheduler),
+          std::move(promise_factory), std::move(wakeup_scheduler),
           std::move(on_done), std::move(contexts)...));
 }
 
-// A callback scheduler that simply crashes
-struct NoCallbackScheduler {
-  template <typename F>
-  void operator()(F) {
-    abort();
-  }
-};
-
 }  // namespace grpc_core
 
 #endif  // GRPC_CORE_LIB_PROMISE_ACTIVITY_H
index 59cdf21..b9862a9 100644 (file)
@@ -15,7 +15,7 @@
 #ifndef GRPC_CORE_LIB_PROMISE_CONTEXT_H
 #define GRPC_CORE_LIB_PROMISE_CONTEXT_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include <utility>
 
index 01d2d33..6fe6679 100644 (file)
@@ -15,7 +15,7 @@
 #ifndef GRPC_CORE_LIB_PROMISE_DETAIL_BASIC_JOIN_H
 #define GRPC_CORE_LIB_PROMISE_DETAIL_BASIC_JOIN_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include <tuple>
 #include <utility>
index 72b91f9..991cd46 100644 (file)
@@ -15,7 +15,9 @@
 #ifndef GRPC_CORE_LIB_PROMISE_DETAIL_BASIC_SEQ_H
 #define GRPC_CORE_LIB_PROMISE_DETAIL_BASIC_SEQ_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
+
+#include <cassert>
 
 #include "absl/types/variant.h"
 #include "absl/utility/utility.h"
@@ -68,12 +70,14 @@ struct SeqState {
   // Move constructor - assumes we're in the initial state (move prior) as it's
   // illegal to move a promise after polling it.
   SeqState(SeqState&& other) noexcept
-      : prior(std::move(other.prior)),
-        next_factory(std::move(other.next_factory)) {}
+      : next_factory(std::move(other.next_factory)) {
+    new (&prior) PriorState(std::move(other.prior));
+  }
   // Copy constructor - assumes we're in the initial state (move prior) as it's
   // illegal to move a promise after polling it.
-  SeqState(const SeqState& other)
-      : prior(other.prior), next_factory(other.next_factory) {}
+  SeqState(const SeqState& other) : next_factory(other.next_factory) {
+    new (&prior) PriorState(std::move(other.prior));
+  }
   // Empty destructor - we instead destruct the innards in BasicSeq manually
   // depending on state.
   ~SeqState() {}
@@ -115,7 +119,7 @@ struct SeqState<Traits, 0, Fs...> {
         next_factory(other.next_factory) {}
   // Empty destructor - we instead destruct the innards in BasicSeq manually
   // depending on state.
-  ~SeqState(){};
+  ~SeqState() {}
   // Evaluate the current promise, next promise factory types for this state.
   // Our callable is the first element of Fs, wrapped in PromiseLike to handle
   // some common edge cases. The next factory is the second element.
index 2adb0b7..2da6a8b 100644 (file)
@@ -15,7 +15,7 @@
 #ifndef GRPC_CORE_LIB_PROMISE_DETAIL_PROMISE_FACTORY_H
 #define GRPC_CORE_LIB_PROMISE_DETAIL_PROMISE_FACTORY_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include "absl/meta/type_traits.h"
 
index c80169a..b2af650 100644 (file)
@@ -15,7 +15,7 @@
 #ifndef GRPC_CORE_LIB_PROMISE_DETAIL_PROMISE_LIKE_H
 #define GRPC_CORE_LIB_PROMISE_DETAIL_PROMISE_LIKE_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include <utility>
 
index 8b0aa25..92a980f 100644 (file)
@@ -15,7 +15,7 @@
 #ifndef GRPC_CORE_LIB_PROMISE_DETAIL_STATUS_H
 #define GRPC_CORE_LIB_PROMISE_DETAIL_STATUS_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include "absl/status/status.h"
 #include "absl/status/statusor.h"
index f164e23..84b1191 100644 (file)
@@ -21,7 +21,7 @@
 #ifndef GRPC_CORE_LIB_PROMISE_DETAIL_SWITCH_H
 #define GRPC_CORE_LIB_PROMISE_DETAIL_SWITCH_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include <stdlib.h>
 
diff --git a/src/core/lib/promise/exec_ctx_wakeup_scheduler.h b/src/core/lib/promise/exec_ctx_wakeup_scheduler.h
new file mode 100644 (file)
index 0000000..5af59de
--- /dev/null
@@ -0,0 +1,45 @@
+// 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.
+
+#ifndef GRPC_CORE_LIB_PROMISE_EXEC_CTX_WAKEUP_SCHEDULER_H
+#define GRPC_CORE_LIB_PROMISE_EXEC_CTX_WAKEUP_SCHEDULER_H
+
+#include <grpc/support/port_platform.h>
+
+#include "src/core/lib/iomgr/exec_ctx.h"
+
+namespace grpc_core {
+
+// A callback scheduler for activities that works by scheduling callbacks on the
+// exec ctx.
+class ExecCtxWakeupScheduler {
+ public:
+  template <typename ActivityType>
+  void ScheduleWakeup(ActivityType* activity) {
+    GRPC_CLOSURE_INIT(
+        &closure_,
+        [](void* arg, grpc_error_handle) {
+          static_cast<ActivityType*>(arg)->RunScheduledWakeup();
+        },
+        activity, grpc_schedule_on_exec_ctx);
+    ExecCtx::Run(DEBUG_LOCATION, &closure_, GRPC_ERROR_NONE);
+  }
+
+ private:
+  grpc_closure closure_;
+};
+
+}  // namespace grpc_core
+
+#endif  // GRPC_CORE_LIB_PROMISE_EXEC_CTX_WAKEUP_SCHEDULER_H
index c9136ee..42c7083 100644 (file)
@@ -15,7 +15,7 @@
 #ifndef GRPC_CORE_LIB_PROMISE_FOR_EACH_H
 #define GRPC_CORE_LIB_PROMISE_FOR_EACH_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include "absl/status/status.h"
 #include "absl/types/variant.h"
index 5c13105..04fcf5e 100644 (file)
@@ -15,7 +15,7 @@
 #ifndef GRPC_CORE_LIB_PROMISE_IF_H
 #define GRPC_CORE_LIB_PROMISE_IF_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include "absl/status/statusor.h"
 #include "absl/types/variant.h"
index a9e43ab..b0eb299 100644 (file)
@@ -15,7 +15,7 @@
 #ifndef GRPC_CORE_LIB_PROMISE_INTRA_ACTIVITY_WAITER_H
 #define GRPC_CORE_LIB_PROMISE_INTRA_ACTIVITY_WAITER_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include "src/core/lib/promise/activity.h"
 
index d41840b..b936901 100644 (file)
@@ -15,7 +15,7 @@
 #ifndef GRPC_CORE_LIB_PROMISE_JOIN_H
 #define GRPC_CORE_LIB_PROMISE_JOIN_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include "src/core/lib/promise/detail/basic_join.h"
 
index c697956..e20dd59 100644 (file)
@@ -15,7 +15,7 @@
 #ifndef GRPC_CORE_LIB_PROMISE_LATCH_H
 #define GRPC_CORE_LIB_PROMISE_LATCH_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include <grpc/support/log.h>
 
index 0a5346b..6d6f4af 100644 (file)
@@ -15,7 +15,7 @@
 #ifndef GRPC_CORE_LIB_PROMISE_LOOP_H
 #define GRPC_CORE_LIB_PROMISE_LOOP_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include "absl/types/variant.h"
 
@@ -54,6 +54,13 @@ class Loop {
   explicit Loop(F f) : factory_(std::move(f)), promise_(factory_.Repeated()) {}
   ~Loop() { promise_.~Promise(); }
 
+  Loop(Loop&& loop) noexcept
+      : factory_(std::move(loop.factory_)),
+        promise_(std::move(loop.promise_)) {}
+
+  Loop(const Loop& loop) = delete;
+  Loop& operator=(const Loop& loop) = delete;
+
   Poll<Result> operator()() {
     while (true) {
       // Poll the inner promise.
index 1ac94d4..7d43de0 100644 (file)
@@ -15,7 +15,7 @@
 #ifndef GRPC_CORE_LIB_PROMISE_MAP_H
 #define GRPC_CORE_LIB_PROMISE_MAP_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include <tuple>
 
index 6ca58c3..1509851 100644 (file)
@@ -15,7 +15,7 @@
 #ifndef GRPC_CORE_LIB_PROMISE_OBSERVABLE_H
 #define GRPC_CORE_LIB_PROMISE_OBSERVABLE_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include <limits>
 
index 3d287ca..d0f472e 100644 (file)
@@ -15,7 +15,7 @@
 #ifndef GRPC_CORE_LIB_PROMISE_PIPE_H
 #define GRPC_CORE_LIB_PROMISE_PIPE_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include "absl/status/status.h"
 #include "absl/status/statusor.h"
index fa3e19f..b7cd470 100644 (file)
@@ -15,7 +15,7 @@
 #ifndef GRPC_CORE_LIB_PROMISE_POLL_H
 #define GRPC_CORE_LIB_PROMISE_POLL_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include "absl/types/variant.h"
 
index 9cf5266..ecba758 100644 (file)
@@ -15,7 +15,7 @@
 #ifndef GRPC_CORE_LIB_PROMISE_PROMISE_H
 #define GRPC_CORE_LIB_PROMISE_PROMISE_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include <functional>
 
index 9bd9e93..4b55bcc 100644 (file)
@@ -15,7 +15,7 @@
 #ifndef GRPC_CORE_LIB_PROMISE_RACE_H
 #define GRPC_CORE_LIB_PROMISE_RACE_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include <tuple>
 
index b81cb2d..a6342a0 100644 (file)
@@ -15,7 +15,7 @@
 #ifndef GRPC_CORE_LIB_PROMISE_SEQ_H
 #define GRPC_CORE_LIB_PROMISE_SEQ_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include "absl/types/variant.h"
 
index c15a6ee..9239d93 100644 (file)
@@ -15,7 +15,7 @@
 #ifndef GRPC_CORE_LIB_PROMISE_TRY_JOIN_H
 #define GRPC_CORE_LIB_PROMISE_TRY_JOIN_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include "src/core/lib/promise/detail/basic_join.h"
 #include "src/core/lib/promise/detail/status.h"
index 9b4fb93..3e142a9 100644 (file)
@@ -15,7 +15,7 @@
 #ifndef GRPC_CORE_LIB_PROMISE_TRY_SEQ_H
 #define GRPC_CORE_LIB_PROMISE_TRY_SEQ_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include <tuple>
 
index 719f60b..bdfc850 100644 (file)
@@ -15,7 +15,7 @@
 #ifndef GRPC_CORE_LIB_PROMISE_WAIT_SET_H
 #define GRPC_CORE_LIB_PROMISE_WAIT_SET_H
 
-#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/support/port_platform.h>
 
 #include "absl/container/flat_hash_set.h"
 
diff --git a/src/core/lib/resource_quota/memory_quota.cc b/src/core/lib/resource_quota/memory_quota.cc
new file mode 100644 (file)
index 0000000..c72c09e
--- /dev/null
@@ -0,0 +1,408 @@
+// 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 <grpc/support/port_platform.h>
+
+#include "src/core/lib/resource_quota/memory_quota.h"
+
+#include "src/core/lib/gpr/useful.h"
+#include "src/core/lib/promise/exec_ctx_wakeup_scheduler.h"
+#include "src/core/lib/promise/loop.h"
+#include "src/core/lib/promise/race.h"
+#include "src/core/lib/promise/seq.h"
+
+namespace grpc_core {
+
+// Maximum number of bytes an allocator will request from a quota in one step.
+// Larger allocations than this will require multiple allocation requests.
+static constexpr size_t kMaxReplenishBytes = 1024 * 1024;
+
+// Minimum number of bytes an allocator will request from a quota in one step.
+static constexpr size_t kMinReplenishBytes = 4096;
+
+//
+// Reclaimer
+//
+
+ReclamationSweep::~ReclamationSweep() {
+  if (memory_quota_ != nullptr) {
+    memory_quota_->FinishReclamation(sweep_token_);
+  }
+}
+
+//
+// ReclaimerQueue
+//
+
+const ReclaimerQueue::Index ReclaimerQueue::kInvalidIndex;
+
+void ReclaimerQueue::Insert(
+    std::shared_ptr<EventEngineMemoryAllocatorImpl> allocator,
+    ReclamationFunction reclaimer, Index* index) {
+  ReleasableMutexLock lock(&mu_);
+  if (*index < entries_.size() && entries_[*index].allocator == allocator) {
+    entries_[*index].reclaimer.swap(reclaimer);
+    lock.Release();
+    reclaimer({});
+    return;
+  }
+  if (free_entries_.empty()) {
+    *index = entries_.size();
+    entries_.emplace_back(std::move(allocator), std::move(reclaimer));
+  } else {
+    *index = free_entries_.back();
+    free_entries_.pop_back();
+    Entry& entry = entries_[*index];
+    entry.allocator = std::move(allocator);
+    entry.reclaimer = std::move(reclaimer);
+  }
+  if (queue_.empty()) waker_.Wakeup();
+  queue_.push(*index);
+}
+
+ReclamationFunction ReclaimerQueue::Cancel(
+    Index index, EventEngineMemoryAllocatorImpl* allocator) {
+  MutexLock lock(&mu_);
+  if (index >= entries_.size()) return nullptr;
+  Entry& entry = entries_[index];
+  if (entry.allocator.get() != allocator) return {};
+  entry.allocator.reset();
+  return std::move(entry.reclaimer);
+}
+
+Poll<ReclamationFunction> ReclaimerQueue::PollNext() {
+  MutexLock lock(&mu_);
+  while (true) {
+    if (queue_.empty()) {
+      waker_ = Activity::current()->MakeNonOwningWaker();
+      return Pending{};
+    }
+    Index index = queue_.front();
+    queue_.pop();
+    free_entries_.push_back(index);
+    Entry& entry = entries_[index];
+    if (entry.allocator != nullptr) {
+      entry.allocator.reset();
+      return std::move(entry.reclaimer);
+    }
+  }
+}
+
+//
+// GrpcMemoryAllocatorImpl
+//
+
+GrpcMemoryAllocatorImpl::GrpcMemoryAllocatorImpl(
+    std::shared_ptr<BasicMemoryQuota> memory_quota)
+    : memory_quota_(memory_quota) {
+  memory_quota_->Take(taken_bytes_);
+}
+
+GrpcMemoryAllocatorImpl::~GrpcMemoryAllocatorImpl() {
+  GPR_ASSERT(free_bytes_.load(std::memory_order_acquire) +
+                 sizeof(GrpcMemoryAllocatorImpl) ==
+             taken_bytes_);
+  memory_quota_->Return(taken_bytes_);
+}
+
+void GrpcMemoryAllocatorImpl::Shutdown() {
+  std::shared_ptr<BasicMemoryQuota> memory_quota;
+  ReclaimerQueue::Index reclamation_indices[kNumReclamationPasses];
+  {
+    MutexLock lock(&memory_quota_mu_);
+    GPR_ASSERT(!shutdown_);
+    shutdown_ = true;
+    memory_quota = memory_quota_;
+    for (size_t i = 0; i < kNumReclamationPasses; i++) {
+      reclamation_indices[i] = absl::exchange(reclamation_indices_[i],
+                                              ReclaimerQueue::kInvalidIndex);
+    }
+  }
+  for (size_t i = 0; i < kNumReclamationPasses; i++) {
+    auto fn = memory_quota->CancelReclaimer(i, reclamation_indices[i], this);
+    if (fn != nullptr) fn({});
+  }
+}
+
+size_t GrpcMemoryAllocatorImpl::Reserve(MemoryRequest request) {
+  // Validate request - performed here so we don't bloat the generated code with
+  // inlined asserts.
+  GPR_ASSERT(request.min() <= request.max());
+  GPR_ASSERT(request.max() <= MemoryRequest::max_allowed_size());
+  while (true) {
+    // Attempt to reserve memory from our pool.
+    auto reservation = TryReserve(request);
+    if (reservation.has_value()) return *reservation;
+    // If that failed, grab more from the quota and retry.
+    Replenish();
+  }
+}
+
+absl::optional<size_t> GrpcMemoryAllocatorImpl::TryReserve(
+    MemoryRequest request) {
+  // How much memory should we request? (see the scaling below)
+  size_t scaled_size_over_min = request.max() - request.min();
+  // Scale the request down according to memory pressure if we have that
+  // flexibility.
+  if (scaled_size_over_min != 0) {
+    double pressure;
+    {
+      MutexLock lock(&memory_quota_mu_);
+      pressure = memory_quota_->InstantaneousPressure();
+    }
+    // Reduce allocation size proportional to the pressure > 80% usage.
+    if (pressure > 0.8) {
+      scaled_size_over_min =
+          std::min(scaled_size_over_min,
+                   static_cast<size_t>((request.max() - request.min()) *
+                                       (1.0 - pressure) / 0.2));
+    }
+  }
+
+  // How much do we want to reserve?
+  const size_t reserve = request.min() + scaled_size_over_min;
+  // See how many bytes are available.
+  size_t available = free_bytes_.load(std::memory_order_acquire);
+  while (true) {
+    // Does the current free pool satisfy the request?
+    if (available < reserve) {
+      return {};
+    }
+    // Try to reserve the requested amount.
+    // If the amount of free memory changed through this loop, then available
+    // will be set to the new value and we'll repeat.
+    if (free_bytes_.compare_exchange_weak(available, available - reserve,
+                                          std::memory_order_acq_rel,
+                                          std::memory_order_acquire)) {
+      return reserve;
+    }
+  }
+}
+
+void GrpcMemoryAllocatorImpl::Replenish() {
+  MutexLock lock(&memory_quota_mu_);
+  GPR_ASSERT(!shutdown_);
+  // Attempt a fairly low rate exponential growth request size, bounded between
+  // some reasonable limits declared at top of file.
+  auto amount = Clamp(taken_bytes_ / 3, kMinReplenishBytes, kMaxReplenishBytes);
+  // Take the requested amount from the quota.
+  memory_quota_->Take(amount);
+  // Record that we've taken it.
+  taken_bytes_ += amount;
+  // Add the taken amount to the free pool.
+  free_bytes_.fetch_add(amount, std::memory_order_acq_rel);
+  // See if we can add ourselves as a reclaimer.
+  MaybeRegisterReclaimerLocked();
+}
+
+void GrpcMemoryAllocatorImpl::MaybeRegisterReclaimer() {
+  MutexLock lock(&memory_quota_mu_);
+  MaybeRegisterReclaimerLocked();
+}
+
+void GrpcMemoryAllocatorImpl::MaybeRegisterReclaimerLocked() {
+  // If the reclaimer is already registered, then there's nothing to do.
+  if (reclamation_indices_[0] != ReclaimerQueue::kInvalidIndex) return;
+  if (shutdown_) return;
+  // Grab references to the things we'll need
+  auto self = shared_from_this();
+  memory_quota_->InsertReclaimer(
+      0, self,
+      [self](absl::optional<ReclamationSweep> sweep) {
+        if (!sweep.has_value()) return;
+        auto* p = static_cast<GrpcMemoryAllocatorImpl*>(self.get());
+        MutexLock lock(&p->memory_quota_mu_);
+        // Figure out how many bytes we can return to the quota.
+        size_t return_bytes =
+            p->free_bytes_.exchange(0, std::memory_order_acq_rel);
+        if (return_bytes == 0) return;
+        // Subtract that from our outstanding balance.
+        p->taken_bytes_ -= return_bytes;
+        // And return them to the quota.
+        p->memory_quota_->Return(return_bytes);
+      },
+      &reclamation_indices_[0]);
+}
+
+void GrpcMemoryAllocatorImpl::Rebind(
+    std::shared_ptr<BasicMemoryQuota> memory_quota) {
+  MutexLock lock(&memory_quota_mu_);
+  GPR_ASSERT(!shutdown_);
+  if (memory_quota_ == memory_quota) return;
+  // Return memory to the original memory quota.
+  memory_quota_->Return(taken_bytes_);
+  // Fetch back any reclaimers that are queued.
+  ReclamationFunction reclaimers[kNumReclamationPasses];
+  for (size_t i = 0; i < kNumReclamationPasses; i++) {
+    reclaimers[i] =
+        memory_quota_->CancelReclaimer(i, reclamation_indices_[i], this);
+  }
+  // Switch to the new memory quota, leaving the old one in memory_quota so that
+  // when we unref it, we are outside of lock.
+  memory_quota_.swap(memory_quota);
+  // Drop our freed memory down to zero, to avoid needing to ask the new
+  // quota for memory we're not currently using.
+  taken_bytes_ -= free_bytes_.exchange(0, std::memory_order_acq_rel);
+  // And let the new quota know how much we're already using.
+  memory_quota_->Take(taken_bytes_);
+  // Reinsert active reclaimers.
+  for (size_t i = 0; i < kNumReclamationPasses; i++) {
+    if (reclaimers[i] == nullptr) continue;
+    memory_quota_->InsertReclaimer(i, shared_from_this(),
+                                   std::move(reclaimers[i]),
+                                   &reclamation_indices_[i]);
+  }
+}
+
+void GrpcMemoryAllocatorImpl::PostReclaimer(ReclamationPass pass,
+                                            ReclamationFunction fn) {
+  MutexLock lock(&memory_quota_mu_);
+  GPR_ASSERT(!shutdown_);
+  auto pass_num = static_cast<size_t>(pass);
+  memory_quota_->InsertReclaimer(pass_num, shared_from_this(), std::move(fn),
+                                 &reclamation_indices_[pass_num]);
+}
+
+//
+// MemoryOwner
+//
+
+void MemoryOwner::Rebind(MemoryQuota* quota) {
+  static_cast<GrpcMemoryAllocatorImpl*>(allocator_.get_internal_impl_ptr())
+      ->Rebind(quota->memory_quota_);
+}
+
+//
+// BasicMemoryQuota
+//
+
+class BasicMemoryQuota::WaitForSweepPromise {
+ public:
+  WaitForSweepPromise(std::shared_ptr<BasicMemoryQuota> memory_quota,
+                      uint64_t token)
+      : memory_quota_(std::move(memory_quota)), token_(token) {}
+
+  struct Empty {};
+  Poll<Empty> operator()() {
+    if (memory_quota_->reclamation_counter_.load(std::memory_order_relaxed) !=
+        token_) {
+      return Empty{};
+    } else {
+      return Pending{};
+    }
+  }
+
+ private:
+  std::shared_ptr<BasicMemoryQuota> memory_quota_;
+  uint64_t token_;
+};
+
+void BasicMemoryQuota::Start() {
+  auto self = shared_from_this();
+
+  // Reclamation loop:
+  // basically, wait until we are in overcommit (free_bytes_ < 0), and then:
+  // while (free_bytes_ < 0) reclaim_memory()
+  // ... and repeat
+  auto reclamation_loop = Loop(Seq(
+      [self]() -> Poll<int> {
+        // If there's free memory we no longer need to reclaim memory!
+        if (self->free_bytes_.load(std::memory_order_acquire) > 0) {
+          return Pending{};
+        }
+        return 0;
+      },
+      [self]() {
+        // Race biases to the first thing that completes... so this will
+        // choose the highest priority/least destructive thing to do that's
+        // available.
+        return Race(self->reclaimers_[0].Next(), self->reclaimers_[1].Next(),
+                    self->reclaimers_[2].Next(), self->reclaimers_[3].Next());
+      },
+      [self](ReclamationFunction reclaimer) {
+        // One of the reclaimer queues gave us a way to get back memory.
+        // Call the reclaimer with a token that contains enough to wake us
+        // up again.
+        const uint64_t token =
+            self->reclamation_counter_.fetch_add(1, std::memory_order_relaxed) +
+            1;
+        reclaimer(ReclamationSweep(self, token));
+        // Return a promise that will wait for our barrier. This will be
+        // awoken by the token above being destroyed. So, once that token is
+        // destroyed, we'll be able to proceed.
+        return WaitForSweepPromise(self, token);
+      },
+      []() -> LoopCtl<absl::Status> {
+        // Continue the loop!
+        return Continue{};
+      }));
+
+  reclaimer_activity_ =
+      MakeActivity(std::move(reclamation_loop), ExecCtxWakeupScheduler(),
+                   [](absl::Status status) {
+                     GPR_ASSERT(status.code() == absl::StatusCode::kCancelled);
+                   });
+}
+
+void BasicMemoryQuota::Stop() { reclaimer_activity_.reset(); }
+
+void BasicMemoryQuota::SetSize(size_t new_size) {
+  size_t old_size = quota_size_.exchange(new_size, std::memory_order_relaxed);
+  if (old_size < new_size) {
+    // We're growing the quota.
+    Return(new_size - old_size);
+  } else {
+    // We're shrinking the quota.
+    Take(old_size - new_size);
+  }
+}
+
+void BasicMemoryQuota::Take(size_t amount) {
+  // If there's a request for nothing, then do nothing!
+  if (amount == 0) return;
+  GPR_DEBUG_ASSERT(amount <= std::numeric_limits<intptr_t>::max());
+  // Grab memory from the quota.
+  auto prior = free_bytes_.fetch_sub(amount, std::memory_order_acq_rel);
+  // If we push into overcommit, awake the reclaimer.
+  if (prior >= 0 && prior < static_cast<intptr_t>(amount)) {
+    if (reclaimer_activity_ != nullptr) reclaimer_activity_->ForceWakeup();
+  }
+}
+
+void BasicMemoryQuota::FinishReclamation(uint64_t token) {
+  uint64_t current = reclamation_counter_.load(std::memory_order_relaxed);
+  if (current != token) return;
+  if (reclamation_counter_.compare_exchange_strong(current, current + 1,
+                                                   std::memory_order_relaxed,
+                                                   std::memory_order_relaxed)) {
+    if (reclaimer_activity_ != nullptr) reclaimer_activity_->ForceWakeup();
+  }
+}
+
+void BasicMemoryQuota::Return(size_t amount) {
+  free_bytes_.fetch_add(amount, std::memory_order_relaxed);
+}
+
+size_t BasicMemoryQuota::InstantaneousPressure() const {
+  double free = free_bytes_.load();
+  if (free < 0) free = 0;
+  double size = quota_size_.load();
+  if (size < 1) return 1.0;
+  double pressure = (size - free) / size;
+  if (pressure < 0.0) pressure = 0.0;
+  if (pressure > 1.0) pressure = 1.0;
+  return pressure;
+}
+
+}  // namespace grpc_core
diff --git a/src/core/lib/resource_quota/memory_quota.h b/src/core/lib/resource_quota/memory_quota.h
new file mode 100644 (file)
index 0000000..c19c262
--- /dev/null
@@ -0,0 +1,359 @@
+// 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.
+
+#ifndef GRPC_CORE_LIB_RESOURCE_QUOTA_MEMORY_QUOTA_H
+#define GRPC_CORE_LIB_RESOURCE_QUOTA_MEMORY_QUOTA_H
+
+#include <grpc/support/port_platform.h>
+
+#include <algorithm>
+#include <cstddef>
+#include <limits>
+#include <memory>
+#include <queue>
+#include <vector>
+
+#include <grpc/event_engine/memory_allocator.h>
+#include <grpc/slice.h>
+
+#include "src/core/lib/gprpp/sync.h"
+#include "src/core/lib/promise/activity.h"
+#include "src/core/lib/promise/poll.h"
+
+namespace grpc_core {
+
+class BasicMemoryQuota;
+class MemoryQuota;
+
+using grpc_event_engine::experimental::MemoryRequest;
+
+// Pull in impl under a different name to keep the gRPC/EventEngine separation
+// clear.
+using EventEngineMemoryAllocatorImpl =
+    grpc_event_engine::experimental::internal::MemoryAllocatorImpl;
+using grpc_event_engine::experimental::MemoryAllocator;
+template <typename T>
+using Vector = grpc_event_engine::experimental::Vector<T>;
+
+// Reclamation passes.
+// When memory is tight, we start trying to claim some back from memory
+// reclaimers. We do this in multiple passes: if there is a less destructive
+// operation available, we do that, otherwise we do something more destructive.
+enum class ReclamationPass {
+  // Non-empty reclamation ought to take index 0, but to simplify API we don't
+  // expose that publicly (it's an internal detail), and hence index zero is
+  // here unnamed.
+
+  // Benign reclamation is intended for reclamation steps that are not
+  // observable outside of gRPC (besides maybe causing an increase in CPU
+  // usage).
+  // Examples of such reclamation would be resizing buffers to fit the current
+  // load needs, rather than whatever was the peak usage requirement.
+  kBenign = 1,
+  // Idle reclamation is intended for reclamation steps that are observable
+  // outside of gRPC, but do not cause application work to be lost.
+  // Examples of such reclamation would be dropping channels that are not being
+  // used.
+  kIdle = 2,
+  // Destructive reclamation is our last resort, and is these reclamations are
+  // allowed to drop work - such as cancelling in flight requests.
+  kDestructive = 3,
+};
+static constexpr size_t kNumReclamationPasses = 4;
+
+// For each reclamation function run we construct a ReclamationSweep.
+// When this object is finally destroyed (it may be moved several times first),
+// then that reclamation is complete and we may continue the reclamation loop.
+class ReclamationSweep {
+ public:
+  ReclamationSweep(std::shared_ptr<BasicMemoryQuota> memory_quota,
+                   uint64_t sweep_token)
+      : memory_quota_(std::move(memory_quota)), sweep_token_(sweep_token) {}
+  ~ReclamationSweep();
+
+  ReclamationSweep(const ReclamationSweep&) = delete;
+  ReclamationSweep& operator=(const ReclamationSweep&) = delete;
+  ReclamationSweep(ReclamationSweep&&) = default;
+  ReclamationSweep& operator=(ReclamationSweep&&) = default;
+
+  // Has enough work been done that we would not be called upon again
+  // immediately to do reclamation work if we stopped and requeued. Reclaimers
+  // with a variable amount of work to do can use this to ascertain when they
+  // can stop more efficiently than going through the reclaimer queue once per
+  // work item.
+  bool IsSufficient() const;
+
+ private:
+  std::shared_ptr<BasicMemoryQuota> memory_quota_;
+  uint64_t sweep_token_;
+};
+
+using ReclamationFunction =
+    std::function<void(absl::optional<ReclamationSweep>)>;
+
+class ReclaimerQueue {
+ public:
+  using Index = size_t;
+
+  // An invalid index usable as an empty value.
+  // This value will not be returned from Insert ever.
+  static constexpr Index kInvalidIndex = std::numeric_limits<Index>::max();
+
+  // Insert a new element at the back of the queue.
+  // If there is already an element from allocator at *index, then it is
+  // replaced with the new reclaimer and *index is unchanged. If there is not,
+  // then *index is set to the index of the newly queued entry.
+  // Associates the reclamation function with an allocator, and keeps that
+  // allocator alive, so that we can use the pointer as an ABA guard.
+  void Insert(std::shared_ptr<EventEngineMemoryAllocatorImpl> allocator,
+              ReclamationFunction reclaimer, Index* index)
+      ABSL_LOCKS_EXCLUDED(mu_);
+  // Cancel a reclamation function - returns the function if cancelled
+  // successfully, or nullptr if the reclamation was already begun and could not
+  // be cancelled. allocator must be the same as was passed to Insert.
+  ReclamationFunction Cancel(Index index,
+                             EventEngineMemoryAllocatorImpl* allocator)
+      ABSL_LOCKS_EXCLUDED(mu_);
+  // Poll to see if an entry is available: returns Pending if not, or the
+  // removed reclamation function if so.
+  Poll<ReclamationFunction> PollNext() ABSL_LOCKS_EXCLUDED(mu_);
+
+  // This callable is the promise backing Next - it resolves when there is an
+  // entry available. This really just redirects to calling PollNext().
+  class NextPromise {
+   public:
+    explicit NextPromise(ReclaimerQueue* queue) : queue_(queue) {}
+    Poll<ReclamationFunction> operator()() { return queue_->PollNext(); }
+
+   private:
+    // Borrowed ReclaimerQueue backing this promise.
+    ReclaimerQueue* queue_;
+  };
+  NextPromise Next() { return NextPromise(this); }
+
+ private:
+  // One entry in the reclaimer queue
+  struct Entry {
+    Entry(std::shared_ptr<EventEngineMemoryAllocatorImpl> allocator,
+          ReclamationFunction reclaimer)
+        : allocator(std::move(allocator)), reclaimer(reclaimer) {}
+    // The allocator we'd be reclaiming for.
+    std::shared_ptr<EventEngineMemoryAllocatorImpl> allocator;
+    // The reclamation function to call.
+    ReclamationFunction reclaimer;
+  };
+  // Guarding mutex.
+  Mutex mu_;
+  // Entries in the queue (or empty entries waiting to be queued).
+  // We actually queue indices into this vector - and do this so that
+  // we can use the memory allocator pointer as an ABA protection.
+  std::vector<Entry> entries_ ABSL_GUARDED_BY(mu_);
+  // Which entries in entries_ are not allocated right now.
+  std::vector<size_t> free_entries_ ABSL_GUARDED_BY(mu_);
+  // Allocated entries waiting to be consumed.
+  std::queue<Index> queue_ ABSL_GUARDED_BY(mu_);
+  // Potentially one activity can be waiting for new entries on the queue.
+  Waker waker_ ABSL_GUARDED_BY(mu_);
+};
+
+class BasicMemoryQuota final
+    : public std::enable_shared_from_this<BasicMemoryQuota> {
+ public:
+  // Start the reclamation activity.
+  void Start();
+  // Stop the reclamation activity.
+  // Until reclamation is stopped, it's possible that circular references to the
+  // BasicMemoryQuota remain. i.e. to guarantee deletion, a singular owning
+  // object should call BasicMemoryQuota::Stop().
+  void Stop();
+
+  // Resize the quota to new_size.
+  void SetSize(size_t new_size);
+  // Forcefully take some memory from the quota, potentially entering
+  // overcommit.
+  void Take(size_t amount);
+  // Finish reclamation pass.
+  void FinishReclamation(uint64_t token);
+  // Return some memory to the quota.
+  void Return(size_t amount);
+  // Instantaneous memory pressure approximation.
+  size_t InstantaneousPressure() const;
+  // Cancel a reclaimer
+  ReclamationFunction CancelReclaimer(
+      size_t reclaimer, typename ReclaimerQueue::Index index,
+      EventEngineMemoryAllocatorImpl* allocator) {
+    return reclaimers_[reclaimer].Cancel(index, allocator);
+  }
+  // Insert a reclaimer
+  void InsertReclaimer(
+      size_t reclaimer,
+      std::shared_ptr<EventEngineMemoryAllocatorImpl> allocator,
+      ReclamationFunction fn, ReclaimerQueue::Index* index) {
+    reclaimers_[reclaimer].Insert(std::move(allocator), std::move(fn), index);
+  }
+
+ private:
+  friend class ReclamationSweep;
+  class WaitForSweepPromise;
+
+  static constexpr intptr_t kInitialSize = std::numeric_limits<intptr_t>::max();
+
+  // The amount of memory that's free in this quota.
+  // We use intptr_t as a reasonable proxy for ssize_t that's portable.
+  // We allow arbitrary overcommit and so this must allow negative values.
+  std::atomic<intptr_t> free_bytes_{kInitialSize};
+  // The total number of bytes in this quota.
+  std::atomic<size_t> quota_size_{kInitialSize};
+
+  // Reclaimer queues.
+  ReclaimerQueue reclaimers_[kNumReclamationPasses];
+  // The reclaimer activity consumes reclaimers whenever we are in overcommit to
+  // try and get back under memory limits.
+  ActivityPtr reclaimer_activity_;
+  // Each time we do a reclamation sweep, we increment this counter and give it
+  // to the sweep in question. In this way, should we choose to cancel a sweep
+  // we can do so and not get confused when the sweep reports back that it's
+  // completed.
+  // We also increment this counter on completion of a sweep, as an indicator
+  // that the wait has ended.
+  std::atomic<uint64_t> reclamation_counter_{0};
+};
+
+// MemoryAllocatorImpl grants the owner the ability to allocate memory from an
+// underlying resource quota.
+class GrpcMemoryAllocatorImpl final : public EventEngineMemoryAllocatorImpl {
+ public:
+  explicit GrpcMemoryAllocatorImpl(
+      std::shared_ptr<BasicMemoryQuota> memory_quota);
+  ~GrpcMemoryAllocatorImpl() override;
+
+  // Rebind - Swaps the underlying quota for this allocator, taking care to
+  // make sure memory allocated is moved to allocations against the new quota.
+  void Rebind(std::shared_ptr<BasicMemoryQuota> memory_quota)
+      ABSL_LOCKS_EXCLUDED(memory_quota_mu_);
+
+  // Reserve bytes from the quota.
+  // If we enter overcommit, reclamation will begin concurrently.
+  // Returns the number of bytes reserved.
+  size_t Reserve(MemoryRequest request) override;
+
+  // Release some bytes that were previously reserved.
+  void Release(size_t n) override {
+    // Add the released memory to our free bytes counter... if this increases
+    // from  0 to non-zero, then we have more to do, otherwise, we're actually
+    // done.
+    if (free_bytes_.fetch_add(n, std::memory_order_release) != 0) return;
+    MaybeRegisterReclaimer();
+  }
+
+  // Post a reclamation function.
+  void PostReclaimer(ReclamationPass pass, ReclamationFunction fn);
+
+  // Shutdown the allocator.
+  void Shutdown() override;
+
+ private:
+  // Primitive reservation function.
+  absl::optional<size_t> TryReserve(MemoryRequest request) GRPC_MUST_USE_RESULT;
+  // Replenish bytes from the quota, without blocking, possibly entering
+  // overcommit.
+  void Replenish() ABSL_LOCKS_EXCLUDED(memory_quota_mu_);
+  // If we have not already, register a reclamation function against the quota
+  // to sweep any free memory back to that quota.
+  void MaybeRegisterReclaimer() ABSL_LOCKS_EXCLUDED(memory_quota_mu_);
+  void MaybeRegisterReclaimerLocked()
+      ABSL_EXCLUSIVE_LOCKS_REQUIRED(memory_quota_mu_);
+
+  // Amount of memory this allocator has cached for its own use: to avoid quota
+  // contention, each MemoryAllocator can keep some memory in addition to what
+  // it is immediately using, and the quota can pull it back under memory
+  // pressure.
+  std::atomic<size_t> free_bytes_{0};
+  // Mutex guarding the backing resource quota.
+  Mutex memory_quota_mu_;
+  // Backing resource quota.
+  std::shared_ptr<BasicMemoryQuota> memory_quota_
+      ABSL_GUARDED_BY(memory_quota_mu_);
+  // Amount of memory taken from the quota by this allocator.
+  size_t taken_bytes_ ABSL_GUARDED_BY(memory_quota_mu_) =
+      sizeof(GrpcMemoryAllocatorImpl);
+  bool shutdown_ ABSL_GUARDED_BY(memory_quota_mu_) = false;
+  // Indices into the various reclaimer queues, used so that we can cancel
+  // reclamation should we shutdown or get rebound.
+  ReclaimerQueue::Index
+      reclamation_indices_[kNumReclamationPasses] ABSL_GUARDED_BY(
+          memory_quota_mu_) = {
+          ReclaimerQueue::kInvalidIndex, ReclaimerQueue::kInvalidIndex,
+          ReclaimerQueue::kInvalidIndex, ReclaimerQueue::kInvalidIndex};
+};
+
+// MemoryOwner is an enhanced MemoryAllocator that can also reclaim memory, and
+// be rebound to a different memory quota.
+class MemoryOwner {
+ public:
+  explicit MemoryOwner(std::shared_ptr<GrpcMemoryAllocatorImpl> allocator)
+      : allocator_(std::move(allocator)) {}
+
+  MemoryAllocator* allocator() { return &allocator_; }
+
+  // Post a reclaimer for some reclamation pass.
+  void PostReclaimer(ReclamationPass pass, ReclamationFunction fn) {
+    static_cast<GrpcMemoryAllocatorImpl*>(allocator_.get_internal_impl_ptr())
+        ->PostReclaimer(pass, std::move(fn));
+  }
+
+  // Rebind to a different quota.
+  void Rebind(MemoryQuota* quota);
+
+ private:
+  MemoryAllocator allocator_;
+};
+
+// MemoryQuota tracks the amount of memory available as part of a ResourceQuota.
+class MemoryQuota final
+    : public grpc_event_engine::experimental::MemoryAllocatorFactory {
+ public:
+  MemoryQuota() : memory_quota_(std::make_shared<BasicMemoryQuota>()) {
+    memory_quota_->Start();
+  }
+  ~MemoryQuota() override {
+    if (memory_quota_ != nullptr) memory_quota_->Stop();
+  }
+
+  MemoryQuota(const MemoryQuota&) = delete;
+  MemoryQuota& operator=(const MemoryQuota&) = delete;
+  MemoryQuota(MemoryQuota&&) = default;
+  MemoryQuota& operator=(MemoryQuota&&) = default;
+
+  MemoryAllocator CreateMemoryAllocator() override {
+    auto impl = std::make_shared<GrpcMemoryAllocatorImpl>(memory_quota_);
+    return MemoryAllocator(std::move(impl));
+  }
+
+  MemoryOwner CreateMemoryOwner() {
+    auto impl = std::make_shared<GrpcMemoryAllocatorImpl>(memory_quota_);
+    return MemoryOwner(std::move(impl));
+  }
+
+  // Resize the quota to new_size.
+  void SetSize(size_t new_size) { memory_quota_->SetSize(new_size); }
+
+ private:
+  friend class MemoryOwner;
+  std::shared_ptr<BasicMemoryQuota> memory_quota_;
+};
+
+}  // namespace grpc_core
+
+#endif  // GRPC_CORE_LIB_RESOURCE_QUOTA_MEMORY_QUOTA_H
diff --git a/src/core/lib/resource_quota/resource_quota.cc b/src/core/lib/resource_quota/resource_quota.cc
new file mode 100644 (file)
index 0000000..cf4229b
--- /dev/null
@@ -0,0 +1,27 @@
+// 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 <grpc/support/port_platform.h>
+
+#include "src/core/lib/resource_quota/resource_quota.h"
+
+namespace grpc_core {
+
+ResourceQuota::ResourceQuota()
+    : memory_quota_(std::make_shared<MemoryQuota>()),
+      thread_quota_(MakeRefCounted<ThreadQuota>()) {}
+
+ResourceQuota::~ResourceQuota() = default;
+
+}  // namespace grpc_core
diff --git a/src/core/lib/resource_quota/resource_quota.h b/src/core/lib/resource_quota/resource_quota.h
new file mode 100644 (file)
index 0000000..c43e4c8
--- /dev/null
@@ -0,0 +1,44 @@
+// 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.
+
+#ifndef GRPC_CORE_LIB_RESOURCE_QUOTA_RESOURCE_QUOTA_H
+#define GRPC_CORE_LIB_RESOURCE_QUOTA_RESOURCE_QUOTA_H
+
+#include <grpc/support/port_platform.h>
+
+#include "src/core/lib/resource_quota/memory_quota.h"
+#include "src/core/lib/resource_quota/thread_quota.h"
+
+namespace grpc_core {
+
+class ResourceQuota : public RefCounted<ResourceQuota> {
+ public:
+  ResourceQuota();
+  ~ResourceQuota() override;
+
+  ResourceQuota(const ResourceQuota&) = delete;
+  ResourceQuota& operator=(const ResourceQuota&) = delete;
+
+  std::shared_ptr<MemoryQuota> memory_quota() { return memory_quota_; }
+
+  const RefCountedPtr<ThreadQuota>& thread_quota() { return thread_quota_; }
+
+ private:
+  std::shared_ptr<MemoryQuota> memory_quota_;
+  RefCountedPtr<ThreadQuota> thread_quota_;
+};
+
+}  // namespace grpc_core
+
+#endif  // GRPC_CORE_LIB_RESOURCE_QUOTA_RESOURCE_QUOTA_H
diff --git a/src/core/lib/resource_quota/thread_quota.cc b/src/core/lib/resource_quota/thread_quota.cc
new file mode 100644 (file)
index 0000000..c935be0
--- /dev/null
@@ -0,0 +1,43 @@
+// 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 <grpc/support/port_platform.h>
+
+#include "src/core/lib/resource_quota/thread_quota.h"
+
+namespace grpc_core {
+
+ThreadQuota::ThreadQuota() = default;
+
+ThreadQuota::~ThreadQuota() = default;
+
+void ThreadQuota::SetMax(size_t new_max) {
+  MutexLock lock(&mu_);
+  max_ = new_max;
+}
+
+bool ThreadQuota::Reserve(size_t num_threads) {
+  MutexLock lock(&mu_);
+  if (allocated_ + num_threads > max_) return false;
+  allocated_ += num_threads;
+  return true;
+}
+
+void ThreadQuota::Release(size_t num_threads) {
+  MutexLock lock(&mu_);
+  GPR_ASSERT(num_threads <= allocated_);
+  allocated_ -= num_threads;
+}
+
+}  // namespace grpc_core
diff --git a/src/core/lib/resource_quota/thread_quota.h b/src/core/lib/resource_quota/thread_quota.h
new file mode 100644 (file)
index 0000000..0f236dd
--- /dev/null
@@ -0,0 +1,55 @@
+// 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.
+
+#ifndef GRPC_CORE_LIB_RESOURCE_QUOTA_THREAD_QUOTA_H
+#define GRPC_CORE_LIB_RESOURCE_QUOTA_THREAD_QUOTA_H
+
+#include <grpc/support/port_platform.h>
+
+#include <cstddef>
+
+#include "src/core/lib/gprpp/ref_counted.h"
+#include "src/core/lib/gprpp/sync.h"
+
+namespace grpc_core {
+
+// Tracks the amount of threads in a resource quota.
+class ThreadQuota : public RefCounted<ThreadQuota> {
+ public:
+  ThreadQuota();
+  ~ThreadQuota() override;
+
+  ThreadQuota(const ThreadQuota&) = delete;
+  ThreadQuota& operator=(const ThreadQuota&) = delete;
+
+  // Set the maximum number of threads that can be used by this quota.
+  // If there are more, new reservations will fail until the quota is available.
+  void SetMax(size_t new_max);
+
+  // Try to allocate some number of threads.
+  // Returns true if the allocation succeeded, false otherwise.
+  bool Reserve(size_t num_threads);
+
+  // Release some number of threads.
+  void Release(size_t num_threads);
+
+ private:
+  Mutex mu_;
+  size_t allocated_ ABSL_GUARDED_BY(mu_) = 0;
+  size_t max_ ABSL_GUARDED_BY(mu_) = std::numeric_limits<size_t>::max();
+};
+
+}  // namespace grpc_core
+
+#endif  // GRPC_CORE_LIB_RESOURCE_QUOTA_THREAD_QUOTA_H
index 0268a2c..7db9006 100644 (file)
@@ -27,7 +27,7 @@ struct grpc_authorization_policy_provider
     grpc_core::RefCountedPtr<grpc_core::AuthorizationEngine> allow_engine;
     grpc_core::RefCountedPtr<grpc_core::AuthorizationEngine> deny_engine;
   };
-  virtual AuthorizationEngines engines() const = 0;
+  virtual AuthorizationEngines engines() = 0;
 };
 
 #endif  // GRPC_CORE_LIB_SECURITY_AUTHORIZATION_AUTHORIZATION_POLICY_PROVIDER_H
index ed040ed..f8a4426 100644 (file)
@@ -33,7 +33,7 @@ void ProviderArgDestroy(void* p) {
   provider->Unref();
 }
 
-int ProviderArgCmp(void* p, void* q) { return GPR_ICMP(p, q); }
+int ProviderArgCmp(void* p, void* q) { return grpc_core::QsortCompare(p, q); }
 
 }  // namespace
 
index aa9f249..80b713c 100644 (file)
@@ -80,8 +80,9 @@ EvaluateArgs::PerChannelArgs::PerChannelArgs(grpc_auth_context* auth_context,
 
 absl::string_view EvaluateArgs::GetPath() const {
   absl::string_view path;
-  if (metadata_ != nullptr && metadata_->idx.named.path != nullptr) {
-    grpc_linked_mdelem* elem = metadata_->idx.named.path;
+  if (metadata_ != nullptr &&
+      metadata_->legacy_index()->named.path != nullptr) {
+    grpc_linked_mdelem* elem = metadata_->legacy_index()->named.path;
     const grpc_slice& val = GRPC_MDVALUE(elem->md);
     path = StringViewFromSlice(val);
   }
@@ -90,8 +91,9 @@ absl::string_view EvaluateArgs::GetPath() const {
 
 absl::string_view EvaluateArgs::GetHost() const {
   absl::string_view host;
-  if (metadata_ != nullptr && metadata_->idx.named.host != nullptr) {
-    grpc_linked_mdelem* elem = metadata_->idx.named.host;
+  if (metadata_ != nullptr &&
+      metadata_->legacy_index()->named.host != nullptr) {
+    grpc_linked_mdelem* elem = metadata_->legacy_index()->named.host;
     const grpc_slice& val = GRPC_MDVALUE(elem->md);
     host = StringViewFromSlice(val);
   }
@@ -100,8 +102,9 @@ absl::string_view EvaluateArgs::GetHost() const {
 
 absl::string_view EvaluateArgs::GetMethod() const {
   absl::string_view method;
-  if (metadata_ != nullptr && metadata_->idx.named.method != nullptr) {
-    grpc_linked_mdelem* elem = metadata_->idx.named.method;
+  if (metadata_ != nullptr &&
+      metadata_->legacy_index()->named.method != nullptr) {
+    grpc_linked_mdelem* elem = metadata_->legacy_index()->named.method;
     const grpc_slice& val = GRPC_MDVALUE(elem->md);
     method = StringViewFromSlice(val);
   }
@@ -114,12 +117,11 @@ std::multimap<absl::string_view, absl::string_view> EvaluateArgs::GetHeaders()
   if (metadata_ == nullptr) {
     return headers;
   }
-  for (grpc_linked_mdelem* elem = metadata_->list.head; elem != nullptr;
-       elem = elem->next) {
-    const grpc_slice& key = GRPC_MDKEY(elem->md);
-    const grpc_slice& val = GRPC_MDVALUE(elem->md);
+  metadata_->ForEach([&](grpc_mdelem md) {
+    const grpc_slice& key = GRPC_MDKEY(md);
+    const grpc_slice& val = GRPC_MDVALUE(md);
     headers.emplace(StringViewFromSlice(key), StringViewFromSlice(val));
-  }
+  });
   return headers;
 }
 
@@ -128,7 +130,7 @@ absl::optional<absl::string_view> EvaluateArgs::GetHeaderValue(
   if (metadata_ == nullptr) {
     return absl::nullopt;
   }
-  return grpc_metadata_batch_get_value(metadata_, key, concatenated_value);
+  return metadata_->GetValue(key, concatenated_value);
 }
 
 grpc_resolved_address EvaluateArgs::GetLocalAddress() const {
index c482f79..773dbd2 100644 (file)
@@ -38,6 +38,9 @@ class GrpcAuthorizationEngine : public AuthorizationEngine {
 
   Rbac::Action action() { return action_; }
 
+  // Required only for testing purpose.
+  size_t num_policies() { return policies_.size(); }
+
   // Evaluates incoming request against RBAC policy and makes a decision to
   // whether allow/deny this request.
   Decision Evaluate(const EvaluateArgs& args) const override;
index 7a0c77e..c7236aa 100644 (file)
 #include <grpc/grpc_security.h>
 #include <grpc/support/string_util.h>
 
+#include "src/core/lib/iomgr/load_file.h"
 #include "src/core/lib/security/authorization/grpc_authorization_engine.h"
+#include "src/core/lib/slice/slice_internal.h"
 
 namespace grpc_core {
 
+extern TraceFlag grpc_sdk_authz_trace;
+
 absl::StatusOr<RefCountedPtr<grpc_authorization_policy_provider>>
 StaticDataAuthorizationPolicyProvider::Create(absl::string_view authz_policy) {
   auto policies_or = GenerateRbacPolicies(authz_policy);
@@ -40,6 +44,113 @@ StaticDataAuthorizationPolicyProvider::StaticDataAuthorizationPolicyProvider(
       deny_engine_(MakeRefCounted<GrpcAuthorizationEngine>(
           std::move(policies.deny_policy))) {}
 
+namespace {
+
+absl::StatusOr<std::string> ReadPolicyFromFile(absl::string_view policy_path) {
+  grpc_slice policy_slice = grpc_empty_slice();
+  grpc_error_handle error =
+      grpc_load_file(std::string(policy_path).c_str(), 0, &policy_slice);
+  if (error != GRPC_ERROR_NONE) {
+    absl::Status status =
+        absl::InvalidArgumentError(grpc_error_std_string(error));
+    GRPC_ERROR_UNREF(error);
+    return status;
+  }
+  std::string policy_contents(StringViewFromSlice(policy_slice));
+  grpc_slice_unref_internal(policy_slice);
+  return policy_contents;
+}
+
+gpr_timespec TimeoutSecondsToDeadline(int64_t seconds) {
+  return gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
+                      gpr_time_from_seconds(seconds, GPR_TIMESPAN));
+}
+
+}  // namespace
+
+absl::StatusOr<RefCountedPtr<grpc_authorization_policy_provider>>
+FileWatcherAuthorizationPolicyProvider::Create(
+    absl::string_view authz_policy_path, unsigned int refresh_interval_sec) {
+  GPR_ASSERT(!authz_policy_path.empty());
+  GPR_ASSERT(refresh_interval_sec > 0);
+  absl::Status status;
+  auto provider = MakeRefCounted<FileWatcherAuthorizationPolicyProvider>(
+      authz_policy_path, refresh_interval_sec, &status);
+  if (!status.ok()) return status;
+  return provider;
+}
+
+FileWatcherAuthorizationPolicyProvider::FileWatcherAuthorizationPolicyProvider(
+    absl::string_view authz_policy_path, unsigned int refresh_interval_sec,
+    absl::Status* status)
+    : authz_policy_path_(std::string(authz_policy_path)),
+      refresh_interval_sec_(refresh_interval_sec) {
+  gpr_event_init(&shutdown_event_);
+  // Initial read is done synchronously.
+  *status = ForceUpdate();
+  if (!status->ok()) {
+    return;
+  }
+  auto thread_lambda = [](void* arg) {
+    WeakRefCountedPtr<FileWatcherAuthorizationPolicyProvider> provider(
+        static_cast<FileWatcherAuthorizationPolicyProvider*>(arg));
+    GPR_ASSERT(provider != nullptr);
+    while (true) {
+      void* value = gpr_event_wait(
+          &provider->shutdown_event_,
+          TimeoutSecondsToDeadline(provider->refresh_interval_sec_));
+      if (value != nullptr) {
+        return;
+      }
+      absl::Status status = provider->ForceUpdate();
+      if (GRPC_TRACE_FLAG_ENABLED(grpc_sdk_authz_trace) && !status.ok()) {
+        gpr_log(GPR_ERROR,
+                "authorization policy reload status. code=%d error_details=%s",
+                status.code(), std::string(status.message()).c_str());
+      }
+    }
+  };
+  refresh_thread_ = absl::make_unique<grpc_core::Thread>(
+      "FileWatcherAuthorizationPolicyProvider_refreshing_thread", thread_lambda,
+      WeakRef().release());
+  refresh_thread_->Start();
+}
+
+absl::Status FileWatcherAuthorizationPolicyProvider::ForceUpdate() {
+  absl::StatusOr<std::string> file_contents =
+      ReadPolicyFromFile(authz_policy_path_);
+  if (!file_contents.ok()) {
+    return file_contents.status();
+  }
+  if (file_contents_ == *file_contents) {
+    return absl::OkStatus();
+  }
+  file_contents_ = std::move(*file_contents);
+  auto rbac_policies_or = GenerateRbacPolicies(file_contents_);
+  if (!rbac_policies_or.ok()) {
+    return rbac_policies_or.status();
+  }
+  grpc_core::MutexLock lock(&mu_);
+  allow_engine_ = MakeRefCounted<GrpcAuthorizationEngine>(
+      std::move(rbac_policies_or->allow_policy));
+  deny_engine_ = MakeRefCounted<GrpcAuthorizationEngine>(
+      std::move(rbac_policies_or->deny_policy));
+  if (GRPC_TRACE_FLAG_ENABLED(grpc_sdk_authz_trace)) {
+    gpr_log(GPR_INFO,
+            "authorization policy reload status: successfully loaded new "
+            "policy\n%s",
+            file_contents_.c_str());
+  }
+  return absl::OkStatus();
+}
+
+void FileWatcherAuthorizationPolicyProvider::Orphan() {
+  gpr_event_set(&shutdown_event_, reinterpret_cast<void*>(1));
+  if (refresh_thread_ != nullptr) {
+    refresh_thread_->Join();
+  }
+}
+
 }  // namespace grpc_core
 
 // Wrapper APIs declared in grpc_security.h
@@ -57,8 +168,22 @@ grpc_authorization_policy_provider_static_data_create(
         gpr_strdup(std::string(provider_or.status().message()).c_str());
     return nullptr;
   }
-  *code = GRPC_STATUS_OK;
-  *error_details = nullptr;
+  return provider_or->release();
+}
+
+grpc_authorization_policy_provider*
+grpc_authorization_policy_provider_file_watcher_create(
+    const char* authz_policy_path, unsigned int refresh_interval_sec,
+    grpc_status_code* code, const char** error_details) {
+  GPR_ASSERT(authz_policy_path != nullptr);
+  auto provider_or = grpc_core::FileWatcherAuthorizationPolicyProvider::Create(
+      authz_policy_path, refresh_interval_sec);
+  if (!provider_or.ok()) {
+    *code = static_cast<grpc_status_code>(provider_or.status().code());
+    *error_details =
+        gpr_strdup(std::string(provider_or.status().message()).c_str());
+    return nullptr;
+  }
   return provider_or->release();
 }
 
index 4e80ac6..44b74a3 100644 (file)
@@ -21,6 +21,8 @@
 
 #include "absl/status/statusor.h"
 
+#include "src/core/lib/gprpp/sync.h"
+#include "src/core/lib/gprpp/thd.h"
 #include "src/core/lib/security/authorization/authorization_policy_provider.h"
 #include "src/core/lib/security/authorization/rbac_translator.h"
 
@@ -36,9 +38,11 @@ class StaticDataAuthorizationPolicyProvider
   static absl::StatusOr<RefCountedPtr<grpc_authorization_policy_provider>>
   Create(absl::string_view authz_policy);
 
+  // Use factory method "Create" to create an instance of
+  // StaticDataAuthorizationPolicyProvider.
   explicit StaticDataAuthorizationPolicyProvider(RbacPolicies policies);
 
-  AuthorizationEngines engines() const override {
+  AuthorizationEngines engines() override {
     return {allow_engine_, deny_engine_};
   }
 
@@ -49,8 +53,50 @@ class StaticDataAuthorizationPolicyProvider
   RefCountedPtr<AuthorizationEngine> deny_engine_;
 };
 
-// TODO(ashithasantosh): Add implementation for file watcher authorization
-// policy provider.
+// Provider class will get SDK Authorization policy from provided file path.
+// This policy will be translated to Envoy RBAC policies and used to initialize
+// allow and deny AuthorizationEngine objects. This provider will periodically
+// load file contents in specified path, and upon modification update the engine
+// instances with new policy configuration. During reload if the file contents
+// are invalid or there are I/O errors, we will skip that particular update and
+// log error status. The authorization decisions will be made using the latest
+// valid policy.
+class FileWatcherAuthorizationPolicyProvider
+    : public grpc_authorization_policy_provider {
+ public:
+  static absl::StatusOr<RefCountedPtr<grpc_authorization_policy_provider>>
+  Create(absl::string_view authz_policy_path,
+         unsigned int refresh_interval_sec);
+
+  // Use factory method "Create" to create an instance of
+  // FileWatcherAuthorizationPolicyProvider.
+  FileWatcherAuthorizationPolicyProvider(absl::string_view authz_policy_path,
+                                         unsigned int refresh_interval_sec,
+                                         absl::Status* status);
+
+  void Orphan() override;
+
+  AuthorizationEngines engines() override {
+    grpc_core::MutexLock lock(&mu_);
+    return {allow_engine_, deny_engine_};
+  }
+
+ private:
+  // Force an update from the file system regardless of the interval.
+  absl::Status ForceUpdate();
+
+  std::string authz_policy_path_;
+  std::string file_contents_;
+  unsigned int refresh_interval_sec_;
+
+  std::unique_ptr<Thread> refresh_thread_;
+  gpr_event shutdown_event_;
+
+  grpc_core::Mutex mu_;
+  // Engines created using authz_policy_.
+  RefCountedPtr<AuthorizationEngine> allow_engine_ ABSL_GUARDED_BY(mu_);
+  RefCountedPtr<AuthorizationEngine> deny_engine_ ABSL_GUARDED_BY(mu_);
+};
 
 }  // namespace grpc_core
 
index a5d337b..202e591 100644 (file)
@@ -175,7 +175,8 @@ bool PortAuthorizationMatcher::Matches(const EvaluateArgs& args) const {
 
 bool AuthenticatedAuthorizationMatcher::Matches(
     const EvaluateArgs& args) const {
-  if (args.GetTransportSecurityType() != GRPC_SSL_TRANSPORT_SECURITY_TYPE) {
+  if (args.GetTransportSecurityType() != GRPC_SSL_TRANSPORT_SECURITY_TYPE &&
+      args.GetTransportSecurityType() != GRPC_TLS_TRANSPORT_SECURITY_TYPE) {
     // Connection is not authenticated.
     return false;
   }
index 473fc73..efd1755 100644 (file)
@@ -92,6 +92,18 @@ void SdkServerAuthzFilter::CallData::Destroy(
 bool SdkServerAuthzFilter::CallData::IsAuthorized(SdkServerAuthzFilter* chand) {
   EvaluateArgs args(recv_initial_metadata_batch_,
                     &chand->per_channel_evaluate_args_);
+  if (GRPC_TRACE_FLAG_ENABLED(grpc_sdk_authz_trace)) {
+    gpr_log(
+        GPR_DEBUG,
+        "checking request: url_path=%s, transport_security_type=%s, "
+        "uri_sans=[%s], dns_sans=[%s], local_address=%s:%d, peer_address=%s:%d",
+        std::string(args.GetPath()).c_str(),
+        std::string(args.GetTransportSecurityType()).c_str(),
+        absl::StrJoin(args.GetUriSans(), ",").c_str(),
+        absl::StrJoin(args.GetDnsSans(), ",").c_str(),
+        std::string(args.GetLocalAddressString()).c_str(), args.GetLocalPort(),
+        std::string(args.GetPeerAddressString()).c_str(), args.GetPeerPort());
+  }
   grpc_authorization_policy_provider::AuthorizationEngines engines =
       chand->provider_->engines();
   if (engines.deny_engine != nullptr) {
@@ -137,7 +149,7 @@ void SdkServerAuthzFilter::CallData::RecvInitialMetadataReady(
                                  GRPC_STATUS_PERMISSION_DENIED);
     }
   } else {
-    GRPC_ERROR_REF(error);
+    (void)GRPC_ERROR_REF(error);
   }
   Closure::Run(DEBUG_LOCATION, calld->original_recv_initial_metadata_ready_,
                error);
index bc683f3..257f5c2 100644 (file)
@@ -223,7 +223,7 @@ grpc_auth_property_iterator grpc_auth_context_peer_identity(
 void grpc_auth_context::ensure_capacity() {
   if (properties_.count == properties_.capacity) {
     properties_.capacity =
-        GPR_MAX(properties_.capacity + 8, properties_.capacity * 2);
+        std::max(properties_.capacity + 8, properties_.capacity * 2);
     properties_.array = static_cast<grpc_auth_property*>(gpr_realloc(
         properties_.array, properties_.capacity * sizeof(grpc_auth_property)));
   }
@@ -289,7 +289,9 @@ static void* auth_context_pointer_arg_copy(void* p) {
              : ctx->Ref(DEBUG_LOCATION, "auth_context_pointer_arg").release();
 }
 
-static int auth_context_pointer_cmp(void* a, void* b) { return GPR_ICMP(a, b); }
+static int auth_context_pointer_cmp(void* a, void* b) {
+  return grpc_core::QsortCompare(a, b);
+}
 
 static const grpc_arg_pointer_vtable auth_context_pointer_vtable = {
     auth_context_pointer_arg_copy, auth_context_pointer_arg_destroy,
index b4bdc31..83bc728 100644 (file)
@@ -147,7 +147,7 @@ void grpc_composite_call_credentials::push_to_inner(
   auto composite_creds =
       static_cast<grpc_composite_call_credentials*>(creds.get());
   for (size_t i = 0; i < composite_creds->inner().size(); ++i) {
-    inner_.push_back(std::move(composite_creds->inner_[i]));
+    inner_.push_back(composite_creds->inner_[i]);
   }
 }
 
index dcc69d7..01e409c 100644 (file)
@@ -59,7 +59,9 @@ static void* credentials_pointer_arg_copy(void* p) {
   return static_cast<grpc_channel_credentials*>(p)->Ref().release();
 }
 
-static int credentials_pointer_cmp(void* a, void* b) { return GPR_ICMP(a, b); }
+static int credentials_pointer_cmp(void* a, void* b) {
+  return grpc_core::QsortCompare(a, b);
+}
 
 static const grpc_arg_pointer_vtable credentials_pointer_vtable = {
     credentials_pointer_arg_copy, credentials_pointer_arg_destroy,
@@ -127,7 +129,7 @@ static void* server_credentials_pointer_arg_copy(void* p) {
 }
 
 static int server_credentials_pointer_cmp(void* a, void* b) {
-  return GPR_ICMP(a, b);
+  return grpc_core::QsortCompare(a, b);
 }
 
 static const grpc_arg_pointer_vtable cred_ptr_vtable = {
index 737fe87..674937b 100644 (file)
@@ -93,7 +93,7 @@ void grpc_override_well_known_credentials_path_getter(
 
 /* --- grpc_channel_credentials. --- */
 
-#define GRPC_ARG_CHANNEL_CREDENTIALS "grpc.channel_credentials"
+#define GRPC_ARG_CHANNEL_CREDENTIALS "grpc.internal.channel_credentials"
 
 // This type is forward declared as a C struct and we cannot define it as a
 // class. Otherwise, compiler will complain about type mismatch due to
@@ -137,6 +137,11 @@ struct grpc_channel_credentials
   const char* type_;
 };
 
+// TODO(roth): Once we eliminate insecure builds, find a better way to
+// plumb credentials so that it doesn't need to flow through channel
+// args.  For example, we'll want to expose it to LB policies by adding
+// methods on the helper API.
+
 /* Util to encapsulate the channel credentials in a channel arg. */
 grpc_arg grpc_channel_credentials_to_arg(grpc_channel_credentials* credentials);
 
index f3c6a78..dbcb123 100644 (file)
 
 #include "src/core/lib/security/credentials/external/external_account_credentials.h"
 
+#include "absl/strings/match.h"
 #include "absl/strings/str_format.h"
 #include "absl/strings/str_join.h"
 #include "absl/strings/str_split.h"
+#include "absl/strings/strip.h"
 #include "absl/time/clock.h"
 #include "absl/time/time.h"
 
@@ -59,6 +61,23 @@ std::string UrlEncode(const absl::string_view& s) {
   return result;
 }
 
+// Expression to match:
+// //iam.googleapis.com/locations/[^/]+/workforcePools/[^/]+/providers/.+
+bool MatchWorkforcePoolAudience(absl::string_view audience) {
+  // Match "//iam.googleapis.com/locations/"
+  if (!absl::ConsumePrefix(&audience, "//iam.googleapis.com")) return false;
+  if (!absl::ConsumePrefix(&audience, "/locations/")) return false;
+  // Match "[^/]+/workforcePools/"
+  std::pair<absl::string_view, absl::string_view> workforce_pools_split_result =
+      absl::StrSplit(audience, absl::MaxSplits("/workforcePools/", 1));
+  if (absl::StrContains(workforce_pools_split_result.first, '/')) return false;
+  // Match "[^/]+/providers/.+"
+  std::pair<absl::string_view, absl::string_view> providers_split_result =
+      absl::StrSplit(workforce_pools_split_result.second,
+                     absl::MaxSplits("/providers/", 1));
+  return !absl::StrContains(providers_split_result.first, '/');
+}
+
 }  // namespace
 
 RefCountedPtr<ExternalAccountCredentials> ExternalAccountCredentials::Create(
@@ -151,6 +170,17 @@ RefCountedPtr<ExternalAccountCredentials> ExternalAccountCredentials::Create(
   if (it != json.object_value().end()) {
     options.client_secret = it->second.string_value();
   }
+  it = json.object_value().find("workforce_pool_user_project");
+  if (it != json.object_value().end()) {
+    if (MatchWorkforcePoolAudience(options.audience)) {
+      options.workforce_pool_user_project = it->second.string_value();
+    } else {
+      *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+          "workforce_pool_user_project should not be set for non-workforce "
+          "pool credentials");
+      return nullptr;
+    }
+  }
   RefCountedPtr<ExternalAccountCredentials> creds;
   if (options.credential_source.object_value().find("environment_id") !=
       options.credential_source.object_value().end()) {
@@ -267,25 +297,31 @@ void ExternalAccountCredentials::ExchangeToken(
   request.handshaker =
       uri->scheme() == "https" ? &grpc_httpcli_ssl : &grpc_httpcli_plaintext;
   std::vector<std::string> body_parts;
-  body_parts.push_back(absl::StrFormat("%s=%s", "audience",
-                                       UrlEncode(options_.audience).c_str()));
+  body_parts.push_back(
+      absl::StrFormat("audience=%s", UrlEncode(options_.audience).c_str()));
   body_parts.push_back(absl::StrFormat(
-      "%s=%s", "grant_type",
+      "grant_type=%s",
       UrlEncode(EXTERNAL_ACCOUNT_CREDENTIALS_GRANT_TYPE).c_str()));
   body_parts.push_back(absl::StrFormat(
-      "%s=%s", "requested_token_type",
+      "requested_token_type=%s",
       UrlEncode(EXTERNAL_ACCOUNT_CREDENTIALS_REQUESTED_TOKEN_TYPE).c_str()));
+  body_parts.push_back(absl::StrFormat(
+      "subject_token_type=%s", UrlEncode(options_.subject_token_type).c_str()));
   body_parts.push_back(
-      absl::StrFormat("%s=%s", "subject_token_type",
-                      UrlEncode(options_.subject_token_type).c_str()));
-  body_parts.push_back(absl::StrFormat("%s=%s", "subject_token",
-                                       UrlEncode(subject_token).c_str()));
+      absl::StrFormat("subject_token=%s", UrlEncode(subject_token).c_str()));
   std::string scope = GOOGLE_CLOUD_PLATFORM_DEFAULT_SCOPE;
   if (options_.service_account_impersonation_url.empty()) {
     scope = absl::StrJoin(scopes_, " ");
   }
-  body_parts.push_back(
-      absl::StrFormat("%s=%s", "scope", UrlEncode(scope).c_str()));
+  body_parts.push_back(absl::StrFormat("scope=%s", UrlEncode(scope).c_str()));
+  Json::Object addtional_options_json_object;
+  if (options_.client_id.empty() && options_.client_secret.empty()) {
+    addtional_options_json_object["userProject"] =
+        options_.workforce_pool_user_project;
+  }
+  Json addtional_options_json(std::move(addtional_options_json_object));
+  body_parts.push_back(absl::StrFormat(
+      "options=%s", UrlEncode(addtional_options_json.Dump()).c_str()));
   std::string body = absl::StrJoin(body_parts, "&");
   grpc_resource_quota* resource_quota =
       grpc_resource_quota_create("external_account_credentials");
@@ -372,7 +408,7 @@ void ExternalAccountCredentials::ImpersenateServiceAccount() {
   request.handshaker =
       uri->scheme() == "https" ? &grpc_httpcli_ssl : &grpc_httpcli_plaintext;
   std::string scope = absl::StrJoin(scopes_, " ");
-  std::string body = absl::StrFormat("%s=%s", "scope", scope);
+  std::string body = absl::StrFormat("scope=%s", scope);
   grpc_resource_quota* resource_quota =
       grpc_resource_quota_create("external_account_credentials");
   grpc_http_response_destroy(&ctx_->response);
index 3c00096..9d0c175 100644 (file)
@@ -46,6 +46,7 @@ class ExternalAccountCredentials
     std::string quota_project_id;
     std::string client_id;
     std::string client_secret;
+    std::string workforce_pool_user_project;
   };
 
   static RefCountedPtr<ExternalAccountCredentials> Create(
index 1d95fe3..18710c5 100644 (file)
@@ -290,7 +290,7 @@ static grpc_error_handle create_default_creds_from_path(
   if (json.type() != Json::Type::OBJECT) {
     error = grpc_error_set_str(
         GRPC_ERROR_CREATE_FROM_STATIC_STRING("Failed to parse JSON"),
-        GRPC_ERROR_STR_RAW_BYTES, grpc_slice_ref_internal(creds_data));
+        GRPC_ERROR_STR_RAW_BYTES, grpc_core::StringViewFromSlice(creds_data));
     goto end;
   }
 
index 9f1e025..010ef78 100644 (file)
@@ -134,7 +134,7 @@ static void jose_header_destroy(jose_header* h) {
 static jose_header* jose_header_from_json(Json json) {
   const char* alg_value;
   Json::Object::const_iterator it;
-  jose_header* h = static_cast<jose_header*>(gpr_zalloc(sizeof(jose_header)));
+  jose_header* h = grpc_core::Zalloc<jose_header>();
   if (json.type() != Json::Type::OBJECT) {
     gpr_log(GPR_ERROR, "JSON value is not an object");
     goto error;
@@ -238,8 +238,7 @@ gpr_timespec grpc_jwt_claims_not_before(const grpc_jwt_claims* claims) {
 }
 
 grpc_jwt_claims* grpc_jwt_claims_from_json(Json json) {
-  grpc_jwt_claims* claims =
-      static_cast<grpc_jwt_claims*>(gpr_zalloc(sizeof(grpc_jwt_claims)));
+  grpc_jwt_claims* claims = grpc_core::Zalloc<grpc_jwt_claims>();
   claims->json.Init(std::move(json));
   claims->iat = gpr_inf_past(GPR_CLOCK_REALTIME);
   claims->nbf = gpr_inf_past(GPR_CLOCK_REALTIME);
@@ -356,8 +355,7 @@ static verifier_cb_ctx* verifier_cb_ctx_create(
     grpc_jwt_verification_done_cb cb) {
   grpc_core::ApplicationCallbackExecCtx callback_exec_ctx;
   grpc_core::ExecCtx exec_ctx;
-  verifier_cb_ctx* ctx =
-      static_cast<verifier_cb_ctx*>(gpr_zalloc(sizeof(verifier_cb_ctx)));
+  verifier_cb_ctx* ctx = new verifier_cb_ctx();
   ctx->verifier = verifier;
   ctx->pollent = grpc_polling_entity_create_from_pollset(pollset);
   ctx->header = header;
@@ -367,7 +365,6 @@ static verifier_cb_ctx* verifier_cb_ctx_create(
   ctx->signed_data = grpc_slice_from_copied_buffer(signed_jwt, signed_jwt_len);
   ctx->user_data = user_data;
   ctx->user_cb = cb;
-
   return ctx;
 }
 
@@ -381,7 +378,7 @@ void verifier_cb_ctx_destroy(verifier_cb_ctx* ctx) {
     grpc_http_response_destroy(&ctx->responses[i]);
   }
   /* TODO: see what to do with claims... */
-  gpr_free(ctx);
+  delete ctx;
 }
 
 /* --- grpc_jwt_verifier object. --- */
@@ -890,8 +887,7 @@ error:
 grpc_jwt_verifier* grpc_jwt_verifier_create(
     const grpc_jwt_verifier_email_domain_key_url_mapping* mappings,
     size_t num_mappings) {
-  grpc_jwt_verifier* v =
-      static_cast<grpc_jwt_verifier*>(gpr_zalloc(sizeof(grpc_jwt_verifier)));
+  grpc_jwt_verifier* v = grpc_core::Zalloc<grpc_jwt_verifier>();
   grpc_httpcli_context_init(&v->http_ctx);
 
   /* We know at least of one mapping. */
index 5b8fe1a..370ccb4 100644 (file)
@@ -29,6 +29,7 @@
 #include <grpc/support/log.h>
 #include <grpc/support/sync.h>
 
+#include "src/core/lib/gprpp/memory.h"
 #include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/slice/slice_string_helpers.h"
 #include "src/core/lib/surface/api_trace.h"
@@ -159,8 +160,7 @@ bool grpc_plugin_credentials::get_request_metadata(
   bool retval = true;  // Synchronous return.
   if (plugin_.get_metadata != nullptr) {
     // Create pending_request object.
-    pending_request* request =
-        static_cast<pending_request*>(gpr_zalloc(sizeof(*request)));
+    pending_request* request = grpc_core::Zalloc<pending_request>();
     request->creds = this;
     request->md_array = md_array;
     request->on_request_metadata = on_request_metadata;
index 3307d24..12e4d04 100644 (file)
@@ -92,12 +92,12 @@ class grpc_fake_channel_security_connector final
     c = strcmp(target_, other->target_);
     if (c != 0) return c;
     if (expected_targets_ == nullptr || other->expected_targets_ == nullptr) {
-      c = GPR_ICMP(expected_targets_, other->expected_targets_);
+      c = grpc_core::QsortCompare(expected_targets_, other->expected_targets_);
     } else {
       c = strcmp(expected_targets_, other->expected_targets_);
     }
     if (c != 0) return c;
-    return GPR_ICMP(is_lb_channel_, other->is_lb_channel_);
+    return grpc_core::QsortCompare(is_lb_channel_, other->is_lb_channel_);
   }
 
   void add_handshakers(const grpc_channel_args* args,
index 822fe15..67ce84a 100644 (file)
@@ -60,7 +60,9 @@ grpc_channel_security_connector::~grpc_channel_security_connector() {}
 
 int grpc_security_connector_cmp(const grpc_security_connector* sc,
                                 const grpc_security_connector* other) {
-  if (sc == nullptr || other == nullptr) return GPR_ICMP(sc, other);
+  if (sc == nullptr || other == nullptr) {
+    return grpc_core::QsortCompare(sc, other);
+  }
   return sc->cmp(other);
 }
 
@@ -70,9 +72,10 @@ int grpc_channel_security_connector::channel_security_connector_cmp(
       static_cast<const grpc_channel_security_connector*>(other);
   GPR_ASSERT(channel_creds() != nullptr);
   GPR_ASSERT(other_sc->channel_creds() != nullptr);
-  int c = GPR_ICMP(channel_creds(), other_sc->channel_creds());
+  int c = grpc_core::QsortCompare(channel_creds(), other_sc->channel_creds());
   if (c != 0) return c;
-  return GPR_ICMP(request_metadata_creds(), other_sc->request_metadata_creds());
+  return grpc_core::QsortCompare(request_metadata_creds(),
+                                 other_sc->request_metadata_creds());
 }
 
 int grpc_server_security_connector::server_security_connector_cmp(
@@ -81,15 +84,17 @@ int grpc_server_security_connector::server_security_connector_cmp(
       static_cast<const grpc_server_security_connector*>(other);
   GPR_ASSERT(server_creds() != nullptr);
   GPR_ASSERT(other_sc->server_creds() != nullptr);
-  return GPR_ICMP(server_creds(), other_sc->server_creds());
+  return grpc_core::QsortCompare(server_creds(), other_sc->server_creds());
 }
 
 static void connector_arg_destroy(void* p) {
+  if (p == nullptr) return;
   static_cast<grpc_security_connector*>(p)->Unref(DEBUG_LOCATION,
                                                   "connector_arg_destroy");
 }
 
 static void* connector_arg_copy(void* p) {
+  if (p == nullptr) return nullptr;
   return static_cast<grpc_security_connector*>(p)
       ->Ref(DEBUG_LOCATION, "connector_arg_copy")
       .release();
index 50d9af3..3cfe341 100644 (file)
@@ -42,7 +42,7 @@ typedef enum { GRPC_SECURITY_OK = 0, GRPC_SECURITY_ERROR } grpc_security_status;
     A security connector object represents away to configure the underlying
     transport security mechanism and check the resulting trusted peer.  */
 
-#define GRPC_ARG_SECURITY_CONNECTOR "grpc.security_connector"
+#define GRPC_ARG_SECURITY_CONNECTOR "grpc.internal.security_connector"
 
 class grpc_security_connector
     : public grpc_core::RefCounted<grpc_security_connector> {
index de22379..4fe689d 100644 (file)
@@ -523,7 +523,7 @@ static void grpc_ssl_session_cache_arg_destroy(void* p) {
 }
 
 static int grpc_ssl_session_cache_arg_cmp(void* p, void* q) {
-  return GPR_ICMP(p, q);
+  return grpc_core::QsortCompare(p, q);
 }
 
 grpc_arg grpc_ssl_session_cache_create_channel_arg(
index 7ee655d..760c610 100644 (file)
@@ -27,6 +27,7 @@
 #include "absl/strings/string_view.h"
 
 #include <grpc/grpc.h>
+#include <grpc/grpc_security_constants.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
index 80c2695..67ff420 100644 (file)
@@ -26,8 +26,6 @@
 #include "src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h"
 #include "src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h"
 
-#define GRPC_TLS_TRANSPORT_SECURITY_TYPE "tls"
-
 namespace grpc_core {
 
 // Channel security connector using TLS as transport security protocol.
index 4e940b1..fdf10e8 100644 (file)
@@ -372,13 +372,13 @@ static void client_auth_start_transport_stream_op_batch(
   if (batch->send_initial_metadata) {
     grpc_metadata_batch* metadata =
         batch->payload->send_initial_metadata.send_initial_metadata;
-    if (metadata->idx.named.path != nullptr) {
-      calld->method =
-          grpc_slice_ref_internal(GRPC_MDVALUE(metadata->idx.named.path->md));
+    if (metadata->legacy_index()->named.path != nullptr) {
+      calld->method = grpc_slice_ref_internal(
+          GRPC_MDVALUE(metadata->legacy_index()->named.path->md));
     }
-    if (metadata->idx.named.authority != nullptr) {
+    if (metadata->legacy_index()->named.authority != nullptr) {
       calld->host = grpc_slice_ref_internal(
-          GRPC_MDVALUE(metadata->idx.named.authority->md));
+          GRPC_MDVALUE(metadata->legacy_index()->named.authority->md));
       batch->handler_private.extra_arg = elem;
       GRPC_CALL_STACK_REF(calld->owning_call, "check_call_host");
       GRPC_CLOSURE_INIT(&calld->async_result_closure, on_host_checked, batch,
index d062e90..0f9114d 100644 (file)
@@ -116,13 +116,10 @@ SecurityHandshaker::SecurityHandshaker(tsi_handshaker* handshaker,
       connector_(connector->Ref(DEBUG_LOCATION, "handshake")),
       handshake_buffer_size_(GRPC_INITIAL_HANDSHAKE_BUFFER_SIZE),
       handshake_buffer_(
-          static_cast<uint8_t*>(gpr_malloc(handshake_buffer_size_))) {
-  const grpc_arg* arg =
-      grpc_channel_args_find(args, GRPC_ARG_TSI_MAX_FRAME_SIZE);
-  if (arg != nullptr && arg->type == GRPC_ARG_INTEGER) {
-    max_frame_size_ = grpc_channel_arg_get_integer(
-        arg, {0, 0, std::numeric_limits<int>::max()});
-  }
+          static_cast<uint8_t*>(gpr_malloc(handshake_buffer_size_))),
+      max_frame_size_(grpc_channel_args_find_integer(
+          args, GRPC_ARG_TSI_MAX_FRAME_SIZE,
+          {0, 0, std::numeric_limits<int>::max()})) {
   grpc_slice_buffer_init(&outgoing_);
   GRPC_CLOSURE_INIT(&on_peer_checked_, &SecurityHandshaker::OnPeerCheckedFn,
                     this, grpc_schedule_on_exec_ctx);
@@ -232,49 +229,83 @@ void SecurityHandshaker::OnPeerCheckedInner(grpc_error_handle error) {
     HandshakeFailedLocked(error);
     return;
   }
-  // Create zero-copy frame protector, if implemented.
-  tsi_zero_copy_grpc_protector* zero_copy_protector = nullptr;
-  tsi_result result = tsi_handshaker_result_create_zero_copy_grpc_protector(
-      handshaker_result_, max_frame_size_ == 0 ? nullptr : &max_frame_size_,
-      &zero_copy_protector);
-  if (result != TSI_OK && result != TSI_UNIMPLEMENTED) {
-    error = grpc_set_tsi_error_result(
+  // Get unused bytes.
+  const unsigned char* unused_bytes = nullptr;
+  size_t unused_bytes_size = 0;
+  tsi_result result = tsi_handshaker_result_get_unused_bytes(
+      handshaker_result_, &unused_bytes, &unused_bytes_size);
+  if (result != TSI_OK) {
+    HandshakeFailedLocked(grpc_set_tsi_error_result(
         GRPC_ERROR_CREATE_FROM_STATIC_STRING(
-            "Zero-copy frame protector creation failed"),
-        result);
-    HandshakeFailedLocked(error);
+            "TSI handshaker result does not provide unused bytes"),
+        result));
+    return;
+  }
+  // Check whether we need to wrap the endpoint.
+  tsi_frame_protector_type frame_protector_type;
+  result = tsi_handshaker_result_get_frame_protector_type(
+      handshaker_result_, &frame_protector_type);
+  if (result != TSI_OK) {
+    HandshakeFailedLocked(grpc_set_tsi_error_result(
+        GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+            "TSI handshaker result does not implement "
+            "get_frame_protector_type"),
+        result));
     return;
   }
-  // Create frame protector if zero-copy frame protector is NULL.
+  tsi_zero_copy_grpc_protector* zero_copy_protector = nullptr;
   tsi_frame_protector* protector = nullptr;
-  if (zero_copy_protector == nullptr) {
-    result = tsi_handshaker_result_create_frame_protector(
-        handshaker_result_, max_frame_size_ == 0 ? nullptr : &max_frame_size_,
-        &protector);
-    if (result != TSI_OK) {
-      error = grpc_set_tsi_error_result(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
-                                            "Frame protector creation failed"),
-                                        result);
-      HandshakeFailedLocked(error);
-      return;
-    }
+  switch (frame_protector_type) {
+    case TSI_FRAME_PROTECTOR_ZERO_COPY:
+      ABSL_FALLTHROUGH_INTENDED;
+    case TSI_FRAME_PROTECTOR_NORMAL_OR_ZERO_COPY:
+      // Create zero-copy frame protector.
+      result = tsi_handshaker_result_create_zero_copy_grpc_protector(
+          handshaker_result_, max_frame_size_ == 0 ? nullptr : &max_frame_size_,
+          &zero_copy_protector);
+      if (result != TSI_OK) {
+        HandshakeFailedLocked(grpc_set_tsi_error_result(
+            GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+                "Zero-copy frame protector creation failed"),
+            result));
+        return;
+      }
+      break;
+    case TSI_FRAME_PROTECTOR_NORMAL:
+      // Create normal frame protector.
+      result = tsi_handshaker_result_create_frame_protector(
+          handshaker_result_, max_frame_size_ == 0 ? nullptr : &max_frame_size_,
+          &protector);
+      if (result != TSI_OK) {
+        HandshakeFailedLocked(
+            grpc_set_tsi_error_result(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+                                          "Frame protector creation failed"),
+                                      result));
+        return;
+      }
+      break;
+    case TSI_FRAME_PROTECTOR_NONE:
+      break;
   }
-  // Get unused bytes.
-  const unsigned char* unused_bytes = nullptr;
-  size_t unused_bytes_size = 0;
-  result = tsi_handshaker_result_get_unused_bytes(
-      handshaker_result_, &unused_bytes, &unused_bytes_size);
-  // Create secure endpoint.
-  if (unused_bytes_size > 0) {
+  // If we have a frame protector, create a secure endpoint.
+  if (zero_copy_protector != nullptr || protector != nullptr) {
+    if (unused_bytes_size > 0) {
+      grpc_slice slice = grpc_slice_from_copied_buffer(
+          reinterpret_cast<const char*>(unused_bytes), unused_bytes_size);
+      args_->endpoint = grpc_secure_endpoint_create(
+          protector, zero_copy_protector, args_->endpoint, &slice, 1);
+      grpc_slice_unref_internal(slice);
+    } else {
+      args_->endpoint = grpc_secure_endpoint_create(
+          protector, zero_copy_protector, args_->endpoint, nullptr, 0);
+    }
+  } else if (unused_bytes_size > 0) {
+    // Not wrapping the endpoint, so just pass along unused bytes.
     grpc_slice slice = grpc_slice_from_copied_buffer(
         reinterpret_cast<const char*>(unused_bytes), unused_bytes_size);
-    args_->endpoint = grpc_secure_endpoint_create(
-        protector, zero_copy_protector, args_->endpoint, &slice, 1);
-    grpc_slice_unref_internal(slice);
-  } else {
-    args_->endpoint = grpc_secure_endpoint_create(
-        protector, zero_copy_protector, args_->endpoint, nullptr, 0);
+    grpc_slice_buffer_add(args_->read_buffer, slice);
   }
+  // Done with handshaker result.
   tsi_handshaker_result_destroy(handshaker_result_);
   handshaker_result_ = nullptr;
   // Add auth context to channel args.
@@ -430,7 +461,6 @@ void SecurityHandshaker::OnHandshakeDataReceivedFromPeerFn(
   size_t bytes_received_size = h->MoveReadBufferIntoHandshakeBuffer();
   // Call TSI handshaker.
   error = h->DoHandshakerNextLocked(h->handshake_buffer_, bytes_received_size);
-
   if (error != GRPC_ERROR_NONE) {
     h->HandshakeFailedLocked(error);
   } else {
index 4e9defd..feae3f7 100644 (file)
@@ -96,23 +96,21 @@ struct call_data {
 
 static grpc_metadata_array metadata_batch_to_md_array(
     const grpc_metadata_batch* batch) {
-  grpc_linked_mdelem* l;
   grpc_metadata_array result;
   grpc_metadata_array_init(&result);
-  for (l = batch->list.head; l != nullptr; l = l->next) {
+  batch->ForEach([&](grpc_mdelem md) {
     grpc_metadata* usr_md = nullptr;
-    grpc_mdelem md = l->md;
     grpc_slice key = GRPC_MDKEY(md);
     grpc_slice value = GRPC_MDVALUE(md);
     if (result.count == result.capacity) {
-      result.capacity = GPR_MAX(result.capacity + 8, result.capacity * 2);
+      result.capacity = std::max(result.capacity + 8, result.capacity * 2);
       result.metadata = static_cast<grpc_metadata*>(gpr_realloc(
           result.metadata, result.capacity * sizeof(grpc_metadata)));
     }
     usr_md = &result.metadata[result.count++];
     usr_md->key = grpc_slice_ref_internal(key);
     usr_md->value = grpc_slice_ref_internal(value);
-  }
+  });
   return result;
 }
 
index 4d337b4..23b1081 100644 (file)
@@ -22,9 +22,7 @@
 
 grpc_error_handle grpc_set_tsi_error_result(grpc_error_handle error,
                                             tsi_result result) {
-  return grpc_error_set_int(
-      grpc_error_set_str(
-          error, GRPC_ERROR_STR_TSI_ERROR,
-          grpc_slice_from_static_string(tsi_result_to_string(result))),
-      GRPC_ERROR_INT_TSI_CODE, result);
+  return grpc_error_set_int(grpc_error_set_str(error, GRPC_ERROR_STR_TSI_ERROR,
+                                               tsi_result_to_string(result)),
+                            GRPC_ERROR_INT_TSI_CODE, result);
 }
index ac33a31..8f15a06 100644 (file)
@@ -26,7 +26,6 @@
 
 #include "src/core/lib/gprpp/memory.h"
 #include "src/core/lib/gprpp/ref_counted.h"
-#include "src/core/lib/iomgr/exec_ctx.h"
 #include "src/core/lib/slice/slice_internal.h"
 
 char* grpc_slice_to_c_string(grpc_slice slice) {
@@ -45,21 +44,6 @@ grpc_slice grpc_slice_copy(grpc_slice s) {
   return out;
 }
 
-/* Public API */
-grpc_slice grpc_slice_ref(grpc_slice slice) {
-  return grpc_slice_ref_internal(slice);
-}
-
-/* Public API */
-void grpc_slice_unref(grpc_slice slice) {
-  if (grpc_core::ExecCtx::Get() == nullptr) {
-    grpc_core::ExecCtx exec_ctx;
-    grpc_slice_unref_internal(slice);
-  } else {
-    grpc_slice_unref_internal(slice);
-  }
-}
-
 namespace grpc_core {
 
 /* grpc_slice_from_static_string support structure - a refcount that does
diff --git a/src/core/lib/slice/slice_api.cc b/src/core/lib/slice/slice_api.cc
new file mode 100644 (file)
index 0000000..28827d2
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ *
+ * 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 <grpc/slice.h>
+
+#include "src/core/lib/iomgr/exec_ctx.h"
+#include "src/core/lib/slice/slice_internal.h"
+
+/* Public API */
+grpc_slice grpc_slice_ref(grpc_slice slice) {
+  return grpc_slice_ref_internal(slice);
+}
+
+/* Public API */
+void grpc_slice_unref(grpc_slice slice) {
+  if (grpc_core::ExecCtx::Get() == nullptr) {
+    grpc_core::ExecCtx exec_ctx;
+    grpc_slice_unref_internal(slice);
+  } else {
+    grpc_slice_unref_internal(slice);
+  }
+}
index b16d493..d461fe6 100644 (file)
@@ -231,19 +231,19 @@ void grpc_slice_buffer_swap(grpc_slice_buffer* a, grpc_slice_buffer* b) {
     memcpy(a->base_slices, b->inlined, b_count * sizeof(grpc_slice));
   } else {
     /* no inlining: easy swap */
-    GPR_SWAP(grpc_slice*, a->base_slices, b->base_slices);
+    std::swap(a->base_slices, b->base_slices);
   }
 
-  /* Update the slices pointers (cannot do a GPR_SWAP on slices fields here).
+  /* Update the slices pointers (cannot do a std::swap on slices fields here).
    * Also note that since the base_slices pointers are already swapped we need
    * use 'b_offset' for 'a->base_slices' and vice versa */
   a->slices = a->base_slices + b_offset;
   b->slices = b->base_slices + a_offset;
 
   /* base_slices and slices fields are correctly set. Swap all other fields */
-  GPR_SWAP(size_t, a->count, b->count);
-  GPR_SWAP(size_t, a->capacity, b->capacity);
-  GPR_SWAP(size_t, a->length, b->length);
+  std::swap(a->count, b->count);
+  std::swap(a->capacity, b->capacity);
+  std::swap(a->length, b->length);
 }
 
 void grpc_slice_buffer_move_into(grpc_slice_buffer* src,
index 305d99e..d374457 100644 (file)
@@ -136,12 +136,11 @@ grpc_slice grpc_slice_maybe_static_intern(grpc_slice slice,
   for (uint32_t i = 0; i <= max_static_metadata_hash_probe; i++) {
     static_metadata_hash_ent ent =
         static_metadata_hash[(hash + i) % GPR_ARRAY_SIZE(static_metadata_hash)];
-    const grpc_core::StaticMetadataSlice* static_slice_table =
-        grpc_static_slice_table();
     if (ent.hash == hash && ent.idx < GRPC_STATIC_MDSTR_COUNT &&
-        grpc_slice_eq_static_interned(slice, static_slice_table[ent.idx])) {
+        grpc_slice_eq_static_interned(
+            slice, grpc_core::g_static_metadata_slice_table[ent.idx])) {
       *returned_slice_is_different = true;
-      return static_slice_table[ent.idx];
+      return grpc_core::g_static_metadata_slice_table[ent.idx];
     }
   }
 
@@ -167,11 +166,9 @@ static const grpc_core::StaticMetadataSlice* MatchStaticSlice(
   for (uint32_t i = 0; i <= max_static_metadata_hash_probe; i++) {
     static_metadata_hash_ent ent =
         static_metadata_hash[(hash + i) % GPR_ARRAY_SIZE(static_metadata_hash)];
-    const grpc_core::StaticMetadataSlice* static_slice_table =
-        grpc_static_slice_table();
     if (ent.hash == hash && ent.idx < GRPC_STATIC_MDSTR_COUNT &&
-        static_slice_table[ent.idx] == args) {
-      return &static_slice_table[ent.idx];
+        grpc_core::g_static_metadata_slice_table[ent.idx] == args) {
+      return &grpc_core::g_static_metadata_slice_table[ent.idx];
     }
   }
   return nullptr;
@@ -323,11 +320,9 @@ void grpc_slice_intern_init(void) {
     static_metadata_hash[i].idx = GRPC_STATIC_MDSTR_COUNT;
   }
   max_static_metadata_hash_probe = 0;
-  const grpc_core::StaticMetadataSlice* static_slice_table =
-      grpc_static_slice_table();
   for (size_t i = 0; i < GRPC_STATIC_MDSTR_COUNT; i++) {
-    grpc_static_metadata_hash_values[i] =
-        grpc_slice_default_hash_internal(static_slice_table[i]);
+    grpc_static_metadata_hash_values[i] = grpc_slice_default_hash_internal(
+        grpc_core::g_static_metadata_slice_table[i]);
     for (size_t j = 0; j < GPR_ARRAY_SIZE(static_metadata_hash); j++) {
       size_t slot = (grpc_static_metadata_hash_values[i] + j) %
                     GPR_ARRAY_SIZE(static_metadata_hash);
@@ -343,7 +338,7 @@ void grpc_slice_intern_init(void) {
   }
   // Handle KV hash for all static mdelems.
   for (size_t i = 0; i < GRPC_STATIC_MDELEM_COUNT; ++i) {
-    grpc_static_mdelem_table()[i].HashInit();
+    grpc_core::g_static_mdelem_table[i].HashInit();
   }
 }
 
index 1e90ac5..b1a6047 100644 (file)
 #include "src/core/lib/gpr/murmur_hash.h"
 #include "src/core/lib/gprpp/memory.h"
 #include "src/core/lib/gprpp/ref_counted.h"
+#include "src/core/lib/slice/slice_refcount.h"
 #include "src/core/lib/slice/slice_utils.h"
-#include "src/core/lib/transport/static_metadata.h"
-
-// Interned slices have specific fast-path operations for hashing. To inline
-// these operations, we need to forward declare them here.
-extern uint32_t grpc_static_metadata_hash_values[GRPC_STATIC_MDSTR_COUNT];
-
-// grpc_slice_refcount : A reference count for grpc_slice.
-//
-// Non-inlined grpc_slice objects are refcounted. Historically this was
-// implemented via grpc_slice_refcount, a C-style polymorphic class using a
-// manually managed vtable of operations. Subclasses would define their own
-// vtable; the 'virtual' methods (ref, unref, equals and hash) would simply call
-// the function pointers in the vtable as necessary.
-//
-// Unfortunately, this leads to some inefficiencies in the generated code that
-// can be improved upon. For example, equality checking for interned slices is a
-// simple equality check on the refcount pointer. With the vtable approach, this
-// would translate to roughly the following (high-level) instructions:
-//
-// grpc_slice_equals(slice1, slice2):
-//   load vtable->eq -> eq_func
-//   call eq_func(slice1, slice2)
-//
-// interned_slice_equals(slice1, slice2)
-//   load slice1.ref -> r1
-//   load slice2.ref -> r2
-//   cmp r1, r2 -> retval
-//   ret retval
-//
-// This leads to a function call for a function defined in another translation
-// unit, which imposes memory barriers, which reduces the compiler's ability to
-// optimize (in addition to the added overhead of call/ret). Additionally, it
-// may be harder to reason about branch prediction when we're jumping to
-// essentially arbitrarily provided function pointers.
-//
-// In addition, it is arguable that while virtualization was helpful for
-// Equals()/Hash() methods, that it was fundamentally unnecessary for
-// Ref()/Unref().
-//
-// Instead, grpc_slice_refcount provides the same functionality as the C-style
-// virtual class, but in a de-virtualized manner - Eq(), Hash(), Ref() and
-// Unref() are provided within this header file. Fastpaths for Eq()/Hash()
-// (interned and static metadata slices), as well as the Ref() operation, can
-// all be inlined without any memory barriers.
-//
-// It does this by:
-// 1. Using grpc_core::RefCount<> (header-only) for Ref/Unref. Two special cases
-//    need support: No-op ref/unref (eg. static metadata slices) and stream
-//    slice references (where all the slices share the streamref). This is in
-//    addition to the normal case of '1 slice, 1 ref'.
-//    To support these cases, we explicitly track a nullable pointer to the
-//    underlying RefCount<>. No-op ref/unref is used by checking the pointer for
-//    null, and doing nothing if it is. Both stream slice refs and 'normal'
-//    slices use the same path for Ref/Unref (by targeting the non-null
-//    pointer).
-//
-// 2. introducing the notion of grpc_slice_refcount::Type. This describes if a
-//    slice ref is used by a static metadata slice, an interned slice, or other
-//    slices. We switch on the slice ref type in order to provide fastpaths for
-//    Equals() and Hash().
-//
-// In total, this saves us roughly 1-2% latency for unary calls, with smaller
-// calls benefitting. The effect is present, but not as useful, for larger calls
-// where the cost of sending the data dominates.
-// TODO(arjunroy): Investigate if this can be removed with strongly typed
-// grpc_slices.
-struct grpc_slice_refcount {
- public:
-  enum class Type {
-    STATIC,    // Refcount for a static metadata slice.
-    INTERNED,  // Refcount for an interned slice.
-    NOP,       // No-Op
-    REGULAR    // Refcount for non-static-metadata, non-interned slices.
-  };
-  typedef void (*DestroyerFn)(void*);
-
-  grpc_slice_refcount() = default;
-
-  explicit grpc_slice_refcount(Type t) : ref_type_(t) {}
-
-  explicit grpc_slice_refcount(grpc_slice_refcount* sub) : sub_refcount_(sub) {}
-  // Regular constructor for grpc_slice_refcount.
-  //
-  // Parameters:
-  //  1. grpc_slice_refcount::Type type
-  //  Whether we are the refcount for a static
-  //  metadata slice, an interned slice, or any other kind of slice.
-  //
-  //  2. RefCount* ref
-  //  The pointer to the actual underlying grpc_core::RefCount. Rather than
-  //  performing struct offset computations as in the original implementation to
-  //  get to the refcount, which requires a virtual method, we devirtualize by
-  //  using a nullable pointer to allow a single pair of Ref/Unref methods.
-  //
-  //  3. DestroyerFn destroyer_fn
-  //  Called when the refcount goes to 0, with destroyer_arg as parameter.
-  //
-  //  4. void* destroyer_arg
-  //  Argument for the virtualized destructor.
-  //
-  //  5. grpc_slice_refcount* sub
-  //  Argument used for interned slices.
-  grpc_slice_refcount(grpc_slice_refcount::Type type, grpc_core::RefCount* ref,
-                      DestroyerFn destroyer_fn, void* destroyer_arg,
-                      grpc_slice_refcount* sub)
-      : ref_(ref),
-        ref_type_(type),
-        sub_refcount_(sub),
-        dest_fn_(destroyer_fn),
-        destroy_fn_arg_(destroyer_arg) {}
-  // Initializer for static refcounts.
-  grpc_slice_refcount(grpc_slice_refcount* sub, Type type)
-      : ref_type_(type), sub_refcount_(sub) {}
-
-  Type GetType() const { return ref_type_; }
-
-  int Eq(const grpc_slice& a, const grpc_slice& b);
-
-  uint32_t Hash(const grpc_slice& slice);
-  void Ref() {
-    if (ref_ == nullptr) return;
-    ref_->RefNonZero();
-  }
-  void Unref() {
-    if (ref_ == nullptr) return;
-    if (ref_->Unref()) {
-      dest_fn_(destroy_fn_arg_);
-    }
-  }
-
-  grpc_slice_refcount* sub_refcount() const { return sub_refcount_; }
-
- private:
-  grpc_core::RefCount* ref_ = nullptr;
-  const Type ref_type_ = Type::REGULAR;
-  grpc_slice_refcount* sub_refcount_ = this;
-  DestroyerFn dest_fn_ = nullptr;
-  void* destroy_fn_arg_ = nullptr;
-};
-
-namespace grpc_core {
-
-struct StaticSliceRefcount {
-  static grpc_slice_refcount kStaticSubRefcount;
-
-  explicit StaticSliceRefcount(uint32_t index)
-      : base(&kStaticSubRefcount, grpc_slice_refcount::Type::STATIC),
-        index(index) {}
-
-  grpc_slice_refcount base;
-  const uint32_t index;
-};
-
-extern grpc_slice_refcount kNoopRefcount;
-
-struct InternedSliceRefcount {
-  static void Destroy(void* arg) {
-    auto* rc = static_cast<InternedSliceRefcount*>(arg);
-    rc->~InternedSliceRefcount();
-    gpr_free(rc);
-  }
-
-  InternedSliceRefcount(size_t length, uint32_t hash,
-                        InternedSliceRefcount* bucket_next)
-      : base(grpc_slice_refcount::Type::INTERNED, &refcnt, Destroy, this, &sub),
-        sub(grpc_slice_refcount::Type::REGULAR, &refcnt, Destroy, this, &sub),
-        length(length),
-        hash(hash),
-        bucket_next(bucket_next) {}
-
-  ~InternedSliceRefcount();
-
-  grpc_slice_refcount base;
-  grpc_slice_refcount sub;
-  const size_t length;
-  RefCount refcnt;
-  const uint32_t hash;
-  InternedSliceRefcount* bucket_next;
-};
-
-}  // namespace grpc_core
-
-inline size_t grpc_refcounted_slice_length(const grpc_slice& slice) {
-  GPR_DEBUG_ASSERT(slice.refcount != nullptr);
-  return slice.data.refcounted.length;
-}
-
-inline const uint8_t* grpc_refcounted_slice_data(const grpc_slice& slice) {
-  GPR_DEBUG_ASSERT(slice.refcount != nullptr);
-  return slice.data.refcounted.bytes;
-}
-
-inline int grpc_slice_refcount::Eq(const grpc_slice& a, const grpc_slice& b) {
-  GPR_DEBUG_ASSERT(a.refcount != nullptr);
-  GPR_DEBUG_ASSERT(a.refcount == this);
-  switch (ref_type_) {
-    case Type::STATIC:
-      GPR_DEBUG_ASSERT(
-          (GRPC_STATIC_METADATA_INDEX(a) == GRPC_STATIC_METADATA_INDEX(b)) ==
-          (a.refcount == b.refcount));
-      ABSL_FALLTHROUGH_INTENDED;
-    case Type::INTERNED:
-      return a.refcount == b.refcount;
-    case Type::NOP:
-    case Type::REGULAR:
-      break;
-  }
-  if (grpc_refcounted_slice_length(a) != GRPC_SLICE_LENGTH(b)) return false;
-  if (grpc_refcounted_slice_length(a) == 0) return true;
-  return 0 == memcmp(grpc_refcounted_slice_data(a), GRPC_SLICE_START_PTR(b),
-                     grpc_refcounted_slice_length(a));
-}
-
-inline uint32_t grpc_slice_refcount::Hash(const grpc_slice& slice) {
-  GPR_DEBUG_ASSERT(slice.refcount != nullptr);
-  GPR_DEBUG_ASSERT(slice.refcount == this);
-  switch (ref_type_) {
-    case Type::STATIC:
-      return ::grpc_static_metadata_hash_values[GRPC_STATIC_METADATA_INDEX(
-          slice)];
-    case Type::INTERNED:
-      return reinterpret_cast<grpc_core::InternedSliceRefcount*>(slice.refcount)
-          ->hash;
-    case Type::NOP:
-    case Type::REGULAR:
-      break;
-  }
-  return gpr_murmur_hash3(grpc_refcounted_slice_data(slice),
-                          grpc_refcounted_slice_length(slice),
-                          grpc_core::g_hash_seed);
-}
-
-inline const grpc_slice& grpc_slice_ref_internal(const grpc_slice& slice) {
-  if (slice.refcount) {
-    slice.refcount->Ref();
-  }
-  return slice;
-}
-
-inline void grpc_slice_unref_internal(const grpc_slice& slice) {
-  if (slice.refcount) {
-    slice.refcount->Unref();
-  }
-}
 
 void grpc_slice_buffer_reset_and_unref_internal(grpc_slice_buffer* sb);
 void grpc_slice_buffer_partial_unref_internal(grpc_slice_buffer* sb,
diff --git a/src/core/lib/slice/slice_refcount.cc b/src/core/lib/slice/slice_refcount.cc
new file mode 100644 (file)
index 0000000..10de62b
--- /dev/null
@@ -0,0 +1,17 @@
+// 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 <grpc/support/port_platform.h>
+
+#include "src/core/lib/slice/slice_refcount.h"
diff --git a/src/core/lib/slice/slice_refcount.h b/src/core/lib/slice/slice_refcount.h
new file mode 100644 (file)
index 0000000..1a98f19
--- /dev/null
@@ -0,0 +1,121 @@
+// 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.
+
+#ifndef GRPC_CORE_LIB_SLICE_SLICE_REFCOUNT_H
+#define GRPC_CORE_LIB_SLICE_SLICE_REFCOUNT_H
+
+#include <grpc/support/port_platform.h>
+
+#include "src/core/lib/slice/slice_refcount_base.h"
+#include "src/core/lib/slice/static_slice.h"
+
+// Interned slices have specific fast-path operations for hashing. To inline
+// these operations, we need to forward declare them here.
+extern uint32_t grpc_static_metadata_hash_values[GRPC_STATIC_MDSTR_COUNT];
+
+namespace grpc_core {
+
+extern grpc_slice_refcount kNoopRefcount;
+
+struct InternedSliceRefcount {
+  static void Destroy(void* arg) {
+    auto* rc = static_cast<InternedSliceRefcount*>(arg);
+    rc->~InternedSliceRefcount();
+    gpr_free(rc);
+  }
+
+  InternedSliceRefcount(size_t length, uint32_t hash,
+                        InternedSliceRefcount* bucket_next)
+      : base(grpc_slice_refcount::Type::INTERNED, &refcnt, Destroy, this, &sub),
+        sub(grpc_slice_refcount::Type::REGULAR, &refcnt, Destroy, this, &sub),
+        length(length),
+        hash(hash),
+        bucket_next(bucket_next) {}
+
+  ~InternedSliceRefcount();
+
+  grpc_slice_refcount base;
+  grpc_slice_refcount sub;
+  const size_t length;
+  RefCount refcnt;
+  const uint32_t hash;
+  InternedSliceRefcount* bucket_next;
+};
+
+}  // namespace grpc_core
+
+inline size_t grpc_refcounted_slice_length(const grpc_slice& slice) {
+  GPR_DEBUG_ASSERT(slice.refcount != nullptr);
+  return slice.data.refcounted.length;
+}
+
+inline const uint8_t* grpc_refcounted_slice_data(const grpc_slice& slice) {
+  GPR_DEBUG_ASSERT(slice.refcount != nullptr);
+  return slice.data.refcounted.bytes;
+}
+
+inline int grpc_slice_refcount::Eq(const grpc_slice& a, const grpc_slice& b) {
+  GPR_DEBUG_ASSERT(a.refcount != nullptr);
+  GPR_DEBUG_ASSERT(a.refcount == this);
+  switch (ref_type_) {
+    case Type::STATIC:
+      GPR_DEBUG_ASSERT(
+          (GRPC_STATIC_METADATA_INDEX(a) == GRPC_STATIC_METADATA_INDEX(b)) ==
+          (a.refcount == b.refcount));
+      ABSL_FALLTHROUGH_INTENDED;
+    case Type::INTERNED:
+      return a.refcount == b.refcount;
+    case Type::NOP:
+    case Type::REGULAR:
+      break;
+  }
+  if (grpc_refcounted_slice_length(a) != GRPC_SLICE_LENGTH(b)) return false;
+  if (grpc_refcounted_slice_length(a) == 0) return true;
+  return 0 == memcmp(grpc_refcounted_slice_data(a), GRPC_SLICE_START_PTR(b),
+                     grpc_refcounted_slice_length(a));
+}
+
+inline uint32_t grpc_slice_refcount::Hash(const grpc_slice& slice) {
+  GPR_DEBUG_ASSERT(slice.refcount != nullptr);
+  GPR_DEBUG_ASSERT(slice.refcount == this);
+  switch (ref_type_) {
+    case Type::STATIC:
+      return ::grpc_static_metadata_hash_values[GRPC_STATIC_METADATA_INDEX(
+          slice)];
+    case Type::INTERNED:
+      return reinterpret_cast<grpc_core::InternedSliceRefcount*>(slice.refcount)
+          ->hash;
+    case Type::NOP:
+    case Type::REGULAR:
+      break;
+  }
+  return gpr_murmur_hash3(grpc_refcounted_slice_data(slice),
+                          grpc_refcounted_slice_length(slice),
+                          grpc_core::g_hash_seed);
+}
+
+inline const grpc_slice& grpc_slice_ref_internal(const grpc_slice& slice) {
+  if (slice.refcount) {
+    slice.refcount->Ref();
+  }
+  return slice;
+}
+
+inline void grpc_slice_unref_internal(const grpc_slice& slice) {
+  if (slice.refcount) {
+    slice.refcount->Unref();
+  }
+}
+
+#endif /* GRPC_CORE_LIB_SLICE_SLICE_REFCOUNT_H */
diff --git a/src/core/lib/slice/slice_refcount_base.h b/src/core/lib/slice/slice_refcount_base.h
new file mode 100644 (file)
index 0000000..62ad152
--- /dev/null
@@ -0,0 +1,173 @@
+// 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.
+
+#ifndef GRPC_CORE_LIB_SLICE_SLICE_REFCOUNT_BASE_H
+#define GRPC_CORE_LIB_SLICE_SLICE_REFCOUNT_BASE_H
+
+#include <grpc/support/port_platform.h>
+
+#include <grpc/slice.h>
+
+#include "src/core/lib/gprpp/ref_counted.h"
+
+// grpc_slice_refcount : A reference count for grpc_slice.
+//
+// Non-inlined grpc_slice objects are refcounted. Historically this was
+// implemented via grpc_slice_refcount, a C-style polymorphic class using a
+// manually managed vtable of operations. Subclasses would define their own
+// vtable; the 'virtual' methods (ref, unref, equals and hash) would simply call
+// the function pointers in the vtable as necessary.
+//
+// Unfortunately, this leads to some inefficiencies in the generated code that
+// can be improved upon. For example, equality checking for interned slices is a
+// simple equality check on the refcount pointer. With the vtable approach, this
+// would translate to roughly the following (high-level) instructions:
+//
+// grpc_slice_equals(slice1, slice2):
+//   load vtable->eq -> eq_func
+//   call eq_func(slice1, slice2)
+//
+// interned_slice_equals(slice1, slice2)
+//   load slice1.ref -> r1
+//   load slice2.ref -> r2
+//   cmp r1, r2 -> retval
+//   ret retval
+//
+// This leads to a function call for a function defined in another translation
+// unit, which imposes memory barriers, which reduces the compiler's ability to
+// optimize (in addition to the added overhead of call/ret). Additionally, it
+// may be harder to reason about branch prediction when we're jumping to
+// essentially arbitrarily provided function pointers.
+//
+// In addition, it is arguable that while virtualization was helpful for
+// Equals()/Hash() methods, that it was fundamentally unnecessary for
+// Ref()/Unref().
+//
+// Instead, grpc_slice_refcount provides the same functionality as the C-style
+// virtual class, but in a de-virtualized manner - Eq(), Hash(), Ref() and
+// Unref() are provided within this header file. Fastpaths for Eq()/Hash()
+// (interned and static metadata slices), as well as the Ref() operation, can
+// all be inlined without any memory barriers.
+//
+// It does this by:
+// 1. Using grpc_core::RefCount<> (header-only) for Ref/Unref. Two special cases
+//    need support: No-op ref/unref (eg. static metadata slices) and stream
+//    slice references (where all the slices share the streamref). This is in
+//    addition to the normal case of '1 slice, 1 ref'.
+//    To support these cases, we explicitly track a nullable pointer to the
+//    underlying RefCount<>. No-op ref/unref is used by checking the pointer for
+//    null, and doing nothing if it is. Both stream slice refs and 'normal'
+//    slices use the same path for Ref/Unref (by targeting the non-null
+//    pointer).
+//
+// 2. introducing the notion of grpc_slice_refcount::Type. This describes if a
+//    slice ref is used by a static metadata slice, an interned slice, or other
+//    slices. We switch on the slice ref type in order to provide fastpaths for
+//    Equals() and Hash().
+//
+// In total, this saves us roughly 1-2% latency for unary calls, with smaller
+// calls benefitting. The effect is present, but not as useful, for larger calls
+// where the cost of sending the data dominates.
+// TODO(arjunroy): Investigate if this can be removed with strongly typed
+// grpc_slices.
+struct grpc_slice_refcount {
+ public:
+  enum class Type {
+    STATIC,    // Refcount for a static metadata slice.
+    INTERNED,  // Refcount for an interned slice.
+    NOP,       // No-Op
+    REGULAR    // Refcount for non-static-metadata, non-interned slices.
+  };
+  typedef void (*DestroyerFn)(void*);
+
+  grpc_slice_refcount() = default;
+
+  explicit grpc_slice_refcount(Type t) : ref_type_(t) {}
+
+  explicit grpc_slice_refcount(grpc_slice_refcount* sub) : sub_refcount_(sub) {}
+  // Regular constructor for grpc_slice_refcount.
+  //
+  // Parameters:
+  //  1. grpc_slice_refcount::Type type
+  //  Whether we are the refcount for a static
+  //  metadata slice, an interned slice, or any other kind of slice.
+  //
+  //  2. RefCount* ref
+  //  The pointer to the actual underlying grpc_core::RefCount. Rather than
+  //  performing struct offset computations as in the original implementation to
+  //  get to the refcount, which requires a virtual method, we devirtualize by
+  //  using a nullable pointer to allow a single pair of Ref/Unref methods.
+  //
+  //  3. DestroyerFn destroyer_fn
+  //  Called when the refcount goes to 0, with destroyer_arg as parameter.
+  //
+  //  4. void* destroyer_arg
+  //  Argument for the virtualized destructor.
+  //
+  //  5. grpc_slice_refcount* sub
+  //  Argument used for interned slices.
+  grpc_slice_refcount(grpc_slice_refcount::Type type, grpc_core::RefCount* ref,
+                      DestroyerFn destroyer_fn, void* destroyer_arg,
+                      grpc_slice_refcount* sub)
+      : ref_(ref),
+        ref_type_(type),
+        sub_refcount_(sub),
+        dest_fn_(destroyer_fn),
+        destroy_fn_arg_(destroyer_arg) {}
+  // Initializer for static refcounts.
+  grpc_slice_refcount(grpc_slice_refcount* sub, Type type)
+      : ref_type_(type), sub_refcount_(sub) {}
+
+  Type GetType() const { return ref_type_; }
+
+  int Eq(const grpc_slice& a, const grpc_slice& b);
+
+  uint32_t Hash(const grpc_slice& slice);
+  void Ref() {
+    if (ref_ == nullptr) return;
+    ref_->RefNonZero();
+  }
+  void Unref() {
+    if (ref_ == nullptr) return;
+    if (ref_->Unref()) {
+      dest_fn_(destroy_fn_arg_);
+    }
+  }
+
+  grpc_slice_refcount* sub_refcount() const { return sub_refcount_; }
+
+ private:
+  grpc_core::RefCount* ref_ = nullptr;
+  const Type ref_type_ = Type::REGULAR;
+  grpc_slice_refcount* sub_refcount_ = this;
+  DestroyerFn dest_fn_ = nullptr;
+  void* destroy_fn_arg_ = nullptr;
+};
+
+namespace grpc_core {
+
+struct StaticSliceRefcount {
+  static grpc_slice_refcount kStaticSubRefcount;
+
+  explicit StaticSliceRefcount(uint32_t index)
+      : base(&kStaticSubRefcount, grpc_slice_refcount::Type::STATIC),
+        index(index) {}
+
+  grpc_slice_refcount base;
+  const uint32_t index;
+};
+
+}  // namespace grpc_core
+
+#endif  // GRPC_CORE_LIB_SLICE_SLICE_REFCOUNT_BASE_H
diff --git a/src/core/lib/slice/slice_split.cc b/src/core/lib/slice/slice_split.cc
new file mode 100644 (file)
index 0000000..d2a951c
--- /dev/null
@@ -0,0 +1,100 @@
+// 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 <grpc/support/port_platform.h>
+
+#include "src/core/lib/slice/slice_split.h"
+
+#include <string.h>
+
+#include <grpc/support/log.h>
+
+/** Finds the initial (\a begin) and final (\a end) offsets of the next
+ * substring from \a str + \a read_offset until the next \a sep or the end of \a
+ * str.
+ *
+ * Returns 1 and updates \a begin and \a end. Returns 0 otherwise. */
+static int slice_find_separator_offset(const grpc_slice str, const char* sep,
+                                       const size_t read_offset, size_t* begin,
+                                       size_t* end) {
+  size_t i;
+  const uint8_t* str_ptr = GRPC_SLICE_START_PTR(str) + read_offset;
+  const size_t str_len = GRPC_SLICE_LENGTH(str) - read_offset;
+  const size_t sep_len = strlen(sep);
+  if (str_len < sep_len) {
+    return 0;
+  }
+
+  for (i = 0; i <= str_len - sep_len; i++) {
+    if (memcmp(str_ptr + i, sep, sep_len) == 0) {
+      *begin = read_offset;
+      *end = read_offset + i;
+      return 1;
+    }
+  }
+  return 0;
+}
+
+static void skip_leading_trailing_spaces(const uint8_t* str_buffer,
+                                         size_t* begin, size_t* end) {
+  while (*begin < *end && str_buffer[*begin] == ' ') {
+    (*begin)++;
+  }
+  while (*begin < *end && str_buffer[*end - 1] == ' ') {
+    (*end)--;
+  }
+}
+
+static void grpc_slice_split_inner(grpc_slice str, const char* sep,
+                                   grpc_slice_buffer* dst, bool no_space) {
+  const size_t sep_len = strlen(sep);
+  size_t begin, end;
+  const uint8_t* str_buffer = GRPC_SLICE_START_PTR(str);
+  size_t sep_pos;
+
+  GPR_ASSERT(sep_len > 0);
+
+  if (slice_find_separator_offset(str, sep, 0, &begin, &end) != 0) {
+    do {
+      sep_pos = end;
+      if (no_space) {
+        skip_leading_trailing_spaces(str_buffer, &begin, &end);
+      }
+      grpc_slice_buffer_add_indexed(dst, grpc_slice_sub(str, begin, end));
+    } while (slice_find_separator_offset(str, sep, sep_pos + sep_len, &begin,
+                                         &end) != 0);
+    begin = sep_pos + sep_len;
+    end = GRPC_SLICE_LENGTH(str);
+    if (no_space) {
+      skip_leading_trailing_spaces(str_buffer, &begin, &end);
+    }
+    grpc_slice_buffer_add_indexed(dst, grpc_slice_sub(str, begin, end));
+  } else { /* no sep found, add whole input */
+    begin = 0;
+    end = GRPC_SLICE_LENGTH(str);
+    if (no_space) {
+      skip_leading_trailing_spaces(str_buffer, &begin, &end);
+    }
+    grpc_slice_buffer_add_indexed(dst, grpc_slice_sub(str, begin, end));
+  }
+}
+
+void grpc_slice_split(grpc_slice str, const char* sep, grpc_slice_buffer* dst) {
+  grpc_slice_split_inner(str, sep, dst, false);
+}
+
+void grpc_slice_split_without_space(grpc_slice str, const char* sep,
+                                    grpc_slice_buffer* dst) {
+  grpc_slice_split_inner(str, sep, dst, true);
+}
diff --git a/src/core/lib/slice/slice_split.h b/src/core/lib/slice/slice_split.h
new file mode 100644 (file)
index 0000000..835b16a
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#ifndef GRPC_CORE_LIB_SLICE_SLICE_SPLIT_H
+#define GRPC_CORE_LIB_SLICE_SLICE_SPLIT_H
+
+#include <grpc/support/port_platform.h>
+
+#include <stdbool.h>
+#include <stddef.h>
+
+#include <grpc/slice.h>
+#include <grpc/slice_buffer.h>
+
+/** Split \a str by the separator \a sep. Results are stored in \a dst, which
+ * should be a properly initialized instance. */
+void grpc_slice_split(grpc_slice str, const char* sep, grpc_slice_buffer* dst);
+
+/** Split \a str by the separator \a sep and remove the leading and trailing
+ * spaces of each resulting token. Results are stored in \a dst, which should be
+ * a properly initialized instance. */
+void grpc_slice_split_without_space(grpc_slice str, const char* sep,
+                                    grpc_slice_buffer* dst);
+
+#endif /* GRPC_CORE_LIB_SLICE_SLICE_SPLIT_H */
index 7887e03..35744d0 100644 (file)
 
 #include "src/core/lib/slice/slice_string_helpers.h"
 
-#include <string.h>
-
-#include <grpc/support/log.h>
-
 #include "src/core/lib/gpr/string.h"
 #include "src/core/lib/gprpp/memory.h"
 #include "src/core/lib/slice/slice_internal.h"
@@ -41,85 +37,6 @@ grpc_slice grpc_dump_slice_to_slice(const grpc_slice& s, uint32_t flags) {
   return grpc_slice_from_moved_buffer(std::move(ptr), len);
 }
 
-/** Finds the initial (\a begin) and final (\a end) offsets of the next
- * substring from \a str + \a read_offset until the next \a sep or the end of \a
- * str.
- *
- * Returns 1 and updates \a begin and \a end. Returns 0 otherwise. */
-static int slice_find_separator_offset(const grpc_slice str, const char* sep,
-                                       const size_t read_offset, size_t* begin,
-                                       size_t* end) {
-  size_t i;
-  const uint8_t* str_ptr = GRPC_SLICE_START_PTR(str) + read_offset;
-  const size_t str_len = GRPC_SLICE_LENGTH(str) - read_offset;
-  const size_t sep_len = strlen(sep);
-  if (str_len < sep_len) {
-    return 0;
-  }
-
-  for (i = 0; i <= str_len - sep_len; i++) {
-    if (memcmp(str_ptr + i, sep, sep_len) == 0) {
-      *begin = read_offset;
-      *end = read_offset + i;
-      return 1;
-    }
-  }
-  return 0;
-}
-
-static void skip_leading_trailing_spaces(const uint8_t* str_buffer,
-                                         size_t* begin, size_t* end) {
-  while (*begin < *end && str_buffer[*begin] == ' ') {
-    (*begin)++;
-  }
-  while (*begin < *end && str_buffer[*end - 1] == ' ') {
-    (*end)--;
-  }
-}
-
-static void grpc_slice_split_inner(grpc_slice str, const char* sep,
-                                   grpc_slice_buffer* dst, bool no_space) {
-  const size_t sep_len = strlen(sep);
-  size_t begin, end;
-  const uint8_t* str_buffer = GRPC_SLICE_START_PTR(str);
-  size_t sep_pos;
-
-  GPR_ASSERT(sep_len > 0);
-
-  if (slice_find_separator_offset(str, sep, 0, &begin, &end) != 0) {
-    do {
-      sep_pos = end;
-      if (no_space) {
-        skip_leading_trailing_spaces(str_buffer, &begin, &end);
-      }
-      grpc_slice_buffer_add_indexed(dst, grpc_slice_sub(str, begin, end));
-    } while (slice_find_separator_offset(str, sep, sep_pos + sep_len, &begin,
-                                         &end) != 0);
-    begin = sep_pos + sep_len;
-    end = GRPC_SLICE_LENGTH(str);
-    if (no_space) {
-      skip_leading_trailing_spaces(str_buffer, &begin, &end);
-    }
-    grpc_slice_buffer_add_indexed(dst, grpc_slice_sub(str, begin, end));
-  } else { /* no sep found, add whole input */
-    begin = 0;
-    end = GRPC_SLICE_LENGTH(str);
-    if (no_space) {
-      skip_leading_trailing_spaces(str_buffer, &begin, &end);
-    }
-    grpc_slice_buffer_add_indexed(dst, grpc_slice_sub(str, begin, end));
-  }
-}
-
-void grpc_slice_split(grpc_slice str, const char* sep, grpc_slice_buffer* dst) {
-  grpc_slice_split_inner(str, sep, dst, false);
-}
-
-void grpc_slice_split_without_space(grpc_slice str, const char* sep,
-                                    grpc_slice_buffer* dst) {
-  grpc_slice_split_inner(str, sep, dst, true);
-}
-
 bool grpc_parse_slice_to_uint32(grpc_slice str, uint32_t* result) {
   return gpr_parse_bytes_to_uint32(
              reinterpret_cast<const char*> GRPC_SLICE_START_PTR(str),
index 6551a6d..df9cadd 100644 (file)
@@ -25,7 +25,6 @@
 #include <stddef.h>
 
 #include <grpc/slice.h>
-#include <grpc/slice_buffer.h>
 
 #include "src/core/lib/gpr/string.h"
 
@@ -34,16 +33,6 @@ char* grpc_dump_slice(const grpc_slice& slice, uint32_t flags);
 /* Calls gpr_dump on a slice and returns the result as a slice. */
 grpc_slice grpc_dump_slice_to_slice(const grpc_slice& slice, uint32_t flags);
 
-/** Split \a str by the separator \a sep. Results are stored in \a dst, which
- * should be a properly initialized instance. */
-void grpc_slice_split(grpc_slice str, const char* sep, grpc_slice_buffer* dst);
-
-/** Split \a str by the separator \a sep and remove the leading and trailing
- * spaces of each resulting token. Results are stored in \a dst, which should be
- * a properly initialized instance. */
-void grpc_slice_split_without_space(grpc_slice str, const char* sep,
-                                    grpc_slice_buffer* dst);
-
 bool grpc_parse_slice_to_uint32(grpc_slice str, uint32_t* result);
 
 #endif /* GRPC_CORE_LIB_SLICE_SLICE_STRING_HELPERS_H */
diff --git a/src/core/lib/slice/static_slice.cc b/src/core/lib/slice/static_slice.cc
new file mode 100644 (file)
index 0000000..40681b1
--- /dev/null
@@ -0,0 +1,529 @@
+/*
+ * 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.
+ */
+
+/*
+ * WARNING: Auto-generated code.
+ *
+ * To make changes to this file, change
+ * tools/codegen/core/gen_static_metadata.py, and then re-run it.
+ *
+ * See metadata.h for an explanation of the interface here, and metadata.cc for
+ * an explanation of what's going on.
+ */
+
+#include <grpc/support/port_platform.h>
+
+#include "src/core/lib/slice/static_slice.h"
+
+namespace grpc_core {
+const uint8_t g_static_metadata_bytes[] = {
+    58,  112, 97,  116, 104, 58,  109, 101, 116, 104, 111, 100, 58,  115, 116,
+    97,  116, 117, 115, 58,  97,  117, 116, 104, 111, 114, 105, 116, 121, 58,
+    115, 99,  104, 101, 109, 101, 103, 114, 112, 99,  45,  109, 101, 115, 115,
+    97,  103, 101, 103, 114, 112, 99,  45,  115, 116, 97,  116, 117, 115, 103,
+    114, 112, 99,  45,  112, 97,  121, 108, 111, 97,  100, 45,  98,  105, 110,
+    103, 114, 112, 99,  45,  101, 110, 99,  111, 100, 105, 110, 103, 103, 114,
+    112, 99,  45,  97,  99,  99,  101, 112, 116, 45,  101, 110, 99,  111, 100,
+    105, 110, 103, 103, 114, 112, 99,  45,  115, 101, 114, 118, 101, 114, 45,
+    115, 116, 97,  116, 115, 45,  98,  105, 110, 103, 114, 112, 99,  45,  116,
+    97,  103, 115, 45,  98,  105, 110, 103, 114, 112, 99,  45,  116, 114, 97,
+    99,  101, 45,  98,  105, 110, 99,  111, 110, 116, 101, 110, 116, 45,  116,
+    121, 112, 101, 99,  111, 110, 116, 101, 110, 116, 45,  101, 110, 99,  111,
+    100, 105, 110, 103, 97,  99,  99,  101, 112, 116, 45,  101, 110, 99,  111,
+    100, 105, 110, 103, 103, 114, 112, 99,  45,  105, 110, 116, 101, 114, 110,
+    97,  108, 45,  101, 110, 99,  111, 100, 105, 110, 103, 45,  114, 101, 113,
+    117, 101, 115, 116, 103, 114, 112, 99,  45,  105, 110, 116, 101, 114, 110,
+    97,  108, 45,  115, 116, 114, 101, 97,  109, 45,  101, 110, 99,  111, 100,
+    105, 110, 103, 45,  114, 101, 113, 117, 101, 115, 116, 117, 115, 101, 114,
+    45,  97,  103, 101, 110, 116, 104, 111, 115, 116, 103, 114, 112, 99,  45,
+    112, 114, 101, 118, 105, 111, 117, 115, 45,  114, 112, 99,  45,  97,  116,
+    116, 101, 109, 112, 116, 115, 103, 114, 112, 99,  45,  114, 101, 116, 114,
+    121, 45,  112, 117, 115, 104, 98,  97,  99,  107, 45,  109, 115, 120, 45,
+    101, 110, 100, 112, 111, 105, 110, 116, 45,  108, 111, 97,  100, 45,  109,
+    101, 116, 114, 105, 99,  115, 45,  98,  105, 110, 103, 114, 112, 99,  45,
+    116, 105, 109, 101, 111, 117, 116, 49,  50,  51,  52,  103, 114, 112, 99,
+    46,  119, 97,  105, 116, 95,  102, 111, 114, 95,  114, 101, 97,  100, 121,
+    103, 114, 112, 99,  46,  116, 105, 109, 101, 111, 117, 116, 103, 114, 112,
+    99,  46,  109, 97,  120, 95,  114, 101, 113, 117, 101, 115, 116, 95,  109,
+    101, 115, 115, 97,  103, 101, 95,  98,  121, 116, 101, 115, 103, 114, 112,
+    99,  46,  109, 97,  120, 95,  114, 101, 115, 112, 111, 110, 115, 101, 95,
+    109, 101, 115, 115, 97,  103, 101, 95,  98,  121, 116, 101, 115, 47,  103,
+    114, 112, 99,  46,  108, 98,  46,  118, 49,  46,  76,  111, 97,  100, 66,
+    97,  108, 97,  110, 99,  101, 114, 47,  66,  97,  108, 97,  110, 99,  101,
+    76,  111, 97,  100, 47,  101, 110, 118, 111, 121, 46,  115, 101, 114, 118,
+    105, 99,  101, 46,  108, 111, 97,  100, 95,  115, 116, 97,  116, 115, 46,
+    118, 50,  46,  76,  111, 97,  100, 82,  101, 112, 111, 114, 116, 105, 110,
+    103, 83,  101, 114, 118, 105, 99,  101, 47,  83,  116, 114, 101, 97,  109,
+    76,  111, 97,  100, 83,  116, 97,  116, 115, 47,  101, 110, 118, 111, 121,
+    46,  115, 101, 114, 118, 105, 99,  101, 46,  108, 111, 97,  100, 95,  115,
+    116, 97,  116, 115, 46,  118, 51,  46,  76,  111, 97,  100, 82,  101, 112,
+    111, 114, 116, 105, 110, 103, 83,  101, 114, 118, 105, 99,  101, 47,  83,
+    116, 114, 101, 97,  109, 76,  111, 97,  100, 83,  116, 97,  116, 115, 47,
+    103, 114, 112, 99,  46,  104, 101, 97,  108, 116, 104, 46,  118, 49,  46,
+    72,  101, 97,  108, 116, 104, 47,  87,  97,  116, 99,  104, 47,  101, 110,
+    118, 111, 121, 46,  115, 101, 114, 118, 105, 99,  101, 46,  100, 105, 115,
+    99,  111, 118, 101, 114, 121, 46,  118, 50,  46,  65,  103, 103, 114, 101,
+    103, 97,  116, 101, 100, 68,  105, 115, 99,  111, 118, 101, 114, 121, 83,
+    101, 114, 118, 105, 99,  101, 47,  83,  116, 114, 101, 97,  109, 65,  103,
+    103, 114, 101, 103, 97,  116, 101, 100, 82,  101, 115, 111, 117, 114, 99,
+    101, 115, 47,  101, 110, 118, 111, 121, 46,  115, 101, 114, 118, 105, 99,
+    101, 46,  100, 105, 115, 99,  111, 118, 101, 114, 121, 46,  118, 51,  46,
+    65,  103, 103, 114, 101, 103, 97,  116, 101, 100, 68,  105, 115, 99,  111,
+    118, 101, 114, 121, 83,  101, 114, 118, 105, 99,  101, 47,  83,  116, 114,
+    101, 97,  109, 65,  103, 103, 114, 101, 103, 97,  116, 101, 100, 82,  101,
+    115, 111, 117, 114, 99,  101, 115, 100, 101, 102, 108, 97,  116, 101, 103,
+    122, 105, 112, 115, 116, 114, 101, 97,  109, 47,  103, 122, 105, 112, 116,
+    101, 116, 114, 97,  105, 108, 101, 114, 115, 71,  69,  84,  80,  79,  83,
+    84,  47,  47,  105, 110, 100, 101, 120, 46,  104, 116, 109, 108, 104, 116,
+    116, 112, 104, 116, 116, 112, 115, 50,  48,  48,  50,  48,  52,  50,  48,
+    54,  51,  48,  52,  52,  48,  48,  52,  48,  52,  53,  48,  48,  97,  99,
+    99,  101, 112, 116, 45,  99,  104, 97,  114, 115, 101, 116, 103, 122, 105,
+    112, 44,  32,  100, 101, 102, 108, 97,  116, 101, 97,  99,  99,  101, 112,
+    116, 45,  108, 97,  110, 103, 117, 97,  103, 101, 97,  99,  99,  101, 112,
+    116, 45,  114, 97,  110, 103, 101, 115, 97,  99,  99,  101, 112, 116, 97,
+    99,  99,  101, 115, 115, 45,  99,  111, 110, 116, 114, 111, 108, 45,  97,
+    108, 108, 111, 119, 45,  111, 114, 105, 103, 105, 110, 97,  103, 101, 97,
+    108, 108, 111, 119, 97,  117, 116, 104, 111, 114, 105, 122, 97,  116, 105,
+    111, 110, 99,  97,  99,  104, 101, 45,  99,  111, 110, 116, 114, 111, 108,
+    99,  111, 110, 116, 101, 110, 116, 45,  100, 105, 115, 112, 111, 115, 105,
+    116, 105, 111, 110, 99,  111, 110, 116, 101, 110, 116, 45,  108, 97,  110,
+    103, 117, 97,  103, 101, 99,  111, 110, 116, 101, 110, 116, 45,  108, 101,
+    110, 103, 116, 104, 99,  111, 110, 116, 101, 110, 116, 45,  108, 111, 99,
+    97,  116, 105, 111, 110, 99,  111, 110, 116, 101, 110, 116, 45,  114, 97,
+    110, 103, 101, 99,  111, 111, 107, 105, 101, 100, 97,  116, 101, 101, 116,
+    97,  103, 101, 120, 112, 101, 99,  116, 101, 120, 112, 105, 114, 101, 115,
+    102, 114, 111, 109, 105, 102, 45,  109, 97,  116, 99,  104, 105, 102, 45,
+    109, 111, 100, 105, 102, 105, 101, 100, 45,  115, 105, 110, 99,  101, 105,
+    102, 45,  110, 111, 110, 101, 45,  109, 97,  116, 99,  104, 105, 102, 45,
+    114, 97,  110, 103, 101, 105, 102, 45,  117, 110, 109, 111, 100, 105, 102,
+    105, 101, 100, 45,  115, 105, 110, 99,  101, 108, 97,  115, 116, 45,  109,
+    111, 100, 105, 102, 105, 101, 100, 108, 105, 110, 107, 108, 111, 99,  97,
+    116, 105, 111, 110, 109, 97,  120, 45,  102, 111, 114, 119, 97,  114, 100,
+    115, 112, 114, 111, 120, 121, 45,  97,  117, 116, 104, 101, 110, 116, 105,
+    99,  97,  116, 101, 112, 114, 111, 120, 121, 45,  97,  117, 116, 104, 111,
+    114, 105, 122, 97,  116, 105, 111, 110, 114, 97,  110, 103, 101, 114, 101,
+    102, 101, 114, 101, 114, 114, 101, 102, 114, 101, 115, 104, 114, 101, 116,
+    114, 121, 45,  97,  102, 116, 101, 114, 115, 101, 114, 118, 101, 114, 115,
+    101, 116, 45,  99,  111, 111, 107, 105, 101, 115, 116, 114, 105, 99,  116,
+    45,  116, 114, 97,  110, 115, 112, 111, 114, 116, 45,  115, 101, 99,  117,
+    114, 105, 116, 121, 116, 114, 97,  110, 115, 102, 101, 114, 45,  101, 110,
+    99,  111, 100, 105, 110, 103, 118, 97,  114, 121, 118, 105, 97,  119, 119,
+    119, 45,  97,  117, 116, 104, 101, 110, 116, 105, 99,  97,  116, 101, 48,
+    105, 100, 101, 110, 116, 105, 116, 121, 97,  112, 112, 108, 105, 99,  97,
+    116, 105, 111, 110, 47,  103, 114, 112, 99,  103, 114, 112, 99,  80,  85,
+    84,  108, 98,  45,  99,  111, 115, 116, 45,  98,  105, 110, 105, 100, 101,
+    110, 116, 105, 116, 121, 44,  100, 101, 102, 108, 97,  116, 101, 105, 100,
+    101, 110, 116, 105, 116, 121, 44,  103, 122, 105, 112, 100, 101, 102, 108,
+    97,  116, 101, 44,  103, 122, 105, 112, 105, 100, 101, 110, 116, 105, 116,
+    121, 44,  100, 101, 102, 108, 97,  116, 101, 44,  103, 122, 105, 112};
+
+grpc_slice_refcount grpc_core::StaticSliceRefcount::kStaticSubRefcount;
+
+StaticSliceRefcount g_static_metadata_slice_refcounts[GRPC_STATIC_MDSTR_COUNT] =
+    {
+
+        StaticSliceRefcount(0),   StaticSliceRefcount(1),
+        StaticSliceRefcount(2),   StaticSliceRefcount(3),
+        StaticSliceRefcount(4),   StaticSliceRefcount(5),
+        StaticSliceRefcount(6),   StaticSliceRefcount(7),
+        StaticSliceRefcount(8),   StaticSliceRefcount(9),
+        StaticSliceRefcount(10),  StaticSliceRefcount(11),
+        StaticSliceRefcount(12),  StaticSliceRefcount(13),
+        StaticSliceRefcount(14),  StaticSliceRefcount(15),
+        StaticSliceRefcount(16),  StaticSliceRefcount(17),
+        StaticSliceRefcount(18),  StaticSliceRefcount(19),
+        StaticSliceRefcount(20),  StaticSliceRefcount(21),
+        StaticSliceRefcount(22),  StaticSliceRefcount(23),
+        StaticSliceRefcount(24),  StaticSliceRefcount(25),
+        StaticSliceRefcount(26),  StaticSliceRefcount(27),
+        StaticSliceRefcount(28),  StaticSliceRefcount(29),
+        StaticSliceRefcount(30),  StaticSliceRefcount(31),
+        StaticSliceRefcount(32),  StaticSliceRefcount(33),
+        StaticSliceRefcount(34),  StaticSliceRefcount(35),
+        StaticSliceRefcount(36),  StaticSliceRefcount(37),
+        StaticSliceRefcount(38),  StaticSliceRefcount(39),
+        StaticSliceRefcount(40),  StaticSliceRefcount(41),
+        StaticSliceRefcount(42),  StaticSliceRefcount(43),
+        StaticSliceRefcount(44),  StaticSliceRefcount(45),
+        StaticSliceRefcount(46),  StaticSliceRefcount(47),
+        StaticSliceRefcount(48),  StaticSliceRefcount(49),
+        StaticSliceRefcount(50),  StaticSliceRefcount(51),
+        StaticSliceRefcount(52),  StaticSliceRefcount(53),
+        StaticSliceRefcount(54),  StaticSliceRefcount(55),
+        StaticSliceRefcount(56),  StaticSliceRefcount(57),
+        StaticSliceRefcount(58),  StaticSliceRefcount(59),
+        StaticSliceRefcount(60),  StaticSliceRefcount(61),
+        StaticSliceRefcount(62),  StaticSliceRefcount(63),
+        StaticSliceRefcount(64),  StaticSliceRefcount(65),
+        StaticSliceRefcount(66),  StaticSliceRefcount(67),
+        StaticSliceRefcount(68),  StaticSliceRefcount(69),
+        StaticSliceRefcount(70),  StaticSliceRefcount(71),
+        StaticSliceRefcount(72),  StaticSliceRefcount(73),
+        StaticSliceRefcount(74),  StaticSliceRefcount(75),
+        StaticSliceRefcount(76),  StaticSliceRefcount(77),
+        StaticSliceRefcount(78),  StaticSliceRefcount(79),
+        StaticSliceRefcount(80),  StaticSliceRefcount(81),
+        StaticSliceRefcount(82),  StaticSliceRefcount(83),
+        StaticSliceRefcount(84),  StaticSliceRefcount(85),
+        StaticSliceRefcount(86),  StaticSliceRefcount(87),
+        StaticSliceRefcount(88),  StaticSliceRefcount(89),
+        StaticSliceRefcount(90),  StaticSliceRefcount(91),
+        StaticSliceRefcount(92),  StaticSliceRefcount(93),
+        StaticSliceRefcount(94),  StaticSliceRefcount(95),
+        StaticSliceRefcount(96),  StaticSliceRefcount(97),
+        StaticSliceRefcount(98),  StaticSliceRefcount(99),
+        StaticSliceRefcount(100), StaticSliceRefcount(101),
+        StaticSliceRefcount(102), StaticSliceRefcount(103),
+        StaticSliceRefcount(104), StaticSliceRefcount(105),
+        StaticSliceRefcount(106), StaticSliceRefcount(107),
+        StaticSliceRefcount(108), StaticSliceRefcount(109),
+};
+
+const StaticMetadataSlice
+    g_static_metadata_slice_table[GRPC_STATIC_MDSTR_COUNT] = {
+
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[0].base, 5,
+            g_static_metadata_bytes + 0),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[1].base, 7,
+            g_static_metadata_bytes + 5),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[2].base, 7,
+            g_static_metadata_bytes + 12),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[3].base, 10,
+            g_static_metadata_bytes + 19),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[4].base, 7,
+            g_static_metadata_bytes + 29),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[5].base, 12,
+            g_static_metadata_bytes + 36),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[6].base, 11,
+            g_static_metadata_bytes + 48),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[7].base, 16,
+            g_static_metadata_bytes + 59),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[8].base, 13,
+            g_static_metadata_bytes + 75),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[9].base, 20,
+            g_static_metadata_bytes + 88),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[10].base, 21,
+            g_static_metadata_bytes + 108),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[11].base, 13,
+            g_static_metadata_bytes + 129),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[12].base, 14,
+            g_static_metadata_bytes + 142),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[13].base, 12,
+            g_static_metadata_bytes + 156),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[14].base, 16,
+            g_static_metadata_bytes + 168),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[15].base, 15,
+            g_static_metadata_bytes + 184),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[16].base, 30,
+            g_static_metadata_bytes + 199),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[17].base, 37,
+            g_static_metadata_bytes + 229),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[18].base, 10,
+            g_static_metadata_bytes + 266),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[19].base, 4,
+            g_static_metadata_bytes + 276),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[20].base, 26,
+            g_static_metadata_bytes + 280),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[21].base, 22,
+            g_static_metadata_bytes + 306),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[22].base, 27,
+            g_static_metadata_bytes + 328),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[23].base, 12,
+            g_static_metadata_bytes + 355),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[24].base, 1,
+            g_static_metadata_bytes + 367),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[25].base, 1,
+            g_static_metadata_bytes + 368),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[26].base, 1,
+            g_static_metadata_bytes + 369),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[27].base, 1,
+            g_static_metadata_bytes + 370),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[28].base, 0,
+            g_static_metadata_bytes + 371),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[29].base, 19,
+            g_static_metadata_bytes + 371),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[30].base, 12,
+            g_static_metadata_bytes + 390),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[31].base, 30,
+            g_static_metadata_bytes + 402),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[32].base, 31,
+            g_static_metadata_bytes + 432),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[33].base, 36,
+            g_static_metadata_bytes + 463),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[34].base, 65,
+            g_static_metadata_bytes + 499),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[35].base, 65,
+            g_static_metadata_bytes + 564),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[36].base, 28,
+            g_static_metadata_bytes + 629),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[37].base, 80,
+            g_static_metadata_bytes + 657),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[38].base, 80,
+            g_static_metadata_bytes + 737),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[39].base, 7,
+            g_static_metadata_bytes + 817),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[40].base, 4,
+            g_static_metadata_bytes + 824),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[41].base, 11,
+            g_static_metadata_bytes + 828),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[42].base, 2,
+            g_static_metadata_bytes + 839),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[43].base, 8,
+            g_static_metadata_bytes + 841),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[44].base, 3,
+            g_static_metadata_bytes + 849),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[45].base, 4,
+            g_static_metadata_bytes + 852),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[46].base, 1,
+            g_static_metadata_bytes + 856),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[47].base, 11,
+            g_static_metadata_bytes + 857),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[48].base, 4,
+            g_static_metadata_bytes + 868),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[49].base, 5,
+            g_static_metadata_bytes + 872),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[50].base, 3,
+            g_static_metadata_bytes + 877),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[51].base, 3,
+            g_static_metadata_bytes + 880),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[52].base, 3,
+            g_static_metadata_bytes + 883),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[53].base, 3,
+            g_static_metadata_bytes + 886),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[54].base, 3,
+            g_static_metadata_bytes + 889),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[55].base, 3,
+            g_static_metadata_bytes + 892),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[56].base, 3,
+            g_static_metadata_bytes + 895),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[57].base, 14,
+            g_static_metadata_bytes + 898),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[58].base, 13,
+            g_static_metadata_bytes + 912),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[59].base, 15,
+            g_static_metadata_bytes + 925),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[60].base, 13,
+            g_static_metadata_bytes + 940),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[61].base, 6,
+            g_static_metadata_bytes + 953),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[62].base, 27,
+            g_static_metadata_bytes + 959),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[63].base, 3,
+            g_static_metadata_bytes + 986),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[64].base, 5,
+            g_static_metadata_bytes + 989),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[65].base, 13,
+            g_static_metadata_bytes + 994),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[66].base, 13,
+            g_static_metadata_bytes + 1007),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[67].base, 19,
+            g_static_metadata_bytes + 1020),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[68].base, 16,
+            g_static_metadata_bytes + 1039),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[69].base, 14,
+            g_static_metadata_bytes + 1055),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[70].base, 16,
+            g_static_metadata_bytes + 1069),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[71].base, 13,
+            g_static_metadata_bytes + 1085),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[72].base, 6,
+            g_static_metadata_bytes + 1098),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[73].base, 4,
+            g_static_metadata_bytes + 1104),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[74].base, 4,
+            g_static_metadata_bytes + 1108),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[75].base, 6,
+            g_static_metadata_bytes + 1112),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[76].base, 7,
+            g_static_metadata_bytes + 1118),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[77].base, 4,
+            g_static_metadata_bytes + 1125),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[78].base, 8,
+            g_static_metadata_bytes + 1129),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[79].base, 17,
+            g_static_metadata_bytes + 1137),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[80].base, 13,
+            g_static_metadata_bytes + 1154),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[81].base, 8,
+            g_static_metadata_bytes + 1167),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[82].base, 19,
+            g_static_metadata_bytes + 1175),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[83].base, 13,
+            g_static_metadata_bytes + 1194),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[84].base, 4,
+            g_static_metadata_bytes + 1207),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[85].base, 8,
+            g_static_metadata_bytes + 1211),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[86].base, 12,
+            g_static_metadata_bytes + 1219),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[87].base, 18,
+            g_static_metadata_bytes + 1231),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[88].base, 19,
+            g_static_metadata_bytes + 1249),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[89].base, 5,
+            g_static_metadata_bytes + 1268),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[90].base, 7,
+            g_static_metadata_bytes + 1273),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[91].base, 7,
+            g_static_metadata_bytes + 1280),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[92].base, 11,
+            g_static_metadata_bytes + 1287),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[93].base, 6,
+            g_static_metadata_bytes + 1298),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[94].base, 10,
+            g_static_metadata_bytes + 1304),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[95].base, 25,
+            g_static_metadata_bytes + 1314),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[96].base, 17,
+            g_static_metadata_bytes + 1339),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[97].base, 4,
+            g_static_metadata_bytes + 1356),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[98].base, 3,
+            g_static_metadata_bytes + 1360),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[99].base, 16,
+            g_static_metadata_bytes + 1363),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[100].base, 1,
+            g_static_metadata_bytes + 1379),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[101].base, 8,
+            g_static_metadata_bytes + 1380),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[102].base, 16,
+            g_static_metadata_bytes + 1388),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[103].base, 4,
+            g_static_metadata_bytes + 1404),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[104].base, 3,
+            g_static_metadata_bytes + 1408),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[105].base, 11,
+            g_static_metadata_bytes + 1411),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[106].base, 16,
+            g_static_metadata_bytes + 1422),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[107].base, 13,
+            g_static_metadata_bytes + 1438),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[108].base, 12,
+            g_static_metadata_bytes + 1451),
+        grpc_core::StaticMetadataSlice(
+            &g_static_metadata_slice_refcounts[109].base, 21,
+            g_static_metadata_bytes + 1463),
+};
+}  // namespace grpc_core
diff --git a/src/core/lib/slice/static_slice.h b/src/core/lib/slice/static_slice.h
new file mode 100644 (file)
index 0000000..893b2ef
--- /dev/null
@@ -0,0 +1,331 @@
+/*
+ * 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.
+ */
+
+/*
+ * WARNING: Auto-generated code.
+ *
+ * To make changes to this file, change
+ * tools/codegen/core/gen_static_metadata.py, and then re-run it.
+ *
+ * See metadata.h for an explanation of the interface here, and metadata.cc for
+ * an explanation of what's going on.
+ */
+
+#ifndef GRPC_CORE_LIB_SLICE_STATIC_SLICE_H
+#define GRPC_CORE_LIB_SLICE_STATIC_SLICE_H
+
+#include <grpc/support/port_platform.h>
+
+#include <cstdint>
+#include <type_traits>
+
+#include "src/core/lib/slice/slice_refcount_base.h"
+#include "src/core/lib/slice/slice_utils.h"
+
+static_assert(
+    std::is_trivially_destructible<grpc_core::StaticMetadataSlice>::value,
+    "grpc_core::StaticMetadataSlice must be trivially destructible.");
+#define GRPC_STATIC_MDSTR_COUNT 110
+/* ":path" */
+#define GRPC_MDSTR_PATH (::grpc_core::g_static_metadata_slice_table[0])
+/* ":method" */
+#define GRPC_MDSTR_METHOD (::grpc_core::g_static_metadata_slice_table[1])
+/* ":status" */
+#define GRPC_MDSTR_STATUS (::grpc_core::g_static_metadata_slice_table[2])
+/* ":authority" */
+#define GRPC_MDSTR_AUTHORITY (::grpc_core::g_static_metadata_slice_table[3])
+/* ":scheme" */
+#define GRPC_MDSTR_SCHEME (::grpc_core::g_static_metadata_slice_table[4])
+/* "grpc-message" */
+#define GRPC_MDSTR_GRPC_MESSAGE (::grpc_core::g_static_metadata_slice_table[5])
+/* "grpc-status" */
+#define GRPC_MDSTR_GRPC_STATUS (::grpc_core::g_static_metadata_slice_table[6])
+/* "grpc-payload-bin" */
+#define GRPC_MDSTR_GRPC_PAYLOAD_BIN \
+  (::grpc_core::g_static_metadata_slice_table[7])
+/* "grpc-encoding" */
+#define GRPC_MDSTR_GRPC_ENCODING (::grpc_core::g_static_metadata_slice_table[8])
+/* "grpc-accept-encoding" */
+#define GRPC_MDSTR_GRPC_ACCEPT_ENCODING \
+  (::grpc_core::g_static_metadata_slice_table[9])
+/* "grpc-server-stats-bin" */
+#define GRPC_MDSTR_GRPC_SERVER_STATS_BIN \
+  (::grpc_core::g_static_metadata_slice_table[10])
+/* "grpc-tags-bin" */
+#define GRPC_MDSTR_GRPC_TAGS_BIN \
+  (::grpc_core::g_static_metadata_slice_table[11])
+/* "grpc-trace-bin" */
+#define GRPC_MDSTR_GRPC_TRACE_BIN \
+  (::grpc_core::g_static_metadata_slice_table[12])
+/* "content-type" */
+#define GRPC_MDSTR_CONTENT_TYPE (::grpc_core::g_static_metadata_slice_table[13])
+/* "content-encoding" */
+#define GRPC_MDSTR_CONTENT_ENCODING \
+  (::grpc_core::g_static_metadata_slice_table[14])
+/* "accept-encoding" */
+#define GRPC_MDSTR_ACCEPT_ENCODING \
+  (::grpc_core::g_static_metadata_slice_table[15])
+/* "grpc-internal-encoding-request" */
+#define GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST \
+  (::grpc_core::g_static_metadata_slice_table[16])
+/* "grpc-internal-stream-encoding-request" */
+#define GRPC_MDSTR_GRPC_INTERNAL_STREAM_ENCODING_REQUEST \
+  (::grpc_core::g_static_metadata_slice_table[17])
+/* "user-agent" */
+#define GRPC_MDSTR_USER_AGENT (::grpc_core::g_static_metadata_slice_table[18])
+/* "host" */
+#define GRPC_MDSTR_HOST (::grpc_core::g_static_metadata_slice_table[19])
+/* "grpc-previous-rpc-attempts" */
+#define GRPC_MDSTR_GRPC_PREVIOUS_RPC_ATTEMPTS \
+  (::grpc_core::g_static_metadata_slice_table[20])
+/* "grpc-retry-pushback-ms" */
+#define GRPC_MDSTR_GRPC_RETRY_PUSHBACK_MS \
+  (::grpc_core::g_static_metadata_slice_table[21])
+/* "x-endpoint-load-metrics-bin" */
+#define GRPC_MDSTR_X_ENDPOINT_LOAD_METRICS_BIN \
+  (::grpc_core::g_static_metadata_slice_table[22])
+/* "grpc-timeout" */
+#define GRPC_MDSTR_GRPC_TIMEOUT (::grpc_core::g_static_metadata_slice_table[23])
+/* "1" */
+#define GRPC_MDSTR_1 (::grpc_core::g_static_metadata_slice_table[24])
+/* "2" */
+#define GRPC_MDSTR_2 (::grpc_core::g_static_metadata_slice_table[25])
+/* "3" */
+#define GRPC_MDSTR_3 (::grpc_core::g_static_metadata_slice_table[26])
+/* "4" */
+#define GRPC_MDSTR_4 (::grpc_core::g_static_metadata_slice_table[27])
+/* "" */
+#define GRPC_MDSTR_EMPTY (::grpc_core::g_static_metadata_slice_table[28])
+/* "grpc.wait_for_ready" */
+#define GRPC_MDSTR_GRPC_DOT_WAIT_FOR_READY \
+  (::grpc_core::g_static_metadata_slice_table[29])
+/* "grpc.timeout" */
+#define GRPC_MDSTR_GRPC_DOT_TIMEOUT \
+  (::grpc_core::g_static_metadata_slice_table[30])
+/* "grpc.max_request_message_bytes" */
+#define GRPC_MDSTR_GRPC_DOT_MAX_REQUEST_MESSAGE_BYTES \
+  (::grpc_core::g_static_metadata_slice_table[31])
+/* "grpc.max_response_message_bytes" */
+#define GRPC_MDSTR_GRPC_DOT_MAX_RESPONSE_MESSAGE_BYTES \
+  (::grpc_core::g_static_metadata_slice_table[32])
+/* "/grpc.lb.v1.LoadBalancer/BalanceLoad" */
+#define GRPC_MDSTR_SLASH_GRPC_DOT_LB_DOT_V1_DOT_LOADBALANCER_SLASH_BALANCELOAD \
+  (::grpc_core::g_static_metadata_slice_table[33])
+/* "/envoy.service.load_stats.v2.LoadReportingService/StreamLoadStats" */
+#define GRPC_MDSTR_SLASH_ENVOY_DOT_SERVICE_DOT_LOAD_STATS_DOT_V2_DOT_LOADREPORTINGSERVICE_SLASH_STREAMLOADSTATS \
+  (::grpc_core::g_static_metadata_slice_table[34])
+/* "/envoy.service.load_stats.v3.LoadReportingService/StreamLoadStats" */
+#define GRPC_MDSTR_SLASH_ENVOY_DOT_SERVICE_DOT_LOAD_STATS_DOT_V3_DOT_LOADREPORTINGSERVICE_SLASH_STREAMLOADSTATS \
+  (::grpc_core::g_static_metadata_slice_table[35])
+/* "/grpc.health.v1.Health/Watch" */
+#define GRPC_MDSTR_SLASH_GRPC_DOT_HEALTH_DOT_V1_DOT_HEALTH_SLASH_WATCH \
+  (::grpc_core::g_static_metadata_slice_table[36])
+/* "/envoy.service.discovery.v2.AggregatedDiscoveryService/StreamAggregatedResources"
+ */
+#define GRPC_MDSTR_SLASH_ENVOY_DOT_SERVICE_DOT_DISCOVERY_DOT_V2_DOT_AGGREGATEDDISCOVERYSERVICE_SLASH_STREAMAGGREGATEDRESOURCES \
+  (::grpc_core::g_static_metadata_slice_table[37])
+/* "/envoy.service.discovery.v3.AggregatedDiscoveryService/StreamAggregatedResources"
+ */
+#define GRPC_MDSTR_SLASH_ENVOY_DOT_SERVICE_DOT_DISCOVERY_DOT_V3_DOT_AGGREGATEDDISCOVERYSERVICE_SLASH_STREAMAGGREGATEDRESOURCES \
+  (::grpc_core::g_static_metadata_slice_table[38])
+/* "deflate" */
+#define GRPC_MDSTR_DEFLATE (::grpc_core::g_static_metadata_slice_table[39])
+/* "gzip" */
+#define GRPC_MDSTR_GZIP (::grpc_core::g_static_metadata_slice_table[40])
+/* "stream/gzip" */
+#define GRPC_MDSTR_STREAM_SLASH_GZIP \
+  (::grpc_core::g_static_metadata_slice_table[41])
+/* "te" */
+#define GRPC_MDSTR_TE (::grpc_core::g_static_metadata_slice_table[42])
+/* "trailers" */
+#define GRPC_MDSTR_TRAILERS (::grpc_core::g_static_metadata_slice_table[43])
+/* "GET" */
+#define GRPC_MDSTR_GET (::grpc_core::g_static_metadata_slice_table[44])
+/* "POST" */
+#define GRPC_MDSTR_POST (::grpc_core::g_static_metadata_slice_table[45])
+/* "/" */
+#define GRPC_MDSTR_SLASH (::grpc_core::g_static_metadata_slice_table[46])
+/* "/index.html" */
+#define GRPC_MDSTR_SLASH_INDEX_DOT_HTML \
+  (::grpc_core::g_static_metadata_slice_table[47])
+/* "http" */
+#define GRPC_MDSTR_HTTP (::grpc_core::g_static_metadata_slice_table[48])
+/* "https" */
+#define GRPC_MDSTR_HTTPS (::grpc_core::g_static_metadata_slice_table[49])
+/* "200" */
+#define GRPC_MDSTR_200 (::grpc_core::g_static_metadata_slice_table[50])
+/* "204" */
+#define GRPC_MDSTR_204 (::grpc_core::g_static_metadata_slice_table[51])
+/* "206" */
+#define GRPC_MDSTR_206 (::grpc_core::g_static_metadata_slice_table[52])
+/* "304" */
+#define GRPC_MDSTR_304 (::grpc_core::g_static_metadata_slice_table[53])
+/* "400" */
+#define GRPC_MDSTR_400 (::grpc_core::g_static_metadata_slice_table[54])
+/* "404" */
+#define GRPC_MDSTR_404 (::grpc_core::g_static_metadata_slice_table[55])
+/* "500" */
+#define GRPC_MDSTR_500 (::grpc_core::g_static_metadata_slice_table[56])
+/* "accept-charset" */
+#define GRPC_MDSTR_ACCEPT_CHARSET \
+  (::grpc_core::g_static_metadata_slice_table[57])
+/* "gzip, deflate" */
+#define GRPC_MDSTR_GZIP_COMMA_DEFLATE \
+  (::grpc_core::g_static_metadata_slice_table[58])
+/* "accept-language" */
+#define GRPC_MDSTR_ACCEPT_LANGUAGE \
+  (::grpc_core::g_static_metadata_slice_table[59])
+/* "accept-ranges" */
+#define GRPC_MDSTR_ACCEPT_RANGES \
+  (::grpc_core::g_static_metadata_slice_table[60])
+/* "accept" */
+#define GRPC_MDSTR_ACCEPT (::grpc_core::g_static_metadata_slice_table[61])
+/* "access-control-allow-origin" */
+#define GRPC_MDSTR_ACCESS_CONTROL_ALLOW_ORIGIN \
+  (::grpc_core::g_static_metadata_slice_table[62])
+/* "age" */
+#define GRPC_MDSTR_AGE (::grpc_core::g_static_metadata_slice_table[63])
+/* "allow" */
+#define GRPC_MDSTR_ALLOW (::grpc_core::g_static_metadata_slice_table[64])
+/* "authorization" */
+#define GRPC_MDSTR_AUTHORIZATION \
+  (::grpc_core::g_static_metadata_slice_table[65])
+/* "cache-control" */
+#define GRPC_MDSTR_CACHE_CONTROL \
+  (::grpc_core::g_static_metadata_slice_table[66])
+/* "content-disposition" */
+#define GRPC_MDSTR_CONTENT_DISPOSITION \
+  (::grpc_core::g_static_metadata_slice_table[67])
+/* "content-language" */
+#define GRPC_MDSTR_CONTENT_LANGUAGE \
+  (::grpc_core::g_static_metadata_slice_table[68])
+/* "content-length" */
+#define GRPC_MDSTR_CONTENT_LENGTH \
+  (::grpc_core::g_static_metadata_slice_table[69])
+/* "content-location" */
+#define GRPC_MDSTR_CONTENT_LOCATION \
+  (::grpc_core::g_static_metadata_slice_table[70])
+/* "content-range" */
+#define GRPC_MDSTR_CONTENT_RANGE \
+  (::grpc_core::g_static_metadata_slice_table[71])
+/* "cookie" */
+#define GRPC_MDSTR_COOKIE (::grpc_core::g_static_metadata_slice_table[72])
+/* "date" */
+#define GRPC_MDSTR_DATE (::grpc_core::g_static_metadata_slice_table[73])
+/* "etag" */
+#define GRPC_MDSTR_ETAG (::grpc_core::g_static_metadata_slice_table[74])
+/* "expect" */
+#define GRPC_MDSTR_EXPECT (::grpc_core::g_static_metadata_slice_table[75])
+/* "expires" */
+#define GRPC_MDSTR_EXPIRES (::grpc_core::g_static_metadata_slice_table[76])
+/* "from" */
+#define GRPC_MDSTR_FROM (::grpc_core::g_static_metadata_slice_table[77])
+/* "if-match" */
+#define GRPC_MDSTR_IF_MATCH (::grpc_core::g_static_metadata_slice_table[78])
+/* "if-modified-since" */
+#define GRPC_MDSTR_IF_MODIFIED_SINCE \
+  (::grpc_core::g_static_metadata_slice_table[79])
+/* "if-none-match" */
+#define GRPC_MDSTR_IF_NONE_MATCH \
+  (::grpc_core::g_static_metadata_slice_table[80])
+/* "if-range" */
+#define GRPC_MDSTR_IF_RANGE (::grpc_core::g_static_metadata_slice_table[81])
+/* "if-unmodified-since" */
+#define GRPC_MDSTR_IF_UNMODIFIED_SINCE \
+  (::grpc_core::g_static_metadata_slice_table[82])
+/* "last-modified" */
+#define GRPC_MDSTR_LAST_MODIFIED \
+  (::grpc_core::g_static_metadata_slice_table[83])
+/* "link" */
+#define GRPC_MDSTR_LINK (::grpc_core::g_static_metadata_slice_table[84])
+/* "location" */
+#define GRPC_MDSTR_LOCATION (::grpc_core::g_static_metadata_slice_table[85])
+/* "max-forwards" */
+#define GRPC_MDSTR_MAX_FORWARDS (::grpc_core::g_static_metadata_slice_table[86])
+/* "proxy-authenticate" */
+#define GRPC_MDSTR_PROXY_AUTHENTICATE \
+  (::grpc_core::g_static_metadata_slice_table[87])
+/* "proxy-authorization" */
+#define GRPC_MDSTR_PROXY_AUTHORIZATION \
+  (::grpc_core::g_static_metadata_slice_table[88])
+/* "range" */
+#define GRPC_MDSTR_RANGE (::grpc_core::g_static_metadata_slice_table[89])
+/* "referer" */
+#define GRPC_MDSTR_REFERER (::grpc_core::g_static_metadata_slice_table[90])
+/* "refresh" */
+#define GRPC_MDSTR_REFRESH (::grpc_core::g_static_metadata_slice_table[91])
+/* "retry-after" */
+#define GRPC_MDSTR_RETRY_AFTER (::grpc_core::g_static_metadata_slice_table[92])
+/* "server" */
+#define GRPC_MDSTR_SERVER (::grpc_core::g_static_metadata_slice_table[93])
+/* "set-cookie" */
+#define GRPC_MDSTR_SET_COOKIE (::grpc_core::g_static_metadata_slice_table[94])
+/* "strict-transport-security" */
+#define GRPC_MDSTR_STRICT_TRANSPORT_SECURITY \
+  (::grpc_core::g_static_metadata_slice_table[95])
+/* "transfer-encoding" */
+#define GRPC_MDSTR_TRANSFER_ENCODING \
+  (::grpc_core::g_static_metadata_slice_table[96])
+/* "vary" */
+#define GRPC_MDSTR_VARY (::grpc_core::g_static_metadata_slice_table[97])
+/* "via" */
+#define GRPC_MDSTR_VIA (::grpc_core::g_static_metadata_slice_table[98])
+/* "www-authenticate" */
+#define GRPC_MDSTR_WWW_AUTHENTICATE \
+  (::grpc_core::g_static_metadata_slice_table[99])
+/* "0" */
+#define GRPC_MDSTR_0 (::grpc_core::g_static_metadata_slice_table[100])
+/* "identity" */
+#define GRPC_MDSTR_IDENTITY (::grpc_core::g_static_metadata_slice_table[101])
+/* "application/grpc" */
+#define GRPC_MDSTR_APPLICATION_SLASH_GRPC \
+  (::grpc_core::g_static_metadata_slice_table[102])
+/* "grpc" */
+#define GRPC_MDSTR_GRPC (::grpc_core::g_static_metadata_slice_table[103])
+/* "PUT" */
+#define GRPC_MDSTR_PUT (::grpc_core::g_static_metadata_slice_table[104])
+/* "lb-cost-bin" */
+#define GRPC_MDSTR_LB_COST_BIN (::grpc_core::g_static_metadata_slice_table[105])
+/* "identity,deflate" */
+#define GRPC_MDSTR_IDENTITY_COMMA_DEFLATE \
+  (::grpc_core::g_static_metadata_slice_table[106])
+/* "identity,gzip" */
+#define GRPC_MDSTR_IDENTITY_COMMA_GZIP \
+  (::grpc_core::g_static_metadata_slice_table[107])
+/* "deflate,gzip" */
+#define GRPC_MDSTR_DEFLATE_COMMA_GZIP \
+  (::grpc_core::g_static_metadata_slice_table[108])
+/* "identity,deflate,gzip" */
+#define GRPC_MDSTR_IDENTITY_COMMA_DEFLATE_COMMA_GZIP \
+  (::grpc_core::g_static_metadata_slice_table[109])
+
+namespace grpc_core {
+extern StaticSliceRefcount
+    g_static_metadata_slice_refcounts[GRPC_STATIC_MDSTR_COUNT];
+extern const StaticMetadataSlice
+    g_static_metadata_slice_table[GRPC_STATIC_MDSTR_COUNT];
+extern const uint8_t g_static_metadata_bytes[];
+}  // namespace grpc_core
+
+#define GRPC_IS_STATIC_METADATA_STRING(slice) \
+  ((slice).refcount != NULL &&                \
+   (slice).refcount->GetType() == grpc_slice_refcount::Type::STATIC)
+
+#define GRPC_STATIC_METADATA_INDEX(static_slice)                              \
+  (reinterpret_cast<grpc_core::StaticSliceRefcount*>((static_slice).refcount) \
+       ->index)
+
+#endif /* GRPC_CORE_LIB_SLICE_STATIC_SLICE_H */
diff --git a/src/core/lib/surface/builtins.cc b/src/core/lib/surface/builtins.cc
new file mode 100644 (file)
index 0000000..b195ef9
--- /dev/null
@@ -0,0 +1,49 @@
+// 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 <grpc/support/port_platform.h>
+
+#include "src/core/lib/surface/builtins.h"
+
+#include "src/core/lib/channel/connected_channel.h"
+#include "src/core/lib/config/core_configuration.h"
+#include "src/core/lib/surface/lame_client.h"
+#include "src/core/lib/surface/server.h"
+
+namespace grpc_core {
+
+void RegisterBuiltins(CoreConfiguration::Builder* builder) {
+  builder->channel_init()->RegisterStage(GRPC_CLIENT_SUBCHANNEL,
+                                         GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
+                                         grpc_add_connected_filter);
+  builder->channel_init()->RegisterStage(GRPC_CLIENT_DIRECT_CHANNEL,
+                                         GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
+                                         grpc_add_connected_filter);
+  builder->channel_init()->RegisterStage(GRPC_SERVER_CHANNEL,
+                                         GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
+                                         grpc_add_connected_filter);
+  builder->channel_init()->RegisterStage(
+      GRPC_CLIENT_LAME_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
+      [](grpc_channel_stack_builder* builder) {
+        return grpc_channel_stack_builder_append_filter(
+            builder, &grpc_lame_filter, nullptr, nullptr);
+      });
+  builder->channel_init()->RegisterStage(
+      GRPC_SERVER_CHANNEL, INT_MAX, [](grpc_channel_stack_builder* builder) {
+        return grpc_channel_stack_builder_prepend_filter(
+            builder, &grpc_core::Server::kServerTopFilter, nullptr, nullptr);
+      });
+}
+
+}  // namespace grpc_core
diff --git a/src/core/lib/surface/builtins.h b/src/core/lib/surface/builtins.h
new file mode 100644 (file)
index 0000000..c177f02
--- /dev/null
@@ -0,0 +1,26 @@
+// 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.
+
+#ifndef GRPC_CORE_LIB_SURFACE_BUILTINS_H
+#define GRPC_CORE_LIB_SURFACE_BUILTINS_H
+
+#include <grpc/support/port_platform.h>
+
+#include "src/core/lib/config/core_configuration.h"
+
+namespace grpc_core {
+void RegisterBuiltins(CoreConfiguration::Builder* builder);
+}  // namespace grpc_core
+
+#endif  // GRPC_CORE_LIB_SURFACE_BUILTINS_H
index 5d91002..632f6ed 100644 (file)
@@ -50,6 +50,7 @@
 #include "src/core/lib/gprpp/ref_counted.h"
 #include "src/core/lib/iomgr/timer.h"
 #include "src/core/lib/profiling/timers.h"
+#include "src/core/lib/slice/slice_split.h"
 #include "src/core/lib/slice/slice_string_helpers.h"
 #include "src/core/lib/slice/slice_utils.h"
 #include "src/core/lib/surface/api_trace.h"
@@ -107,7 +108,7 @@ struct batch_control {
   grpc_closure start_batch;
   grpc_closure finish_batch;
   std::atomic<intptr_t> steps_to_complete{0};
-  gpr_atm batch_error = reinterpret_cast<gpr_atm>(GRPC_ERROR_NONE);
+  AtomicError batch_error;
   void set_num_steps_to_complete(uintptr_t steps) {
     steps_to_complete.store(steps, std::memory_order_release);
   }
@@ -143,13 +144,7 @@ struct grpc_call {
         cq(args.cq),
         channel(args.channel),
         is_client(args.server_transport_data == nullptr),
-        stream_op_payload(context) {
-    for (int i = 0; i < 2; i++) {
-      for (int j = 0; j < 2; j++) {
-        metadata_batch[i][j].deadline = GRPC_MILLIS_INF_FUTURE;
-      }
-    }
-  }
+        stream_op_payload(context) {}
 
   ~grpc_call() {
     for (int i = 0; i < GRPC_CONTEXT_COUNT; ++i) {
@@ -192,7 +187,10 @@ struct grpc_call {
   grpc_transport_stream_op_batch_payload stream_op_payload;
 
   /* first idx: is_receiving, second idx: is_trailing */
-  grpc_metadata_batch metadata_batch[2][2] = {};
+  grpc_metadata_batch send_initial_metadata{arena};
+  grpc_metadata_batch send_trailing_metadata{arena};
+  grpc_metadata_batch recv_initial_metadata{arena};
+  grpc_metadata_batch recv_trailing_metadata{arena};
 
   /* Buffered read metadata waiting to be returned to the application.
      Element 0 is initial metadata, element 1 is trailing metadata. */
@@ -257,7 +255,7 @@ struct grpc_call {
       grpc_core::Server* core_server;
     } server;
   } final_op;
-  gpr_atm status_error = 0;
+  AtomicError status_error;
 
   /* recv_state can contain one of the following values:
      RECV_NONE :                 :  no initial metadata and messages received
@@ -407,7 +405,7 @@ grpc_error_handle grpc_call_create(const grpc_call_create_args* args,
     GPR_ASSERT(!args->parent->is_client);
 
     if (args->propagation_mask & GRPC_PROPAGATE_DEADLINE) {
-      send_deadline = GPR_MIN(send_deadline, args->parent->send_deadline);
+      send_deadline = std::min(send_deadline, args->parent->send_deadline);
     }
     /* for now GRPC_PROPAGATE_TRACING_CONTEXT *MUST* be passed with
      * GRPC_PROPAGATE_STATS_CONTEXT */
@@ -545,31 +543,26 @@ static void release_call(void* call, grpc_error_handle /*error*/) {
 
 static void destroy_call(void* call, grpc_error_handle /*error*/) {
   GPR_TIMER_SCOPE("destroy_call", 0);
-  size_t i;
-  int ii;
   grpc_call* c = static_cast<grpc_call*>(call);
-  for (i = 0; i < 2; i++) {
-    grpc_metadata_batch_destroy(
-        &c->metadata_batch[1 /* is_receiving */][i /* is_initial */]);
-  }
+  c->recv_initial_metadata.Clear();
+  c->recv_trailing_metadata.Clear();
   c->receiving_stream.reset();
   parent_call* pc = get_parent_call(c);
   if (pc != nullptr) {
     pc->~parent_call();
   }
-  for (ii = 0; ii < c->send_extra_metadata_count; ii++) {
-    GRPC_MDELEM_UNREF(c->send_extra_metadata[ii].md);
+  for (int i = 0; i < c->send_extra_metadata_count; i++) {
+    GRPC_MDELEM_UNREF(c->send_extra_metadata[i].md);
   }
   if (c->cq) {
     GRPC_CQ_INTERNAL_UNREF(c->cq, "bind");
   }
 
-  grpc_error_handle status_error =
-      reinterpret_cast<grpc_error_handle>(gpr_atm_acq_load(&c->status_error));
+  grpc_error_handle status_error = c->status_error.get();
   grpc_error_get_status(status_error, c->send_deadline,
                         &c->final_info.final_status, nullptr, nullptr,
                         &(c->final_info.error_string));
-  GRPC_ERROR_UNREF(status_error);
+  c->status_error.set(GRPC_ERROR_NONE);
   c->final_info.stats.latency =
       gpr_cycle_counter_sub(gpr_get_cycle_counter(), c->start_time);
   grpc_call_stack_destroy(CALL_STACK_FROM_CALL(c), &c->final_info,
@@ -734,8 +727,7 @@ static grpc_error_handle error_from_status(grpc_status_code status,
   // guarantee that can be short-lived.
   return grpc_error_set_int(
       grpc_error_set_str(GRPC_ERROR_CREATE_FROM_COPIED_STRING(description),
-                         GRPC_ERROR_STR_GRPC_MESSAGE,
-                         grpc_slice_from_copied_string(description)),
+                         GRPC_ERROR_STR_GRPC_MESSAGE, description),
       GRPC_ERROR_INT_GRPC_STATUS, status);
 }
 
@@ -750,13 +742,14 @@ static void set_final_status(grpc_call* call, grpc_error_handle error) {
     gpr_log(GPR_DEBUG, "%s", grpc_error_std_string(error).c_str());
   }
   if (call->is_client) {
+    std::string status_details;
     grpc_error_get_status(error, call->send_deadline,
-                          call->final_op.client.status,
-                          call->final_op.client.status_details, nullptr,
-                          call->final_op.client.error_string);
-    // explicitly take a ref
-    grpc_slice_ref_internal(*call->final_op.client.status_details);
-    gpr_atm_rel_store(&call->status_error, reinterpret_cast<gpr_atm>(error));
+                          call->final_op.client.status, &status_details,
+                          nullptr, call->final_op.client.error_string);
+    *call->final_op.client.status_details =
+        grpc_slice_from_cpp_string(std::move(status_details));
+    call->status_error.set(error);
+    GRPC_ERROR_UNREF(error);
     grpc_core::channelz::ChannelNode* channelz_channel =
         grpc_channel_get_channelz_node(call->channel);
     if (channelz_channel != nullptr) {
@@ -772,9 +765,7 @@ static void set_final_status(grpc_call* call, grpc_error_handle error) {
     grpc_core::channelz::ServerNode* channelz_node =
         call->final_op.server.core_server->channelz_node();
     if (channelz_node != nullptr) {
-      if (*call->final_op.server.cancelled ||
-          reinterpret_cast<grpc_error_handle>(
-              gpr_atm_acq_load(&call->status_error)) != GRPC_ERROR_NONE) {
+      if (*call->final_op.server.cancelled || !call->status_error.ok()) {
         channelz_node->RecordCallFailed();
       } else {
         channelz_node->RecordCallSucceeded();
@@ -848,7 +839,7 @@ static void set_encodings_accepted_by_peer(grpc_call* /*call*/,
   grpc_slice_split_without_space(accept_encoding_slice, ",",
                                  &accept_encoding_parts);
 
-  GPR_BITSET(encodings_accepted_by_peer, GRPC_COMPRESS_NONE);
+  grpc_core::SetBit(encodings_accepted_by_peer, GRPC_COMPRESS_NONE);
   for (i = 0; i < accept_encoding_parts.count; i++) {
     int r;
     grpc_slice accept_encoding_entry_slice = accept_encoding_parts.slices[i];
@@ -862,7 +853,7 @@ static void set_encodings_accepted_by_peer(grpc_call* /*call*/,
           reinterpret_cast<grpc_stream_compression_algorithm*>(&algorithm));
     }
     if (r) {
-      GPR_BITSET(encodings_accepted_by_peer, algorithm);
+      grpc_core::SetBit(encodings_accepted_by_peer, algorithm);
     } else {
       char* accept_encoding_entry_str =
           grpc_slice_to_c_string(accept_encoding_entry_slice);
@@ -913,8 +904,8 @@ static int prepare_application_metadata(grpc_call* call, int count,
                                         int additional_metadata_count) {
   int total_count = count + additional_metadata_count;
   int i;
-  grpc_metadata_batch* batch =
-      &call->metadata_batch[0 /* is_receiving */][is_trailing];
+  grpc_metadata_batch* batch = is_trailing ? &call->send_trailing_metadata
+                                           : &call->send_initial_metadata;
   for (i = 0; i < total_count; i++) {
     grpc_metadata* md = get_md_elem(metadata, additional_metadata, i, count);
     grpc_linked_mdelem* l = linked_from_md(md);
@@ -947,15 +938,14 @@ static int prepare_application_metadata(grpc_call* call, int count,
     } else {
       for (i = 0; i < call->send_extra_metadata_count; i++) {
         GRPC_LOG_IF_ERROR("prepare_application_metadata",
-                          grpc_metadata_batch_link_tail(
-                              batch, &call->send_extra_metadata[i]));
+                          batch->LinkTail(&call->send_extra_metadata[i]));
       }
     }
   }
   for (i = 0; i < total_count; i++) {
     grpc_metadata* md = get_md_elem(metadata, additional_metadata, i, count);
     grpc_linked_mdelem* l = linked_from_md(md);
-    grpc_error_handle error = grpc_metadata_batch_link_tail(batch, l);
+    grpc_error_handle error = batch->LinkTail(l);
     if (error != GRPC_ERROR_NONE) {
       GRPC_MDELEM_UNREF(l->md);
     }
@@ -1000,53 +990,57 @@ static grpc_stream_compression_algorithm decode_stream_compression(
 
 static void publish_app_metadata(grpc_call* call, grpc_metadata_batch* b,
                                  int is_trailing) {
-  if (b->list.count == 0) return;
+  if (b->non_deadline_count() == 0) return;
   if (!call->is_client && is_trailing) return;
   if (is_trailing && call->buffered_metadata[1] == nullptr) return;
   GPR_TIMER_SCOPE("publish_app_metadata", 0);
   grpc_metadata_array* dest;
   grpc_metadata* mdusr;
   dest = call->buffered_metadata[is_trailing];
-  if (dest->count + b->list.count > dest->capacity) {
-    dest->capacity =
-        GPR_MAX(dest->capacity + b->list.count, dest->capacity * 3 / 2);
+  if (dest->count + b->non_deadline_count() > dest->capacity) {
+    dest->capacity = std::max(dest->capacity + b->non_deadline_count(),
+                              dest->capacity * 3 / 2);
     dest->metadata = static_cast<grpc_metadata*>(
         gpr_realloc(dest->metadata, sizeof(grpc_metadata) * dest->capacity));
   }
-  for (grpc_linked_mdelem* l = b->list.head; l != nullptr; l = l->next) {
+  b->ForEach([&](grpc_mdelem md) {
     mdusr = &dest->metadata[dest->count++];
     /* we pass back borrowed slices that are valid whilst the call is valid */
-    mdusr->key = GRPC_MDKEY(l->md);
-    mdusr->value = GRPC_MDVALUE(l->md);
-  }
+    mdusr->key = GRPC_MDKEY(md);
+    mdusr->value = GRPC_MDVALUE(md);
+  });
 }
 
 static void recv_initial_filter(grpc_call* call, grpc_metadata_batch* b) {
-  if (b->idx.named.content_encoding != nullptr) {
+  if (b->legacy_index()->named.content_encoding != nullptr) {
     GPR_TIMER_SCOPE("incoming_stream_compression_algorithm", 0);
     set_incoming_stream_compression_algorithm(
-        call, decode_stream_compression(b->idx.named.content_encoding->md));
-    grpc_metadata_batch_remove(b, GRPC_BATCH_CONTENT_ENCODING);
+        call, decode_stream_compression(
+                  b->legacy_index()->named.content_encoding->md));
+    b->Remove(GRPC_BATCH_CONTENT_ENCODING);
   }
-  if (b->idx.named.grpc_encoding != nullptr) {
+  if (b->legacy_index()->named.grpc_encoding != nullptr) {
     GPR_TIMER_SCOPE("incoming_message_compression_algorithm", 0);
     set_incoming_message_compression_algorithm(
-        call, decode_message_compression(b->idx.named.grpc_encoding->md));
-    grpc_metadata_batch_remove(b, GRPC_BATCH_GRPC_ENCODING);
+        call,
+        decode_message_compression(b->legacy_index()->named.grpc_encoding->md));
+    b->Remove(GRPC_BATCH_GRPC_ENCODING);
   }
   uint32_t message_encodings_accepted_by_peer = 1u;
   uint32_t stream_encodings_accepted_by_peer = 1u;
-  if (b->idx.named.grpc_accept_encoding != nullptr) {
+  if (b->legacy_index()->named.grpc_accept_encoding != nullptr) {
     GPR_TIMER_SCOPE("encodings_accepted_by_peer", 0);
-    set_encodings_accepted_by_peer(call, b->idx.named.grpc_accept_encoding->md,
-                                   &message_encodings_accepted_by_peer, false);
-    grpc_metadata_batch_remove(b, GRPC_BATCH_GRPC_ACCEPT_ENCODING);
+    set_encodings_accepted_by_peer(
+        call, b->legacy_index()->named.grpc_accept_encoding->md,
+        &message_encodings_accepted_by_peer, false);
+    b->Remove(GRPC_BATCH_GRPC_ACCEPT_ENCODING);
   }
-  if (b->idx.named.accept_encoding != nullptr) {
+  if (b->legacy_index()->named.accept_encoding != nullptr) {
     GPR_TIMER_SCOPE("stream_encodings_accepted_by_peer", 0);
-    set_encodings_accepted_by_peer(call, b->idx.named.accept_encoding->md,
+    set_encodings_accepted_by_peer(call,
+                                   b->legacy_index()->named.accept_encoding->md,
                                    &stream_encodings_accepted_by_peer, true);
-    grpc_metadata_batch_remove(b, GRPC_BATCH_ACCEPT_ENCODING);
+    b->Remove(GRPC_BATCH_ACCEPT_ENCODING);
   }
   call->encodings_accepted_by_peer =
       grpc_compression_bitset_from_message_stream_compression_bitset(
@@ -1060,9 +1054,9 @@ static void recv_trailing_filter(void* args, grpc_metadata_batch* b,
   grpc_call* call = static_cast<grpc_call*>(args);
   if (batch_error != GRPC_ERROR_NONE) {
     set_final_status(call, batch_error);
-  } else if (b->idx.named.grpc_status != nullptr) {
-    grpc_status_code status_code =
-        grpc_get_status_code_from_metadata(b->idx.named.grpc_status->md);
+  } else if (b->legacy_index()->named.grpc_status != nullptr) {
+    grpc_status_code status_code = grpc_get_status_code_from_metadata(
+        b->legacy_index()->named.grpc_status->md);
     grpc_error_handle error = GRPC_ERROR_NONE;
     if (status_code != GRPC_STATUS_OK) {
       char* peer = grpc_call_get_peer(call);
@@ -1072,17 +1066,17 @@ static void recv_trailing_filter(void* args, grpc_metadata_batch* b,
                                  static_cast<intptr_t>(status_code));
       gpr_free(peer);
     }
-    if (b->idx.named.grpc_message != nullptr) {
+    if (b->legacy_index()->named.grpc_message != nullptr) {
       error = grpc_error_set_str(
           error, GRPC_ERROR_STR_GRPC_MESSAGE,
-          grpc_slice_ref_internal(GRPC_MDVALUE(b->idx.named.grpc_message->md)));
-      grpc_metadata_batch_remove(b, GRPC_BATCH_GRPC_MESSAGE);
+          grpc_core::StringViewFromSlice(
+              GRPC_MDVALUE(b->legacy_index()->named.grpc_message->md)));
+      b->Remove(GRPC_BATCH_GRPC_MESSAGE);
     } else if (error != GRPC_ERROR_NONE) {
-      error = grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE,
-                                 grpc_empty_slice());
+      error = grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE, "");
     }
     set_final_status(call, GRPC_ERROR_REF(error));
-    grpc_metadata_batch_remove(b, GRPC_BATCH_GRPC_STATUS);
+    b->Remove(GRPC_BATCH_GRPC_STATUS);
     GRPC_ERROR_UNREF(error);
   } else if (!call->is_client) {
     set_final_status(call, GRPC_ERROR_NONE);
@@ -1156,6 +1150,7 @@ static batch_control* reuse_or_allocate_batch_control(grpc_call* call,
     }
     bctl->~batch_control();
     bctl->op = {};
+    new (&bctl->batch_error) AtomicError();
   } else {
     bctl = call->arena->New<batch_control>();
     *pslot = bctl;
@@ -1174,21 +1169,16 @@ static void finish_batch_completion(void* user_data,
 }
 
 static void reset_batch_errors(batch_control* bctl) {
-  GRPC_ERROR_UNREF(reinterpret_cast<grpc_error_handle>(
-      gpr_atm_acq_load(&bctl->batch_error)));
-  gpr_atm_rel_store(&bctl->batch_error,
-                    reinterpret_cast<gpr_atm>(GRPC_ERROR_NONE));
+  bctl->batch_error.set(GRPC_ERROR_NONE);
 }
 
 static void post_batch_completion(batch_control* bctl) {
   grpc_call* next_child_call;
   grpc_call* call = bctl->call;
-  grpc_error_handle error = GRPC_ERROR_REF(reinterpret_cast<grpc_error_handle>(
-      gpr_atm_acq_load(&bctl->batch_error)));
+  grpc_error_handle error = GRPC_ERROR_REF(bctl->batch_error.get());
 
   if (bctl->op.send_initial_metadata) {
-    grpc_metadata_batch_destroy(
-        &call->metadata_batch[0 /* is_receiving */][0 /* is_trailing */]);
+    call->send_initial_metadata.Clear();
   }
   if (bctl->op.send_message) {
     if (bctl->op.payload->send_message.stream_write_closed &&
@@ -1200,8 +1190,7 @@ static void post_batch_completion(batch_control* bctl) {
     call->sending_message = false;
   }
   if (bctl->op.send_trailing_metadata) {
-    grpc_metadata_batch_destroy(
-        &call->metadata_batch[0 /* is_receiving */][1 /* is_trailing */]);
+    call->send_trailing_metadata.Clear();
   }
   if (bctl->op.recv_trailing_metadata) {
     /* propagate cancellation to any interested children */
@@ -1353,10 +1342,8 @@ static void receiving_stream_ready(void* bctlp, grpc_error_handle error) {
   grpc_call* call = bctl->call;
   if (error != GRPC_ERROR_NONE) {
     call->receiving_stream.reset();
-    if (reinterpret_cast<grpc_error_handle>(
-            gpr_atm_acq_load(&bctl->batch_error)) == GRPC_ERROR_NONE) {
-      gpr_atm_rel_store(&bctl->batch_error,
-                        reinterpret_cast<gpr_atm>(GRPC_ERROR_REF(error)));
+    if (bctl->batch_error.ok()) {
+      bctl->batch_error.set(error);
     }
     cancel_with_error(call, GRPC_ERROR_REF(error));
   }
@@ -1458,8 +1445,8 @@ static void validate_filtered_metadata(batch_control* bctl) {
     }
     /* GRPC_COMPRESS_NONE is always set. */
     GPR_DEBUG_ASSERT(call->encodings_accepted_by_peer != 0);
-    if (GPR_UNLIKELY(!GPR_BITGET(call->encodings_accepted_by_peer,
-                                 compression_algorithm))) {
+    if (GPR_UNLIKELY(!grpc_core::GetBit(call->encodings_accepted_by_peer,
+                                        compression_algorithm))) {
       if (GRPC_TRACE_FLAG_ENABLED(grpc_compression_trace)) {
         handle_compression_algorithm_not_accepted(call, compression_algorithm);
       }
@@ -1475,22 +1462,21 @@ static void receiving_initial_metadata_ready(void* bctlp,
   GRPC_CALL_COMBINER_STOP(&call->call_combiner, "recv_initial_metadata_ready");
 
   if (error == GRPC_ERROR_NONE) {
-    grpc_metadata_batch* md =
-        &call->metadata_batch[1 /* is_receiving */][0 /* is_trailing */];
+    grpc_metadata_batch* md = &call->recv_initial_metadata;
     recv_initial_filter(call, md);
 
     /* TODO(ctiller): this could be moved into recv_initial_filter now */
     GPR_TIMER_SCOPE("validate_filtered_metadata", 0);
     validate_filtered_metadata(bctl);
 
-    if (md->deadline != GRPC_MILLIS_INF_FUTURE && !call->is_client) {
-      call->send_deadline = md->deadline;
+    absl::optional<grpc_millis> deadline =
+        md->get(grpc_core::GrpcTimeoutMetadata());
+    if (deadline.has_value() && !call->is_client) {
+      call->send_deadline = *deadline;
     }
   } else {
-    if (reinterpret_cast<grpc_error_handle>(
-            gpr_atm_acq_load(&bctl->batch_error)) == GRPC_ERROR_NONE) {
-      gpr_atm_rel_store(&bctl->batch_error,
-                        reinterpret_cast<gpr_atm>(GRPC_ERROR_REF(error)));
+    if (bctl->batch_error.ok()) {
+      bctl->batch_error.set(error);
     }
     cancel_with_error(call, GRPC_ERROR_REF(error));
   }
@@ -1532,8 +1518,7 @@ static void receiving_trailing_metadata_ready(void* bctlp,
   batch_control* bctl = static_cast<batch_control*>(bctlp);
   grpc_call* call = bctl->call;
   GRPC_CALL_COMBINER_STOP(&call->call_combiner, "recv_trailing_metadata_ready");
-  grpc_metadata_batch* md =
-      &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */];
+  grpc_metadata_batch* md = &call->recv_trailing_metadata;
   recv_trailing_filter(call, md, GRPC_ERROR_REF(error));
   finish_batch_step(bctl);
 }
@@ -1542,10 +1527,8 @@ static void finish_batch(void* bctlp, grpc_error_handle error) {
   batch_control* bctl = static_cast<batch_control*>(bctlp);
   grpc_call* call = bctl->call;
   GRPC_CALL_COMBINER_STOP(&call->call_combiner, "on_complete");
-  if (reinterpret_cast<grpc_error_handle>(
-          gpr_atm_acq_load(&bctl->batch_error)) == GRPC_ERROR_NONE) {
-    gpr_atm_rel_store(&bctl->batch_error,
-                      reinterpret_cast<gpr_atm>(GRPC_ERROR_REF(error)));
+  if (bctl->batch_error.ok()) {
+    bctl->batch_error.set(error);
   }
   if (error != GRPC_ERROR_NONE) {
     cancel_with_error(call, GRPC_ERROR_REF(error));
@@ -1669,11 +1652,12 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops,
           goto done_with_error;
         }
         /* TODO(ctiller): just make these the same variable? */
-        if (call->is_client) {
-          call->metadata_batch[0][0].deadline = call->send_deadline;
+        if (call->is_client && call->send_deadline != GRPC_MILLIS_INF_FUTURE) {
+          call->send_initial_metadata.Set(grpc_core::GrpcTimeoutMetadata(),
+                                          call->send_deadline);
         }
         stream_op_payload->send_initial_metadata.send_initial_metadata =
-            &call->metadata_batch[0 /* is_receiving */][0 /* is_trailing */];
+            &call->send_initial_metadata;
         stream_op_payload->send_initial_metadata.send_initial_metadata_flags =
             op->flags;
         if (call->is_client) {
@@ -1730,7 +1714,7 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops,
         stream_op->send_trailing_metadata = true;
         call->sent_final_op = true;
         stream_op_payload->send_trailing_metadata.send_trailing_metadata =
-            &call->metadata_batch[0 /* is_receiving */][1 /* is_trailing */];
+            &call->send_trailing_metadata;
         has_send_ops = true;
         break;
       }
@@ -1771,21 +1755,21 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops,
         if (op->data.send_status_from_server.status_details != nullptr) {
           call->send_extra_metadata[1].md = grpc_mdelem_from_slices(
               GRPC_MDSTR_GRPC_MESSAGE,
-              grpc_slice_ref_internal(
+              grpc_slice_copy(
                   *op->data.send_status_from_server.status_details));
           call->send_extra_metadata_count++;
           if (status_error != GRPC_ERROR_NONE) {
             char* msg = grpc_slice_to_c_string(
                 GRPC_MDVALUE(call->send_extra_metadata[1].md));
-            status_error =
-                grpc_error_set_str(status_error, GRPC_ERROR_STR_GRPC_MESSAGE,
-                                   grpc_slice_from_copied_string(msg));
+            status_error = grpc_error_set_str(status_error,
+                                              GRPC_ERROR_STR_GRPC_MESSAGE, msg);
             gpr_free(msg);
           }
         }
 
-        gpr_atm_rel_store(&call->status_error,
-                          reinterpret_cast<gpr_atm>(status_error));
+        call->status_error.set(status_error);
+        GRPC_ERROR_UNREF(status_error);
+
         if (!prepare_application_metadata(
                 call,
                 static_cast<int>(
@@ -1800,7 +1784,7 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops,
           goto done_with_error;
         }
         stream_op_payload->send_trailing_metadata.send_trailing_metadata =
-            &call->metadata_batch[0 /* is_receiving */][1 /* is_trailing */];
+            &call->send_trailing_metadata;
         stream_op_payload->send_trailing_metadata.sent =
             &call->sent_server_trailing_metadata;
         has_send_ops = true;
@@ -1824,7 +1808,7 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops,
                           grpc_schedule_on_exec_ctx);
         stream_op->recv_initial_metadata = true;
         stream_op_payload->recv_initial_metadata.recv_initial_metadata =
-            &call->metadata_batch[1 /* is_receiving */][0 /* is_trailing */];
+            &call->recv_initial_metadata;
         stream_op_payload->recv_initial_metadata.recv_initial_metadata_ready =
             &call->receiving_initial_metadata_ready;
         if (call->is_client) {
@@ -1885,7 +1869,7 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops,
             op->data.recv_status_on_client.error_string;
         stream_op->recv_trailing_metadata = true;
         stream_op_payload->recv_trailing_metadata.recv_trailing_metadata =
-            &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */];
+            &call->recv_trailing_metadata;
         stream_op_payload->recv_trailing_metadata.collect_stats =
             &call->final_info.stats.transport_stream_stats;
         GRPC_CLOSURE_INIT(&call->receiving_trailing_metadata_ready,
@@ -1915,7 +1899,7 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops,
             op->data.recv_close_on_server.cancelled;
         stream_op->recv_trailing_metadata = true;
         stream_op_payload->recv_trailing_metadata.recv_trailing_metadata =
-            &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */];
+            &call->recv_trailing_metadata;
         stream_op_payload->recv_trailing_metadata.collect_stats =
             &call->final_info.stats.transport_stream_stats;
         GRPC_CLOSURE_INIT(&call->receiving_trailing_metadata_ready,
@@ -1951,15 +1935,16 @@ done_with_error:
   /* reverse any mutations that occurred */
   if (stream_op->send_initial_metadata) {
     call->sent_initial_metadata = false;
-    grpc_metadata_batch_clear(&call->metadata_batch[0][0]);
+    call->send_initial_metadata.Clear();
   }
   if (stream_op->send_message) {
     call->sending_message = false;
     call->sending_stream->Orphan();
+    stream_op_payload->send_message.send_message.reset();
   }
   if (stream_op->send_trailing_metadata) {
     call->sent_final_op = false;
-    grpc_metadata_batch_clear(&call->metadata_batch[0][1]);
+    call->send_trailing_metadata.Clear();
   }
   if (stream_op->recv_initial_metadata) {
     call->received_initial_metadata = false;
@@ -2024,13 +2009,11 @@ grpc_compression_algorithm grpc_call_compression_for_level(
 
 bool grpc_call_is_trailers_only(const grpc_call* call) {
   bool result = call->is_trailers_only;
-  GPR_DEBUG_ASSERT(
-      !result || call->metadata_batch[1 /* is_receiving */][0 /* is_trailing */]
-                         .list.count == 0);
+  GPR_DEBUG_ASSERT(!result || call->recv_initial_metadata.empty());
   return result;
 }
 
-bool grpc_call_failed_before_recv_message(const grpc_call* c) {
+int grpc_call_failed_before_recv_message(const grpc_call* c) {
   return c->call_failed_before_recv_message;
 }
 
index 221de35..e16a6be 100644 (file)
@@ -125,12 +125,6 @@ grpc_compression_algorithm grpc_call_compression_for_level(
                     Move to surface API if requested by other languages. */
 bool grpc_call_is_trailers_only(const grpc_call* call);
 
-/* Returns whether or not the call's receive message operation failed because of
- * an error (as opposed to a graceful end-of-stream) */
-/* TODO(markdroth): This is currently available only to the C++ API.
-                    Move to surface API if requested by other languages. */
-bool grpc_call_failed_before_recv_message(const grpc_call* c);
-
 extern grpc_core::TraceFlag grpc_call_error_trace;
 extern grpc_core::TraceFlag grpc_compression_trace;
 
index f914f6e..f4af87e 100644 (file)
@@ -34,6 +34,7 @@
 #include "src/core/lib/channel/channel_trace.h"
 #include "src/core/lib/channel/channelz.h"
 #include "src/core/lib/channel/channelz_registry.h"
+#include "src/core/lib/config/core_configuration.h"
 #include "src/core/lib/debug/stats.h"
 #include "src/core/lib/gpr/string.h"
 #include "src/core/lib/gprpp/manual_constructor.h"
@@ -44,7 +45,6 @@
 #include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/surface/api_trace.h"
 #include "src/core/lib/surface/call.h"
-#include "src/core/lib/surface/channel_init.h"
 #include "src/core/lib/transport/static_metadata.h"
 
 /** Cache grpc-status: X mdelems for X = 0..NUM_CACHED_STATUS_ELEMS.
@@ -187,7 +187,9 @@ void channelz_node_destroy(void* p) {
       static_cast<grpc_core::channelz::ChannelNode*>(p);
   node->Unref();
 }
-int channelz_node_cmp(void* p1, void* p2) { return GPR_ICMP(p1, p2); }
+int channelz_node_cmp(void* p1, void* p2) {
+  return grpc_core::QsortCompare(p1, p2);
+}
 const grpc_arg_pointer_vtable channelz_node_arg_vtable = {
     channelz_node_copy, channelz_node_destroy, channelz_node_cmp};
 
@@ -267,7 +269,8 @@ grpc_channel* grpc_channel_create(const char* target,
   grpc_channel_args_destroy(args);
   grpc_channel_stack_builder_set_target(builder, target);
   grpc_channel_stack_builder_set_transport(builder, optional_transport);
-  if (!grpc_channel_init_create_stack(builder, channel_stack_type)) {
+  if (!grpc_core::CoreConfiguration::Get().channel_init().CreateStack(
+          builder, channel_stack_type)) {
     grpc_channel_stack_builder_destroy(builder);
     if (resource_user != nullptr) {
       if (preallocated_bytes > 0) {
@@ -321,7 +324,7 @@ void grpc_channel_update_call_size_estimate(grpc_channel* channel,
     /* size shrank: decrease estimate */
     gpr_atm_no_barrier_cas(
         &channel->call_size_estimate, static_cast<gpr_atm>(cur),
-        static_cast<gpr_atm>(GPR_MIN(cur - 1, (255 * cur + size) / 256)));
+        static_cast<gpr_atm>(std::min(cur - 1, (255 * cur + size) / 256)));
     /* if we lose: never mind, something else will likely update soon enough */
   }
 }
@@ -420,35 +423,19 @@ grpc_call* grpc_channel_create_pollset_set_call(
 namespace grpc_core {
 
 RegisteredCall::RegisteredCall(const char* method_arg, const char* host_arg)
-    : method(method_arg != nullptr ? method_arg : ""),
-      host(host_arg != nullptr ? host_arg : ""),
-      path(grpc_mdelem_from_slices(
-          GRPC_MDSTR_PATH, grpc_core::ExternallyManagedSlice(method.c_str()))),
-      authority(!host.empty()
-                    ? grpc_mdelem_from_slices(
-                          GRPC_MDSTR_AUTHORITY,
-                          grpc_core::ExternallyManagedSlice(host.c_str()))
-                    : GRPC_MDNULL) {}
-
-// TODO(vjpai): Delete copy-constructor when allowed by all supported compilers.
+    : path(method_arg != nullptr && method_arg[0] != 0
+               ? grpc_mdelem_from_slices(
+                     GRPC_MDSTR_PATH, grpc_slice_from_copied_string(method_arg))
+               : GRPC_MDNULL),
+      authority(
+          host_arg != nullptr && host_arg[0] != 0
+              ? grpc_mdelem_from_slices(GRPC_MDSTR_AUTHORITY,
+                                        grpc_slice_from_copied_string(host_arg))
+              : GRPC_MDNULL) {}
+
 RegisteredCall::RegisteredCall(const RegisteredCall& other)
-    : RegisteredCall(other.method.c_str(), other.host.c_str()) {}
-
-RegisteredCall::RegisteredCall(RegisteredCall&& other) noexcept
-    : method(std::move(other.method)),
-      host(std::move(other.host)),
-      path(grpc_mdelem_from_slices(
-          GRPC_MDSTR_PATH, grpc_core::ExternallyManagedSlice(method.c_str()))),
-      authority(!host.empty()
-                    ? grpc_mdelem_from_slices(
-                          GRPC_MDSTR_AUTHORITY,
-                          grpc_core::ExternallyManagedSlice(host.c_str()))
-                    : GRPC_MDNULL) {
-  GRPC_MDELEM_UNREF(other.path);
-  GRPC_MDELEM_UNREF(other.authority);
-  other.path = GRPC_MDNULL;
-  other.authority = GRPC_MDNULL;
-}
+    : path(GRPC_MDELEM_REF(other.path)),
+      authority(GRPC_MDELEM_REF(other.authority)) {}
 
 RegisteredCall::~RegisteredCall() {
   GRPC_MDELEM_UNREF(path);
index 4e885fa..353df77 100644 (file)
@@ -82,21 +82,12 @@ void grpc_channel_update_call_size_estimate(grpc_channel* channel, size_t size);
 namespace grpc_core {
 
 struct RegisteredCall {
-  // The method and host are kept as part of this struct just to manage their
-  // lifetime since they must outlive the mdelem contents.
-  std::string method;
-  std::string host;
-
   grpc_mdelem path;
   grpc_mdelem authority;
 
   explicit RegisteredCall(const char* method_arg, const char* host_arg);
-  // TODO(vjpai): delete copy constructor once all supported compilers allow
-  //              std::map value_type to be MoveConstructible.
   RegisteredCall(const RegisteredCall& other);
-  RegisteredCall(RegisteredCall&& other) noexcept;
   RegisteredCall& operator=(const RegisteredCall&) = delete;
-  RegisteredCall& operator=(RegisteredCall&&) = delete;
 
   ~RegisteredCall();
 };
index 17f6c90..beeb23d 100644 (file)
 
 #include "src/core/lib/surface/channel_init.h"
 
-#include <grpc/support/alloc.h>
+#include <algorithm>
 
-typedef struct stage_slot {
-  grpc_channel_init_stage fn;
-  void* arg;
-  int priority;
-  size_t insertion_order;
-} stage_slot;
+namespace grpc_core {
 
-typedef struct stage_slots {
-  stage_slot* slots;
-  size_t num_slots;
-  size_t cap_slots;
-} stage_slots;
-
-static stage_slots g_slots[GRPC_NUM_CHANNEL_STACK_TYPES];
-static bool g_finalized;
-
-void grpc_channel_init_init(void) {
-  for (int i = 0; i < GRPC_NUM_CHANNEL_STACK_TYPES; i++) {
-    g_slots[i].slots = nullptr;
-    g_slots[i].num_slots = 0;
-    g_slots[i].cap_slots = 0;
-  }
-  g_finalized = false;
-}
-
-void grpc_channel_init_register_stage(grpc_channel_stack_type type,
-                                      int priority,
-                                      grpc_channel_init_stage stage,
-                                      void* stage_arg) {
-  GPR_ASSERT(!g_finalized);
-  if (g_slots[type].cap_slots == g_slots[type].num_slots) {
-    g_slots[type].cap_slots = GPR_MAX(8, 3 * g_slots[type].cap_slots / 2);
-    g_slots[type].slots = static_cast<stage_slot*>(
-        gpr_realloc(g_slots[type].slots,
-                    g_slots[type].cap_slots * sizeof(*g_slots[type].slots)));
-  }
-  stage_slot* s = &g_slots[type].slots[g_slots[type].num_slots++];
-  s->insertion_order = g_slots[type].num_slots;
-  s->priority = priority;
-  s->fn = stage;
-  s->arg = stage_arg;
-}
-
-static int compare_slots(const void* a, const void* b) {
-  const stage_slot* sa = static_cast<const stage_slot*>(a);
-  const stage_slot* sb = static_cast<const stage_slot*>(b);
-
-  int c = GPR_ICMP(sa->priority, sb->priority);
-  if (c != 0) return c;
-  return GPR_ICMP(sa->insertion_order, sb->insertion_order);
+void ChannelInit::Builder::RegisterStage(grpc_channel_stack_type type,
+                                         int priority, Stage stage) {
+  slots_[type].emplace_back(std::move(stage), priority);
 }
 
-void grpc_channel_init_finalize(void) {
-  GPR_ASSERT(!g_finalized);
+ChannelInit ChannelInit::Builder::Build() {
+  ChannelInit result;
   for (int i = 0; i < GRPC_NUM_CHANNEL_STACK_TYPES; i++) {
-    qsort(g_slots[i].slots, g_slots[i].num_slots, sizeof(*g_slots[i].slots),
-          compare_slots);
-  }
-  g_finalized = true;
-}
-
-void grpc_channel_init_shutdown(void) {
-  for (int i = 0; i < GRPC_NUM_CHANNEL_STACK_TYPES; i++) {
-    gpr_free(g_slots[i].slots);
-    g_slots[i].slots =
-        static_cast<stage_slot*>(reinterpret_cast<void*>(0xdeadbeef));
+    auto& slots = slots_[i];
+    std::stable_sort(
+        slots.begin(), slots.end(),
+        [](const Slot& a, const Slot& b) { return a.priority < b.priority; });
+    auto& result_slots = result.slots_[i];
+    result_slots.reserve(slots.size());
+    for (auto& slot : slots) {
+      result_slots.emplace_back(std::move(slot.stage));
+    }
   }
+  return result;
 }
 
-bool grpc_channel_init_create_stack(grpc_channel_stack_builder* builder,
-                                    grpc_channel_stack_type type) {
-  GPR_ASSERT(g_finalized);
-
-  grpc_channel_stack_builder_set_name(builder,
-                                      grpc_channel_stack_type_string(type));
-
-  for (size_t i = 0; i < g_slots[type].num_slots; i++) {
-    const stage_slot* slot = &g_slots[type].slots[i];
-    if (!slot->fn(builder, slot->arg)) {
-      return false;
-    }
+bool ChannelInit::CreateStack(grpc_channel_stack_builder* builder,
+                              grpc_channel_stack_type type) const {
+  for (const auto& stage : slots_[type]) {
+    if (!stage(builder)) return false;
   }
-
   return true;
 }
+
+}  // namespace grpc_core
index d17a721..8f83993 100644 (file)
 
 #include <grpc/support/port_platform.h>
 
-#include "src/core/lib/channel/channel_stack_builder.h"
+#include <functional>
+#include <vector>
+
 #include "src/core/lib/surface/channel_stack_type.h"
-#include "src/core/lib/transport/transport.h"
 
 #define GRPC_CHANNEL_INIT_BUILTIN_PRIORITY 10000
 
 /// It also provides a universal entry path to run those mutators to build
 /// a channel stack for various subsystems.
 
-/// One stage of mutation: call functions against \a builder to influence the
-/// finally constructed channel stack
-typedef bool (*grpc_channel_init_stage)(grpc_channel_stack_builder* builder,
-                                        void* arg);
-
-/// Global initialization of the system
-void grpc_channel_init_init(void);
-
-/// Register one stage of mutators.
-/// Stages are run in priority order (lowest to highest), and then in
-/// registration order (in the case of a tie).
-/// Stages are registered against one of the pre-determined channel stack
-/// types.
-/// If the channel stack type is GRPC_CLIENT_SUBCHANNEL, the caller should
-/// ensure that subchannels with different filter lists will always have
-/// different channel args. This requires setting a channel arg in case the
-/// registration function relies on some condition other than channel args to
-/// decide whether to add a filter or not.
-void grpc_channel_init_register_stage(grpc_channel_stack_type type,
-                                      int priority,
-                                      grpc_channel_init_stage stage_fn,
-                                      void* stage_arg);
-
-/// Finalize registration. No more calls to grpc_channel_init_register_stage are
-/// allowed.
-void grpc_channel_init_finalize(void);
-/// Shutdown the channel init system
-void grpc_channel_init_shutdown(void);
-
-/// Construct a channel stack of some sort: see channel_stack.h for details
-/// \a type is the type of channel stack to create
-/// \a prefix_bytes is the number of bytes before the channel stack to allocate
-/// \a args are configuration arguments for the channel stack
-/// \a initial_refs is the initial refcount to give the channel stack
-/// \a destroy and \a destroy_arg specify how to destroy the channel stack
-///    if destroy_arg is NULL, the returned value from this function will be
-///    substituted
-/// \a optional_transport is either NULL or a constructed transport object
-/// Returns a pointer to the base of the memory allocated (the actual channel
-/// stack object will be prefix_bytes past that pointer)
-bool grpc_channel_init_create_stack(grpc_channel_stack_builder* builder,
-                                    grpc_channel_stack_type type);
+typedef struct grpc_channel_stack_builder grpc_channel_stack_builder;
+
+namespace grpc_core {
+
+class ChannelInit {
+ public:
+  /// One stage of mutation: call functions against \a builder to influence the
+  /// finally constructed channel stack
+  using Stage = std::function<bool(grpc_channel_stack_builder* builder)>;
+
+  class Builder {
+   public:
+    /// Register one stage of mutators.
+    /// Stages are run in priority order (lowest to highest), and then in
+    /// registration order (in the case of a tie).
+    /// Stages are registered against one of the pre-determined channel stack
+    /// types.
+    /// If the channel stack type is GRPC_CLIENT_SUBCHANNEL, the caller should
+    /// ensure that subchannels with different filter lists will always have
+    /// different channel args. This requires setting a channel arg in case the
+    /// registration function relies on some condition other than channel args
+    /// to decide whether to add a filter or not.
+    void RegisterStage(grpc_channel_stack_type type, int priority, Stage stage);
+
+    /// Finalize registration. No more calls to grpc_channel_init_register_stage
+    /// are allowed.
+    ChannelInit Build();
+
+   private:
+    struct Slot {
+      Slot(Stage stage, int priority)
+          : stage(std::move(stage)), priority(priority) {}
+      Stage stage;
+      int priority;
+    };
+    std::vector<Slot> slots_[GRPC_NUM_CHANNEL_STACK_TYPES];
+  };
+
+  /// Construct a channel stack of some sort: see channel_stack.h for details
+  /// \a type is the type of channel stack to create
+  /// \a builder is the channel stack builder to build into.
+  bool CreateStack(grpc_channel_stack_builder* builder,
+                   grpc_channel_stack_type type) const;
+
+ private:
+  std::vector<Stage> slots_[GRPC_NUM_CHANNEL_STACK_TYPES];
+};
+
+}  // namespace grpc_core
 
 #endif /* GRPC_CORE_LIB_SURFACE_CHANNEL_INIT_H */
index 17e8ed4..847b0fe 100644 (file)
@@ -628,8 +628,8 @@ static void cq_check_tag(grpc_completion_queue* cq, void* tag, bool lock_cq) {
   for (int i = 0; i < static_cast<int>(cq->outstanding_tag_count); i++) {
     if (cq->outstanding_tags[i] == tag) {
       cq->outstanding_tag_count--;
-      GPR_SWAP(void*, cq->outstanding_tags[i],
-               cq->outstanding_tags[cq->outstanding_tag_count]);
+      std::swap(cq->outstanding_tags[i],
+                cq->outstanding_tags[cq->outstanding_tag_count]);
       found = 1;
       break;
     }
@@ -665,7 +665,8 @@ bool grpc_cq_begin_op(grpc_completion_queue* cq, void* tag) {
 #ifndef NDEBUG
   gpr_mu_lock(cq->mu);
   if (cq->outstanding_tag_count == cq->outstanding_tag_capacity) {
-    cq->outstanding_tag_capacity = GPR_MAX(4, 2 * cq->outstanding_tag_capacity);
+    cq->outstanding_tag_capacity =
+        std::max(size_t(4), 2 * cq->outstanding_tag_capacity);
     cq->outstanding_tags = static_cast<void**>(gpr_realloc(
         cq->outstanding_tags,
         sizeof(*cq->outstanding_tags) * cq->outstanding_tag_capacity));
@@ -1066,7 +1067,7 @@ static grpc_event cq_next(grpc_completion_queue* cq, gpr_timespec deadline,
   if (cqd->queue.num_items() > 0 &&
       cqd->pending_events.load(std::memory_order_acquire) > 0) {
     gpr_mu_lock(cq->mu);
-    cq->poller_vtable->kick(POLLSET_FROM_CQ(cq), nullptr);
+    (void)cq->poller_vtable->kick(POLLSET_FROM_CQ(cq), nullptr);
     gpr_mu_unlock(cq->mu);
   }
 
@@ -1143,7 +1144,7 @@ static void del_plucker(grpc_completion_queue* cq, void* tag,
   for (int i = 0; i < cqd->num_pluckers; i++) {
     if (cqd->pluckers[i].tag == tag && cqd->pluckers[i].worker == worker) {
       cqd->num_pluckers--;
-      GPR_SWAP(plucker, cqd->pluckers[i], cqd->pluckers[cqd->num_pluckers]);
+      std::swap(cqd->pluckers[i], cqd->pluckers[cqd->num_pluckers]);
       return;
     }
   }
index 961de64..3bc610c 100644 (file)
@@ -48,7 +48,6 @@
 #include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/surface/api_trace.h"
 #include "src/core/lib/surface/call.h"
-#include "src/core/lib/surface/channel_init.h"
 #include "src/core/lib/surface/completion_queue.h"
 #include "src/core/lib/surface/lame_client.h"
 #include "src/core/lib/surface/server.h"
@@ -77,34 +76,6 @@ static void do_basic_init(void) {
   gpr_time_init();
 }
 
-static bool append_filter(grpc_channel_stack_builder* builder, void* arg) {
-  return grpc_channel_stack_builder_append_filter(
-      builder, static_cast<const grpc_channel_filter*>(arg), nullptr, nullptr);
-}
-
-static bool prepend_filter(grpc_channel_stack_builder* builder, void* arg) {
-  return grpc_channel_stack_builder_prepend_filter(
-      builder, static_cast<const grpc_channel_filter*>(arg), nullptr, nullptr);
-}
-
-static void register_builtin_channel_init() {
-  grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL,
-                                   GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
-                                   grpc_add_connected_filter, nullptr);
-  grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL,
-                                   GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
-                                   grpc_add_connected_filter, nullptr);
-  grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL,
-                                   GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
-                                   grpc_add_connected_filter, nullptr);
-  grpc_channel_init_register_stage(
-      GRPC_CLIENT_LAME_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
-      append_filter, const_cast<grpc_channel_filter*>(&grpc_lame_filter));
-  grpc_channel_init_register_stage(
-      GRPC_SERVER_CHANNEL, INT_MAX, prepend_filter,
-      const_cast<grpc_channel_filter*>(&grpc_core::Server::kServerTopFilter));
-}
-
 typedef struct grpc_plugin {
   void (*init)();
   void (*destroy)();
@@ -134,10 +105,8 @@ void grpc_init(void) {
     grpc_core::Fork::GlobalInit();
     grpc_fork_handlers_auto_register();
     grpc_stats_init();
-    grpc_init_static_metadata_ctx();
     grpc_slice_intern_init();
     grpc_mdctx_global_init();
-    grpc_channel_init_init();
     grpc_core::channelz::ChannelzRegistry::Init();
     grpc_security_pre_init();
     grpc_core::ApplicationCallbackExecCtx::GlobalInit();
@@ -149,13 +118,7 @@ void grpc_init(void) {
         g_all_of_the_plugins[i].init();
       }
     }
-    /* register channel finalization AFTER all plugins, to ensure that it's run
-     * at the appropriate time */
-    grpc_register_security_filters();
-    register_builtin_channel_init();
     grpc_tracer_init();
-    /* no more changes to channel init pipelines */
-    grpc_channel_init_finalize();
     grpc_iomgr_start();
   }
 
@@ -189,8 +152,6 @@ void grpc_shutdown_internal_locked(void)
   grpc_core::ApplicationCallbackExecCtx::GlobalShutdown();
   g_shutting_down = false;
   g_shutting_down_cv->SignalAll();
-  // Absolute last action will be to delete static metadata context.
-  grpc_destroy_static_metadata_ctx();
 }
 
 void grpc_shutdown_internal(void* /*ignored*/) {
index 0db0ebc..cd336fd 100644 (file)
@@ -21,6 +21,8 @@
 #include <limits.h>
 #include <string.h>
 
+#include "src/core/lib/channel/channel_stack_builder.h"
+#include "src/core/lib/config/core_configuration.h"
 #include "src/core/lib/debug/trace.h"
 #include "src/core/lib/security/authorization/sdk_server_authz_filter.h"
 #include "src/core/lib/security/context/security_context.h"
 #include "src/core/lib/security/transport/auth_filters.h"
 #include "src/core/lib/security/transport/secure_endpoint.h"
 #include "src/core/lib/security/transport/security_handshaker.h"
-#include "src/core/lib/surface/channel_init.h"
 #include "src/core/lib/surface/init.h"
 #include "src/core/tsi/transport_security_interface.h"
 
 void grpc_security_pre_init(void) {}
 
 static bool maybe_prepend_client_auth_filter(
-    grpc_channel_stack_builder* builder, void* /*arg*/) {
+    grpc_channel_stack_builder* builder) {
   const grpc_channel_args* args =
       grpc_channel_stack_builder_get_channel_arguments(builder);
   if (args) {
@@ -52,7 +53,7 @@ static bool maybe_prepend_client_auth_filter(
 }
 
 static bool maybe_prepend_server_auth_filter(
-    grpc_channel_stack_builder* builder, void* /*arg*/) {
+    grpc_channel_stack_builder* builder) {
   const grpc_channel_args* args =
       grpc_channel_stack_builder_get_channel_arguments(builder);
   if (args) {
@@ -67,7 +68,7 @@ static bool maybe_prepend_server_auth_filter(
 }
 
 static bool maybe_prepend_sdk_server_authz_filter(
-    grpc_channel_stack_builder* builder, void* /*arg*/) {
+    grpc_channel_stack_builder* builder) {
   const grpc_channel_args* args =
       grpc_channel_stack_builder_get_channel_arguments(builder);
   const auto* provider =
@@ -81,20 +82,22 @@ static bool maybe_prepend_sdk_server_authz_filter(
   return true;
 }
 
-void grpc_register_security_filters(void) {
+namespace grpc_core {
+void RegisterSecurityFilters(CoreConfiguration::Builder* builder) {
   // Register the auth client with a priority < INT_MAX to allow the authority
   // filter -on which the auth filter depends- to be higher on the channel
   // stack.
-  grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL, INT_MAX - 1,
-                                   maybe_prepend_client_auth_filter, nullptr);
-  grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL, INT_MAX - 1,
-                                   maybe_prepend_client_auth_filter, nullptr);
-  grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX - 1,
-                                   maybe_prepend_server_auth_filter, nullptr);
+  builder->channel_init()->RegisterStage(GRPC_CLIENT_SUBCHANNEL, INT_MAX - 1,
+                                         maybe_prepend_client_auth_filter);
+  builder->channel_init()->RegisterStage(GRPC_CLIENT_DIRECT_CHANNEL,
+                                         INT_MAX - 1,
+                                         maybe_prepend_client_auth_filter);
+  builder->channel_init()->RegisterStage(GRPC_SERVER_CHANNEL, INT_MAX - 1,
+                                         maybe_prepend_server_auth_filter);
   // Register the SdkServerAuthzFilter with a priority less than
   // server_auth_filter to allow server_auth_filter on which the sdk filter
   // depends on to be higher on the channel stack.
-  grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX - 2,
-                                   maybe_prepend_sdk_server_authz_filter,
-                                   nullptr);
+  builder->channel_init()->RegisterStage(GRPC_SERVER_CHANNEL, INT_MAX - 2,
+                                         maybe_prepend_sdk_server_authz_filter);
 }
+}  // namespace grpc_core
index 65843e0..a1fbd06 100644 (file)
@@ -45,9 +45,9 @@ namespace {
 struct ChannelData {
   explicit ChannelData(grpc_channel_element_args* args)
       : state_tracker("lame_channel", GRPC_CHANNEL_SHUTDOWN) {
-    grpc_error_handle err = grpc_channel_args_find_pointer<grpc_error>(
+    grpc_error_handle* err = grpc_channel_args_find_pointer<grpc_error_handle>(
         args->channel_args, GRPC_ARG_LAME_FILTER_ERROR);
-    if (err != nullptr) error = GRPC_ERROR_REF(err);
+    if (err != nullptr) error = GRPC_ERROR_REF(*err);
   }
 
   ~ChannelData() { GRPC_ERROR_UNREF(error); }
@@ -125,20 +125,28 @@ static void lame_destroy_channel_elem(grpc_channel_element* elem) {
 
 // Channel arg vtable for a grpc_error_handle.
 void* ErrorCopy(void* p) {
-  grpc_error_handle error = static_cast<grpc_error_handle>(p);
-  return GRPC_ERROR_REF(error);
+  grpc_error_handle* new_error = nullptr;
+  if (p != nullptr) {
+    grpc_error_handle* error = static_cast<grpc_error_handle*>(p);
+    new_error = new grpc_error_handle();
+    *new_error = GRPC_ERROR_REF(*error);
+  }
+  return new_error;
 }
 void ErrorDestroy(void* p) {
-  grpc_error_handle error = static_cast<grpc_error_handle>(p);
-  GRPC_ERROR_UNREF(error);
+  if (p != nullptr) {
+    grpc_error_handle* error = static_cast<grpc_error_handle*>(p);
+    GRPC_ERROR_UNREF(*error);
+    delete error;
+  }
 }
-int ErrorCompare(void* p, void* q) { return GPR_ICMP(p, q); }
+int ErrorCompare(void* p, void* q) { return grpc_core::QsortCompare(p, q); }
 const grpc_arg_pointer_vtable kLameFilterErrorArgVtable = {
     ErrorCopy, ErrorDestroy, ErrorCompare};
 
 }  // namespace
 
-grpc_arg MakeLameClientErrorArg(grpc_error_handle error) {
+grpc_arg MakeLameClientErrorArg(grpc_error_handle* error) {
   return grpc_channel_arg_pointer_create(
       const_cast<char*>(GRPC_ARG_LAME_FILTER_ERROR), error,
       &kLameFilterErrorArgVtable);
@@ -174,9 +182,8 @@ grpc_channel* grpc_lame_client_channel_create(const char* target,
       grpc_error_set_int(
           GRPC_ERROR_CREATE_FROM_STATIC_STRING("lame client channel"),
           GRPC_ERROR_INT_GRPC_STATUS, error_code),
-      GRPC_ERROR_STR_GRPC_MESSAGE,
-      grpc_slice_from_static_string(error_message));
-  grpc_arg error_arg = grpc_core::MakeLameClientErrorArg(error);
+      GRPC_ERROR_STR_GRPC_MESSAGE, error_message);
+  grpc_arg error_arg = grpc_core::MakeLameClientErrorArg(&error);
   grpc_channel_args args = {1, &error_arg};
   grpc_channel* channel = grpc_channel_create(
       target, &args, GRPC_CLIENT_LAME_CHANNEL, nullptr, nullptr, 0, nullptr);
index 41759cb..6c9d145 100644 (file)
@@ -25,7 +25,7 @@
 
 namespace grpc_core {
 // Does NOT take ownership of error.
-grpc_arg MakeLameClientErrorArg(grpc_error_handle error);
+grpc_arg MakeLameClientErrorArg(grpc_error_handle* error);
 }  // namespace grpc_core
 
 extern const grpc_channel_filter grpc_lame_filter;
index 6c5f713..5f85523 100644 (file)
@@ -794,6 +794,7 @@ void DonePublishedShutdown(void* /*done_arg*/, grpc_cq_completion* storage) {
 //       connection is NOT closed until the server is done with all those calls.
 //    -- Once there are no more calls in progress, the channel is closed.
 void Server::ShutdownAndNotify(grpc_completion_queue* cq, void* tag) {
+  absl::Notification* await_requests = nullptr;
   ChannelBroadcaster broadcaster;
   {
     // Wait for startup to be finished.  Locks mu_global.
@@ -820,7 +821,12 @@ void Server::ShutdownAndNotify(grpc_completion_queue* cq, void* tag) {
       KillPendingWorkLocked(
           GRPC_ERROR_CREATE_FROM_STATIC_STRING("Server Shutdown"));
     }
-    ShutdownUnrefOnShutdownCall();
+    await_requests = ShutdownUnrefOnShutdownCall();
+  }
+  // We expect no new requests but there can still be requests in-flight.
+  // Wait for them to complete before proceeding.
+  if (await_requests != nullptr) {
+    await_requests->WaitForNotification();
   }
   // Shutdown listeners.
   for (auto& listener : listeners_) {
@@ -1248,7 +1254,7 @@ void Server::CallData::Publish(size_t cq_idx, RequestedCall* rc) {
   grpc_call_set_completion_queue(call_, rc->cq_bound_to_call);
   *rc->call = call_;
   cq_new_ = server_->cqs_[cq_idx];
-  GPR_SWAP(grpc_metadata_array, *rc->initial_metadata, initial_metadata_);
+  std::swap(*rc->initial_metadata, initial_metadata_);
   switch (rc->type) {
     case RequestedCall::Type::BATCH_CALL:
       GPR_ASSERT(host_.has_value());
@@ -1379,24 +1385,24 @@ void Server::CallData::RecvInitialMetadataReady(void* arg,
                                                 grpc_error_handle error) {
   grpc_call_element* elem = static_cast<grpc_call_element*>(arg);
   CallData* calld = static_cast<CallData*>(elem->call_data);
-  grpc_millis op_deadline;
   if (error == GRPC_ERROR_NONE) {
-    GPR_DEBUG_ASSERT(calld->recv_initial_metadata_->idx.named.path != nullptr);
-    GPR_DEBUG_ASSERT(calld->recv_initial_metadata_->idx.named.authority !=
-                     nullptr);
-    calld->path_.emplace(grpc_slice_ref_internal(
-        GRPC_MDVALUE(calld->recv_initial_metadata_->idx.named.path->md)));
-    calld->host_.emplace(grpc_slice_ref_internal(
-        GRPC_MDVALUE(calld->recv_initial_metadata_->idx.named.authority->md)));
-    grpc_metadata_batch_remove(calld->recv_initial_metadata_, GRPC_BATCH_PATH);
-    grpc_metadata_batch_remove(calld->recv_initial_metadata_,
-                               GRPC_BATCH_AUTHORITY);
+    GPR_DEBUG_ASSERT(
+        calld->recv_initial_metadata_->legacy_index()->named.path != nullptr);
+    GPR_DEBUG_ASSERT(
+        calld->recv_initial_metadata_->legacy_index()->named.authority !=
+        nullptr);
+    calld->path_.emplace(grpc_slice_ref_internal(GRPC_MDVALUE(
+        calld->recv_initial_metadata_->legacy_index()->named.path->md)));
+    calld->host_.emplace(grpc_slice_ref_internal(GRPC_MDVALUE(
+        calld->recv_initial_metadata_->legacy_index()->named.authority->md)));
+    calld->recv_initial_metadata_->Remove(GRPC_BATCH_PATH);
+    calld->recv_initial_metadata_->Remove(GRPC_BATCH_AUTHORITY);
   } else {
-    GRPC_ERROR_REF(error);
+    (void)GRPC_ERROR_REF(error);
   }
-  op_deadline = calld->recv_initial_metadata_->deadline;
-  if (op_deadline != GRPC_MILLIS_INF_FUTURE) {
-    calld->deadline_ = op_deadline;
+  auto op_deadline = calld->recv_initial_metadata_->get(GrpcTimeoutMetadata());
+  if (op_deadline.has_value()) {
+    calld->deadline_ = *op_deadline;
   }
   if (calld->host_.has_value() && calld->path_.has_value()) {
     /* do nothing */
@@ -1469,9 +1475,11 @@ void Server::CallData::StartTransportStreamOpBatch(
 
 grpc_server* grpc_server_create(const grpc_channel_args* args, void* reserved) {
   grpc_core::ExecCtx exec_ctx;
+  args = grpc_channel_args_remove_grpc_internal(args);
   GRPC_API_TRACE("grpc_server_create(%p, %p)", 2, (args, reserved));
   grpc_server* c_server = new grpc_server;
   c_server->core_server = grpc_core::MakeOrphanable<grpc_core::Server>(args);
+  grpc_channel_args_destroy(args);
   return c_server;
 }
 
index ab41300..3e1a4a9 100644 (file)
@@ -24,6 +24,7 @@
 #include <vector>
 
 #include "absl/status/statusor.h"
+#include "absl/synchronization/notification.h"
 #include "absl/types/optional.h"
 
 #include <grpc/grpc.h>
@@ -364,7 +365,7 @@ class Server : public InternallyRefCounted<Server> {
   std::vector<grpc_channel*> GetChannelsLocked() const;
 
   // Take a shutdown ref for a request (increment by 2) and return if shutdown
-  // has already been called.
+  // has not been called.
   bool ShutdownRefOnRequest() {
     int old_value = shutdown_refs_.fetch_add(2, std::memory_order_acq_rel);
     return (old_value & 1) != 0;
@@ -377,12 +378,24 @@ class Server : public InternallyRefCounted<Server> {
     if (shutdown_refs_.fetch_sub(2, std::memory_order_acq_rel) == 2) {
       MutexLock lock(&mu_global_);
       MaybeFinishShutdown();
+      // The last request in-flight during shutdown is now complete.
+      if (requests_complete_ != nullptr) {
+        GPR_ASSERT(!requests_complete_->HasBeenNotified());
+        requests_complete_->Notify();
+      }
     }
   }
-  void ShutdownUnrefOnShutdownCall() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_global_) {
+  // Returns a notification pointer to wait on if there are requests in-flight,
+  // or null.
+  absl::Notification* ShutdownUnrefOnShutdownCall()
+      ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_global_) GRPC_MUST_USE_RESULT {
     if (shutdown_refs_.fetch_sub(1, std::memory_order_acq_rel) == 1) {
+      // There is no request in-flight.
       MaybeFinishShutdown();
+      return nullptr;
     }
+    requests_complete_ = absl::make_unique<absl::Notification>();
+    return requests_complete_.get();
   }
 
   bool ShutdownCalled() const {
@@ -433,6 +446,8 @@ class Server : public InternallyRefCounted<Server> {
   std::atomic<int> shutdown_refs_{1};
   bool shutdown_published_ ABSL_GUARDED_BY(mu_global_) = false;
   std::vector<ShutdownTag> shutdown_tags_ ABSL_GUARDED_BY(mu_global_);
+  std::unique_ptr<absl::Notification> requests_complete_
+      ABSL_GUARDED_BY(mu_global_);
 
   std::list<ChannelData*> channels_;
 
@@ -449,12 +464,6 @@ struct grpc_server {
   grpc_core::OrphanablePtr<grpc_core::Server> core_server;
 };
 
-// TODO(roth): Eventually, will need a way to modify configuration even after
-// a connection is established (e.g., to change things like L7 rate
-// limiting, RBAC, and fault injection configs).  One possible option
-// would be to do something like ServiceConfig and ConfigSelector, but
-// that might add unnecessary per-call overhead.  Need to consider other
-// approaches here.
 struct grpc_server_config_fetcher {
  public:
   class ConnectionManager : public grpc_core::RefCounted<ConnectionManager> {
@@ -479,9 +488,7 @@ struct grpc_server_config_fetcher {
 
   virtual ~grpc_server_config_fetcher() = default;
 
-  // Ownership of \a args is transferred.
   virtual void StartWatch(std::string listening_address,
-                          grpc_channel_args* args,
                           std::unique_ptr<WatcherInterface> watcher) = 0;
   virtual void CancelWatch(WatcherInterface* watcher) = 0;
   virtual grpc_pollset_set* interested_parties() = 0;
index 1f16ec2..077acb1 100644 (file)
@@ -47,12 +47,15 @@ static grpc_error_handle conforms_to(const grpc_slice& slice,
   const uint8_t* e = GRPC_SLICE_END_PTR(slice);
   for (; p != e; p++) {
     if (!legal_bits.is_set(*p)) {
+      size_t len;
+      grpc_core::UniquePtr<char> ptr(gpr_dump_return_len(
+          reinterpret_cast<const char*> GRPC_SLICE_START_PTR(slice),
+          GRPC_SLICE_LENGTH(slice), GPR_DUMP_HEX | GPR_DUMP_ASCII, &len));
       grpc_error_handle error = grpc_error_set_str(
           grpc_error_set_int(GRPC_ERROR_CREATE_FROM_COPIED_STRING(err_desc),
                              GRPC_ERROR_INT_OFFSET,
                              p - GRPC_SLICE_START_PTR(slice)),
-          GRPC_ERROR_STR_RAW_BYTES,
-          grpc_dump_slice_to_slice(slice, GPR_DUMP_HEX | GPR_DUMP_ASCII));
+          GRPC_ERROR_STR_RAW_BYTES, absl::string_view(ptr.get(), len));
       return error;
     }
   }
index 07f1fbc..db7f935 100644 (file)
@@ -23,6 +23,6 @@
 
 #include <grpc/grpc.h>
 
-const char* grpc_version_string(void) { return "19.0.0"; }
+const char* grpc_version_string(void) { return "20.0.0"; }
 
-const char* grpc_g_stands_for(void) { return "goat"; }
+const char* grpc_g_stands_for(void) { return "granola"; }
diff --git a/src/core/lib/transport/authority_override.cc b/src/core/lib/transport/authority_override.cc
deleted file mode 100644 (file)
index 6685072..0000000
+++ /dev/null
@@ -1,40 +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 <grpc/support/port_platform.h>
-
-#include "absl/strings/string_view.h"
-
-#include "src/core/lib/channel/channel_args.h"
-
-// Channel arg key for the authority override.
-#define GRPC_ARG_AUTHORITY_OVERRIDE "grpc.authority_override"
-
-namespace grpc_core {
-
-grpc_arg CreateAuthorityOverrideChannelArg(const char* authority) {
-  return grpc_channel_arg_string_create(
-      const_cast<char*>(GRPC_ARG_AUTHORITY_OVERRIDE),
-      const_cast<char*>(authority));
-}
-
-absl::string_view FindAuthorityOverrideInArgs(const grpc_channel_args* args) {
-  const char* found =
-      grpc_channel_args_find_string(args, GRPC_ARG_AUTHORITY_OVERRIDE);
-  return found == nullptr ? "" : found;
-}
-
-}  // namespace grpc_core
diff --git a/src/core/lib/transport/authority_override.h b/src/core/lib/transport/authority_override.h
deleted file mode 100644 (file)
index 7af6526..0000000
+++ /dev/null
@@ -1,37 +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.
-//
-
-#ifndef GRPC_CORE_LIB_TRANSPORT_AUTHORITY_OVERRIDE_H
-#define GRPC_CORE_LIB_TRANSPORT_AUTHORITY_OVERRIDE_H
-
-#include <grpc/support/port_platform.h>
-
-#include "absl/strings/string_view.h"
-
-#include <grpc/grpc.h>
-
-namespace grpc_core {
-
-/// Returns a channel argument containing \a authority.
-grpc_arg CreateAuthorityOverrideChannelArg(const char* authority);
-
-/// Returns the authority override from \a args or the empty string. The return
-/// value is a string_view into the `args` data structure.
-absl::string_view FindAuthorityOverrideInArgs(const grpc_channel_args* args);
-
-}  // namespace grpc_core
-
-#endif /* GRPC_CORE_LIB_TRANSPORT_AUTHORITY_OVERRIDE_H */
index dd26687..853eca6 100644 (file)
@@ -55,7 +55,7 @@ grpc_millis BdpEstimator::CompletePing() {
   }
   GPR_ASSERT(ping_state_ == PingState::STARTED);
   if (accumulator_ > 2 * estimate_ / 3 && bw > bw_est_) {
-    estimate_ = GPR_MAX(accumulator_, estimate_ * 2);
+    estimate_ = std::max(accumulator_, estimate_ * 2);
     bw_est_ = bw;
     if (GRPC_TRACE_FLAG_ENABLED(grpc_bdp_estimator_trace)) {
       gpr_log(GPR_INFO, "bdp[%s]: estimate increased to %" PRId64, name_,
index a826b91..2d2b67e 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <grpc/support/string_util.h>
 
+#include "src/core/lib/gprpp/status_helper.h"
 #include "src/core/lib/iomgr/error_internal.h"
 #include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/transport/status_conversion.h"
@@ -33,7 +34,14 @@ static grpc_error_handle recursively_find_error_with_field(
   if (grpc_error_get_int(error, which, &unused)) {
     return error;
   }
-  if (grpc_error_is_special(error)) return nullptr;
+#ifdef GRPC_ERROR_IS_ABSEIL_STATUS
+  std::vector<absl::Status> children = grpc_core::StatusGetChildren(error);
+  for (const absl::Status& child : children) {
+    grpc_error_handle result = recursively_find_error_with_field(child, which);
+    if (result != GRPC_ERROR_NONE) return result;
+  }
+#else
+  if (grpc_error_is_special(error)) return GRPC_ERROR_NONE;
   // Otherwise, search through its children.
   uint8_t slot = error->first_err;
   while (slot != UINT8_MAX) {
@@ -44,26 +52,27 @@ static grpc_error_handle recursively_find_error_with_field(
     if (result) return result;
     slot = lerr->next;
   }
-  return nullptr;
+#endif
+  return GRPC_ERROR_NONE;
 }
 
 void grpc_error_get_status(grpc_error_handle error, grpc_millis deadline,
-                           grpc_status_code* code, grpc_slice* slice,
+                           grpc_status_code* code, std::string* message,
                            grpc_http2_error_code* http_error,
                            const char** error_string) {
   // Fast path: We expect no error.
   if (GPR_LIKELY(error == GRPC_ERROR_NONE)) {
     if (code != nullptr) *code = GRPC_STATUS_OK;
-    if (slice != nullptr) {
+    if (message != nullptr) {
       // Normally, we call grpc_error_get_str(
-      //   error, GRPC_ERROR_STR_GRPC_MESSAGE, slice).
+      //   error, GRPC_ERROR_STR_GRPC_MESSAGE, message).
       // We can fastpath since we know that:
       // 1) Error is null
       // 2) which == GRPC_ERROR_STR_GRPC_MESSAGE
-      // 3) The resulting slice is statically known.
-      // 4) Said resulting slice is of length 0 ("").
+      // 3) The resulting message is statically known.
+      // 4) Said resulting message is "".
       // This means 3 movs, instead of 10s of instructions and a strlen.
-      *slice = grpc_core::ExternallyManagedSlice("");
+      *message = "";
     }
     if (http_error != nullptr) {
       *http_error = GRPC_HTTP2_NO_ERROR;
@@ -94,6 +103,10 @@ void grpc_error_get_status(grpc_error_handle error, grpc_millis deadline,
                                 &integer)) {
     status = grpc_http2_error_to_grpc_status(
         static_cast<grpc_http2_error_code>(integer), deadline);
+  } else {
+#ifdef GRPC_ERROR_IS_ABSEIL_STATUS
+    status = static_cast<grpc_status_code>(found_error.code());
+#endif
   }
   if (code != nullptr) *code = status;
 
@@ -116,10 +129,16 @@ void grpc_error_get_status(grpc_error_handle error, grpc_millis deadline,
 
   // If the error has a status message, use it.  Otherwise, fall back to
   // the error description.
-  if (slice != nullptr) {
-    if (!grpc_error_get_str(found_error, GRPC_ERROR_STR_GRPC_MESSAGE, slice)) {
-      if (!grpc_error_get_str(found_error, GRPC_ERROR_STR_DESCRIPTION, slice)) {
-        *slice = grpc_slice_from_static_string("unknown error");
+  if (message != nullptr) {
+    if (!grpc_error_get_str(found_error, GRPC_ERROR_STR_GRPC_MESSAGE,
+                            message)) {
+      if (!grpc_error_get_str(found_error, GRPC_ERROR_STR_DESCRIPTION,
+                              message)) {
+#ifdef GRPC_ERROR_IS_ABSEIL_STATUS
+        *message = grpc_error_std_string(error);
+#else
+        *message = "unknown error";
+#endif
       }
     }
   }
@@ -129,13 +148,10 @@ absl::Status grpc_error_to_absl_status(grpc_error_handle error) {
   grpc_status_code status;
   // TODO(yashykt): This should be updated once we decide on how to use the
   // absl::Status payload to capture all the contents of grpc_error.
-  grpc_slice message;
+  std::string message;
   grpc_error_get_status(error, GRPC_MILLIS_INF_FUTURE, &status, &message,
                         nullptr /* http_error */, nullptr /* error_string */);
-  return absl::Status(static_cast<absl::StatusCode>(status),
-                      absl::string_view(reinterpret_cast<const char*>(
-                                            GRPC_SLICE_START_PTR(message)),
-                                        GRPC_SLICE_LENGTH(message)));
+  return absl::Status(static_cast<absl::StatusCode>(status), message);
 }
 
 grpc_error_handle absl_status_to_grpc_error(absl::Status status) {
@@ -153,6 +169,14 @@ bool grpc_error_has_clear_grpc_status(grpc_error_handle error) {
   if (grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, &unused)) {
     return true;
   }
+#ifdef GRPC_ERROR_IS_ABSEIL_STATUS
+  std::vector<absl::Status> children = grpc_core::StatusGetChildren(error);
+  for (const absl::Status& child : children) {
+    if (grpc_error_has_clear_grpc_status(child)) {
+      return true;
+    }
+  }
+#else
   uint8_t slot = error->first_err;
   while (slot != UINT8_MAX) {
     grpc_linked_error* lerr =
@@ -162,5 +186,6 @@ bool grpc_error_has_clear_grpc_status(grpc_error_handle error) {
     }
     slot = lerr->next;
   }
+#endif
   return false;
 }
index 777e632..4cc2db6 100644 (file)
@@ -35,7 +35,7 @@
 /// msg, http_status, error_string) are unneeded, they can be passed as
 /// NULL.
 void grpc_error_get_status(grpc_error_handle error, grpc_millis deadline,
-                           grpc_status_code* code, grpc_slice* slice,
+                           grpc_status_code* code, std::string* message,
                            grpc_http2_error_code* http_error,
                            const char** error_string);
 
index 5b19eb8..004e44a 100644 (file)
@@ -279,9 +279,9 @@ void grpc_mdctx_global_shutdown() {
 #ifndef NDEBUG
 static int is_mdelem_static(grpc_mdelem e) {
   return reinterpret_cast<grpc_core::StaticMetadata*>(GRPC_MDELEM_DATA(e)) >=
-             &grpc_static_mdelem_table()[0] &&
+             &grpc_core::g_static_mdelem_table[0] &&
          reinterpret_cast<grpc_core::StaticMetadata*>(GRPC_MDELEM_DATA(e)) <
-             &grpc_static_mdelem_table()[GRPC_STATIC_MDELEM_COUNT];
+             &grpc_core::g_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT];
 }
 #endif
 
@@ -549,14 +549,35 @@ grpc_mdelem grpc_mdelem_from_slices(
 }
 
 grpc_mdelem grpc_mdelem_from_grpc_metadata(grpc_metadata* metadata) {
-  bool changed = false;
+  bool key_changed = false;
   grpc_slice key_slice =
-      grpc_slice_maybe_static_intern(metadata->key, &changed);
+      grpc_slice_maybe_static_intern(metadata->key, &key_changed);
+  bool value_changed = false;
+  grpc_slice* unref_slice = nullptr;
   grpc_slice value_slice =
-      grpc_slice_maybe_static_intern(metadata->value, &changed);
-  return grpc_mdelem_create(
-      key_slice, value_slice,
-      changed ? nullptr : reinterpret_cast<grpc_mdelem_data*>(metadata));
+      grpc_slice_maybe_static_intern(metadata->value, &value_changed);
+  // If key or value changed, but the other didn't.... AND the other is a NOP
+  // refcount, then we need to convert it to a slice with a refcount else we run
+  // the risk of leaving a dangling reference to that metadata on the heap via
+  // this mdelem.
+  if (key_changed && !value_changed && value_slice.refcount != nullptr &&
+      value_slice.refcount->GetType() == grpc_slice_refcount::Type::NOP) {
+    value_slice = grpc_slice_copy(value_slice);
+    unref_slice = &value_slice;
+    value_changed = true;
+  } else if (!key_changed && value_changed && key_slice.refcount != nullptr &&
+             key_slice.refcount->GetType() == grpc_slice_refcount::Type::NOP) {
+    key_slice = grpc_slice_copy(key_slice);
+    unref_slice = &key_slice;
+    key_changed = true;
+  }
+  auto mdelem =
+      grpc_mdelem_create(key_slice, value_slice,
+                         key_changed || value_changed
+                             ? nullptr
+                             : reinterpret_cast<grpc_mdelem_data*>(metadata));
+  if (unref_slice != nullptr) grpc_slice_unref_internal(*unref_slice);
+  return mdelem;
 }
 
 static void* get_user_data(UserData* user_data, void (*destroy_func)(void*)) {
@@ -577,7 +598,7 @@ void* grpc_mdelem_get_user_data(grpc_mdelem md, void (*destroy_func)(void*)) {
           grpc_static_mdelem_user_data
               [reinterpret_cast<grpc_core::StaticMetadata*>(
                    GRPC_MDELEM_DATA(md)) -
-               grpc_static_mdelem_table()]);
+               grpc_core::g_static_mdelem_table]);
     case GRPC_MDELEM_STORAGE_ALLOCATED: {
       auto* am = reinterpret_cast<AllocatedMetadata*>(GRPC_MDELEM_DATA(md));
       return get_user_data(am->user_data(), destroy_func);
@@ -619,7 +640,7 @@ void* grpc_mdelem_set_user_data(grpc_mdelem md, void (*destroy_func)(void*),
           grpc_static_mdelem_user_data
               [reinterpret_cast<grpc_core::StaticMetadata*>(
                    GRPC_MDELEM_DATA(md)) -
-               grpc_static_mdelem_table()]);
+               grpc_core::g_static_mdelem_table]);
     case GRPC_MDELEM_STORAGE_ALLOCATED: {
       auto* am = reinterpret_cast<AllocatedMetadata*>(GRPC_MDELEM_DATA(md));
       return set_user_data(am->user_data(), destroy_func, data);
index 5d83cbb..43e1827 100644 (file)
@@ -409,7 +409,8 @@ inline void grpc_mdelem_unref(grpc_mdelem gmd) {
   (GRPC_SLICE_LENGTH(GRPC_MDKEY((e))) + GRPC_SLICE_LENGTH(GRPC_MDVALUE((e))) + \
    32)
 
-#define GRPC_MDSTR_KV_HASH(k_hash, v_hash) (GPR_ROTL((k_hash), 2) ^ (v_hash))
+#define GRPC_MDSTR_KV_HASH(k_hash, v_hash) \
+  (::grpc_core::RotateLeft(size_t(k_hash), size_t(2)) ^ (v_hash))
 
 void grpc_mdctx_global_init(void);
 void grpc_mdctx_global_shutdown();
index 8207fb5..c651faa 100644 (file)
@@ -24,7 +24,6 @@
 #include <string.h>
 
 #include "absl/container/inlined_vector.h"
-#include "absl/strings/str_join.h"
 
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/slice/slice_string_helpers.h"
 
-static void assert_valid_list(grpc_mdelem_list* list) {
-#ifndef NDEBUG
-  grpc_linked_mdelem* l;
-
-  GPR_ASSERT((list->head == nullptr) == (list->tail == nullptr));
-  if (!list->head) return;
-  GPR_ASSERT(list->head->prev == nullptr);
-  GPR_ASSERT(list->tail->next == nullptr);
-  GPR_ASSERT((list->head == list->tail) == (list->head->next == nullptr));
-
-  size_t verified_count = 0;
-  for (l = list->head; l; l = l->next) {
-    GPR_ASSERT(!GRPC_MDISNULL(l->md));
-    GPR_ASSERT((l->prev == nullptr) == (l == list->head));
-    GPR_ASSERT((l->next == nullptr) == (l == list->tail));
-    if (l->next) GPR_ASSERT(l->next->prev == l);
-    if (l->prev) GPR_ASSERT(l->prev->next == l);
-    verified_count++;
-  }
-  GPR_ASSERT(list->count == verified_count);
-#else
-  // Avoid unused-parameter warning for debug-only parameter
-  (void)list;
-#endif /* NDEBUG */
-}
-
-static void assert_valid_callouts(grpc_metadata_batch* batch) {
-#ifndef NDEBUG
-  for (grpc_linked_mdelem* l = batch->list.head; l != nullptr; l = l->next) {
-    grpc_slice key_interned = grpc_slice_intern(GRPC_MDKEY(l->md));
-    grpc_metadata_batch_callouts_index callout_idx =
-        GRPC_BATCH_INDEX_OF(key_interned);
-    if (callout_idx != GRPC_BATCH_CALLOUTS_COUNT) {
-      GPR_ASSERT(batch->idx.array[callout_idx] == l);
-    }
-    grpc_slice_unref_internal(key_interned);
-  }
-#else
-  // Avoid unused-parameter warning for debug-only parameter
-  (void)batch;
-#endif
-}
-
-#ifndef NDEBUG
-void grpc_metadata_batch_assert_ok(grpc_metadata_batch* batch) {
-  assert_valid_list(&batch->list);
-}
-#endif /* NDEBUG */
-
-void grpc_metadata_batch_init(grpc_metadata_batch* batch) {
-  memset(batch, 0, sizeof(*batch));
-  batch->deadline = GRPC_MILLIS_INF_FUTURE;
-}
-
-void grpc_metadata_batch_destroy(grpc_metadata_batch* batch) {
-  grpc_linked_mdelem* l;
-  for (l = batch->list.head; l; l = l->next) {
-    GRPC_MDELEM_UNREF(l->md);
-  }
-}
-
-grpc_error_handle grpc_attach_md_to_error(grpc_error_handle src,
-                                          grpc_mdelem md) {
-  grpc_error_handle out = grpc_error_set_str(
-      grpc_error_set_str(src, GRPC_ERROR_STR_KEY,
-                         grpc_slice_ref_internal(GRPC_MDKEY(md))),
-      GRPC_ERROR_STR_VALUE, grpc_slice_ref_internal(GRPC_MDVALUE(md)));
-  return out;
-}
-
-static grpc_error_handle GPR_ATTRIBUTE_NOINLINE error_with_md(grpc_mdelem md) {
-  return grpc_attach_md_to_error(
-      GRPC_ERROR_CREATE_FROM_STATIC_STRING("Unallowed duplicate metadata"), md);
-}
-
-static grpc_error_handle link_callout(grpc_metadata_batch* batch,
-                                      grpc_linked_mdelem* storage,
-                                      grpc_metadata_batch_callouts_index idx) {
-  GPR_DEBUG_ASSERT(idx >= 0 && idx < GRPC_BATCH_CALLOUTS_COUNT);
-  if (GPR_LIKELY(batch->idx.array[idx] == nullptr)) {
-    ++batch->list.default_count;
-    batch->idx.array[idx] = storage;
-    return GRPC_ERROR_NONE;
-  }
-  return error_with_md(storage->md);
-}
-
-static grpc_error_handle maybe_link_callout(grpc_metadata_batch* batch,
-                                            grpc_linked_mdelem* storage)
-    GRPC_MUST_USE_RESULT;
-
-static grpc_error_handle maybe_link_callout(grpc_metadata_batch* batch,
-                                            grpc_linked_mdelem* storage) {
-  grpc_metadata_batch_callouts_index idx =
-      GRPC_BATCH_INDEX_OF(GRPC_MDKEY(storage->md));
-  if (idx == GRPC_BATCH_CALLOUTS_COUNT) {
-    return GRPC_ERROR_NONE;
-  }
-  return link_callout(batch, storage, idx);
-}
-
-static void maybe_unlink_callout(grpc_metadata_batch* batch,
-                                 grpc_linked_mdelem* storage) {
-  grpc_metadata_batch_callouts_index idx =
-      GRPC_BATCH_INDEX_OF(GRPC_MDKEY(storage->md));
-  if (idx == GRPC_BATCH_CALLOUTS_COUNT) {
-    return;
-  }
-  --batch->list.default_count;
-  GPR_DEBUG_ASSERT(batch->idx.array[idx] != nullptr);
-  batch->idx.array[idx] = nullptr;
-}
-
-grpc_error_handle grpc_metadata_batch_add_head(grpc_metadata_batch* batch,
-                                               grpc_linked_mdelem* storage,
-                                               grpc_mdelem elem_to_add) {
-  GPR_DEBUG_ASSERT(!GRPC_MDISNULL(elem_to_add));
-  storage->md = elem_to_add;
-  return grpc_metadata_batch_link_head(batch, storage);
-}
-
-static void link_head(grpc_mdelem_list* list, grpc_linked_mdelem* storage) {
-  assert_valid_list(list);
-  GPR_DEBUG_ASSERT(!GRPC_MDISNULL(storage->md));
-  storage->prev = nullptr;
-  storage->next = list->head;
-  storage->reserved = nullptr;
-  if (list->head != nullptr) {
-    list->head->prev = storage;
-  } else {
-    list->tail = storage;
-  }
-  list->head = storage;
-  list->count++;
-  assert_valid_list(list);
-}
-
-grpc_error_handle grpc_metadata_batch_link_head(grpc_metadata_batch* batch,
-                                                grpc_linked_mdelem* storage) {
-  assert_valid_callouts(batch);
-  grpc_error_handle err = maybe_link_callout(batch, storage);
-  if (err != GRPC_ERROR_NONE) {
-    assert_valid_callouts(batch);
-    return err;
-  }
-  link_head(&batch->list, storage);
-  assert_valid_callouts(batch);
-  return GRPC_ERROR_NONE;
-}
-
-// TODO(arjunroy): Need to revisit this and see what guarantees exist between
-// C-core and the internal-metadata subsystem. E.g. can we ensure a particular
-// metadata is never added twice, even in the presence of user supplied data?
-grpc_error_handle grpc_metadata_batch_link_head(
-    grpc_metadata_batch* batch, grpc_linked_mdelem* storage,
-    grpc_metadata_batch_callouts_index idx) {
-  GPR_DEBUG_ASSERT(GRPC_BATCH_INDEX_OF(GRPC_MDKEY(storage->md)) == idx);
-  assert_valid_callouts(batch);
-  grpc_error_handle err = link_callout(batch, storage, idx);
-  if (GPR_UNLIKELY(err != GRPC_ERROR_NONE)) {
-    assert_valid_callouts(batch);
-    return err;
-  }
-  link_head(&batch->list, storage);
-  assert_valid_callouts(batch);
-  return GRPC_ERROR_NONE;
-}
-
-grpc_error_handle grpc_metadata_batch_add_tail(grpc_metadata_batch* batch,
-                                               grpc_linked_mdelem* storage,
-                                               grpc_mdelem elem_to_add) {
-  GPR_DEBUG_ASSERT(!GRPC_MDISNULL(elem_to_add));
-  storage->md = elem_to_add;
-  return grpc_metadata_batch_link_tail(batch, storage);
-}
-
-static void link_tail(grpc_mdelem_list* list, grpc_linked_mdelem* storage) {
-  assert_valid_list(list);
-  GPR_DEBUG_ASSERT(!GRPC_MDISNULL(storage->md));
-  storage->prev = list->tail;
-  storage->next = nullptr;
-  storage->reserved = nullptr;
-  if (list->tail != nullptr) {
-    list->tail->next = storage;
-  } else {
-    list->head = storage;
-  }
-  list->tail = storage;
-  list->count++;
-  assert_valid_list(list);
-}
-
-grpc_error_handle grpc_metadata_batch_link_tail(grpc_metadata_batch* batch,
-                                                grpc_linked_mdelem* storage) {
-  assert_valid_callouts(batch);
-  grpc_error_handle err = maybe_link_callout(batch, storage);
-  if (err != GRPC_ERROR_NONE) {
-    assert_valid_callouts(batch);
-    return err;
-  }
-  link_tail(&batch->list, storage);
-  assert_valid_callouts(batch);
-  return GRPC_ERROR_NONE;
-}
-
-grpc_error_handle grpc_metadata_batch_link_tail(
-    grpc_metadata_batch* batch, grpc_linked_mdelem* storage,
-    grpc_metadata_batch_callouts_index idx) {
-  GPR_DEBUG_ASSERT(GRPC_BATCH_INDEX_OF(GRPC_MDKEY(storage->md)) == idx);
-  assert_valid_callouts(batch);
-  grpc_error_handle err = link_callout(batch, storage, idx);
-  if (GPR_UNLIKELY(err != GRPC_ERROR_NONE)) {
-    assert_valid_callouts(batch);
-    return err;
-  }
-  link_tail(&batch->list, storage);
-  assert_valid_callouts(batch);
-  return GRPC_ERROR_NONE;
-}
-
-static void unlink_storage(grpc_mdelem_list* list,
-                           grpc_linked_mdelem* storage) {
-  assert_valid_list(list);
-  if (storage->prev != nullptr) {
-    storage->prev->next = storage->next;
-  } else {
-    list->head = storage->next;
-  }
-  if (storage->next != nullptr) {
-    storage->next->prev = storage->prev;
-  } else {
-    list->tail = storage->prev;
-  }
-  list->count--;
-  assert_valid_list(list);
-}
-
-void grpc_metadata_batch_remove(grpc_metadata_batch* batch,
-                                grpc_linked_mdelem* storage) {
-  assert_valid_callouts(batch);
-  maybe_unlink_callout(batch, storage);
-  unlink_storage(&batch->list, storage);
-  GRPC_MDELEM_UNREF(storage->md);
-  assert_valid_callouts(batch);
-}
-
-void grpc_metadata_batch_remove(grpc_metadata_batch* batch,
-                                grpc_metadata_batch_callouts_index idx) {
-  assert_valid_callouts(batch);
-  grpc_linked_mdelem* storage = batch->idx.array[idx];
-  GPR_DEBUG_ASSERT(storage != nullptr);
-  --batch->list.default_count;
-  batch->idx.array[idx] = nullptr;
-  unlink_storage(&batch->list, storage);
-  GRPC_MDELEM_UNREF(storage->md);
-  assert_valid_callouts(batch);
-}
-
 void grpc_metadata_batch_set_value(grpc_linked_mdelem* storage,
                                    const grpc_slice& value) {
   grpc_mdelem old_mdelem = storage->md;
@@ -300,131 +41,54 @@ void grpc_metadata_batch_set_value(grpc_linked_mdelem* storage,
   GRPC_MDELEM_UNREF(old_mdelem);
 }
 
-absl::optional<absl::string_view> grpc_metadata_batch_get_value(
-    grpc_metadata_batch* batch, absl::string_view target_key,
-    std::string* concatenated_value) {
-  // Find all values for the specified key.
-  GPR_DEBUG_ASSERT(batch != nullptr);
-  absl::InlinedVector<absl::string_view, 1> values;
-  for (grpc_linked_mdelem* md = batch->list.head; md != nullptr;
-       md = md->next) {
-    absl::string_view key = grpc_core::StringViewFromSlice(GRPC_MDKEY(md->md));
-    absl::string_view value =
-        grpc_core::StringViewFromSlice(GRPC_MDVALUE(md->md));
-    if (target_key == key) values.push_back(value);
-  }
-  // If none found, no match.
-  if (values.empty()) return absl::nullopt;
-  // If exactly one found, return it as-is.
-  if (values.size() == 1) return values.front();
-  // If more than one found, concatenate the values, using
-  // *concatenated_values as a temporary holding place for the
-  // concatenated string.
-  *concatenated_value = absl::StrJoin(values, ",");
-  return *concatenated_value;
-}
-
-grpc_error_handle grpc_metadata_batch_substitute(grpc_metadata_batch* batch,
-                                                 grpc_linked_mdelem* storage,
-                                                 grpc_mdelem new_mdelem) {
-  assert_valid_callouts(batch);
-  grpc_error_handle error = GRPC_ERROR_NONE;
-  grpc_mdelem old_mdelem = storage->md;
-  if (!grpc_slice_eq(GRPC_MDKEY(new_mdelem), GRPC_MDKEY(old_mdelem))) {
-    maybe_unlink_callout(batch, storage);
-    storage->md = new_mdelem;
-    error = maybe_link_callout(batch, storage);
-    if (error != GRPC_ERROR_NONE) {
-      unlink_storage(&batch->list, storage);
-      GRPC_MDELEM_UNREF(storage->md);
-    }
-  } else {
-    storage->md = new_mdelem;
-  }
-  GRPC_MDELEM_UNREF(old_mdelem);
-  assert_valid_callouts(batch);
-  return error;
-}
+namespace {
 
-void grpc_metadata_batch_clear(grpc_metadata_batch* batch) {
-  grpc_metadata_batch_destroy(batch);
-  grpc_metadata_batch_init(batch);
-}
+class CopySink {
+ public:
+  explicit CopySink(grpc_metadata_batch* dst) : dst_(dst) {}
 
-bool grpc_metadata_batch_is_empty(grpc_metadata_batch* batch) {
-  return batch->list.head == nullptr &&
-         batch->deadline == GRPC_MILLIS_INF_FUTURE;
-}
-
-size_t grpc_metadata_batch_size(grpc_metadata_batch* batch) {
-  size_t size = 0;
-  for (grpc_linked_mdelem* elem = batch->list.head; elem != nullptr;
-       elem = elem->next) {
-    size += GRPC_MDELEM_LENGTH(elem->md);
-  }
-  return size;
-}
-
-static void add_error(grpc_error_handle* composite, grpc_error_handle error,
-                      const char* composite_error_string) {
-  if (error == GRPC_ERROR_NONE) return;
-  if (*composite == GRPC_ERROR_NONE) {
-    *composite = GRPC_ERROR_CREATE_FROM_COPIED_STRING(composite_error_string);
-  }
-  *composite = grpc_error_add_child(*composite, error);
-}
-
-grpc_error_handle grpc_metadata_batch_filter(
-    grpc_metadata_batch* batch, grpc_metadata_batch_filter_func func,
-    void* user_data, const char* composite_error_string) {
-  grpc_linked_mdelem* l = batch->list.head;
-  grpc_error_handle error = GRPC_ERROR_NONE;
-  while (l) {
-    grpc_linked_mdelem* next = l->next;
-    grpc_filtered_mdelem new_mdelem = func(user_data, l->md);
-    add_error(&error, new_mdelem.error, composite_error_string);
-    if (GRPC_MDISNULL(new_mdelem.md)) {
-      grpc_metadata_batch_remove(batch, l);
-    } else if (new_mdelem.md.payload != l->md.payload) {
-      grpc_metadata_batch_substitute(batch, l, new_mdelem.md);
-    }
-    l = next;
-  }
-  return error;
-}
-
-void grpc_metadata_batch_copy(grpc_metadata_batch* src,
-                              grpc_metadata_batch* dst,
-                              grpc_linked_mdelem* storage) {
-  grpc_metadata_batch_init(dst);
-  dst->deadline = src->deadline;
-  size_t i = 0;
-  for (grpc_linked_mdelem* elem = src->list.head; elem != nullptr;
-       elem = elem->next) {
+  void Encode(grpc_mdelem md) {
     // If the mdelem is not external, take a ref.
     // Otherwise, create a new copy, holding its own refs to the
     // underlying slices.
-    grpc_mdelem md;
-    if (GRPC_MDELEM_STORAGE(elem->md) != GRPC_MDELEM_STORAGE_EXTERNAL) {
-      md = GRPC_MDELEM_REF(elem->md);
+    if (GRPC_MDELEM_STORAGE(md) != GRPC_MDELEM_STORAGE_EXTERNAL) {
+      md = GRPC_MDELEM_REF(md);
     } else {
-      md = grpc_mdelem_from_slices(
-          grpc_slice_ref_internal(GRPC_MDKEY(elem->md)),
-          grpc_slice_ref_internal(GRPC_MDVALUE(elem->md)));
+      md = grpc_mdelem_from_slices(grpc_slice_copy(GRPC_MDKEY(md)),
+                                   grpc_slice_copy(GRPC_MDVALUE(md)));
     }
     // Error unused in non-debug builds.
-    grpc_error_handle GRPC_UNUSED error =
-        grpc_metadata_batch_add_tail(dst, &storage[i++], md);
-    // The only way that grpc_metadata_batch_add_tail() can fail is if
+    grpc_error_handle GRPC_UNUSED error = dst_->Append(md);
+    // The only way that Append() can fail is if
     // there's a duplicate entry for a callout.  However, that can't be
     // the case here, because we would not have been allowed to create
     // a source batch that had that kind of conflict.
     GPR_DEBUG_ASSERT(error == GRPC_ERROR_NONE);
   }
-}
 
-void grpc_metadata_batch_move(grpc_metadata_batch* src,
+  template <class T, class V>
+  void Encode(T trait, V value) {
+    dst_->Set(trait, value);
+  }
+
+ private:
+  grpc_metadata_batch* dst_;
+};
+
+}  // namespace
+
+void grpc_metadata_batch_copy(const grpc_metadata_batch* src,
                               grpc_metadata_batch* dst) {
-  *dst = *src;
-  grpc_metadata_batch_init(src);
+  dst->Clear();
+  CopySink sink(dst);
+  src->Encode(&sink);
+}
+
+grpc_error_handle grpc_attach_md_to_error(grpc_error_handle src,
+                                          grpc_mdelem md) {
+  grpc_error_handle out = grpc_error_set_str(
+      grpc_error_set_str(src, GRPC_ERROR_STR_KEY,
+                         grpc_core::StringViewFromSlice(GRPC_MDKEY(md))),
+      GRPC_ERROR_STR_VALUE, grpc_core::StringViewFromSlice(GRPC_MDVALUE(md)));
+  return out;
 }
index 028bf52..fbd9abc 100644 (file)
 
 #include <stdbool.h>
 
+#include "absl/strings/match.h"
+#include "absl/strings/str_join.h"
 #include "absl/types/optional.h"
 
 #include <grpc/grpc.h>
 #include <grpc/slice.h>
 #include <grpc/support/time.h>
 
+#include "src/core/lib/gprpp/chunked_vector.h"
+#include "src/core/lib/gprpp/table.h"
 #include "src/core/lib/iomgr/exec_ctx.h"
+#include "src/core/lib/surface/validate_metadata.h"
 #include "src/core/lib/transport/metadata.h"
+#include "src/core/lib/transport/parsed_metadata.h"
 #include "src/core/lib/transport/static_metadata.h"
+#include "src/core/lib/transport/timeout_encoding.h"
 
 typedef struct grpc_linked_mdelem {
   grpc_linked_mdelem() {}
@@ -49,42 +56,877 @@ typedef struct grpc_mdelem_list {
   grpc_linked_mdelem* tail;
 } grpc_mdelem_list;
 
-typedef struct grpc_metadata_batch {
-  /** Metadata elements in this batch */
-  grpc_mdelem_list list;
-  grpc_metadata_batch_callouts idx;
-  /** Used to calculate grpc-timeout at the point of sending,
-      or GRPC_MILLIS_INF_FUTURE if this batch does not need to send a
-      grpc-timeout */
-  grpc_millis deadline;
+struct grpc_filtered_mdelem {
+  grpc_error_handle error;
+  grpc_mdelem md;
+};
+#define GRPC_FILTERED_ERROR(error) \
+  { (error), GRPC_MDNULL }
+#define GRPC_FILTERED_MDELEM(md) \
+  { GRPC_ERROR_NONE, (md) }
+#define GRPC_FILTERED_REMOVE() \
+  { GRPC_ERROR_NONE, GRPC_MDNULL }
+
+grpc_error_handle grpc_attach_md_to_error(grpc_error_handle src,
+                                          grpc_mdelem md);
+
+namespace grpc_core {
+
+// grpc-timeout metadata trait.
+// ValueType is defined as grpc_millis - an absolute timestamp (i.e. a
+// deadline!), that is converted to a duration by transports before being
+// sent.
+// TODO(ctiller): Move this elsewhere. During the transition we need to be able
+// to name this in MetadataMap, but ultimately once the transition is done we
+// should not need to.
+struct GrpcTimeoutMetadata {
+  using ValueType = grpc_millis;
+  using MementoType = grpc_millis;
+  static const char* key() { return "grpc-timeout"; }
+  static MementoType ParseMemento(const grpc_slice& value) {
+    grpc_millis timeout;
+    if (GPR_UNLIKELY(!grpc_http2_decode_timeout(value, &timeout))) {
+      timeout = GRPC_MILLIS_INF_FUTURE;
+    }
+    grpc_slice_unref_internal(value);
+    return timeout;
+  }
+  static ValueType MementoToValue(MementoType timeout) {
+    if (timeout == GRPC_MILLIS_INF_FUTURE) {
+      return GRPC_MILLIS_INF_FUTURE;
+    }
+    return grpc_core::ExecCtx::Get()->Now() + timeout;
+  }
+  static grpc_slice Encode(ValueType x) {
+    char timeout[GRPC_HTTP2_TIMEOUT_ENCODE_MIN_BUFSIZE];
+    grpc_http2_encode_timeout(x, timeout);
+    return grpc_slice_from_copied_string(timeout);
+  }
+  static MementoType DisplayValue(MementoType x) { return x; }
+};
+
+// TE metadata trait.
+struct TeMetadata {
+  // HTTP2 says that TE can either be empty or "trailers".
+  // Empty means this trait is not included, "trailers" means kTrailers, and
+  // kInvalid is used to remember an invalid value.
+  enum ValueType : uint8_t {
+    kTrailers,
+    kInvalid,
+  };
+  using MementoType = ValueType;
+  static const char* key() { return "te"; }
+  static MementoType ParseMemento(const grpc_slice& value) {
+    auto out = kInvalid;
+    if (grpc_slice_eq(value, GRPC_MDSTR_TRAILERS)) {
+      out = kTrailers;
+    }
+    grpc_slice_unref_internal(value);
+    return out;
+  }
+  static ValueType MementoToValue(MementoType te) { return te; }
+  static grpc_slice Encode(ValueType x) {
+    GPR_ASSERT(x == kTrailers);
+    return GRPC_MDSTR_TRAILERS;
+  }
+  static const char* DisplayValue(MementoType te) {
+    switch (te) {
+      case ValueType::kTrailers:
+        return "trailers";
+      default:
+        return "<discarded-invalid-value>";
+    }
+  }
+};
+
+namespace metadata_detail {
 
+// Inner implementation of MetadataMap<Container>::Parse()
+// Recursive in terms of metadata trait, tries each known type in order by doing
+// a string comparison on key, and if that key is found parses it. If not found,
+// calls not_found to generate the result value.
+template <typename Container, typename... Traits>
+struct ParseHelper;
+
+template <typename Container, typename Trait, typename... Traits>
+struct ParseHelper<Container, Trait, Traits...> {
+  template <typename NotFound>
+  static ParsedMetadata<Container> Parse(absl::string_view key,
+                                         const grpc_slice& value,
+                                         NotFound not_found) {
+    if (key == Trait::key()) {
+      return ParsedMetadata<Container>(
+          Trait(), Trait::ParseMemento(value),
+          ParsedMetadata<Container>::TransportSize(key.size(),
+                                                   GRPC_SLICE_LENGTH(value)));
+    }
+    return ParseHelper<Container, Traits...>::Parse(key, value, not_found);
+  }
+};
+
+template <typename Container>
+struct ParseHelper<Container> {
+  template <typename NotFound>
+  static ParsedMetadata<Container> Parse(absl::string_view, const grpc_slice&,
+                                         NotFound not_found) {
+    return not_found();
+  }
+};
+
+// Inner implementation of MetadataMap<Container>::Append()
+// Recursive in terms of metadata trait, tries each known type in order by doing
+// a string comparison on key, and if that key is found sets it. If not found,
+// calls not_found to append generically.
+template <typename Container, typename... Traits>
+struct AppendHelper;
+
+template <typename Container, typename Trait, typename... Traits>
+struct AppendHelper<Container, Trait, Traits...> {
+  template <typename NotFound>
+  static void Append(Container* container, absl::string_view key,
+                     const grpc_slice& value, NotFound not_found) {
+    if (key == Trait::key()) {
+      container->Set(Trait(),
+                     Trait::MementoToValue(Trait::ParseMemento(value)));
+      return;
+    }
+    AppendHelper<Container, Traits...>::Append(container, key, value,
+                                               not_found);
+  }
+};
+
+template <typename Container>
+struct AppendHelper<Container> {
+  template <typename NotFound>
+  static void Append(Container*, absl::string_view, const grpc_slice&,
+                     NotFound not_found) {
+    not_found();
+  }
+};
+
+}  // namespace metadata_detail
+
+// MetadataMap encodes the mapping of metadata keys to metadata values.
+// Right now the API presented is the minimal one that will allow us to
+// substitute this type for grpc_metadata_batch in a relatively easy fashion. At
+// that point we'll start iterating this API into something that's ergonomic
+// again, whilst minimally holding the performance bar already set (and
+// hopefully improving some things).
+// In the meantime, we're not going to invest much time in ephemeral API
+// documentation, so if you must use one of these APIs and it's not obvious
+// how, reach out to ctiller.
+//
+// MetadataMap takes a list of traits. Each of these trait objects defines
+// one metadata field that is used by core, and so should have more specialized
+// handling than just using the generic APIs.
+//
+// Each trait object has the following signature:
+// // Traits for the grpc-xyz metadata field:
+// struct GrpcXyzMetadata {
+//   // The type that's stored on MetadataBatch
+//   using ValueType = ...;
+//   // The type that's stored in compression/decompression tables
+//   using MementoType = ...;
+//   // The string key for this metadata type (for transports that require it)
+//   static constexpr char* key() { return "grpc-xyz"; }
+//   // Parse a memento from a slice
+//   // Takes ownership of value
+//   static MementoType ParseMemento(const grpc_slice& value) { ... }
+//   // Convert a memento to a value
+//   static ValueType MementoToValue(MementoType memento) { ... }
+//   // Convert a value to its canonical text wire format (the format that
+//   // ParseMemento will accept!)
+//   static grpc_slice Encode(ValueType value);
+//   // Convert a value to something that can be passed to StrCat and displayed
+//   // for debugging
+//   static SomeStrCatableType DisplayValue(MementoType value) { ... }
+// };
+//
+// About parsing and mementos:
+//
+// Many gRPC transports exchange metadata as key/value strings, but also allow
+// for a more efficient representation as a single integer. We can use this
+// integer representation to avoid reparsing too, by storing the parsed value
+// in the compression table. This is what mementos are used for.
+//
+// A trait offers the capability to turn a slice into a memento via
+// ParseMemento. This is exposed to users of MetadataMap via the Parse() method,
+// that returns a ParsedMetadata object. That ParsedMetadata object can in turn
+// be used to set the same value on many different MetadataMaps without having
+// to reparse.
+//
+// Implementation wise, ParsedMetadata is a type erased wrapper around
+// MementoType. When we set a value on MetadataMap, we first turn that memento
+// into a value. For most types, this is going to be a no-op, but for example
+// for grpc-timeout we make the memento the timeout expressed on the wire, but
+// we make the value the timestamp of when the timeout will expire (i.e. the
+// deadline).
+template <typename... Traits>
+class MetadataMap {
+ public:
+  explicit MetadataMap(Arena* arena);
+  ~MetadataMap();
+
+  MetadataMap(const MetadataMap&) = delete;
+  MetadataMap& operator=(const MetadataMap&) = delete;
+  MetadataMap(MetadataMap&&) noexcept;
+  MetadataMap& operator=(MetadataMap&&) noexcept;
+
+  // Encode this metadata map into some encoder.
+  // For each field that is set in the MetadataMap, call
+  // encoder->Encode.
+  //
+  // For fields for which we have traits, this will be a method with
+  // the signature:
+  //    void Encode(TraitsType, typename TraitsType::ValueType value);
+  // For fields for which we do not have traits, this will be a method
+  // with the signature:
+  //    void Encode(grpc_mdelem md);
+  // TODO(ctiller): It's expected that the latter Encode method will
+  // become Encode(Slice, Slice) by the end of the current metadata API
+  // transitions.
   template <typename Encoder>
   void Encode(Encoder* encoder) const {
-    for (auto* l = list.head; l; l = l->next) {
+    for (auto* l = list_.head; l; l = l->next) {
       encoder->Encode(l->md);
     }
-    if (deadline != GRPC_MILLIS_INF_FUTURE) encoder->EncodeDeadline(deadline);
+    table_.ForEach(EncodeWrapper<Encoder>{encoder});
+  }
+
+  // Get the pointer to the value of some known metadata.
+  // Returns nullptr if the metadata is not present.
+  // Causes a compilation error if Which is not an element of Traits.
+  template <typename Which>
+  const typename Which::ValueType* get_pointer(Which) const {
+    if (auto* p = table_.template get<Value<Which>>()) return &p->value;
+    return nullptr;
+  }
+
+  // Get the pointer to the value of some known metadata.
+  // Returns nullptr if the metadata is not present.
+  // Causes a compilation error if Which is not an element of Traits.
+  template <typename Which>
+  typename Which::ValueType* get_pointer(Which) {
+    if (auto* p = table_.template get<Value<Which>>()) return &p->value;
+    return nullptr;
+  }
+
+  // Get the value of some known metadata.
+  // Returns nullopt if the metadata is not present.
+  // Causes a compilation error if Which is not an element of Traits.
+  template <typename Which>
+  absl::optional<typename Which::ValueType> get(Which) const {
+    if (auto* p = table_.template get<Value<Which>>()) return p->value;
+    return absl::nullopt;
+  }
+
+  // Set the value of some known metadata.
+  // Returns a pointer to the new value.
+  template <typename Which, typename... Args>
+  typename Which::ValueType* Set(Which, Args&&... args) {
+    return &table_.template set<Value<Which>>(std::forward<Args>(args)...)
+                ->value;
+  }
+
+  // Remove a specific piece of known metadata.
+  template <typename Which>
+  void Remove(Which) {
+    table_.template clear<Value<Which>>();
+  }
+
+  // Extract a piece of known metadata.
+  // Returns nullopt if the metadata was not present, or the value if it was.
+  // The same as:
+  //  auto value = m.get(T());
+  //  m.Remove(T());
+  template <typename Which>
+  absl::optional<typename Which::ValueType> Take(Which which) {
+    auto value = get(which);
+    Remove(which);
+    return value;
+  }
+
+  // Parse metadata from a key/value pair, and return an object representing
+  // that result.
+  // TODO(ctiller): key should probably be an absl::string_view.
+  // Once we don't care about interning anymore, make that change!
+  template <class KeySlice, class ValueSlice>
+  static ParsedMetadata<MetadataMap> Parse(const KeySlice& key,
+                                           const ValueSlice& value) {
+    bool parsed = true;
+    auto out = metadata_detail::ParseHelper<MetadataMap, Traits...>::Parse(
+        StringViewFromSlice(key), value, [&] {
+          parsed = false;
+          return ParsedMetadata<MetadataMap>(
+              grpc_mdelem_from_slices(key, value));
+        });
+    if (parsed) {
+      grpc_slice_unref_internal(key);
+    }
+    return out;
+  }
+
+  // Set a value from a parsed metadata object.
+  GRPC_MUST_USE_RESULT grpc_error_handle
+  Set(const ParsedMetadata<MetadataMap>& m) {
+    return m.SetOnContainer(this);
+  }
+
+  // Append a key/value pair - takes ownership of value
+  void Append(absl::string_view key, const grpc_slice& value) {
+    metadata_detail::AppendHelper<MetadataMap, Traits...>::Append(
+        this, key, value, [&] {
+          GPR_ASSERT(GRPC_ERROR_NONE ==
+                     Append(grpc_mdelem_from_slices(
+                         grpc_slice_intern(grpc_slice_from_static_buffer(
+                             key.data(), key.length())),
+                         value)));
+        });
+  }
+
+  //
+  // All APIs below this point are subject to change.
+  //
+
+  template <typename F>
+  void ForEach(F f) const {
+    for (auto* l = list_.head; l; l = l->next) {
+      f(l->md);
+    }
+  }
+
+  template <typename F>
+  grpc_error_handle Filter(F f, const char* composite_error_string) {
+    grpc_linked_mdelem* l = list_.head;
+    grpc_error_handle error = GRPC_ERROR_NONE;
+    auto add_error = [&](grpc_error_handle new_error) {
+      if (new_error == GRPC_ERROR_NONE) return;
+      if (error == GRPC_ERROR_NONE) {
+        error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(composite_error_string);
+      }
+      error = grpc_error_add_child(error, new_error);
+    };
+    while (l) {
+      grpc_linked_mdelem* next = l->next;
+      grpc_filtered_mdelem new_mdelem = f(l->md);
+      add_error(new_mdelem.error);
+      if (GRPC_MDISNULL(new_mdelem.md)) {
+        Remove(l);
+      } else if (new_mdelem.md.payload != l->md.payload) {
+        add_error(Substitute(l, new_mdelem.md));
+      }
+      l = next;
+    }
+    return error;
+  }
+
+  GRPC_MUST_USE_RESULT grpc_error_handle Append(grpc_mdelem md) {
+    return AddTail(elem_storage_.EmplaceBack(), md);
+  }
+
+  GRPC_MUST_USE_RESULT grpc_error_handle ReplaceOrAppend(grpc_slice key,
+                                                         grpc_slice value) {
+    if (ReplaceIfExists(key, value)) return GRPC_ERROR_NONE;
+    return Append(grpc_mdelem_from_slices(key, value));
+  }
+
+  // Set key to value if it exists and return true, otherwise return false.
+  // If this function returns true, it takes ownership of key and value.
+  // If this function returns false, it does not take ownership of key nor
+  // value.
+  bool ReplaceIfExists(grpc_slice key, grpc_slice value);
+
+  void Clear();
+  bool empty() const { return count() == 0; }
+
+  size_t count() const { return list_.count + table_.count(); }
+  size_t non_deadline_count() const { return list_.count; }
+  size_t default_count() const { return list_.default_count; }
+
+  size_t TransportSize() const;
+
+  void Remove(grpc_linked_mdelem* storage);
+  void Remove(grpc_metadata_batch_callouts_index idx);
+
+  absl::optional<grpc_slice> Remove(grpc_slice key);
+
+  grpc_error_handle Substitute(grpc_linked_mdelem* storage,
+                               grpc_mdelem new_mdelem);
+
+  absl::optional<absl::string_view> GetValue(
+      absl::string_view target_key, std::string* concatenated_value) const;
+
+  grpc_error_handle LinkHead(grpc_linked_mdelem* storage) GRPC_MUST_USE_RESULT;
+  grpc_error_handle LinkHead(grpc_linked_mdelem* storage,
+                             grpc_metadata_batch_callouts_index idx)
+      GRPC_MUST_USE_RESULT;
+  grpc_error_handle LinkTail(grpc_linked_mdelem* storage) GRPC_MUST_USE_RESULT;
+  grpc_error_handle LinkTail(grpc_linked_mdelem* storage,
+                             grpc_metadata_batch_callouts_index idx)
+      GRPC_MUST_USE_RESULT;
+
+  grpc_error_handle AddHead(grpc_linked_mdelem* storage) GRPC_MUST_USE_RESULT;
+  grpc_error_handle AddHead(grpc_linked_mdelem* storage,
+                            grpc_mdelem elem_to_add) GRPC_MUST_USE_RESULT;
+  grpc_error_handle AddTail(grpc_linked_mdelem* storage) GRPC_MUST_USE_RESULT;
+  grpc_error_handle AddTail(grpc_linked_mdelem* storage,
+                            grpc_mdelem elem_to_add) GRPC_MUST_USE_RESULT;
+
+  void CopyFrom(MetadataMap* src, grpc_linked_mdelem* storage);
+
+#ifndef NDEBUG
+  void AssertOk();
+#else
+  void AssertOk() {}
+#endif
+
+  // TODO(ctiller): the following explicit deadline handling methods are
+  // deprecated in terms of the traits based APIs.
+  grpc_millis deadline() const {
+    return get(GrpcTimeoutMetadata()).value_or(GRPC_MILLIS_INF_FUTURE);
+  };
+
+  const grpc_metadata_batch_callouts* legacy_index() const { return &idx_; }
+
+ private:
+  // Generate a strong type for metadata values per trait.
+  template <typename Which>
+  struct Value {
+    Value() = default;
+    explicit Value(const typename Which::ValueType& value) : value(value) {}
+    Value(const Value&) = default;
+    Value& operator=(const Value&) = default;
+    Value(Value&&) noexcept = default;
+    Value& operator=(Value&&) noexcept = default;
+    GPR_NO_UNIQUE_ADDRESS typename Which::ValueType value;
+  };
+  // Callable for the ForEach in Encode() -- for each value, call the
+  // appropriate encoder method.
+  template <typename Encoder>
+  struct EncodeWrapper {
+    Encoder* encoder;
+    template <typename Which>
+    void operator()(const Value<Which>& which) {
+      encoder->Encode(Which(), which.value);
+    }
+  };
+
+  void AssertValidCallouts();
+  grpc_error_handle LinkCallout(grpc_linked_mdelem* storage,
+                                grpc_metadata_batch_callouts_index idx)
+      GRPC_MUST_USE_RESULT;
+  grpc_error_handle MaybeLinkCallout(grpc_linked_mdelem* storage)
+      GRPC_MUST_USE_RESULT;
+  void MaybeUnlinkCallout(grpc_linked_mdelem* storage);
+
+  static void assert_valid_list(grpc_mdelem_list* list) {
+#ifndef NDEBUG
+    grpc_linked_mdelem* l;
+
+    GPR_ASSERT((list->head == nullptr) == (list->tail == nullptr));
+    if (!list->head) return;
+    GPR_ASSERT(list->head->prev == nullptr);
+    GPR_ASSERT(list->tail->next == nullptr);
+    GPR_ASSERT((list->head == list->tail) == (list->head->next == nullptr));
+
+    size_t verified_count = 0;
+    for (l = list->head; l; l = l->next) {
+      GPR_ASSERT(!GRPC_MDISNULL(l->md));
+      GPR_ASSERT((l->prev == nullptr) == (l == list->head));
+      GPR_ASSERT((l->next == nullptr) == (l == list->tail));
+      if (l->next) GPR_ASSERT(l->next->prev == l);
+      if (l->prev) GPR_ASSERT(l->prev->next == l);
+      verified_count++;
+    }
+    GPR_ASSERT(list->count == verified_count);
+#else
+    // Avoid unused-parameter warning for debug-only parameter
+    (void)list;
+#endif /* NDEBUG */
+  }
+
+  static grpc_error_handle GPR_ATTRIBUTE_NOINLINE
+  error_with_md(grpc_mdelem md) {
+    return grpc_attach_md_to_error(
+        GRPC_ERROR_CREATE_FROM_STATIC_STRING("Unallowed duplicate metadata"),
+        md);
+  }
+
+  static void link_head(grpc_mdelem_list* list, grpc_linked_mdelem* storage) {
+    assert_valid_list(list);
+    GPR_DEBUG_ASSERT(!GRPC_MDISNULL(storage->md));
+    storage->prev = nullptr;
+    storage->next = list->head;
+    storage->reserved = nullptr;
+    if (list->head != nullptr) {
+      list->head->prev = storage;
+    } else {
+      list->tail = storage;
+    }
+    list->head = storage;
+    list->count++;
+    assert_valid_list(list);
+  }
+
+  static void link_tail(grpc_mdelem_list* list, grpc_linked_mdelem* storage) {
+    assert_valid_list(list);
+    GPR_DEBUG_ASSERT(!GRPC_MDISNULL(storage->md));
+    storage->prev = list->tail;
+    storage->next = nullptr;
+    storage->reserved = nullptr;
+    if (list->tail != nullptr) {
+      list->tail->next = storage;
+    } else {
+      list->head = storage;
+    }
+    list->tail = storage;
+    list->count++;
+    assert_valid_list(list);
+  }
+
+  static void unlink_storage(grpc_mdelem_list* list,
+                             grpc_linked_mdelem* storage) {
+    assert_valid_list(list);
+    if (storage->prev != nullptr) {
+      storage->prev->next = storage->next;
+    } else {
+      list->head = storage->next;
+    }
+    if (storage->next != nullptr) {
+      storage->next->prev = storage->prev;
+    } else {
+      list->tail = storage->prev;
+    }
+    list->count--;
+    assert_valid_list(list);
+  }
+
+  // Table of known metadata types.
+  Table<Value<Traits>...> table_;
+  /** Metadata elements in this batch */
+  grpc_mdelem_list list_;
+  grpc_metadata_batch_callouts idx_;
+  // Backing store for added metadata.
+  ChunkedVector<grpc_linked_mdelem, 10> elem_storage_;
+};
+
+template <typename... Traits>
+void MetadataMap<Traits...>::AssertValidCallouts() {
+#ifndef NDEBUG
+  for (grpc_linked_mdelem* l = list_.head; l != nullptr; l = l->next) {
+    grpc_slice key_interned = grpc_slice_intern(GRPC_MDKEY(l->md));
+    grpc_metadata_batch_callouts_index callout_idx =
+        GRPC_BATCH_INDEX_OF(key_interned);
+    if (callout_idx != GRPC_BATCH_CALLOUTS_COUNT) {
+      GPR_ASSERT(idx_.array[callout_idx] == l);
+    }
+    grpc_slice_unref_internal(key_interned);
+  }
+#endif
+}
+
+#ifndef NDEBUG
+template <typename... Traits>
+void MetadataMap<Traits...>::AssertOk() {
+  assert_valid_list(&list_);
+}
+#endif /* NDEBUG */
+
+template <typename... Traits>
+MetadataMap<Traits...>::MetadataMap(Arena* arena) : elem_storage_(arena) {
+  memset(&list_, 0, sizeof(list_));
+  memset(&idx_, 0, sizeof(idx_));
+}
+
+template <typename... Traits>
+MetadataMap<Traits...>::MetadataMap(MetadataMap&& other) noexcept
+    : table_(std::move(other.table_)) {
+  list_ = other.list_;
+  idx_ = other.idx_;
+  memset(&other.list_, 0, sizeof(list_));
+  memset(&other.idx_, 0, sizeof(idx_));
+}
+
+template <typename... Traits>
+MetadataMap<Traits...>& MetadataMap<Traits...>::operator=(
+    MetadataMap&& other) noexcept {
+  Clear();
+  table_ = std::move(other.table_);
+  list_ = other.list_;
+  idx_ = other.idx_;
+  memset(&other.list_, 0, sizeof(list_));
+  memset(&other.idx_, 0, sizeof(idx_));
+  return *this;
+}
+
+template <typename... Traits>
+MetadataMap<Traits...>::~MetadataMap() {
+  AssertValidCallouts();
+  for (auto* l = list_.head; l; l = l->next) {
+    GRPC_MDELEM_UNREF(l->md);
+  }
+}
+
+template <typename... Traits>
+absl::optional<grpc_slice> MetadataMap<Traits...>::Remove(grpc_slice key) {
+  for (auto* l = list_.head; l; l = l->next) {
+    if (grpc_slice_eq(GRPC_MDKEY(l->md), key)) {
+      auto out = grpc_slice_ref_internal(GRPC_MDVALUE(l->md));
+      Remove(l);
+      return out;
+    }
   }
-} grpc_metadata_batch;
+  return {};
+}
+
+template <typename... Traits>
+grpc_error_handle MetadataMap<Traits...>::LinkCallout(
+    grpc_linked_mdelem* storage, grpc_metadata_batch_callouts_index idx) {
+  AssertValidCallouts();
+  GPR_DEBUG_ASSERT(idx >= 0 && idx < GRPC_BATCH_CALLOUTS_COUNT);
+  if (GPR_LIKELY(idx_.array[idx] == nullptr)) {
+    ++list_.default_count;
+    idx_.array[idx] = storage;
+    AssertValidCallouts();
+    return GRPC_ERROR_NONE;
+  }
+  AssertValidCallouts();
+  return error_with_md(storage->md);
+}
 
-void grpc_metadata_batch_init(grpc_metadata_batch* batch);
-void grpc_metadata_batch_destroy(grpc_metadata_batch* batch);
-void grpc_metadata_batch_clear(grpc_metadata_batch* batch);
-bool grpc_metadata_batch_is_empty(grpc_metadata_batch* batch);
+template <typename... Traits>
+grpc_error_handle MetadataMap<Traits...>::MaybeLinkCallout(
+    grpc_linked_mdelem* storage) {
+  grpc_metadata_batch_callouts_index idx =
+      GRPC_BATCH_INDEX_OF(GRPC_MDKEY(storage->md));
+  if (idx == GRPC_BATCH_CALLOUTS_COUNT) {
+    return GRPC_ERROR_NONE;
+  }
+  return LinkCallout(storage, idx);
+}
+
+template <typename... Traits>
+void MetadataMap<Traits...>::MaybeUnlinkCallout(grpc_linked_mdelem* storage) {
+  grpc_metadata_batch_callouts_index idx =
+      GRPC_BATCH_INDEX_OF(GRPC_MDKEY(storage->md));
+  if (idx == GRPC_BATCH_CALLOUTS_COUNT) {
+    return;
+  }
+  --list_.default_count;
+  GPR_DEBUG_ASSERT(idx_.array[idx] != nullptr);
+  idx_.array[idx] = nullptr;
+}
+
+template <typename... Traits>
+grpc_error_handle MetadataMap<Traits...>::AddHead(grpc_linked_mdelem* storage,
+                                                  grpc_mdelem elem_to_add) {
+  GPR_DEBUG_ASSERT(!GRPC_MDISNULL(elem_to_add));
+  storage->md = elem_to_add;
+  return LinkHead(storage);
+}
+
+template <typename... Traits>
+grpc_error_handle MetadataMap<Traits...>::LinkHead(
+    grpc_linked_mdelem* storage) {
+  AssertValidCallouts();
+  grpc_error_handle err = MaybeLinkCallout(storage);
+  if (err != GRPC_ERROR_NONE) {
+    AssertValidCallouts();
+    return err;
+  }
+  link_head(&list_, storage);
+  AssertValidCallouts();
+  return GRPC_ERROR_NONE;
+}
+
+// TODO(arjunroy): Need to revisit this and see what guarantees exist between
+// C-core and the internal-metadata subsystem. E.g. can we ensure a particular
+// metadata is never added twice, even in the presence of user supplied data?
+template <typename... Traits>
+grpc_error_handle MetadataMap<Traits...>::LinkHead(
+    grpc_linked_mdelem* storage, grpc_metadata_batch_callouts_index idx) {
+  GPR_DEBUG_ASSERT(GRPC_BATCH_INDEX_OF(GRPC_MDKEY(storage->md)) == idx);
+  AssertValidCallouts();
+  grpc_error_handle err = LinkCallout(storage, idx);
+  if (GPR_UNLIKELY(err != GRPC_ERROR_NONE)) {
+    AssertValidCallouts();
+    return err;
+  }
+  link_head(&list_, storage);
+  AssertValidCallouts();
+  return GRPC_ERROR_NONE;
+}
+
+template <typename... Traits>
+grpc_error_handle MetadataMap<Traits...>::AddTail(grpc_linked_mdelem* storage,
+                                                  grpc_mdelem elem_to_add) {
+  GPR_DEBUG_ASSERT(!GRPC_MDISNULL(elem_to_add));
+  storage->md = elem_to_add;
+  return LinkTail(storage);
+}
+
+template <typename... Traits>
+grpc_error_handle MetadataMap<Traits...>::LinkTail(
+    grpc_linked_mdelem* storage) {
+  AssertValidCallouts();
+  grpc_error_handle err = MaybeLinkCallout(storage);
+  if (err != GRPC_ERROR_NONE) {
+    AssertValidCallouts();
+    return err;
+  }
+  link_tail(&list_, storage);
+  AssertValidCallouts();
+  return GRPC_ERROR_NONE;
+}
+
+template <typename... Traits>
+grpc_error_handle MetadataMap<Traits...>::LinkTail(
+    grpc_linked_mdelem* storage, grpc_metadata_batch_callouts_index idx) {
+  GPR_DEBUG_ASSERT(GRPC_BATCH_INDEX_OF(GRPC_MDKEY(storage->md)) == idx);
+  AssertValidCallouts();
+  grpc_error_handle err = LinkCallout(storage, idx);
+  if (GPR_UNLIKELY(err != GRPC_ERROR_NONE)) {
+    AssertValidCallouts();
+    return err;
+  }
+  link_tail(&list_, storage);
+  AssertValidCallouts();
+  return GRPC_ERROR_NONE;
+}
+
+template <typename... Traits>
+void MetadataMap<Traits...>::Remove(grpc_linked_mdelem* storage) {
+  AssertValidCallouts();
+  MaybeUnlinkCallout(storage);
+  unlink_storage(&list_, storage);
+  GRPC_MDELEM_UNREF(storage->md);
+  AssertValidCallouts();
+}
+
+template <typename... Traits>
+void MetadataMap<Traits...>::Remove(grpc_metadata_batch_callouts_index idx) {
+  AssertValidCallouts();
+  if (idx_.array[idx] == nullptr) return;
+  --list_.default_count;
+  unlink_storage(&list_, idx_.array[idx]);
+  GRPC_MDELEM_UNREF(idx_.array[idx]->md);
+  idx_.array[idx] = nullptr;
+  AssertValidCallouts();
+}
+
+template <typename... Traits>
+absl::optional<absl::string_view> MetadataMap<Traits...>::GetValue(
+    absl::string_view target_key, std::string* concatenated_value) const {
+  // Find all values for the specified key.
+  absl::InlinedVector<absl::string_view, 1> values;
+  for (grpc_linked_mdelem* md = list_.head; md != nullptr; md = md->next) {
+    absl::string_view key = grpc_core::StringViewFromSlice(GRPC_MDKEY(md->md));
+    absl::string_view value =
+        grpc_core::StringViewFromSlice(GRPC_MDVALUE(md->md));
+    if (target_key == key) values.push_back(value);
+  }
+  // If none found, no match.
+  if (values.empty()) return absl::nullopt;
+  // If exactly one found, return it as-is.
+  if (values.size() == 1) return values.front();
+  // If more than one found, concatenate the values, using
+  // *concatenated_values as a temporary holding place for the
+  // concatenated string.
+  *concatenated_value = absl::StrJoin(values, ",");
+  return *concatenated_value;
+}
+
+template <typename... Traits>
+grpc_error_handle MetadataMap<Traits...>::Substitute(
+    grpc_linked_mdelem* storage, grpc_mdelem new_mdelem) {
+  AssertValidCallouts();
+  grpc_error_handle error = GRPC_ERROR_NONE;
+  grpc_mdelem old_mdelem = storage->md;
+  if (!grpc_slice_eq(GRPC_MDKEY(new_mdelem), GRPC_MDKEY(old_mdelem))) {
+    MaybeUnlinkCallout(storage);
+    storage->md = new_mdelem;
+    error = MaybeLinkCallout(storage);
+    if (error != GRPC_ERROR_NONE) {
+      unlink_storage(&list_, storage);
+      GRPC_MDELEM_UNREF(storage->md);
+    }
+  } else {
+    storage->md = new_mdelem;
+  }
+  GRPC_MDELEM_UNREF(old_mdelem);
+  AssertValidCallouts();
+  return error;
+}
+
+template <typename... Traits>
+void MetadataMap<Traits...>::Clear() {
+  // TODO(ctiller): implement this without deconstructing/reconstructing once
+  // linked_mdelem is no longer a thing.
+  auto* arena = elem_storage_.arena();
+  this->~MetadataMap();
+  new (this) MetadataMap(arena);
+}
+
+template <typename... Traits>
+size_t MetadataMap<Traits...>::TransportSize() const {
+  size_t size = 0;
+  for (grpc_linked_mdelem* elem = list_.head; elem != nullptr;
+       elem = elem->next) {
+    size += GRPC_MDELEM_LENGTH(elem->md);
+  }
+  return size;
+}
+
+template <typename... Traits>
+bool MetadataMap<Traits...>::ReplaceIfExists(grpc_slice key, grpc_slice value) {
+  AssertValidCallouts();
+  for (grpc_linked_mdelem* l = list_.head; l != nullptr; l = l->next) {
+    if (grpc_slice_eq(GRPC_MDKEY(l->md), key)) {
+      auto new_mdelem = grpc_mdelem_from_slices(key, value);
+      GRPC_MDELEM_UNREF(l->md);
+      l->md = new_mdelem;
+      AssertValidCallouts();
+      return true;
+    }
+  }
+  AssertValidCallouts();
+  return false;
+}
+
+}  // namespace grpc_core
+
+using grpc_metadata_batch =
+    grpc_core::MetadataMap<grpc_core::GrpcTimeoutMetadata,
+                           grpc_core::TeMetadata>;
+
+inline void grpc_metadata_batch_clear(grpc_metadata_batch* batch) {
+  batch->Clear();
+}
+inline bool grpc_metadata_batch_is_empty(grpc_metadata_batch* batch) {
+  return batch->empty();
+}
 
 /* Returns the transport size of the batch. */
-size_t grpc_metadata_batch_size(grpc_metadata_batch* batch);
+inline size_t grpc_metadata_batch_size(grpc_metadata_batch* batch) {
+  return batch->TransportSize();
+}
 
 /** Remove \a storage from the batch, unreffing the mdelem contained */
-void grpc_metadata_batch_remove(grpc_metadata_batch* batch,
-                                grpc_linked_mdelem* storage);
-void grpc_metadata_batch_remove(grpc_metadata_batch* batch,
-                                grpc_metadata_batch_callouts_index idx);
+inline void grpc_metadata_batch_remove(grpc_metadata_batch* batch,
+                                       grpc_linked_mdelem* storage) {
+  batch->Remove(storage);
+}
+inline void grpc_metadata_batch_remove(grpc_metadata_batch* batch,
+                                       grpc_metadata_batch_callouts_index idx) {
+  batch->Remove(idx);
+}
 
 /** Substitute a new mdelem for an old value */
-grpc_error_handle grpc_metadata_batch_substitute(grpc_metadata_batch* batch,
-                                                 grpc_linked_mdelem* storage,
-                                                 grpc_mdelem new_mdelem);
+inline grpc_error_handle grpc_metadata_batch_substitute(
+    grpc_metadata_batch* batch, grpc_linked_mdelem* storage,
+    grpc_mdelem new_mdelem) {
+  return batch->Substitute(storage, new_mdelem);
+}
 
 void grpc_metadata_batch_set_value(grpc_linked_mdelem* storage,
                                    const grpc_slice& value);
@@ -96,33 +938,43 @@ void grpc_metadata_batch_set_value(grpc_linked_mdelem* storage,
     If the key is present more than once in the batch, constructs a
     comma-concatenated string of all values in concatenated_value and returns a
     string_view of that string. */
-absl::optional<absl::string_view> grpc_metadata_batch_get_value(
+inline absl::optional<absl::string_view> grpc_metadata_batch_get_value(
     grpc_metadata_batch* batch, absl::string_view target_key,
-    std::string* concatenated_value);
+    std::string* concatenated_value) {
+  return batch->GetValue(target_key, concatenated_value);
+}
 
 /** Add \a storage to the beginning of \a batch. storage->md is
     assumed to be valid.
     \a storage is owned by the caller and must survive for the
     lifetime of batch. This usually means it should be around
     for the lifetime of the call. */
-grpc_error_handle grpc_metadata_batch_link_head(grpc_metadata_batch* batch,
-                                                grpc_linked_mdelem* storage)
-    GRPC_MUST_USE_RESULT;
-grpc_error_handle grpc_metadata_batch_link_head(
+inline GRPC_MUST_USE_RESULT grpc_error_handle grpc_metadata_batch_link_head(
+    grpc_metadata_batch* batch, grpc_linked_mdelem* storage) {
+  return batch->LinkHead(storage);
+}
+
+inline GRPC_MUST_USE_RESULT grpc_error_handle grpc_metadata_batch_link_head(
     grpc_metadata_batch* batch, grpc_linked_mdelem* storage,
-    grpc_metadata_batch_callouts_index idx) GRPC_MUST_USE_RESULT;
+    grpc_metadata_batch_callouts_index idx) {
+  return batch->LinkHead(storage, idx);
+}
 
 /** Add \a storage to the end of \a batch. storage->md is
     assumed to be valid.
     \a storage is owned by the caller and must survive for the
     lifetime of batch. This usually means it should be around
     for the lifetime of the call. */
-grpc_error_handle grpc_metadata_batch_link_tail(grpc_metadata_batch* batch,
-                                                grpc_linked_mdelem* storage)
-    GRPC_MUST_USE_RESULT;
-grpc_error_handle grpc_metadata_batch_link_tail(
+inline GRPC_MUST_USE_RESULT grpc_error_handle grpc_metadata_batch_link_tail(
+    grpc_metadata_batch* batch, grpc_linked_mdelem* storage) {
+  return batch->LinkTail(storage);
+}
+
+inline GRPC_MUST_USE_RESULT grpc_error_handle grpc_metadata_batch_link_tail(
     grpc_metadata_batch* batch, grpc_linked_mdelem* storage,
-    grpc_metadata_batch_callouts_index idx) GRPC_MUST_USE_RESULT;
+    grpc_metadata_batch_callouts_index idx) {
+  return batch->LinkTail(storage, idx);
+}
 
 /** Add \a elem_to_add as the first element in \a batch, using
     \a storage as backing storage for the linked list element.
@@ -130,9 +982,11 @@ grpc_error_handle grpc_metadata_batch_link_tail(
     lifetime of batch. This usually means it should be around
     for the lifetime of the call.
     Takes ownership of \a elem_to_add */
-grpc_error_handle grpc_metadata_batch_add_head(
+inline grpc_error_handle grpc_metadata_batch_add_head(
     grpc_metadata_batch* batch, grpc_linked_mdelem* storage,
-    grpc_mdelem elem_to_add) GRPC_MUST_USE_RESULT;
+    grpc_mdelem elem_to_add) {
+  return batch->AddHead(storage, elem_to_add);
+}
 
 // TODO(arjunroy, roth): Remove redundant methods.
 // add/link_head/tail are almost identical.
@@ -156,9 +1010,11 @@ inline grpc_error_handle GRPC_MUST_USE_RESULT grpc_metadata_batch_add_head(
     lifetime of batch. This usually means it should be around
     for the lifetime of the call.
     Takes ownership of \a elem_to_add */
-grpc_error_handle grpc_metadata_batch_add_tail(
+inline GRPC_MUST_USE_RESULT grpc_error_handle grpc_metadata_batch_add_tail(
     grpc_metadata_batch* batch, grpc_linked_mdelem* storage,
-    grpc_mdelem elem_to_add) GRPC_MUST_USE_RESULT;
+    grpc_mdelem elem_to_add) {
+  return batch->AddTail(storage, elem_to_add);
+}
 
 inline grpc_error_handle GRPC_MUST_USE_RESULT grpc_metadata_batch_add_tail(
     grpc_metadata_batch* batch, grpc_linked_mdelem* storage,
@@ -174,48 +1030,26 @@ inline grpc_error_handle GRPC_MUST_USE_RESULT grpc_metadata_batch_add_tail(
   return grpc_metadata_batch_add_tail(batch, storage, idx);
 }
 
-grpc_error_handle grpc_attach_md_to_error(grpc_error_handle src,
-                                          grpc_mdelem md);
-
-struct grpc_filtered_mdelem {
-  grpc_error_handle error;
-  grpc_mdelem md;
-};
-#define GRPC_FILTERED_ERROR(error) \
-  { (error), GRPC_MDNULL }
-#define GRPC_FILTERED_MDELEM(md) \
-  { GRPC_ERROR_NONE, (md) }
-#define GRPC_FILTERED_REMOVE() \
-  { GRPC_ERROR_NONE, GRPC_MDNULL }
-
 typedef grpc_filtered_mdelem (*grpc_metadata_batch_filter_func)(
     void* user_data, grpc_mdelem elem);
-grpc_error_handle grpc_metadata_batch_filter(
+inline GRPC_MUST_USE_RESULT grpc_error_handle grpc_metadata_batch_filter(
     grpc_metadata_batch* batch, grpc_metadata_batch_filter_func func,
-    void* user_data, const char* composite_error_string) GRPC_MUST_USE_RESULT;
+    void* user_data, const char* composite_error_string) {
+  return batch->Filter([=](grpc_mdelem elem) { return func(user_data, elem); },
+                       composite_error_string);
+}
 
-#ifndef NDEBUG
-void grpc_metadata_batch_assert_ok(grpc_metadata_batch* batch);
-#else
-#define grpc_metadata_batch_assert_ok(batch) \
-  do {                                       \
-  } while (0)
-#endif
+inline void grpc_metadata_batch_assert_ok(grpc_metadata_batch* batch) {
+  batch->AssertOk();
+}
 
-/// Copies \a src to \a dst.  \a storage must point to an array of
-/// \a grpc_linked_mdelem structs of at least the same size as \a src.
+/// Copies \a src to \a dst.
 ///
 /// For each mdelem in \a src, if the mdelem is of storage types
 /// GRPC_MDELEM_STORAGE_INTERNED or GRPC_MDELEM_STORAGE_ALLOCATED,
 /// refs the original mdelem for the copy.  Otherwise, makes a new
 /// mdelem that will hold its own refs to the key and value slices.
-///
-/// Currently used only in the retry code.
-void grpc_metadata_batch_copy(grpc_metadata_batch* src,
-                              grpc_metadata_batch* dst,
-                              grpc_linked_mdelem* storage);
-
-void grpc_metadata_batch_move(grpc_metadata_batch* src,
+void grpc_metadata_batch_copy(const grpc_metadata_batch* src,
                               grpc_metadata_batch* dst);
 
 #endif /* GRPC_CORE_LIB_TRANSPORT_METADATA_BATCH_H */
diff --git a/src/core/lib/transport/parsed_metadata.h b/src/core/lib/transport/parsed_metadata.h
new file mode 100644 (file)
index 0000000..305c369
--- /dev/null
@@ -0,0 +1,263 @@
+// 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.
+
+#ifndef GRPC_CORE_LIB_TRANSPORT_PARSED_METADATA_H
+#define GRPC_CORE_LIB_TRANSPORT_PARSED_METADATA_H
+
+#include <grpc/support/port_platform.h>
+
+#include <cstdint>
+#include <type_traits>
+
+#include "absl/meta/type_traits.h"
+#include "absl/strings/match.h"
+
+#include "src/core/lib/iomgr/error.h"
+#include "src/core/lib/surface/validate_metadata.h"
+#include "src/core/lib/transport/metadata.h"
+
+namespace grpc_core {
+
+namespace metadata_detail {
+
+// Helper to determine whether a traits metadata is inlinable inside a memento,
+// or (if not) we'll need to take the memory allocation path.
+template <typename Which>
+struct HasSimpleMemento {
+  static constexpr bool value =
+      std::is_trivial<typename Which::MementoType>::value &&
+      sizeof(typename Which::MementoType) <= sizeof(intptr_t);
+};
+
+}  // namespace metadata_detail
+
+// A parsed metadata value.
+// This type captures a type erased MementoType from one trait of
+// MetadataContainer, and provides utilities to manipulate that and to set it on
+// a MetadataContainer.
+template <typename MetadataContainer>
+class ParsedMetadata {
+ public:
+  // Construct metadata from a trait Which of MetadataContainer.
+  // Two versions: the first is for simple inlinable mementos, and the second
+  // forces an allocation.
+  template <typename Which>
+  ParsedMetadata(
+      Which,
+      absl::enable_if_t<metadata_detail::HasSimpleMemento<Which>::value,
+                        typename Which::MementoType>
+          value,
+      uint32_t transport_size)
+      : vtable_(ParsedMetadata::template TrivialTraitVTable<Which>()),
+        value_(static_cast<intptr_t>(value)),
+        transport_size_(transport_size) {}
+  template <typename Which>
+  ParsedMetadata(
+      Which,
+      absl::enable_if_t<!metadata_detail::HasSimpleMemento<Which>::value,
+                        typename Which::MementoType>
+          value,
+      uint32_t transport_size)
+      : vtable_(ParsedMetadata::template NonTrivialTraitVTable<Which>()),
+        value_(
+            reinterpret_cast<intptr_t>(new typename Which::MementoType(value))),
+        transport_size_(transport_size) {}
+  // Takes ownership of elem
+  explicit ParsedMetadata(grpc_mdelem elem)
+      : vtable_(grpc_is_binary_header_internal(GRPC_MDKEY(elem))
+                    ? MdelemVtable<true>()
+                    : MdelemVtable<false>()),
+        value_(static_cast<intptr_t>(elem.payload)),
+        transport_size_(GRPC_MDELEM_LENGTH(elem)) {}
+  ParsedMetadata() : vtable_(EmptyVTable()), value_(0), transport_size_(0) {}
+  ~ParsedMetadata() { vtable_->destroy(value_); }
+
+  // Non copyable, but movable.
+  ParsedMetadata(const ParsedMetadata&) = delete;
+  ParsedMetadata& operator=(const ParsedMetadata&) = delete;
+  ParsedMetadata(ParsedMetadata&& other) noexcept
+      : vtable_(other.vtable_),
+        value_(other.value_),
+        transport_size_(other.transport_size_) {
+    other.vtable_ = EmptyVTable();
+  }
+  ParsedMetadata& operator=(ParsedMetadata&& other) noexcept {
+    vtable_ = other.vtable_;
+    value_ = other.value_;
+    transport_size_ = other.transport_size_;
+    other.vtable_ = EmptyVTable();
+    return *this;
+  }
+
+  // Set this parsed value on a container.
+  GRPC_MUST_USE_RESULT grpc_error_handle
+  SetOnContainer(MetadataContainer* container) const {
+    return vtable_->set(value_, container);
+  }
+
+  // Is this a binary header or not?
+  bool is_binary_header() const { return vtable_->is_binary_header; }
+  // HTTP2 defined storage size of this metadatum.
+  uint32_t transport_size() const { return transport_size_; }
+  // Create a new parsed metadata with the same key but a different value.
+  ParsedMetadata WithNewValue(const grpc_slice& value) const {
+    return vtable_->with_new_value(value_, value);
+  }
+  std::string DebugString() const { return vtable_->debug_string(value_); }
+
+  // TODO(ctiller): move to transport
+  static uint32_t TransportSize(uint32_t key_size, uint32_t value_size) {
+    // TODO(ctiller): use hpack constant?
+    return key_size + value_size + 32;
+  }
+
+ private:
+  struct VTable {
+    const bool is_binary_header;
+    void (*const destroy)(intptr_t value);
+    grpc_error_handle (*const set)(intptr_t value,
+                                   MetadataContainer* container);
+    ParsedMetadata (*const with_new_value)(intptr_t value,
+                                           const grpc_slice& new_value);
+    std::string (*debug_string)(intptr_t value);
+  };
+
+  static const VTable* EmptyVTable();
+  template <typename Which>
+  static const VTable* TrivialTraitVTable();
+  template <typename Which>
+  static const VTable* NonTrivialTraitVTable();
+  template <bool kIsBinaryHeader>
+  static const VTable* MdelemVtable();
+
+  const VTable* vtable_;
+  intptr_t value_;
+  uint32_t transport_size_;
+};
+
+template <typename MetadataContainer>
+const typename ParsedMetadata<MetadataContainer>::VTable*
+ParsedMetadata<MetadataContainer>::EmptyVTable() {
+  static const VTable vtable = {
+      false,
+      // destroy
+      [](intptr_t) {},
+      // set
+      [](intptr_t, MetadataContainer*) { return GRPC_ERROR_NONE; },
+      // with_new_value
+      [](intptr_t, const grpc_slice&) { return ParsedMetadata(); },
+      // debug_string
+      [](intptr_t) -> std::string { return "empty"; }};
+  return &vtable;
+}
+
+template <typename MetadataContainer>
+template <typename Which>
+const typename ParsedMetadata<MetadataContainer>::VTable*
+ParsedMetadata<MetadataContainer>::TrivialTraitVTable() {
+  static const VTable vtable = {
+      absl::EndsWith(Which::key(), "-bin"),
+      // destroy
+      [](intptr_t) {},
+      // set
+      [](intptr_t value, MetadataContainer* map) {
+        map->Set(Which(), Which::MementoToValue(
+                              static_cast<typename Which::MementoType>(value)));
+        return GRPC_ERROR_NONE;
+      },
+      // with_new_value
+      [](intptr_t, const grpc_slice& value) {
+        return ParsedMetadata(
+            Which(), Which::ParseMemento(value),
+            TransportSize(strlen(Which::key()), GRPC_SLICE_LENGTH(value)));
+      },
+      // debug_string
+      [](intptr_t value) {
+        return absl::StrCat(
+            Which::key(), ": ",
+            Which::DisplayValue(
+                static_cast<typename Which::MementoType>(value)));
+      }};
+  return &vtable;
+}
+
+template <typename MetadataContainer>
+template <typename Which>
+const typename ParsedMetadata<MetadataContainer>::VTable*
+ParsedMetadata<MetadataContainer>::NonTrivialTraitVTable() {
+  static const VTable vtable = {
+      absl::EndsWith(Which::key(), "-bin"),
+      // destroy
+      [](intptr_t value) {
+        delete reinterpret_cast<typename Which::MementoType*>(value);
+      },
+      // set
+      [](intptr_t value, MetadataContainer* map) {
+        auto* p = reinterpret_cast<typename Which::MementoType*>(value);
+        map->Set(Which(), Which::MementoToValue(*p));
+        return GRPC_ERROR_NONE;
+      },
+      // with_new_value
+      [](intptr_t, const grpc_slice& value) {
+        return ParsedMetadata(
+            Which(), Which::ParseMemento(value),
+            TransportSize(strlen(Which::key()), GRPC_SLICE_LENGTH(value)));
+      },
+      // debug_string
+      [](intptr_t value) {
+        auto* p = reinterpret_cast<typename Which::MementoType*>(value);
+        return absl::StrCat(Which::key(), ": ", Which::DisplayValue(*p));
+      }};
+  return &vtable;
+}
+
+template <typename MetadataContainer>
+template <bool kIsBinaryHeader>
+const typename ParsedMetadata<MetadataContainer>::VTable*
+ParsedMetadata<MetadataContainer>::MdelemVtable() {
+  static const VTable vtable = {
+      kIsBinaryHeader,
+      // destroy
+      [](intptr_t value) { GRPC_MDELEM_UNREF(grpc_mdelem{uintptr_t(value)}); },
+      // set
+      [](intptr_t value, MetadataContainer* map) {
+        auto md = GRPC_MDELEM_REF(grpc_mdelem{uintptr_t(value)});
+        auto err = map->Append(md);
+        // If an error occurs, md is not consumed and we need to.
+        // This is an awful API, but that's why we're replacing it.
+        if (err != GRPC_ERROR_NONE) {
+          GRPC_MDELEM_UNREF(md);
+        }
+        return err;
+      },
+      // with_new_value
+      [](intptr_t value, const grpc_slice& value_slice) {
+        grpc_mdelem elem{uintptr_t(value)};
+        return ParsedMetadata(grpc_mdelem_from_slices(
+            static_cast<const ManagedMemorySlice&>(
+                grpc_slice_ref_internal(GRPC_MDKEY(elem))),
+            value_slice));
+      },
+      // debug_string
+      [](intptr_t value) {
+        grpc_mdelem elem{uintptr_t(value)};
+        return absl::StrCat(StringViewFromSlice(GRPC_MDKEY(elem)), ": ",
+                            StringViewFromSlice(GRPC_MDVALUE(elem)));
+      }};
+  return &vtable;
+}
+
+}  // namespace grpc_core
+
+#endif  // GRPC_CORE_LIB_TRANSPORT_PARSED_METADATA_H
index dbc98f4..c187a2b 100644 (file)
@@ -31,8 +31,8 @@ double PidController::Update(double error, double dt) {
   if (dt <= 0) return last_control_value_;
   /* integrate error using the trapezoid rule */
   error_integral_ += dt * (last_error_ + error) * 0.5;
-  error_integral_ = GPR_CLAMP(error_integral_, -args_.integral_range(),
-                              args_.integral_range());
+  error_integral_ = grpc_core::Clamp(error_integral_, -args_.integral_range(),
+                                     args_.integral_range());
   double diff_error = (error - last_error_) / dt;
   /* calculate derivative of control value vs time */
   double dc_dt = args_.gain_p() * error + args_.gain_i() * error_integral_ +
@@ -40,8 +40,8 @@ double PidController::Update(double error, double dt) {
   /* and perform trapezoidal integration */
   double new_control_value =
       last_control_value_ + dt * (last_dc_dt_ + dc_dt) * 0.5;
-  new_control_value = GPR_CLAMP(new_control_value, args_.min_control_value(),
-                                args_.max_control_value());
+  new_control_value = grpc_core::Clamp(
+      new_control_value, args_.min_control_value(), args_.max_control_value());
   last_error_ = error;
   last_dc_dt_ = dc_dt;
   last_control_value_ = new_control_value;
index 483a40f..71f4dee 100644 (file)
 
 #include "src/core/lib/slice/slice_internal.h"
 
-static constexpr uint8_t g_bytes[] = {
-    58,  112, 97,  116, 104, 58,  109, 101, 116, 104, 111, 100, 58,  115, 116,
-    97,  116, 117, 115, 58,  97,  117, 116, 104, 111, 114, 105, 116, 121, 58,
-    115, 99,  104, 101, 109, 101, 116, 101, 103, 114, 112, 99,  45,  109, 101,
-    115, 115, 97,  103, 101, 103, 114, 112, 99,  45,  115, 116, 97,  116, 117,
-    115, 103, 114, 112, 99,  45,  112, 97,  121, 108, 111, 97,  100, 45,  98,
-    105, 110, 103, 114, 112, 99,  45,  101, 110, 99,  111, 100, 105, 110, 103,
-    103, 114, 112, 99,  45,  97,  99,  99,  101, 112, 116, 45,  101, 110, 99,
-    111, 100, 105, 110, 103, 103, 114, 112, 99,  45,  115, 101, 114, 118, 101,
-    114, 45,  115, 116, 97,  116, 115, 45,  98,  105, 110, 103, 114, 112, 99,
-    45,  116, 97,  103, 115, 45,  98,  105, 110, 103, 114, 112, 99,  45,  116,
-    114, 97,  99,  101, 45,  98,  105, 110, 99,  111, 110, 116, 101, 110, 116,
-    45,  116, 121, 112, 101, 99,  111, 110, 116, 101, 110, 116, 45,  101, 110,
-    99,  111, 100, 105, 110, 103, 97,  99,  99,  101, 112, 116, 45,  101, 110,
-    99,  111, 100, 105, 110, 103, 103, 114, 112, 99,  45,  105, 110, 116, 101,
-    114, 110, 97,  108, 45,  101, 110, 99,  111, 100, 105, 110, 103, 45,  114,
-    101, 113, 117, 101, 115, 116, 103, 114, 112, 99,  45,  105, 110, 116, 101,
-    114, 110, 97,  108, 45,  115, 116, 114, 101, 97,  109, 45,  101, 110, 99,
-    111, 100, 105, 110, 103, 45,  114, 101, 113, 117, 101, 115, 116, 117, 115,
-    101, 114, 45,  97,  103, 101, 110, 116, 104, 111, 115, 116, 103, 114, 112,
-    99,  45,  112, 114, 101, 118, 105, 111, 117, 115, 45,  114, 112, 99,  45,
-    97,  116, 116, 101, 109, 112, 116, 115, 103, 114, 112, 99,  45,  114, 101,
-    116, 114, 121, 45,  112, 117, 115, 104, 98,  97,  99,  107, 45,  109, 115,
-    120, 45,  101, 110, 100, 112, 111, 105, 110, 116, 45,  108, 111, 97,  100,
-    45,  109, 101, 116, 114, 105, 99,  115, 45,  98,  105, 110, 103, 114, 112,
-    99,  45,  116, 105, 109, 101, 111, 117, 116, 49,  50,  51,  52,  103, 114,
-    112, 99,  46,  119, 97,  105, 116, 95,  102, 111, 114, 95,  114, 101, 97,
-    100, 121, 103, 114, 112, 99,  46,  116, 105, 109, 101, 111, 117, 116, 103,
-    114, 112, 99,  46,  109, 97,  120, 95,  114, 101, 113, 117, 101, 115, 116,
-    95,  109, 101, 115, 115, 97,  103, 101, 95,  98,  121, 116, 101, 115, 103,
-    114, 112, 99,  46,  109, 97,  120, 95,  114, 101, 115, 112, 111, 110, 115,
-    101, 95,  109, 101, 115, 115, 97,  103, 101, 95,  98,  121, 116, 101, 115,
-    47,  103, 114, 112, 99,  46,  108, 98,  46,  118, 49,  46,  76,  111, 97,
-    100, 66,  97,  108, 97,  110, 99,  101, 114, 47,  66,  97,  108, 97,  110,
-    99,  101, 76,  111, 97,  100, 47,  101, 110, 118, 111, 121, 46,  115, 101,
-    114, 118, 105, 99,  101, 46,  108, 111, 97,  100, 95,  115, 116, 97,  116,
-    115, 46,  118, 50,  46,  76,  111, 97,  100, 82,  101, 112, 111, 114, 116,
-    105, 110, 103, 83,  101, 114, 118, 105, 99,  101, 47,  83,  116, 114, 101,
-    97,  109, 76,  111, 97,  100, 83,  116, 97,  116, 115, 47,  101, 110, 118,
-    111, 121, 46,  115, 101, 114, 118, 105, 99,  101, 46,  108, 111, 97,  100,
-    95,  115, 116, 97,  116, 115, 46,  118, 51,  46,  76,  111, 97,  100, 82,
-    101, 112, 111, 114, 116, 105, 110, 103, 83,  101, 114, 118, 105, 99,  101,
-    47,  83,  116, 114, 101, 97,  109, 76,  111, 97,  100, 83,  116, 97,  116,
-    115, 47,  103, 114, 112, 99,  46,  104, 101, 97,  108, 116, 104, 46,  118,
-    49,  46,  72,  101, 97,  108, 116, 104, 47,  87,  97,  116, 99,  104, 47,
-    101, 110, 118, 111, 121, 46,  115, 101, 114, 118, 105, 99,  101, 46,  100,
-    105, 115, 99,  111, 118, 101, 114, 121, 46,  118, 50,  46,  65,  103, 103,
-    114, 101, 103, 97,  116, 101, 100, 68,  105, 115, 99,  111, 118, 101, 114,
-    121, 83,  101, 114, 118, 105, 99,  101, 47,  83,  116, 114, 101, 97,  109,
-    65,  103, 103, 114, 101, 103, 97,  116, 101, 100, 82,  101, 115, 111, 117,
-    114, 99,  101, 115, 47,  101, 110, 118, 111, 121, 46,  115, 101, 114, 118,
-    105, 99,  101, 46,  100, 105, 115, 99,  111, 118, 101, 114, 121, 46,  118,
-    51,  46,  65,  103, 103, 114, 101, 103, 97,  116, 101, 100, 68,  105, 115,
-    99,  111, 118, 101, 114, 121, 83,  101, 114, 118, 105, 99,  101, 47,  83,
-    116, 114, 101, 97,  109, 65,  103, 103, 114, 101, 103, 97,  116, 101, 100,
-    82,  101, 115, 111, 117, 114, 99,  101, 115, 100, 101, 102, 108, 97,  116,
-    101, 103, 122, 105, 112, 115, 116, 114, 101, 97,  109, 47,  103, 122, 105,
-    112, 71,  69,  84,  80,  79,  83,  84,  47,  47,  105, 110, 100, 101, 120,
-    46,  104, 116, 109, 108, 104, 116, 116, 112, 104, 116, 116, 112, 115, 50,
-    48,  48,  50,  48,  52,  50,  48,  54,  51,  48,  52,  52,  48,  48,  52,
-    48,  52,  53,  48,  48,  97,  99,  99,  101, 112, 116, 45,  99,  104, 97,
-    114, 115, 101, 116, 103, 122, 105, 112, 44,  32,  100, 101, 102, 108, 97,
-    116, 101, 97,  99,  99,  101, 112, 116, 45,  108, 97,  110, 103, 117, 97,
-    103, 101, 97,  99,  99,  101, 112, 116, 45,  114, 97,  110, 103, 101, 115,
-    97,  99,  99,  101, 112, 116, 97,  99,  99,  101, 115, 115, 45,  99,  111,
-    110, 116, 114, 111, 108, 45,  97,  108, 108, 111, 119, 45,  111, 114, 105,
-    103, 105, 110, 97,  103, 101, 97,  108, 108, 111, 119, 97,  117, 116, 104,
-    111, 114, 105, 122, 97,  116, 105, 111, 110, 99,  97,  99,  104, 101, 45,
-    99,  111, 110, 116, 114, 111, 108, 99,  111, 110, 116, 101, 110, 116, 45,
-    100, 105, 115, 112, 111, 115, 105, 116, 105, 111, 110, 99,  111, 110, 116,
-    101, 110, 116, 45,  108, 97,  110, 103, 117, 97,  103, 101, 99,  111, 110,
-    116, 101, 110, 116, 45,  108, 101, 110, 103, 116, 104, 99,  111, 110, 116,
-    101, 110, 116, 45,  108, 111, 99,  97,  116, 105, 111, 110, 99,  111, 110,
-    116, 101, 110, 116, 45,  114, 97,  110, 103, 101, 99,  111, 111, 107, 105,
-    101, 100, 97,  116, 101, 101, 116, 97,  103, 101, 120, 112, 101, 99,  116,
-    101, 120, 112, 105, 114, 101, 115, 102, 114, 111, 109, 105, 102, 45,  109,
-    97,  116, 99,  104, 105, 102, 45,  109, 111, 100, 105, 102, 105, 101, 100,
-    45,  115, 105, 110, 99,  101, 105, 102, 45,  110, 111, 110, 101, 45,  109,
-    97,  116, 99,  104, 105, 102, 45,  114, 97,  110, 103, 101, 105, 102, 45,
-    117, 110, 109, 111, 100, 105, 102, 105, 101, 100, 45,  115, 105, 110, 99,
-    101, 108, 97,  115, 116, 45,  109, 111, 100, 105, 102, 105, 101, 100, 108,
-    105, 110, 107, 108, 111, 99,  97,  116, 105, 111, 110, 109, 97,  120, 45,
-    102, 111, 114, 119, 97,  114, 100, 115, 112, 114, 111, 120, 121, 45,  97,
-    117, 116, 104, 101, 110, 116, 105, 99,  97,  116, 101, 112, 114, 111, 120,
-    121, 45,  97,  117, 116, 104, 111, 114, 105, 122, 97,  116, 105, 111, 110,
-    114, 97,  110, 103, 101, 114, 101, 102, 101, 114, 101, 114, 114, 101, 102,
-    114, 101, 115, 104, 114, 101, 116, 114, 121, 45,  97,  102, 116, 101, 114,
-    115, 101, 114, 118, 101, 114, 115, 101, 116, 45,  99,  111, 111, 107, 105,
-    101, 115, 116, 114, 105, 99,  116, 45,  116, 114, 97,  110, 115, 112, 111,
-    114, 116, 45,  115, 101, 99,  117, 114, 105, 116, 121, 116, 114, 97,  110,
-    115, 102, 101, 114, 45,  101, 110, 99,  111, 100, 105, 110, 103, 118, 97,
-    114, 121, 118, 105, 97,  119, 119, 119, 45,  97,  117, 116, 104, 101, 110,
-    116, 105, 99,  97,  116, 101, 48,  105, 100, 101, 110, 116, 105, 116, 121,
-    116, 114, 97,  105, 108, 101, 114, 115, 97,  112, 112, 108, 105, 99,  97,
-    116, 105, 111, 110, 47,  103, 114, 112, 99,  103, 114, 112, 99,  80,  85,
-    84,  108, 98,  45,  99,  111, 115, 116, 45,  98,  105, 110, 105, 100, 101,
-    110, 116, 105, 116, 121, 44,  100, 101, 102, 108, 97,  116, 101, 105, 100,
-    101, 110, 116, 105, 116, 121, 44,  103, 122, 105, 112, 100, 101, 102, 108,
-    97,  116, 101, 44,  103, 122, 105, 112, 105, 100, 101, 110, 116, 105, 116,
-    121, 44,  100, 101, 102, 108, 97,  116, 101, 44,  103, 122, 105, 112};
-
-grpc_slice_refcount grpc_core::StaticSliceRefcount::kStaticSubRefcount;
-
 namespace grpc_core {
-struct StaticMetadataCtx {
-#ifndef NDEBUG
-  const uint64_t init_canary = kGrpcStaticMetadataInitCanary;
-#endif
-  StaticSliceRefcount refcounts[GRPC_STATIC_MDSTR_COUNT] = {
-
-      StaticSliceRefcount(0),   StaticSliceRefcount(1),
-      StaticSliceRefcount(2),   StaticSliceRefcount(3),
-      StaticSliceRefcount(4),   StaticSliceRefcount(5),
-      StaticSliceRefcount(6),   StaticSliceRefcount(7),
-      StaticSliceRefcount(8),   StaticSliceRefcount(9),
-      StaticSliceRefcount(10),  StaticSliceRefcount(11),
-      StaticSliceRefcount(12),  StaticSliceRefcount(13),
-      StaticSliceRefcount(14),  StaticSliceRefcount(15),
-      StaticSliceRefcount(16),  StaticSliceRefcount(17),
-      StaticSliceRefcount(18),  StaticSliceRefcount(19),
-      StaticSliceRefcount(20),  StaticSliceRefcount(21),
-      StaticSliceRefcount(22),  StaticSliceRefcount(23),
-      StaticSliceRefcount(24),  StaticSliceRefcount(25),
-      StaticSliceRefcount(26),  StaticSliceRefcount(27),
-      StaticSliceRefcount(28),  StaticSliceRefcount(29),
-      StaticSliceRefcount(30),  StaticSliceRefcount(31),
-      StaticSliceRefcount(32),  StaticSliceRefcount(33),
-      StaticSliceRefcount(34),  StaticSliceRefcount(35),
-      StaticSliceRefcount(36),  StaticSliceRefcount(37),
-      StaticSliceRefcount(38),  StaticSliceRefcount(39),
-      StaticSliceRefcount(40),  StaticSliceRefcount(41),
-      StaticSliceRefcount(42),  StaticSliceRefcount(43),
-      StaticSliceRefcount(44),  StaticSliceRefcount(45),
-      StaticSliceRefcount(46),  StaticSliceRefcount(47),
-      StaticSliceRefcount(48),  StaticSliceRefcount(49),
-      StaticSliceRefcount(50),  StaticSliceRefcount(51),
-      StaticSliceRefcount(52),  StaticSliceRefcount(53),
-      StaticSliceRefcount(54),  StaticSliceRefcount(55),
-      StaticSliceRefcount(56),  StaticSliceRefcount(57),
-      StaticSliceRefcount(58),  StaticSliceRefcount(59),
-      StaticSliceRefcount(60),  StaticSliceRefcount(61),
-      StaticSliceRefcount(62),  StaticSliceRefcount(63),
-      StaticSliceRefcount(64),  StaticSliceRefcount(65),
-      StaticSliceRefcount(66),  StaticSliceRefcount(67),
-      StaticSliceRefcount(68),  StaticSliceRefcount(69),
-      StaticSliceRefcount(70),  StaticSliceRefcount(71),
-      StaticSliceRefcount(72),  StaticSliceRefcount(73),
-      StaticSliceRefcount(74),  StaticSliceRefcount(75),
-      StaticSliceRefcount(76),  StaticSliceRefcount(77),
-      StaticSliceRefcount(78),  StaticSliceRefcount(79),
-      StaticSliceRefcount(80),  StaticSliceRefcount(81),
-      StaticSliceRefcount(82),  StaticSliceRefcount(83),
-      StaticSliceRefcount(84),  StaticSliceRefcount(85),
-      StaticSliceRefcount(86),  StaticSliceRefcount(87),
-      StaticSliceRefcount(88),  StaticSliceRefcount(89),
-      StaticSliceRefcount(90),  StaticSliceRefcount(91),
-      StaticSliceRefcount(92),  StaticSliceRefcount(93),
-      StaticSliceRefcount(94),  StaticSliceRefcount(95),
-      StaticSliceRefcount(96),  StaticSliceRefcount(97),
-      StaticSliceRefcount(98),  StaticSliceRefcount(99),
-      StaticSliceRefcount(100), StaticSliceRefcount(101),
-      StaticSliceRefcount(102), StaticSliceRefcount(103),
-      StaticSliceRefcount(104), StaticSliceRefcount(105),
-      StaticSliceRefcount(106), StaticSliceRefcount(107),
-      StaticSliceRefcount(108), StaticSliceRefcount(109),
-  };
-
-  const StaticMetadataSlice slices[GRPC_STATIC_MDSTR_COUNT] = {
-
-      grpc_core::StaticMetadataSlice(&refcounts[0].base, 5, g_bytes + 0),
-      grpc_core::StaticMetadataSlice(&refcounts[1].base, 7, g_bytes + 5),
-      grpc_core::StaticMetadataSlice(&refcounts[2].base, 7, g_bytes + 12),
-      grpc_core::StaticMetadataSlice(&refcounts[3].base, 10, g_bytes + 19),
-      grpc_core::StaticMetadataSlice(&refcounts[4].base, 7, g_bytes + 29),
-      grpc_core::StaticMetadataSlice(&refcounts[5].base, 2, g_bytes + 36),
-      grpc_core::StaticMetadataSlice(&refcounts[6].base, 12, g_bytes + 38),
-      grpc_core::StaticMetadataSlice(&refcounts[7].base, 11, g_bytes + 50),
-      grpc_core::StaticMetadataSlice(&refcounts[8].base, 16, g_bytes + 61),
-      grpc_core::StaticMetadataSlice(&refcounts[9].base, 13, g_bytes + 77),
-      grpc_core::StaticMetadataSlice(&refcounts[10].base, 20, g_bytes + 90),
-      grpc_core::StaticMetadataSlice(&refcounts[11].base, 21, g_bytes + 110),
-      grpc_core::StaticMetadataSlice(&refcounts[12].base, 13, g_bytes + 131),
-      grpc_core::StaticMetadataSlice(&refcounts[13].base, 14, g_bytes + 144),
-      grpc_core::StaticMetadataSlice(&refcounts[14].base, 12, g_bytes + 158),
-      grpc_core::StaticMetadataSlice(&refcounts[15].base, 16, g_bytes + 170),
-      grpc_core::StaticMetadataSlice(&refcounts[16].base, 15, g_bytes + 186),
-      grpc_core::StaticMetadataSlice(&refcounts[17].base, 30, g_bytes + 201),
-      grpc_core::StaticMetadataSlice(&refcounts[18].base, 37, g_bytes + 231),
-      grpc_core::StaticMetadataSlice(&refcounts[19].base, 10, g_bytes + 268),
-      grpc_core::StaticMetadataSlice(&refcounts[20].base, 4, g_bytes + 278),
-      grpc_core::StaticMetadataSlice(&refcounts[21].base, 26, g_bytes + 282),
-      grpc_core::StaticMetadataSlice(&refcounts[22].base, 22, g_bytes + 308),
-      grpc_core::StaticMetadataSlice(&refcounts[23].base, 27, g_bytes + 330),
-      grpc_core::StaticMetadataSlice(&refcounts[24].base, 12, g_bytes + 357),
-      grpc_core::StaticMetadataSlice(&refcounts[25].base, 1, g_bytes + 369),
-      grpc_core::StaticMetadataSlice(&refcounts[26].base, 1, g_bytes + 370),
-      grpc_core::StaticMetadataSlice(&refcounts[27].base, 1, g_bytes + 371),
-      grpc_core::StaticMetadataSlice(&refcounts[28].base, 1, g_bytes + 372),
-      grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-      grpc_core::StaticMetadataSlice(&refcounts[30].base, 19, g_bytes + 373),
-      grpc_core::StaticMetadataSlice(&refcounts[31].base, 12, g_bytes + 392),
-      grpc_core::StaticMetadataSlice(&refcounts[32].base, 30, g_bytes + 404),
-      grpc_core::StaticMetadataSlice(&refcounts[33].base, 31, g_bytes + 434),
-      grpc_core::StaticMetadataSlice(&refcounts[34].base, 36, g_bytes + 465),
-      grpc_core::StaticMetadataSlice(&refcounts[35].base, 65, g_bytes + 501),
-      grpc_core::StaticMetadataSlice(&refcounts[36].base, 65, g_bytes + 566),
-      grpc_core::StaticMetadataSlice(&refcounts[37].base, 28, g_bytes + 631),
-      grpc_core::StaticMetadataSlice(&refcounts[38].base, 80, g_bytes + 659),
-      grpc_core::StaticMetadataSlice(&refcounts[39].base, 80, g_bytes + 739),
-      grpc_core::StaticMetadataSlice(&refcounts[40].base, 7, g_bytes + 819),
-      grpc_core::StaticMetadataSlice(&refcounts[41].base, 4, g_bytes + 826),
-      grpc_core::StaticMetadataSlice(&refcounts[42].base, 11, g_bytes + 830),
-      grpc_core::StaticMetadataSlice(&refcounts[43].base, 3, g_bytes + 841),
-      grpc_core::StaticMetadataSlice(&refcounts[44].base, 4, g_bytes + 844),
-      grpc_core::StaticMetadataSlice(&refcounts[45].base, 1, g_bytes + 848),
-      grpc_core::StaticMetadataSlice(&refcounts[46].base, 11, g_bytes + 849),
-      grpc_core::StaticMetadataSlice(&refcounts[47].base, 4, g_bytes + 860),
-      grpc_core::StaticMetadataSlice(&refcounts[48].base, 5, g_bytes + 864),
-      grpc_core::StaticMetadataSlice(&refcounts[49].base, 3, g_bytes + 869),
-      grpc_core::StaticMetadataSlice(&refcounts[50].base, 3, g_bytes + 872),
-      grpc_core::StaticMetadataSlice(&refcounts[51].base, 3, g_bytes + 875),
-      grpc_core::StaticMetadataSlice(&refcounts[52].base, 3, g_bytes + 878),
-      grpc_core::StaticMetadataSlice(&refcounts[53].base, 3, g_bytes + 881),
-      grpc_core::StaticMetadataSlice(&refcounts[54].base, 3, g_bytes + 884),
-      grpc_core::StaticMetadataSlice(&refcounts[55].base, 3, g_bytes + 887),
-      grpc_core::StaticMetadataSlice(&refcounts[56].base, 14, g_bytes + 890),
-      grpc_core::StaticMetadataSlice(&refcounts[57].base, 13, g_bytes + 904),
-      grpc_core::StaticMetadataSlice(&refcounts[58].base, 15, g_bytes + 917),
-      grpc_core::StaticMetadataSlice(&refcounts[59].base, 13, g_bytes + 932),
-      grpc_core::StaticMetadataSlice(&refcounts[60].base, 6, g_bytes + 945),
-      grpc_core::StaticMetadataSlice(&refcounts[61].base, 27, g_bytes + 951),
-      grpc_core::StaticMetadataSlice(&refcounts[62].base, 3, g_bytes + 978),
-      grpc_core::StaticMetadataSlice(&refcounts[63].base, 5, g_bytes + 981),
-      grpc_core::StaticMetadataSlice(&refcounts[64].base, 13, g_bytes + 986),
-      grpc_core::StaticMetadataSlice(&refcounts[65].base, 13, g_bytes + 999),
-      grpc_core::StaticMetadataSlice(&refcounts[66].base, 19, g_bytes + 1012),
-      grpc_core::StaticMetadataSlice(&refcounts[67].base, 16, g_bytes + 1031),
-      grpc_core::StaticMetadataSlice(&refcounts[68].base, 14, g_bytes + 1047),
-      grpc_core::StaticMetadataSlice(&refcounts[69].base, 16, g_bytes + 1061),
-      grpc_core::StaticMetadataSlice(&refcounts[70].base, 13, g_bytes + 1077),
-      grpc_core::StaticMetadataSlice(&refcounts[71].base, 6, g_bytes + 1090),
-      grpc_core::StaticMetadataSlice(&refcounts[72].base, 4, g_bytes + 1096),
-      grpc_core::StaticMetadataSlice(&refcounts[73].base, 4, g_bytes + 1100),
-      grpc_core::StaticMetadataSlice(&refcounts[74].base, 6, g_bytes + 1104),
-      grpc_core::StaticMetadataSlice(&refcounts[75].base, 7, g_bytes + 1110),
-      grpc_core::StaticMetadataSlice(&refcounts[76].base, 4, g_bytes + 1117),
-      grpc_core::StaticMetadataSlice(&refcounts[77].base, 8, g_bytes + 1121),
-      grpc_core::StaticMetadataSlice(&refcounts[78].base, 17, g_bytes + 1129),
-      grpc_core::StaticMetadataSlice(&refcounts[79].base, 13, g_bytes + 1146),
-      grpc_core::StaticMetadataSlice(&refcounts[80].base, 8, g_bytes + 1159),
-      grpc_core::StaticMetadataSlice(&refcounts[81].base, 19, g_bytes + 1167),
-      grpc_core::StaticMetadataSlice(&refcounts[82].base, 13, g_bytes + 1186),
-      grpc_core::StaticMetadataSlice(&refcounts[83].base, 4, g_bytes + 1199),
-      grpc_core::StaticMetadataSlice(&refcounts[84].base, 8, g_bytes + 1203),
-      grpc_core::StaticMetadataSlice(&refcounts[85].base, 12, g_bytes + 1211),
-      grpc_core::StaticMetadataSlice(&refcounts[86].base, 18, g_bytes + 1223),
-      grpc_core::StaticMetadataSlice(&refcounts[87].base, 19, g_bytes + 1241),
-      grpc_core::StaticMetadataSlice(&refcounts[88].base, 5, g_bytes + 1260),
-      grpc_core::StaticMetadataSlice(&refcounts[89].base, 7, g_bytes + 1265),
-      grpc_core::StaticMetadataSlice(&refcounts[90].base, 7, g_bytes + 1272),
-      grpc_core::StaticMetadataSlice(&refcounts[91].base, 11, g_bytes + 1279),
-      grpc_core::StaticMetadataSlice(&refcounts[92].base, 6, g_bytes + 1290),
-      grpc_core::StaticMetadataSlice(&refcounts[93].base, 10, g_bytes + 1296),
-      grpc_core::StaticMetadataSlice(&refcounts[94].base, 25, g_bytes + 1306),
-      grpc_core::StaticMetadataSlice(&refcounts[95].base, 17, g_bytes + 1331),
-      grpc_core::StaticMetadataSlice(&refcounts[96].base, 4, g_bytes + 1348),
-      grpc_core::StaticMetadataSlice(&refcounts[97].base, 3, g_bytes + 1352),
-      grpc_core::StaticMetadataSlice(&refcounts[98].base, 16, g_bytes + 1355),
-      grpc_core::StaticMetadataSlice(&refcounts[99].base, 1, g_bytes + 1371),
-      grpc_core::StaticMetadataSlice(&refcounts[100].base, 8, g_bytes + 1372),
-      grpc_core::StaticMetadataSlice(&refcounts[101].base, 8, g_bytes + 1380),
-      grpc_core::StaticMetadataSlice(&refcounts[102].base, 16, g_bytes + 1388),
-      grpc_core::StaticMetadataSlice(&refcounts[103].base, 4, g_bytes + 1404),
-      grpc_core::StaticMetadataSlice(&refcounts[104].base, 3, g_bytes + 1408),
-      grpc_core::StaticMetadataSlice(&refcounts[105].base, 11, g_bytes + 1411),
-      grpc_core::StaticMetadataSlice(&refcounts[106].base, 16, g_bytes + 1422),
-      grpc_core::StaticMetadataSlice(&refcounts[107].base, 13, g_bytes + 1438),
-      grpc_core::StaticMetadataSlice(&refcounts[108].base, 12, g_bytes + 1451),
-      grpc_core::StaticMetadataSlice(&refcounts[109].base, 21, g_bytes + 1463),
-  };
-  StaticMetadata static_mdelem_table[GRPC_STATIC_MDELEM_COUNT] = {
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[3].base, 10, g_bytes + 19),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          0),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[1].base, 7, g_bytes + 5),
-          grpc_core::StaticMetadataSlice(&refcounts[43].base, 3, g_bytes + 841),
-          1),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[1].base, 7, g_bytes + 5),
-          grpc_core::StaticMetadataSlice(&refcounts[44].base, 4, g_bytes + 844),
-          2),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[0].base, 5, g_bytes + 0),
-          grpc_core::StaticMetadataSlice(&refcounts[45].base, 1, g_bytes + 848),
-          3),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[0].base, 5, g_bytes + 0),
-          grpc_core::StaticMetadataSlice(&refcounts[46].base, 11,
-                                         g_bytes + 849),
-          4),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[4].base, 7, g_bytes + 29),
-          grpc_core::StaticMetadataSlice(&refcounts[47].base, 4, g_bytes + 860),
-          5),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[4].base, 7, g_bytes + 29),
-          grpc_core::StaticMetadataSlice(&refcounts[48].base, 5, g_bytes + 864),
-          6),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[2].base, 7, g_bytes + 12),
-          grpc_core::StaticMetadataSlice(&refcounts[49].base, 3, g_bytes + 869),
-          7),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[2].base, 7, g_bytes + 12),
-          grpc_core::StaticMetadataSlice(&refcounts[50].base, 3, g_bytes + 872),
-          8),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[2].base, 7, g_bytes + 12),
-          grpc_core::StaticMetadataSlice(&refcounts[51].base, 3, g_bytes + 875),
-          9),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[2].base, 7, g_bytes + 12),
-          grpc_core::StaticMetadataSlice(&refcounts[52].base, 3, g_bytes + 878),
-          10),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[2].base, 7, g_bytes + 12),
-          grpc_core::StaticMetadataSlice(&refcounts[53].base, 3, g_bytes + 881),
-          11),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[2].base, 7, g_bytes + 12),
-          grpc_core::StaticMetadataSlice(&refcounts[54].base, 3, g_bytes + 884),
-          12),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[2].base, 7, g_bytes + 12),
-          grpc_core::StaticMetadataSlice(&refcounts[55].base, 3, g_bytes + 887),
-          13),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[56].base, 14,
-                                         g_bytes + 890),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          14),
-      StaticMetadata(grpc_core::StaticMetadataSlice(&refcounts[16].base, 15,
-                                                    g_bytes + 186),
-                     grpc_core::StaticMetadataSlice(&refcounts[57].base, 13,
-                                                    g_bytes + 904),
-                     15),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[58].base, 15,
-                                         g_bytes + 917),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          16),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[59].base, 13,
-                                         g_bytes + 932),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          17),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[60].base, 6, g_bytes + 945),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          18),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[61].base, 27,
-                                         g_bytes + 951),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          19),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[62].base, 3, g_bytes + 978),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          20),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[63].base, 5, g_bytes + 981),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          21),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[64].base, 13,
-                                         g_bytes + 986),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          22),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[65].base, 13,
-                                         g_bytes + 999),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          23),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[66].base, 19,
-                                         g_bytes + 1012),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          24),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[15].base, 16,
-                                         g_bytes + 170),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          25),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[67].base, 16,
-                                         g_bytes + 1031),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          26),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[68].base, 14,
-                                         g_bytes + 1047),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          27),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[69].base, 16,
-                                         g_bytes + 1061),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          28),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[70].base, 13,
-                                         g_bytes + 1077),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          29),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[14].base, 12,
-                                         g_bytes + 158),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          30),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[71].base, 6,
-                                         g_bytes + 1090),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          31),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[72].base, 4,
-                                         g_bytes + 1096),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          32),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[73].base, 4,
-                                         g_bytes + 1100),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          33),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[74].base, 6,
-                                         g_bytes + 1104),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          34),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[75].base, 7,
-                                         g_bytes + 1110),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          35),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[76].base, 4,
-                                         g_bytes + 1117),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          36),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[20].base, 4, g_bytes + 278),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          37),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[77].base, 8,
-                                         g_bytes + 1121),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          38),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[78].base, 17,
-                                         g_bytes + 1129),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          39),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[79].base, 13,
-                                         g_bytes + 1146),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          40),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[80].base, 8,
-                                         g_bytes + 1159),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          41),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[81].base, 19,
-                                         g_bytes + 1167),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          42),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[82].base, 13,
-                                         g_bytes + 1186),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          43),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[83].base, 4,
-                                         g_bytes + 1199),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          44),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[84].base, 8,
-                                         g_bytes + 1203),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          45),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[85].base, 12,
-                                         g_bytes + 1211),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          46),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[86].base, 18,
-                                         g_bytes + 1223),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          47),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[87].base, 19,
-                                         g_bytes + 1241),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          48),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[88].base, 5,
-                                         g_bytes + 1260),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          49),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[89].base, 7,
-                                         g_bytes + 1265),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          50),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[90].base, 7,
-                                         g_bytes + 1272),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          51),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[91].base, 11,
-                                         g_bytes + 1279),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          52),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[92].base, 6,
-                                         g_bytes + 1290),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          53),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[93].base, 10,
-                                         g_bytes + 1296),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          54),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[94].base, 25,
-                                         g_bytes + 1306),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          55),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[95].base, 17,
-                                         g_bytes + 1331),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          56),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[19].base, 10,
-                                         g_bytes + 268),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          57),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[96].base, 4,
-                                         g_bytes + 1348),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          58),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[97].base, 3,
-                                         g_bytes + 1352),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          59),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[98].base, 16,
-                                         g_bytes + 1355),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          60),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[7].base, 11, g_bytes + 50),
-          grpc_core::StaticMetadataSlice(&refcounts[99].base, 1,
-                                         g_bytes + 1371),
-          61),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[7].base, 11, g_bytes + 50),
-          grpc_core::StaticMetadataSlice(&refcounts[25].base, 1, g_bytes + 369),
-          62),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[7].base, 11, g_bytes + 50),
-          grpc_core::StaticMetadataSlice(&refcounts[26].base, 1, g_bytes + 370),
-          63),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[9].base, 13, g_bytes + 77),
-          grpc_core::StaticMetadataSlice(&refcounts[100].base, 8,
-                                         g_bytes + 1372),
-          64),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[9].base, 13, g_bytes + 77),
-          grpc_core::StaticMetadataSlice(&refcounts[41].base, 4, g_bytes + 826),
-          65),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[9].base, 13, g_bytes + 77),
-          grpc_core::StaticMetadataSlice(&refcounts[40].base, 7, g_bytes + 819),
-          66),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[5].base, 2, g_bytes + 36),
-          grpc_core::StaticMetadataSlice(&refcounts[101].base, 8,
-                                         g_bytes + 1380),
-          67),
-      StaticMetadata(grpc_core::StaticMetadataSlice(&refcounts[14].base, 12,
-                                                    g_bytes + 158),
-                     grpc_core::StaticMetadataSlice(&refcounts[102].base, 16,
-                                                    g_bytes + 1388),
-                     68),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[4].base, 7, g_bytes + 29),
-          grpc_core::StaticMetadataSlice(&refcounts[103].base, 4,
-                                         g_bytes + 1404),
-          69),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[1].base, 7, g_bytes + 5),
-          grpc_core::StaticMetadataSlice(&refcounts[104].base, 3,
-                                         g_bytes + 1408),
-          70),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[16].base, 15,
-                                         g_bytes + 186),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          71),
-      StaticMetadata(grpc_core::StaticMetadataSlice(&refcounts[15].base, 16,
-                                                    g_bytes + 170),
-                     grpc_core::StaticMetadataSlice(&refcounts[100].base, 8,
-                                                    g_bytes + 1372),
-                     72),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[15].base, 16,
-                                         g_bytes + 170),
-          grpc_core::StaticMetadataSlice(&refcounts[41].base, 4, g_bytes + 826),
-          73),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[105].base, 11,
-                                         g_bytes + 1411),
-          grpc_core::StaticMetadataSlice(&refcounts[29].base, 0, g_bytes + 373),
-          74),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[10].base, 20, g_bytes + 90),
-          grpc_core::StaticMetadataSlice(&refcounts[100].base, 8,
-                                         g_bytes + 1372),
-          75),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[10].base, 20, g_bytes + 90),
-          grpc_core::StaticMetadataSlice(&refcounts[40].base, 7, g_bytes + 819),
-          76),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[10].base, 20, g_bytes + 90),
-          grpc_core::StaticMetadataSlice(&refcounts[106].base, 16,
-                                         g_bytes + 1422),
-          77),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[10].base, 20, g_bytes + 90),
-          grpc_core::StaticMetadataSlice(&refcounts[41].base, 4, g_bytes + 826),
-          78),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[10].base, 20, g_bytes + 90),
-          grpc_core::StaticMetadataSlice(&refcounts[107].base, 13,
-                                         g_bytes + 1438),
-          79),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[10].base, 20, g_bytes + 90),
-          grpc_core::StaticMetadataSlice(&refcounts[108].base, 12,
-                                         g_bytes + 1451),
-          80),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[10].base, 20, g_bytes + 90),
-          grpc_core::StaticMetadataSlice(&refcounts[109].base, 21,
-                                         g_bytes + 1463),
-          81),
-      StaticMetadata(grpc_core::StaticMetadataSlice(&refcounts[16].base, 15,
-                                                    g_bytes + 186),
-                     grpc_core::StaticMetadataSlice(&refcounts[100].base, 8,
-                                                    g_bytes + 1372),
-                     82),
-      StaticMetadata(
-          grpc_core::StaticMetadataSlice(&refcounts[16].base, 15,
-                                         g_bytes + 186),
-          grpc_core::StaticMetadataSlice(&refcounts[41].base, 4, g_bytes + 826),
-          83),
-      StaticMetadata(grpc_core::StaticMetadataSlice(&refcounts[16].base, 15,
-                                                    g_bytes + 186),
-                     grpc_core::StaticMetadataSlice(&refcounts[107].base, 13,
-                                                    g_bytes + 1438),
-                     84),
-  };
+StaticMetadata g_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT] = {
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[3].base, 10,
+                       g_static_metadata_bytes + 19),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   0),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[1].base, 7,
+                       g_static_metadata_bytes + 5),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[44].base, 3,
+                       g_static_metadata_bytes + 849),
+                   1),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[1].base, 7,
+                       g_static_metadata_bytes + 5),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[45].base, 4,
+                       g_static_metadata_bytes + 852),
+                   2),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[0].base, 5,
+                       g_static_metadata_bytes + 0),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[46].base, 1,
+                       g_static_metadata_bytes + 856),
+                   3),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[0].base, 5,
+                       g_static_metadata_bytes + 0),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[47].base, 11,
+                       g_static_metadata_bytes + 857),
+                   4),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[4].base, 7,
+                       g_static_metadata_bytes + 29),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[48].base, 4,
+                       g_static_metadata_bytes + 868),
+                   5),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[4].base, 7,
+                       g_static_metadata_bytes + 29),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[49].base, 5,
+                       g_static_metadata_bytes + 872),
+                   6),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[2].base, 7,
+                       g_static_metadata_bytes + 12),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[50].base, 3,
+                       g_static_metadata_bytes + 877),
+                   7),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[2].base, 7,
+                       g_static_metadata_bytes + 12),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[51].base, 3,
+                       g_static_metadata_bytes + 880),
+                   8),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[2].base, 7,
+                       g_static_metadata_bytes + 12),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[52].base, 3,
+                       g_static_metadata_bytes + 883),
+                   9),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[2].base, 7,
+                       g_static_metadata_bytes + 12),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[53].base, 3,
+                       g_static_metadata_bytes + 886),
+                   10),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[2].base, 7,
+                       g_static_metadata_bytes + 12),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[54].base, 3,
+                       g_static_metadata_bytes + 889),
+                   11),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[2].base, 7,
+                       g_static_metadata_bytes + 12),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[55].base, 3,
+                       g_static_metadata_bytes + 892),
+                   12),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[2].base, 7,
+                       g_static_metadata_bytes + 12),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[56].base, 3,
+                       g_static_metadata_bytes + 895),
+                   13),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[57].base, 14,
+                       g_static_metadata_bytes + 898),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   14),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[15].base, 15,
+                       g_static_metadata_bytes + 184),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[58].base, 13,
+                       g_static_metadata_bytes + 912),
+                   15),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[59].base, 15,
+                       g_static_metadata_bytes + 925),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   16),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[60].base, 13,
+                       g_static_metadata_bytes + 940),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   17),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[61].base, 6,
+                       g_static_metadata_bytes + 953),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   18),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[62].base, 27,
+                       g_static_metadata_bytes + 959),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   19),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[63].base, 3,
+                       g_static_metadata_bytes + 986),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   20),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[64].base, 5,
+                       g_static_metadata_bytes + 989),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   21),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[65].base, 13,
+                       g_static_metadata_bytes + 994),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   22),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[66].base, 13,
+                       g_static_metadata_bytes + 1007),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   23),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[67].base, 19,
+                       g_static_metadata_bytes + 1020),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   24),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[14].base, 16,
+                       g_static_metadata_bytes + 168),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   25),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[68].base, 16,
+                       g_static_metadata_bytes + 1039),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   26),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[69].base, 14,
+                       g_static_metadata_bytes + 1055),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   27),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[70].base, 16,
+                       g_static_metadata_bytes + 1069),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   28),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[71].base, 13,
+                       g_static_metadata_bytes + 1085),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   29),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[13].base, 12,
+                       g_static_metadata_bytes + 156),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   30),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[72].base, 6,
+                       g_static_metadata_bytes + 1098),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   31),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[73].base, 4,
+                       g_static_metadata_bytes + 1104),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   32),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[74].base, 4,
+                       g_static_metadata_bytes + 1108),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   33),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[75].base, 6,
+                       g_static_metadata_bytes + 1112),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   34),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[76].base, 7,
+                       g_static_metadata_bytes + 1118),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   35),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[77].base, 4,
+                       g_static_metadata_bytes + 1125),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   36),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[19].base, 4,
+                       g_static_metadata_bytes + 276),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   37),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[78].base, 8,
+                       g_static_metadata_bytes + 1129),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   38),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[79].base, 17,
+                       g_static_metadata_bytes + 1137),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   39),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[80].base, 13,
+                       g_static_metadata_bytes + 1154),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   40),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[81].base, 8,
+                       g_static_metadata_bytes + 1167),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   41),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[82].base, 19,
+                       g_static_metadata_bytes + 1175),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   42),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[83].base, 13,
+                       g_static_metadata_bytes + 1194),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   43),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[84].base, 4,
+                       g_static_metadata_bytes + 1207),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   44),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[85].base, 8,
+                       g_static_metadata_bytes + 1211),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   45),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[86].base, 12,
+                       g_static_metadata_bytes + 1219),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   46),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[87].base, 18,
+                       g_static_metadata_bytes + 1231),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   47),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[88].base, 19,
+                       g_static_metadata_bytes + 1249),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   48),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[89].base, 5,
+                       g_static_metadata_bytes + 1268),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   49),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[90].base, 7,
+                       g_static_metadata_bytes + 1273),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   50),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[91].base, 7,
+                       g_static_metadata_bytes + 1280),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   51),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[92].base, 11,
+                       g_static_metadata_bytes + 1287),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   52),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[93].base, 6,
+                       g_static_metadata_bytes + 1298),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   53),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[94].base, 10,
+                       g_static_metadata_bytes + 1304),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   54),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[95].base, 25,
+                       g_static_metadata_bytes + 1314),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   55),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[96].base, 17,
+                       g_static_metadata_bytes + 1339),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   56),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[18].base, 10,
+                       g_static_metadata_bytes + 266),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   57),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[97].base, 4,
+                       g_static_metadata_bytes + 1356),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   58),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[98].base, 3,
+                       g_static_metadata_bytes + 1360),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   59),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[99].base, 16,
+                       g_static_metadata_bytes + 1363),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   60),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[6].base, 11,
+                       g_static_metadata_bytes + 48),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[100].base, 1,
+                       g_static_metadata_bytes + 1379),
+                   61),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[6].base, 11,
+                       g_static_metadata_bytes + 48),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[24].base, 1,
+                       g_static_metadata_bytes + 367),
+                   62),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[6].base, 11,
+                       g_static_metadata_bytes + 48),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[25].base, 1,
+                       g_static_metadata_bytes + 368),
+                   63),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[8].base, 13,
+                       g_static_metadata_bytes + 75),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[101].base, 8,
+                       g_static_metadata_bytes + 1380),
+                   64),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[8].base, 13,
+                       g_static_metadata_bytes + 75),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[40].base, 4,
+                       g_static_metadata_bytes + 824),
+                   65),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[8].base, 13,
+                       g_static_metadata_bytes + 75),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[39].base, 7,
+                       g_static_metadata_bytes + 817),
+                   66),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[13].base, 12,
+                       g_static_metadata_bytes + 156),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[102].base, 16,
+                       g_static_metadata_bytes + 1388),
+                   67),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[4].base, 7,
+                       g_static_metadata_bytes + 29),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[103].base, 4,
+                       g_static_metadata_bytes + 1404),
+                   68),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[1].base, 7,
+                       g_static_metadata_bytes + 5),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[104].base, 3,
+                       g_static_metadata_bytes + 1408),
+                   69),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[15].base, 15,
+                       g_static_metadata_bytes + 184),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   70),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[14].base, 16,
+                       g_static_metadata_bytes + 168),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[101].base, 8,
+                       g_static_metadata_bytes + 1380),
+                   71),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[14].base, 16,
+                       g_static_metadata_bytes + 168),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[40].base, 4,
+                       g_static_metadata_bytes + 824),
+                   72),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[105].base, 11,
+                       g_static_metadata_bytes + 1411),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[28].base, 0,
+                       g_static_metadata_bytes + 371),
+                   73),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[9].base, 20,
+                       g_static_metadata_bytes + 88),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[101].base, 8,
+                       g_static_metadata_bytes + 1380),
+                   74),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[9].base, 20,
+                       g_static_metadata_bytes + 88),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[39].base, 7,
+                       g_static_metadata_bytes + 817),
+                   75),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[9].base, 20,
+                       g_static_metadata_bytes + 88),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[106].base, 16,
+                       g_static_metadata_bytes + 1422),
+                   76),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[9].base, 20,
+                       g_static_metadata_bytes + 88),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[40].base, 4,
+                       g_static_metadata_bytes + 824),
+                   77),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[9].base, 20,
+                       g_static_metadata_bytes + 88),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[107].base, 13,
+                       g_static_metadata_bytes + 1438),
+                   78),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[9].base, 20,
+                       g_static_metadata_bytes + 88),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[108].base, 12,
+                       g_static_metadata_bytes + 1451),
+                   79),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[9].base, 20,
+                       g_static_metadata_bytes + 88),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[109].base, 21,
+                       g_static_metadata_bytes + 1463),
+                   80),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[15].base, 15,
+                       g_static_metadata_bytes + 184),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[101].base, 8,
+                       g_static_metadata_bytes + 1380),
+                   81),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[15].base, 15,
+                       g_static_metadata_bytes + 184),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[40].base, 4,
+                       g_static_metadata_bytes + 824),
+                   82),
+    StaticMetadata(grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[15].base, 15,
+                       g_static_metadata_bytes + 184),
+                   grpc_core::StaticMetadataSlice(
+                       &g_static_metadata_slice_refcounts[107].base, 13,
+                       g_static_metadata_bytes + 1438),
+                   83),
+};
 
-  /* Warning: the core static metadata currently operates under the soft
-  constraint that the first GRPC_CHTTP2_LAST_STATIC_ENTRY (61) entries must
-  contain metadata specified by the http2 hpack standard. The CHTTP2 transport
-  reads the core metadata with this assumption in mind. If the order of the core
-  static metadata is to be changed, then the CHTTP2 transport must be changed as
-  well to stop relying on the core metadata. */
+/* Warning: the core static metadata currently operates under the soft
+constraint that the first GRPC_CHTTP2_LAST_STATIC_ENTRY (61) entries must
+contain metadata specified by the http2 hpack standard. The CHTTP2 transport
+reads the core metadata with this assumption in mind. If the order of the core
+static metadata is to be changed, then the CHTTP2 transport must be changed as
+well to stop relying on the core metadata. */
 
-  grpc_mdelem static_mdelem_manifested[GRPC_STATIC_MDELEM_COUNT] = {
-      // clang-format off
+grpc_mdelem g_static_mdelem_manifested[GRPC_STATIC_MDELEM_COUNT] = {
+    // clang-format off
     /* GRPC_MDELEM_AUTHORITY_EMPTY: 
      ":authority": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[0].data(),
+        &g_static_mdelem_table[0].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_METHOD_GET: 
      ":method": "GET" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[1].data(),
+        &g_static_mdelem_table[1].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_METHOD_POST: 
      ":method": "POST" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[2].data(),
+        &g_static_mdelem_table[2].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_PATH_SLASH: 
      ":path": "/" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[3].data(),
+        &g_static_mdelem_table[3].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_PATH_SLASH_INDEX_DOT_HTML: 
      ":path": "/index.html" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[4].data(),
+        &g_static_mdelem_table[4].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_SCHEME_HTTP: 
      ":scheme": "http" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[5].data(),
+        &g_static_mdelem_table[5].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_SCHEME_HTTPS: 
      ":scheme": "https" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[6].data(),
+        &g_static_mdelem_table[6].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_STATUS_200: 
      ":status": "200" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[7].data(),
+        &g_static_mdelem_table[7].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_STATUS_204: 
      ":status": "204" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[8].data(),
+        &g_static_mdelem_table[8].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_STATUS_206: 
      ":status": "206" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[9].data(),
+        &g_static_mdelem_table[9].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_STATUS_304: 
      ":status": "304" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[10].data(),
+        &g_static_mdelem_table[10].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_STATUS_400: 
      ":status": "400" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[11].data(),
+        &g_static_mdelem_table[11].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_STATUS_404: 
      ":status": "404" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[12].data(),
+        &g_static_mdelem_table[12].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_STATUS_500: 
      ":status": "500" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[13].data(),
+        &g_static_mdelem_table[13].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_ACCEPT_CHARSET_EMPTY: 
      "accept-charset": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[14].data(),
+        &g_static_mdelem_table[14].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_ACCEPT_ENCODING_GZIP_COMMA_DEFLATE: 
      "accept-encoding": "gzip, deflate" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[15].data(),
+        &g_static_mdelem_table[15].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_ACCEPT_LANGUAGE_EMPTY: 
      "accept-language": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[16].data(),
+        &g_static_mdelem_table[16].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_ACCEPT_RANGES_EMPTY: 
      "accept-ranges": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[17].data(),
+        &g_static_mdelem_table[17].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_ACCEPT_EMPTY: 
      "accept": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[18].data(),
+        &g_static_mdelem_table[18].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_ACCESS_CONTROL_ALLOW_ORIGIN_EMPTY: 
      "access-control-allow-origin": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[19].data(),
+        &g_static_mdelem_table[19].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_AGE_EMPTY: 
      "age": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[20].data(),
+        &g_static_mdelem_table[20].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_ALLOW_EMPTY: 
      "allow": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[21].data(),
+        &g_static_mdelem_table[21].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_AUTHORIZATION_EMPTY: 
      "authorization": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[22].data(),
+        &g_static_mdelem_table[22].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_CACHE_CONTROL_EMPTY: 
      "cache-control": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[23].data(),
+        &g_static_mdelem_table[23].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_CONTENT_DISPOSITION_EMPTY: 
      "content-disposition": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[24].data(),
+        &g_static_mdelem_table[24].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_CONTENT_ENCODING_EMPTY: 
      "content-encoding": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[25].data(),
+        &g_static_mdelem_table[25].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_CONTENT_LANGUAGE_EMPTY: 
      "content-language": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[26].data(),
+        &g_static_mdelem_table[26].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_CONTENT_LENGTH_EMPTY: 
      "content-length": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[27].data(),
+        &g_static_mdelem_table[27].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_CONTENT_LOCATION_EMPTY: 
      "content-location": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[28].data(),
+        &g_static_mdelem_table[28].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_CONTENT_RANGE_EMPTY: 
      "content-range": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[29].data(),
+        &g_static_mdelem_table[29].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_CONTENT_TYPE_EMPTY: 
      "content-type": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[30].data(),
+        &g_static_mdelem_table[30].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_COOKIE_EMPTY: 
      "cookie": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[31].data(),
+        &g_static_mdelem_table[31].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_DATE_EMPTY: 
      "date": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[32].data(),
+        &g_static_mdelem_table[32].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_ETAG_EMPTY: 
      "etag": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[33].data(),
+        &g_static_mdelem_table[33].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_EXPECT_EMPTY: 
      "expect": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[34].data(),
+        &g_static_mdelem_table[34].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_EXPIRES_EMPTY: 
      "expires": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[35].data(),
+        &g_static_mdelem_table[35].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_FROM_EMPTY: 
      "from": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[36].data(),
+        &g_static_mdelem_table[36].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_HOST_EMPTY: 
      "host": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[37].data(),
+        &g_static_mdelem_table[37].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_IF_MATCH_EMPTY: 
      "if-match": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[38].data(),
+        &g_static_mdelem_table[38].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_IF_MODIFIED_SINCE_EMPTY: 
      "if-modified-since": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[39].data(),
+        &g_static_mdelem_table[39].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_IF_NONE_MATCH_EMPTY: 
      "if-none-match": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[40].data(),
+        &g_static_mdelem_table[40].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_IF_RANGE_EMPTY: 
      "if-range": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[41].data(),
+        &g_static_mdelem_table[41].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_IF_UNMODIFIED_SINCE_EMPTY: 
      "if-unmodified-since": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[42].data(),
+        &g_static_mdelem_table[42].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_LAST_MODIFIED_EMPTY: 
      "last-modified": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[43].data(),
+        &g_static_mdelem_table[43].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_LINK_EMPTY: 
      "link": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[44].data(),
+        &g_static_mdelem_table[44].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_LOCATION_EMPTY: 
      "location": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[45].data(),
+        &g_static_mdelem_table[45].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_MAX_FORWARDS_EMPTY: 
      "max-forwards": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[46].data(),
+        &g_static_mdelem_table[46].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_PROXY_AUTHENTICATE_EMPTY: 
      "proxy-authenticate": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[47].data(),
+        &g_static_mdelem_table[47].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_PROXY_AUTHORIZATION_EMPTY: 
      "proxy-authorization": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[48].data(),
+        &g_static_mdelem_table[48].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_RANGE_EMPTY: 
      "range": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[49].data(),
+        &g_static_mdelem_table[49].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_REFERER_EMPTY: 
      "referer": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[50].data(),
+        &g_static_mdelem_table[50].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_REFRESH_EMPTY: 
      "refresh": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[51].data(),
+        &g_static_mdelem_table[51].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_RETRY_AFTER_EMPTY: 
      "retry-after": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[52].data(),
+        &g_static_mdelem_table[52].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_SERVER_EMPTY: 
      "server": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[53].data(),
+        &g_static_mdelem_table[53].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_SET_COOKIE_EMPTY: 
      "set-cookie": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[54].data(),
+        &g_static_mdelem_table[54].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_STRICT_TRANSPORT_SECURITY_EMPTY: 
      "strict-transport-security": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[55].data(),
+        &g_static_mdelem_table[55].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_TRANSFER_ENCODING_EMPTY: 
      "transfer-encoding": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[56].data(),
+        &g_static_mdelem_table[56].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_USER_AGENT_EMPTY: 
      "user-agent": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[57].data(),
+        &g_static_mdelem_table[57].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_VARY_EMPTY: 
      "vary": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[58].data(),
+        &g_static_mdelem_table[58].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_VIA_EMPTY: 
      "via": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[59].data(),
+        &g_static_mdelem_table[59].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_WWW_AUTHENTICATE_EMPTY: 
      "www-authenticate": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[60].data(),
+        &g_static_mdelem_table[60].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_GRPC_STATUS_0: 
      "grpc-status": "0" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[61].data(),
+        &g_static_mdelem_table[61].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_GRPC_STATUS_1: 
      "grpc-status": "1" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[62].data(),
+        &g_static_mdelem_table[62].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_GRPC_STATUS_2: 
      "grpc-status": "2" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[63].data(),
+        &g_static_mdelem_table[63].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_GRPC_ENCODING_IDENTITY: 
      "grpc-encoding": "identity" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[64].data(),
+        &g_static_mdelem_table[64].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_GRPC_ENCODING_GZIP: 
      "grpc-encoding": "gzip" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[65].data(),
+        &g_static_mdelem_table[65].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_GRPC_ENCODING_DEFLATE: 
      "grpc-encoding": "deflate" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[66].data(),
-        GRPC_MDELEM_STORAGE_STATIC),
-    /* GRPC_MDELEM_TE_TRAILERS: 
-     "te": "trailers" */
-    GRPC_MAKE_MDELEM(
-        &static_mdelem_table[67].data(),
+        &g_static_mdelem_table[66].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC: 
      "content-type": "application/grpc" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[68].data(),
+        &g_static_mdelem_table[67].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_SCHEME_GRPC: 
      ":scheme": "grpc" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[69].data(),
+        &g_static_mdelem_table[68].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_METHOD_PUT: 
      ":method": "PUT" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[70].data(),
+        &g_static_mdelem_table[69].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_ACCEPT_ENCODING_EMPTY: 
      "accept-encoding": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[71].data(),
+        &g_static_mdelem_table[70].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_CONTENT_ENCODING_IDENTITY: 
      "content-encoding": "identity" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[72].data(),
+        &g_static_mdelem_table[71].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_CONTENT_ENCODING_GZIP: 
      "content-encoding": "gzip" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[73].data(),
+        &g_static_mdelem_table[72].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_LB_COST_BIN_EMPTY: 
      "lb-cost-bin": "" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[74].data(),
+        &g_static_mdelem_table[73].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY: 
      "grpc-accept-encoding": "identity" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[75].data(),
+        &g_static_mdelem_table[74].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_GRPC_ACCEPT_ENCODING_DEFLATE: 
      "grpc-accept-encoding": "deflate" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[76].data(),
+        &g_static_mdelem_table[75].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE: 
      "grpc-accept-encoding": "identity,deflate" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[77].data(),
+        &g_static_mdelem_table[76].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_GRPC_ACCEPT_ENCODING_GZIP: 
      "grpc-accept-encoding": "gzip" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[78].data(),
+        &g_static_mdelem_table[77].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_GZIP: 
      "grpc-accept-encoding": "identity,gzip" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[79].data(),
+        &g_static_mdelem_table[78].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_GRPC_ACCEPT_ENCODING_DEFLATE_COMMA_GZIP: 
      "grpc-accept-encoding": "deflate,gzip" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[80].data(),
+        &g_static_mdelem_table[79].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE_COMMA_GZIP: 
      "grpc-accept-encoding": "identity,deflate,gzip" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[81].data(),
+        &g_static_mdelem_table[80].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_ACCEPT_ENCODING_IDENTITY: 
      "accept-encoding": "identity" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[82].data(),
+        &g_static_mdelem_table[81].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_ACCEPT_ENCODING_GZIP: 
      "accept-encoding": "gzip" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[83].data(),
+        &g_static_mdelem_table[82].data(),
         GRPC_MDELEM_STORAGE_STATIC),
     /* GRPC_MDELEM_ACCEPT_ENCODING_IDENTITY_COMMA_GZIP: 
      "accept-encoding": "identity,gzip" */
     GRPC_MAKE_MDELEM(
-        &static_mdelem_table[84].data(),
+        &g_static_mdelem_table[83].data(),
         GRPC_MDELEM_STORAGE_STATIC)
-      // clang-format on
-  };
+    // clang-format on
 };
 }  // namespace grpc_core
 
-namespace grpc_core {
-static StaticMetadataCtx* g_static_metadata_slice_ctx = nullptr;
-const StaticMetadataSlice* g_static_metadata_slice_table = nullptr;
-StaticSliceRefcount* g_static_metadata_slice_refcounts = nullptr;
-StaticMetadata* g_static_mdelem_table = nullptr;
-grpc_mdelem* g_static_mdelem_manifested = nullptr;
-#ifndef NDEBUG
-uint64_t StaticMetadataInitCanary() {
-  return g_static_metadata_slice_ctx->init_canary;
-}
-#endif
-}  // namespace grpc_core
-
-void grpc_init_static_metadata_ctx(void) {
-  grpc_core::g_static_metadata_slice_ctx = new grpc_core::StaticMetadataCtx();
-  grpc_core::g_static_metadata_slice_table =
-      grpc_core::g_static_metadata_slice_ctx->slices;
-  grpc_core::g_static_metadata_slice_refcounts =
-      grpc_core::g_static_metadata_slice_ctx->refcounts;
-  grpc_core::g_static_mdelem_table =
-      grpc_core::g_static_metadata_slice_ctx->static_mdelem_table;
-  grpc_core::g_static_mdelem_manifested =
-      grpc_core::g_static_metadata_slice_ctx->static_mdelem_manifested;
-}
-
-void grpc_destroy_static_metadata_ctx(void) {
-  delete grpc_core::g_static_metadata_slice_ctx;
-  grpc_core::g_static_metadata_slice_ctx = nullptr;
-  grpc_core::g_static_metadata_slice_table = nullptr;
-  grpc_core::g_static_metadata_slice_refcounts = nullptr;
-  grpc_core::g_static_mdelem_table = nullptr;
-  grpc_core::g_static_mdelem_manifested = nullptr;
-}
-
 uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT] = {
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 4, 6, 6, 8, 8, 2, 4, 4};
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 4, 6, 6, 8, 8, 2, 4, 4};
 
 static const int8_t elems_r[] = {
-    15, 10, -8,  0,  2,   -43, -83, -44, 0,  4,  -8, 0,  0,  0,  10, 0,  -7, 0,
-    0,  3,  3,   0,  0,   0,   0,   0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,   0,  0,   0,   0,   0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  -68, 0,  -53, -56, -53, -77, 0,  30, 29, 28, 27, 26, 25, 24, 35, 22,
-    21, 20, 19,  18, 17,  16,  15,  16,  16, 16, 15, 14, 13, 12, 11, 10, 9,  8,
-    7,  6,  5,   4,  3,   2,   3,   2,   2,  6,  0,  0,  0,  0,  0,  0,  -7, 0};
+    18, 11, -8, 0,  3,  -75, -51, 0,  7,  -4,  0,   0,   0,   12,  -1,  -2,
+    0,  0,  7,  6,  0,  0,   0,   0,  0,  0,   0,   0,   0,   0,   0,   0,
+    0,  0,  0,  0,  0,  0,   0,   0,  0,  0,   0,   0,   0,   0,   0,   0,
+    0,  0,  0,  0,  0,  0,   0,   0,  0,  -50, 0,   -55, -75, -76, -77, 0,
+    30, 29, 28, 27, 26, 25,  24,  23, 22, 21,  28,  19,  18,  17,  16,  17,
+    17, 16, 15, 14, 13, 12,  11,  10, 9,  8,   7,   6,   5,   4,   3,   2,
+    1,  0,  -1, 0,  0,  0,   0,   0,  0,  0,   -11, 0};
 static uint32_t elems_phash(uint32_t i) {
-  i -= 45;
+  i -= 46;
   uint32_t x = i % 108;
   uint32_t y = i / 108;
   uint32_t h = x;
@@ -1214,22 +1082,22 @@ static uint32_t elems_phash(uint32_t i) {
 }
 
 static const uint16_t elem_keys[] = {
-    269,   270,   271,   272,   273,   274,  275,   1140, 1141,  1789,  153,
-    154,   487,   488,   1679,  45,    46,   1030,  1031, 795,   796,   1801,
-    1569,  651,   869,   2119,  1691,  2229, 6189,  6739, 6849,  6959,  7069,
-    7179,  7289,  7399,  7509,  1817,  7729, 7839,  7949, 8059,  8169,  8279,
-    8389,  8499,  6519,  6409,  8609,  7619, 8719,  6629, 8829,  8939,  9049,
-    9159,  9269,  9379,  9489,  9599,  9709, 9819,  9929, 10039, 10149, 10259,
-    10369, 1200,  543,   10479, 10589, 214,  10699, 1206, 1207,  1208,  1209,
-    1090,  10809, 11579, 1860,  0,     0,    0,     0,    1750,  0,     1867,
-    0,     0,     359,   0,     0,     0,    0,     1642};
+    270,   271,   272,  273,  274,   275,  276,   1029,  1030,  1568,  1678,
+    154,   155,   488,  489,  760,   919,  920,   46,    47,    1458,  1580,
+    1690,  684,   685,  2008, 2118,  6628, 6738,  6848,  6958,  7068,  7178,
+    7288,  7398,  7508, 7618, 7728,  7838, 7948,  1708,  8168,  8278,  8388,
+    8498,  6518,  6298, 8608, 8058,  8718, 8828,  8938,  9048,  9158,  9268,
+    9378,  9488,  9598, 9708, 9818,  9928, 10038, 10148, 10258, 10368, 10478,
+    10588, 10698, 543,  1091, 10808, 214,  10918, 11578, 1096,  1097,  1098,
+    1099,  981,   0,    0,    0,     1641, 1751,  0,     0,     0,     0,
+    358,   1757,  0,    0,    0,     0,    1532};
 static const uint8_t elem_idxs[] = {
-    7,  8,   9,   10,  11,  12, 13,  76, 78,  71,  1,  2,   5,   6,   25,  3,
-    4,  66,  65,  62,  63,  83, 30,  67, 61,  57,  73, 37,  14,  19,  20,  21,
-    22, 23,  24,  26,  27,  15, 29,  31, 32,  33,  34, 35,  36,  38,  17,  16,
-    39, 28,  40,  18,  41,  42, 43,  44, 45,  46,  47, 48,  49,  50,  51,  52,
-    53, 54,  55,  75,  69,  56, 58,  70, 59,  77,  79, 80,  81,  64,  60,  74,
-    82, 255, 255, 255, 255, 72, 255, 84, 255, 255, 0,  255, 255, 255, 255, 68};
+    7,   8,   9,  10, 11,  12,  13,  75,  77, 25, 70,  1,   2,   5,   6,  61,
+    66,  65,  3,  4,  30,  72,  82,  62,  63, 57, 37,  17,  18,  19,  20, 21,
+    22,  23,  24, 26, 27,  28,  29,  31,  15, 33, 34,  35,  36,  16,  14, 38,
+    32,  39,  40, 41, 42,  43,  44,  45,  46, 47, 48,  49,  50,  51,  52, 53,
+    54,  55,  56, 58, 68,  74,  59,  69,  60, 73, 76,  78,  79,  80,  64, 255,
+    255, 255, 71, 81, 255, 255, 255, 255, 0,  83, 255, 255, 255, 255, 67};
 
 grpc_mdelem grpc_static_mdelem_for_static_strings(intptr_t a, intptr_t b) {
   if (a == -1 || b == -1) return GRPC_MDNULL;
@@ -1238,12 +1106,12 @@ grpc_mdelem grpc_static_mdelem_for_static_strings(intptr_t a, intptr_t b) {
   return h < GPR_ARRAY_SIZE(elem_keys) && elem_keys[h] == k &&
                  elem_idxs[h] != 255
              ? GRPC_MAKE_MDELEM(
-                   &grpc_static_mdelem_table()[elem_idxs[h]].data(),
+                   &grpc_core::g_static_mdelem_table[elem_idxs[h]].data(),
                    GRPC_MDELEM_STORAGE_STATIC)
              : GRPC_MDNULL;
 }
 
-const uint8_t grpc_static_accept_encoding_metadata[8] = {0,  75, 76, 77,
-                                                         78, 79, 80, 81};
+const uint8_t grpc_static_accept_encoding_metadata[8] = {0,  74, 75, 76,
+                                                         77, 78, 79, 80};
 
-const uint8_t grpc_static_accept_stream_encoding_metadata[4] = {0, 82, 83, 84};
+const uint8_t grpc_static_accept_stream_encoding_metadata[4] = {0, 81, 82, 83};
index 5d844af..8b5783e 100644 (file)
 
 #include <cstdint>
 
+#include "src/core/lib/slice/static_slice.h"
 #include "src/core/lib/transport/metadata.h"
 
-static_assert(
-    std::is_trivially_destructible<grpc_core::StaticMetadataSlice>::value,
-    "grpc_core::StaticMetadataSlice must be trivially destructible.");
-#define GRPC_STATIC_MDSTR_COUNT 110
+#define GRPC_STATIC_MDELEM_COUNT 84
 
-void grpc_init_static_metadata_ctx(void);
-void grpc_destroy_static_metadata_ctx(void);
 namespace grpc_core {
-#ifndef NDEBUG
-constexpr uint64_t kGrpcStaticMetadataInitCanary = 0xCAFEF00DC0FFEE11L;
-uint64_t StaticMetadataInitCanary();
-#endif
-extern const StaticMetadataSlice* g_static_metadata_slice_table;
+extern StaticMetadata g_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT];
+extern grpc_mdelem g_static_mdelem_manifested[GRPC_STATIC_MDELEM_COUNT];
 }  // namespace grpc_core
-inline const grpc_core::StaticMetadataSlice* grpc_static_slice_table() {
-  GPR_DEBUG_ASSERT(grpc_core::StaticMetadataInitCanary() ==
-                   grpc_core::kGrpcStaticMetadataInitCanary);
-  GPR_DEBUG_ASSERT(grpc_core::g_static_metadata_slice_table != nullptr);
-  return grpc_core::g_static_metadata_slice_table;
-}
-
-/* ":path" */
-#define GRPC_MDSTR_PATH (grpc_static_slice_table()[0])
-/* ":method" */
-#define GRPC_MDSTR_METHOD (grpc_static_slice_table()[1])
-/* ":status" */
-#define GRPC_MDSTR_STATUS (grpc_static_slice_table()[2])
-/* ":authority" */
-#define GRPC_MDSTR_AUTHORITY (grpc_static_slice_table()[3])
-/* ":scheme" */
-#define GRPC_MDSTR_SCHEME (grpc_static_slice_table()[4])
-/* "te" */
-#define GRPC_MDSTR_TE (grpc_static_slice_table()[5])
-/* "grpc-message" */
-#define GRPC_MDSTR_GRPC_MESSAGE (grpc_static_slice_table()[6])
-/* "grpc-status" */
-#define GRPC_MDSTR_GRPC_STATUS (grpc_static_slice_table()[7])
-/* "grpc-payload-bin" */
-#define GRPC_MDSTR_GRPC_PAYLOAD_BIN (grpc_static_slice_table()[8])
-/* "grpc-encoding" */
-#define GRPC_MDSTR_GRPC_ENCODING (grpc_static_slice_table()[9])
-/* "grpc-accept-encoding" */
-#define GRPC_MDSTR_GRPC_ACCEPT_ENCODING (grpc_static_slice_table()[10])
-/* "grpc-server-stats-bin" */
-#define GRPC_MDSTR_GRPC_SERVER_STATS_BIN (grpc_static_slice_table()[11])
-/* "grpc-tags-bin" */
-#define GRPC_MDSTR_GRPC_TAGS_BIN (grpc_static_slice_table()[12])
-/* "grpc-trace-bin" */
-#define GRPC_MDSTR_GRPC_TRACE_BIN (grpc_static_slice_table()[13])
-/* "content-type" */
-#define GRPC_MDSTR_CONTENT_TYPE (grpc_static_slice_table()[14])
-/* "content-encoding" */
-#define GRPC_MDSTR_CONTENT_ENCODING (grpc_static_slice_table()[15])
-/* "accept-encoding" */
-#define GRPC_MDSTR_ACCEPT_ENCODING (grpc_static_slice_table()[16])
-/* "grpc-internal-encoding-request" */
-#define GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST \
-  (grpc_static_slice_table()[17])
-/* "grpc-internal-stream-encoding-request" */
-#define GRPC_MDSTR_GRPC_INTERNAL_STREAM_ENCODING_REQUEST \
-  (grpc_static_slice_table()[18])
-/* "user-agent" */
-#define GRPC_MDSTR_USER_AGENT (grpc_static_slice_table()[19])
-/* "host" */
-#define GRPC_MDSTR_HOST (grpc_static_slice_table()[20])
-/* "grpc-previous-rpc-attempts" */
-#define GRPC_MDSTR_GRPC_PREVIOUS_RPC_ATTEMPTS (grpc_static_slice_table()[21])
-/* "grpc-retry-pushback-ms" */
-#define GRPC_MDSTR_GRPC_RETRY_PUSHBACK_MS (grpc_static_slice_table()[22])
-/* "x-endpoint-load-metrics-bin" */
-#define GRPC_MDSTR_X_ENDPOINT_LOAD_METRICS_BIN (grpc_static_slice_table()[23])
-/* "grpc-timeout" */
-#define GRPC_MDSTR_GRPC_TIMEOUT (grpc_static_slice_table()[24])
-/* "1" */
-#define GRPC_MDSTR_1 (grpc_static_slice_table()[25])
-/* "2" */
-#define GRPC_MDSTR_2 (grpc_static_slice_table()[26])
-/* "3" */
-#define GRPC_MDSTR_3 (grpc_static_slice_table()[27])
-/* "4" */
-#define GRPC_MDSTR_4 (grpc_static_slice_table()[28])
-/* "" */
-#define GRPC_MDSTR_EMPTY (grpc_static_slice_table()[29])
-/* "grpc.wait_for_ready" */
-#define GRPC_MDSTR_GRPC_DOT_WAIT_FOR_READY (grpc_static_slice_table()[30])
-/* "grpc.timeout" */
-#define GRPC_MDSTR_GRPC_DOT_TIMEOUT (grpc_static_slice_table()[31])
-/* "grpc.max_request_message_bytes" */
-#define GRPC_MDSTR_GRPC_DOT_MAX_REQUEST_MESSAGE_BYTES \
-  (grpc_static_slice_table()[32])
-/* "grpc.max_response_message_bytes" */
-#define GRPC_MDSTR_GRPC_DOT_MAX_RESPONSE_MESSAGE_BYTES \
-  (grpc_static_slice_table()[33])
-/* "/grpc.lb.v1.LoadBalancer/BalanceLoad" */
-#define GRPC_MDSTR_SLASH_GRPC_DOT_LB_DOT_V1_DOT_LOADBALANCER_SLASH_BALANCELOAD \
-  (grpc_static_slice_table()[34])
-/* "/envoy.service.load_stats.v2.LoadReportingService/StreamLoadStats" */
-#define GRPC_MDSTR_SLASH_ENVOY_DOT_SERVICE_DOT_LOAD_STATS_DOT_V2_DOT_LOADREPORTINGSERVICE_SLASH_STREAMLOADSTATS \
-  (grpc_static_slice_table()[35])
-/* "/envoy.service.load_stats.v3.LoadReportingService/StreamLoadStats" */
-#define GRPC_MDSTR_SLASH_ENVOY_DOT_SERVICE_DOT_LOAD_STATS_DOT_V3_DOT_LOADREPORTINGSERVICE_SLASH_STREAMLOADSTATS \
-  (grpc_static_slice_table()[36])
-/* "/grpc.health.v1.Health/Watch" */
-#define GRPC_MDSTR_SLASH_GRPC_DOT_HEALTH_DOT_V1_DOT_HEALTH_SLASH_WATCH \
-  (grpc_static_slice_table()[37])
-/* "/envoy.service.discovery.v2.AggregatedDiscoveryService/StreamAggregatedResources"
- */
-#define GRPC_MDSTR_SLASH_ENVOY_DOT_SERVICE_DOT_DISCOVERY_DOT_V2_DOT_AGGREGATEDDISCOVERYSERVICE_SLASH_STREAMAGGREGATEDRESOURCES \
-  (grpc_static_slice_table()[38])
-/* "/envoy.service.discovery.v3.AggregatedDiscoveryService/StreamAggregatedResources"
- */
-#define GRPC_MDSTR_SLASH_ENVOY_DOT_SERVICE_DOT_DISCOVERY_DOT_V3_DOT_AGGREGATEDDISCOVERYSERVICE_SLASH_STREAMAGGREGATEDRESOURCES \
-  (grpc_static_slice_table()[39])
-/* "deflate" */
-#define GRPC_MDSTR_DEFLATE (grpc_static_slice_table()[40])
-/* "gzip" */
-#define GRPC_MDSTR_GZIP (grpc_static_slice_table()[41])
-/* "stream/gzip" */
-#define GRPC_MDSTR_STREAM_SLASH_GZIP (grpc_static_slice_table()[42])
-/* "GET" */
-#define GRPC_MDSTR_GET (grpc_static_slice_table()[43])
-/* "POST" */
-#define GRPC_MDSTR_POST (grpc_static_slice_table()[44])
-/* "/" */
-#define GRPC_MDSTR_SLASH (grpc_static_slice_table()[45])
-/* "/index.html" */
-#define GRPC_MDSTR_SLASH_INDEX_DOT_HTML (grpc_static_slice_table()[46])
-/* "http" */
-#define GRPC_MDSTR_HTTP (grpc_static_slice_table()[47])
-/* "https" */
-#define GRPC_MDSTR_HTTPS (grpc_static_slice_table()[48])
-/* "200" */
-#define GRPC_MDSTR_200 (grpc_static_slice_table()[49])
-/* "204" */
-#define GRPC_MDSTR_204 (grpc_static_slice_table()[50])
-/* "206" */
-#define GRPC_MDSTR_206 (grpc_static_slice_table()[51])
-/* "304" */
-#define GRPC_MDSTR_304 (grpc_static_slice_table()[52])
-/* "400" */
-#define GRPC_MDSTR_400 (grpc_static_slice_table()[53])
-/* "404" */
-#define GRPC_MDSTR_404 (grpc_static_slice_table()[54])
-/* "500" */
-#define GRPC_MDSTR_500 (grpc_static_slice_table()[55])
-/* "accept-charset" */
-#define GRPC_MDSTR_ACCEPT_CHARSET (grpc_static_slice_table()[56])
-/* "gzip, deflate" */
-#define GRPC_MDSTR_GZIP_COMMA_DEFLATE (grpc_static_slice_table()[57])
-/* "accept-language" */
-#define GRPC_MDSTR_ACCEPT_LANGUAGE (grpc_static_slice_table()[58])
-/* "accept-ranges" */
-#define GRPC_MDSTR_ACCEPT_RANGES (grpc_static_slice_table()[59])
-/* "accept" */
-#define GRPC_MDSTR_ACCEPT (grpc_static_slice_table()[60])
-/* "access-control-allow-origin" */
-#define GRPC_MDSTR_ACCESS_CONTROL_ALLOW_ORIGIN (grpc_static_slice_table()[61])
-/* "age" */
-#define GRPC_MDSTR_AGE (grpc_static_slice_table()[62])
-/* "allow" */
-#define GRPC_MDSTR_ALLOW (grpc_static_slice_table()[63])
-/* "authorization" */
-#define GRPC_MDSTR_AUTHORIZATION (grpc_static_slice_table()[64])
-/* "cache-control" */
-#define GRPC_MDSTR_CACHE_CONTROL (grpc_static_slice_table()[65])
-/* "content-disposition" */
-#define GRPC_MDSTR_CONTENT_DISPOSITION (grpc_static_slice_table()[66])
-/* "content-language" */
-#define GRPC_MDSTR_CONTENT_LANGUAGE (grpc_static_slice_table()[67])
-/* "content-length" */
-#define GRPC_MDSTR_CONTENT_LENGTH (grpc_static_slice_table()[68])
-/* "content-location" */
-#define GRPC_MDSTR_CONTENT_LOCATION (grpc_static_slice_table()[69])
-/* "content-range" */
-#define GRPC_MDSTR_CONTENT_RANGE (grpc_static_slice_table()[70])
-/* "cookie" */
-#define GRPC_MDSTR_COOKIE (grpc_static_slice_table()[71])
-/* "date" */
-#define GRPC_MDSTR_DATE (grpc_static_slice_table()[72])
-/* "etag" */
-#define GRPC_MDSTR_ETAG (grpc_static_slice_table()[73])
-/* "expect" */
-#define GRPC_MDSTR_EXPECT (grpc_static_slice_table()[74])
-/* "expires" */
-#define GRPC_MDSTR_EXPIRES (grpc_static_slice_table()[75])
-/* "from" */
-#define GRPC_MDSTR_FROM (grpc_static_slice_table()[76])
-/* "if-match" */
-#define GRPC_MDSTR_IF_MATCH (grpc_static_slice_table()[77])
-/* "if-modified-since" */
-#define GRPC_MDSTR_IF_MODIFIED_SINCE (grpc_static_slice_table()[78])
-/* "if-none-match" */
-#define GRPC_MDSTR_IF_NONE_MATCH (grpc_static_slice_table()[79])
-/* "if-range" */
-#define GRPC_MDSTR_IF_RANGE (grpc_static_slice_table()[80])
-/* "if-unmodified-since" */
-#define GRPC_MDSTR_IF_UNMODIFIED_SINCE (grpc_static_slice_table()[81])
-/* "last-modified" */
-#define GRPC_MDSTR_LAST_MODIFIED (grpc_static_slice_table()[82])
-/* "link" */
-#define GRPC_MDSTR_LINK (grpc_static_slice_table()[83])
-/* "location" */
-#define GRPC_MDSTR_LOCATION (grpc_static_slice_table()[84])
-/* "max-forwards" */
-#define GRPC_MDSTR_MAX_FORWARDS (grpc_static_slice_table()[85])
-/* "proxy-authenticate" */
-#define GRPC_MDSTR_PROXY_AUTHENTICATE (grpc_static_slice_table()[86])
-/* "proxy-authorization" */
-#define GRPC_MDSTR_PROXY_AUTHORIZATION (grpc_static_slice_table()[87])
-/* "range" */
-#define GRPC_MDSTR_RANGE (grpc_static_slice_table()[88])
-/* "referer" */
-#define GRPC_MDSTR_REFERER (grpc_static_slice_table()[89])
-/* "refresh" */
-#define GRPC_MDSTR_REFRESH (grpc_static_slice_table()[90])
-/* "retry-after" */
-#define GRPC_MDSTR_RETRY_AFTER (grpc_static_slice_table()[91])
-/* "server" */
-#define GRPC_MDSTR_SERVER (grpc_static_slice_table()[92])
-/* "set-cookie" */
-#define GRPC_MDSTR_SET_COOKIE (grpc_static_slice_table()[93])
-/* "strict-transport-security" */
-#define GRPC_MDSTR_STRICT_TRANSPORT_SECURITY (grpc_static_slice_table()[94])
-/* "transfer-encoding" */
-#define GRPC_MDSTR_TRANSFER_ENCODING (grpc_static_slice_table()[95])
-/* "vary" */
-#define GRPC_MDSTR_VARY (grpc_static_slice_table()[96])
-/* "via" */
-#define GRPC_MDSTR_VIA (grpc_static_slice_table()[97])
-/* "www-authenticate" */
-#define GRPC_MDSTR_WWW_AUTHENTICATE (grpc_static_slice_table()[98])
-/* "0" */
-#define GRPC_MDSTR_0 (grpc_static_slice_table()[99])
-/* "identity" */
-#define GRPC_MDSTR_IDENTITY (grpc_static_slice_table()[100])
-/* "trailers" */
-#define GRPC_MDSTR_TRAILERS (grpc_static_slice_table()[101])
-/* "application/grpc" */
-#define GRPC_MDSTR_APPLICATION_SLASH_GRPC (grpc_static_slice_table()[102])
-/* "grpc" */
-#define GRPC_MDSTR_GRPC (grpc_static_slice_table()[103])
-/* "PUT" */
-#define GRPC_MDSTR_PUT (grpc_static_slice_table()[104])
-/* "lb-cost-bin" */
-#define GRPC_MDSTR_LB_COST_BIN (grpc_static_slice_table()[105])
-/* "identity,deflate" */
-#define GRPC_MDSTR_IDENTITY_COMMA_DEFLATE (grpc_static_slice_table()[106])
-/* "identity,gzip" */
-#define GRPC_MDSTR_IDENTITY_COMMA_GZIP (grpc_static_slice_table()[107])
-/* "deflate,gzip" */
-#define GRPC_MDSTR_DEFLATE_COMMA_GZIP (grpc_static_slice_table()[108])
-/* "identity,deflate,gzip" */
-#define GRPC_MDSTR_IDENTITY_COMMA_DEFLATE_COMMA_GZIP \
-  (grpc_static_slice_table()[109])
-
-namespace grpc_core {
-struct StaticSliceRefcount;
-extern StaticSliceRefcount* g_static_metadata_slice_refcounts;
-}  // namespace grpc_core
-inline grpc_core::StaticSliceRefcount* grpc_static_metadata_refcounts() {
-  GPR_DEBUG_ASSERT(grpc_core::StaticMetadataInitCanary() ==
-                   grpc_core::kGrpcStaticMetadataInitCanary);
-  GPR_DEBUG_ASSERT(grpc_core::g_static_metadata_slice_refcounts != nullptr);
-  return grpc_core::g_static_metadata_slice_refcounts;
-}
-
-#define GRPC_IS_STATIC_METADATA_STRING(slice) \
-  ((slice).refcount != NULL &&                \
-   (slice).refcount->GetType() == grpc_slice_refcount::Type::STATIC)
-
-#define GRPC_STATIC_METADATA_INDEX(static_slice)                              \
-  (reinterpret_cast<grpc_core::StaticSliceRefcount*>((static_slice).refcount) \
-       ->index)
-
-#define GRPC_STATIC_MDELEM_COUNT 85
-
-namespace grpc_core {
-extern StaticMetadata* g_static_mdelem_table;
-extern grpc_mdelem* g_static_mdelem_manifested;
-}  // namespace grpc_core
-inline grpc_core::StaticMetadata* grpc_static_mdelem_table() {
-  GPR_DEBUG_ASSERT(grpc_core::StaticMetadataInitCanary() ==
-                   grpc_core::kGrpcStaticMetadataInitCanary);
-  GPR_DEBUG_ASSERT(grpc_core::g_static_mdelem_table != nullptr);
-  return grpc_core::g_static_mdelem_table;
-}
-inline grpc_mdelem* grpc_static_mdelem_manifested() {
-  GPR_DEBUG_ASSERT(grpc_core::StaticMetadataInitCanary() ==
-                   grpc_core::kGrpcStaticMetadataInitCanary);
-  GPR_DEBUG_ASSERT(grpc_core::g_static_mdelem_manifested != nullptr);
-  return grpc_core::g_static_mdelem_manifested;
-}
 
 extern uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT];
 /* ":authority": "" */
-#define GRPC_MDELEM_AUTHORITY_EMPTY (grpc_static_mdelem_manifested()[0])
+#define GRPC_MDELEM_AUTHORITY_EMPTY (::grpc_core::g_static_mdelem_manifested[0])
 /* ":method": "GET" */
-#define GRPC_MDELEM_METHOD_GET (grpc_static_mdelem_manifested()[1])
+#define GRPC_MDELEM_METHOD_GET (::grpc_core::g_static_mdelem_manifested[1])
 /* ":method": "POST" */
-#define GRPC_MDELEM_METHOD_POST (grpc_static_mdelem_manifested()[2])
+#define GRPC_MDELEM_METHOD_POST (::grpc_core::g_static_mdelem_manifested[2])
 /* ":path": "/" */
-#define GRPC_MDELEM_PATH_SLASH (grpc_static_mdelem_manifested()[3])
+#define GRPC_MDELEM_PATH_SLASH (::grpc_core::g_static_mdelem_manifested[3])
 /* ":path": "/index.html" */
 #define GRPC_MDELEM_PATH_SLASH_INDEX_DOT_HTML \
-  (grpc_static_mdelem_manifested()[4])
+  (::grpc_core::g_static_mdelem_manifested[4])
 /* ":scheme": "http" */
-#define GRPC_MDELEM_SCHEME_HTTP (grpc_static_mdelem_manifested()[5])
+#define GRPC_MDELEM_SCHEME_HTTP (::grpc_core::g_static_mdelem_manifested[5])
 /* ":scheme": "https" */
-#define GRPC_MDELEM_SCHEME_HTTPS (grpc_static_mdelem_manifested()[6])
+#define GRPC_MDELEM_SCHEME_HTTPS (::grpc_core::g_static_mdelem_manifested[6])
 /* ":status": "200" */
-#define GRPC_MDELEM_STATUS_200 (grpc_static_mdelem_manifested()[7])
+#define GRPC_MDELEM_STATUS_200 (::grpc_core::g_static_mdelem_manifested[7])
 /* ":status": "204" */
-#define GRPC_MDELEM_STATUS_204 (grpc_static_mdelem_manifested()[8])
+#define GRPC_MDELEM_STATUS_204 (::grpc_core::g_static_mdelem_manifested[8])
 /* ":status": "206" */
-#define GRPC_MDELEM_STATUS_206 (grpc_static_mdelem_manifested()[9])
+#define GRPC_MDELEM_STATUS_206 (::grpc_core::g_static_mdelem_manifested[9])
 /* ":status": "304" */
-#define GRPC_MDELEM_STATUS_304 (grpc_static_mdelem_manifested()[10])
+#define GRPC_MDELEM_STATUS_304 (::grpc_core::g_static_mdelem_manifested[10])
 /* ":status": "400" */
-#define GRPC_MDELEM_STATUS_400 (grpc_static_mdelem_manifested()[11])
+#define GRPC_MDELEM_STATUS_400 (::grpc_core::g_static_mdelem_manifested[11])
 /* ":status": "404" */
-#define GRPC_MDELEM_STATUS_404 (grpc_static_mdelem_manifested()[12])
+#define GRPC_MDELEM_STATUS_404 (::grpc_core::g_static_mdelem_manifested[12])
 /* ":status": "500" */
-#define GRPC_MDELEM_STATUS_500 (grpc_static_mdelem_manifested()[13])
+#define GRPC_MDELEM_STATUS_500 (::grpc_core::g_static_mdelem_manifested[13])
 /* "accept-charset": "" */
-#define GRPC_MDELEM_ACCEPT_CHARSET_EMPTY (grpc_static_mdelem_manifested()[14])
+#define GRPC_MDELEM_ACCEPT_CHARSET_EMPTY \
+  (::grpc_core::g_static_mdelem_manifested[14])
 /* "accept-encoding": "gzip, deflate" */
 #define GRPC_MDELEM_ACCEPT_ENCODING_GZIP_COMMA_DEFLATE \
-  (grpc_static_mdelem_manifested()[15])
+  (::grpc_core::g_static_mdelem_manifested[15])
 /* "accept-language": "" */
-#define GRPC_MDELEM_ACCEPT_LANGUAGE_EMPTY (grpc_static_mdelem_manifested()[16])
+#define GRPC_MDELEM_ACCEPT_LANGUAGE_EMPTY \
+  (::grpc_core::g_static_mdelem_manifested[16])
 /* "accept-ranges": "" */
-#define GRPC_MDELEM_ACCEPT_RANGES_EMPTY (grpc_static_mdelem_manifested()[17])
+#define GRPC_MDELEM_ACCEPT_RANGES_EMPTY \
+  (::grpc_core::g_static_mdelem_manifested[17])
 /* "accept": "" */
-#define GRPC_MDELEM_ACCEPT_EMPTY (grpc_static_mdelem_manifested()[18])
+#define GRPC_MDELEM_ACCEPT_EMPTY (::grpc_core::g_static_mdelem_manifested[18])
 /* "access-control-allow-origin": "" */
 #define GRPC_MDELEM_ACCESS_CONTROL_ALLOW_ORIGIN_EMPTY \
-  (grpc_static_mdelem_manifested()[19])
+  (::grpc_core::g_static_mdelem_manifested[19])
 /* "age": "" */
-#define GRPC_MDELEM_AGE_EMPTY (grpc_static_mdelem_manifested()[20])
+#define GRPC_MDELEM_AGE_EMPTY (::grpc_core::g_static_mdelem_manifested[20])
 /* "allow": "" */
-#define GRPC_MDELEM_ALLOW_EMPTY (grpc_static_mdelem_manifested()[21])
+#define GRPC_MDELEM_ALLOW_EMPTY (::grpc_core::g_static_mdelem_manifested[21])
 /* "authorization": "" */
-#define GRPC_MDELEM_AUTHORIZATION_EMPTY (grpc_static_mdelem_manifested()[22])
+#define GRPC_MDELEM_AUTHORIZATION_EMPTY \
+  (::grpc_core::g_static_mdelem_manifested[22])
 /* "cache-control": "" */
-#define GRPC_MDELEM_CACHE_CONTROL_EMPTY (grpc_static_mdelem_manifested()[23])
+#define GRPC_MDELEM_CACHE_CONTROL_EMPTY \
+  (::grpc_core::g_static_mdelem_manifested[23])
 /* "content-disposition": "" */
 #define GRPC_MDELEM_CONTENT_DISPOSITION_EMPTY \
-  (grpc_static_mdelem_manifested()[24])
+  (::grpc_core::g_static_mdelem_manifested[24])
 /* "content-encoding": "" */
-#define GRPC_MDELEM_CONTENT_ENCODING_EMPTY (grpc_static_mdelem_manifested()[25])
+#define GRPC_MDELEM_CONTENT_ENCODING_EMPTY \
+  (::grpc_core::g_static_mdelem_manifested[25])
 /* "content-language": "" */
-#define GRPC_MDELEM_CONTENT_LANGUAGE_EMPTY (grpc_static_mdelem_manifested()[26])
+#define GRPC_MDELEM_CONTENT_LANGUAGE_EMPTY \
+  (::grpc_core::g_static_mdelem_manifested[26])
 /* "content-length": "" */
-#define GRPC_MDELEM_CONTENT_LENGTH_EMPTY (grpc_static_mdelem_manifested()[27])
+#define GRPC_MDELEM_CONTENT_LENGTH_EMPTY \
+  (::grpc_core::g_static_mdelem_manifested[27])
 /* "content-location": "" */
-#define GRPC_MDELEM_CONTENT_LOCATION_EMPTY (grpc_static_mdelem_manifested()[28])
+#define GRPC_MDELEM_CONTENT_LOCATION_EMPTY \
+  (::grpc_core::g_static_mdelem_manifested[28])
 /* "content-range": "" */
-#define GRPC_MDELEM_CONTENT_RANGE_EMPTY (grpc_static_mdelem_manifested()[29])
+#define GRPC_MDELEM_CONTENT_RANGE_EMPTY \
+  (::grpc_core::g_static_mdelem_manifested[29])
 /* "content-type": "" */
-#define GRPC_MDELEM_CONTENT_TYPE_EMPTY (grpc_static_mdelem_manifested()[30])
+#define GRPC_MDELEM_CONTENT_TYPE_EMPTY \
+  (::grpc_core::g_static_mdelem_manifested[30])
 /* "cookie": "" */
-#define GRPC_MDELEM_COOKIE_EMPTY (grpc_static_mdelem_manifested()[31])
+#define GRPC_MDELEM_COOKIE_EMPTY (::grpc_core::g_static_mdelem_manifested[31])
 /* "date": "" */
-#define GRPC_MDELEM_DATE_EMPTY (grpc_static_mdelem_manifested()[32])
+#define GRPC_MDELEM_DATE_EMPTY (::grpc_core::g_static_mdelem_manifested[32])
 /* "etag": "" */
-#define GRPC_MDELEM_ETAG_EMPTY (grpc_static_mdelem_manifested()[33])
+#define GRPC_MDELEM_ETAG_EMPTY (::grpc_core::g_static_mdelem_manifested[33])
 /* "expect": "" */
-#define GRPC_MDELEM_EXPECT_EMPTY (grpc_static_mdelem_manifested()[34])
+#define GRPC_MDELEM_EXPECT_EMPTY (::grpc_core::g_static_mdelem_manifested[34])
 /* "expires": "" */
-#define GRPC_MDELEM_EXPIRES_EMPTY (grpc_static_mdelem_manifested()[35])
+#define GRPC_MDELEM_EXPIRES_EMPTY (::grpc_core::g_static_mdelem_manifested[35])
 /* "from": "" */
-#define GRPC_MDELEM_FROM_EMPTY (grpc_static_mdelem_manifested()[36])
+#define GRPC_MDELEM_FROM_EMPTY (::grpc_core::g_static_mdelem_manifested[36])
 /* "host": "" */
-#define GRPC_MDELEM_HOST_EMPTY (grpc_static_mdelem_manifested()[37])
+#define GRPC_MDELEM_HOST_EMPTY (::grpc_core::g_static_mdelem_manifested[37])
 /* "if-match": "" */
-#define GRPC_MDELEM_IF_MATCH_EMPTY (grpc_static_mdelem_manifested()[38])
+#define GRPC_MDELEM_IF_MATCH_EMPTY (::grpc_core::g_static_mdelem_manifested[38])
 /* "if-modified-since": "" */
 #define GRPC_MDELEM_IF_MODIFIED_SINCE_EMPTY \
-  (grpc_static_mdelem_manifested()[39])
+  (::grpc_core::g_static_mdelem_manifested[39])
 /* "if-none-match": "" */
-#define GRPC_MDELEM_IF_NONE_MATCH_EMPTY (grpc_static_mdelem_manifested()[40])
+#define GRPC_MDELEM_IF_NONE_MATCH_EMPTY \
+  (::grpc_core::g_static_mdelem_manifested[40])
 /* "if-range": "" */
-#define GRPC_MDELEM_IF_RANGE_EMPTY (grpc_static_mdelem_manifested()[41])
+#define GRPC_MDELEM_IF_RANGE_EMPTY (::grpc_core::g_static_mdelem_manifested[41])
 /* "if-unmodified-since": "" */
 #define GRPC_MDELEM_IF_UNMODIFIED_SINCE_EMPTY \
-  (grpc_static_mdelem_manifested()[42])
+  (::grpc_core::g_static_mdelem_manifested[42])
 /* "last-modified": "" */
-#define GRPC_MDELEM_LAST_MODIFIED_EMPTY (grpc_static_mdelem_manifested()[43])
+#define GRPC_MDELEM_LAST_MODIFIED_EMPTY \
+  (::grpc_core::g_static_mdelem_manifested[43])
 /* "link": "" */
-#define GRPC_MDELEM_LINK_EMPTY (grpc_static_mdelem_manifested()[44])
+#define GRPC_MDELEM_LINK_EMPTY (::grpc_core::g_static_mdelem_manifested[44])
 /* "location": "" */
-#define GRPC_MDELEM_LOCATION_EMPTY (grpc_static_mdelem_manifested()[45])
+#define GRPC_MDELEM_LOCATION_EMPTY (::grpc_core::g_static_mdelem_manifested[45])
 /* "max-forwards": "" */
-#define GRPC_MDELEM_MAX_FORWARDS_EMPTY (grpc_static_mdelem_manifested()[46])
+#define GRPC_MDELEM_MAX_FORWARDS_EMPTY \
+  (::grpc_core::g_static_mdelem_manifested[46])
 /* "proxy-authenticate": "" */
 #define GRPC_MDELEM_PROXY_AUTHENTICATE_EMPTY \
-  (grpc_static_mdelem_manifested()[47])
+  (::grpc_core::g_static_mdelem_manifested[47])
 /* "proxy-authorization": "" */
 #define GRPC_MDELEM_PROXY_AUTHORIZATION_EMPTY \
-  (grpc_static_mdelem_manifested()[48])
+  (::grpc_core::g_static_mdelem_manifested[48])
 /* "range": "" */
-#define GRPC_MDELEM_RANGE_EMPTY (grpc_static_mdelem_manifested()[49])
+#define GRPC_MDELEM_RANGE_EMPTY (::grpc_core::g_static_mdelem_manifested[49])
 /* "referer": "" */
-#define GRPC_MDELEM_REFERER_EMPTY (grpc_static_mdelem_manifested()[50])
+#define GRPC_MDELEM_REFERER_EMPTY (::grpc_core::g_static_mdelem_manifested[50])
 /* "refresh": "" */
-#define GRPC_MDELEM_REFRESH_EMPTY (grpc_static_mdelem_manifested()[51])
+#define GRPC_MDELEM_REFRESH_EMPTY (::grpc_core::g_static_mdelem_manifested[51])
 /* "retry-after": "" */
-#define GRPC_MDELEM_RETRY_AFTER_EMPTY (grpc_static_mdelem_manifested()[52])
+#define GRPC_MDELEM_RETRY_AFTER_EMPTY \
+  (::grpc_core::g_static_mdelem_manifested[52])
 /* "server": "" */
-#define GRPC_MDELEM_SERVER_EMPTY (grpc_static_mdelem_manifested()[53])
+#define GRPC_MDELEM_SERVER_EMPTY (::grpc_core::g_static_mdelem_manifested[53])
 /* "set-cookie": "" */
-#define GRPC_MDELEM_SET_COOKIE_EMPTY (grpc_static_mdelem_manifested()[54])
+#define GRPC_MDELEM_SET_COOKIE_EMPTY \
+  (::grpc_core::g_static_mdelem_manifested[54])
 /* "strict-transport-security": "" */
 #define GRPC_MDELEM_STRICT_TRANSPORT_SECURITY_EMPTY \
-  (grpc_static_mdelem_manifested()[55])
+  (::grpc_core::g_static_mdelem_manifested[55])
 /* "transfer-encoding": "" */
 #define GRPC_MDELEM_TRANSFER_ENCODING_EMPTY \
-  (grpc_static_mdelem_manifested()[56])
+  (::grpc_core::g_static_mdelem_manifested[56])
 /* "user-agent": "" */
-#define GRPC_MDELEM_USER_AGENT_EMPTY (grpc_static_mdelem_manifested()[57])
+#define GRPC_MDELEM_USER_AGENT_EMPTY \
+  (::grpc_core::g_static_mdelem_manifested[57])
 /* "vary": "" */
-#define GRPC_MDELEM_VARY_EMPTY (grpc_static_mdelem_manifested()[58])
+#define GRPC_MDELEM_VARY_EMPTY (::grpc_core::g_static_mdelem_manifested[58])
 /* "via": "" */
-#define GRPC_MDELEM_VIA_EMPTY (grpc_static_mdelem_manifested()[59])
+#define GRPC_MDELEM_VIA_EMPTY (::grpc_core::g_static_mdelem_manifested[59])
 /* "www-authenticate": "" */
-#define GRPC_MDELEM_WWW_AUTHENTICATE_EMPTY (grpc_static_mdelem_manifested()[60])
+#define GRPC_MDELEM_WWW_AUTHENTICATE_EMPTY \
+  (::grpc_core::g_static_mdelem_manifested[60])
 /* "grpc-status": "0" */
-#define GRPC_MDELEM_GRPC_STATUS_0 (grpc_static_mdelem_manifested()[61])
+#define GRPC_MDELEM_GRPC_STATUS_0 (::grpc_core::g_static_mdelem_manifested[61])
 /* "grpc-status": "1" */
-#define GRPC_MDELEM_GRPC_STATUS_1 (grpc_static_mdelem_manifested()[62])
+#define GRPC_MDELEM_GRPC_STATUS_1 (::grpc_core::g_static_mdelem_manifested[62])
 /* "grpc-status": "2" */
-#define GRPC_MDELEM_GRPC_STATUS_2 (grpc_static_mdelem_manifested()[63])
+#define GRPC_MDELEM_GRPC_STATUS_2 (::grpc_core::g_static_mdelem_manifested[63])
 /* "grpc-encoding": "identity" */
-#define GRPC_MDELEM_GRPC_ENCODING_IDENTITY (grpc_static_mdelem_manifested()[64])
+#define GRPC_MDELEM_GRPC_ENCODING_IDENTITY \
+  (::grpc_core::g_static_mdelem_manifested[64])
 /* "grpc-encoding": "gzip" */
-#define GRPC_MDELEM_GRPC_ENCODING_GZIP (grpc_static_mdelem_manifested()[65])
+#define GRPC_MDELEM_GRPC_ENCODING_GZIP \
+  (::grpc_core::g_static_mdelem_manifested[65])
 /* "grpc-encoding": "deflate" */
-#define GRPC_MDELEM_GRPC_ENCODING_DEFLATE (grpc_static_mdelem_manifested()[66])
-/* "te": "trailers" */
-#define GRPC_MDELEM_TE_TRAILERS (grpc_static_mdelem_manifested()[67])
+#define GRPC_MDELEM_GRPC_ENCODING_DEFLATE \
+  (::grpc_core::g_static_mdelem_manifested[66])
 /* "content-type": "application/grpc" */
 #define GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC \
-  (grpc_static_mdelem_manifested()[68])
+  (::grpc_core::g_static_mdelem_manifested[67])
 /* ":scheme": "grpc" */
-#define GRPC_MDELEM_SCHEME_GRPC (grpc_static_mdelem_manifested()[69])
+#define GRPC_MDELEM_SCHEME_GRPC (::grpc_core::g_static_mdelem_manifested[68])
 /* ":method": "PUT" */
-#define GRPC_MDELEM_METHOD_PUT (grpc_static_mdelem_manifested()[70])
+#define GRPC_MDELEM_METHOD_PUT (::grpc_core::g_static_mdelem_manifested[69])
 /* "accept-encoding": "" */
-#define GRPC_MDELEM_ACCEPT_ENCODING_EMPTY (grpc_static_mdelem_manifested()[71])
+#define GRPC_MDELEM_ACCEPT_ENCODING_EMPTY \
+  (::grpc_core::g_static_mdelem_manifested[70])
 /* "content-encoding": "identity" */
 #define GRPC_MDELEM_CONTENT_ENCODING_IDENTITY \
-  (grpc_static_mdelem_manifested()[72])
+  (::grpc_core::g_static_mdelem_manifested[71])
 /* "content-encoding": "gzip" */
-#define GRPC_MDELEM_CONTENT_ENCODING_GZIP (grpc_static_mdelem_manifested()[73])
+#define GRPC_MDELEM_CONTENT_ENCODING_GZIP \
+  (::grpc_core::g_static_mdelem_manifested[72])
 /* "lb-cost-bin": "" */
-#define GRPC_MDELEM_LB_COST_BIN_EMPTY (grpc_static_mdelem_manifested()[74])
+#define GRPC_MDELEM_LB_COST_BIN_EMPTY \
+  (::grpc_core::g_static_mdelem_manifested[73])
 /* "grpc-accept-encoding": "identity" */
 #define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY \
-  (grpc_static_mdelem_manifested()[75])
+  (::grpc_core::g_static_mdelem_manifested[74])
 /* "grpc-accept-encoding": "deflate" */
 #define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_DEFLATE \
-  (grpc_static_mdelem_manifested()[76])
+  (::grpc_core::g_static_mdelem_manifested[75])
 /* "grpc-accept-encoding": "identity,deflate" */
 #define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE \
-  (grpc_static_mdelem_manifested()[77])
+  (::grpc_core::g_static_mdelem_manifested[76])
 /* "grpc-accept-encoding": "gzip" */
 #define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_GZIP \
-  (grpc_static_mdelem_manifested()[78])
+  (::grpc_core::g_static_mdelem_manifested[77])
 /* "grpc-accept-encoding": "identity,gzip" */
 #define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_GZIP \
-  (grpc_static_mdelem_manifested()[79])
+  (::grpc_core::g_static_mdelem_manifested[78])
 /* "grpc-accept-encoding": "deflate,gzip" */
 #define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_DEFLATE_COMMA_GZIP \
-  (grpc_static_mdelem_manifested()[80])
+  (::grpc_core::g_static_mdelem_manifested[79])
 /* "grpc-accept-encoding": "identity,deflate,gzip" */
 #define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE_COMMA_GZIP \
-  (grpc_static_mdelem_manifested()[81])
+  (::grpc_core::g_static_mdelem_manifested[80])
 /* "accept-encoding": "identity" */
 #define GRPC_MDELEM_ACCEPT_ENCODING_IDENTITY \
-  (grpc_static_mdelem_manifested()[82])
+  (::grpc_core::g_static_mdelem_manifested[81])
 /* "accept-encoding": "gzip" */
-#define GRPC_MDELEM_ACCEPT_ENCODING_GZIP (grpc_static_mdelem_manifested()[83])
+#define GRPC_MDELEM_ACCEPT_ENCODING_GZIP \
+  (::grpc_core::g_static_mdelem_manifested[82])
 /* "accept-encoding": "identity,gzip" */
 #define GRPC_MDELEM_ACCEPT_ENCODING_IDENTITY_COMMA_GZIP \
-  (grpc_static_mdelem_manifested()[84])
+  (::grpc_core::g_static_mdelem_manifested[83])
 
 grpc_mdelem grpc_static_mdelem_for_static_strings(intptr_t a, intptr_t b);
 typedef enum {
@@ -526,7 +264,6 @@ typedef enum {
   GRPC_BATCH_STATUS,
   GRPC_BATCH_AUTHORITY,
   GRPC_BATCH_SCHEME,
-  GRPC_BATCH_TE,
   GRPC_BATCH_GRPC_MESSAGE,
   GRPC_BATCH_GRPC_STATUS,
   GRPC_BATCH_GRPC_PAYLOAD_BIN,
@@ -556,7 +293,6 @@ typedef union {
     struct grpc_linked_mdelem* status;
     struct grpc_linked_mdelem* authority;
     struct grpc_linked_mdelem* scheme;
-    struct grpc_linked_mdelem* te;
     struct grpc_linked_mdelem* grpc_message;
     struct grpc_linked_mdelem* grpc_status;
     struct grpc_linked_mdelem* grpc_payload_bin;
@@ -590,14 +326,14 @@ typedef union {
 
 extern const uint8_t grpc_static_accept_encoding_metadata[8];
 #define GRPC_MDELEM_ACCEPT_ENCODING_FOR_ALGORITHMS(algs)                \
-  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table()                         \
+  (GRPC_MAKE_MDELEM(&grpc_core::g_static_mdelem_table                   \
                          [grpc_static_accept_encoding_metadata[(algs)]] \
                              .data(),                                   \
                     GRPC_MDELEM_STORAGE_STATIC))
 
 extern const uint8_t grpc_static_accept_stream_encoding_metadata[4];
 #define GRPC_MDELEM_ACCEPT_STREAM_ENCODING_FOR_ALGORITHMS(algs)                \
-  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table()                                \
+  (GRPC_MAKE_MDELEM(&grpc_core::g_static_mdelem_table                          \
                          [grpc_static_accept_stream_encoding_metadata[(algs)]] \
                              .data(),                                          \
                     GRPC_MDELEM_STORAGE_STATIC))
index 1b19307..fb70646 100644 (file)
@@ -20,6 +20,7 @@
 
 #include "src/core/lib/transport/status_metadata.h"
 
+#include "src/core/lib/gpr/string.h"
 #include "src/core/lib/slice/slice_string_helpers.h"
 #include "src/core/lib/transport/static_metadata.h"
 
index 36060a6..5555b62 100644 (file)
@@ -237,22 +237,21 @@ grpc_transport_op* grpc_make_transport_op(grpc_closure* on_complete) {
 
 struct made_transport_stream_op {
   grpc_closure outer_on_complete;
-  grpc_closure* inner_on_complete;
+  grpc_closure* inner_on_complete = nullptr;
   grpc_transport_stream_op_batch op;
-  grpc_transport_stream_op_batch_payload payload;
+  grpc_transport_stream_op_batch_payload payload{nullptr};
 };
 static void destroy_made_transport_stream_op(void* arg,
                                              grpc_error_handle error) {
   made_transport_stream_op* op = static_cast<made_transport_stream_op*>(arg);
   grpc_closure* c = op->inner_on_complete;
-  gpr_free(op);
+  delete op;
   grpc_core::Closure::Run(DEBUG_LOCATION, c, GRPC_ERROR_REF(error));
 }
 
 grpc_transport_stream_op_batch* grpc_make_transport_stream_op(
     grpc_closure* on_complete) {
-  made_transport_stream_op* op =
-      static_cast<made_transport_stream_op*>(gpr_zalloc(sizeof(*op)));
+  made_transport_stream_op* op = new made_transport_stream_op();
   op->op.payload = &op->payload;
   GRPC_CLOSURE_INIT(&op->outer_on_complete, destroy_made_transport_stream_op,
                     op, grpc_schedule_on_exec_ctx);
index 449141d..230d43e 100644 (file)
 /* These routines are here to facilitate debugging - they produce string
    representations of various transport data structures */
 
-static void put_metadata(grpc_mdelem md, std::vector<std::string>* out) {
-  out->push_back("key=");
-  char* dump = grpc_dump_slice(GRPC_MDKEY(md), GPR_DUMP_HEX | GPR_DUMP_ASCII);
-  out->push_back(dump);
-  gpr_free(dump);
-  out->push_back(" value=");
-  dump = grpc_dump_slice(GRPC_MDVALUE(md), GPR_DUMP_HEX | GPR_DUMP_ASCII);
-  out->push_back(dump);
-  gpr_free(dump);
-}
-
-static void put_metadata_list(grpc_metadata_batch md,
+namespace {
+class MetadataListEncoder {
+ public:
+  explicit MetadataListEncoder(std::vector<std::string>* out) : out_(out) {}
+  void Encode(const grpc_mdelem& md) {
+    MaybeAddComma();
+    out_->push_back("key=");
+    char* dump = grpc_dump_slice(GRPC_MDKEY(md), GPR_DUMP_HEX | GPR_DUMP_ASCII);
+    out_->push_back(dump);
+    gpr_free(dump);
+    out_->push_back(" value=");
+    dump = grpc_dump_slice(GRPC_MDVALUE(md), GPR_DUMP_HEX | GPR_DUMP_ASCII);
+    out_->push_back(dump);
+    gpr_free(dump);
+  }
+
+  void Encode(grpc_core::GrpcTimeoutMetadata, grpc_millis deadline) {
+    MaybeAddComma();
+    out_->push_back(absl::StrFormat("deadline=%" PRId64, deadline));
+  }
+
+  template <typename Which>
+  void Encode(Which, typename Which::ValueType value) {
+    MaybeAddComma();
+    out_->push_back(
+        absl::StrCat(Which::key(), "=", Which::DisplayValue(value)));
+  }
+
+ private:
+  void MaybeAddComma() {
+    if (out_->size() != initial_size_) out_->push_back(", ");
+  }
+  std::vector<std::string>* const out_;
+  const size_t initial_size_ = out_->size();
+};
+}  // namespace
+
+static void put_metadata_list(const grpc_metadata_batch& md,
                               std::vector<std::string>* out) {
-  grpc_linked_mdelem* m;
-  for (m = md.list.head; m != nullptr; m = m->next) {
-    if (m != md.list.head) out->push_back(", ");
-    put_metadata(m->md, out);
-  }
-  if (md.deadline != GRPC_MILLIS_INF_FUTURE) {
-    out->push_back(absl::StrFormat(" deadline=%" PRId64, md.deadline));
-  }
+  MetadataListEncoder encoder(out);
+  md.Encode(&encoder);
 }
 
 std::string grpc_transport_stream_op_batch_string(
index 6a790f3..8fb0d54 100644 (file)
 #include <grpc/grpc.h>
 
 #include "src/core/lib/config/core_configuration.h"
+#include "src/core/lib/surface/builtins.h"
 
-void grpc_http_filters_init(void);
-void grpc_http_filters_shutdown(void);
 void grpc_chttp2_plugin_init(void);
 void grpc_chttp2_plugin_shutdown(void);
-void grpc_deadline_filter_init(void);
-void grpc_deadline_filter_shutdown(void);
 void grpc_client_channel_init(void);
 void grpc_client_channel_shutdown(void);
 void grpc_inproc_plugin_init(void);
@@ -50,23 +47,19 @@ void grpc_resolver_dns_native_init(void);
 void grpc_resolver_dns_native_shutdown(void);
 void grpc_resolver_sockaddr_init(void);
 void grpc_resolver_sockaddr_shutdown(void);
-void grpc_client_idle_filter_init(void);
-void grpc_client_idle_filter_shutdown(void);
-void grpc_max_age_filter_init(void);
-void grpc_max_age_filter_shutdown(void);
 void grpc_message_size_filter_init(void);
 void grpc_message_size_filter_shutdown(void);
-void grpc_service_config_channel_arg_filter_init(void);
-void grpc_service_config_channel_arg_filter_shutdown(void);
-void grpc_client_authority_filter_init(void);
-void grpc_client_authority_filter_shutdown(void);
-void grpc_workaround_cronet_compression_filter_init(void);
-void grpc_workaround_cronet_compression_filter_shutdown(void);
 namespace grpc_core {
 void FaultInjectionFilterInit(void);
 void FaultInjectionFilterShutdown(void);
 void GrpcLbPolicyRingHashInit(void);
 void GrpcLbPolicyRingHashShutdown(void);
+#ifndef GRPC_NO_RLS
+void RlsLbPluginInit();
+void RlsLbPluginShutdown();
+#endif  // !GRPC_NO_RLS
+void ServiceConfigParserInit(void);
+void ServiceConfigParserShutdown(void);
 }  // namespace grpc_core
 
 #ifndef GRPC_NO_XDS
@@ -93,24 +86,27 @@ void grpc_resolver_xds_shutdown(void);
 namespace grpc_core {
 void GoogleCloud2ProdResolverInit();
 void GoogleCloud2ProdResolverShutdown();
-}
+}  // namespace grpc_core
+#endif
+
+#ifdef GPR_SUPPORT_BINDER_TRANSPORT
+void grpc_resolver_binder_init(void);
+void grpc_resolver_binder_shutdown(void);
 #endif
 
 void grpc_register_built_in_plugins(void) {
-  grpc_register_plugin(grpc_http_filters_init,
-                       grpc_http_filters_shutdown);
-  grpc_register_plugin(grpc_chttp2_plugin_init,
-                       grpc_chttp2_plugin_shutdown);
-  grpc_register_plugin(grpc_deadline_filter_init,
-                       grpc_deadline_filter_shutdown);
-  grpc_register_plugin(grpc_client_channel_init,
-                       grpc_client_channel_shutdown);
-  grpc_register_plugin(grpc_inproc_plugin_init,
-                       grpc_inproc_plugin_shutdown);
-  grpc_register_plugin(grpc_resolver_fake_init,
-                       grpc_resolver_fake_shutdown);
+  grpc_register_plugin(grpc_chttp2_plugin_init, grpc_chttp2_plugin_shutdown);
+  grpc_register_plugin(grpc_core::ServiceConfigParserInit,
+                       grpc_core::ServiceConfigParserShutdown);
+  grpc_register_plugin(grpc_client_channel_init, grpc_client_channel_shutdown);
+  grpc_register_plugin(grpc_inproc_plugin_init, grpc_inproc_plugin_shutdown);
+  grpc_register_plugin(grpc_resolver_fake_init, grpc_resolver_fake_shutdown);
   grpc_register_plugin(grpc_lb_policy_grpclb_init,
                        grpc_lb_policy_grpclb_shutdown);
+#ifndef GRPC_NO_RLS
+  grpc_register_plugin(grpc_core::RlsLbPluginInit,
+                       grpc_core::RlsLbPluginShutdown);
+#endif  // !GRPC_NO_RLS
   grpc_register_plugin(grpc_lb_policy_priority_init,
                        grpc_lb_policy_priority_shutdown);
   grpc_register_plugin(grpc_lb_policy_weighted_target_init,
@@ -127,20 +123,10 @@ void grpc_register_built_in_plugins(void) {
                        grpc_resolver_dns_native_shutdown);
   grpc_register_plugin(grpc_resolver_sockaddr_init,
                        grpc_resolver_sockaddr_shutdown);
-  grpc_register_plugin(grpc_client_idle_filter_init,
-                       grpc_client_idle_filter_shutdown);
-  grpc_register_plugin(grpc_max_age_filter_init,
-                       grpc_max_age_filter_shutdown);
   grpc_register_plugin(grpc_message_size_filter_init,
                        grpc_message_size_filter_shutdown);
   grpc_register_plugin(grpc_core::FaultInjectionFilterInit,
                        grpc_core::FaultInjectionFilterShutdown);
-  grpc_register_plugin(grpc_service_config_channel_arg_filter_init,
-                       grpc_service_config_channel_arg_filter_shutdown);
-  grpc_register_plugin(grpc_client_authority_filter_init,
-                       grpc_client_authority_filter_shutdown);
-  grpc_register_plugin(grpc_workaround_cronet_compression_filter_init,
-                       grpc_workaround_cronet_compression_filter_shutdown);
 #ifndef GRPC_NO_XDS
   grpc_register_plugin(grpc_core::XdsClientGlobalInit,
                        grpc_core::XdsClientGlobalShutdown);
@@ -148,29 +134,64 @@ void grpc_register_built_in_plugins(void) {
                        grpc_certificate_provider_registry_shutdown);
   grpc_register_plugin(grpc_core::FileWatcherCertificateProviderInit,
                        grpc_core::FileWatcherCertificateProviderShutdown);
-  grpc_register_plugin(grpc_lb_policy_cds_init,
-                       grpc_lb_policy_cds_shutdown);
+  grpc_register_plugin(grpc_lb_policy_cds_init, grpc_lb_policy_cds_shutdown);
   grpc_register_plugin(grpc_lb_policy_xds_cluster_impl_init,
                        grpc_lb_policy_xds_cluster_impl_shutdown);
   grpc_register_plugin(grpc_lb_policy_xds_cluster_resolver_init,
                        grpc_lb_policy_xds_cluster_resolver_shutdown);
   grpc_register_plugin(grpc_lb_policy_xds_cluster_manager_init,
                        grpc_lb_policy_xds_cluster_manager_shutdown);
-  grpc_register_plugin(grpc_resolver_xds_init,
-                       grpc_resolver_xds_shutdown);
+  grpc_register_plugin(grpc_resolver_xds_init, grpc_resolver_xds_shutdown);
   grpc_register_plugin(grpc_core::GoogleCloud2ProdResolverInit,
                        grpc_core::GoogleCloud2ProdResolverShutdown);
 #endif
+
+#ifdef GPR_SUPPORT_BINDER_TRANSPORT
+  grpc_register_plugin(grpc_resolver_binder_init,
+                       grpc_resolver_binder_shutdown);
+#endif
 }
 
 namespace grpc_core {
 
-extern void BuildClientChannelConfiguration(CoreConfiguration::Builder* builder);
-extern void SecurityRegisterHandshakerFactories(CoreConfiguration::Builder* builder);
+extern void BuildClientChannelConfiguration(
+    CoreConfiguration::Builder* builder);
+extern void SecurityRegisterHandshakerFactories(
+    CoreConfiguration::Builder* builder);
+extern void RegisterClientAuthorityFilter(CoreConfiguration::Builder* builder);
+extern void RegisterClientIdleFilter(CoreConfiguration::Builder* builder);
+extern void RegisterDeadlineFilter(CoreConfiguration::Builder* builder);
+extern void RegisterGrpcLbLoadReportingFilter(
+    CoreConfiguration::Builder* builder);
+extern void RegisterHttpFilters(CoreConfiguration::Builder* builder);
+extern void RegisterMaxAgeFilter(CoreConfiguration::Builder* builder);
+extern void RegisterMessageSizeFilter(CoreConfiguration::Builder* builder);
+extern void RegisterSecurityFilters(CoreConfiguration::Builder* builder);
+extern void RegisterServiceConfigChannelArgFilter(
+    CoreConfiguration::Builder* builder);
+#ifndef GRPC_NO_XDS
+extern void RegisterXdsChannelStackModifier(
+    CoreConfiguration::Builder* builder);
+#endif
 
 void BuildCoreConfiguration(CoreConfiguration::Builder* builder) {
   BuildClientChannelConfiguration(builder);
   SecurityRegisterHandshakerFactories(builder);
+  RegisterClientAuthorityFilter(builder);
+  RegisterClientIdleFilter(builder);
+  RegisterGrpcLbLoadReportingFilter(builder);
+  RegisterHttpFilters(builder);
+  RegisterMaxAgeFilter(builder);
+  RegisterDeadlineFilter(builder);
+  RegisterMessageSizeFilter(builder);
+  RegisterServiceConfigChannelArgFilter(builder);
+  #ifndef GRPC_NO_XDS
+  RegisterXdsChannelStackModifier(builder);
+  #endif
+  // Run last so it gets a consistent location.
+  // TODO(ctiller): Is this actually necessary?
+  RegisterSecurityFilters(builder);
+  RegisterBuiltins(builder);
 }
 
 }  // namespace grpc_core
index 86edc86..e8a7556 100644 (file)
 #include <grpc/grpc.h>
 
 #include "src/core/lib/config/core_configuration.h"
+#include "src/core/lib/surface/builtins.h"
 
-void grpc_http_filters_init(void);
-void grpc_http_filters_shutdown(void);
 void grpc_chttp2_plugin_init(void);
 void grpc_chttp2_plugin_shutdown(void);
-void grpc_deadline_filter_init(void);
-void grpc_deadline_filter_shutdown(void);
 void grpc_client_channel_init(void);
 void grpc_client_channel_shutdown(void);
 void grpc_inproc_plugin_init(void);
@@ -50,10 +47,6 @@ void grpc_lb_policy_pick_first_init(void);
 void grpc_lb_policy_pick_first_shutdown(void);
 void grpc_lb_policy_round_robin_init(void);
 void grpc_lb_policy_round_robin_shutdown(void);
-void grpc_client_idle_filter_init(void);
-void grpc_client_idle_filter_shutdown(void);
-void grpc_max_age_filter_init(void);
-void grpc_max_age_filter_shutdown(void);
 void grpc_message_size_filter_init(void);
 void grpc_message_size_filter_shutdown(void);
 namespace grpc_core {
@@ -61,33 +54,23 @@ void FaultInjectionFilterInit(void);
 void FaultInjectionFilterShutdown(void);
 void GrpcLbPolicyRingHashInit(void);
 void GrpcLbPolicyRingHashShutdown(void);
+void ServiceConfigParserInit(void);
+void ServiceConfigParserShutdown(void);
 }  // namespace grpc_core
-void grpc_service_config_channel_arg_filter_init(void);
-void grpc_service_config_channel_arg_filter_shutdown(void);
-void grpc_client_authority_filter_init(void);
-void grpc_client_authority_filter_shutdown(void);
-void grpc_workaround_cronet_compression_filter_init(void);
-void grpc_workaround_cronet_compression_filter_shutdown(void);
 
 void grpc_register_built_in_plugins(void) {
-  grpc_register_plugin(grpc_http_filters_init,
-                       grpc_http_filters_shutdown);
-  grpc_register_plugin(grpc_chttp2_plugin_init,
-                       grpc_chttp2_plugin_shutdown);
-  grpc_register_plugin(grpc_deadline_filter_init,
-                       grpc_deadline_filter_shutdown);
-  grpc_register_plugin(grpc_client_channel_init,
-                       grpc_client_channel_shutdown);
-  grpc_register_plugin(grpc_inproc_plugin_init,
-                       grpc_inproc_plugin_shutdown);
+  grpc_register_plugin(grpc_chttp2_plugin_init, grpc_chttp2_plugin_shutdown);
+  grpc_register_plugin(grpc_core::ServiceConfigParserInit,
+                       grpc_core::ServiceConfigParserShutdown);
+  grpc_register_plugin(grpc_client_channel_init, grpc_client_channel_shutdown);
+  grpc_register_plugin(grpc_inproc_plugin_init, grpc_inproc_plugin_shutdown);
   grpc_register_plugin(grpc_resolver_dns_ares_init,
                        grpc_resolver_dns_ares_shutdown);
   grpc_register_plugin(grpc_resolver_dns_native_init,
                        grpc_resolver_dns_native_shutdown);
   grpc_register_plugin(grpc_resolver_sockaddr_init,
                        grpc_resolver_sockaddr_shutdown);
-  grpc_register_plugin(grpc_resolver_fake_init,
-                       grpc_resolver_fake_shutdown);
+  grpc_register_plugin(grpc_resolver_fake_init, grpc_resolver_fake_shutdown);
   grpc_register_plugin(grpc_lb_policy_grpclb_init,
                        grpc_lb_policy_grpclb_shutdown);
   grpc_register_plugin(grpc_lb_policy_priority_init,
@@ -100,28 +83,41 @@ void grpc_register_built_in_plugins(void) {
                        grpc_lb_policy_round_robin_shutdown);
   grpc_register_plugin(grpc_core::GrpcLbPolicyRingHashInit,
                        grpc_core::GrpcLbPolicyRingHashShutdown);
-  grpc_register_plugin(grpc_client_idle_filter_init,
-                       grpc_client_idle_filter_shutdown);
-  grpc_register_plugin(grpc_max_age_filter_init,
-                       grpc_max_age_filter_shutdown);
   grpc_register_plugin(grpc_message_size_filter_init,
                        grpc_message_size_filter_shutdown);
   grpc_register_plugin(grpc_core::FaultInjectionFilterInit,
                        grpc_core::FaultInjectionFilterShutdown);
-  grpc_register_plugin(grpc_service_config_channel_arg_filter_init,
-                       grpc_service_config_channel_arg_filter_shutdown);
-  grpc_register_plugin(grpc_client_authority_filter_init,
-                       grpc_client_authority_filter_shutdown);
-  grpc_register_plugin(grpc_workaround_cronet_compression_filter_init,
-                       grpc_workaround_cronet_compression_filter_shutdown);
 }
 
 namespace grpc_core {
 
-extern void BuildClientChannelConfiguration(CoreConfiguration::Builder* builder);
+extern void BuildClientChannelConfiguration(
+    CoreConfiguration::Builder* builder);
+extern void RegisterClientAuthorityFilter(CoreConfiguration::Builder* builder);
+extern void RegisterClientIdleFilter(CoreConfiguration::Builder* builder);
+extern void RegisterDeadlineFilter(CoreConfiguration::Builder* builder);
+extern void RegisterGrpcLbLoadReportingFilter(
+    CoreConfiguration::Builder* builder);
+extern void RegisterHttpFilters(CoreConfiguration::Builder* builder);
+extern void RegisterMaxAgeFilter(CoreConfiguration::Builder* builder);
+extern void RegisterMessageSizeFilter(CoreConfiguration::Builder* builder);
+extern void RegisterSecurityFilters(CoreConfiguration::Builder* builder);
+extern void RegisterServiceConfigChannelArgFilter(
+    CoreConfiguration::Builder* builder);
 
 void BuildCoreConfiguration(CoreConfiguration::Builder* builder) {
   BuildClientChannelConfiguration(builder);
+  RegisterClientAuthorityFilter(builder);
+  RegisterClientIdleFilter(builder);
+  RegisterGrpcLbLoadReportingFilter(builder);
+  RegisterHttpFilters(builder);
+  RegisterMaxAgeFilter(builder);
+  RegisterDeadlineFilter(builder);
+  RegisterMessageSizeFilter(builder);
+  RegisterServiceConfigChannelArgFilter(builder);
+  // Run last so it gets a consistent location.
+  // TODO(ctiller): Is this actually necessary?
+  RegisterBuiltins(builder);
 }
 
-}
+}  // namespace grpc_core
index b761224..4eaaee2 100644 (file)
@@ -559,7 +559,9 @@ static grpc_status_code gsec_aes_gcm_aead_crypter_decrypt_iovec(
   if (!EVP_DecryptFinal_ex(aes_gcm_crypter->ctx, nullptr,
                            &bytes_written_temp)) {
     aes_gcm_format_errors("Checking tag failed.", error_details);
-    memset(plaintext_vec.iov_base, 0x00, plaintext_vec.iov_len);
+    if (plaintext_vec.iov_base != nullptr) {
+      memset(plaintext_vec.iov_base, 0x00, plaintext_vec.iov_len);
+    }
     return GRPC_STATUS_FAILED_PRECONDITION;
   }
   if (bytes_written_temp != 0) {
index bfa0b7a..aae92a4 100644 (file)
@@ -23,6 +23,8 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+#include <algorithm>
+
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 
@@ -156,10 +158,10 @@ static tsi_result alts_protect(tsi_frame_protector* self,
    */
   if (impl->in_place_protect_bytes_buffered + impl->overhead_length <
       max_encrypted_payload_bytes(impl)) {
-    size_t bytes_to_buffer = GPR_MIN(*unprotected_bytes_size,
-                                     max_encrypted_payload_bytes(impl) -
-                                         impl->in_place_protect_bytes_buffered -
-                                         impl->overhead_length);
+    size_t bytes_to_buffer = std::min(
+        *unprotected_bytes_size, max_encrypted_payload_bytes(impl) -
+                                     impl->in_place_protect_bytes_buffered -
+                                     impl->overhead_length);
     *unprotected_bytes_size = bytes_to_buffer;
     if (bytes_to_buffer > 0) {
       memcpy(
@@ -266,9 +268,9 @@ static tsi_result alts_unprotect(tsi_frame_protector* self,
   if (!alts_is_frame_reader_done(impl->reader)) {
     ensure_buffer_size(impl);
     *protected_frames_bytes_size =
-        GPR_MIN(impl->max_unprotected_frame_size -
-                    alts_get_output_bytes_read(impl->reader),
-                *protected_frames_bytes_size);
+        std::min(impl->max_unprotected_frame_size -
+                     alts_get_output_bytes_read(impl->reader),
+                 *protected_frames_bytes_size);
     size_t read_frames_bytes_size = *protected_frames_bytes_size;
     if (!alts_read_frame_bytes(impl->reader, protected_frames_bytes,
                                &read_frames_bytes_size)) {
@@ -290,7 +292,7 @@ static tsi_result alts_unprotect(tsi_frame_protector* self,
         return result;
       }
     }
-    size_t bytes_to_write = GPR_MIN(
+    size_t bytes_to_write = std::min(
         *unprotected_bytes_size, alts_get_output_bytes_read(impl->reader) -
                                      impl->in_place_unprotect_bytes_processed -
                                      impl->overhead_length);
@@ -368,8 +370,7 @@ tsi_result alts_create_frame_protector(const uint8_t* key, size_t key_size,
     return TSI_INTERNAL_ERROR;
   }
   char* error_details = nullptr;
-  alts_frame_protector* impl =
-      static_cast<alts_frame_protector*>(gpr_zalloc(sizeof(*impl)));
+  alts_frame_protector* impl = grpc_core::Zalloc<alts_frame_protector>();
   grpc_status_code status = create_alts_crypters(
       key, key_size, is_client, is_rekey, impl, &error_details);
   if (status != GRPC_STATUS_OK) {
@@ -385,9 +386,9 @@ tsi_result alts_create_frame_protector(const uint8_t* key, size_t key_size,
   size_t max_protected_frame_size_to_set = kDefaultFrameLength;
   if (max_protected_frame_size != nullptr) {
     *max_protected_frame_size =
-        GPR_MIN(*max_protected_frame_size, kMaxFrameLength);
+        std::min(*max_protected_frame_size, kMaxFrameLength);
     *max_protected_frame_size =
-        GPR_MAX(*max_protected_frame_size, kMinFrameLength);
+        std::max(*max_protected_frame_size, kMinFrameLength);
     max_protected_frame_size_to_set = *max_protected_frame_size;
   }
   impl->max_protected_frame_size = max_protected_frame_size_to_set;
index aa90bbc..0237f24 100644 (file)
 #include <stdint.h>
 #include <string.h>
 
+#include <algorithm>
+
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 
-#include "src/core/lib/gpr/useful.h"
+#include "src/core/lib/gprpp/memory.h"
 
 /* Use little endian to interpret a string of bytes as uint32_t. */
 static uint32_t load_32_le(const unsigned char* buffer) {
@@ -47,9 +49,7 @@ static void store_32_le(uint32_t value, unsigned char* buffer) {
 
 /* Frame writer implementation. */
 alts_frame_writer* alts_create_frame_writer() {
-  alts_frame_writer* writer =
-      static_cast<alts_frame_writer*>(gpr_zalloc(sizeof(*writer)));
-  return writer;
+  return grpc_core::Zalloc<alts_frame_writer>();
 }
 
 bool alts_reset_frame_writer(alts_frame_writer* writer,
@@ -82,8 +82,8 @@ bool alts_write_frame_bytes(alts_frame_writer* writer, unsigned char* output,
   /* Write some header bytes, if needed. */
   if (writer->header_bytes_written != sizeof(writer->header_buffer)) {
     size_t bytes_to_write =
-        GPR_MIN(*bytes_size,
-                sizeof(writer->header_buffer) - writer->header_bytes_written);
+        std::min(*bytes_size,
+                 sizeof(writer->header_buffer) - writer->header_bytes_written);
     memcpy(output, writer->header_buffer + writer->header_bytes_written,
            bytes_to_write);
     bytes_written += bytes_to_write;
@@ -97,7 +97,7 @@ bool alts_write_frame_bytes(alts_frame_writer* writer, unsigned char* output,
   }
   /* Write some non-header bytes. */
   size_t bytes_to_write =
-      GPR_MIN(writer->input_size - writer->input_bytes_written, *bytes_size);
+      std::min(writer->input_size - writer->input_bytes_written, *bytes_size);
   memcpy(output, writer->input_buffer, bytes_to_write);
   writer->input_buffer += bytes_to_write;
   bytes_written += bytes_to_write;
@@ -120,8 +120,7 @@ void alts_destroy_frame_writer(alts_frame_writer* writer) { gpr_free(writer); }
 
 /* Frame reader implementation. */
 alts_frame_reader* alts_create_frame_reader() {
-  alts_frame_reader* reader =
-      static_cast<alts_frame_reader*>(gpr_zalloc(sizeof(*reader)));
+  alts_frame_reader* reader = grpc_core::Zalloc<alts_frame_reader>();
   return reader;
 }
 
@@ -167,7 +166,7 @@ bool alts_read_frame_bytes(alts_frame_reader* reader,
   size_t bytes_processed = 0;
   /* Process the header, if needed. */
   if (reader->header_bytes_read != sizeof(reader->header_buffer)) {
-    size_t bytes_to_write = GPR_MIN(
+    size_t bytes_to_write = std::min(
         *bytes_size, sizeof(reader->header_buffer) - reader->header_bytes_read);
     memcpy(reader->header_buffer + reader->header_bytes_read, bytes,
            bytes_to_write);
@@ -199,7 +198,7 @@ bool alts_read_frame_bytes(alts_frame_reader* reader,
     reader->bytes_remaining = frame_length - kFrameMessageTypeFieldSize;
   }
   /* Process the non-header bytes. */
-  size_t bytes_to_write = GPR_MIN(*bytes_size, reader->bytes_remaining);
+  size_t bytes_to_write = std::min(*bytes_size, reader->bytes_remaining);
   memcpy(reader->output_buffer, bytes, bytes_to_write);
   reader->output_buffer += bytes_to_write;
   bytes_processed += bytes_to_write;
index 2e335ab..87fd18e 100644 (file)
@@ -178,8 +178,7 @@ static void handle_response_done(alts_grpc_handshaker_client* client,
                                  const unsigned char* bytes_to_send,
                                  size_t bytes_to_send_size,
                                  tsi_handshaker_result* result) {
-  recv_message_result* p =
-      static_cast<recv_message_result*>(gpr_zalloc(sizeof(*p)));
+  recv_message_result* p = grpc_core::Zalloc<recv_message_result>();
   p->status = status;
   p->bytes_to_send = bytes_to_send;
   p->bytes_to_send_size = bytes_to_send_size;
index 9cca8ab..aac6445 100644 (file)
@@ -32,6 +32,7 @@
 #include <grpc/support/sync.h>
 #include <grpc/support/thd_id.h>
 
+#include "src/core/lib/gprpp/memory.h"
 #include "src/core/lib/gprpp/sync.h"
 #include "src/core/lib/gprpp/thd.h"
 #include "src/core/lib/iomgr/closure.h"
@@ -151,6 +152,13 @@ static tsi_result handshaker_result_extract_peer(
   return ok;
 }
 
+static tsi_result handshaker_result_get_frame_protector_type(
+    const tsi_handshaker_result* /*self*/,
+    tsi_frame_protector_type* frame_protector_type) {
+  *frame_protector_type = TSI_FRAME_PROTECTOR_NORMAL_OR_ZERO_COPY;
+  return TSI_OK;
+}
+
 static tsi_result handshaker_result_create_zero_copy_grpc_protector(
     const tsi_handshaker_result* self, size_t* max_output_protected_frame_size,
     tsi_zero_copy_grpc_protector** protector) {
@@ -247,9 +255,11 @@ static void handshaker_result_destroy(tsi_handshaker_result* self) {
 
 static const tsi_handshaker_result_vtable result_vtable = {
     handshaker_result_extract_peer,
+    handshaker_result_get_frame_protector_type,
     handshaker_result_create_zero_copy_grpc_protector,
     handshaker_result_create_frame_protector,
-    handshaker_result_get_unused_bytes, handshaker_result_destroy};
+    handshaker_result_get_unused_bytes,
+    handshaker_result_destroy};
 
 tsi_result alts_tsi_handshaker_result_create(grpc_gcp_HandshakerResp* resp,
                                              bool is_client,
@@ -306,7 +316,7 @@ tsi_result alts_tsi_handshaker_result_create(grpc_gcp_HandshakerResp* resp,
   // We don't check if local service account is empty here
   // because local identity could be empty in certain situations.
   alts_tsi_handshaker_result* sresult =
-      static_cast<alts_tsi_handshaker_result*>(gpr_zalloc(sizeof(*sresult)));
+      grpc_core::Zalloc<alts_tsi_handshaker_result>();
   sresult->key_data =
       static_cast<char*>(gpr_zalloc(kAltsAes128GcmRekeyKeyLength));
   memcpy(sresult->key_data, key_data.data, kAltsAes128GcmRekeyKeyLength);
index 1048b60..f601b32 100644 (file)
@@ -39,7 +39,7 @@ static void ensure_iovec_buf_size(alts_grpc_record_protocol* rp,
     return;
   }
   /* At least double the iovec buffer size.  */
-  rp->iovec_buf_length = GPR_MAX(sb->count, 2 * rp->iovec_buf_length);
+  rp->iovec_buf_length = std::max(sb->count, 2 * rp->iovec_buf_length);
   rp->iovec_buf = static_cast<iovec_t*>(
       gpr_realloc(rp->iovec_buf, rp->iovec_buf_length * sizeof(iovec_t)));
 }
index e0ce641..d5455b6 100644 (file)
@@ -278,9 +278,9 @@ tsi_result alts_zero_copy_grpc_protector_create(
       size_t max_protected_frame_size_to_set = kDefaultFrameLength;
       if (max_protected_frame_size != nullptr) {
         *max_protected_frame_size =
-            GPR_MIN(*max_protected_frame_size, kMaxFrameLength);
+            std::min(*max_protected_frame_size, kMaxFrameLength);
         *max_protected_frame_size =
-            GPR_MAX(*max_protected_frame_size, kMinFrameLength);
+            std::max(*max_protected_frame_size, kMinFrameLength);
         max_protected_frame_size_to_set = *max_protected_frame_size;
       }
       impl->max_protected_frame_size = max_protected_frame_size_to_set;
index 5e63f11..ce09cdb 100644 (file)
@@ -27,6 +27,7 @@
 #include <grpc/support/log.h>
 
 #include "src/core/lib/gpr/useful.h"
+#include "src/core/lib/gprpp/memory.h"
 #include "src/core/lib/slice/slice_internal.h"
 #include "src/core/tsi/transport_security_grpc.h"
 
@@ -416,8 +417,8 @@ static tsi_result fake_zero_copy_grpc_protector_protect(
   /* Protects each frame. */
   while (unprotected_slices->length > 0) {
     size_t frame_length =
-        GPR_MIN(impl->max_frame_size,
-                unprotected_slices->length + TSI_FAKE_FRAME_HEADER_SIZE);
+        std::min(impl->max_frame_size,
+                 unprotected_slices->length + TSI_FAKE_FRAME_HEADER_SIZE);
     grpc_slice slice = GRPC_SLICE_MALLOC(TSI_FAKE_FRAME_HEADER_SIZE);
     store32_little_endian(static_cast<uint32_t>(frame_length),
                           GRPC_SLICE_START_PTR(slice));
@@ -498,6 +499,7 @@ struct fake_handshaker_result {
   unsigned char* unused_bytes;
   size_t unused_bytes_size;
 };
+
 static tsi_result fake_handshaker_result_extract_peer(
     const tsi_handshaker_result* /*self*/, tsi_peer* peer) {
   /* Construct a tsi_peer with 1 property: certificate type, security_level. */
@@ -514,6 +516,13 @@ static tsi_result fake_handshaker_result_extract_peer(
   return result;
 }
 
+static tsi_result fake_handshaker_result_get_frame_protector_type(
+    const tsi_handshaker_result* /*self*/,
+    tsi_frame_protector_type* frame_protector_type) {
+  *frame_protector_type = TSI_FRAME_PROTECTOR_NORMAL_OR_ZERO_COPY;
+  return TSI_OK;
+}
+
 static tsi_result fake_handshaker_result_create_zero_copy_grpc_protector(
     const tsi_handshaker_result* /*self*/,
     size_t* max_output_protected_frame_size,
@@ -549,6 +558,7 @@ static void fake_handshaker_result_destroy(tsi_handshaker_result* self) {
 
 static const tsi_handshaker_result_vtable handshaker_result_vtable = {
     fake_handshaker_result_extract_peer,
+    fake_handshaker_result_get_frame_protector_type,
     fake_handshaker_result_create_zero_copy_grpc_protector,
     fake_handshaker_result_create_frame_protector,
     fake_handshaker_result_get_unused_bytes,
@@ -562,8 +572,7 @@ static tsi_result fake_handshaker_result_create(
       handshaker_result == nullptr) {
     return TSI_INVALID_ARGUMENT;
   }
-  fake_handshaker_result* result =
-      static_cast<fake_handshaker_result*>(gpr_zalloc(sizeof(*result)));
+  fake_handshaker_result* result = grpc_core::Zalloc<fake_handshaker_result>();
   result->base.vtable = &handshaker_result_vtable;
   if (unused_bytes_size > 0) {
     result->unused_bytes =
@@ -755,8 +764,7 @@ static const tsi_handshaker_vtable handshaker_vtable = {
 };
 
 tsi_handshaker* tsi_create_fake_handshaker(int is_client) {
-  tsi_fake_handshaker* impl =
-      static_cast<tsi_fake_handshaker*>(gpr_zalloc(sizeof(*impl)));
+  tsi_fake_handshaker* impl = grpc_core::Zalloc<tsi_fake_handshaker>();
   impl->base.vtable = &handshaker_vtable;
   impl->is_client = is_client;
   impl->result = TSI_HANDSHAKE_IN_PROGRESS;
@@ -777,7 +785,7 @@ tsi_handshaker* tsi_create_fake_handshaker(int is_client) {
 tsi_frame_protector* tsi_create_fake_frame_protector(
     size_t* max_protected_frame_size) {
   tsi_fake_frame_protector* impl =
-      static_cast<tsi_fake_frame_protector*>(gpr_zalloc(sizeof(*impl)));
+      grpc_core::Zalloc<tsi_fake_frame_protector>();
   impl->max_frame_size = (max_protected_frame_size == nullptr)
                              ? TSI_FAKE_DEFAULT_FRAME_SIZE
                              : *max_protected_frame_size;
index 19043cd..e12ba01 100644 (file)
@@ -42,6 +42,8 @@ typedef struct local_zero_copy_grpc_protector {
 typedef struct local_tsi_handshaker_result {
   tsi_handshaker_result base;
   bool is_client;
+  unsigned char* unused_bytes;
+  size_t unused_bytes_size;
 } local_tsi_handshaker_result;
 
 /* Main struct for local TSI handshaker. */
@@ -50,83 +52,34 @@ typedef struct local_tsi_handshaker {
   bool is_client;
 } local_tsi_handshaker;
 
-/* --- tsi_zero_copy_grpc_protector methods implementation. --- */
+/* --- tsi_handshaker_result methods implementation. --- */
 
-static tsi_result local_zero_copy_grpc_protector_protect(
-    tsi_zero_copy_grpc_protector* self, grpc_slice_buffer* unprotected_slices,
-    grpc_slice_buffer* protected_slices) {
-  if (self == nullptr || unprotected_slices == nullptr ||
-      protected_slices == nullptr) {
-    gpr_log(GPR_ERROR, "Invalid nullptr arguments to zero-copy grpc protect.");
-    return TSI_INVALID_ARGUMENT;
-  }
-  grpc_slice_buffer_move_into(unprotected_slices, protected_slices);
+static tsi_result handshaker_result_extract_peer(
+    const tsi_handshaker_result* /*self*/, tsi_peer* /*peer*/) {
   return TSI_OK;
 }
 
-static tsi_result local_zero_copy_grpc_protector_unprotect(
-    tsi_zero_copy_grpc_protector* self, grpc_slice_buffer* protected_slices,
-    grpc_slice_buffer* unprotected_slices) {
-  if (self == nullptr || unprotected_slices == nullptr ||
-      protected_slices == nullptr) {
-    gpr_log(GPR_ERROR,
-            "Invalid nullptr arguments to zero-copy grpc unprotect.");
-    return TSI_INVALID_ARGUMENT;
-  }
-  grpc_slice_buffer_move_into(protected_slices, unprotected_slices);
+static tsi_result handshaker_result_get_frame_protector_type(
+    const tsi_handshaker_result* /*self*/,
+    tsi_frame_protector_type* frame_protector_type) {
+  *frame_protector_type = TSI_FRAME_PROTECTOR_NONE;
   return TSI_OK;
 }
 
-static void local_zero_copy_grpc_protector_destroy(
-    tsi_zero_copy_grpc_protector* self) {
-  gpr_free(self);
-}
-
-static const tsi_zero_copy_grpc_protector_vtable
-    local_zero_copy_grpc_protector_vtable = {
-        local_zero_copy_grpc_protector_protect,
-        local_zero_copy_grpc_protector_unprotect,
-        local_zero_copy_grpc_protector_destroy,
-        nullptr /* local_zero_copy_grpc_protector_max_frame_size */};
-
-tsi_result local_zero_copy_grpc_protector_create(
-    tsi_zero_copy_grpc_protector** protector) {
-  if (grpc_core::ExecCtx::Get() == nullptr || protector == nullptr) {
-    gpr_log(
-        GPR_ERROR,
-        "Invalid nullptr arguments to local_zero_copy_grpc_protector create.");
+static tsi_result handshaker_result_get_unused_bytes(
+    const tsi_handshaker_result* self, const unsigned char** bytes,
+    size_t* bytes_size) {
+  if (self == nullptr || bytes == nullptr || bytes_size == nullptr) {
+    gpr_log(GPR_ERROR, "Invalid arguments to get_unused_bytes()");
     return TSI_INVALID_ARGUMENT;
   }
-  local_zero_copy_grpc_protector* impl =
-      static_cast<local_zero_copy_grpc_protector*>(gpr_zalloc(sizeof(*impl)));
-  impl->base.vtable = &local_zero_copy_grpc_protector_vtable;
-  *protector = &impl->base;
+  auto* result = reinterpret_cast<local_tsi_handshaker_result*>(
+      const_cast<tsi_handshaker_result*>(self));
+  *bytes_size = result->unused_bytes_size;
+  *bytes = result->unused_bytes;
   return TSI_OK;
 }
 
-/* --- tsi_handshaker_result methods implementation. --- */
-
-static tsi_result handshaker_result_extract_peer(
-    const tsi_handshaker_result* /*self*/, tsi_peer* /*peer*/) {
-  return TSI_OK;
-}
-
-static tsi_result handshaker_result_create_zero_copy_grpc_protector(
-    const tsi_handshaker_result* self,
-    size_t* /*max_output_protected_frame_size*/,
-    tsi_zero_copy_grpc_protector** protector) {
-  if (self == nullptr || protector == nullptr) {
-    gpr_log(GPR_ERROR,
-            "Invalid arguments to create_zero_copy_grpc_protector()");
-    return TSI_INVALID_ARGUMENT;
-  }
-  tsi_result ok = local_zero_copy_grpc_protector_create(protector);
-  if (ok != TSI_OK) {
-    gpr_log(GPR_ERROR, "Failed to create zero-copy grpc protector");
-  }
-  return ok;
-}
-
 static void handshaker_result_destroy(tsi_handshaker_result* self) {
   if (self == nullptr) {
     return;
@@ -134,25 +87,35 @@ static void handshaker_result_destroy(tsi_handshaker_result* self) {
   local_tsi_handshaker_result* result =
       reinterpret_cast<local_tsi_handshaker_result*>(
           const_cast<tsi_handshaker_result*>(self));
+  gpr_free(result->unused_bytes);
   gpr_free(result);
 }
 
 static const tsi_handshaker_result_vtable result_vtable = {
     handshaker_result_extract_peer,
-    handshaker_result_create_zero_copy_grpc_protector,
+    handshaker_result_get_frame_protector_type,
+    nullptr, /* handshaker_result_create_zero_copy_grpc_protector */
     nullptr, /* handshaker_result_create_frame_protector */
-    nullptr, /* handshaker_result_get_unused_bytes */
+    handshaker_result_get_unused_bytes,
     handshaker_result_destroy};
 
 static tsi_result create_handshaker_result(bool is_client,
+                                           const unsigned char* received_bytes,
+                                           size_t received_bytes_size,
                                            tsi_handshaker_result** self) {
   if (self == nullptr) {
     gpr_log(GPR_ERROR, "Invalid arguments to create_handshaker_result()");
     return TSI_INVALID_ARGUMENT;
   }
   local_tsi_handshaker_result* result =
-      static_cast<local_tsi_handshaker_result*>(gpr_zalloc(sizeof(*result)));
+      grpc_core::Zalloc<local_tsi_handshaker_result>();
   result->is_client = is_client;
+  if (received_bytes_size > 0) {
+    result->unused_bytes =
+        static_cast<unsigned char*>(gpr_malloc(received_bytes_size));
+    memcpy(result->unused_bytes, received_bytes, received_bytes_size);
+  }
+  result->unused_bytes_size = received_bytes_size;
   result->base.vtable = &result_vtable;
   *self = &result->base;
   return TSI_OK;
@@ -161,8 +124,8 @@ static tsi_result create_handshaker_result(bool is_client,
 /* --- tsi_handshaker methods implementation. --- */
 
 static tsi_result handshaker_next(
-    tsi_handshaker* self, const unsigned char* /*received_bytes*/,
-    size_t /*received_bytes_size*/, const unsigned char** /*bytes_to_send*/,
+    tsi_handshaker* self, const unsigned char* received_bytes,
+    size_t received_bytes_size, const unsigned char** /*bytes_to_send*/,
     size_t* bytes_to_send_size, tsi_handshaker_result** result,
     tsi_handshaker_on_next_done_cb /*cb*/, void* /*user_data*/) {
   if (self == nullptr) {
@@ -175,7 +138,8 @@ static tsi_result handshaker_next(
   local_tsi_handshaker* handshaker =
       reinterpret_cast<local_tsi_handshaker*>(self);
   *bytes_to_send_size = 0;
-  create_handshaker_result(handshaker->is_client, result);
+  create_handshaker_result(handshaker->is_client, received_bytes,
+                           received_bytes_size, result);
   return TSI_OK;
 }
 
@@ -206,8 +170,7 @@ tsi_result tsi_local_handshaker_create(bool is_client, tsi_handshaker** self) {
     gpr_log(GPR_ERROR, "Invalid arguments to local_tsi_handshaker_create()");
     return TSI_INVALID_ARGUMENT;
   }
-  local_tsi_handshaker* handshaker =
-      static_cast<local_tsi_handshaker*>(gpr_zalloc(sizeof(*handshaker)));
+  local_tsi_handshaker* handshaker = grpc_core::Zalloc<local_tsi_handshaker>();
   handshaker->is_client = is_client;
   handshaker->base.vtable = &handshaker_vtable;
   *self = &handshaker->base;
index 15fd6fd..5657fbc 100644 (file)
 
 namespace tsi {
 
-static void cache_key_avl_destroy(void* /*key*/, void* /*unused*/) {}
-
-static void* cache_key_avl_copy(void* key, void* /*unused*/) { return key; }
-
-static long cache_key_avl_compare(void* key1, void* key2, void* /*unused*/) {
-  return grpc_slice_cmp(*static_cast<grpc_slice*>(key1),
-                        *static_cast<grpc_slice*>(key2));
-}
-
-static void cache_value_avl_destroy(void* /*value*/, void* /*unused*/) {}
-
-static void* cache_value_avl_copy(void* value, void* /*unused*/) {
-  return value;
-}
-
-// AVL only stores pointers, ownership belonges to the linked list.
-static const grpc_avl_vtable cache_avl_vtable = {
-    cache_key_avl_destroy,   cache_key_avl_copy,   cache_key_avl_compare,
-    cache_value_avl_destroy, cache_value_avl_copy,
-};
-
 /// Node for single cached session.
 class SslSessionLRUCache::Node {
  public:
-  Node(const grpc_slice& key, SslSessionPtr session) : key_(key) {
+  Node(const std::string& key, SslSessionPtr session) : key_(key) {
     SetSession(std::move(session));
   }
 
-  ~Node() { grpc_slice_unref_internal(key_); }
-
   // Not copyable nor movable.
   Node(const Node&) = delete;
   Node& operator=(const Node&) = delete;
 
-  void* AvlKey() { return &key_; }
+  const std::string& key() const { return key_; }
 
   /// Returns a copy of the node's cache session.
   SslSessionPtr CopySession() const { return session_->CopySession(); }
@@ -76,7 +53,7 @@ class SslSessionLRUCache::Node {
  private:
   friend class SslSessionLRUCache;
 
-  grpc_slice key_;
+  std::string key_;
   std::unique_ptr<SslCachedSession> session_;
 
   Node* next_ = nullptr;
@@ -85,7 +62,6 @@ class SslSessionLRUCache::Node {
 
 SslSessionLRUCache::SslSessionLRUCache(size_t capacity) : capacity_(capacity) {
   GPR_ASSERT(capacity > 0);
-  entry_by_key_ = grpc_avl_create(&cache_avl_vtable);
 }
 
 SslSessionLRUCache::~SslSessionLRUCache() {
@@ -95,7 +71,6 @@ SslSessionLRUCache::~SslSessionLRUCache() {
     delete node;
     node = next;
   }
-  grpc_avl_unref(entry_by_key_, nullptr);
 }
 
 size_t SslSessionLRUCache::Size() {
@@ -104,13 +79,12 @@ size_t SslSessionLRUCache::Size() {
 }
 
 SslSessionLRUCache::Node* SslSessionLRUCache::FindLocked(
-    const grpc_slice& key) {
-  void* value =
-      grpc_avl_get(entry_by_key_, const_cast<grpc_slice*>(&key), nullptr);
-  if (value == nullptr) {
+    const std::string& key) {
+  auto it = entry_by_key_.find(key);
+  if (it == entry_by_key_.end()) {
     return nullptr;
   }
-  Node* node = static_cast<Node*>(value);
+  Node* node = it->second;
   // Move to the beginning.
   Remove(node);
   PushFront(node);
@@ -120,22 +94,21 @@ SslSessionLRUCache::Node* SslSessionLRUCache::FindLocked(
 
 void SslSessionLRUCache::Put(const char* key, SslSessionPtr session) {
   grpc_core::MutexLock lock(&lock_);
-  Node* node = FindLocked(grpc_slice_from_static_string(key));
+  Node* node = FindLocked(key);
   if (node != nullptr) {
     node->SetSession(std::move(session));
     return;
   }
-  grpc_slice key_slice = grpc_slice_from_copied_string(key);
-  node = new Node(key_slice, std::move(session));
+  node = new Node(key, std::move(session));
   PushFront(node);
-  entry_by_key_ = grpc_avl_add(entry_by_key_, node->AvlKey(), node, nullptr);
+  entry_by_key_.emplace(key, node);
   AssertInvariants();
   if (use_order_list_size_ > capacity_) {
     GPR_ASSERT(use_order_list_tail_);
     node = use_order_list_tail_;
     Remove(node);
     // Order matters, key is destroyed after deleting node.
-    entry_by_key_ = grpc_avl_remove(entry_by_key_, node->AvlKey(), nullptr);
+    entry_by_key_.erase(node->key());
     delete node;
     AssertInvariants();
   }
@@ -144,8 +117,7 @@ void SslSessionLRUCache::Put(const char* key, SslSessionPtr session) {
 SslSessionPtr SslSessionLRUCache::Get(const char* key) {
   grpc_core::MutexLock lock(&lock_);
   // Key is only used for lookups.
-  grpc_slice key_slice = grpc_slice_from_static_string(key);
-  Node* node = FindLocked(key_slice);
+  Node* node = FindLocked(key);
   if (node == nullptr) {
     return nullptr;
   }
@@ -183,13 +155,6 @@ void SslSessionLRUCache::PushFront(SslSessionLRUCache::Node* node) {
 }
 
 #ifndef NDEBUG
-static size_t calculate_tree_size(grpc_avl_node* node) {
-  if (node == nullptr) {
-    return 0;
-  }
-  return 1 + calculate_tree_size(node->left) + calculate_tree_size(node->right);
-}
-
 void SslSessionLRUCache::AssertInvariants() {
   size_t size = 0;
   Node* prev = nullptr;
@@ -197,14 +162,15 @@ void SslSessionLRUCache::AssertInvariants() {
   while (current != nullptr) {
     size++;
     GPR_ASSERT(current->prev_ == prev);
-    void* node = grpc_avl_get(entry_by_key_, current->AvlKey(), nullptr);
-    GPR_ASSERT(node == current);
+    auto it = entry_by_key_.find(current->key());
+    GPR_ASSERT(it != entry_by_key_.end());
+    GPR_ASSERT(it->second == current);
     prev = current;
     current = current->next_;
   }
   GPR_ASSERT(prev == use_order_list_tail_);
   GPR_ASSERT(size == use_order_list_size_);
-  GPR_ASSERT(calculate_tree_size(entry_by_key_.root) == use_order_list_size_);
+  GPR_ASSERT(entry_by_key_.size() == use_order_list_size_);
 }
 #else
 void SslSessionLRUCache::AssertInvariants() {}
index 0aa3f16..2a99080 100644 (file)
@@ -28,7 +28,8 @@ extern "C" {
 #include <openssl/ssl.h>
 }
 
-#include "src/core/lib/avl/avl.h"
+#include <map>
+
 #include "src/core/lib/gprpp/memory.h"
 #include "src/core/lib/gprpp/ref_counted.h"
 #include "src/core/lib/gprpp/sync.h"
@@ -72,7 +73,7 @@ class SslSessionLRUCache : public grpc_core::RefCounted<SslSessionLRUCache> {
  private:
   class Node;
 
-  Node* FindLocked(const grpc_slice& key);
+  Node* FindLocked(const std::string& key);
   void Remove(Node* node);
   void PushFront(Node* node);
   void AssertInvariants();
@@ -83,7 +84,7 @@ class SslSessionLRUCache : public grpc_core::RefCounted<SslSessionLRUCache> {
   Node* use_order_list_head_ = nullptr;
   Node* use_order_list_tail_ = nullptr;
   size_t use_order_list_size_ = 0;
-  grpc_avl entry_by_key_;
+  std::map<std::string, Node*> entry_by_key_;
 };
 
 }  // namespace tsi
index b687207..5f4a40a 100644 (file)
@@ -1302,6 +1302,13 @@ static tsi_result ssl_handshaker_result_extract_peer(
   return result;
 }
 
+static tsi_result ssl_handshaker_result_get_frame_protector_type(
+    const tsi_handshaker_result* /*self*/,
+    tsi_frame_protector_type* frame_protector_type) {
+  *frame_protector_type = TSI_FRAME_PROTECTOR_NORMAL;
+  return TSI_OK;
+}
+
 static tsi_result ssl_handshaker_result_create_frame_protector(
     const tsi_handshaker_result* self, size_t* max_output_protected_frame_size,
     tsi_frame_protector** protector) {
@@ -1368,6 +1375,7 @@ static void ssl_handshaker_result_destroy(tsi_handshaker_result* self) {
 
 static const tsi_handshaker_result_vtable handshaker_result_vtable = {
     ssl_handshaker_result_extract_peer,
+    ssl_handshaker_result_get_frame_protector_type,
     nullptr, /* create_zero_copy_grpc_protector */
     ssl_handshaker_result_create_frame_protector,
     ssl_handshaker_result_get_unused_bytes,
@@ -1382,7 +1390,7 @@ static tsi_result ssl_handshaker_result_create(
     return TSI_INVALID_ARGUMENT;
   }
   tsi_ssl_handshaker_result* result =
-      static_cast<tsi_ssl_handshaker_result*>(gpr_zalloc(sizeof(*result)));
+      grpc_core::Zalloc<tsi_ssl_handshaker_result>();
   result->base.vtable = &handshaker_result_vtable;
   /* Transfer ownership of ssl and network_io to the handshaker result. */
   result->ssl = handshaker->ssl;
@@ -1661,7 +1669,7 @@ static tsi_result create_tsi_ssl_handshaker(SSL_CTX* ctx, int is_client,
     SSL_set_accept_state(ssl);
   }
 
-  impl = static_cast<tsi_ssl_handshaker*>(gpr_zalloc(sizeof(*impl)));
+  impl = grpc_core::Zalloc<tsi_ssl_handshaker>();
   impl->ssl = ssl;
   impl->network_io = network_io;
   impl->result = TSI_HANDSHAKE_IN_PROGRESS;
index 94bb5d4..1ff2471 100644 (file)
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 exports_files([
     "ca.pem",
index f08093d..5d82260 100644 (file)
@@ -251,6 +251,18 @@ tsi_result tsi_handshaker_result_extract_peer(const tsi_handshaker_result* self,
   return self->vtable->extract_peer(self, peer);
 }
 
+tsi_result tsi_handshaker_result_get_frame_protector_type(
+    const tsi_handshaker_result* self,
+    tsi_frame_protector_type* frame_protector_type) {
+  if (self == nullptr || frame_protector_type == nullptr) {
+    return TSI_INVALID_ARGUMENT;
+  }
+  if (self->vtable->get_frame_protector_type == nullptr) {
+    return TSI_UNIMPLEMENTED;
+  }
+  return self->vtable->get_frame_protector_type(self, frame_protector_type);
+}
+
 tsi_result tsi_handshaker_result_create_frame_protector(
     const tsi_handshaker_result* self, size_t* max_output_protected_frame_size,
     tsi_frame_protector** protector) {
index d3b1c7f..53f85d2 100644 (file)
@@ -29,7 +29,8 @@
 extern grpc_core::TraceFlag tsi_tracing_enabled;
 
 /* Base for tsi_frame_protector implementations.
-   See transport_security_interface.h for documentation. */
+   See transport_security_interface.h for documentation.
+   All methods must be implemented. */
 struct tsi_frame_protector_vtable {
   tsi_result (*protect)(tsi_frame_protector* self,
                         const unsigned char* unprotected_bytes,
@@ -54,6 +55,9 @@ struct tsi_frame_protector {
 /* Base for tsi_handshaker implementations.
    See transport_security_interface.h for documentation. */
 struct tsi_handshaker_vtable {
+  /* Methods for supporting the old synchronous API.
+     These can be null if the TSI impl supports only the new
+     async-capable API. */
   tsi_result (*get_bytes_to_send_to_peer)(tsi_handshaker* self,
                                           unsigned char* bytes,
                                           size_t* bytes_size);
@@ -65,7 +69,10 @@ struct tsi_handshaker_vtable {
   tsi_result (*create_frame_protector)(tsi_handshaker* self,
                                        size_t* max_protected_frame_size,
                                        tsi_frame_protector** protector);
+  /* Must be implemented by all TSI impls. */
   void (*destroy)(tsi_handshaker* self);
+  /* Methods for supporting the new async-capable API.
+     These can be null if the TSI impl supports only the old sync API. */
   tsi_result (*next)(tsi_handshaker* self, const unsigned char* received_bytes,
                      size_t received_bytes_size,
                      const unsigned char** bytes_to_send,
@@ -88,13 +95,21 @@ struct tsi_handshaker {
    API depend on grpc. The create_zero_copy_grpc_protector() method is only used
    in grpc, where we do need the exec_ctx passed through, but the API still
    needs to compile in other applications, where grpc_exec_ctx is not defined.
+   All methods must be non-null, except where noted below.
 */
 struct tsi_handshaker_result_vtable {
   tsi_result (*extract_peer)(const tsi_handshaker_result* self, tsi_peer* peer);
+  tsi_result (*get_frame_protector_type)(
+      const tsi_handshaker_result* self,
+      tsi_frame_protector_type* frame_protector_type);
+  /* May be null if get_frame_protector_type() returns
+     TSI_FRAME_PROTECTOR_NORMAL or TSI_FRAME_PROTECTOR_NONE. */
   tsi_result (*create_zero_copy_grpc_protector)(
       const tsi_handshaker_result* self,
       size_t* max_output_protected_frame_size,
       tsi_zero_copy_grpc_protector** protector);
+  /* May be null if get_frame_protector_type() returns
+     TSI_FRAME_PROTECTOR_ZERO_COPY or TSI_FRAME_PROTECTOR_NONE. */
   tsi_result (*create_frame_protector)(const tsi_handshaker_result* self,
                                        size_t* max_output_protected_frame_size,
                                        tsi_frame_protector** protector);
index 50becca..0ba1393 100644 (file)
@@ -65,6 +65,26 @@ typedef enum {
 } tsi_client_certificate_request_type;
 
 typedef enum {
+  // TSI implementation provides a normal frame protector.  The caller
+  // should invoke tsi_handshaker_result_create_frame_protector() to
+  // generate the frame protector.
+  TSI_FRAME_PROTECTOR_NORMAL,
+  // TSI implementation provides a zero-copy frame protector.  The caller
+  // should invoke tsi_handshaker_result_create_zero_copy_grpc_protector()
+  // to generate the frame protector.
+  TSI_FRAME_PROTECTOR_ZERO_COPY,
+  // TSI implementation provides both normal and zero-copy frame protectors.
+  // The caller should invoke either
+  // tsi_handshaker_result_create_frame_protector() or
+  // tsi_handshaker_result_create_zero_copy_grpc_protector() to generate
+  // the frame protector.
+  TSI_FRAME_PROTECTOR_NORMAL_OR_ZERO_COPY,
+  // TSI implementation does not provide any frame protector.  This means
+  // that it is safe for the caller to send bytes unprotected on the wire.
+  TSI_FRAME_PROTECTOR_NONE,
+} tsi_frame_protector_type;
+
+typedef enum {
   TSI_TLS1_2,
   TSI_TLS1_3,
 } tsi_tls_version;
@@ -234,6 +254,12 @@ typedef struct tsi_handshaker_result tsi_handshaker_result;
 tsi_result tsi_handshaker_result_extract_peer(const tsi_handshaker_result* self,
                                               tsi_peer* peer);
 
+/* This method indicates what type of frame protector is provided by the
+   TSI implementation. */
+tsi_result tsi_handshaker_result_get_frame_protector_type(
+    const tsi_handshaker_result* self,
+    tsi_frame_protector_type* frame_protector_type);
+
 /* This method creates a tsi_frame_protector object. It returns TSI_OK assuming
    there is no fatal error.
    The caller is responsible for destroying the protector.  */
diff --git a/src/cpp/Protobuf-C++.podspec b/src/cpp/Protobuf-C++.podspec
deleted file mode 100644 (file)
index 7565d95..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-Pod::Spec.new do |s|
-  s.name     = 'Protobuf-C++'
-  s.version  = '3.17.3'
-  s.summary  = 'Protocol Buffers v3 runtime library for C++.'
-  s.homepage = 'https://github.com/protocolbuffers/protobuf'
-  s.license  = '3-Clause BSD License'
-  s.authors  = { 'The Protocol Buffers contributors' => 'protobuf@googlegroups.com' }
-  s.cocoapods_version = '>= 1.0'
-
-  s.source = { :git => 'https://github.com/protocolbuffers/protobuf.git',
-               :tag => "v#{s.version}" }
-
-  s.source_files = 'src/google/protobuf/*.{h,cc,inc}',
-                   'src/google/protobuf/stubs/*.{h,cc}',
-                   'src/google/protobuf/io/*.{h,cc}',
-                   'src/google/protobuf/util/*.{h,cc}',
-                   'src/google/protobuf/util/internal/*.{h,cc}'
-
-  # Excluding all the tests in the directories above
-  s.exclude_files = 'src/google/**/*_test.{h,cc,inc}',
-                    'src/google/**/*_unittest.{h,cc}',
-                    'src/google/protobuf/test_util*.{h,cc}',
-                    'src/google/protobuf/map_lite_test_util.{h,cc}',
-                    'src/google/protobuf/map_test_util*.{h,cc,inc}'
-
-  s.header_mappings_dir = 'src'
-
-  s.ios.deployment_target = '9.0'
-  s.osx.deployment_target = '10.10'
-  s.tvos.deployment_target = '9.0'
-  s.watchos.deployment_target = '2.0'
-
-  s.pod_target_xcconfig = {
-    # Do not let src/google/protobuf/stubs/time.h override system API
-    'USE_HEADERMAP' => 'NO',
-    'ALWAYS_SEARCH_USER_PATHS' => 'NO',
-
-    # Configure tool is not being used for Xcode. When building, assume pthread is supported.
-    'GCC_PREPROCESSOR_DEFINITIONS' => '"$(inherited)" "HAVE_PTHREAD=1"',
-  }
-
-end
index e4bd449..5c1c40a 100755 (executable)
@@ -11,21 +11,36 @@ Therefore, gRPC supports several major build systems, which should satisfy most
 
 ## Supported Platforms
 
-* Supported: These platforms are officially supported. We test our code on these
-platform and have automated continuous integration tests for them.
+* Officially Supported: These platforms are officially supported. We test our
+  code on these platform and have automated continuous integration tests for
+  them.
 
-* Best Effort: We do not have continous integration tests for these, but we are fairly confident that gRPC C++ would work on them.
-We will make our best effort to support them, and we welcome patches for such platforms, but we might need to declare bankruptcy on some issues.
+* Best Effort: We do not have continous integration tests for these, but we are
+  fairly confident that gRPC C++ would work on them. We will make our best
+  effort to support them, and we welcome patches for such platforms, but we
+  might need to declare bankruptcy on some issues.
+
+* Community Supported: These platforms are supported by contributions from the
+  open source community, there is no official support for them. Breakages on
+  these platforms may go unnoticed, and the community is responsible for all
+  maintenance. Unmaintained code for these platforms may be deleted.
 
 | Operating System | Architectures | Versions | Support Level |
 |------------------|---------------|----------|---------------|
-| Linux - Debian, Ubuntu, CentOS | x86, x64      | clang 3.4+, GCC 4.9+   | Supported |
-| Windows 10+                    | x86, x64      | Visual Studio 2015+    | Supported |
-| MacOS                          | x86, x64      | XCode 7.2+             | Supported |
-| Linux - Others                 | x86, x64      | clang 3.4+, GCC 4.9+   | Best Effort |
-| Linux                          | ARM           |                        | Best Effort |
-| iOS                            |               |                        | Best Effort |
-| Android                        |               |                        | Best Effort |
+| Linux - Debian, Ubuntu, CentOS | x86, x64      | clang 4+, GCC 4.9+     | Officially Supported |
+| Windows 10+                    | x86, x64      | Visual Studio 2015+    | Officially Supported |
+| MacOS                          | x86, x64      | XCode 7.2+             | Officially Supported |
+| Linux - Others                 | x86, x64      | clang 4+, GCC 4.9+     | Best Effort          |
+| Linux                          | ARM           |                        | Best Effort          |
+| iOS                            |               |                        | Best Effort          |
+| Android                        |               |                        | Best Effort          |
+| Asylo                          |               |                        | Best Effort          |
+| FreeBSD                        |               |                        | Community Supported  |
+| OpenBSD                        |               |                        | Community Supported  |
+| AIX                            |               |                        | Community Supported  |
+| Solaris                        |               |                        | Community Supported  |
+| NaCL                           |               |                        | Community Supported  |
+| Fuchsia                        |               |                        | Community Supported  |
 
 ## Bazel
 
index 3a3b04a..d5bdd31 100644 (file)
@@ -217,6 +217,7 @@ grpc::Status StsCredentialsOptionsFromEnv(StsCredentialsOptions* options) {
   char* sts_creds_path = gpr_getenv("STS_CREDENTIALS");
   grpc_error_handle error = GRPC_ERROR_NONE;
   grpc::Status status;
+  // NOLINTNEXTLINE(clang-diagnostic-unused-lambda-capture)
   auto cleanup = [&json_string, &sts_creds_path, &error, &status]() {
     grpc_slice_unref_internal(json_string);
     gpr_free(sts_creds_path);
@@ -523,6 +524,10 @@ void MetadataCredentialsPluginWrapper::InvokePlugin(
 
 MetadataCredentialsPluginWrapper::MetadataCredentialsPluginWrapper(
     std::unique_ptr<MetadataCredentialsPlugin> plugin)
-    : thread_pool_(CreateDefaultThreadPool()), plugin_(std::move(plugin)) {}
+    : plugin_(std::move(plugin)) {
+  if (plugin_->IsBlocking()) {
+    thread_pool_.reset(CreateDefaultThreadPool());
+  }
+}
 
 }  // namespace grpc
index 6d3a055..373aebf 100644 (file)
@@ -23,6 +23,8 @@
 #include <grpcpp/impl/codegen/slice.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"
 
 namespace grpc {
 
@@ -33,8 +35,7 @@ grpc_linked_mdelem* MetadataBatch::AddMetadata(const string& key,
   grpc_linked_mdelem* storage = new grpc_linked_mdelem;
   storage->md = grpc_mdelem_from_slices(SliceFromCopiedString(key),
                                         SliceFromCopiedString(value));
-  GRPC_LOG_IF_ERROR("MetadataBatch::AddMetadata",
-                    grpc_metadata_batch_link_head(batch_, storage));
+  GRPC_LOG_IF_ERROR("MetadataBatch::AddMetadata", batch_->LinkHead(storage));
   return storage;
 }
 
@@ -62,38 +63,30 @@ void CallData::SetPollsetOrPollsetSet(grpc_call_element* elem,
   grpc_call_stack_ignore_set_pollset_or_pollset_set(elem, pollent);
 }
 
-// internal code used by RegisterChannelFilter()
-
 namespace internal {
 
-// Note: Implicitly initialized to nullptr due to static lifetime.
-std::vector<FilterRecord>* channel_filters;
-
-namespace {
-
-bool MaybeAddFilter(grpc_channel_stack_builder* builder, void* arg) {
-  const FilterRecord& filter = *static_cast<FilterRecord*>(arg);
-  if (filter.include_filter) {
-    const grpc_channel_args* args =
-        grpc_channel_stack_builder_get_channel_arguments(builder);
-    if (!filter.include_filter(*args)) return true;
-  }
-  return grpc_channel_stack_builder_prepend_filter(builder, &filter.filter,
-                                                   nullptr, nullptr);
+void RegisterChannelFilter(
+    grpc_channel_stack_type stack_type, int priority,
+    std::function<bool(const grpc_channel_args&)> include_filter,
+    const grpc_channel_filter* filter) {
+  auto maybe_add_filter = [include_filter,
+                           filter](grpc_channel_stack_builder* builder) {
+    if (include_filter != nullptr) {
+      const grpc_channel_args* args =
+          grpc_channel_stack_builder_get_channel_arguments(builder);
+      if (!include_filter(*args)) return true;
+    }
+    return grpc_channel_stack_builder_prepend_filter(builder, filter, nullptr,
+                                                     nullptr);
+  };
+  grpc_core::CoreConfiguration::RegisterBuilder(
+      [stack_type, priority,
+       maybe_add_filter](grpc_core::CoreConfiguration::Builder* builder) {
+        builder->channel_init()->RegisterStage(stack_type, priority,
+                                               maybe_add_filter);
+      });
 }
 
-}  // namespace
-
-void ChannelFilterPluginInit() {
-  for (size_t i = 0; i < channel_filters->size(); ++i) {
-    FilterRecord& filter = (*channel_filters)[i];
-    grpc_channel_init_register_stage(filter.stack_type, filter.priority,
-                                     MaybeAddFilter, &filter);
-  }
-}
-
-void ChannelFilterPluginShutdown() {}
-
 }  // namespace internal
 
 }  // namespace grpc
index 87f38af..5364895 100644 (file)
@@ -306,16 +306,10 @@ class ChannelFilter final {
   }
 };
 
-struct FilterRecord {
-  grpc_channel_stack_type stack_type;
-  int priority;
-  std::function<bool(const grpc_channel_args&)> include_filter;
-  grpc_channel_filter filter;
-};
-extern std::vector<FilterRecord>* channel_filters;
-
-void ChannelFilterPluginInit();
-void ChannelFilterPluginShutdown();
+void RegisterChannelFilter(
+    grpc_channel_stack_type stack_type, int priority,
+    std::function<bool(const grpc_channel_args&)> include_filter,
+    const grpc_channel_filter* filter);
 
 }  // namespace internal
 
@@ -333,26 +327,21 @@ template <typename ChannelDataType, typename CallDataType>
 void RegisterChannelFilter(
     const char* name, grpc_channel_stack_type stack_type, int priority,
     std::function<bool(const grpc_channel_args&)> include_filter) {
-  // If we haven't been called before, initialize channel_filters and
-  // call grpc_register_plugin().
-  if (internal::channel_filters == nullptr) {
-    grpc_register_plugin(internal::ChannelFilterPluginInit,
-                         internal::ChannelFilterPluginShutdown);
-    internal::channel_filters = new std::vector<internal::FilterRecord>();
-  }
-  // Add an entry to channel_filters. The filter will be added when the
-  // C-core initialization code calls ChannelFilterPluginInit().
-  typedef internal::ChannelFilter<ChannelDataType, CallDataType> FilterType;
-  internal::FilterRecord filter_record = {
-      stack_type,
-      priority,
-      include_filter,
-      {FilterType::StartTransportStreamOpBatch, FilterType::StartTransportOp,
-       FilterType::call_data_size, FilterType::InitCallElement,
-       FilterType::SetPollsetOrPollsetSet, FilterType::DestroyCallElement,
-       FilterType::channel_data_size, FilterType::InitChannelElement,
-       FilterType::DestroyChannelElement, FilterType::GetChannelInfo, name}};
-  internal::channel_filters->push_back(filter_record);
+  using FilterType = internal::ChannelFilter<ChannelDataType, CallDataType>;
+  static const grpc_channel_filter filter = {
+      FilterType::StartTransportStreamOpBatch,
+      FilterType::StartTransportOp,
+      FilterType::call_data_size,
+      FilterType::InitCallElement,
+      FilterType::SetPollsetOrPollsetSet,
+      FilterType::DestroyCallElement,
+      FilterType::channel_data_size,
+      FilterType::InitChannelElement,
+      FilterType::DestroyChannelElement,
+      FilterType::GetChannelInfo,
+      name};
+  grpc::internal::RegisterChannelFilter(stack_type, priority,
+                                        std::move(include_filter), &filter);
 }
 
 }  // namespace grpc
index 42494f7..b962c52 100644 (file)
@@ -52,7 +52,8 @@ struct CallbackAlternativeCQ {
     refs++;
     if (refs == 1) {
       cq = new CompletionQueue;
-      int num_nexting_threads = GPR_CLAMP(gpr_cpu_num_cores() / 2, 2, 16);
+      int num_nexting_threads =
+          grpc_core::Clamp(gpr_cpu_num_cores() / 2, 2u, 16u);
       nexting_threads = new std::vector<grpc_core::Thread>;
       for (int i = 0; i < num_nexting_threads; i++) {
         nexting_threads->emplace_back(
index e35b1dd..da964f6 100644 (file)
@@ -118,6 +118,10 @@ grpc_call_error CoreCodegen::grpc_call_cancel_with_status(
     void* reserved) {
   return ::grpc_call_cancel_with_status(call, status, description, reserved);
 }
+
+int CoreCodegen::grpc_call_failed_before_recv_message(const grpc_call* c) {
+  return ::grpc_call_failed_before_recv_message(c);
+}
 void CoreCodegen::grpc_call_ref(grpc_call* call) { ::grpc_call_ref(call); }
 void CoreCodegen::grpc_call_unref(grpc_call* call) { ::grpc_call_unref(call); }
 void* CoreCodegen::grpc_call_arena_alloc(grpc_call* call, size_t length) {
index cac39ad..86172d9 100644 (file)
@@ -19,7 +19,7 @@
 #include <grpc/grpc.h>
 #include <grpcpp/support/validate_service_config.h>
 
-#include "src/core/ext/filters/client_channel/service_config.h"
+#include "src/core/ext/service_config/service_config.h"
 
 namespace grpc {
 namespace experimental {
index ea1ef0a..6796ad6 100644 (file)
@@ -22,5 +22,5 @@
 #include <grpcpp/grpcpp.h>
 
 namespace grpc {
-std::string Version() { return "1.41.1"; }
+std::string Version() { return "1.42.0"; }
 }  // namespace grpc
index bb332a8..e1ae787 100644 (file)
@@ -44,15 +44,28 @@ constexpr uint32_t
 
 grpc_error_handle CensusClientCallData::Init(
     grpc_call_element* /* elem */, const grpc_call_element_args* args) {
-  auto tracer = args->arena->New<OpenCensusCallTracer>(args);
+  tracer_ = args->arena->New<OpenCensusCallTracer>(args);
   GPR_DEBUG_ASSERT(args->context[GRPC_CONTEXT_CALL_TRACER].value == nullptr);
-  args->context[GRPC_CONTEXT_CALL_TRACER].value = tracer;
+  args->context[GRPC_CONTEXT_CALL_TRACER].value = tracer_;
   args->context[GRPC_CONTEXT_CALL_TRACER].destroy = [](void* tracer) {
     (static_cast<OpenCensusCallTracer*>(tracer))->~OpenCensusCallTracer();
   };
   return GRPC_ERROR_NONE;
 }
 
+void CensusClientCallData::StartTransportStreamOpBatch(
+    grpc_call_element* elem, TransportStreamOpBatch* op) {
+  // Note that we are generating the overall call context here instead of in
+  // the constructor of `OpenCensusCallTracer` due to the semantics of
+  // `grpc_census_call_set_context` which allows the application to set the
+  // census context for a call anytime before the first call to
+  // `grpc_call_start_batch`.
+  if (op->op()->send_initial_metadata) {
+    tracer_->GenerateContext();
+  }
+  grpc_call_next_op(elem, op->op());
+}
+
 //
 // OpenCensusCallTracer::OpenCensusCallAttemptTracer
 //
@@ -123,13 +136,14 @@ void OpenCensusCallTracer::OpenCensusCallAttemptTracer::RecordReceivedMessage(
 namespace {
 
 void FilterTrailingMetadata(grpc_metadata_batch* b, uint64_t* elapsed_time) {
-  if (b->idx.named.grpc_server_stats_bin != nullptr) {
+  if (b->legacy_index()->named.grpc_server_stats_bin != nullptr) {
     ServerStatsDeserialize(
         reinterpret_cast<const char*>(GRPC_SLICE_START_PTR(
-            GRPC_MDVALUE(b->idx.named.grpc_server_stats_bin->md))),
-        GRPC_SLICE_LENGTH(GRPC_MDVALUE(b->idx.named.grpc_server_stats_bin->md)),
+            GRPC_MDVALUE(b->legacy_index()->named.grpc_server_stats_bin->md))),
+        GRPC_SLICE_LENGTH(
+            GRPC_MDVALUE(b->legacy_index()->named.grpc_server_stats_bin->md)),
         elapsed_time);
-    grpc_metadata_batch_remove(b, b->idx.named.grpc_server_stats_bin);
+    b->Remove(b->legacy_index()->named.grpc_server_stats_bin);
   }
 }
 
@@ -212,6 +226,13 @@ OpenCensusCallTracer::~OpenCensusCallTracer() {
   grpc_slice_unref_internal(path_);
 }
 
+void OpenCensusCallTracer::GenerateContext() {
+  auto* parent_context = reinterpret_cast<CensusContext*>(
+      call_context_[GRPC_CONTEXT_TRACING].value);
+  GenerateClientContext(absl::StrCat("Sent.", method_), &context_,
+                        (parent_context == nullptr) ? nullptr : parent_context);
+}
+
 OpenCensusCallTracer::OpenCensusCallAttemptTracer*
 OpenCensusCallTracer::StartNewAttempt(bool is_transparent_retry) {
   // We allocate the first attempt on the arena and all subsequent attempts on
@@ -236,16 +257,6 @@ OpenCensusCallTracer::StartNewAttempt(bool is_transparent_retry) {
     ++num_active_rpcs_;
   }
   if (is_first_attempt) {
-    // Note that we are generating the overall call context here instead of in
-    // the constructor of `OpenCensusCallTracer` due to the semantics of
-    // `grpc_census_call_set_context` which allows the application to set the
-    // census context for a call anytime before the first call to
-    // `grpc_call_start_batch`.
-    auto* parent_context = reinterpret_cast<CensusContext*>(
-        call_context_[GRPC_CONTEXT_TRACING].value);
-    GenerateClientContext(
-        absl::StrCat("Sent.", method_), &context_,
-        (parent_context == nullptr) ? nullptr : parent_context);
     return arena_->New<OpenCensusCallAttemptTracer>(
         this, attempt_num, is_transparent_retry, true /* arena_allocated */);
   }
index 1c08f7d..871b8fa 100644 (file)
@@ -37,6 +37,11 @@ class CensusClientCallData : public CallData {
  public:
   grpc_error_handle Init(grpc_call_element* /* elem */,
                          const grpc_call_element_args* args) override;
+  void StartTransportStreamOpBatch(grpc_call_element* elem,
+                                   TransportStreamOpBatch* op) override;
+
+ private:
+  OpenCensusCallTracer* tracer_ = nullptr;
 };
 
 }  // namespace grpc
index 66ecd75..7886ae4 100644 (file)
@@ -83,6 +83,7 @@ class OpenCensusCallTracer : public grpc_core::CallTracer {
   explicit OpenCensusCallTracer(const grpc_call_element_args* args);
   ~OpenCensusCallTracer() override;
 
+  void GenerateContext();
   OpenCensusCallAttemptTracer* StartNewAttempt(
       bool is_transparent_retry) override;
 
index fa606b8..0a84680 100644 (file)
@@ -45,18 +45,19 @@ struct ServerMetadataElements {
 
 void FilterInitialMetadata(grpc_metadata_batch* b,
                            ServerMetadataElements* sml) {
-  if (b->idx.named.path != nullptr) {
-    sml->path = grpc_slice_ref_internal(GRPC_MDVALUE(b->idx.named.path->md));
+  if (b->legacy_index()->named.path != nullptr) {
+    sml->path = grpc_slice_ref_internal(
+        GRPC_MDVALUE(b->legacy_index()->named.path->md));
   }
-  if (b->idx.named.grpc_trace_bin != nullptr) {
-    sml->tracing_slice =
-        grpc_slice_ref_internal(GRPC_MDVALUE(b->idx.named.grpc_trace_bin->md));
-    grpc_metadata_batch_remove(b, GRPC_BATCH_GRPC_TRACE_BIN);
+  if (b->legacy_index()->named.grpc_trace_bin != nullptr) {
+    sml->tracing_slice = grpc_slice_ref_internal(
+        GRPC_MDVALUE(b->legacy_index()->named.grpc_trace_bin->md));
+    b->Remove(GRPC_BATCH_GRPC_TRACE_BIN);
   }
-  if (b->idx.named.grpc_tags_bin != nullptr) {
-    sml->census_proto =
-        grpc_slice_ref_internal(GRPC_MDVALUE(b->idx.named.grpc_tags_bin->md));
-    grpc_metadata_batch_remove(b, GRPC_BATCH_GRPC_TAGS_BIN);
+  if (b->legacy_index()->named.grpc_tags_bin != nullptr) {
+    sml->census_proto = grpc_slice_ref_internal(
+        GRPC_MDVALUE(b->legacy_index()->named.grpc_tags_bin->md));
+    b->Remove(GRPC_BATCH_GRPC_TAGS_BIN);
   }
 }
 
index e5b51a5..8dab33d 100644 (file)
@@ -14,6 +14,7 @@
 
 #include <grpc/grpc_security.h>
 #include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
 #include <grpcpp/security/authorization_policy_provider.h>
 
 namespace grpc {
@@ -22,7 +23,7 @@ namespace experimental {
 std::shared_ptr<StaticDataAuthorizationPolicyProvider>
 StaticDataAuthorizationPolicyProvider::Create(const std::string& authz_policy,
                                               grpc::Status* status) {
-  grpc_status_code code;
+  grpc_status_code code = GRPC_STATUS_OK;
   const char* error_details;
   grpc_authorization_policy_provider* provider =
       grpc_authorization_policy_provider_static_data_create(
@@ -41,5 +42,28 @@ StaticDataAuthorizationPolicyProvider::
   grpc_authorization_policy_provider_release(c_provider_);
 }
 
+std::shared_ptr<FileWatcherAuthorizationPolicyProvider>
+FileWatcherAuthorizationPolicyProvider::Create(
+    const std::string& authz_policy_path, unsigned int refresh_interval_sec,
+    grpc::Status* status) {
+  grpc_status_code code = GRPC_STATUS_OK;
+  const char* error_details;
+  grpc_authorization_policy_provider* provider =
+      grpc_authorization_policy_provider_file_watcher_create(
+          authz_policy_path.c_str(), refresh_interval_sec, &code,
+          &error_details);
+  if (code != GRPC_STATUS_OK) {
+    *status = grpc::Status(static_cast<grpc::StatusCode>(code), error_details);
+    gpr_free(const_cast<char*>(error_details));
+    return nullptr;
+  }
+  return std::make_shared<FileWatcherAuthorizationPolicyProvider>(provider);
+}
+
+FileWatcherAuthorizationPolicyProvider::
+    ~FileWatcherAuthorizationPolicyProvider() {
+  grpc_authorization_policy_provider_release(c_provider_);
+}
+
 }  // namespace experimental
 }  // namespace grpc
index 561d4f5..f778b13 100644 (file)
@@ -20,6 +20,8 @@
 
 #ifdef GPR_LINUX
 
+#include <inttypes.h>
+
 #include <cstdio>
 
 #include "src/cpp/server/load_reporter/get_cpu_stats.h"
@@ -32,7 +34,8 @@ std::pair<uint64_t, uint64_t> GetCpuStatsImpl() {
   FILE* fp;
   fp = fopen("/proc/stat", "r");
   uint64_t user, nice, system, idle;
-  if (fscanf(fp, "cpu %lu %lu %lu %lu", &user, &nice, &system, &idle) != 4) {
+  if (fscanf(fp, "cpu %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64, &user,
+             &nice, &system, &idle) != 4) {
     // Something bad happened with the information, so assume it's all invalid
     user = nice = system = idle = 0;
   }
index 4519eb0..f0fec74 100644 (file)
@@ -167,9 +167,9 @@ ServerBuilder& ServerBuilder::SetSyncServerOption(
 ServerBuilder& ServerBuilder::SetCompressionAlgorithmSupportStatus(
     grpc_compression_algorithm algorithm, bool enabled) {
   if (enabled) {
-    GPR_BITSET(&enabled_compression_algorithms_bitset_, algorithm);
+    grpc_core::SetBit(&enabled_compression_algorithms_bitset_, algorithm);
   } else {
-    GPR_BITCLEAR(&enabled_compression_algorithms_bitset_, algorithm);
+    grpc_core::ClearBit(&enabled_compression_algorithms_bitset_, algorithm);
   }
   return *this;
 }
index 43a98b4..b6c593c 100644 (file)
@@ -324,12 +324,6 @@ void ServerContextBase::TryCancel() const {
   }
 }
 
-void ServerContextBase::MaybeMarkCancelledOnRead() {
-  if (grpc_call_failed_before_recv_message(call_.call)) {
-    marked_cancelled_.store(true, std::memory_order_release);
-  }
-}
-
 bool ServerContextBase::IsCancelled() const {
   if (completion_tag_) {
     // When using callback API, this result is always valid.
@@ -341,7 +335,8 @@ bool ServerContextBase::IsCancelled() const {
     return completion_op_ && completion_op_->CheckCancelledAsync();
   } else {
     // when using sync API, the result is always valid
-    return completion_op_ && completion_op_->CheckCancelled(cq_);
+    return marked_cancelled_.load(std::memory_order_acquire) ||
+           (completion_op_ && completion_op_->CheckCancelled(cq_));
   }
 }
 
index 9c56476..50b8fd5 100644 (file)
@@ -83,7 +83,7 @@ namespace Grpc.Core
         {
             for (int i = entries.Count - 1; i >= 0; i--)
             {
-                if (entries[i].Key == key)
+                if (entries[i].KeyEqualsIgnoreCase(key))
                 {
                     return entries[i];
                 }
@@ -119,7 +119,7 @@ namespace Grpc.Core
         {
             for (int i = 0; i < entries.Count; i++)
             {
-                if (entries[i].Key == key)
+                if (entries[i].KeyEqualsIgnoreCase(key))
                 {
                     yield return entries[i];
                 }
@@ -393,6 +393,16 @@ namespace Grpc.Core
                 return valueBytes ?? EncodingASCII.GetBytes(value);
             }
 
+            internal bool KeyEqualsIgnoreCase(string key)
+            {
+                // NormalizeKey() uses ToLowerInvariant() to lowercase keys, so we'd like to use the same invariant culture
+                // for comparisons to get valid results. StringComparison.InvariantCultureIgnoreCase isn't available
+                // on all the frameworks we're targeting, but since we know that the Entry's key has already
+                // been checked by IsValidKey and it only contains a subset of ASCII, using StringComparison.OrdinalIgnoreCase
+                // is also fine.
+                return string.Equals(this.key, key, StringComparison.OrdinalIgnoreCase);
+            }
+
             /// <summary>
             /// Creates a binary value or ascii value metadata entry from data received from the native layer.
             /// We trust C core to give us well-formed data, so we don't perform any checks or defensive copying.
index fc167ea..3edf5ab 100644 (file)
@@ -33,11 +33,11 @@ namespace Grpc.Core
         /// <summary>
         /// Current <c>AssemblyFileVersion</c> of gRPC C# assemblies
         /// </summary>
-        public const string CurrentAssemblyFileVersion = "2.41.1.0";
+        public const string CurrentAssemblyFileVersion = "2.42.0.0";
 
         /// <summary>
         /// Current version of gRPC C#
         /// </summary>
-        public const string CurrentVersion = "2.41.1";
+        public const string CurrentVersion = "2.42.0";
     }
 }
index 56112fb..dbbd2c4 100644 (file)
@@ -262,6 +262,10 @@ namespace Grpc.Core.Tests
             var xyzEntries = metadata.GetAll("xyz").ToList();
             Assert.AreEqual(1, xyzEntries.Count);
             Assert.AreEqual("xyz-value1", xyzEntries[0].Value);
+
+            var xyzUppercaseEntries = metadata.GetAll("XYZ").ToList();
+            Assert.AreEqual(1, xyzUppercaseEntries.Count);
+            Assert.AreEqual("xyz-value1", xyzUppercaseEntries[0].Value);
         }
 
         [Test]
@@ -280,8 +284,12 @@ namespace Grpc.Core.Tests
             var xyzEntry = metadata.Get("xyz");
             Assert.AreEqual("xyz-value1", xyzEntry.Value);
 
+            var abcUppercaseEntry = metadata.Get("AbC");
+            Assert.AreEqual("abc-value2", abcUppercaseEntry.Value);
+
             var notFound = metadata.Get("not-found");
             Assert.AreEqual(null, notFound);
+
         }
 
         [Test]
@@ -301,6 +309,9 @@ namespace Grpc.Core.Tests
             var xyzValue = metadata.GetValue("xyz");
             Assert.AreEqual("xyz-value1", xyzValue);
 
+            var abcUppercaseValue = metadata.GetValue("ABC");
+            Assert.AreEqual("abc-value2", abcUppercaseValue);
+
             var notFound = metadata.GetValue("not-found");
             Assert.AreEqual(null, notFound);
         }
@@ -332,6 +343,9 @@ namespace Grpc.Core.Tests
             var xyzValue = metadata.GetValueBytes("xyz-bin");
             Assert.AreEqual(Encoding.ASCII.GetBytes("xyz-value1"), xyzValue);
 
+            var xyzUppercaseValue = metadata.GetValueBytes("XYZ-BIN");
+            Assert.AreEqual(Encoding.ASCII.GetBytes("xyz-value1"), xyzUppercaseValue);
+
             var notFound = metadata.GetValueBytes("not-found");
             Assert.AreEqual(null, notFound);
         }
index dda1cdd..aac3f02 100644 (file)
@@ -5,10 +5,12 @@
     <NativeReference Include="$(MSBuildThisFileDirectory)..\..\native\ios\universal\libgrpc_csharp_ext.a">
       <Kind>Static</Kind>
       <ForceLoad>True</ForceLoad>
+      <IsCxx>true</IsCxx>
     </NativeReference>
     <NativeReference Include="$(MSBuildThisFileDirectory)..\..\native\ios\universal\libgrpc.a">
       <Kind>Static</Kind>
       <ForceLoad>True</ForceLoad>
+      <IsCxx>true</IsCxx>
     </NativeReference>
   </ItemGroup>
 
index 1fd51a5..b07889f 100644 (file)
@@ -1,7 +1,7 @@
 <!-- This file is generated -->
 <Project>
   <PropertyGroup>
-    <GrpcCsharpVersion>2.41.1</GrpcCsharpVersion>
-    <GoogleProtobufVersion>3.17.3</GoogleProtobufVersion>
+    <GrpcCsharpVersion>2.42.0</GrpcCsharpVersion>
+    <GoogleProtobufVersion>3.18.1</GoogleProtobufVersion>
   </PropertyGroup>
 </Project>
index e2d0b86..afac220 100644 (file)
@@ -42,7 +42,7 @@ Pod::Spec.new do |s|
   # exclamation mark ensures that other "regular" pods will be able to find it as it'll be installed
   # before them.
   s.name     = '!ProtoCompiler-gRPCCppPlugin'
-  v = '1.41.1'
+  v = '1.42.0'
   s.version  = v
   s.summary  = 'The gRPC ProtoC plugin generates C++ files from .proto services.'
   s.description = <<-DESC
@@ -100,7 +100,7 @@ Pod::Spec.new do |s|
   s.preserve_paths = plugin
 
   # Restrict the protoc version to the one supported by this plugin.
-  s.dependency '!ProtoCompiler', '3.17.3'
+  s.dependency '!ProtoCompiler', '3.18.1'
   # For the Protobuf dependency not to complain:
   s.ios.deployment_target = '9.0'
   s.osx.deployment_target = '10.10'
@@ -112,6 +112,7 @@ Pod::Spec.new do |s|
   # present in this pod's directory. We use that knowledge to check for the existence of the file
   # and, if absent, compile the plugin from the local sources.
   s.prepare_command = <<-CMD
+    set -e
     #{bazel} build //src/compiler:grpc_cpp_plugin
   CMD
 end
index b64af71..bef081c 100644 (file)
@@ -42,7 +42,7 @@ Pod::Spec.new do |s|
   # exclamation mark ensures that other "regular" pods will be able to find it as it'll be installed
   # before them.
   s.name     = '!ProtoCompiler-gRPCPlugin'
-  v = '1.41.1'
+  v = '1.42.0'
   s.version  = v
   s.summary  = 'The gRPC ProtoC plugin generates Objective-C files from .proto services.'
   s.description = <<-DESC
@@ -102,7 +102,7 @@ Pod::Spec.new do |s|
   s.preserve_paths = plugin
 
   # Restrict the protoc version to the one supported by this plugin.
-  s.dependency '!ProtoCompiler', '3.17.3'
+  s.dependency '!ProtoCompiler', '3.18.1'
   # For the Protobuf dependency not to complain:
   s.ios.deployment_target = '9.0'
   s.osx.deployment_target = '10.10'
@@ -121,6 +121,7 @@ Pod::Spec.new do |s|
   # present in this pod's directory. We use that knowledge to check for the existence of the file
   # and, if absent, compile the plugin from the local sources.
   s.prepare_command = <<-CMD
+    set -e
     if [ ! -f #{plugin} ]; then
       #{bazel} build //src/compiler:grpc_objective_c_plugin
     fi
index 3b23259..642d1d8 100644 (file)
@@ -36,7 +36,7 @@ Pod::Spec.new do |s|
   # exclamation mark ensures that other "regular" pods will be able to find it as it'll be installed
   # before them.
   s.name     = '!ProtoCompiler'
-  v = '3.17.3'
+  v = '3.18.1'
   s.version  = v
   s.summary  = 'The Protobuf Compiler (protoc) generates Objective-C files from .proto files'
   s.description = <<-DESC
@@ -121,8 +121,9 @@ Pod::Spec.new do |s|
   # and, if absent, build it from the local sources.
   repo_root = '../..'
   bazel = "#{repo_root}/tools/bazel"
-  
+
   s.prepare_command = <<-CMD
+    set -e
     if [ ! -f bin/protoc ]; then
       #{bazel} build @com_google_protobuf//:protoc
     else
index 6fb1a2e..3eaea2d 100644 (file)
@@ -39,7 +39,7 @@
 
 Pod::Spec.new do |s|
   s.name     = 'BoringSSL-GRPC'
-  version = '0.0.21'
+  version = '0.0.22'
   s.version  = version
   s.summary  = 'BoringSSL is a fork of OpenSSL that is designed to meet Google\'s needs.'
   # Adapted from the homepage:
@@ -76,7 +76,7 @@ Pod::Spec.new do |s|
 
   s.source = {
     :git => 'https://github.com/google/boringssl.git',
-    :commit => "340faef0ad19283e985ce7fff0dec73ba4022c8d",
+    :commit => "95b3ed1b01f2ef1d72fed290ed79fe1b0e7dafc0",
   }
 
   s.ios.deployment_target = '9.0'
@@ -152,6 +152,7 @@ Pod::Spec.new do |s|
   end
 
   s.prepare_command = <<-END_OF_COMMAND
+    set -e
     # Add a module map and an umbrella header
     mkdir -p src/include/openssl
     cat > src/include/openssl/umbrella.h <<EOF
@@ -220,498 +221,498 @@ Pod::Spec.new do |s|
     base64 --decode $opts <<EOF | gunzip > src/include/openssl/boringssl_prefix_symbols.h
       H4sICAAAAAAC/2JvcmluZ3NzbF9wcmVmaXhfc3ltYm9scy5oAKydXXPbuJZo3+dXuO683Kk6NRM7nW73
       fVNsJdG0Y/tIck9nXliURNk8oUiFoOy4f/0FQErEx94g94arTs10LK21KQDEF0Hgv/7r7DErszptss3Z
-      6vX0j2RV1Xn5KESR7Otsm/9MnrJ0k9X/KZ7OqvLso/50sbg5W1e7Xd78v7P3v7zbptn2Xbo5//3i8n32
-      ++WHdfbbdrt9t8nWv71fpb+8u7hYX27+7d/+67/Orqr9a50/PjVn/3f9H2cX784v/3H2uaoei+xsVq7/
-      U35Ffes+q3e5ELmM11RnB5H9Q0bbv/7jbFdt8q38/2m5+a+qPtvkoqnz1aHJzpqnXJyJatu8pHV2tpUf
-      puWrcu0P9b4S2dlL3sgfUOv/Xx2as22WnUnkKasz9evrtJQJ8Y+zfV095xuZJM1T2sj/k52lq+o5U6b1
-      6drLqsnXmbqKNu6+v97jR/t9ltZneXmWFoUi80wcf93yy/Rscfdp+T+T+fRstji7n9/9ObueXp/9n8lC
-      /vv/nE1ur/WXJg/LL3fzs+vZ4upmMvu6OJvc3JxJaj65Xc6mC+X6n9nyy9l8+nkyl8idpKSvd99e3Txc
-      z24/a3D29f5mJqP0grO7T8rxdTq/+iL/Mvk4u5ktv+nwn2bL2+li8Z/ScXZ7dzb9c3q7PFt8UR7jyj5O
-      z25mk48307NP8l+T229Kt7ifXs0mN/+Q1z2fXi3/IRXH/5Jfurq7XUz/+SB18jtn15Ovk8/qQjR9/Kf+
-      YV8my8WdjDuXP2/xcLNUP+PT/O7r2c3dQl352cNiKmNMlhNFyzSUl7z4h+Sm8gLn6ron8n9Xy9ndrfJJ
-      QIZezifqOm6nn29mn6e3V1PF3mlgeTeX331YdMw/zibz2UIFvXtYKvpOOXURvru9nervtKmv0kNei76K
-      6VwmxNeJFn+yc+M/dfn/eDeXTnn7JJPr6+R+Pv00++tsn4omE2fNS3Umi17Z5Ns8q4UsPLLwV2UmM6FR
-      RUwW6p1Qf1CivFF3qypx1fZsl67r6iz7uU9LXQjl//JGnKX142EnfeJslUk404Hk3fuf//bvG3lnlxl4
-      Of83/cfZ6j/Aj5KZ/Onz9gtBh/nFs/Ts3//9LFH/Z/VvPTW7S7aJrGXga+j/2P7hHz3wH5ZDZA3V0iG9
-      53p5s0jWRS6TKtllsnrYjNX5pGNl6ECPyOrnrOboLNKxqrowWR22W1ncOG6AtyM8nycX/JT1acDO1KI+
-      dkr7tGePSYlwOjzKMt3ku0y1bDSvQXrWJ9nCFRlTbMOem5UIyK+PybNwjqm6Ii/zJk+L4y9JNoeu5qUG
-      wlV93Ol8nhRVukmUQfVuZFdsbCCI7c1399Nb9YG6BkqV6XK98X76NamzLt5CdhdUmzjSCrGAeZVXUXaH
-      tyO81LIV5eo9GHJHXD4o6GOoP17N7mXPJdlkYl3ne0qRhGnQruqH9CDr+TLfMPQmjvpXqrfCcysU9a7z
-      vezfR1x5L0BjbPLHTDQRMXoBGoPtDji//0zKdJcxxR0dtLOvuoVR9y79mcgqW/DKu2PAo+RlbJTegEaJ
-      yIJg+u/rbUQGdHTAXjXVuiqSiAgnAxql3q5j0ueIo/7ntDhw5ZrFzVHlJlRmcpGksl1jmDsSs66Kav29
-      q+94dtMARhGN7BGm9YabqRbvRLj7ep+km02yrnb7OtNTMcTu4IAGiLetswz4piBHxERATFk+3tHTzyJh
-      65v8EMSDRMw3rAD5BvFxkwVKleVfqhy8S9ZPqazF11ndkMw+DvrP4/znQ379iZUjafHICAR6kIjtMPVq
-      wgpzhGF39rOp07gk8xxwJNH+TE6ADvW966dM1o/7On9Ws+zfs1eq3RMAMdr+qvxtj3V12JMj2DjgL7K0
-      NlJPkCO4AiyGm0/MSJ4Gi7erNhkvhCIxa6XHVcxr72DfnZXpqsiSai32qlHcF3KgTw0BOdBIIn8ss64W
-      UFMXEtjtBTMkLENjN4VQ+VeWGbm7iUn8WNviIJ6Oty75h9k0YJftO9kpGd+kG3GVcvk2X8tagGp1eSyC
-      ul94bkWGrLyb2eWRCPu0TncstyYxa1vjMmpsBwf97Y0gGvV8hq43aMSuq3TBUrco4j021UmRi4altwxw
-      FPmn9FDI4WIqxIusM1acQJ5kZKzkILJ6kzbpmwQ92eDo2c+EG6pDUW+ZvcgmfZP9ZMpPPBYhsqUGJXCs
-      vNxWyTotilW6/s6JYwngGPJGLarHqCiOAo6jJqH03cu9gSwBHkNPtbCmJDAJEktmXXwsV4LEYvTWjhxs
-      ZPbUDBT2/jjk6nHz06HZVC+sJLENcBT9rCN9os4MeTRs73o2sjzLIQg77X0LHI34tBFAEW8hZC0jv7P+
-      3t6irMz2LXA0WXzz7WtULeIognE22b55igii+WAEbrYbuO/XTyu7bxTVOmXdg6DEj1VmctTR7PbJfEGe
-      nDBZyPxCF774njrbVc8Zd/LBpn27+iBJ12uZ01S1gQa9yWNVbSLkmg9HqLMye6yanDH4QTRIvLaa2h6K
-      ghWnxzH/KnnK6Z0lk8XMlRznrnmZ3LFhMz+bTcFAjNiMBjxIRD0Y0dkl8r95wWxFII7+4oodo8UDftVX
-      j/C3eMDfVTIRIU4GJAr7pgjcEWpxbsaztijiLQ+7FfFxmY0iXhFfIsWYEiniSqQYKpEirkSKoRIpokuk
-      GFEiu14lr/wcYcjdvOsWTyb7qmI0MzaPRGDN5YnAXF772XHyRvDUJxzxH/u+7Lkx2AJGO2en0XkgjeRn
-      h/qZU+uc0KCXNW3g8kiEbP3EGiBZMOJmzdH2JGIV+WNaPPIuuGPDZn5ymwIkRtwzDkCBxHmLu+p85F2V
-      yGFr9ZIcyu9l9aIeGO+7mR1OJuEyLHZktDF+kRWqg8lpeVwDHKV96s7Sd2jAy83/wXzXn0dOf2AeJKKe
-      Nk7LDeepuidAYrSPxpm1gIkj/qjnKWLE8xTjOzEFyzIgUQ51rb6k+j7cMLYCiyOL4a4rI7wohgCOEf0E
-      Sox7AiXe9AmUID6BMr/f3XL7tHkSMXFNDxKxErqWlXWgnhjmpa0rgWNlaV286udk3ZoATjMLWJBovKd5
-      IvQ0T324TQuRqfUaddckZpuke6FVtyicgENO+Eoe6yyVWERa2gY4StTzPjH8vE/EP+8TY573idjnfWL4
-      eZ94i+d9YtzzvuPXRCbbzG2dPqrXTLmxLAkSK/bZohj3bFEwny0K9Nmi/kTEFS+TH46QpPVjbBTlgCOV
-      6ulXm4pR/V/IMxRRJOnmWS1eEtkmOqwjg2Pr5XF1JvZVKViFwhIgMXhPnkXoybP6UG1KcGgytbQiKwU3
-      hG9BovXLUjkL71ELEk18P/VEI24sQIPH614UjY3naJB43aYVnBgtCnt/HPJ1RPYYOOqPWO0gRqx2EFGr
-      HcTAaof280aNBqtS9vTEU3rx4dek2prjHsGLOmTFrqbrR8u+raxHDruMF921wNGOVXG/QpRZz4IiLGbs
-      6hIxcnWJ+b1cveRTNrJai4nWW8LR1I2/ecq4a1sCKiQutMaa3fHEbXj0vHxUL4lUtRxJ7PROQoIbGlAh
-      cetmrxr3bV5kvGimAInR1Pk6ejrIt8DRumVG6sW9iGrbt2DR2KUzWBrtuemYMSNsQqOqzl7b3qpXvLgd
-      Y1A0NmZMdwG3haM3aXMQsb/2JBkTi9dIuI5gpH7FXVw0yzMyoniTeCIY7aAmYWT9ExHqqEDiyDp788TS
-      azJkjSvmtgKPk635169Y3FyLlCuWaNAbnTSmA4lUH3jNkAZhJ39SPTSb3vVC36BjAJuCUVlrZMXgGtmD
-      GuBvqd6WAmzyHr5vR8F/0B9m2fSQPZksbs/jQmjFYBzVn4qMoxRwnPliEpdglmBEDHay+ZYx0biJ51vg
-      aBGvEzr4oJ+dcq5jOFL7SJebdrBpOOpbxMMjqaFfu0Fk85o85fQZd1Bix5pefUn+mH5bqHfZKXqTQ4zU
-      12AtEHE+pSLZHPZFl1VVuc0fiUtohlxI5F1ai6e0UBM79Wv3bcGKC5qQqMRXDUwOMdKbLwe1vd1GZYna
-      LPf0GLF/bEqJM6CC4xpPaNfpXg0POSF9CxyNWqRNDjNWu2T12tAmMHwatrfvUZM3+QHwgJ83tYYoAnHY
-      D2dwSyDaPotIMwUPuM02QEQFskxDUdu56Lh4rSMQ6W2mI0cqA9fRjsXZMVsc9XNWfQB40M96lxtz4JFo
-      LahN4tad2ue6pi7Sgw14lNPWcoylAiEPHrGb4inybabXq1G7ZkOuUORdxo+0y8Jm4lwwgOP+yMwJ5onq
-      yEVWbo4Cj8OvUnoatueifVTH7cOYPByB2Jk0MNinV4fzqo4ODXpjehWOAo0TU4eLoTpcvFHtJEbXTv3T
-      H26cUAkVETWQCNZAIq4GEkM1kJBjiWKTrNTbceVjkamRMSsQ4IEjNhW/V39kw+ZkW9URmQ1o4Hj0AaNN
-      2lb6C+nQe+gRezUG92mM2KMxuD+j2igw3bdTDeqhviywDWWn95DDj8TakzGwH6P6SM1Sda+CHFb/ytaN
-      UCVI9sJpDzoGVE7cQn1JbVje7W5PiuTCA+6kqCIDaAMURY/Su4cKqokuGnoc3wFFal73GTutDHjAzUwr
-      12BHaVfyPOWkxDlBrkuteyr0gnPmDpyIwomjFnK12zeS3D3m+GL2DB3YL5R+lcD1xewHOrAXKG9fTmxP
-      TvZ+nIG9OBkbbYD7a6wPTfNUV4fHJ73HbpHRnsQAuO3fyGL7qM55S9Z1pqf+00L1VEg9dVTixKr0wS9y
-      2PSd9CNMzjHKbgPjtTgDs33t3O5ppfu6+dkvblZjS0qQIRcUWc8qt50YWg4AOOpX79aoPgG56sccTqT1
-      E+8nGJxjjNzTdng/2zfby5awj230HrYj9q/N6lr22JmHwHiw4/65r2q9eEm10Tt5+9fyticFAA12FOpT
-      FP/pyenwSrWsSx9EQPH5tGtv3pkvbNPKvE8DdvMBsOoWCXIEzwBF4TXU4d139afqxtYrFCvZJ61zWpsN
-      G5Ao7OetsAGIYryadNo6ip7joAWIxn6KNfT0ircjMrYbcv+0J3bcGjZhUblPx8Y8Feu/03VyuhMO2pVl
-      zHCgCovrrmZjxvQ0QLzu/aM6+3GQTZZswIh7+KASMFbMyxaIAorzJs8XSc8VH/XWLvSdGk3OMybdQh2i
-      8Ij5PubaLgcFvO2LC6tX+iFKAI76GTmIv1PB3A0d3Qk9bhf0oR3Qjc9rOS6qdkx5CwPuboMN+mIQnw7Y
-      +yNj2CF6BR6nP/qYGeUkAGM8Z8Ruu8lhRupxRTbpW4/7bjCemwC47/dGhtQIngCIoYYjZK+CABf9SR66
-      CsP4IPnrw7vfk8Xybj7VayrzzU9mCMAERmWt+Qiv9ei23N+JRBz2aoBGVxuw796S75YtcJ/If+TiKaO7
-      Os43svcTGTg7QH/8TG5XJOJ7ToPQpMjI95gF+272HiQD5w1EnzUw4pyB6DMGRpwvwDlbAD5XgHmmAHqe
-      gF6RdBzG0DesBPCAn9lldHkkAve2tmDMfSiK2CRyHEgkvRdCI7tXQk9w6SGzYMUDTUhUNTxJm0Od9YM8
-      VkzAA0UsN2rWjtdHtGnAzjpWySYBq/F6A9lrsGEzeYkfKPBj8PfPGDopRG+9vcorqlMxgIm1A0forJHT
-      Z0LNKZTrjCU+woCb3iWpoT6JyNbqrul3ldeTV7xOVMgFRW5nj61dCughAQkUq53fYY08LRh1q1dbGfe+
-      TWN2ztiqJ0NWPbfOV2sc8rPGyOg8knhKazWLxZvusGnUzthz2achO6/2w+s9oLFLNvljRu8C46ZxUVX3
-      nFWAAq5xkVl3BOIBInJ3XnkM77pirIhPH7NEfKetWAZwwM9+OOvTsP1Q5j/ok6Q9CVqNnTNOD4EYISDN
-      UDxOCfYNfpSITaMHz8uKOSsrfE5WxBlZwfOxjA/piwQ9GHRz2hx03PzC6F2+gL3LF3pf7QXqq73IKitj
-      dyht2rardzdin4NiDjtSXjLfnrVAz2ls+kuUGqRnlWNzqk4hjkckG1lbkDwt4nmUnDXd4LKeue3REZUt
-      5LuAZlZt+rIX1EQImOyoqu9w2G+Iczw9ZduKfFWn9Ss5+03OMaoj/frHY9SRDoAD/nbtU7u8TZD1Fm3b
-      d+ljvj7Nf5w27mtI5QWVuLHazQPUwpZ2SQstiEu7drU9s/yCWpRDHe57sO3mnseIn8VIfJ/Ne4+tPOzs
-      wTipVPi0bd9nGalLo77vGnRhoEk04njqaq3OptITj/tKNLwluwENHE9W0efv9SOpY3Gmv6405PIiP+eb
-      rL1Eagvqwba73QxXlvHTr062Rf741FCf2wRFQEw901Vkz1lBjtKjgLft8PDEBmuba2KlUXv1BPMgSPTc
-      R+MDzh0F4K5fL4oyclPN9QpaDFDhxhHuQ/V/Ed9GQBR2nG4r3349IyWCB7tutfW/jFy0rwTR1DbrmtU6
-      4/zvrN3AJS/yJqdNTcAGLEpEbqMSN1Zbz9UZ9dUNm3StnDMCsfMBI84GDJ4LqD+kPr44QYAr6iS0MWcL
-      6u+8cK74Bbric1YenSN5xDmbED2XMOZMwvB5hPpT6L0jcghIAsTqu8G8X+LwQATyemzs5EPuqYf4iYdR
-      px0OnHQYecrh4AmH8acbjjnZUPBW6Apsha4+B7A9j1zNi1Kv12IBM+8MxOD5h+pDep2WQDUa5xA69GTD
-      qFMAB04AjDj9L3jyX9ypf0Mn/unPuyPQWYXLggE39+y9gXP34s9qG3NOm/5O+2qdqrPbo8jIQVwBFGNb
-      1etMT8Lp2TORPjLiABIgFn29K7pjjSCv4RTAGk71t6h+cTPUI45Y0TlwOpz6+F+b7+fnyUtVf0/r6lCS
-      08Pl/Qjs9ZgD58FFnwU34hy46DPgRpz/Fn3224hz3zhnvsHnvcWc9RY+5y32jLfh8930N5oDWdocfA/7
-      lcaBE9OYp6WhJ6XFn5I25oS0+NPRxpyM9ganoo06Ee0NTkMbdRIa8xQ09AS00/Fl5ta+9HcSAxokHi+7
-      0ZPWTh/GLD1GJUgstW+4GkCv1WvTm2xf5SUv1SARGJO5DmzoBDn+6XGhk+Paz/ppYU5r4vJQhLc8l45z
-      Jp2gr6MV0DpawVvxKLAVj/Hnuo05001/5ynbGH1S+gNXVALF4pV/vOS/zWvSlBPh3ug0uNEnwUWdAjdw
-      Alx7bhtjJI2MoONOkhtzitzbnL029tw14yCqJ/UwmLriFOLRCDErH8XYlY8ieuWjGLHyMfIMsMHzv3hn
-      f2HnfkWe+TV43hf3rC/8nC/mGV/o+V6xZ3sNn+vFOtMLOc+Ld5YXdo7X25zhNfb8rpizu8Lndgn6KlMB
-      rTJltdFw+0xuWYBWRf2JseebyeFG8iafHmy7m6rRh95w11tBvB2Bf5Za6By1yDPUBs9Pizw7bfDctKgz
-      0wbOS4s/K23MOWnxZ6SNOR8t4my04LlosWeiDZ+HFnsq2fCJZNGnkY04iUytVUmesqKouh3bulVRxDCg
-      w47EmFcGZ5JfUloiqO87BrWMjqRQgOV4vnh/HMKTp5481jOzlIirm/9jKS22Ny9vFrwf74G2ky6DLKwf
-      7IG2U52LlqwO260skAwzgFv+5/PknJ2iPuy7eVLMxk1hH3bdFzGpcBFOhQumFLNFpMJFOBUi0iCYAhwh
-      bIr47cgv31zkiXGKxVing6E+ynoaAO29+cWGc50Ohvoo1wmgvVe2+lfzb/fLu+Tjw6dP07keBLeHPG4P
-      5XpsjAHNUDy1h/AbxDtpAvE2WbbXF8YOdTIEoqhXIcpDUbCDHAWhGIcdX3/YBcz7g3hiqxUccIvxb5hA
-      bMBM2vwSpi37Yr68l9+/W06vluq+kf/5aXYz5eTtkGpcXFJ+ByyjohHLQEhjx1NrL2f3X051xG5PvfMx
-      BRZHrTduMl6AlkXNhz1Te9hjTvmnDU+qSMzKKbQ+jdppRdMCMSe1ANokZqVWEi5qefWWkbeTr1N2UUYM
-      wSiMthlThOJw2mRMgcThtMUAjdiJN5INYk7C4QgeiDgJL8q6HG6k3uw+jLj31Z6fCkcYc9NueRtEnHqF
-      c8yNaQqwGITtxjzQd8bdfkN3Hrdw4OWCVvsfEd/DLVp4qRJP+ZacMxryXdSWo4d61+TqSg7Ckuvp4mo+
-      u19SD61H8KB//CYQIBx0E2oumDbs00Vy9XVyNdrXfd82rFfrJCvX9ev4QywdzPFtV+cXlyylRTrWpuZa
-      LdK2bjKyrkNsT7ZecS7NwBwfwwV5KnZeVIG8EHqzdf0B5U0lAPW9XUCO10Bt76F8qdM9VdlTmC3Zp5vN
-      +KVIIGy7OdcJX2XENeJXuLg9Tya33yj1Y484no+zZbJYqu+3xzySjC6Mu0lNBcDi5kf9WmDDlXc47uer
-      Q1ZK8+OjAe9hRzseGhXgMQjTYAAa9MbkpIBz8us9uwhaKOqlXrEBok5y8TBJ13p3dzOd3JKv84Q5vunt
-      w9fpfLKcXtOT1GFx8yOxjNko7s3Z2lA6ULPLRnGv4KeCCKVCUyUfb7lmDTvuT8xC9gktZZ+ntzLezex/
-      p9fLmRxuppt/kcwAPxCB3vyBhoEo5FsGEgzEIGaCjw/4qcUd4Aci7GvCMiDcMBCFensB/HAE4jLKAQ0c
-      j9vC+XjQzytXWGtnf8wsU2irN5t84KaKjaJeYmqYIOqkpoJFutbb5fSzes6029OcPYcYCY+OXA4x0vPI
-      ABEntQthcIgx5wlzzEfO7Z5DjIL5mwX6m1XVc5BV6a+/cMUdjvjpXRGLdKy3Dzc39MJ0oiAbMdM7BjJR
-      s/sIOa67j/89vVqq/acIi4l9EraS087gYCMx/U4UbKOmYY+5vqvltJ+8IFaRLhxyUytLFw656bnl0iE7
-      NedsNmQm56IDh9zUKtCFHfe9/Pty8vFmyk1ySDAQg5jwPj7gpyY/wGMRItInmDLsNAmkBj8dgilAebUT
-      QB3vYvrPh+nt1ZQz4euwmJlrBYxL3mUukStsi1ubNulmQ7M6cMi9LrK0JNbTkCAUg9oddWHYTW250Dbr
-      +AFhRYvLwUbKVmIuhxh5ObXB8odcZeE1ef9Q4R37h59g1H06YnmXiu/MEJYDjlRk5eP4d2V9ErZSK120
-      zek+oE8VmWDAmYw/Jxliw+Zku4+RSxz2C14tI7D6RW0kzBS+Q43J6jW5nV0zvR2N22PvDjHq7nC/laRi
-      /RbRlAeOKAe8D8tPl5wgHYp4qR0Wg8ON3Bv9yDrm5a/n3OraRlEvsddigqiTmgYW6VqZz1iW6DMW1oMV
-      5GkK8xEK+txEf7DJt1u6TlGQjV5wkOctnIcs8JMV1uMU5BkK88EJ+rSE9YgEeS4S8zAk/AREfyqrt8es
-      zGp9+MFG7SNFj+A73Ejf7qfk/vYRglz08nikIBt1fHGEIBe5RHYQ5BKc6xLwdam91Vmyc8f2cDv7czpf
-      8J+cQYKBGMQKw8cH/NRMA3g3wvKK1UQYHGKkNxQWiVl3e72JXNLw1Ccc8dNLiQEizpx3rTl2jeRS0HOI
-      kd6kWCRipVYLBocbOc2Lj3v+T5fsasJmcTO5GBgkbqUXBhN1vH/OFrOIeXAfD/qJCeLCQTc1WTzasdOO
-      ADcQx9P2Pxo5/FFbeZJ8Nop5n9/zpM/vPWOTVCvKKWEO5vjyJtslm4ucZDtCiIuyz4AHYk7itI3BgUZ6
-      wTE40HjgXOABvDp1oAMnS1oOMZLrDRNEnPnFhqWUHGKk1hAGBxl5Pxr7xayfi/xWtcEG6z7pQMzJuU9a
-      DjKysgPJi31K7HmeKMimNhOm2xSF2ZJ185NnVCRkPZS839xykJG2D6jLOcbdqtvZkfzsySIxa8nXloC3
-      bb5kev9Nu6MNzjHKXvIub/LnjF5N2KjrPTRJVtHmpDsGMDFa+x5zfE36eEF90aNjAJMYfxy2ybimbLcv
-      9B6F1EywSMP6sPwigeW3ZHb76S7pXiIl2VHDUBRC2iL8UARKjYwJoBh/TL/Nrpmp1LO4mZMyRxK3slLj
-      hPbej5PF7Cq5uruVQ43J7HZJKy8wHbKPTw2IDZkJKQLChnt2l6T7vT7aKS8yymbwAGp7T6cYrZu6oFgt
-      0HEWWVon2yIdf5ymg0G+dtNRptWAHbfaTEUfqay/QjLbqOOlJqefivIverioj0ohbtiKCpAY7Znjj4e0
-      Tssmy1hhHAcQiXhEuMvZxk11PFeR4usp25ZVW4pGft3m1a4zpMfIFuS4CsJOKifAcdS0XHTqye4vSVoU
-      VItibJNea0NYCmQyvmn8VvM9AVj2ZMvet+Rl3lA9ivFNOzUJwUijIwcb9+M7hg7m+9QOMrK8jl8S5IG+
-      k1mnOyjmVQeJjt+KGmJ9M/WUApfzjNQf7vzap+zn5rAjFeYOsT0qg0pSWW4J19KQW74jY5tUMdRHR5W0
-      FDI519g8kavFEwS4KB08gwFMepMq0sssAIp5idlhgYhzIzsSdfXK0nYsYqbeEBaIOOUgnOdUIOKsCUfe
-      eSDiJG1Y75O+taL3SAzM9hELu1fOVSOwyqtkn+Y1UXTifCOjA2hgvo/Wt2gJwEI4I8JkANOe7Nn7FlUn
-      rg5bqqrDfJ+o1t8zcqK3lGv7SfT8dA2H3SqryfejgYE+dUfJNoSh7Ejbyhj4gGOefUUqEPLrDq+WI5AK
-      Qks4lqYmNytHxjERBzp7b5xDrdz9Op1adPwy055lKspzqkZDgIszy2OBrlPQblcNOI4X3lW9INckOHW3
-      gGtuQay3hVdrC3KdLYAaW536saNJJOA66LWrAOtW3YcrCGc+WxDgkkmvT5OklgEPRtxqILAn7MUKwoib
-      7YWd1JG6AGczBHk2QwCzGfpv1BH0CQJce7Jo71uoMyMCnBkR3YQEsfdiYLAvq7ZqnH+oS462p317SVhK
-      YDK+6TQPQS4hPRmwEmdGRHBmpP9U7LN1nhY8dQdjbvIAyUF9L2c2R6CzOaehWHcKFOkROSpwYjxVh2KT
-      yBERJ6VdGHSTi1yPIT7igxWTA430gmBwrrHNSfkZTXjCHF9J72MfGdvUZIJRsfeUbTuoQ5lJV9UStuWZ
-      On/27M+dPXOS6BlOoxfGwOoFHFmRixRQltpbl/jI5ARBLk6X2yYN683kj+nFx4sPv462nQjIknzKS0L1
-      43CgcUbpNNgY6HvYbyhzqi5oOG+Tjzez2+v2Pf/yOSP0Jn0U9pJuLYeDjXn5nBY5KQlAGrUzkyEPpAJl
-      ntHGLN/V8q8kG3+ASE94FmK2HBHPQ3g5rSc8Cy15OsKziCatqVejGcv0eXp79VGvAyGoeghwCVIanRjL
-      9PXudqkvmLLo0eVgI7EoWBxspGWniaE+VcmIhvICKCrAY2yrOtlVm0NxENwohgKOQysMJob6kkLNk2yY
-      2o627OlKJLlIXqqaYjUo27YhWTYeTb6QDrE9Yn2xKikWDViOVV7SHC1gO+RfcpJDA4CDePSAywHGfUq3
-      7VPPtF6tWNfWc65xk61pKgm4jifCGo8j4DqKjPXDTpjr2+1zmkkClkOvAyQo9Pd9A2V7fpMBTMTmpIds
-      F2Hxx639Hn77b2qdcURsD62x9drYdXUoVQX7kvyd1ZVKMEHSebRll2WcVhu1gO3InymC/Nmlqel8RGzP
-      gZLb1ltt8t9Z+ZSW62yT7PKiUI8/U13J1flO9vSbVz15QNCP0dnxfxzSgtVBcUjb+pOSJvLbFk28C737
-      b1tXO9mRKZvHapfVrySVRVrWxzWlqMhv2/TxrVWVF1lCqs491jE3Sb1dv/9w8Wv3hfMP738l6SGBF+Mw
-      frPlnvAsxDvuiFge2bbR6o4WsBykhyG37nOQW9VXlHUasUfcQ66rzB5T9coUTXakXFtF6rS2gOcoiRcj
-      Adexr14uaBJFeBb6HWNQsG2bylpLzcvytAbu+okFHBpzyL+pRpNmUYRlKTLaTaK/bxtIpz2eAMBxTpac
-      W5ZdWosn2dqQVnTYmOMT36k9mhNjm6oNcYzYEZAl+XHIx78T63KekdYKdwRkudBtIt3VcpCRKQz7WN0Y
-      WIDHIN7fHuuZ9dSroF5yR2G2ZFWoxeAbnvVIo/ZqwzVXQMkn1zM9hLjOWbJzzMa6Ly0WMUeIEe/uUBB1
-      koAsvA60D3tuYqfgiHge8aMmaiQBWRq6xi934rCiag4ryMIqEifOMzKqK7+W2ue0rkQL2A5auXTLpCxS
-      1F/SIZaHNrnvzumXpUweCq++7xuod0AP2S51JiatC3NEQA81gS3ON1KO+zQZy0QbhLgjkH2qWhzV+UsO
-      pdqLhNQeArRt587RBGZjSLvaHb/vGygLBnvE9ojssKmSOiU9sTUozKb+z2PGc7asZSZeoHdlrEsKXEv7
-      Z9qw0uJsI7VnVPu9oprcI6qB3hDxGNye8CyMqQ4T83y0eSkBzEsJ+ryUgOalaD0StzdC7Il4vRBaD8Tt
-      fageBDUNOsTyNFXiHM1KMPow6O7OWmOIO9K1srq6FmcZD7QJgYM7G3CgPUA6uE+QDrSicHDLwnNaHDJi
-      23tiLBNxGsuZwzp9ZXso101elckToQYCacgusmJLa8N91PA+fEq+Tr92W7yMVlqUbyM9EjEY3/RYVy9U
-      k2JgU3vGEMfXkr6V0kXvEd+jXpiqn8mJ1mG2b5ftKE/5ToRtEU1NtLSEZynWaUPUKATwEJ4Q94jnKek/
-      q4R+V1lkJdVTmO91Xn38qKdDKdPEJgObklVVFRydBhEn6fBSn0Ss1boh7zeNCrAY+aZ9TtoQ3hTGDUiU
-      Az+BDkgKkYakFuS7xD5dZ1SXhnzX4fxXqkkioKc740oO6eRHP8cPdwMKME6RMcwF9NsvyHksEdAT/dt9
-      BRDn/QXZ+/4C9DDSUEGAi36fHKD7Q/6RcU0KAlyXZNElZInO1MvhPFW9TnK9oCHbRTyv0UBsD+VN1uP3
-      HUNOfCHLglyXWKf1Jlk/5cWG5jNA2yn/Ix+/y0BPQBbKxtM25dgoO7ydAMDRNkJqgmD8/nUgbLspC1aO
-      3/cNCfku6inbRuirdV+3eWL/3EBsD2WIefy+aVh0XbWsViP6TVaPl3ko5M2bbt/mp1RQZtBwAxBF9ajk
-      JdB6ZD5rm9WeXWleim4F5yulOoFo175/pXbJTMq20erMhVdnLvRKs7R8JY4dbA43JlmR7Qi7uWE8HEGV
-      wNgorgOIxEkZOFXooyoHRJzc3z/4u5N8ty/ydU4fXOEOLBJt4OOSiPXA1x4QL/nmPUG+q0hFQ+o0Wpjv
-      q/Zqxo+4YgyEB9ysYuwbhqLwBvZDpqGovEIDOfxIpFHvCQE9/EECqgDjFBnDXGSA64KcqM6o9/TH6N8e
-      HvV2X6KMek8I6GGkoTvqXVCXoxsI6GFckzvq7f5MrsCguitm1IsZgChlkxeyY18LcnNpoLaXNkZZeGOU
-      hVrIfFxscWrTskdapxxzeJH0y/ROJ5sYCFKE4vB+ji+wY5DGYgt3LLZod1BSr/NQLCfIdu2z7Ht7qU1K
-      Sk0LtJ3ie76nqNT3HUMz/qnX8fuugfL0picMy3S+nH2aXU2W0/u7m9nVbEo7SQPjwxEIdyRIh+2Ep3UI
-      bvi/Tq7I2wRYEOAiJbAJAS7KjzUYx0Tao6UnHAtlX5YT4DjmlE0oe8Kx0HZ0MRDDc3f7KflzcvNAOinW
-      phyb3scgE7T8d0HEWVTdvp4s8Yl27O16wyIntMc2ZvjmN8n1bLFM7u/I5/VALG4mFEKPxK2UQuCjpvfb
-      /fIu+fjw6dN0Lr9xd0NMChAP+kmXDtGYPS2K8cemASjmJc2ceSRm5SdzKIX1XLRsWnnmI43ZKb0oF8Sc
-      7OIQKAl6qxb1+JydEqYBi0LbnQ5iPfPXh+X0L/JjMoBFzKThhwsiTrXBDGn7RZgO2WlP6mAc8R/KuOs3
-      +HAE/m8wBV4M2VH8Jlt46gNDCEbdjFJjoqj3oDs5yUr9PMEMYDm8SIvlZDm7iiyosGRELE6WI5ZwNH4h
-      xjSj4kX/vmDJXn6ZTyfXs+tkfahryiMLGMf9etvs7mBAbhDTEY5UHnZZna9jAnWKcJx9pSZC6pg4ncKL
-      s16tzy8u1X4z9euemi82jLmzMsLdwb57u1Ifn3PtDo75L+P8g9cfZUfdT6n8X3Lxjqo9cr6x7YmovrU+
-      Wp7eiwYMfpSmjkgTCx5wq38SZvlxhRdnW9Xf5Q3RqIOm88eyqrNkl26ek5d8n1Wl/lRtPKhW0VPmXzly
-      /9rowxRwfKIPWeQVAxP1vI/rnUrglNzy9SDm5NVvNjzgZpUpSIHF4d0XNjzgjvkN4fui+xKra2uxmFmP
-      d79nrzz3kcbssgkdv/0agGJeylMDF/Sd6pCP17Yf1h7Jx+0LBUzBqN3Zem8R1lUF47YXGh/U8oARedWe
-      QWJW8ummCA76ddPQbayWVyUjhGMAo+jUo+wWD7GoWa0JjMhiVwHGaZ70KVbyu4SHFjDu+59StRKXPv7u
-      Qc+p1kimYkcUdpRvazuA5H7jifOMuloVr4Ly3jqA+l59ENc2VwfA5mmRrA6U5doBhxepyFd1Wr9y8s1E
-      Pe+OM8O9g+e22z9zLtEgfWu2I7yZa0GeS9VOvJrTIH3rYZdw5ptOnGesYkZlVXhUVpVrasWoEM+zr4rX
-      8/fvPvD6Ug6N2xmlyWJx84H2CBWkfbscCwlZVayqn6xLd3DPX28YdVgLIS61Z0+T74vsknK6WEDhx8k4
-      lUxHAbZtu82xHKwkKrjeEpL0QsKQCI+Zl2tuFIl6XjUjpt5riuk3gg4w0tv0yQWhTy7erk8uKH1y8UZ9
-      cjG6Ty7YfXIR6JPrwwA3MVdv0KA9skcrxvRoRVyPVgz1aHkdO6xP1/1dz2CJLGNqTzjqz7dJ+pzmRboq
-      MmYMU+HFaQpxLtsTao1+xAzfcp5czz9+pp0cYFOA7bi/Nll4BAEnqcU1IcCl3nsj5L6NGb6n9EqNSYhT
-      WhbV266ni+Mk3fuxLpOxTdl69Z7ayXQ5z8gUIr5NdqEewbCkDuuZ30eY3wfMJT1/joxtKpnXV6LXpupS
-      wuSkgYCe5FCunzLKUUIg7Lsr2aHZp3XekC+1Jw3rl0RHGu3qvu8bkv1hRUpAh7ON1W5/kN0noq+nMJua
-      WXki5AkEo27aaTYgbLkpT4O6r1v86ZwGWjKaGOyTpSjdZU1WC8LGgqjAidG8Sx5JTgX4DupvbhHfs6da
-      9oDjB/kXSQTw1Pkz54cdOcBIvmlNzPf9oJp+uA519Mdvv5//nly8++WSZrNQy3vceL8vdwSzD1tuwpLK
-      9ts2Tdw110AsT7vsmvX7XNTyCvq9JKB7SdDvAwHdB3pYpd8lo5k6yHYRzt7uvm7xtCWpJ8B06FQXlDOb
-      TMYwzebTq+Xd/NtiOaeeFAuxuHn8MMIncSvlJvJR07u4v5l8W07/WhLTwOZgI+W3mxRsI/1mC7N83asG
-      ye3k65T6mz0WN5N+u0PiVloauCjoZSYB+utZPxz5zbyfi/1SPQe3pzzOBWHDvZgkixmx9jAY39S1nVRZ
-      h/k+SgL2iO/RbR7VpCHb1Q5h1Mu9aXOoSUYHtb2bKkbt055dfUJUKsTzPGd1vn0lmlrIccnG8foLSaQJ
-      20ItuX6pZQ2aHA4x8oZNqMGNQho4nQjAQv7lXn/v+Nc92bOHLD/ov8vuN57+Sh1AuSDkJA6hHA4w/iC7
-      fngW6iMXBwN95AVQEGubIwZmII3YZe4xbmkAR/yHVZGv2foTbduJbZ3XzrGHhAALmnmp6sGgm5WiLmub
-      BaNuE2DdJhi1kgBrJcG7UwV2p1Kbdb9NJw2Ku+/bBuKw+ETYFnrHAuhVMIbXJtS7ple8WWmXw43JNt8L
-      rlbDlpvRk7cp2FYRT1KCWMisWjG6U1GYLal5vqRGjYJpBH8xcWTkgbDzJ+WtcQ+EnIRWyIIgF2nU5WCQ
-      T7BKjUBKTVNxy/aRdK3EcZYFAS5alehgro9+YdBVqb8lL3nzlJRqKaReLFZk6Xezfee8TsWz+1f3d0aN
-      +LdX0jjJ7qd58vlTd+qq7FE9jT+3zyc9a5mLZn9x8QvP7NCI/cOvMfYTDdr/jrL/jdnndw/3CWGBtMkA
-      JkInwmQAE61RNiDA1Q7i2/mBqiZbbRzzVzVhH2oAhb3t5mrbIn3kqHsasa+rbbpmpskJxtyH+jlTJZAn
-      P9JBO2VeF8ER/yZ75JTAHkW87GKClpL2tiZsXO+TgFXNRaxeY5LZMyBR+OXEogG7TjHSk2MABbwi6r4U
-      A/el+pxfWVk0Yte7KKjXhtTx3uqQNdk92LEigSYr6h/Tb908O23s5oCIkzTKtDnPKDM8l0VJj8FEtq7H
-      b7OHCvwYpPaxIzwLsW08Ip6HM40PoEEvJ9s9HoigmuS6IidnD8JOxnwdgiN+8pwdTEN2fR9S72WPBc1Z
-      udbVlWCYTyxspk3s+SRmJU/EI7jnz0VS7dMfB+oteOI8o8zPC8LLUzbl2Y5T5qymGxagMfi3S/C5Qfcd
-      0rTKkYAs7J4MyIMRyEMzG/Sc7TQ9+6JdHPHTH3wgOOZnl4/AE5DuG9xemMeCZm5dKoJ1qYioS0WwLhXs
-      ulQE6lLdm2Q0sycONPJLhUPDdm4Ta8MD7iTdqg9lXsuhQl6mpDnRcT7vCmgPjSzIcn2dLr/cXbcbYuRZ
-      sUma1z2lggF5K0K7fIpwpLbJACb9Fhi13+uikJc083ViIBNh/3MLAlybVUFWSQYyHei/zx1x0FcMWhDg
-      0jNTMbdPSDM6HnHKYUgFxM3VsLghx2gxyCeSVL0JrjY9aOilzcZhvxzC604DR35kAfPuQC/RkgFMtD4h
-      sDb09Ndq3Vzo+Quy70QCVv33i/VqRbaeSNQq4zKtkgSs4m3uQzH2PhRvdx8Kyn3Y9sl2+zoTItu8SWxc
-      h8RvKv6N6/BWhK6Ln28uSsIpBB4IOkUjP9swnC1oOfU5coe8aPKulqCUMx823NcXHz6c/676UPs0Hz9h
-      amOo7zidN/6dRVTgxyA9XzYY30R8/mpRpm12P5kvv5Ffk/BAxDn+PQEHQ3yU1sDhDOPt59kt8ff2iOdR
-      hbV9wE2cE4Bx0D+Psc9xtz7n5HinZeWj/EgQI0AKLw4l306EZ6mzR1nVqDNQi0LXyEXWULMQdHiRRFye
-      iqE8FTF5KrA8nc+TxeTPqd7hnFi+fdT2qi2DsrquatqMg0eGrFu+dmt72zGg/pjiNDDIJ15lwdlxtSZt
-      29ufQTvazuVwY1JynUlpW/UuyO1HguI0Ocd4KNfsn+/BtlvP61Oz6gQhrqRQf+IINRmykm8sAPf9Zfaz
-      /5be2JEawjfYUeQf2Vnoso5ZtSwfZ3ecMueygFn9B9dssIB5Prm9ZqtNGHDrXVoqtt3Gbb8+3JF8y/QU
-      ZiPfNA4a9JJvG4gHIuhTq3mJ0aNBLy9ZHH44Ai+BIIkTq9qrQeourb+T7D3m+Gq1tESHJBVrk8ONyXrF
-      lUo04N3u2d7t3vEeOCXuAJa1OktFVbIrZgB3/bvqWbXqhC3ZXA40dlv3ccUm7vpFo46eYJgN0HaKlJMG
-      PeXYZGtLvZ2OjGH68z6ZTCfX+mTTlHAekwciTuLZcBCLmEkjFhdEnKoLM/4MBABFvJS9Az0w4GyX9m/y
-      OltT9rwf8iARKeNyh0OM1T7jXbQCA87kMW2eCCtpER6JIDLCW0cuGHAmYp02DfOyTQESo0kfSS83ASxi
-      puyQ7IGAUz3ypu1RBKCAV72lJSv++olT05kw4uamsMEC5vbVHWZ6mLDt/qheuFpWfxCWQliUbbua3X+Z
-      znWm6sMNaa8OYQI0xjrfE29wD8bd9DbLp3E7ZS2Aj+Lepi64Xomi3m6vT0qfEBOgMWgrngAWNxN7CQ6K
-      evWj/v2eNl7CFWgcas/BQXHvM6NCgXg0Aq8OBwVojF214eauQlEvsadjk7g133Ct+Qa1qk2huUVEs6hZ
-      xJdxMaaMqy/F1AAnPhghujzakmAstRUtv8I0DGCUqPZ1oG3l5gOe/jE1TbiWicrRgZxk1ixorcK79/37
-      nt7tgfo6+m+f8jItCPto+SRknVEbrBOF2ViX2IGQ84F0No/L2cbrbC1z/GMqsl9/oRhNDjSqu5QhVBjk
-      0zlG92kM8lFzuacgGz1HTA4ybm7I9YIFek7Vg+XcMA4KehmJecRQH+8ywbum+4yVST3oOPPHTNB+tCYg
-      C71s9xjq++vuE1MpSdRKzRWLhKzkonOiMBvrEuFyoz9aUFaxWRRmY+b3CcW8vLQ8kpiVcds4LGTmWnHj
-      n7Q1gg6HG5m5ZcC4m5djPYubuelr0rZ9WrLadQODfOTUNTDIR03RnoJs9FQ0OcjIaNct0HNy23UHBb2M
-      xITbdeMD3mWC9XP3GSuTsHb9y/0f03bemfow0SYxa8505pCR88zTAhEnY/7YZRFz9nNf1Q1L3KKIlzpL
-      aoGI8/tmy1JKDjFyn96AAiQGcebP5BAj9RmnBSJO6hNIC0SdjX4bdJ3v86xsmHrLEYwksnJDm8oABSNi
-      tE+31UsWrI30aFrkeqhPSC0QcP5x/YlTGbYY5Jt+Zfk0Bvq+setBg8XMxGdoFog4WXUgsHuO+RH1HEoQ
-      RtzUJ0MWiDi/ZzuWUnKIkVOf+nt1mJ9w9gdAeCwCfY8AGEf8rLrgCNrOr9cRT9w9GHQz7uKvgfVbx8+I
-      d7CBoT5i39gmYas+g5oj1SDo7A6YZkg7ErRSa6+v2Fq4r7wVa1+x9WrdB7sNw7bbwK7qmfNbFQb6iHXU
-      V2RVW/d38vNYkwONrOejLgubeTUGWleQtgqxMc/HrtMC9RknFeHUU6/TtXucMJQ27LmJzwpbwrMwUg5M
-      M0ae+vl5/3GaCNJZwzbl2P64WlxeyFbxG8l2olzb9NuF/pBmO1K+jbUeywIR54bWDpscYqS2GxaIONvd
-      CIndJ58O2WuRJlWa7ZMiXWUFP47twSPqL+4et+fEhgxzDETSlxQZqXMMRGKsVMEcQ5GESERaNMT1sSFP
-      IOLp3LaYZDQlSCxi38HkcCNxJO6giFe80X0jRt83eu+4dbsPoFoFyg1nSUbEkgPnfgOT6KCWLRBdJYms
-      tdTXSZtKD3jGRZRjzuzn/i1itqaBqDE1oRhVE4o3qAnFqJpQvEFNKEbVhMKowbrUjvxllokQ9Q2yz9eN
-      jx/TDOC6EfHfKvBwxOj2Rwy3P6kQxMUVBob6kuvFhOlUKO5tt5zkqlsat8/5Vz0Hr3qViozTEHccZOQ0
-      C0gbQNmb0mBgE2enXxiH/Gp+LSaAzQMRNhl9ZGlwuJE8C+bBoFsdBMCwKgz1cS/1xOJmvRw9oz2qg3gg
-      QvdqENnccbiRlxwmDLhZY2VknEw6rs+EEBfh5GeXQ42MGvUIYk5mG2CwmHnOvdo5drXnzDQ9R9P0nJum
-      53iankek6XkwTc+5aXoeStOmEOo+U0uyaPurBi1wtKROX7jPCzFHKBLruSGiAOIwOiNgP4R+RoVHAta2
-      M05Wthjq41XkBguYd7ns95WPMZ0SXwHE4cwNwfNCamIntiwDjlAkfln2FUCc49QK2X4EA05embFoyK53
-      42mPNqbLDRh3tznDlbc0btfZwZVrGHALbqsm8FZNRLRqItiqCW6rJvBWTbxJqyZGtmp6t2fiEzkLhJyc
-      WQRkDkEPqFn334kErX8zfrH3NFP/mZV6SMoRz9ywMcD3TH4Jw8BQHy8/DBY319laLajlyjt80B/1C0yH
-      HYn1NhHyHhHnDSL43aHjX4nLmQzM99EX+WPvHzHf6kHf5+G9yYO9w9P/nZh6Fgg56SmIvwuktiNu96BJ
-      0iJPSd0Jl/XNG/K7lT3l2NTueGkmkvOLy2S9WifiKdWtFEmOSUbGSvLdXvY9curObKOEoWtY75JVccia
-      qqK9cIRbxkZLLt8mXnIZitjUydMu1ely8eFXfkTbE4j4uN6xo0g2bJZDjnKjN7uKidFbBqKJiMLY8QMR
-      ZEk9v4iKoQ0joryPjvIei/L7BT/XWxYxqyPro2skVzIyVnSNFBKGruEN7ljAE4jIzbuODZsj71jPMhBN
-      RGRW+I49foN/x1qGEVHeR0eB7tj1Uyr/d/Eu2VfF6/n7dx/IUTwDEGUjryTbZO/jbl/QMjZa1A08aASu
-      ojwUBf+3WjRg/xmfcT8Hc+7Uj6K5Txjia2qWr6lhX0bYudvGYB+5AkR7K+0H1ZZ1fRIDfLKB5ORHiyE+
-      Rn60GOzj5EeLwT5OfsD9iPYDTn60mO/rWnWqr8MQHz0/Ogz2MfKjw2AfIz+QvkH7ASM/Osz2rYr0e3ax
-      IvaSesq2MV6BA999U00HsYR0iO8h5mSHAB7aPncdAnreM0TvYRMnmY4cYuQkWMeBRuYl+leoju1WTTxF
-      dmRsk3qK3M4NrV5Jx8IDbMBMew7toL63nXniXbHJBsz0KzZQ3Fut/sX1StT2PqVCV2dPab15SWtSSris
-      Y95/z7gdGpdFzIymwGUBc1S3FjYAUZ6+b7aMEbXLAuaf7TmaMQF8hR1nl9byz0VXrJK0eKzqvHki5QTm
-      gCMxlyAAOOJnLTzwace+IW3PKb/u8h9o/AeP1yM4okQztmkvf2kWld+wAYrCzGsPBt2sfHZZ21yvL5Jf
-      3lEb5p7ybQwV4PmF5nDKHrXc+GVGzx1s9VZl3Z4161q9XnDYbvOfVDUq8mJeXPxClEvCt9CqTaiWlH97
-      f0m9Fkl4lg+0+b2WgCwJ/Vd1lG1TU09qHkovkt+lpMLqsrC5qyfUQ/R6w9FbAjhG+9nxm+KwV1uVZaxo
-      iAqLq48BY7z5BRuMKH8tp7fX02u9bcvDYvKZeMIujAf9hAfoEBx0U1YygnRv/zS7X5B2Vz8BgCMhbLVh
-      QY5LHwO3rg4l4fQlD+ydn6e30/nkJlGniS9IGe+TmHV8drscZiRksgfCTspbSi6HGAk7ILgcYuRmTyB3
-      2hcLKnWE2C1hUBtQhOI8p8UhIobGET+vkKFljFvEAiVML09lOTWJWMUp8Utu/tmKUBx+/olA/i0ePi7n
-      U17xNlncTC8cPYlbGUXEQHvvlz+uR+/grr5rk2q71LTcUAQd4nmaOl03RJFmDNPXydVog/yuTXJ2cXM5
-      yEjYwc2CEBdhwZ7LAUZKsbcgwEVZfGpBgItQvE0GMJH2GbMpx0ZazNkTjmVGTaWZn0LEhZsm45hoyzUN
-      xPFQVp6fAMMxXyzUC8Hp+DvvRDiWrKRaNOFYjpuKUiZePNBx8qfuENzxcyeMQNh1V8Xre3mzPmfj99X2
-      QNC5OxQMoaR622yxeJBfTa5ni2Vyfze7XZLqNQQP+sffwyAcdBPqPpju7V+vR0/nyK9aHK26OwG2g1LZ
-      Hb9vG5Z1WoptVe8omhNku2iVXU+Ylg/j8Q8WR03PD356fiCm5wcvPT9w0vMDnJ4fyOn5wU/P6fLL3TXl
-      5aCe8CyHku7RTG/Sw4Wru9vFcj6RN9MiWT9l4w8igemAnVJLgXDAPb6gAGjAS6idINYwy08+0ZLgRLgW
-      vQsd7XB3DwSdTU2Y8XQ511hU4w9k6AnIkqzyim5SlGujZOcRMBzT5eJqcj9NFvd/yE4dKTN9FPUSyrIL
-      ok7KD/dI2DpLVr/+ojqlhGlbjA9FaN995UdoeSwCNxNngTyc6btC9i4J3VKMxyLwCskMLSMzbhGZhUqI
-      iEwHMZgOlNeUfRKz0l65hVjDfLecXU3lV2llzaIgG6EEGAxkouS8CfWuu4//naxX4oKwpspAHA9tUspA
-      HM+O5ti5PGmb/56wLRvaL9m4v0L+x0YV1XyjVmUIistBUe/qNUbd0bZdP0OgnBBuQbaLdphzTziWklo4
-      W8K2yD9crFcriqZDfE9RUjVF6VsIqw0NxPcI8tUI52qklprEHeJ7mp8N1SMR2yPIOS6AHJdaqqZDfA8x
-      rzrE8NxPb9WX1JvZaVH0y7REsq7K0YPBAY0fb3XIC7X/XbvjsaDGcXDfr6tvkVG9HYb4CPWujcG+mtR6
-      +yRglWmdP5KNmgJs+4OsjPVJZGRlj/pezq+Gf+/jrsl3ZFdLYTZZhv/FMyoStW7y7ZapVajvfUrF0/sL
-      qrKlfFuevr9Yp/vknio8gYBTPTDRG11WZGuP+t7iSQ7xiqwhZ/wJhJ2VrrnqR472yIJmToHvMNCXyypq
-      /FMEDwSdhA67TcG2w04ODLKd4DiPLGius6bOs2dOeh7RoJfy3AfBAb+eO1JtlmyydtXmUNCbPMjhR9rJ
-      clitqe6Wwmyk59IACniz3YbeqLSUbysrZsN3An2nHHZxErLDfJ9o6nUqMsoA0iNBKyMdWwq0qeaBoVMY
-      6CvWacPwKQzx7V9Zvv0r6Cv5mVKGcqXkZUuJ5UtJOEzAwXxfUxXVy/j1pw5m+JZfpnPq8ksLglykxtKi
-      IBuh4jIYyERpIE3IcO2zEh4kjRajBjxK+0okO0SH4/52BTzb3+G+/1lGJTyNcjDUp7oXTKdCe+/99Gsy
-      Wdye66XZY40WhLgoj6Y8EHC+yBKSkYWawmysSzyRtvWvD+9+T2a3n+7ICWmTISv1en0as7OSA8Bt/+q1
-      yQTrym3Stsr/TNbynlul45/Iu5xr/C57eNuKZmsZx1QlT/Kix7dKFmS71JMu9e7M1exe1sM6oSlWALf9
-      +1p2bCm7u1qQ7aKWeb+k67y+/kLbL9oDIedict++WvnH+CERTMP25P7hI2HrZQCFvdykOJKAdXoVkRQm
-      DLq5CXEiAas6MfQ3slFTiO2SZbvEbPLrsz/1y1vUGxRzQJF4CYunKr8UBMvAPOpemw/ca+pzvS6VKz/C
-      sJubyvPQfazaSLJRQYgrmTz8xfIpEHNezW94Tglizvn0nzynBAEnsf8A9xyOf+W3MyaMuaPuAc+AR+GW
-      VxvH/TFJFGiD1OdR7ZArQGPEJFCoTVKf89qlExmwXrKtlyFrZDuFeLCI/IQPp3pcqRksM/Poe3c+4t6N
-      asdcAR4jJhfmQ/UDq107ggEnq30z4ZCb086ZcMjNae9M2HaTJzuAeY52UM5p6mwStHJvFABH/Izi67KI
-      mZ0gcKvWfsht0nwatrOTA2nJ2g/JzZiBYb5Lnu8S9cUkrCMYEYNyCHpQgsbiN8WoBIzFLDCB0hKTEcE8
-      mMfVJ/Oh+oTb5Po0Ymen9jxYW1Gb2Z7CbNQG1iZRK7FptUnUSmxUbTJkTW6n/8M3KxqyEwepyKz56c8R
-      bTc+TjU+j7vnBkaq1pfYd0dorGp9IyqhQu16zHAVNuBRopIp2M6zhqwOGvJe8r2XQW9swo9o/4Gv8foA
-      iCgYM7YvMGpcbnw1ooANlK7YjBrMo3l8fTUfU1/F9RXC43PrO1G5MR+sFXl9B3iMbn/G60Pgo3Tnc1Zf
-      Ah+nO5+z+hQDI3Xrc17fwjUYUeTtfX6R3H+cqtUmo80W5dlor3BZkOeiLHUyEM+jnlh/l3VmWm6SdVaP
-      X4yD8V4EvbkJ0aoZz9SdlUnYQtQDbecHmVV/XH+6SCibV3lgwJksvkzO2WJNu/b9KrtQrymrBe6k1bUI
-      DvqzMspv4rb/t2R1KDdFpmoMUlGzQMSpyl++zdfyfuG5TYEbg3rD/Qbcb7/p24X+048UZFO1Gc94JDEr
-      PzkhAxQlLsKQXZ3vHhfBNbhRKG9794RrUSt7klyQXlD1SdRKOmkVYjFzd5dnG578hOP+56yo9nx/h2N+
-      lRdcecuGzZNyM437Cb7HjugMQMh1FMSHI9CaA58O2wnrpBHc9XctHc3aQa6rK7A0Vwe5ruN+cqebgHOO
-      wQiVG7fdae4NogZEXkzVP1Rv0xMjHDHQJ3g+YfvubmZX3+i3jo2BPsKNYkKgi3JbWJRr++fD5Ib5ay0U
-      9VJ/tQGiTvKvN0nXyt4BDMGDfmpqoPuAAR+TUwXfC6z7/Ovk/l6R9Ms2SMzKSWsTRb3ciw1dKz1tDdKw
-      zu/+ksk+nS/b5kmfOrCY3d3SEiNoGRONkEQBx5hIlIQLSdxYXSrTk80AESc1cU4Y4iMnQc/1xvnk9jrp
-      3iAaazMZxyT/kqWvJFGLOB7CTNjx+45Bv2JCcmgCsrSH+6gzTdT+gepoMMLwaUDjxCNu4GEyjil7pKWg
-      /L5rKNNVkSXbqv6eHEqRbrNkddhuM8pWiYMiJ+Y2l1+kHDJgU46tHViXm2SXNU8VLT0c1jHr19xVWJLz
-      RDm2fTX+uMsT4DpEdthUjGJvgo5TZBkt0RTgOfh5IIJ5IJq0OdB+a4sYnqvR+ybLr1qcvjjCWMZADI/5
-      wIqyY5oH2s7j0ymq0uQs4/8m5+8uflEbOqhzHZL0+ecFwQvQlj25XyyS+8l88pXWUwZQ1Du+9fVA1Elo
-      gX3StqoXjfff1+JcDm8zwjF0EGubV/n4Jy3H7zuGIi/VeV7J+PecHcz26e2SZT24J11XT0E2yp1oQraL
-      OIdjIK5nmx6KhlrneaRtJc4KGYjt2RbpIynpNeA4iLepf2+aJygQDrkA0ICXWsg82HU375J13SS09UgA
-      Cng3ZN0Gsuz253SRhEDXD47rB+TKyKIMsGzTdVPV9ITvOMCY/9jtyToFAS5iJXRkAFNJ9pSAhf7DoF+1
-      F4Jb3nsU8P4g6354Fnn300ZjNgb6ZNucyJaLWiXZrG3ORVLt0x8H0k1wgmxXxMnTCI74yQfMwLRtJ3aZ
-      vH6SSmB6q9pTtq07qFT3oPQCjuRuMr1Pdo9bUr0X0AzFU33C+HBHy1A0/bQvMlbrGBXp4g0iXeCRyqrM
-      uBEUC5vbruEblAZQNByTn0e+ZWS0izeJ5uUU88x0EAbdrBoKPwFLf0o5QPMEeA592YzRhIPCXsY4wEFh
-      r+7z1tWOOImEGvAoTRUXo6lCERrq2Ucg7Ljb8sLJUosErZwMtUjQGpGdkACNwcpMH7f9gj/SEqGRlmCO
-      IgQ6ihCMnr8Ae/6C158VWH+Wsmbs+H3foDvx1DbQAgFnnb6QdZJxTX9nNMvfTpt/2FPOJOsJ20I7M6Un
-      IEtEtxAUgDE4OeqgoJeYqz3V2yirmO01y+pftMP3esKxUI7fOwGOg3wAn005NtoRfAZieS4ufiEo5Ldd
-      mpy+J8YzEdP4iHgecsr0kO368CtF8uFXl6anzZHxTNS06RDPwymDFocbPxbV+rvgelvas9Pz8gRZrveX
-      lHIuv+3S5Lw8MZ6JmJdHxPOQ06aHLNeH8wuCRH7bpRPandIRkIWcyhYHGompbWKgj5zqNug5Ob8Y/rWM
-      Xwr+Sk4dYXGekZVmXnrN7r9MFl8SQot1IgzL/eSP6cXpMPvRKhsDfYSJTJvybKdnTjvxSFSaqOdVe7lm
-      qrtG1hqkYSUt7XJXdbX/pm6XbVO9bTl/WCyT5d0f09vk6mY2vV3qST3CKAw3BKOssse8THIhDmm5ziKC
-      2aIRMetsk+32lJNvR6iCceXfc/H0Fj/WMY2J+iY/13OFIxNqCAQP+gk1BkwH7WoWQNR15D1gWOBo6iT6
-      6TzmbrMNwSjcHDHwoF8VyJgAmg9GYOZ5TwftqmBnu4gArWBEDMrQPigJxlKlb5c1qZrKiixermowbsS9
-      41vgaJJt/4Nbri0BHKM9Vfo0m31MAk40RAXHzX7uszrfZWWTPJ9zolmC4Riyk7JbxcbRkjGxnqt9vY2P
-      pjVwPG6RwEuCuZSJYzZ5OAKzcrNqtYfFdN4erUxKAgcDfePHRxYEugg/1aYM2/LTpVomMnpHiRPgOPYH
-      okMBveOviw8fzkfvHNN+26VVmdineU2zHCnP1j0N0s+auuqGaAYMRpQP737/871670dtQtA+/qccG4vx
-      YAS1v0tMBIsHIxDejbEpzJakRZ4KnrNlUXORj98QAEBRLzd1B1O2/TQR32PkEgf9xLd7fBK0bi5yhlFS
-      oI1SCzsY6JMVGEMnKcxG2bzNJ0FrfsExSgq0ccsmXi7bQsX73ScWNJOWu7gcbky2e65UoqD3Wa9ZLBna
-      jvSs3Yl8ssUQ2Zoy04DxXgRZIZwzCtcRg3zqFaZyk9bqTZomK9W0mKDrIQsYTabdIWP4NYcbk1VVFVyt
-      hgfcCfkO9PhABPo9Y7EB82H9lNZst6Y9u64AGNX6ifOMfaFhVSAu7vlVXU1v1ToKtPHucIOErQ3lXVgP
-      BJ3s+8OGA256hlmsZ24XVDJ6ej3oObtU5xRbEwW8TbJufpKVmgJtnNb+xPlGXTBYP7snbWsyufl8N6e8
-      AGlTkI1ylK5NgbbNgWPbHGAbNfEMDPRR9hNyMNDHyQgsHwjzEjYF2gTvlwrsl+pJ2A3PKEHXuVzOZx8f
-      llPZMh1KYiLaLG4m7ZsKwgPuZPWa3M6uo0J0jhGR7j7+d3Qk6RgRqfnZREeSDjQSuY4wSdRKryssFPW2
-      b0ISJt4xPhyhWv1LtnYxMVpDOArlEFmMRyPk3MvP8asm14omiVplpXQek6cnPhwhKk8NgxNF7380efiL
-      XuQtErMSs9HgMCM1E00Qc5JHKw7qeme3nxjpeaQgGzUdWwYykdOvg1zX/Ia+46dPYlbq7+05zEj+3QYI
-      OL9Ol1/urnm/3mBxM+d6exTwppvNu6TOnqvv2YZsNmHYfa7G79RZLQ+G3epTjlZxgLF9RVEc8iZbkbUm
-      DLmJI6COAUybrMjUq3mMn96jkDffbulGCYEuytbODgb5DvTU8/tx6q+sGxO5I3VvRfZD1UbcZKcJB9wi
-      q/O0YNtbHPPz5oQhHotQpKKhLfDFeCxCKS8iJkLPYxHU22Rpc6iZAU447E/m0z/v/phec+RHFjFzqoiO
-      w42cAamPh/3UYaiPh/3rOm/yNe+2ch2BSPR5B48O2Ikz3i6LmPUaxZolblHEG1cRDNYDersO+mjLoxF7
-      XCUzWMf0dQT1qS1sQKIQV9NDLGBmdMnB3vgubdZPZJWmABunmwz3jxmDwCOF2YjPuy0QcOpRfMQN5vBY
-      hIibwOGxCH0hTovHihfFdgxHIj+yRiVwLObmfgEFEqetfkm74WI8EoFfx4qBOlZE1E4iWDtRNjWwIMRF
-      fRxogZCzYowdFAS4aNsTOBjgo21U4GCO77SLOvnJokVi1oinJYhjRCRqNxVxoJGoo16LRK3kETC2r7/z
-      oT74itOxhhXBOORKyMeDfsakOiRAY3BvgdAdQO3xIOcaOJ+J+FwVY3JVxOWqGMpVEZurAstV3mw3NtPN
-      mpNG5qNv7u7+eLhXtQx5xbbLomb5t8espveRQQMapeubMCbDEAcaSRzohcSjYfu6qVnXrjjYSDlRwOUQ
-      I7UcGxxsfEqF7PblNcd6ZGEz5QhQl4ON1Puux2CfeDo0m+ql5EiPrGPWq4int8v5bEruSTksZv4W0ZnC
-      JGNiUbtTmGRMLOryE0yCx6J23mwU95LvUIfFzayOFcCHIzAaYdCAR8nZ9tA9Qa0bbBT3iox9uSJrgt6o
-      3BSDuSmic1MEc3N2u5zObyc3rAw1YMitHwKXTf1KN5/QoJddebqGwSisatM1DEZhVZiuAYpCfTB+hCDX
-      8fk2L2NNGrTTH2obHGjktBFI69CmM/2RkwtDbl6bg7U27WJF4kMmi0Ss3Iw/oZhXb9HPvqNdw2AU1h3t
-      GrAoDfMZLiQYisH+IQ36JFd/RY0L6GJFYbakKjY8oyIhK6fRgtsqVs8D6XNUZVbkJeNm7kDISR/89xjq
-      Ixzx45MhK/XZmwtDblYfzu+9ydI+vWrfjVZv0zWyTqJN2kACOIauSdUfOP4TjLrpa8AdFjbnm5/cORrQ
-      AEeps6bOs+csMhSgGYhHfwIOGuAo7VMeRgcB4J0I9+qce3If4URBNmqdd4RcV3uE7e3dNaea8mjX/vCR
-      98t7DjYSN0EwMNT3rt3enqnt6JCdfLhGQAHHyVmJkiNpQi5hJwz2CV6eCSzPRFSeCTzP5vd3iyl1VxiT
-      Q4yM3UpcFjGT36g0wYCTvlbCo0N2EacXYb9+pLHh6ls6bI+6/pMgEIPeFnl0wB6ROMGUaeqD4F+1phE7
-      vQo5cY5R7QrFey5pkZiVWBMbHGak1sYmCDj1qyNp09Rk6YkMWTnjZ0gwFIM6foYEQzGoE3uQAI7Bfb3A
-      xwf95GWzsAKI077WwziWDDcAUbqpR1aJNVjITJ+07DHIR2zhOwYwnZKelXkWDdhZFR9S50W8BeLjsP88
-      yXZpXnDcHQp7eUXqCAac3CrQ4QcicCpAhw9FoHdAfBzxR9R9No745WCJUxn1KOLlv4kAGrAo7XwIvQMO
-      CZAYnPXEDguYGV0fsNfD6fDAfR36vMaJwmzUyVcTRJ3bPdO5hVoPwb8HROgeELGlUwyXThFROkWwdJJX
-      ux8hxEVe7W6CgJOxorzHPJ9+95H/jjkkwGOQ36Z0WMTMfJvbxzE/ub924hAjo2fVg4gz5m1kxBGKpDYs
-      WKdq27dr6ttMAU8oYrvq9PawW2U1P55pwaOxCxP87q/zKa/jBymG49C7f5BiOA5rgXvAMxCR0+0EDANR
-      qO8HAzwSIeddfI5dMb0vdOIQo2ol3+Am9zWBeNG3uCtxYi1mn+l17xECXORZ9SMEu3Yc1w5wEUtXiwAe
-      aqnqGNe0vJtP9VlsnOcbHo3a6TlroahXtxvkDUoAfiDCU5qXUSGUYCDGoa7VyShr4msUuGZcPMaWCEFT
-      OCr9kR8kGIyhU4DYuUctA9GqIl+/Jg2/hLuacDzRVHVUJC0Ix5DNr3qQQ9wxC5OEYp3H3lvnw/fWeXQZ
-      Px9RtmN/yPDv6O/tqArP0gTjZXVdRaRayw9HkMO8ffMUG6e1hKP9pL8zABqGosiGtl2tGhfqpBmIt5dV
-      R950VUhUSMuERiW/mmajqJfcpzFJ1Lo/1PtKqN3an2T3k3vhjgWNppemyMZXMOOc+HCEmHZUDLej+qVm
-      fi1zxMP+iPpSDNaXxsYiETE6w0AUfu114oMRYuphMVgPi+iaUYyoGdV3tkX6GHFftHwwQneXRsToDMEo
-      Tb6LCaHwsJ+8BgfggxHaKedkvYqIcnKgkbr+nzpfZ/2dGclyoJH+zuqKGUChoFfNbDPrwCOKe1mDvI5E
-      rUVVfWcN4XsYdDNH7+jI3dhrnVMdmDju57aQA6PMdsgh85Z55R0ccPP6DicWM3PX+0MCNIb6bczCbeK4
-      X682ighw5Aci6OHeJipIqxiI00+/RsXqNXg89vyeQaP2dmsjbq50dNDOHsLbAjRGW/3F3NmWYjAO+y43
-      DWgUxpNoFx5w8/oOj4P9hqJKVVvUlmZOEtkCMAZvnImNMfVmidzWpocxd0ydKobqVBFZp4rBOlXE16li
-      TJ0q3qZOFWPrVBFVp4qBOtXcFnOfNk+CGcNyBCLxRrDh0WvMiC882hNRLY4YaHFEbIsjhlscEd/iiDEt
-      johuccSIFidu5D006o4ZEYdHwyKmpRThljJ2lD08wmbsh2qCjnM5f1iQT1PvKdDGqR8tErSSn+z3GOqj
-      L4Z0WMzMeI/NYVEzfZ2Nw6Jmeq3tsKiZfh87LGimvll2ojAba+bYox37nxPG+SxHCHARH2X8Ce0Wpf5I
-      7Q13jGuazmefviX3k/nka3tuEuNxFCYZjNWkK+JekYhjINJ58lQRCzCsCMVRlV/NuAkxSSgWvUC6dMhO
-      rqo9eshOr7hhxWCcfZbVbxDrqBmIx6jcYcVQHHrXH1YMxYkszVjLYn2J84AXEoRiMKbYAT4UgVwdO3DI
-      rWYb+HJFD9kZL/ohjsFIcTXxSTEYJ99HRsn3I2IkqVhHx1GSwVhxtdhJMRhHN915JiJjHTUD8WJrMjGm
-      JhPxNZkYU5OpL6my+QaxTpqheJwBPCYZikV+gA4aBqOQBxuwIhRHdxpZA11c48RjvwEWePNLf1Rn+jU+
-      xia3Pg75deKx9Sbt28lvAcHvqend/+nd1B4DfeRmtsccn17jxD+51cdBP2MmyQQ9pwqXfidOe/QY6Fun
-      DNs6BV30PorBgUZyX6THQB+xz3GEEBe5b2GCsJP+LCfwBCduF5KhHUi6zxnNm0WCVnoTY3CukbhVtL9L
-      tPzLaXE3uYl1YcDNcgIu5lvB6NvAjF1gwB1gqG8T+28R6xqCPqnSY45P/tfGON0llf9inBKDWpBonGVC
-      DuuaqSkCpIWeP0kPzVMlx+ivnMdzoCEcRVYn1Pl70BCOwshT0ABFYb53Hn7fvJ03q5rJtuHkwZFErB+z
-      LfUdJxuFvO2eGMkqb0TDuGQLh/zsF2SH3n2P2J8puDdT+2G3lwe3nNs8FKFZCXUJafFIt/csZD7kG0aZ
-      VpRv40xcobtT6Q+qtdjTdYrybYmx+SnVabKA+bhCRC8TSussJfs9w1AU6nFZkGBEjCQrn6PjKMlQLPI5
-      ZaBhTJT4n3S0BKIde9Ix2WQ4gEict03wt++i3rkbeNOOs98IvM9IxP4iwX1FIvYTCe4jErt/yPC+Ifz9
-      QkL7hHD3B8H3BTltWLfJNrqdO4j0MePIHQUWR+/7SJ/6BXggAvcc7cfgGdrqU37ShFKE28kM9DH5XcxQ
-      D1OvsSyykuzsOMhI3wEO3QHxMWYPl8fw3i1xOysO7aoYtaPiwG6K3J0U8V0U1bYv7EK7C5TaHb/Y7vBy
-      u1PTM0m6+RfNecIcnzfDQJ7VAg1wFJWfXP+RDZjJxzC58ICbfCgTJHBj0BpSb62DrDfyDf15SI+BPvLz
-      kB5zfPrljuMbDfSOt4+j/gg36uVfMny11KUi/uoQNdyUKU3fZNUEHec+rUWWbOtql6wO2y2xFvRo197u
-      k6On0WliA4SdRfacFceZpE3GsTuKUBz1OaPvizjgSPpzYzcjTiTXMRiJvuwTcQxF+nFIi3yby2Y4Llrv
-      gSOqPZnoM9guHHDrq9A5yo7QK4bisJbloJahaAfZiL9RSEsViNveGuw7y3W4kchVJVhHcvahRvag5h79
-      h5/6x9rRGtnNups3Zzyis0jH2q090YucSVITdJztyjZOz90iESuj526jkLcfNqXFY0WX23w4wnNaHLKY
-      EFrgx2DNBuI7zoiIOQ4RnOMQ3NkIgc9GCPZshAjMRjB3j0d3jo/a/3Vg39eoHekHdqPn7kSP70JP3oEe
-      2H2etfM8sut8f3dtDsSBsI2iXnp757Cu2cgu8uDdhUNu8vDdo4fs5AE8aPCi7PdVrXY8Os3lEmN4vBOB
-      NeODzPcc/0ztyhica6yS48EINGPPuUa9kJTeVTA4x8hYLwmulGS8ewy+cXx8T5i6WZXB4cZud03RyJv5
-      kau3JHastOGdZ2dyuJHxvA3Aw37iczcAD/uJZ9gBuOdnnshmk56VcyKXgaE+XiYGz+JyPqdnYfAcLvNz
-      8kDUg23383vO+vee8my81ZgW6DkZz817CrMxioEHh9zEQuDBITfnGTpsQKOQC5rL9ub0Ik8+T2+n88lN
-      cjv5Oh1rdTnbOLuX8Hy6WFB0JwhxJbdXLJ3kDOMqT5pMtvardJMcyhe1lrXJdrIjldaj2+egJBzrpa7K
-      R9lBeMwFYXA5bAKirotqJUdhSX3+jhzHYIPm8wjzedB8EWG+CJrfR5jfB82/RJh/CZo/RJg/hMyXfPFl
-      yPs73/t7yJv+5IvTnyHzas83r/ZBc8Q1r4LXvI4wr4PmTc43b/KgOeKaN8FrFhHXLELX/HO341ehCg67
-      z2Pc5wPuqAs/H7ryuEsfuvaLKPvFgP19lP39gP2XKPsvA/YPUfYPYXtUsg+kelSiD6R5VJIPpHhUgg+k
-      968x7l/D7t9i3L+F3Zcx7suw+/cYN9SD0ANt2W1ud0va5HW2bo6rZ8mxQjIgtt5xIi6irwDiNHW6U8+2
-      y4zs71HA24046qw51CVZbdG4XTTp+ElNEA65qz1fXZm9u0ycX1w+rncif07kP5Lvo9c6AGjQm2TlOvl5
-      HqHvDEiUTbZmuSWHGLP1SodcFdX4JVu4AYsiP9+Jx+TnL7wQJ3zIfxnnv0T83zdbllhylvHiw6/ccuii
-      QS+9HCIGJAqtHFocYuSWQ8SAReGUQwgf8l/G+S8RP60cWpxlTNZNrdsnwioEB7N9Ty/JerVWP6B+3TcU
-      pU361qZ+f3H8tM1bQdUDCi+OLJmMK+8oz9aVRYbRIH0rz4jY2j212kQhFgOfBu3HJOfZDdq2lxW/tLks
-      ZI4scagEiMUodSYHGLlpgqdHRDmBeCQCs6xAvBWhqwCf9B5ev5IOR4Rp3B4lH3LLjv7r8/gnVBgPReg+
-      Sp6quiQ830B4K0KZJ/JLjGJug5CTXtBt0HCK8jzZVEm6Gb1/l4E4HtWEU1ajWxDgIpUpEwJcdUY6ntjl
-      AKNIn+k6BTmux0yWnLTI/842evFRUyXjD3XHDV4UdXxIla8zWWUUclw+/txGjAcibPOs2CT7hu4+kY41
-      F+1iPco22h7oOptsl6yr3Ur+hV5gPdqx19lWP7RWN7CeddGjc8o5gAMaLJ5qCqoy40XpYMctIkuNGCw1
-      zeu+W4CdpDLHKpljGS0GaHCiHJo1896yyN66yrJDsqs2srpR63HVBdSUTcgw3oiQV918nZAdKOpZqzBt
-      27ebRDxVh0LPdY1fTQCgtlftzifLq1rsqZKtuwD1p3SzIf2CsMmOqj6kp1FP+Ta1jl3+N1XXYYavTFK1
-      XdBhJauNUjSkcgKwtnmzSV6qevx+QyZjmdbV/pWs6iHLtZFdI85vtTjLmP3cy3wnqFrAcmzzRsgbjvwj
-      Lc42qrdBd1XZPFa7jHALeWTImohdWhR8d8tbER7T5imrPxCcHWFZZJLUafmYkRPUBm2nUDuZ6YaDbHVQ
-      11tnRdrkz1nxqnoGpHIJ0Jb9X+m6WuUEYQtYjmK9Y90zFmcbMyGS5iktzcIwp6hBARKDml0OaVl3eVHo
-      JTCyk0UaBkBswCx7CqTz+FCBE6PM5S2XvOSb8Ru/u5xtrDbtGcuM8uGxoJmaexbnGWXlm6xS2a25YF8y
-      pADjqKJJriJ92HN3PbN37e3OD4N6sIjsJPN4NAK1/vNY1CyydZ01UQFMhRenEE/5Vh0ozUwjj0ciRAYI
-      +HeHIqZxxxReHG5/02NBM6e+OHGe8XD+K/taLdYxy1utfEfyacK2yMRm1ZAm5xnVBEL6C1HXQrDrkuO6
-      BFyMXDA5z6jSlChTCOhhdFxd1POSb8Aj45k4JcQvHZUsM6V+IVl1O6vVc14dhOx1ygzbV0L2OAgRBl12
-      5FLPc7DGMx5rmffVCy3XWsBy1GrczxtvuKjv7doc/R2q2GRtc7Y5rDOZNGuSs6cwmxpA7YuUqz3hjl/k
-      fzPS1sBsX9fSkoUmBxiP6a3/QfZaNGTnXS5wtWKdNg2t1B8R26MnTsnXZWKOr2GPUDzWM4tGjofWjKu1
-      Uc/LEQKmH/Xlz0TPEJcppdK3QddJb817CHZdclyXgIvemlucZ6S2lifGM5Fz9Mi4pp/sLP2J5imjhwv3
-      bq02kZx6AG3ZD9xJgQM+I3DgDhwO+KjhhTx9++LN31bqDX0h1H6De3UkVbHVj8RGOxG+j7C+yJPJ4vY8
-      +ThbJoulEoyVAyjgnd0up5+nc7K04wDj3cf/nl4tycIWM3yrlR6qqBnOcvTKSZvybYe1uEhWGVXXYYCv
-      2b5nCTsONF4ybJe2ST2+Vn9NCHssu5xp1Oe3kfPCpHwbOS8sDPCR88LmQOMlw2bmxVMq/3ehtwB8PX//
-      7kNS7Qk5AtIhu8jGtzcwbdjVspxKr9FZF2pcmJVq4cLoGhPj+wgbdfNfXakXzK+ni6v57H45u7sd64dp
-      x86rOzehurP/8Os9V3skIevd3c10ckt3thxgnN4+fJ3OJ8vpNVnao4C327xg9r/T6+Vs/L4HGI9HYKay
-      RQP22eQD03wiISutRd2gLerpk9uHmxuyTkGAi9Y6b7DWuf/gajll310mDLjv5d+Xk4839JJ1IkNW5kU7
-      PBBhMf3nw/T2appMbr+R9SYMupdM7RIxLn89Z6bEiYSsnAoBqQWW3+4ZLgkBrofb2Z/T+YJdpzg8FGF5
-      xfrxHQcaP11yL/eEAt4/Z4sZ/z6waMf+sPwiweU3Wal9uusaaVIASIDF+GP6bXbNs2vU8R6a6r49kOmP
-      8WvffdK2fpwsZlfJ1d2tTK6JrD9IqeHBtvtqOl/OPs2uZCt9f3czu5pNSXYAd/zzm+R6tlgm93fUK3dQ
-      23v9ZZ/W6U5QhEcGNiWEpXEu5xhnc9ne3c2/0W8OB3W9i/ubybfl9K8lzXnCPF+XuERdR2E20kZWAOp4
-      FxPeLWWBASc541045B6/tTfE+ubDqsjXjIQ4cp6ReNahTWE2RpIaJGolJ2YP+s7F7DPVJhHPw6iGjpDt
-      ml4xruoEua57FSFrCCc2uJxnZN2EJocbqeXFZQNmWplxUNfLuFlOEOKi/3T0Tuk/ov5o7D6ZXs/uJ/Pl
-      N2qFbnKO8a/l9PZ6eq16T8nDYvKZ5vVo287ZSXGD7qTofrLgKp2+y2yxeJAEs/31adt+O10urib302Rx
-      /8fkimK2Sdw640pnjvNuOZMdyOknku8I2a675ZfpnJrtJ8h23f9xtRi/91VPQBbq7d1ToI12Y58g3/Ub
-      1fMb4OD8uN/g33bJbwwAPOynJ+JloFXQn6uJnT91raTGnGS9jQ/6WSnkK4bjMFLKM0BRWNePXDHnGr2r
-      UmPXb+SsO1GQ7Z8Pkxue8Ug61vndX9/0gLtNWd0WLoiPPFAJFKu9Grq+5RwjueME9Zp4XSasv8TqLCE9
-      JV7vGOsbR1SGoXqQXQUGaj/OgBQZjc65I/05PtKfx4z05+GR/jxipD8PjvTnzJH+HB3pm59wksFkA2Z6
-      Ihio503uF4tEDiQmXxdErUECVnJdNEdmPObsGY95YMZjzp3xmOMzHg8L2dPVXWeKsKdsm9rTnuJR3/cN
-      yeTm892c6mkpzLbg6RaQb7mczz4+LKd05ZGErA9/0X0PfwEm3YpzdEcQcspeAd0nIcg1v6Gr5jewidyv
-      tkDESbxnTQ4x0u5XAwN8rA6eTYasC74WuluoY+8ThLiS6e1y/o1lbFHAS6/4DQzwEU7OMhnYxCvhRxBx
-      ckp4xyFGRglvMdD3590ftIVFJgcYidPnRwYw/Tmh116SAUycPIDTn5H2VrqLNNF7wOyy8S9JWJDt0gd8
-      J3v6kwaA7c3ZOvn8qXuROd2MXjDoYLBvsyo4PonBvm1WZLvuCPXXZvyxyyFHKNLuUPBDSDjkFj9qvlvC
-      IXdTxabP0QBHeayrwz6Rf87Hn0SJ8aEIlJ0bYDpk15tLHerxu7AFFHAcdQXJvs7U65KcICYPR2CWULRs
-      qqW/atcEplSzIXOzfuKrJYy7I5LZwAN+PXKO+wmmw4skb4ZGnaW5rjaZepOvSGu1Hw31JsY0XjyR7/aF
-      Pmw2+Zmsq6re5GXaUHMesWDRImtwxBKOxqwNQQcWKaJGBAzhKI/MeguWhGMxamCPD0cQb/FrxNCv0XuD
-      MH9Jy6JmkaSqplY517wyI1iOQKSqjEkrQ4DF0Nsf6l3ZeCF6PhyBX656PhxBFQl518ZlDKgKxhVJ9uOQ
-      FhHhOoMVJd2q/+p2/UpLcgyQhyK0b33TzS0HGWXCHcPStQZsu6nDKpOxTKv8sTzo+l1X9ASfQyLWtgVm
-      aVvU8kY01sEWWnV9Dk2WvNxOPlGcBmb52kaTNpw8MYCJWt4NCrCxuh/BPkf7YZk9koWSgUyynlZb9Sa7
-      VHynO00asJNvchODfIcVXXZYASbVzdLln+w7kYiVldtgr0/1nMwbSe0aTNWjjsFI5PoEl9ixdD+qzF4o
-      6iNjmZ5S8aRSTvczkv37y1+Snzu132/64fwiEeLlkGzqdNu8+40QarwUvJZuHORy/OsIC61rYE4CoGP/
-      UyMuL6NtJglWHx5wkwe8mMKKs/+evVLb7xNjm3QPTVfLh1KlVZ0JkVHaHcQARNE7d1HvPxcNeqlzLyA/
-      FIGWn7AgHINe2jHFQBw9nxIVRhvGRIlPOHT25zjKILbKJgb6muMN2Nf+guGHNEA8Ritrg7azzX9Gqlig
-      5VS7rVW6e6R7R+RbGeStCF1O0zq+PQS5dCeWejwAgkN+VmfYY1EzfTNAVADFyMvnd1ExHAEYQ5BO3/BA
-      yGnvwEpX2zwUgTYY6SHI1e79R9e1HGQk39YWBxpJg5AeglyMqswhEWtMliO7YyJfUAWbX2ugKjtuOy8m
-      0m03dUUJ5LK2uZ0Pi7/JQ55AxDdJynFG8yrUk3ohR7HJS948qXZmnSXbqk6+l9VLmaSleMlq0qZlBKV5
-      He1TpL8vPvyapM8/L057QRJGSqgCiUPd6ReEETepKrQ5xCj7QXFXbAoCMdSehVExjgIkRtsBI3VXIHrI
-      Th6nBiTBWJvqQDjnCxUgMY5l+AMrwIkesP8WZcfur6iSBJSizcWH/9/aGfS4iYNh+L7/ZG8dZkfdXld7
-      qVRppaTqFRFwEpQEKCZppr9+bScBPvsz4f2Y22jgeRwc7IANr99evggG4n0wdOKDAz44OG2g2c4N2phe
-      aK6PQJzLRaThNodxPrsSJ66zFGfTWqtXXOcwz2c+bwfX3APiXHjNDRjng2uupzgbXnMDRn1u9A6suAfD
-      mOBqGyjGhlZaDzEuuMoGarCVSbYgW5CnPbssW49BGS+YIudzjBFLfvMwxocl43jY2JdLUxoZlPHCNZlH
-      a7JYdEYVT86oQl4PxVQ9FMK0ypDkrFhapc8xRkmLKqZaVLEorTLGx0sQ1nIkrbLfDqdVhiRnRVtHMdU6
-      0LRKAjEutM8qYn1WIU+rZGHGDadVhuSUVfiho2mV/R6StEoWZt3fhdrvESOcVhmSnFXSIUR6ASStkkCM
-      S5hWGeO5ErC0Sp9jjWhaJYMyXlFaJU979iVplVFBrAworZJBqVecK8nC1L0gVzKCe35ZriSDUi+aKzlm
-      eBPy/pfPeUZZriSD+l44V9LDAh+Ya0WpmA16x5RBPa8kbSIAJ5zwFx9Pmwg3z38VkGNDM5o24XOBEXzZ
-      llIxm6BK2ZQFbxtcmVzKwmMT8ArqCAk8gm4ozJW0/4ZzJQnku/BcSZ8LjKJGyOdK+lvQ8yWeKxlsxc6Z
-      aK7kbaOgsTC5kuTf+KFHW4okV9LnPKMgV9LnPKM4V5KnqV2SK+lzceNaqvSuXeS5kjxN7bJcyZCMW79K
-      pV89J5orSSDqgnMlCURdWK7kQHAWtHlzuZKj/2MNm8mVfPz7M+r5zDgkB/eZP7ZRcuPXaltLzIzieTl4
-      hYaGyVIWHsnTo1h2BE8/fVUWS4/grnhezrIjuRmYUmSZnxH8qV9UW1OZn7GdBLU1kfk57CP6/JFPLPmM
-      waeCMz8pxdnQzM+Q9KxLMz8nJVxZWOanz3lG+KKWu6KVXc7GrmVFF7KRq1jZnUvsvmVB1z7Vq4s79Im+
-      XDJYEBkpWElHYVbxUZjVklGY1fQozGrBKMxqchRmJRyFWUVHYaSZnxw7YcYrgc38vG8UZH6GJGOF+6JV
-      ZDRqJR6NWk2MRq2ko1Gr+GgUnvlJKWpDMj8f+4cGLPOTUjHbWqZbcz408zMkOev8kM4xw5jQzM8A5JxA
-      5ieBONfqG65afeNN8HV1JPOTbALbLJ/5SbZg7ZXN/CQbuo0WCQ3HGEWXjLEU0XDbWq7l2h860sKkiJJ/
-      YymiDMp48Z8SNkW03wCkiI4Z3iRrM2GKKNkkaTNBiijZImgzforoaAOUIupzjBGcLAlTRPv/AimiY4Yx
-      Sb4Dvv4Fdc/Wu6SfCvqoVok7Pg/lvfasEXrvKO8VOj1fbSeG8It+go19Wv4UpJ56CjLYmIIPq0UETBnw
-      M4U6+kyhXvLcnp5+bq+TPWPYxZ4xvMif371MPb97Ec5dXaJzVxfp3NUlNnd1+Kduy2pn9jY3M+ufbff9
-      1+y+jmOnzd9UtURu8JH/v0ZVdrPKdF2tO7v3v1mXzS4gwsdK+JEdz/PfAubYaTNSNzw++I/qoo7uPbmq
-      Lma/Akcp32b+lOh6bPCdir/SzbHOD2lh6tu+mqhmJy9w7Nj8dt+a6ZPIzvNDCfVtoUr0d8PDBl9zyPVL
-      kpadarOurCudZnmumi4DXl2ccgQl2dfidvNPNUoFtmajUlXl7XuDxThGcOr/7M5F+8KyKtyXgdgD2Hc3
-      WatVulcZcH6EJLX+7Y6oUO6IECkBR87TpqsPqkrVtXkxZ6ZpS7OtIRrz5sdSVZ37jvEAkBmqWLnmhLJn
-      rLK7y4obG+KldOneveZu32w3nby0KE8TK6/U+qzaD6lNVhUrtzXno6wYS8astgHJrJaMWc/VgnP5DvPu
-      RN5KknTS+2GtJEFaSbK4lSQzWknyMa0kmdtKko9rJQnSShJxK0kmWkkibiXJRCtJlrSShGkltbn2eE/z
-      LN+r21UZ9JPK0jF7q5RMbMCIU6tOpDRc3JiesqZBTvYIH5TgLh0F1dBzvBGI5PSwwGcvyV0OMO4co7xX
-      cOQ9xxtPSOBeABLne7r6iayVMUIGj41/s/3cwTQ0l1u0OW+3yt5Dmgtae+E9u9k+N41Klawi1PKrCLXD
-      SkC3LELg94Vjqdn8mdk4BPBamEF5b3ObzE87U33a1N5JUkIg4ctykUlt9ktSxIONmX8rmfW3okY4J4VA
-      xPU7ffmU/JXusm6v2jeX2ARIGZqz27wjmflBctbKfIdJa274ZGqCc36zLbE7Cf0E5/w6z7pOXukEZ/0/
-      W6n6Tg5WnZSiUWOfY4ySUWMWHrn32Yt40ImFidsGIy2wczjx2zzpBX4OH/nNv5VqoJU+xoxnOqr5axH0
-      AONIm66FPRairnODSM4NobfA9fd9d8oDF0L33QlfVhpYqqYHqEOnum47hRxIzxATcKl429un0+p8PGIK
-      h1DP/BUBbnsTuqmR88Hs7dPod/pAWI+5VxOoDEVt5/kLTd13Jzxwb3Xb26fd3cD2XOWYpseob19uoc9j
-      96eGGmozdnfCX+yMCiBw+xMDkhF8333gO/sVu3vs+et9jJnBdHn8KOJzmwxKvZK5TZ+LG9dS5TruBBob
-      g468r2lmr5zL2T3qQFDLsUMMx47Qm7yuNMC7/YkhN7e2iMHtTw3t0ebXFsDyQ5QKbEDvPhCBpXUzo6Do
-      BvmuArPQb9hclJjrLfNvQNIzxKSuXXo4A5obQBzmt0Pvle7ADzTGiK8sGkBj9qZ0ta0R3Ozu8ftyY1MS
-      q3foY4ww4rMN9KyzHXIm9wwxVdnJLpBQ6a7N7CJugNBHqVenZfaWHkuN9BsjyrPlwLVlDxBHnevGzjab
-      MwT5DsZY6KtqN7aE+u4Y8TV5CWjM3pS+D/eKvskQ5tz3AWSB+EESqwYblQ5alYZ/2XTwy1Y37VYwGedz
-      rHHRNNwzD1uiZAIugrP+RVNhzzxsicgkmIexPmT6y8NYHzjxFZIja5Mpneab/PGcyWypDwbOrn1N+qdX
-      3OiKBuWMwS8FHD8nkO8S1UDk6O3d270YqF1wMOd+1IrIPYIH91UYUn6NZpTft+wUEppPIM5l265ruugy
-      ExMKrpzmpXmxK1E0CV7AwE6aXxeYX1nzq1v3z06/Cip8THP22+ocNsUbdw/stBla1C0qeFKGPmXHI7rw
-      2nMTW+r8lXYIxLm6GvrpC8DACU+KXaNrB9y36Bxc/8jnRsa3T19+vLqnFN340a2H0e455Nn2CQctKS3K
-      nb2Fc/OR2XFXt2W3PyHl8Aa+lItqy+079ERoBPf8TWsX5nBzl1qnWE5bVOCV4Sa3u6vrhTRmpyjjtYXa
-      Pqi7wt4BpV47MpSUadkgP0IeFxhvvx6muL26gtIxGnhvT86oa6cqXQLDVxE88Jsy4QW7GDTwHuv6oM0t
-      9EGlhbmftnfpoJ4xBKXcbv6BLptif/7xP+zmWSIhogQA
+      6vX0j2RV1Xn5KESR7Otsm/9MnrJ0k9X/KZ7OqvLso/50sbg5W1e7Xd78v7PfP6zeZ5vz1bvz7UW2Pd/8
+      drHNNhe/v8s2v/2+zeTfs9826Xb97t/+7b/+6+yq2r/W+eNTc/Z/1/9xdvHu/PIfZ5+r6rHIzmbl+j/l
+      V9S37rN6lwuRy3hNdXYQ2T9ktP3rP8521Sbfyv+flpv/quqzTS6aOl8dmuysecrFmai2zUtaZ2db+WFa
+      virX/lDvK5GdveSN/AG1/v/VoTnbZtmZRJ6yOlO/vk5LmRD/ONvX1XO+kUnSPKWN/D/ZWbqqnjNlWp+u
+      vayafJ2pq2jj7vvrPX6032dpfZaXZ2lRKDLPxPHXLb9MzxZ3n5b/M5lPz2aLs/v53Z+z6+n12f+ZLOS/
+      /8/Z5PZaf2nysPxyNz+7ni2ubiazr4uzyc3NmaTmk9vlbLpQrv+ZLb+czaefJ3OJ3ElK+nr37dXNw/Xs
+      9rMGZ1/vb2YySi84u/ukHF+n86sv8i+Tj7Ob2fKbDv9ptrydLhb/KR1nt3dn0z+nt8uzxRflMa7s4/Ts
+      Zjb5eDM9+yT/Nbn9pnSL++nVbHLzD3nd8+nV8h9Scfwv+aWru9vF9J8PUie/c3Y9+Tr5rC5E08d/6h/2
+      ZbJc3Mm4c/nzFg83S/UzPs3vvp7d3C3UlZ89LKYyxmQ5UbRMQ3nJi39IbiovcK6ueyL/d7Wc3d0qnwRk
+      6OV8oq7jdvr5ZvZ5ens1VeydBpZ3c/ndh0XH/ONsMp8tVNC7h6Wi75RTF+G729up/k6b+io95LXoq5jO
+      ZUJ8nWjxJzs3/lOX/493c+mUt08yub5O7ufTT7O/zvapaDJx1rxUZ7LolU2+zbNayMIjC39VZjITGlXE
+      ZKHeCfUHJcobdbeqEldtz3bpuq7Osp/7tNSFUP4vb8RZWj8edtInzlaZhDMdSN69//lv/76Rd3aZgZfz
+      f9N/nK3+A/womcmfPm+/EHSYXzxLz/79388S9X9W/9ZTs7tkm8haBr6G/o/tH/7RA/9hOUTWUC0d0nuu
+      lzeLZF3kMqmSXSarh81YnU86VoYO9Iisfs5qjs4iHauqC5PVYbuVxY3jBng7wvN5csFPWZ8G7Ewt6mOn
+      tE979piUCKfDoyzTTb7LVMtG8xqkZ32SLVyRMcU27LlZiYD8+pg8C+eYqivyMm/ytDj+kmRz6GpeaiBc
+      1cedzudJUaWbRBlU70Z2xcYGgtjefHc/vVUfqGugVJku1xvvp1+TOuviLWR3QbWJI60QC5hXeRVld3g7
+      wkstW1Gu3oMhd8Tlg4I+hvrj1exe9lySTSbWdb6nFEmYBu2qfkgPsp4v8w1Db+Kof6V6Kzy3QlHvOt/L
+      /n3ElfcCNMYmf8xEExGjF6Ax2O6A8/vPpEx3GVPc0UE7+6pbGHXv0p+JrLIFr7w7BjxKXsZG6Q1olIgs
+      CKb/vt5GZEBHB+xVU62rIomIcDKgUertOiZ9jjjqf06LA1euWdwcVW5CZSYXSSrbNYa5IzHrqqjW37v6
+      jmc3DWAU0cgeYVpvuJlq8U6Eu6/3SbrZJOtqt68zPRVD7A4OaIB42zrLgG8KckRMBMSU5eMdPf0sEra+
+      yQ9BPEjEfMMKkG8QHzdZoFRZ/qXKwbtk/ZTKWnyd1Q3J7OOg/zzOfz7k159YOZIWj4xAoAeJ2A5Tryas
+      MEcYdmc/mzqNSzLPAUcS7c/kBOhQ37t+ymT9uK/zZzXL/j17pdo9ARCj7a/K3/ZYV4c9OYKNA/4iS2sj
+      9QQ5givAYrj5xIzkabB4u2qT8UIoErNWelzFvPYO9t1Zma6KLKnWYq8axX0hB/rUEJADjSTyxzLragE1
+      dSGB3V4wQ8IyNHZTCJV/ZZmRu5uYxI+1LQ7i6Xjrkn+YTQN22b6TnZLxTboRVymXb/O1rAWoVpfHIqj7
+      hedWZMjKu5ldHomwT+t0x3JrErO2NS6jxnZw0N/eCKJRz2foeoNG7LpKFyx1iyLeY1OdFLloWHrLAEeR
+      f0oPhRwupkK8yDpjxQnkSUbGSg4iqzdpk75J0JMNjp79TLihOhT1ltmLbNI32U+m/MRjESJbalACx8rL
+      bZWs06JYpevvnDiWAI4hb9SieoyK4ijgOGoSSt+93BvIEuAx9FQLa0oCkyCxZNbFx3IlSCxGb+3IwUZm
+      T81AYe+PQ64eNz8dmk31wkoS2wBH0c860ifqzJBHw/auZyPLsxyCsNPet8DRiE8bARTxFkLWMvI76+/t
+      LcrKbN8CR5PFN9++RtUijiIYZ5Ptm6eIIJoPRuBmu4H7fv20svtGUa1T1j0ISvxYZSZHHc1un8wX5MkJ
+      k4XML3Thi++ps131nHEnH2zat6sPknS9ljlNVRto0Js8VtUmQq75cIQ6K7PHqskZgx9Eg8Rrq6ntoShY
+      cXoc86+Sp5zeWTJZzFzJce6al8kdGzbzs9kUDMSIzWjAg0TUgxGdXSL/mxfMVgTi6C+u2DFaPOBXffUI
+      f4sH/F0lExHiZECisG+KwB2hFudmPGuLIt7ysFsRH5fZKOIV8SVSjCmRIq5EiqESKeJKpBgqkSK6RIoR
+      JbLrVfLKzxGG3M27bvFksq8qRjNj80gE1lyeCMzltZ8dJ28ET33CEf+x78ueG4MtYLRzdhqdB9JIfnao
+      nzm1zgkNelnTBi6PRMjWT6wBkgUjbtYcbU8iVpE/psUj74I7NmzmJ7cpQGLEPeMAFEict7irzkfeVYkc
+      tlYvyaH8XlYv6oHxvpvZ4WQSLsNiR0Yb4xdZoTqYnJbHNcBR2qfuLH2HBrzc/B/Md/155PQH5kEi6mnj
+      tNxwnqp7AiRG+2icWQuYOOKPep4iRjxPMb4TU7AsAxLlUNfqS6rvww1jK7A4shjuujLCi2II4BjRT6DE
+      uCdQ4k2fQAniEyjz+90tt0+bJxET1/QgESuha1lZB+qJYV7auhI4VpbWxat+TtatCeA0s4AFicZ7midC
+      T/PUh9u0EJlar1F3TWK2SboXWnWLwgk45ISv5LHOUolFpKVtgKNEPe8Tw8/7RPzzPjHmeZ+Ifd4nhp/3
+      ibd43ifGPe87fk1kss3c1umjes2UG8uSILFiny2Kcc8WBfPZokCfLepPRFzxMvnhCElaP8ZGUQ44Uqme
+      frWpGNX/hTxDEUWSbp7V4iWRbaLDOjI4tl4eV2diX5WCVSgsARKD9+RZhJ48qw/VpgSHJlNLK7JScEP4
+      FiRavyyVs/AetSDRxPdTTzTixgI0eLzuRdHYeI4GiddtWsGJ0aKw98chX0dkj4Gj/ojVDmLEagcRtdpB
+      DKx2aD9v1GiwKmVPTzylFx9+TaqtOe4RvKhDVuxqun607NvKeuSwy3jRXQsc7VgV9ytEmfUsKMJixq4u
+      ESNXl5jfy9VLPmUjq7WYaL0lHE3d+JunjLu2JaBC4kJrrNkdT9yGR8/LR/WSSFXLkcRO7yQkuKEBFRK3
+      bvaqcd/mRcaLZgqQGE2dr6Ong3wLHK1bZqRe3Iuotn0LFo1dOoOl0Z6bjhkzwiY0qurste2tesWL2zEG
+      RWNjxnQXcFs4epM2BxH7a0+SMbF4jYTrCEbqV9zFRbM8IyOKN4kngtEOahJG1j8RoY4KJI6sszdPLL0m
+      Q9a4Ym4r8DjZmn/9isXNtUi5YokGvdFJYzqQSPWB1wxpEHbyJ9VDs+ldL/QNOgawKRiVtUZWDK6RPagB
+      /pbqbSnAJu/h+3YU/Af9YZZND9mTyeL2PC6EVgzGUf2pyDhKAceZLyZxCWYJRsRgJ5tvGRONm3i+BY4W
+      8Tqhgw/62SnnOoYjtY90uWkHm4ajvkU8PJIa+rUbRDavyVNOn3EHJXas6dWX5I/pt4V6l52iNznESH0N
+      1gIR51Mqks1hX3RZVZXb/JG4hGbIhUTepbV4Sgs1sVO/dt8WrLigCYlKfNXA5BAjvflyUNvbbVSWqM1y
+      T48R+8emlDgDKjiu8YR2ne7V8JAT0rfA0ahF2uQwY7VLVq8NbQLDp2F7+x41eZMfAA/4eVNriCIQh/1w
+      BrcEou2ziDRT8IDbbANEVCDLNBS1nYuOi9c6ApHeZjpypDJwHe1YnB2zxVE/Z9UHgAf9rHe5MQceidaC
+      2iRu3al9rmvqIj3YgEc5bS3HWCoQ8uARuymeIt9mer0atWs25ApF3mX8SLssbCbOBQM47o/MnGCeqI5c
+      ZOXmKPA4/Cqlp2F7LtpHddw+jMnDEYidSQODfXp1OK/q6NCgN6ZX4SjQODF1uBiqw8Ub1U5idO3UP/3h
+      xgmVUBFRA4lgDSTiaiAxVAMJOZYoNslKvR1XPhaZGhmzAgEeOGJT8Xv1RzZsTrZVHZHZgAaORx8w2qRt
+      pb+QDr2HHrFXY3Cfxog9GoP7M6qNAtN9O9WgHurLAttQdnoPOfxIrD0ZA/sxqo/ULFX3Kshh9a9s3QhV
+      gmQvnPagY0DlxC3Ul9SG5d3u9qRILjzgTooqMoA2QFH0KL17qKCa6KKhx/EdUKTmdZ+x08qAB9zMtHIN
+      dpR2Jc9TTkqcE+S61LqnQi84Z+7AiSicOGohV7t9I8ndY44vZs/Qgf1C6VcJXF/MfqADe4Hy9uXE9uRk
+      78cZ2IuTsdEGuL/G+tA0T3V1eHzSe+wWGe1JDIDb/o0sto/qnLdkXWd66j8tVE+F1FNHJU6sSh/8IodN
+      30k/wuQco+w2MF6LMzDb187tnla6r5uf/eJmNbakBBlyQZH1rHLbiaHlAICjfvVujeoTkKt+zOFEWj/x
+      foLBOcbIPW2H97N9s71sCfvYRu9hO2L/2qyuZY+deQiMBzvun/uq1ouXVBu9k7d/LW97UgDQYEehPkXx
+      n56cDq9Uy7r0QQQUn0+79uad+cI2rcz7NGA3HwCrbpEgR/AMUBReQx3efVd/qm5svUKxkn3SOqe12bAB
+      icJ+3gobgCjGq0mnraPoOQ5agGjsp1hDT694OyJjuyH3T3tix61hExaV+3RszFOx/jtdJ6c74aBdWcYM
+      B6qwuO5qNmZMTwPE694/qrMfB9lkyQaMuIcPKgFjxbxsgSigOG/yfJH0XPFRb+1C36nR5Dxj0i3UIQqP
+      mO9jru1yUMDbvriweqUfogTgqJ+Rg/g7Fczd0NGd0ON2QR/aAd34vJbjomrHlLcw4O422KAvBvHpgL0/
+      MoYdolfgcfqjj5lRTgIwxnNG7LabHGakHldkk771uO8G47kJgPt+b2RIjeAJgBhqOEL2Kghw0Z/koasw
+      jA+Svz68+z1ZLO/mU72mMt/8ZIYATGBU1pqP8FqPbsv9nUjEYa8GaHS1AfvuLflu2QL3ifxHLp4yuqvj
+      fCN7P5GBswP0x8/kdkUivuc0CE2KjHyPWbDvZu9BMnDeQPRZAyPOGYg+Y2DE+QKcswXgcwWYZwqg5wno
+      FUnHYQx9w0oAD/iZXUaXRyJwb2sLxtyHoohNIseBRNJ7ITSyeyX0BJceMgtWPNCERFXDk7Q51Fk/yGPF
+      BDxQxHKjZu14fUSbBuysY5VsErAarzeQvQYbNpOX+IECPwZ//4yhk0L01turvKI6FQOYWDtwhM4aOX0m
+      1JxCuc5Y4iMMuOldkhrqk4hsre6afld5PXnF60SFXFDkdvbY2qWAHhKQQLHa+R3WyNOCUbd6tZVx79s0
+      ZueMrXoyZNVz63y1xiE/a4yMziOJp7RWs1i86Q6bRu2MPZd9GrLzaj+83gMau2STP2b0LjBuGhdVdc9Z
+      BSjgGheZdUcgHiAid+eVx/CuK8aK+PQxS8R32oplAAf87IezPg3bD2X+gz5J2pOg1dg54/QQiBEC0gzF
+      45Rg3+BHidg0evC8rJizssLnZEWckRU8H8v4kL5I0INBN6fNQcfNL4ze5QvYu3yh99VeoL7ai6yyMnaH
+      0qZtu3p3I/Y5KOawI+Ul8+1ZC/Scxqa/RKlBelY5NqfqFOJ4RLKRtQXJ0yKeR8lZ0w0u65nbHh1R2UK+
+      C2hm1aYve0FNhIDJjqr6Dof9hjjH01O2rchXdVq/krPf5ByjOtKvfzxGHekAOOBv1z61y9sEWW/Rtn2X
+      Pubr0/zHaeO+hlReUIkbq908QC1saZe00IK4tGtX2zPLL6hFOdThvgfbbu55jPhZjMT32bz32MrDzh6M
+      k0qFT9v2fZaRujTq+65BFwaaRCOOp67W6mwqPfG4r0TDW7Ib0MDxZBV9/l4/kjoWZ/rrSkMuL/Jzvsna
+      S6S2oB5su9vNcGUZP/3qZFvkj08N9blNUATE1DNdRfacFeQoPQp42w4PT2ywtrkmVhq1V08wD4JEz300
+      PuDcUQDu+vWiKCM31VyvoMUAFW4c4T5U/xfxbQREYcfptvLt1zNSIniw61Zb/8vIRftKEE1ts65ZrTPO
+      /87aDVzyIm9y2tQEbMCiROQ2KnFjtfVcnVFf3bBJ18o5IxA7HzDibMDguYD6Q+rjixMEuKJOQhtztqD+
+      zgvnil+gKz5n5dE5kkecswnRcwljziQMn0eoP4XeOyKHgCRArL4bzPslDg9EIK/Hxk4+5J56iJ94GHXa
+      4cBJh5GnHA6ecBh/uuGYkw0Fb4WuwFbo6nMA2/PI1bwo9XotFjDzzkAMnn+oPqTXaQlUo3EOoUNPNow6
+      BXDgBMCI0/+CJ//Fnfo3dOKf/rw7Ap1VuCwYcHPP3hs4dy/+rLYx57Tp77Sv1qk6uz2KjBzEFUAxtlW9
+      zvQknJ49E+kjIw4gAWLR17uiO9YI8hpOAazhVH+L6hc3Qz3iiBWdA6fDqY//tfl+fp68VPX3tK4OJTk9
+      XN6PwF6POXAeXPRZcCPOgYs+A27E+W/RZ7+NOPeNc+YbfN5bzFlv4XPeYs94Gz7fTX+jOZClzcH3sF9p
+      HDgxjXlaGnpSWvwpaWNOSIs/HW3MyWhvcCraqBPR3uA0tFEnoTFPQUNPQDsdX2Zu7Ut/JzGgQeLxshs9
+      ae30YczSY1SCxFL7hqsB9Fq9Nr3J9lVe8lINEoExmevAhk6Q458eFzo5rv2snxbmtCYuD0V4y3PpOGfS
+      Cfo6WgGtoxW8FY8CW/EYf67bmDPd9Heeso3RJ6U/cEUlUCxe+cdL/tu8Jk05Ee6NToMbfRJc1ClwAyfA
+      tee2MUbSyAg67iS5MafIvc3Za2PPXTMOonpSD4OpK04hHo0Qs/JRjF35KKJXPooRKx8jzwAbPP+Ld/YX
+      du5X5Jlfg+d9cc/6ws/5Yp7xhZ7vFXu21/C5XqwzvZDzvHhneWHneL3NGV5jz++KObsrfG6XoK8yFdAq
+      U1YbDbfP5JYFaFXUnxh7vpkcbiRv8unBtrupGn3oDXe9FcTbEfhnqYXOUYs8Q23w/LTIs9MGz02LOjNt
+      4Ly0+LPSxpyTFn9G2pjz0SLORgueixZ7JtrweWixp5INn0gWfRrZiJPI1FqV5Ckriqrbsa1bFUUMAzrs
+      SIx5ZXAm+SWlJYL6vmNQy+hICgVYjueL98chPHnqyWM9M0uJuLr5P5bSYnvz8mbB+/EeaDvpMsjC+sEe
+      aDvVuWjJ6rDdygLJMAO45X8+T87ZKerDvpsnxWzcFPZh130RkwoX4VS4YEoxW0QqXIRTISINginAEcKm
+      iN+O/PLNRZ4Yp1iMdToY6qOspwHQ3ptfbDjX6WCoj3KdANp7Zat/Nf92v7xLPj58+jSd60Fwe8jj9lCu
+      x8YY0AzFU3sIv0G8kyYQb5Nle31h7FAnQyCKehWiPBQFO8hREIpx2PH1h13AvD+IJ7ZawQG3GP+GCcQG
+      zKTNL2Hasi/my3v5/bvl9Gqp7hv5n59mN1NO3g6pxsUl5XfAMioasQyENHY8tfZydv/lVEfs9tQ7H1Ng
+      cdR64ybjBWhZ1HzYM7WHPeaUf9rwpIrErJxC69OonVY0LRBzUgugTWJWaiXhopZXbxl5O/k6ZRdlxBCM
+      wmibMUUoDqdNxhRIHE5bDNCInXgj2SDmJByO4IGIk/CirMvhRurN7sOIe1/t+alwhDE37Za3QcSpVzjH
+      3JimAItB2G7MA31n3O03dOdxCwdeLmi1/xHxPdyihZcq8ZRvyTmjId9FbTl6qHdNrq7kICy5ni6u5rP7
+      JfXQegQP+sdvAgHCQTeh5oJpwz5dJFdfJ1ejfd33bcN6tU6ycl2/jj/E0sEc33Z1fnHJUlqkY21qrtUi
+      besmI+s6xPZk6xXn0gzM8TFckKdi50UVyAuhN1vXH1DeVAJQ39sF5HgN1PYeypc63VOVPYXZkn262Yxf
+      igTCtptznfBVRlwjfoWL2/NkcvuNUj/2iOP5OFsmi6X6fnvMI8nowrib1FQALG5+1K8FNlx5h+N+vjpk
+      pTQ/PhrwHna046FRAR6DMA0GoEFvTE4KOCe/3rOLoIWiXuoVGyDqJBcPk3Std3c308kt+TpPmOOb3j58
+      nc4ny+k1PUkdFjc/EsuYjeLenK0NpQM1u2wU9wp+KohQKjRV8vGWa9aw4/7ELGSf0FL2eXor493M/nd6
+      vZzJ4Wa6+RfJDPADEejNH2gYiEK+ZSDBQAxiJvj4gJ9a3AF+IMK+JiwDwg0DUai3F8APRyAuoxzQwPG4
+      LZyPB/28coW1dvbHzDKFtnqzyQduqtgo6iWmhgmiTmoqWKRrvV1OP6vnTLs9zdlziJHw6MjlECM9jwwQ
+      cVK7EAaHGHOeMMd85NzuOcQomL9ZoL9ZVT0HWZX++gtX3OGIn94VsUjHevtwc0MvTCcKshEzvWMgEzW7
+      j5Djuvv439Orpdp/irCY2CdhKzntDA42EtPvRME2ahr2mOu7Wk77yQtiFenCITe1snThkJueWy4dslNz
+      zmZDZnIuOnDITa0CXdhx38u/Lycfb6bcJIcEAzGICe/jA35q8gM8FiEifYIpw06TQGrw0yGYApRXOwHU
+      8S6m/3yY3l5NORO+DouZuVbAuORd5hK5wra4tWmTbjY0qwOH3OsiS0tiPQ0J4BjU1gVtV44fEFaduBxs
+      pGz35XKIkZeaGywNydUKXtv2E//v2D/8BKPu0zHIu1R8Z4awHHCkIisfx7/P6pOwlVoxou1C9wF9OscE
+      A85k/FnGEBs2J9t9jFzisJ/aQ0H7Jv0H75jCd6gxWb0mt7NrprejcXvs3SFG3R3ut5JUrN8imvLAEeWg
+      9GH56ZITpEMRL7VTYXC4kXujH1nHvPz1nFtd2yjqJfYsTBB1UtPAIl0r8znIEn0Ownr4gTzxYD7mQJ9t
+      6A82+XZL1ykKstELDvJMhPMgBH76wXrkgTznYD7cQJ9osB5jIM8uYh5YhJ9S6E9l9faYlVmtDyjYqL2e
+      6BF8hxvp2/2U3N8+QpCLXh6PFGSjTkkfIchFLpEdBLkE57oEfF1q/3OW7NyxPdzO/pzOF/ynW5BgIAax
+      wvDxAT810wDejbC8YjURBocY6Q2FRWLW3V5v9JY0PPUJR/z0UmKAiDPnXWuOXSO5FPQcYqQ3KRaJWKnV
+      gsHhRk7z4uOe/9Mlu5qwWdxMLgYGiVvphcFEHe+fs8UsYq7ax4N+YoK4cNBNTRaPduy0Y7oNxPG0/Y9G
+      Dn/Udpskn41i3uf3POnze8/YJNWKcpKXgzm+vMl2yeYiJ9mOEOKi7AXggZiTOG1jcKCRXnAMDjQeOBd4
+      AK9OHbrAyZKWQ4zkesMEEWd+sWEpJYcYqTWEwUFG3o/GfjHr5yK/VW2CwbpPOhBzcu6TloOMrOxA8mKf
+      EnueJwqyqQ1/6TZFYbZk3fzkGRUJWQ8l7ze3HGSk7dXpco5xt+p2XyQ/e7JIzFrytSXgbZsvmd5/0+5o
+      g3OMspe8y5v8OaNXEzbqeg9NklW0OemOAUyM1r7HHF+TPl5QX8boGMAkxh9ZbTKuKdvtC72PIDUTLNKw
+      Piy/SGD5LZndfrpLuhc9SXbUMBSFkLYIPxSBUiNjAijGH9Nvs2tmKvUsbuakzJHErazUOKG99+NkMbtK
+      ru5u5VBjMrtd0soLTIfs41MDYkNmQoqAsOGe3SXpfq+PX8qLjLJhO4Da3tNJQ+umLihWC3ScRZbWybZI
+      xx956WCQr90YlGk1YMetNjzRxx7rr5DMNup4qcnpp6L8ix4u6uNMiJuqogIkRnsu+OMhrdOyyTJWGMcB
+      RCIe4+1ytnFTHc8+pPh6yrZl1ZaikV+3ebUzDOkxsgU5roKw28kJcBw1LRederL7S5IWBdWiGNuk19oQ
+      lgKZjG8avx18TwCWPdmy9y15mTdUj2J8005NQjDS6MjBxv34jqGD+T61y4ssr+OXBHmg72TW6Q6KedVh
+      n+O3i4ZY30w9ScDlPCP1hzu/9in7uTnsSIW5Q2yPyqCSVJZbwrU05JbvyNgmVQz18U4lLYVMzjU2T+Rq
+      8QQBLkoHz2AAk95IivTCCYBiXmJ2WCDi3MiORF29srQdi5ipN4QFIk45COc5FYg4a8KxdB6IOEmbyvuk
+      b63oPRIDs33Ewu6Vc9UIrPIq2ad5TRSdON/I6AAamO+j9S1aArAQznEwGcC0J3v2vkXViavDlqrqMN8n
+      qvX3jJzoLeXafhI9P13DYbfKavL9aGCgT91Rsg1hKDvStjIGPuCYZ1+RCoT8usOr5QikgtASjqWpyc3K
+      kXFMxIHO3hvnUCt3v06nFh2/zLTnjYrynKrREODizPJYoOsUtNtVA47jhXdVL8g1CU7dLeCaWxDrbeHV
+      2oJcZwugxlYnc+xoEgm4DnrtKsC6VffhCsK5zBYEuGTS6xMfqWXAgxG3GgjsCfulgjDiZnthJ3WkLsDZ
+      DEGezRDAbIb+G3UEfYIA154s2vsW6syIAGdGRDchQey9GBjsy6qtGucf6pKj7WnfXhKWEpiMbzrNQ5BL
+      SE8GrMSZERGcGek/FftsnacFT93BmJs8QHJQ38uZzRHobM5pKNad1ER6RI4KnBhP1aHYJHJExElpFwbd
+      5CLXY4iP+GDF5EAjvSAYnGtsc1J+RhOeMMdX0vvYR8Y2NZlgVOw9ZdsO6uBk0lW1hG15ps6fPftzZ8+c
+      JHqG0+iFMbB6AUdW5CIFlKX21iU+MjlBkIvT5bZJw3oz+WN68fHiw6+jbScCsiSf8pJQ/TgcaJxROg02
+      Bvoe9hvKnKoLGs7b5OPN7Pa6fc+/fM4IvUkfhb2kW8vhYGNePqdFTkoCkEbtzGTIA6lAmWe0Mct3tfwr
+      ycYf8tETnoWYLUfE8xBeTusJz0JLno7wLKJJa+rVaMYyfZ7eXn3U60AIqh4CXIKURifGMn29u13qC6Ys
+      enQ52EgsChYHG2nZaWKoT1UyoqG8AIoK8Bjbqk521eZQHAQ3iqGA49AKg4mhvqRQ8yQbprajLXu6Ekku
+      kpeqplgNyrZtSJaNR5MvpENsj1hfrEqKRQOWY5WXNEcL2A75l5zk0ADgIB4P4HKAcZ/SbfvUM61XK9a1
+      9Zxr3GRrmkoCruOJsMbjCLiOImP9sBPm+nb7nGaSgOXQ6wAJCv1930DZQt9kABOxOekh20VY/HFrv4ff
+      /ptaZxwR20NrbL02dl0dSlXBviR/Z3WlEkyQdB5t2WUZp9VGLWA78meKIH92aWo6HxHbc6DktvVWm/x3
+      Vj6l5TrbJLu8KNTjz1RXcnW+kz395lVPHhD0Y3R2/B+HtGB1UBzStv6kpIn8tkUT70Lv/tvW1U52ZMrm
+      sdpl9StJZZGW9XFNKSry2zZ9fGtV5UWWkKpzj3XMTVJv1+8/XPzafeH8w/tfSXpI4MU4jN8QuSc8C/GO
+      OyKWR7ZttLqjBSwH6WHIrfsc5Fb1FWWdRuwR95DrKrPHVL0yRZMdKddWkTqtLeA5SuLFSMB17KuXC5pE
+      EZ6FfscYFGzbprLWUvOyPK2Bu35iAYfGHPJvqtGkWRRhWYqMdpPo79sG0omMJwBwnJMl55Zll9biSbY2
+      pBUdNub4xHdqj+bE2KZqQxwjdgRkSX4c8vHvxLqcZ6S1wh0BWS50m0h3tRxkZArDPlY3BhbgMYj3t8d6
+      Zj31KqiX3FGYLVkVajH4hmc90qi92nDNFVDyyfVMDyGuc5bsHLOx7kuLRcwRYsS7OxREnSQgC68D7cOe
+      m9gpOCKeR/yoiRpJQJaGrvHLnTisqJrDCrKwisSJ84yM6sqvpfY5rSvRAraDVi7dMimLFPWXdIjloU3u
+      u3P6ZSmTh8Kr7/sG6h3QQ7ZLnVtJ68IcEdBDTWCL842UIzlNxjLRBiHuCGSfqhZHdf6SQ6n2IiG1hwBt
+      27lzNIHZGNKudsfv+wbKgsEesT0iO2yqpE5JT2wNCrOp//OY8Zwta5mJF+hdGeuSAtfS/pk2rLQ420jt
+      GdV+r6gm94hqoDdEPKq2JzwLY6rDxDwfbV5KAPNSgj4vJaB5KVqPxO2NEHsiXi+E1gNxex+qB0FNgw6x
+      PE2VOMenEow+DLq789AY4o50rayursVZxgNtQuDgzgYcaA+QDu4TpAOtKBzcsvCcFoeM2PaeGMtEnMZy
+      5rBOX9keynWTV2XyRKiBQBqyi6zY0tpwHzW8D5+Sr9Ov3RYvo5UW5dtIj0QMxjc91tUL1aQY2NSeA8Tx
+      taRvpXTRe8T3qBem6mdyonWY7dtlO8pTvhNhW0RTEy0t4VmKddoQNQoBPIQnxD3ieUr6zyqh31UWWUn1
+      FOZ7nVcfP+rpUMo0scnApmRVVQVHp0HESTpg1CcRa7VuyPtNowIsRr5pn5M2hDeFcQMS5cBPoAOSQqQh
+      qQX5LrFP1xnVpSHfdTj/lWqSCOjpzriSQzr50c/xw92AAoxTZAxzAf32C3IeSwT0RP92XwHEeX9B9r6/
+      AD2MNFQQ4KLfJwfo/pB/ZFyTggDXJVl0CVmiM/VyOE9Vr5NcL2jIdhHPVDQQ20N5k/X4fceQE1/IsiDX
+      JdZpvUnWT3mxofkM0HbK/8jH7zLQE5CFsvG0TTk2yg5vJwBwtI2QmiAYv38dCNtuyoKV4/d9Q0K+i3rK
+      thH6at3XbZ7YPzcQ20MZYh6/bxoWXVctq9WIfpPV42UeCnnzptu3+SkVlBk03ABEUT0qeQm0HpnP2ma1
+      Z1eal6JbwflKqU4g2rXvX6ldMpOybbQ6c+HVmQu90iwtX4ljB5vDjUlWZDvCbm4YD0dQJTA2iusAInFS
+      Bk4V+qjKAREn9/cP/u4k3+2LfJ3TB1e4A4tEG/i4JGI98LUHxEu+eU+Q7ypS0ZA6jRbm+6q9mvEjrhgD
+      4QE3qxj7hqEovIH9kGkoKq/QQA4/EmnUe0JAD3+QgCrAOEXGMBcZ4LogJ6oz6j39Mfq3h0e93Zcoo94T
+      AnoYaeiOehfU5egGAnoY1+SOers/kyswqO6KGfViBiBK2eSF7NjXgtxcGqjtpY1RFt4YZaEWMh8XW5za
+      tOyR1inHHF4k/TK908kmBoIUoTi8n+ML7BiksdjCHYst2h2U1Os8FMsJsl37LPveXmqTklLTAm2n+J7v
+      KSr1fcfQjH/qdfy+a6A8vekJwzKdL2efZleT5fT+7mZ2NZvSTtLA+HAEwh0J0mE74Wkdghv+r5Mr8jYB
+      FgS4SAlsQoCL8mMNxjGR9mjpCcdC2ZflBDiOOWUTyp5wLLQdXQzE8Nzdfkr+nNw8kE6KtSnHpvcxyAQt
+      /10QcRZVt68nS3yiHXu73rDICe2xjRm++U1yPVssk/s78nk9EIubCYXQI3ErpRD4qOn9dr+8Sz4+fPo0
+      nctv3N0QkwLEg37SpUM0Zk+LYvyxaQCKeUkzZx6JWfnJHEphPRctm1ae+UhjdkovygUxJ7s4BEqC3qpF
+      PT5np4RpwKLQdqeDWM/89WE5/Yv8mAxgETNp+OGCiFNtMEPafhGmQ3bakzoYR/yHMu76DT4cgf8bTIEX
+      Q3YUv8kWnvrAEIJRN6PUmCjqPehOTrJSP08wA1gOL9JiOVnOriILKiwZEYuT5YglHI1fiDHNqHjRvy9Y
+      spdf5tPJ9ew6WR/qmvLIAsZxv942uzsYkBvEdIQjlYddVufrmECdIhxnX6mJkDomTqfw4qxX6/OLS7Xf
+      TP26p+aLDWPurIxwd7Dv3q7Ux+dcu4Nj/ss4/+D1R9lR91Mq/5dcvKNqj5xvbHsiqm+tj5an96IBgx+l
+      qSPSxIIH3OqfhFl+XOHF2Vb1d3lDNOqg6fyxrOos2aWb5+Ql32dVqT9VGw+qVfSU+VeO3L82+jAFHJ/o
+      QxZ5xcBEPe/jeqcSOCW3fD2IOXn1mw0PuFllClJgcXj3hQ0PuGN+Q/i+6L7E6tpaLGbW493v2SvPfaQx
+      u2xCx2+/BqCYl/LUwAV9pzrk47Xth7VH8nH7QgFTMGp3tt5bhHVVwbjthcYHtTxgRF61Z5CYlXy6KYKD
+      ft00dBur5VXJCOEYwCg69Si7xUMsalZrAiOy2FWAcZonfYqV/C7hoQWM+/6nVK3EpY+/e9BzqjWSqdgR
+      hR3l29oOILnfeOI8o65WxaugvLcOoL5XH8S1zdUBsHlaJKsDZbl2wOFFKvJVndavnHwzUc+748xw7+C5
+      7fbPnEs0SN+a7Qhv5lqQ51K1E6/mNEjfetglnPmmE+cZq5hRWRUelVXlmloxKsTz7Kvi9fz9uw+8vpRD
+      43ZGabJY3HygPUIFad8ux0JCVhWr6ifr0h3c89cbRh3WQohL7dnT5Psiu6ScLhZQ+HEyTiXTUYBt225z
+      LAcriQqut4QkvZAwJMJj5uWaG0WinlfNiKn3mmL6jaADjPQ2fXJB6JOLt+uTC0qfXLxRn1yM7pMLdp9c
+      BPrk+jDATczVGzRoj+zRijE9WhHXoxVDPVpexw7r03V/1zNYIsuY2hOO+vNtkj6neZGuiowZw1R4cZpC
+      nMv2hFqjHzHDt5wn1/OPn2knB9gUYDvur00WHkHASWpxTQhwqffeCLlvY4bvKb1SYxLilJZF9bbr6eI4
+      Sfd+rMtkbFO2Xr2ndjJdzjMyhYhvk12oRzAsqcN65vcR5vcBc0nPnyNjm0rm9ZXotam6lDA5aSCgJzmU
+      66eMcpQQCPvuSnZo9mmdN+RL7UnD+iXRkUa7uu/7hmR/WJES0OFsY7XbH2T3iejrKcymZlaeCHkCwaib
+      dpoNCFtuytOg7usWfzqngZaMJgb7ZClKd1mT1YKwsSAqcGI075JHklMBvoP6m1vE9+yplj3g+EH+RRIB
+      PHX+zPlhRw4wkm9aE/N9P6imH65DHf3x2+/nvycX7365pNks1PIeN97vyx3B7MOWm7Cksv22TRN3zTUQ
+      y9Muu2b9Phe1vIJ+LwnoXhL0+0BA94EeVul3yWimDrJdhLO3u69bPG1J6gkwHTrVBeXMJpMxTLP59Gp5
+      N/+2WM6pJ8VCLG4eP4zwSdxKuYl81PQu7m8m35bTv5bENLA52Ej57SYF20i/2cIsX/eqQXI7+Tql/maP
+      xc2k3+6QuJWWBi4KeplJgP561g9HfjPv52K/VM/B7SmPc0HYcC8myWJGrD0Mxjd1bSdV1mG+j5KAPeJ7
+      dJtHNWnIdrVDGPVyb9ocapLRQW3vpopR+7RnV58QlQrxPM9ZnW9fiaYWclyycbz+QhJpwrZQS65falmD
+      JodDjLxhE2pwo5AGTicCsJB/udffO/51T/bsIcsP+u+y+42nv1IHUC4IOYlDKIcDjD/Irh+ehfrIxcFA
+      H3kBFMTa5oiBGUgjdpl7jFsawBH/YVXka7b+RNt2YlvntXPsISHAgmZeqnow6GalqMvaZsGo2wRYtwlG
+      rSTAWknw7lSB3anUZt1v00mD4u77toE4LD4RtoXesQB6FYzhtQn1rukVb1ba5XBjss33gqvVsOVm9ORt
+      CrZVxJOUIBYyq1aM7lQUZktqni+pUaNgGsFfTBwZeSDs/El5a9wDISehFbIgyEUadTkY5BOsUiOQUtNU
+      3LJ9JF0rcZxlQYCLViU6mOujXxh0VepvyUvePCWlWgqpF4sVWfrdbN85r1Px7P7V/Z1RI/7tlTROsvtp
+      nnz+1J26KntUT+PP7fNJz1rmotlfXPzCMzs0Yv/wa4z9RIP2v6Psf2P2+d3DfUJYIG0ygInQiTAZwERr
+      lA0IcLWD+HZ+oKrJVhvH/FVN2IcaQGFvu7natkgfOeqeRuzrapuumWlygjH3oX7OVAnkyY900E6Z10Vw
+      xL/JHjklsEcRL7uYoKWkva0JG9f7JGBVcxGr15hk9gxIFH45sWjArlOM9OQYQAGviLovxcB9qT7nV1YW
+      jdj1LgrqtSF1vLc6ZE12D3asSKDJivrH9Fs3z04buzkg4iSNMm3OM8oMz2VR0mMwka3r8dvsoQI/Bql9
+      7AjPQmwbj4jn4UzjA2jQy8l2jwciqCa5rsjJ2YOwkzFfh+CInzxnB9OQXd+H1HvZY0FzVq51dSUY5hML
+      m2kTez6JWckT8Qju+XORVPv0x4F6C544zyjz84Lw8pRNebbjlDmr6YYFaAz+7RJ8btB9hzStciQgC7sn
+      A/JgBPLQzAY9ZztNz75oF0f89AcfCI752eUj8ASk+wa3F+axoJlbl4pgXSoi6lIRrEsFuy4VgbpU9yYZ
+      zeyJA438UuHQsJ3bxNrwgDtJt+pDmddyqJCXKWlOdJzPuwLaQyMLslxfp8svd9fthhh5VmyS5nVPqWBA
+      3orQLp8iHKltMoBJvwVG7fe6KOQlzXydGMhE2P/cggDXZlWQVZKBTAf673NHHPQVgxYEuPTMVMztE9KM
+      jkecchhSAXFzNSxuyDFaDPKJJFVvgqtNDxp6abNx2C+H8LrTwJEfWcC8O9BLtGQAE61PCKwNPf21WjcX
+      ev6C7DuRgFX//WK9WpGtJxK1yrhMqyQBq3ib+1CMvQ/F292HgnIftn2y3b7OhMg2bxIb1yHxm4p/4zq8
+      FaHr4uebi5JwCoEHgk7RyM82DGcLWk59jtwhL5q8qyUo5cyHDff1xYcP57+rPtQ+zcdPmNoY6jtO541/
+      ZxEV+DFIz5cNxjcRn79alGmb3U/my2/k1yQ8EHGOf0/AwRAfpTVwOMN4+3l2S/y9PeJ5VGFtH3AT5wRg
+      HPTPY+xz3K3POTneaVn5KD8SxAiQwotDybcT4Vnq7FFWNeoM1KLQNXKRNdQsBB1eJBGXp2IoT0VMngos
+      T+fzZDH5c6p3OCeWbx+1vWrLoKyuq5o24+CRIeuWr93a3nYMqD+mOA0M8olXWXB2XK1J2/b2Z9COtnM5
+      3JiUXGdS2la9C3L7kaA4Tc4xHso1++d7sO3W8/rUrDpBiCsp1J84Qk2GrOQbC8B9f5n97L+lN3akhvAN
+      dhT5R3YWuqxjVi3Lx9kdp8y5LGBW/8E1Gyxgnk9ur9lqEwbcepeWim23cduvD3ck3zI9hdnIN42DBr3k
+      2wbigQj61GpeYvRo0MtLFocfjsBLIEjixKr2apC6S+vvJHuPOb5aLS3RIUnF2uRwY7JecaUSDXi3e7Z3
+      u3e8B06JO4Blrc5SUZXsihnAXf+uelatOmFLNpcDjd3WfVyxibt+0aijJxhmA7SdIuWkQU85NtnaUm+n
+      I2OY/rxPJtPJtT7ZNCWcx+SBiJN4NhzEImbSiMUFEafqwow/AwFAES9l70APDDjbpf2bvM7WlD3vhzxI
+      RMq43OEQY7XPeBetwIAzeUybJ8JKWoRHIoiM8NaRCwaciVinTcO8bFOAxGjSR9LLTQCLmCk7JHsg4FSP
+      vGl7FAEo4FVvacmKv37i1HQmjLi5KWywgLl9dYeZHiZsuz+qF66W1R+EpRAWZduuZvdfpnOdqfpwQ9qr
+      Q5gAjbHO98Qb3INxN73N8mncTlkL4KO4t6kLrleiqLfb65PSJ8QEaAzaiieAxc3EXoKDol79qH+/p42X
+      cAUah9pzcFDc+8yoUCAejcCrw0EBGmNXbbi5q1DUS+zp2CRuzTdca75BrWpTaG4R0SxqFvFlXIwp4+pL
+      MTXAiQ9GiC6PtiQYS21Fy68wDQMYJap9HWhbufmAp39MTROuZaJydCAnmTULWqvw7n3/vqd3e6C+jv7b
+      p7xMC8I+Wj4JWWfUButEYTbWJXYg5Hwgnc3jcrbxOlvLHP+YiuzXXyhGkwON6i5lCBUG+XSO0X0ag3zU
+      XO4pyEbPEZODjJsbcr1ggZ5T9WA5N4yDgl5GYh4x1Me7TPCu6T5jZVIPOs78MRO0H60JyEIv2z2G+v66
+      +8RUShK1UnPFIiErueicKMzGukS43OiPFpRVbBaF2Zj5fUIxLy8tjyRmZdw2DguZuVbc+CdtjaDD4UZm
+      bhkw7ublWM/iZm76mrRtn5asdt3AIB85dQ0M8lFTtKcgGz0VTQ4yMtp1C/Sc3HbdQUEvIzHhdt34gHeZ
+      YP3cfcbKJKxd/3L/x7Sdd6Y+TLRJzJoznTlk5DzztEDEyZg/dlnEnP3cV3XDErco4qXOklog4vy+2bKU
+      kkOM3Kc3oACJQZz5MznESH3GaYGIk/oE0gJRZ6PfBl3n+zwrG6becgQjiazc0KYyQMGIGO3TbfWSBWsj
+      PZoWuR7qE1ILBJx/XH/iVIYtBvmmX1k+jYG+b+x60GAxM/EZmgUiTlYdCOyeY35EPYcShBE39cmQBSLO
+      79mOpZQcYuTUp/5eHeYnnP0BEB6LQN8jAMYRP6suOIK28+t1xBN3DwbdjLv4a2D91vEz4h1sYKiP2De2
+      Sdiqz6DmSDUIOrsDphnSjgSt1NrrK7YW7itvxdpXbL1a98Fuw7DtNrCreub8VoWBPmId9RVZ1db9nfw8
+      1uRAI+v5qMvCZl6NgdYVpK1CbMzzseu0QH3GSUU49dTrdO0eJwylDXtu4rPClvAsjJQD04yRp35+3n+c
+      JoJ01rBNObY/rhaXF7JV/EaynSjXNv12oT+k2Y6Ub2Otx7JAxLmhtcMmhxip7YYFIs52N0Ji98mnQ/Za
+      pEmVZvukSFdZwY9je/CI+ou7x+05sSHDHAOR9CVFRuocA5EYK1Uwx1AkIRKRFg1xfWzIE4h4OrctJhlN
+      CRKL2HcwOdxIHIk7KOIVb3TfiNH3jd47bt3uA6hWgXLDWZIRseTAud/AJDqoZQtEV0kiay31ddKm0gOe
+      cRHlmDP7uX+LmK1pIGpMTShG1YTiDWpCMaomFG9QE4pRNaEwarAutSN/mWUiRH2D7PN14+PHNAO4bkT8
+      two8HDG6/RHD7U8qBHFxhYGhvuR6MWE6FYp72y0nueqWxu1z/lXPwatepSLjNMQdBxk5zQLSBlD2pjQY
+      2MTZ6RfGIb+aX4sJYPNAhE1GH1kaHG4kz4J5MOhWBwEwrApDfdxLPbG4WS9Hz2iP6iAeiNC9GkQ2dxxu
+      5CWHCQNu1lgZGSeTjuszIcRFOPnZ5VAjo0Y9gpiT2QYYLGaec692jl3tOTNNz9E0Peem6TmepucRaXoe
+      TNNzbpqeh9K0KYS6z9SSLNr+qkELHC2p0xfu80LMEYrEem6IKIA4jM4I2A+hn1HhkYC17YyTlS2G+ngV
+      ucEC5l0u+33lY0ynxFcAcThzQ/C8kJrYiS3LgCMUiV+WfQUQ5zi1QrYfwYCTV2YsGrLr3Xjao43pcgPG
+      3W3OcOUtjdt1dnDlGgbcgtuqCbxVExGtmgi2aoLbqgm8VRNv0qqJka2a3u2Z+ETOAiEnZxYBmUPQA2rW
+      /XciQevfjF/sPc3Uf2alHpJyxDM3bAzwPZNfwjAw1MfLD4PFzXW2VgtqufIOH/RH/QLTYUdivU2EvEfE
+      eYMIfnfo+FficiYD8330Rf7Y+0fMt3rQ93l4b/Jg7/D0fyemngVCTnoK4u8Cqe2I2z1okrTIU1J3wmV9
+      84b8bmVPOTa1O16aieT84jJZr9aJeEp1K0WSY5KRsZJ8t5d9j5y6M9soYega1rtkVRyypqpoLxzhlrHR
+      ksu3iZdchiI2dfK0S3W6XHz4lR/R9gQiPq537CiSDZvlkKPc6M2uYmL0loFoIqIwdvxABFlSzy+iYmjD
+      iCjvo6O8x6L8fsHP9ZZFzOrI+ugayZWMjBVdI4WEoWt4gzsW8AQicvOuY8PmyDvWswxEExGZFb5jj9/g
+      37GWYUSU99FRoDt2/ZTK/128S/ZV8Xr+/t0HchTPAETZyCvJNtn7uNsXtIyNFnUDDxqBqygPRcH/rRYN
+      2H/GZ9zPwZw79aNo7hOG+Jqa5Wtq2JcRdu62MdhHrgDR3kr7QbVlXZ/EAJ9sIDn50WKIj5EfLQb7OPnR
+      YrCPkx9wP6L9gJMfLeb7ulad6uswxEfPjw6DfYz86DDYx8gPpG/QfsDIjw6zfasi/Z5drIi9pJ6ybYxX
+      4MB331TTQSwhHeJ7iDnZIYCHts9dh4Ce9wzRe9jESaYjhxg5CdZxoJF5if4VqmO7VRNPkR0Z26SeIrdz
+      Q6tX0rHwABsw055DO6jvbWeeeFdssgEz/YoNFPdWq39xvRK1vU+p0NXZU1pvXtKalBIu65j33zNuh8Zl
+      ETOjKXBZwBzVrYUNQJSn75stY0TtsoD5Z3uOZkwAX2HH2aW1/HPRFaskLR6rOm+eSDmBOeBIzCUIAI74
+      WQsPfNqxb0jbc8qvu/wHGv/B4/UIjijRjG3ay1+aReU3bICiMPPag0E3K59d1jbX64vkl3fUhrmnfBtD
+      BXh+oTmcskctN36Z0XMHW71VWbdnzbpWrxccttv8J1WNiryYFxe/EOWS8C20ahOqJeXf3l9Sr0USnuUD
+      bX6vJSBLQv9VHWXb1NSTmofSi+R3Kamwuixs7uoJ9RC93nD0lgCO0X52/KY47NVWZRkrGqLC4upjwBhv
+      fsEGI8pfy+nt9fRab9vysJh8Jp6wC+NBP+EBOgQH3ZSVjCDd2z/N7hek3dVPAOBICFttWJDj0sfAratD
+      STh9yQN75+fp7XQ+uUnUaeILUsb7JGYdn90uhxkJmeyBsJPylpLLIUbCDgguhxi52RPInfbFgkodIXZL
+      GNQGFKE4z2lxiIihccTPK2RoGeMWsUAJ08tTWU5NIlZxSvySm3+2IhSHn38ikH+Lh4/L+ZRXvE0WN9ML
+      R0/iVkYRMdDe++WP69E7uKvv2qTaLjUtNxRBh3iepk7XDVGkGcP0dXI12iC/a5OcXdxcDjISdnCzIMRF
+      WLDncoCRUuwtCHBRFp9aEOAiFG+TAUykfcZsyrGRFnP2hGOZUVNp5qcQceGmyTgm2nJNA3E8lJXnJ8Bw
+      zBcL9UJwOv7OOxGOJSupFk04luOmopSJFw90nPypOwR3/NwJIxB23VXx+l7erM/Z+H21PRB07g4FQyip
+      3jZbLB7kV5Pr2WKZ3N/Nbpekeg3Bg/7x9zAIB92Eug+me/vX69HTOfKrFker7k6A7aBUdsfv24ZlnZZi
+      W9U7iuYE2S5aZdcTpuXDePyDxVHT84Ofnh+I6fnBS88PnPT8AKfnB3J6fvDTc7r8cndNeTmoJzzLoaR7
+      NNOb9HDh6u52sZxP5M20SNZP2fiDSGA6YKfUUiAccI8vKAAa8BJqJ4g1zPKTT7QkOBGuRe9CRzvc3QNB
+      Z1MTZjxdzjUW1fgDGXoCsiSrvKKbFOXaKNl5BAzHdLm4mtxPk8X9H7JTR8pMH0W9hLLsgqiT8sM9ErbO
+      ktWvv6hOKWHaFuNDEdp3X/kRWh6LwM3EWSAPZ/qukL1LQrcU47EIvEIyQ8vIjFtEZqESIiLTQQymA+U1
+      ZZ/ErLRXbiHWMN8tZ1dT+VVaWbMoyEYoAQYDmSg5b0K96+7jfyfrlbggrKkyEMdDm5QyEMezozl2Lk/a
+      5r8nbMuG9ks27q+Q/7FRRTXfqFUZguJyUNS7eo1Rd7Rt188QKCeEW5Dtoh3m3BOOpaQWzpawLfIPF+vV
+      iqLpEN9TlFRNUfoWwmpDA/E9gnw1wrkaqaUmcYf4nuZnQ/VIxPYIco4LIMellqrpEN9DzKsOMTz301v1
+      JfVmdloU/TItkayrcvRgcEDjx1sd8kLtf9fueCyocRzc9+vqW2RUb4chPkK9a2Owrya13j4JWGVa549k
+      o6YA2/4gK2N9EhlZ2aO+l/Or4d/7uGvyHdnVUphNluF/8YyKRK2bfLtlahXqe59S8fT+gqpsKd+Wp+8v
+      1uk+uacKTyDgVA9M9EaXFdnao763eJJDvCJryBl/AmFnpWuu+pGjPbKgmVPgOwz05bKKGv8UwQNBJ6HD
+      blOw7bCTA4NsJzjOIwua66yp8+yZk55HNOilPPdBcMCv545UmyWbrF21ORT0Jg9y+JF2shxWa6q7pTAb
+      6bk0gALebLehNyot5dvKitnwnUDfKYddnITsMN8nmnqdiowygPRI0MpIx5YCbap5YOgUBvqKddowfApD
+      fPtXlm//CvpKfqaUoVwpedlSYvlSEg4TcDDf11RF9TJ+/amDGb7ll+mcuvzSgiAXqbG0KMhGqLgMBjJR
+      GkgTMlz7rIQHSaPFqAGP0r4SyQ7R4bi/XQHP9ne473+WUQlPoxwM9anuBdOp0N57P/2aTBa353pp9lij
+      BSEuyqMpDwScL7KEZGShpjAb6xJPpG3968O735PZ7ac7ckLaZMhKvV6fxuys5ABw2796bTLBunKbtK3y
+      P5O1vOdW6fgn8i7nGr/LHt62otlaxjFVyZO86PGtkgXZLvWkS707czW7l/WwTmiKFcBt/76WHVvK7q4W
+      ZLuoZd4v6Tqvr7/Q9ov2QMi5mNy3r1b+MX5IBNOwPbl/+EjYehlAYS83KY4kYJ1eRSSFCYNubkKcSMCq
+      Tgz9jWzUFGK7ZNkuMZv8+uxP/fIW9QbFHFAkXsLiqcovBcEyMI+61+YD95r6XK9L5cqPMOzmpvI8dB+r
+      NpJsVBDiSiYPf7F8CsScV/MbnlOCmHM+/SfPKUHASew/wD2H41/57YwJY+6oe8Az4FG45dXGcX9MEgXa
+      IPV5VDvkCtAYMQkUapPU57x26UQGrJds62XIGtlOIR4sIj/hw6keV2oGy8w8+t6dj7h3o9oxV4DHiMmF
+      +VD9wGrXjmDAyWrfTDjk5rRzJhxyc9o7E7bd5MkOYJ6jHZRzmjqbBK3cGwXAET+j+LosYmYnCNyqtR9y
+      mzSfhu3s5EBasvZDcjNmYJjvkue7RH0xCesIRsSgHIIelKCx+E0xKgFjMQtMoLTEZEQwD+Zx9cl8qD7h
+      Nrk+jdjZqT0P1lbUZranMBu1gbVJ1EpsWm0StRIbVZsMWZPb6f/wzYqG7MRBKjJrfvpzRNuNj1ONz+Pu
+      uYGRqvUl9t0RGqta34hKqFC7HjNchQ14lKhkCrbzrCGrg4a8l3zvZdAbm/Aj2n/ga7w+ACIKxoztC4wa
+      lxtfjShgA6UrNqMG82geX1/Nx9RXcX2F8Pjc+k5UbswHa0Ve3wEeo9uf8foQ+Cjd+ZzVl8DH6c7nrD7F
+      wEjd+pzXt3ANRhR5e59fJPcfp2q1yWizRXk22itcFuS5KEudDMTzqCfW32WdmZabZJ3V4xfjYLwXQW9u
+      QrRqxjN1Z2USthD1QNv5QWbVH9efLhLK5lUeGHAmiy+Tc7ZY0659v8ou1GvKaoE7aXUtgoP+rIzym7jt
+      /y1ZHcpNkakag1TULBBxqvKXb/O1vF94blPgxqDecL8B99tv+nah//QjBdlUbcYzHknMyk9OyABFiYsw
+      ZFfnu8dFcA1uFMrb3j3hWtTKniQXpBdUfRK1kk5ahVjM3N3l2YYnP+G4/zkrqj3f3+GYX+UFV96yYfOk
+      3EzjfoLvsSM6AxByHQXx4Qi05sCnw3bCOmkEd/1dS0ezdpDr6goszdVBruu4n9zpJuCcYzBC5cZtd5p7
+      g6gBkRdT9Q/V2/TECEcM9AmeT9i+u5vZ1Tf6rWNjoI9wo5gQ6KLcFhbl2v75MLlh/loLRb3UX22AqJP8
+      603StbJ3AEPwoJ+aGug+YMDH5FTB9wLrPv86ub9XJP2yDRKzctLaRFEv92JD10pPW4M0rPO7v2SyT+fL
+      tnnSpw4sZne3tMQIWsZEIyRRwDEmEiXhQhI3VpfK9GQzQMRJTZwThvjISdBzvXE+ub1OujeIxtpMxjHJ
+      v2TpK0nUIo6HMBN2/L5j0K+YkByagCzt4T7qTBO1f6A6GowwfBrQOPGIG3iYjGPKHmkpKL/vGsp0VWTJ
+      tqq/J4dSpNssWR2224yyVeKgyIm5zeUXKYcM2JRjawfW5SbZZc1TRUsPh3XM+jV3FZbkPFGObV+NP+7y
+      BLgOkR02FaPYm6DjFFlGSzQFeA5+HohgHogmbQ6039oihudq9L7J8qsWpy+OMJYxEMNjPrCi7Jjmgbbz
+      +HSKqjQ5y/i/yfm7i1/Uhg7qXIckff55QfACtGVP7heL5H4yn3yl9ZQBFPWOb309EHUSWmCftK3qReP9
+      97U4l8PbjHAMHcTa5lU+/knL8fuOochLdZ5XMv49ZwezfXq7ZFkP7knX1VOQjXInmpDtIs7hGIjr2aaH
+      oqHWeR5pW4mzQgZie7ZF+khKeg04DuJt6t+b5gkKhEMuADTgpRYyD3bdzbtkXTcJbT0SgALeDVm3gSy7
+      /TldJCHQ9YPj+gG5MrIoAyzbdN1UNT3hOw4w5j92e7JOQYCLWAkdGcBUkj0lYKH/MOhX7YXglvceBbw/
+      yLofnkXe/bTRmI2BPtk2J7LlolZJNmubc5FU+/THgXQTnCDbFXHyNIIjfvIBMzBt24ldJq+fpBKY3qr2
+      lG3rDirVPSi9gCO5m0zvk93jllTvBTRD8VSfMD7c0TIUTT/ti4zVOkZFuniDSBd4pLIqM24ExcLmtmv4
+      BqUBFA3H5OeRbxkZ7eJNonk5xTwzHYRBN6uGwk/A0p9SDtA8AZ5DXzZjNOGgsJcxDnBQ2Kv7vHW1I04i
+      oQY8SlPFxWiqUISGevYRCDvutrxwstQiQSsnQy0StEZkJyRAY7Ay08dtv+CPtERopCWYowiBjiIEo+cv
+      wJ6/4PVnBdafpawZO37fN+hOPLUNtEDAWacvZJ1kXNPfGc3yt9PmH/aUM8l6wrbQzkzpCcgS0S0EBWAM
+      To46KOgl5mpP9TbKKmZ7zbL6F+3wvZ5wLJTj906A4yAfwGdTjo12BJ+BWJ6Li18ICvltlyan74nxTMQ0
+      PiKeh5wyPWS7PvxKkXz41aXpaXNkPBM1bTrE83DKoMXhxo9Ftf4uuN6W9uz0vDxBluv9JaWcy2+7NDkv
+      T4xnIublEfE85LTpIcv14fyCIJHfdumEdqd0BGQhp7LFgUZiapsY6COnug16Ts4vhn8t45eCv5JTR1ic
+      Z2SlmZdes/svk8WXhNBinQjDcj/5Y3pxOsx+tMrGQB9hItOmPNvpmdNOPBKVJup51V6umequkbUGaVhJ
+      S7vcVV3tv6nbZdtUb1vOHxbLZHn3x/Q2ubqZTW+XelKPMArDDcEoq+wxL5NciENarrOIYLZoRMw622S7
+      PeXk2xGqYFz591w8vcWPdUxjor7Jz/Vc4ciEGgLBg35CjQHTQbuaBRB1HXkPGBY4mjqJfjqPudtsQzAK
+      N0cMPOhXBTImgOaDEZh53tNBuyrY2S4iQCsYEYMytA9KgrFU6dtlTaqmsiKLl6sajBtx7/gWOJpk2//g
+      lmtLAMdoT5U+zWYfk4ATDVHBcbOf+6zOd1nZJM/nnGiWYDiG7KTsVrFxtGRMrOdqX2/jo2kNHI9bJPCS
+      YC5l4phNHo7ArNysWu1hMZ23RyuTksDBQN/48ZEFgS7CT7Upw7b8dKmWiYzeUeIEOI79gehQQO/46+LD
+      h/PRO8e033ZpVSb2aV7TLEfKs3VPg/Szpq66IZoBgxHlw7vf/3yv3vtRmxC0j/8px8ZiPBhB7e8SE8Hi
+      wQiEd2NsCrMlaZGngudsWdRc5OM3BABQ1MtN3cGUbT9NxPcYucRBP/HtHp8ErZuLnGGUFGij1MIOBvpk
+      BcbQSQqzUTZv80nQml9wjJICbdyyiZfLtlDxfveJBc2k5S4uhxuT7Z4rlSjofdZrFkuGtiM9a3cin2wx
+      RLamzDRgvBdBVgjnjMJ1xCCfeoWp3KS1epOmyUo1LSboesgCRpNpd8gYfs3hxmRVVQVXq+EBd0K+Az0+
+      EIF+z1hswHxYP6U1261pz64rAEa1fuI8Y19oWBWIi3t+VVfTW7WOAm28O9wgYWtDeRfWA0En+/6w4YCb
+      nmEW65nbBZWMnl4Pes4u1TnF1kQBb5Osm59kpaZAG6e1P3G+URcM1s/uSduaTG4+380pL0DaFGSjHKVr
+      U6Btc+DYNgfYRk08AwN9lP2EHAz0cTICywfCvIRNgTbB+6UC+6V6EnbDM0rQdS6X89nHh+VUtkyHkpiI
+      NoubSfumgvCAO1m9Jrez66gQnWNEpLuP/x0dSTpGRGp+NtGRpAONRK4jTBK10usKC0W97ZuQhIl3jA9H
+      qFb/kq1dTIzWEI5COUQW49EIOffyc/yqybWiSaJWWSmdx+TpiQ9HiMpTw+BE0fsfTR7+ohd5i8SsxGw0
+      OMxIzUQTxJzk0YqDut7Z7SdGeh4pyEZNx5aBTOT06yDXNb+h7/jpk5iV+nt7DjOSf7cBAs6v0+WXu2ve
+      rzdY3My53h4FvOlm8y6ps+fqe7Yhm00Ydp+r8Tt1VsuDYbf6lKNVHGBsX1EUh7zJVmStCUNu4gioYwDT
+      Jisy9Woe46f3KOTNt1u6UUKgi7K1s4NBvgM99fx+nPor68ZE7kjdW5H9ULURN9lpwgG3yOo8Ldj2Fsf8
+      vDlhiMciFKloaAt8MR6LUMqLiInQ81gE9TZZ2hxqZoATDvuT+fTPuz+m1xz5kUXMnCqi43AjZ0Dq42E/
+      dRjq42H/us6bfM27rVxHIBJ93sGjA3bijLfLIma9RrFmiVsU8cZVBIP1gN6ugz7a8mjEHlfJDNYxfR1B
+      fWoLG5AoxNX0EAuYGV1ysDe+S5v1E1mlKcDG6SbD/WPGIPBIYTbi824LBJx6FB9xgzk8FiHiJnB4LEJf
+      iNPiseJFsR3DkciPrFEJHIu5uV9AgcRpq1/SbrgYj0Tg17FioI4VEbWTCNZOlE0NLAhxUR8HWiDkrBhj
+      BwUBLtr2BA4G+GgbFTiY4zvtok5+smiRmDXiaQniGBGJ2k1FHGgk6qjXIlEreQSM7evvfKgPvuJ0rGFF
+      MA65EvLxoJ8xqQ4J0BjcWyB0B1B7PMi5Bs5nIj5XxZhcFXG5KoZyVcTmqsBylTfbjc10s+akkfnom7u7
+      Px7uVS1DXrHtsqhZ/u0xq+l9ZNCARun6JozJMMSBRhIHeiHxaNi+bmrWtSsONlJOFHA5xEgtxwYHG59S
+      Ibt9ec2xHlnYTDkC1OVgI/W+6zHYJ54OzaZ6KTnSI+uY9Sri6e1yPpuSe1IOi5m/RXSmMMmYWNTuFCYZ
+      E4u6/AST4LGonTcbxb3kO9RhcTOrYwXw4QiMRhg04FFytj10T1DrBhvFvSJjX67ImqA3KjfFYG6K6NwU
+      wdyc3S6n89vJDStDDRhy64fAZVO/0s0nNOhlV56uYTAKq9p0DYNRWBWma4CiUB+MHyHIdXy+zctYkwbt
+      9IfaBgcaOW0E0jq06Ux/5OTCkJvX5mCtTbtYkfiQySIRKzfjTyjm1Vv0s+9o1zAYhXVHuwYsSsN8hgsJ
+      hmKwf0iDPsnVX1HjArpYUZgtqYoNz6hIyMpptOC2itXzQPocVZkVecm4mTsQctIH/z2G+ghH/PhkyEp9
+      9ubCkJvVh/N7b7K0T6/ad6PV23SNrJNokzaQAI6ha1L1B47/BKNu+hpwh4XN+eYnd44GNMBR6qyp8+w5
+      iwwFaAbi0Z+AgwY4SvuUh9FBAHgnwr06557cRzhRkI1a5x0h19UeYXt7d82ppjzatT985P3ynoONxE0Q
+      DAz1vWu3t2dqOzpkJx+uEVDAcXJWouRImpBL2AmDfYKXZwLLMxGVZwLPs/n93WJK3RXG5BAjY7cSl0XM
+      5DcqTTDgpK+V8OiQXcTpRdivH2lsuPqWDtujrv8kCMSgt0UeHbBHJE4wZZr6IPhXrWnETq9CTpxjVLtC
+      8Z5LWiRmJdbEBocZqbWxCQJO/epI2jQ1WXoiQ1bO+BkSDMWgjp8hwVAM6sQeJIBjcF8v8PFBP3nZLKwA
+      4rSv9TCOJcMNQJRu6pFVYg0WMtMnLXsM8hFb+I4BTKekZ2WeRQN2VsWH1HkRb4H4OOw/T7Jdmhccd4fC
+      Xl6ROoIBJ7cKdPiBCJwK0OFDEegdEB9H/BF1n40jfjlY4lRGPYp4+W8igAYsSjsfQu+AQwIkBmc9scMC
+      ZkbXB+z1cDo8cF+HPq9xojAbdfLVBFHnds90bqHWQ/DvARG6B0Rs6RTDpVNElE4RLJ3k1e5HCHGRV7ub
+      IOBkrCjvMc+n333kv2MOCfAY5LcpHRYxM9/m9nHMT+6vnTjEyOhZ9SDijHkbGXGEIqkNC9ap2vbtmvo2
+      U8ATitiuOr097FZZzY9nWvBo7MIEv/vrfMrr+EGK4Tj07h+kGI7DWuAe8AxE5HQ7AcNAFOr7wQCPRMh5
+      F59jV0zvC504xKhayTe4yX1NIF70Le5KnFiL2Wd63XuEABd5Vv0Iwa4dx7UDXMTS1SKAh1qqOsY1Le/m
+      U30WG+f5hkejdnrOWijq1e0GeYMSgB+I8JTmZVQIJRiIcahrdTLKmvgaBa4ZF4+xJULQFI5Kf+QHCQZj
+      6BQgdu5Ry0C0qsjXr0nDL+GuJhxPNFUdFUkLwjFk86se5BB3zMIkoVjnsffW+fC9dR5dxs9HlO3YHzL8
+      O/p7O6rCszTBeFldVxGp1vLDEeQwb988xcZpLeFoP+nvDICGoSiyoW1Xq8aFOmkG4u1l1ZE3XRUSFdIy
+      oVHJr6bZKOol92lMErXuD/W+Emq39ifZ/eReuGNBo+mlKbLxFcw4Jz4cIaYdFcPtqH6pmV/LHPGwP6K+
+      FIP1pbGxSESMzjAQhV97nfhghJh6WAzWwyK6ZhQjakb1nW2RPkbcFy0fjNDdpRExOkMwSpPvYkIoPOwn
+      r8EB+GCEdso5Wa8iopwcaKSu/6fO11l/Z0ayHGikv7O6YgZQKOhVM9vMOvCI4l7WIK8jUWtRVd9ZQ/ge
+      Bt3M0Ts6cjf2WudUByaO+7kt5MAosx1yyLxlXnkHB9y8vsOJxczc9f6QAI2hfhuzcJs47terjSICHPmB
+      CHq4t4kK0ioG4vTTr1Gxeg0ejz2/Z9Covd3aiJsrHR20s4fwtgCN0VZ/MXe2pRiMw77LTQMahfEk2oUH
+      3Ly+w+Ngv6GoUtUWtaWZk0S2AIzBG2diY0y9WSK3telhzB1Tp4qhOlVE1qlisE4V8XWqGFOnirepU8XY
+      OlVE1alioE41t8Xcp82TYMawHIFIvBFsePQaM+ILj/ZEVIsjBlocEdviiOEWR8S3OGJMiyOiWxwxosWJ
+      G3kPjbpjRsTh0bCIaSlFuKWMHWUPj7AZ+6GaoONczh8W5NPUewq0cepHiwSt5Cf7PYb66IshHRYzM95j
+      c1jUTF9n47ComV5rOyxqpt/HDguaqW+WnSjMxpo59mjH/ueEcT7LEQJcxEcZf0K7Rak/UnvDHeOapvPZ
+      p2/J/WQ++dqem8R4HIVJBmM16Yq4VyTiGIh0njxVxAIMK0JxVOVXM25CTBKKRS+QLh2yk6tqjx6y0ytu
+      WDEYZ59l9RvEOmoG4jEqd1gxFIfe9YcVQ3EiSzPWslhf4jzghQShGIwpdoAPRSBXxw4ccqvZBr5c0UN2
+      xot+iGMwUlxNfFIMxsn3kVHy/YgYSSrW0XGUZDBWXC12UgzG0U13nonIWEfNQLzYmkyMqclEfE0mxtRk
+      6kuqbL5BrJNmKB5nAI9JhmKRH6CDhsEo5MEGrAjF0Z1G1kAX1zjx2G+ABd780h/VmX6Nj7HJrY9Dfp14
+      bL1J+3byW0Dwe2p69396N7XHQB+5me0xx6fXOPFPbvVx0M+YSTJBz6nCpd+J0x49BvrWKcO2TkEXvY9i
+      cKCR3BfpMdBH7HMcIcRF7luYIOykP8sJPMGJ24VkaAeS7nNG82aRoJXexBicayRuFe3vEi3/clrcTW5i
+      XRhws5yAi/lWMPo2MGMXGHAHGOrbxP5bxLqGoE+q9Jjjk/+1MU53SeW/GKfEoBYkGmeZkMO6ZmqKAGmh
+      50/SQ/NUyTH6K+fxHGgIR5HVCXX+HjSEozDyFDRAUZjvnYffN2/nzapmsm04eXAkEevHbEt9x8lGIW+7
+      J0ayyhvRMC7ZwiE/+wXZoXffI/ZnCu7N1H7Y7eXBLec2D0VoVkJdQlo80u09C5kP+YZRphXl2zgTV+ju
+      VPqDai32dJ2ifFtibH5KdZosYD6uENHLhNI6S8l+zzAUhXpcFiQYESPJyufoOEoyFIt8ThloGBMl/icd
+      LYFox550TDYZDiAS520T/O27qHfuBt604+w3Au8zErG/SHBfkYj9RIL7iMTuHzK8bwh/v5DQPiHc/UHw
+      fUFOG9Ztso1u5w4ifcw4ckeBxdH7PtKnfgEeiMA9R/sxeIa2+pSfNKEU4XYyA31Mfhcz1MPUayyLrCQ7
+      Ow4y0neAQ3dAfIzZw+UxvHdL3M6KQ7sqRu2oOLCbIncnRXwXRbXtC7vQ7gKldscvtju83O7U9EySbv5F
+      c54wx+fNMJBntUADHEXlJ9d/ZANm8jFMLjzgJh/KBAncGLSG1FvrIOuNfEN/HtJjoI/8PKTHHJ9+ueP4
+      RgO94+3jqD/CjXr5lwxfLXWpiL86RA03ZUrTN1k1Qce5T2uRJdu62iWrw3ZLrAU92rW3++ToaXSa2ABh
+      Z5E9Z8VxJmmTceyOIhRHfc7o+yIOOJL+3NjNiBPJdQxGoi/7RBxDkX4c0iLf5rIZjovWe+CIak8m+gy2
+      Cwfc+ip0jrIj9IqhOKxlOahlKNpBNuJvFNJSBeK2twb7znIdbiRyVQnWkZx9qJE9qLlH/+Gn/rF2tEZ2
+      s+7mzRmP6CzSsXZrT/QiZ5LUBB1nu7KN03O3SMTK6LnbKOTth01p8VjR5TYfjvCcFocsJoQW+DFYs4H4
+      jjMiYo5DBOc4BHc2QuCzEYI9GyECsxHM3ePRneOj9n8d2Pc1akf6gd3ouTvR47vQk3egB3afZ+08j+w6
+      399dmwNxIGyjqJfe3jmsazayizx4d+GQmzx89+ghO3kADxq8KPt9Vasdj05zucQYHu9EYM34IPM9xz9T
+      uzIG5xqr5HgwAs3Yc65RLySldxUMzjEy1kuCKyUZ7x6Dbxwf3xOmblZlcLix211TNPJmfuTqLYkdK214
+      59mZHG5kPG8D8LCf+NwNwMN+4hl2AO75mSey2aRn5ZzIZWCoj5eJwbO4nM/pWRg8h8v8nDwQ9WDb/fye
+      s/69pzwbbzWmBXpOxnPznsJsjGLgwSE3sRB4cMjNeYYOG9Ao5ILmsr05vciTz9Pb6Xxyk9xOvk7HWl3O
+      Ns7uJTyfLhYU3QlCXMntFUsnOcO4ypMmk639Kt0kh/JFrWVtsp3sSKX16PY5KAnHeqmr8lF2EB5zQRhc
+      DpuAqOuiWslRWFKfvyPHMdig+TzCfB40X0SYL4Lm9xHm90HzLxHmX4LmDxHmDyHzJV98GfL+zvf+HvKm
+      P/ni9GfIvNrzzat90BxxzavgNa8jzOugeZPzzZs8aI645k3wmkXENYvQNf/c7fhVqILD7vMY9/mAO+rC
+      z4euPO7Sh679Isp+MWB/H2V/P2D/Jcr+y4D9Q5T9Q9gelewDqR6V6ANpHpXkAykeleAD6f1rjPvXsPu3
+      GPdvYfdljPsy7P49xg31IPRAW3ab292SNnmdrZvj6llyrJAMiK13nIiL6CuAOE2d7tSz7TIj+3sU8HYj
+      jjprDnVJVls0bhdNOn5SE4RD7mrPV1dm7y4T5xeXj+udyJ8T+Y/k++i1DgAa9CZZuU5+nkfoOwMSZZOt
+      WW7JIcZsvdIhV0U1fskWbsCiyM934jH5+QsvxAkf8l/G+S8R//fNliWWnGW8+PArtxy6aNBLL4eIAYlC
+      K4cWhxi55RAxYFE45RDCh/yXcf5LxE8rhxZnGZN1U+v2ibAKwcFs39NLsl6t1Q+oX/cNRWmTvrWp318c
+      P23zVlD1gMKLI0sm48o7yrN1ZZFhNEjfyjMitnZPrTZRiMXAp0H7Mcl5doO27WXFL20uC5kjSxwqAWIx
+      Sp3JAUZumuDpEVFOIB6JwCwrEG9F6CrAJ72H16+kwxFhGrdHyYfcsqP/+jz+CRXGQxG6j5Knqi4JzzcQ
+      3opQ5on8EqOY2yDkpBd0GzScojxPNlWSbkbv32Ugjkc14ZTV6BYEuEhlyoQAV52Rjid2OcAo0me6TkGO
+      6zGTJSct8r+zjV581FTJ+EPdcYMXRR0fUuXrTFYZhRyXjz+3EeOBCNs8KzbJvqG7TyRgbRfndFsRbqta
+      j3cJa34GRU7MXLQLBClbd3ug62yyXbKudiv5F/pN4tGOvc62+kG5qjT0TI+eEaCcPTigweKp5qcqM16U
+      DnbcIrKkisGS2rzuu0XfSSpzrJI5ltFigAYnyqFZM+9ni+ytqyw7JLtqI6s4tQZYXUBN2fgM440IedXN
+      EQrZaaOe7wrTtn27ScRTdSj0/Nr4FQwAanvVjoCyvKoFpirZugtQf0o3G9IvCJvsqOpDehr1lG9Ta+fl
+      f1N1HWb4yiRVWxQdVrLaKEVDKicAa5s3m+SlqsfvcWQylmld7V/Jqh6yXBvZHeP8VouzjNnPvcx3gqoF
+      LMc2b4S84cg/0uJso3oDdVeVzWO1ywi3kEeGrInYpUXBd7e8FeExbZ6y+gPB2RGWRSZJnZaPGTlBbdB2
+      CrV7mm44yFYHdb11VqRN/pwVr6pnQCqXAG3Z/5Wuq1VOELaA5SjWO9Y9Y3G2MRMiaZ7S0iwMc4oaFCAx
+      qNnlkJZ1lxeFXnYjO1mkoQfEBsyyp0A6AxAVODHKXN5yyUu+Gb/ZvMvZxmrTnuvMKB8eC5qpuWdxnlFW
+      vskqld2aC/YlQwowjiqa5CrShz131zN7197u/DCoB4vITjKPRyNQ6z+PRc0iW9dZExXAVHhxCvGUb9Uh
+      1sw08ngkQmSAgH93KGIad0zhxeH2Nz0WNHPqixPnGQ/nv7Kv1WIds7zVyncknyZsi0xsVg1pcp5RTSCk
+      vxB1LQS7LjmuS8DFyAWT84wqTYkyhYAeRsfVRT0v+QY8Mp6JU0L80lHJMlPql6BVt7NaPefVQchep8yw
+      fSVkj4MQYdBlRy71PAdrPOOxlnlfvdByrQUsR63G/bzxhov63q7N0d+hik3WNmebwzqTSbMmOXsKs6kB
+      1L5IudoT7vhF/jcjbQ3M9nUtLVlocoDxmN76H2SvRUN23uUCVyvWadPQSv0RsT164pR8XSbm+Br2CMVj
+      PbNo5HhozbhaG/W8HCFg+lFf/kz0DHGZUip9G3Sd9Na8h2DXJcd1CbjorbnFeUZqa3liPBM5R4+Ma/rJ
+      ztKfaJ4yerhw79ZqE8mpB9CW/cCdFDjgMwIH7sDhgI8aXsjTty/e/G2lnhcKofY43KtjsIqtfiQ22onw
+      fYT1RZ5MFrfnycfZMlkslWCsHEAB7+x2Of08nZOlHQcY7z7+9/RqSRa2mOFbrfRQRc1wlqNXa9qUbzus
+      xUWyyqi6DgN8zfY9S9hxoPGSYbu0TepptvprQtjX2eVMoz4zjpwXJuXbyHlhYYCPnBc2BxovGTYzL55S
+      +b8Lve3g6/n7dx+Sak/IEZAO2UU2vr2BacOulgJVel3QulDjwqxUCxdG15gY30fYqJv/6kq91H49XVzN
+      Z/fL2d3tWD9MO3Ze3bkJ1Z39h1/vudojCVnv7m6mk1u6s+UA4/T24et0PllOr8nSHgW83YYJs/+dXi9n
+      4/dawHg8AjOVLRqwzyYfmOYTCVlpLeoGbVFPn9w+3NyQdQoCXLTWeYO1zv0HV8sp++4yYcB9L/++nHy8
+      oZesExmyMi/a4YEIi+k/H6a3V9NkcvuNrDdh0L1kapeIcfnrOTMlTiRk5VQISC2w/HbPcEkIcD3czv6c
+      zhfsOsXhoQjLK9aP7zjQ+OmSe7knFPD+OVvM+PeBRTv2h+UXCS6/yUrt013XSJMCQAIsxh/Tb7Nrnl2j
+      jvfQVPftIVB/jF9v75O29eNkMbtKru5uZXJNZP1BSg0Ptt1X0/ly9ml2JVvp+7ub2dVsSrIDuOOf3yTX
+      s8Uyub+jXrmD2t7rL/u0TneCIjwysCkhLI1zOcc4m8v27m7+jX5zOKjrXdzfTL4tp38tac4T5vm6xCXq
+      OgqzkTbPAlDHu5jwbikLDDjJGe/CIff47cQh1jcfVkW+ZiTEkfOMxPMVbQqzMZLUIFErOTF70HcuZp+p
+      Nol4HkY1dIRs1/SKcVUnyHXdqwhZQzglwuU8I+smNDncSC0vLhsw08qMg7pexs1yghAX/aejd0r/EfVH
+      Y/fJ9Hp2P5kvv1ErdJNzjH8tp7fX02vVe0oeFpPPNK9H23bO7o0bdPdG95MFV+n0XWaLxYMkmO2vT9v2
+      2+lycTW5nyaL+z8mVxSzTeLWGVc6c5x3y5nsQE4/kXxHyHbdLb9M59RsP0G26/6Pq8X4/bZ6ArJQb++e
+      Am20G/sE+a7fqJ7fAAfnx/0G/7ZLfmMA4GE/PREvA62C/lxN7PypayU15iTrbXzQz0ohXzEch5FSngGK
+      wrp+5Io51+hdlRq7fiNn3YmCbP98mNzwjEfSsc7v/vqmB9xtyuq2cEF85IFKoFjt1dD1LecYyR0nqNfE
+      6zJh/SVWZwnpKfF6x1jfOKIyDNWD7CowUPtxBqTIaHTOHenP8ZH+PGakPw+P9OcRI/15cKQ/Z4705+hI
+      3/yEkwwmGzDTE8FAPW9yv1gkciAx+bogag0SsJLrojky4zFnz3jMAzMec+6Mxxyf8XhYyJ6u7jpThD1l
+      29Q++hSP+r5vSCY3n+/mVE9LYbYFT7eAfMvlfPbxYTmlK48kZH34i+57+Asw6VacozuCkFP2Cug+CUGu
+      +Q1dNb+BTeR+tQUiTuI9a3KIkXa/GhjgY3XwbDJkXfC10N1CHXufIMSVTG+X828sY4sCXnrFb2CAj3Ba
+      l8nAJl4JP4KIk1PCOw4xMkp4i4G+P+/+oC0sMjnASJw+PzKA6c8JvfaSDGDi5AGc/oy0t9JdpIneA2aX
+      jX9JwoJslz5UPNnTnzQAbG/O1snnT92LzOlm9IJBB4N9m1XB8UkM9m2zItt1x7a/NuOPeg45QpF2h4If
+      QsIht/hR890SDrmbKjZ9jgY4ymNdHfaJ/HM+/vRLjA9FoOzcANMhu95c6lCP3/ktoIDjqCtI9nWmXpfk
+      BDF5OAKzhKJlUy39VbsmMKWaDZmb9RNfLWHcHZHMBh7w65Fz3E8wHV4keTM06vzOdbXJ1Jt8RVqr/Wio
+      NzGm8eKJfLcv9AG3yc9kXVX1Ji/ThprziAWLFlmDI5ZwNGZtCDqwSBE1ImAIR3lk1luwJByLUQN7fDiC
+      eItfI4Z+jd4bhPlLWhY1iyRVNbXKueaVGcFyBCJVZUxaGQIsht7+UO/KxgvR8+EI/HLV8+EIqkjIuzYu
+      Y0BVMK5Ish+HtIgI1xmsKOlW/Ve361dakmOAPBShfeubbm45yCgT7hiWrjVg200dVpmMZVrlj+VB1++6
+      oif4HBKxti0wS9uiljeisQ620Krrc2iy5OV28oniNDDL1zaatOHkiQFM1PJuUICN1f0I9jnaD8vskSyU
+      DGSS9bTaqjfZpeI73WnSgJ18k5sY5Dus6LLDCjCpbpYu/2TfiUSsrNwGe32q52TeSGrXYKoedQxGItcn
+      uMSOpftRZfZCUR8Zy/SUiieVcrqfkezfX/6S/Nyp/X7TD+cXiRAvh2RTp9vm3W+EUOOl4LV04yCX419H
+      WGhdA3MSAB37nxpxeRltM0mw+vCAmzzgxRRWnP337JXafp8Y26R7aLpaPpQqrepMiIzS7iAGIIreuYt6
+      /7lo0EudewH5oQi0/IQF4Rj00o4pBuLo+ZSoMNowJkp8wqGzP8dRBrFVNjHQ1xxvwL72Fww/pAHiMVpZ
+      G7Sdbf4zUsUCLafaba3S3SPdOyLfyiBvRehymtbx7SHIpTux1OMBEBzyszrDHoua6ZsBogIoRl4+v4uK
+      4QjAGIJ0+oYHQk57B1a62uahCLTBSA9BrnbvP7qu5SAj+ba2ONBIGoT0EORiVGUOiVhjshzZHRP5girY
+      /FoDVdlx23kxkW67qStKIJe1ze18WPxNHvIEIr5JUo4zmlehntQLOYpNXvLmSbUz6/Zoo+9l9VImaSle
+      spq0aRlBaV5H+xTp74sPvybp88+L016QhJESqkDiUHf6BWHETaoKbQ4xyn5Q3BWbgkAMtWdhVIyjAInR
+      dsBI3RWIHrKTx6kBSTDWpjoQzvlCBUiMYxn+wApwogfsv0XZsfsrqiQBpWhz8eHD+f9v7Qx63MTBMHzf
+      f7K3DrOjbq+rvVSqtFJS9YoIOAlKAhSTNNNfv7aTAJ/9mfB+zG008DwODnbAhtdfBAPxPhg68cEBHxyc
+      NtBs5wZtTC8010cgzuUi0nCbwzifXf0T11mKs2mt1Suuc5jnM5+3g2vuAXEuvOYGjPPBNddTnA2vuQGj
+      Pjd6B1bcg2FMcLUNFGNDK62HGBdcZQM12MokW5AtyNOeXZatx6CMF0yR8znGiCW/eRjjw5JxPGzsy6Up
+      jQzKeOGazKM1WSw6o4onZ1Qhr4diqh4KYVplSHJWLK3S5xijpEUVUy2qWJRWGePjJQhrOZJW2W+H0ypD
+      krOiraOYah1oWiWBGBfaZxWxPquQp1WyMOOG0ypDcsoq/NDRtMp+D0laJQuz7u9C7feIEU6rDEnOKukQ
+      Ir0AklZJIMYlTKuM8VwJWFqlz7FGNK2SQRmvKK2Spz37krTKqCBWBpRWyaDUK86VZGHqXpArGcE9vyxX
+      kkGpF82VHDO8CXn/y+c8oyxXkkF9L5wr6WGBD8y1olTMBr1jyqCeV5I2EYATTviLj6dNhJvnvwrIsaEZ
+      TZvwucAIvmxLqZhNUKVsyoK3Da5MLmXhsQl4BXWEBB5BNxTmStp/w7mSBPJdeK6kzwVGUSPkcyX9Lej5
+      Es+VDLZi50w0V/K2UdBYmFxJ8m/80KMtRZIr6XOeUZAr6XOeUZwrydPULsmV9Lm4cS1Vetcu8lxJnqZ2
+      Wa5kSMatX6XSr54TzZUkEHXBuZIEoi4sV3IgOAvavLlcydH/sYbN5Eo+/v0Z9XxmHJKD+8wf2yi58Wu1
+      rSVmRvG8HLxCQ8NkKQuP5OlRLDuCp5++KoulR3BXPC9n2ZHcDEwpsszPCP7UL6qtqczP2E6C2prI/Bz2
+      EX3+yCeWfMbgU8GZn5TibGjmZ0h61qWZn5MSriws89PnPCN8Uctd0couZ2PXsqIL2chVrOzOJXbfsqBr
+      n+rVxR36RF8uGSyIjBSspKMwq/gozGrJKMxqehRmtWAUZjU5CrMSjsKsoqMw0sxPjp0w45XAZn7eNwoy
+      P0OSscJ90SoyGrUSj0atJkajVtLRqFV8NArP/KQUtSGZn4/9QwOW+UmpmG0t0605H5r5GZKcdX5I55hh
+      TGjmZwByTiDzk0Cca/UNV62+8Sb4ujqS+Uk2gW2Wz/wkW7D2ymZ+kg3dRouEhmOMokvGWIpouG0t13Lt
+      Dx1pYVJEyb+xFFEGZbz4TwmbItpvAFJExwxvkrWZMEWUbJK0mSBFlGwRtBk/RXS0AUoR9TnGCE6WhCmi
+      /X+BFNExw5gk3wFf/4K6Z+td0k8FfVSrxB2fh/Jee9YIvXeU9wqdnq+2E0P4RT/Bxj4tfwpSTz0FGWxM
+      wYfVIgKmDPiZQh19plAveW5PTz+318meMexizxhe5M/vXqae370I564u0bmri3Tu6hKbuzr8U7dltTN7
+      m5uZ9c+2+/5rdl/HsdPmb6paIjf4yP9foyq7WWW6rtad3fvfrMtmFxDhYyX8yI7n+W8Bc+y0GakbHh/8
+      R3VRR/eeXFUXs1+Bo5RvM39KdD02+E7FX+nmWOeHtDD1bV9NVLOTFzh2bH67b830SWTn+aGE+rZQJfq7
+      4WGDrznk+iVJy061WVfWlU6zPFdNlwGvLk45gpLsa3G7+acapQJbs1GpqvL2vcFiHCM49X9256J9YVkV
+      7stA7AHsu5us1Srdqww4P0KSWv92R1Qod0SIlIAj52nT1QdVperavJgz07Sl2dYQjXnzY6mqzn3HeADI
+      DFWsXHNC2TNW2d1lxY0N8VK6dO9ec7dvtptOXlqUp4mVV2p9Vu2H1CaripXbmvNRVowlY1bbgGRWS8as
+      52rBuXyHeXcibyVJOun9sFaSIK0kWdxKkhmtJPmYVpLMbSXJx7WSBGklibiVJBOtJBG3kmSilSRLWknC
+      tJLaXHu8p3mW79Xtqgz6SWXpmL1VSiY2YMSpVSdSGi5uTE9Z0yAne4QPSnCXjoJq6DneCERyeljgs5fk
+      LgcYd45R3is48p7jjSckcC8AifM9Xf1E1soYIYPHxr/Zfu5gGprLLdqct1tl7yHNBa298J7dbJ+bRqVK
+      VhFq+VWE2mEloFsWIfD7wrHUbP7MbBwCeC3MoLy3uU3mp52pPm1q7yQpIZDwZbnIpDb7JSniwcbMv5XM
+      +ltRI5yTQiDi+p2+fEr+SndZt1ftm0tsAqQMzdlt3pHM/CA5a2W+w6Q1N3wyNcE5v9mW2J2EfoJzfp1n
+      XSevdIKz/p+tVH0nB6tOStGosc8xRsmoMQuP3PvsRTzoxMLEbYORFtg5nPhtnvQCP4eP/ObfSjXQSh9j
+      xjMd1fy1CHqAcaRN18IeC1HXuUEk54bQW+D6+7475YELofvuhC8rDSxV0wPUoVNdt51CDqRniAm4VLzt
+      7dNpdT4eMYVDqGf+igC3vQnd1Mj5YPb2afQ7fSCsx9yrCVSGorbz/IWm7rsTHri3uu3t0+5uYHuuckzT
+      Y9S3L7fQ57H7U0MNtRm7O+EvdkYFELj9iQHJCL7vPvCd/YrdPfb89T7GzGC6PH4U8blNBqVeydymz8WN
+      a6lyHXcCjY1BR97XNLNXzuXsHnUgqOXYIYZjR+hNXlca4N3+xJCbW1vE4PanhvZo82sLYPkhSgU2oHcf
+      iMDSuplRUHSDfFeBWeg3bC5KzPWW+Tcg6RliUtcuPZwBzQ0gDvPbofdKd+AHGmPEVxYNoDF7U7ra1ghu
+      dvf4fbmxKYnVO/QxRhjx2QZ61tkOOZN7hpiq7GQXSKh012Z2ETdA6KPUq9Mye0uPpUb6jRHl2XLg2rIH
+      iKPOdWNnm80ZgnwHYyz0VbUbW0J9d4z4mrwENGZvSt+He0XfZAhz7vsAskD8IIlVg41KB61Kw79sOvhl
+      q5t2K5iM8znWuGga7pmHLVEyARfBWf+iqbBnHrZEZBLMw1gfMv3lYawPnPgKyZG1yZRO803+eM5kttQH
+      A2fXvib90ytudEWDcsbglwKOnxPId4lqIHL09u7tXgzULjiYcz9qReQewYP7Kgwpv0Yzyu9bdgoJzScQ
+      57Jt1zVddJmJCQVXTvPSvNiVKJoEL2BgJ82vC8yvrPnVrftnp18FFT6mOfttdQ6b4o27B3baDC3qFhU8
+      KUOfsuMRXXjtuYktdf5KOwTiXF0N/fQFYOCEJ8Wu0bUD7lt0Dq5/5HMj49unLz9e3VOKbvzo1sNo9xzy
+      bPuEg5aUFuXO3sK5+cjsuKvbstufkHJ4A1/KRbXl9h16IjSCe/6mtQtzuLlLrVMspy0q8Mpwk9vd1fVC
+      GrNTlPHaQm0f1F1h74BSrx0ZSsq0bJAfIY8LjLdfD1PcXl1B6RgNvLcnZ9S1U5UugeGrCB74TZnwgl0M
+      GniPdX3Q5hb6oNLC3E/bu3RQzxiCUm43/0CXTbE///gfum2ePjmiBAA=
     EOF
 
     # We are renaming openssl to openssl_grpc so that there is no conflict with openssl if it exists
index 4224f45..5131114 100644 (file)
@@ -26,6 +26,8 @@ NS_ASSUME_NONNULL_BEGIN
 
 /**
  * Immutable user configurable options for a gRPC call.
+ * Caller can obtain a mutable copy of type \b GRPCMutableCallOptions by calling [option
+ * mutableCopy]
  */
 @interface GRPCCallOptions : NSObject <NSCopying, NSMutableCopying>
 
@@ -80,8 +82,10 @@ NS_ASSUME_NONNULL_BEGIN
 
 /**
  * Initial metadata key-value pairs that should be included in the request.
+ * Dictionary key is of type NSString, value should be either NSString or NSData containing binary
+ * bytes data.
  */
-@property(copy, readonly, nullable) NSDictionary *initialMetadata;
+@property(copy, readonly, nullable) NSDictionary<NSString *, id> *initialMetadata;
 
 // Channel parameters; take into account of channel signature.
 
@@ -211,6 +215,7 @@ NS_ASSUME_NONNULL_BEGIN
 
 /**
  * Mutable user configurable options for a gRPC call.
+ * Caller can obtain an immutable copy of type \b GRPCCallOptions by calling [option copy]
  */
 @interface GRPCMutableCallOptions : GRPCCallOptions <NSCopying, NSMutableCopying>
 
@@ -271,8 +276,10 @@ NS_ASSUME_NONNULL_BEGIN
 
 /**
  * Initial metadata key-value pairs that should be included in the request.
+ * Dictionary key is of type NSString, value should be either NSString or NSData containing binary
+ * bytes data.
  */
-@property(copy, readwrite, nullable) NSDictionary *initialMetadata;
+@property(copy, readwrite, nullable) NSDictionary<NSString *, id> *initialMetadata;
 
 // Channel parameters; take into account of channel signature.
 
index cb91633..930b301 100644 (file)
@@ -25,7 +25,7 @@ static NSString *const kDefaultServerAuthority = nil;
 static const NSTimeInterval kDefaultTimeout = 0;
 static const BOOL kDefaultFlowControlEnabled = NO;
 static NSArray<id<GRPCInterceptorFactory>> *const kDefaultInterceptorFactories = nil;
-static NSDictionary *const kDefaultInitialMetadata = nil;
+static NSDictionary<NSString *, id> *const kDefaultInitialMetadata = nil;
 static NSString *const kDefaultUserAgentPrefix = nil;
 static NSString *const kDefaultUserAgentSuffix = nil;
 static const NSUInteger kDefaultResponseSizeLimit = 0;
@@ -68,7 +68,7 @@ static BOOL areObjectsEqual(id obj1, id obj2) {
   NSArray<id<GRPCInterceptorFactory>> *_interceptorFactories;
   NSString *_oauth2AccessToken;
   id<GRPCAuthorizationProtocol> _authTokenProvider;
-  NSDictionary *_initialMetadata;
+  NSDictionary<NSString *, id> *_initialMetadata;
   NSString *_userAgentPrefix;
   NSString *_userAgentSuffix;
   NSUInteger _responseSizeLimit;
@@ -155,7 +155,7 @@ static BOOL areObjectsEqual(id obj1, id obj2) {
                    interceptorFactories:(NSArray<id<GRPCInterceptorFactory>> *)interceptorFactories
                       oauth2AccessToken:(NSString *)oauth2AccessToken
                       authTokenProvider:(id<GRPCAuthorizationProtocol>)authTokenProvider
-                        initialMetadata:(NSDictionary *)initialMetadata
+                        initialMetadata:(NSDictionary<NSString *, id> *)initialMetadata
                         userAgentPrefix:(NSString *)userAgentPrefix
                         userAgentSuffix:(NSString *)userAgentSuffix
                       responseSizeLimit:(NSUInteger)responseSizeLimit
@@ -486,7 +486,7 @@ static BOOL areObjectsEqual(id obj1, id obj2) {
   _authTokenProvider = authTokenProvider;
 }
 
-- (void)setInitialMetadata:(NSDictionary *)initialMetadata {
+- (void)setInitialMetadata:(NSDictionary<NSString *, id> *)initialMetadata {
   _initialMetadata = [[NSDictionary alloc] initWithDictionary:initialMetadata copyItems:YES];
 }
 
index adbfba8..7e43baa 100644 (file)
@@ -22,4 +22,4 @@
 // instead. This file can be regenerated from the template by running
 // `tools/buildgen/generate_projects.sh`.
 
-#define GRPC_OBJC_VERSION_STRING @"1.41.1"
+#define GRPC_OBJC_VERSION_STRING @"1.42.0"
diff --git a/src/objective-c/Libuv-gRPC.podspec b/src/objective-c/Libuv-gRPC.podspec
new file mode 100644 (file)
index 0000000..ef1a58d
--- /dev/null
@@ -0,0 +1,151 @@
+# This file has been automatically generated from a template file.
+# Please make modifications to
+# `templates/src/objective-c/libuv-gRPC.podspec.template` instead. This
+# file can be regenerated from the template by running
+# `tools/buildgen/generate_projects.sh`.
+
+# Libuv CocoaPods podspec
+
+# Copyright 2021, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+#   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Pod::Spec.new do |spec|
+
+  pod_version           = "0.0.10"
+  libuv_version         = "1.37.0"
+
+  spec.name         = "Libuv-gRPC"
+  spec.version      = pod_version
+  spec.summary      = "gRPC-Only Libuv Pod"
+
+  spec.description  = <<-DESC
+    Libuv pod intended to be used only by gRPC iOS. libuv is a multi-platform
+    support library with a focus on asynchronous I/O. It was primarily developed
+    for use by Node.js, but it's also used by Luvit, Julia, pyuv, and others.
+  DESC
+
+  spec.homepage     = "https://libuv.org/"
+
+  spec.license  = { :type => 'Mixed', :file => 'LICENSE' }
+  spec.author    = "libuv"
+
+  # When using multiple platforms
+  spec.ios.deployment_target = '9.0'
+  spec.osx.deployment_target = '10.10'
+  spec.tvos.deployment_target = '10.0'
+  spec.watchos.deployment_target = '4.0'
+
+  spec.source       = { :git => "https://github.com/libuv/libuv.git", :tag => "v#{libuv_version}" }
+
+  name = 'uv'
+  spec.module_name = name
+  spec.header_mappings_dir = 'include'
+  spec.header_dir = name
+
+  spec.subspec 'Interface' do |ss|
+    ss.header_mappings_dir = 'include'
+    ss.source_files = "include/uv.h",
+                      "include/uv/errno.h",
+                      "include/uv/threadpool.h",
+                      "include/uv/version.h",
+                      "include/uv/tree.h",
+                      "include/uv/unix.h",
+                      "include/uv/darwin.h"
+  end
+
+  spec.subspec 'Implementation' do |ss|
+    ss.header_mappings_dir = 'src'
+    ss.source_files =
+    "src/fs-poll.c",
+    "src/idna.c",
+    "src/inet.c",
+    "src/strscpy.c",
+    "src/threadpool.c",
+    "src/timer.c",
+    "src/uv-data-getter-setters.c",
+    "src/uv-common.c",
+    "src/version.c",
+    "src/unix/async.c",
+    "src/unix/core.c",
+    "src/unix/dl.c",
+    "src/unix/fs.c",
+    "src/unix/getaddrinfo.c",
+    "src/unix/getnameinfo.c",
+    "src/unix/loop.c",
+    "src/unix/loop-watcher.c",
+    "src/unix/pipe.c",
+    "src/unix/poll.c",
+    "src/unix/process.c",
+    "src/unix/signal.c",
+    "src/unix/stream.c",
+    "src/unix/tcp.c",
+    "src/unix/thread.c",
+    "src/unix/tty.c",
+    "src/unix/udp.c",
+    "src/unix/bsd-ifaddrs.c",
+    "src/unix/darwin.c",
+    "src/unix/fsevents.c",
+    "src/unix/kqueue.c",
+    "src/unix/darwin-proctitle.c",
+    "src/unix/proctitle.c",
+    "src/heap-inl.h",
+    "src/idna.h",
+    "src/queue.h",
+    "src/strscpy.h",
+    "src/uv-common.h",
+    "src/unix/atomic-ops.h",
+    "src/unix/internal.h",
+    "src/unix/spinlock.h"
+
+    ss.dependency "#{spec.name}/Interface", pod_version
+  end
+
+  spec.requires_arc = false
+
+  spec.pod_target_xcconfig = {
+    'HEADER_SEARCH_PATHS' => '"$(inherited)" "$(PODS_TARGET_SRCROOT)/include"',
+    'USER_HEADER_SEARCH_PATHS' => '"$(PODS_TARGET_SRCROOT)" "$(PODS_TARGET_SRCROOT)/src" "$(PODS_TARGET_SRCROOT)/include"',
+    'CLANG_WARN_STRICT_PROTOTYPES' => 'NO',
+    'CLANG_WARN_DOCUMENTATION_COMMENTS' => 'NO',
+    'USE_HEADERMAP' => 'NO',
+    'ALWAYS_SEARCH_USER_PATHS' => 'NO',
+    'GCC_TREAT_WARNINGS_AS_ERRORS' => 'NO',
+    'GCC_WARN_INHIBIT_ALL_WARNINGS' => 'YES'
+  }
+
+  spec.libraries = 'c++'
+
+  spec.compiler_flags =
+    "-D_LARGEFILE_SOURCE",
+    "-D_FILE_OFFSET_BITS=64",
+    "-D_GNU_SOURCE",
+    "-D_DARWIN_USE_64_BIT_INODE=1",
+    "-D_DARWIN_UNLIMITED_SELECT=1"
+
+end
index 73f0cb7..a080aef 100644 (file)
@@ -14,7 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-licenses(["notice"])  # 3-clause BSD
+licenses(["notice"])
 
 package(default_visibility = ["//visibility:public"])
 
index e61aacd..e1f72e9 100644 (file)
@@ -17,20 +17,3 @@ target 'InterceptorSample' do
   pod 'RemoteTest', :path => "../RemoteTestClient"
   pod '!ProtoCompiler-gRPCPlugin', :path => "#{ROOT_DIR}/src/objective-c"
 end
-
-pre_install do |installer|
-  grpc_core_spec = installer.pod_targets.find{|t| t.name.start_with?('gRPC-Core')}.root_spec
-
-  src_root = "$(PODS_TARGET_SRCROOT)"
-  grpc_core_spec.pod_target_xcconfig = {
-    'GRPC_SRC_ROOT' => src_root,
-    'HEADER_SEARCH_PATHS' => '"$(inherited)" "$(GRPC_SRC_ROOT)/include"',
-    'USER_HEADER_SEARCH_PATHS' => '"$(GRPC_SRC_ROOT)"',
-    # If we don't set these two settings, `include/grpc/support/time.h` and
-    # `src/core/lib/gpr/string.h` shadow the system `<time.h>` and `<string.h>`, breaking the
-    # build.
-    'USE_HEADERMAP' => 'NO',
-    'ALWAYS_SEARCH_USER_PATHS' => 'NO',
-  }
-end
-
index 3c2b09a..db5d8ce 100644 (file)
@@ -70,5 +70,5 @@ Pod::Spec.new do |s|
     # This is needed by all pods that depend on gRPC-RxLibrary:
     'CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES' => 'YES',
   }
-  
+
 end
index c1ae381..2dcd091 100644 (file)
@@ -23,29 +23,10 @@ target 'Sample' do
   pod 'Protobuf', :path => "#{GRPC_LOCAL_SRC}/third_party/protobuf"
 
   pod 'BoringSSL-GRPC', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c"
+  pod 'Libuv-gRPC', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c"
 
   pod 'gRPC', :path => GRPC_LOCAL_SRC
   pod 'gRPC-Core', :path => GRPC_LOCAL_SRC
   pod 'gRPC-RxLibrary', :path => GRPC_LOCAL_SRC
   pod 'gRPC-ProtoRPC',  :path => GRPC_LOCAL_SRC
 end
-
-# This pre_install hook is only needed to use the local version of gRPC-Core. You don't need it in
-# your application.
-pre_install do |installer|
-  # This is the gRPC-Core podspec object, as initialized by its podspec file.
-  grpc_core_spec = installer.pod_targets.find{|t| t.name == 'gRPC-Core'}.root_spec
-
-  # Copied from gRPC-Core.podspec, except for the adjusted src_root:
-  src_root = "$(PODS_ROOT)/../#{GRPC_LOCAL_SRC}"
-  grpc_core_spec.pod_target_xcconfig = {
-    'GRPC_SRC_ROOT' => src_root,
-    'HEADER_SEARCH_PATHS' => '"$(inherited)" "$(GRPC_SRC_ROOT)/include"',
-    'USER_HEADER_SEARCH_PATHS' => '"$(GRPC_SRC_ROOT)"',
-    # If we don't set these two settings, `include/grpc/support/time.h` and
-    # `src/core/lib/gpr/string.h` shadow the system `<time.h>` and `<string.h>`, breaking the
-    # build.
-    'USE_HEADERMAP' => 'NO',
-    'ALWAYS_SEARCH_USER_PATHS' => 'NO',
-  }
-end
index c5c49cf..4c12315 100644 (file)
@@ -20,29 +20,10 @@ target 'SwiftSample' do
   pod 'Protobuf', :path => "#{GRPC_LOCAL_SRC}/third_party/protobuf"
 
   pod 'BoringSSL-GRPC', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c"
+  pod 'Libuv-gRPC', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c"
 
   pod 'gRPC', :path => GRPC_LOCAL_SRC
   pod 'gRPC-Core', :path => GRPC_LOCAL_SRC
   pod 'gRPC-RxLibrary', :path => GRPC_LOCAL_SRC
   pod 'gRPC-ProtoRPC',  :path => GRPC_LOCAL_SRC
 end
-
-# This pre_install hook is only needed to use the local version of gRPC-Core. You don't need it in
-# your application.
-pre_install do |installer|
-  # This is the gRPC-Core podspec object, as initialized by its podspec file.
-  grpc_core_spec = installer.pod_targets.find{|t| t.name == 'gRPC-Core'}.root_spec
-
-  # Copied from gRPC-Core.podspec, except for the adjusted src_root:
-  src_root = "$(PODS_ROOT)/../#{GRPC_LOCAL_SRC}"
-  grpc_core_spec.pod_target_xcconfig = {
-    'GRPC_SRC_ROOT' => src_root,
-    'HEADER_SEARCH_PATHS' => '"$(inherited)" "$(GRPC_SRC_ROOT)/include"',
-    'USER_HEADER_SEARCH_PATHS' => '"$(GRPC_SRC_ROOT)"',
-    # If we don't set these two settings, `include/grpc/support/time.h` and
-    # `src/core/lib/gpr/string.h` shadow the system `<time.h>` and `<string.h>`, breaking the
-    # build.
-    'USE_HEADERMAP' => 'NO',
-    'ALWAYS_SEARCH_USER_PATHS' => 'NO',
-  }
-end
index 79427b9..03b421b 100644 (file)
@@ -14,20 +14,3 @@ target 'tvOS-sample' do
   pod 'RemoteTest', :path => "../RemoteTestClient"
   pod '!ProtoCompiler-gRPCPlugin', :path => "#{ROOT_DIR}/src/objective-c"
 end
-
-pre_install do |installer|
-  grpc_core_spec = installer.pod_targets.find{|t| t.name.start_with?('gRPC-Core')}.root_spec
-
-  src_root = "$(PODS_TARGET_SRCROOT)"
-  grpc_core_spec.pod_target_xcconfig = {
-    'GRPC_SRC_ROOT' => src_root,
-    'HEADER_SEARCH_PATHS' => '"$(inherited)" "$(GRPC_SRC_ROOT)/include"',
-    'USER_HEADER_SEARCH_PATHS' => '"$(GRPC_SRC_ROOT)"',
-    # If we don't set these two settings, `include/grpc/support/time.h` and
-    # `src/core/lib/gpr/string.h` shadow the system `<time.h>` and `<string.h>`, breaking the
-    # build.
-    'USE_HEADERMAP' => 'NO',
-    'ALWAYS_SEARCH_USER_PATHS' => 'NO',
-  }
-end
-
index 30dffad..05439ef 100644 (file)
@@ -24,20 +24,3 @@ target 'watchOS-sample WatchKit Extension' do
 platform :watchos, '4.0'
   grpc_deps
 end
-
-pre_install do |installer|
-  grpc_core_spec = installer.pod_targets.find{|t| t.name.start_with?('gRPC-Core')}.root_spec
-
-  src_root = "$(PODS_TARGET_SRCROOT)"
-  grpc_core_spec.pod_target_xcconfig = {
-    'GRPC_SRC_ROOT' => src_root,
-    'HEADER_SEARCH_PATHS' => '"$(inherited)" "$(GRPC_SRC_ROOT)/include"',
-    'USER_HEADER_SEARCH_PATHS' => '"$(GRPC_SRC_ROOT)"',
-    # If we don't set these two settings, `include/grpc/support/time.h` and
-    # `src/core/lib/gpr/string.h` shadow the system `<time.h>` and `<string.h>`, breaking the
-    # build.
-    'USE_HEADERMAP' => 'NO',
-    'ALWAYS_SEARCH_USER_PATHS' => 'NO',
-  }
-end
-
index ef07d41..6ccfd97 100644 (file)
@@ -26,37 +26,6 @@ GrpcIosTest
   end
 end
 
-# gRPC-Core.podspec needs to be modified to be successfully used for local development. A Podfile's
-# pre_install hook lets us do that. The block passed to it runs after the podspecs are downloaded
-# and before they are installed in the user project.
-#
-# This podspec searches for the gRPC core library headers under "$(PODS_ROOT)/gRPC-Core", where
-# Cocoapods normally places the downloaded sources. When doing local development of the libraries,
-# though, Cocoapods just takes the sources from whatever directory was specified using `:path`, and
-# doesn't copy them under $(PODS_ROOT). When using static libraries, one can sometimes rely on the
-# symbolic links to the pods headers that Cocoapods creates under "$(PODS_ROOT)/Headers". But those
-# aren't created when using dynamic frameworks. So our solution is to modify the podspec on the fly
-# to point at the local directory where the sources are.
-#
-# TODO(jcanizales): Send a PR to Cocoapods to get rid of this need.
-pre_install do |installer|
-  # This is the gRPC-Core podspec object, as initialized by its podspec file.
-  grpc_core_spec = installer.pod_targets.find{|t| t.name.start_with?('gRPC-Core')}.root_spec
-
-  # Copied from gRPC-Core.podspec, except for the adjusted src_root:
-  src_root = "$(PODS_ROOT)/../#{GRPC_LOCAL_SRC}"
-  grpc_core_spec.pod_target_xcconfig = {
-    'GRPC_SRC_ROOT' => src_root,
-    'HEADER_SEARCH_PATHS' => '"$(inherited)" "$(GRPC_SRC_ROOT)/include"',
-    'USER_HEADER_SEARCH_PATHS' => '"$(GRPC_SRC_ROOT)"',
-    # If we don't set these two settings, `include/grpc/support/time.h` and
-    # `src/core/lib/gpr/string.h` shadow the system `<time.h>` and `<string.h>`, breaking the
-    # build.
-    'USE_HEADERMAP' => 'NO',
-    'ALWAYS_SEARCH_USER_PATHS' => 'NO',
-  }
-end
-
 post_install do |installer|
   installer.pods_project.targets.each do |target|
     target.build_configurations.each do |config|
index f029984..ec59473 100644 (file)
@@ -14,7 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 package(default_visibility = ["//visibility:public"])
 
index 6da2d6e..d7b11f5 100644 (file)
@@ -12,21 +12,3 @@ target 'ConnectivityTestingApp' do
   pod 'Protobuf', :path => "#{GRPC_LOCAL_SRC}/third_party/protobuf"
   pod 'BoringSSL-GRPC', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c"
 end
-
-pre_install do |installer|
-  # This is the gRPC-Core podspec object, as initialized by its podspec file.
-  grpc_core_spec = installer.pod_targets.find{|t| t.name == 'gRPC-Core'}.root_spec
-
-  # Copied from gRPC-Core.podspec, except for the adjusted src_root:
-  src_root = "$(PODS_ROOT)/../#{GRPC_LOCAL_SRC}"
-  grpc_core_spec.pod_target_xcconfig = {
-    'GRPC_SRC_ROOT' => src_root,
-    'HEADER_SEARCH_PATHS' => '"$(inherited)" "$(GRPC_SRC_ROOT)/include"',
-    'USER_HEADER_SEARCH_PATHS' => '"$(GRPC_SRC_ROOT)"',
-    # If we don't set these two settings, `include/grpc/support/time.h` and
-    # `src/core/lib/gpr/string.h` shadow the system `<time.h>` and `<string.h>`, breaking the
-    # build.
-    'USE_HEADERMAP' => 'NO',
-    'ALWAYS_SEARCH_USER_PATHS' => 'NO',
-  }
-end
diff --git a/src/objective-c/tests/CoreTests/CoreTests.xcodeproj/project.pbxproj b/src/objective-c/tests/CoreTests/CoreTests.xcodeproj/project.pbxproj
new file mode 100644 (file)
index 0000000..9c90705
--- /dev/null
@@ -0,0 +1,367 @@
+// !$*UTF8*$!
+{
+       archiveVersion = 1;
+       classes = {
+       };
+       objectVersion = 55;
+       objects = {
+
+/* Begin PBXBuildFile section */
+               74EC3A952708149C005DF382 /* EventEngineTimerTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 74EC3A942708149C005DF382 /* EventEngineTimerTests.mm */; };
+               AE7618A265DF8B92E93BDFFC /* libPods-CoreTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CC79A999099057E7806F7A4E /* libPods-CoreTests.a */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+               74EC3A7527081130005DF382 /* CoreTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CoreTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+               74EC3A942708149C005DF382 /* EventEngineTimerTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = EventEngineTimerTests.mm; path = CoreTests/EventEngineTimerTests.mm; sourceTree = "<group>"; };
+               BC32E593C6B40EAC11EDD29E /* Pods-CoreTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CoreTests.release.xcconfig"; path = "Target Support Files/Pods-CoreTests/Pods-CoreTests.release.xcconfig"; sourceTree = "<group>"; };
+               CC2F5D65EA0FAB6B5347995A /* Pods-CoreTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CoreTests.debug.xcconfig"; path = "Target Support Files/Pods-CoreTests/Pods-CoreTests.debug.xcconfig"; sourceTree = "<group>"; };
+               CC79A999099057E7806F7A4E /* libPods-CoreTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-CoreTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+               74EC3A7227081130005DF382 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AE7618A265DF8B92E93BDFFC /* libPods-CoreTests.a in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+               3CD5ACD34F6BAA337C3076B2 /* Frameworks */ = {
+                       isa = PBXGroup;
+                       children = (
+                               CC79A999099057E7806F7A4E /* libPods-CoreTests.a */,
+                       );
+                       name = Frameworks;
+                       sourceTree = "<group>";
+               };
+               653269393ADB5A6623AFDD4C /* Pods */ = {
+                       isa = PBXGroup;
+                       children = (
+                               CC2F5D65EA0FAB6B5347995A /* Pods-CoreTests.debug.xcconfig */,
+                               BC32E593C6B40EAC11EDD29E /* Pods-CoreTests.release.xcconfig */,
+                       );
+                       path = Pods;
+                       sourceTree = "<group>";
+               };
+               74EC3A512708112C005DF382 = {
+                       isa = PBXGroup;
+                       children = (
+                               74EC3A942708149C005DF382 /* EventEngineTimerTests.mm */,
+                               74EC3A5B2708112C005DF382 /* Products */,
+                               653269393ADB5A6623AFDD4C /* Pods */,
+                               3CD5ACD34F6BAA337C3076B2 /* Frameworks */,
+                       );
+                       sourceTree = "<group>";
+               };
+               74EC3A5B2708112C005DF382 /* Products */ = {
+                       isa = PBXGroup;
+                       children = (
+                               74EC3A7527081130005DF382 /* CoreTests.xctest */,
+                       );
+                       name = Products;
+                       sourceTree = "<group>";
+               };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+               74EC3A7427081130005DF382 /* CoreTests */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = 74EC3A8C27081130005DF382 /* Build configuration list for PBXNativeTarget "CoreTests" */;
+                       buildPhases = (
+                               CCD5D09951B532EA7E1165AD /* [CP] Check Pods Manifest.lock */,
+                               74EC3A7127081130005DF382 /* Sources */,
+                               74EC3A7227081130005DF382 /* Frameworks */,
+                               74EC3A7327081130005DF382 /* Resources */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                       );
+                       name = CoreTests;
+                       productName = CoreTestsTests;
+                       productReference = 74EC3A7527081130005DF382 /* CoreTests.xctest */;
+                       productType = "com.apple.product-type.bundle.unit-test";
+               };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+               74EC3A522708112C005DF382 /* Project object */ = {
+                       isa = PBXProject;
+                       attributes = {
+                               BuildIndependentTargetsInParallel = 1;
+                               LastUpgradeCheck = 1300;
+                               TargetAttributes = {
+                                       74EC3A7427081130005DF382 = {
+                                               CreatedOnToolsVersion = 13.0;
+                                       };
+                               };
+                       };
+                       buildConfigurationList = 74EC3A552708112C005DF382 /* Build configuration list for PBXProject "CoreTests" */;
+                       compatibilityVersion = "Xcode 13.0";
+                       developmentRegion = en;
+                       hasScannedForEncodings = 0;
+                       knownRegions = (
+                               en,
+                               Base,
+                       );
+                       mainGroup = 74EC3A512708112C005DF382;
+                       productRefGroup = 74EC3A5B2708112C005DF382 /* Products */;
+                       projectDirPath = "";
+                       projectRoot = "";
+                       targets = (
+                               74EC3A7427081130005DF382 /* CoreTests */,
+                       );
+               };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+               74EC3A7327081130005DF382 /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+               CCD5D09951B532EA7E1165AD /* [CP] Check Pods Manifest.lock */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputFileListPaths = (
+                       );
+                       inputPaths = (
+                               "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+                               "${PODS_ROOT}/Manifest.lock",
+                       );
+                       name = "[CP] Check Pods Manifest.lock";
+                       outputFileListPaths = (
+                       );
+                       outputPaths = (
+                               "$(DERIVED_FILE_DIR)/Pods-CoreTests-checkManifestLockResult.txt",
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
+                       showEnvVarsInLog = 0;
+               };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+               74EC3A7127081130005DF382 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               74EC3A952708149C005DF382 /* EventEngineTimerTests.mm in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+               74EC3A8727081130005DF382 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               ALWAYS_SEARCH_USER_PATHS = NO;
+                               CLANG_ANALYZER_NONNULL = YES;
+                               CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+                               CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
+                               CLANG_CXX_LIBRARY = "libc++";
+                               CLANG_ENABLE_MODULES = YES;
+                               CLANG_ENABLE_OBJC_ARC = YES;
+                               CLANG_ENABLE_OBJC_WEAK = YES;
+                               CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+                               CLANG_WARN_BOOL_CONVERSION = YES;
+                               CLANG_WARN_COMMA = YES;
+                               CLANG_WARN_CONSTANT_CONVERSION = YES;
+                               CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+                               CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+                               CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+                               CLANG_WARN_EMPTY_BODY = YES;
+                               CLANG_WARN_ENUM_CONVERSION = YES;
+                               CLANG_WARN_INFINITE_RECURSION = YES;
+                               CLANG_WARN_INT_CONVERSION = YES;
+                               CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+                               CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+                               CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+                               CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+                               CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+                               CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+                               CLANG_WARN_STRICT_PROTOTYPES = YES;
+                               CLANG_WARN_SUSPICIOUS_MOVE = YES;
+                               CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+                               CLANG_WARN_UNREACHABLE_CODE = YES;
+                               CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+                               COPY_PHASE_STRIP = NO;
+                               DEBUG_INFORMATION_FORMAT = dwarf;
+                               ENABLE_STRICT_OBJC_MSGSEND = YES;
+                               ENABLE_TESTABILITY = YES;
+                               GCC_C_LANGUAGE_STANDARD = gnu11;
+                               GCC_DYNAMIC_NO_PIC = NO;
+                               GCC_NO_COMMON_BLOCKS = YES;
+                               GCC_OPTIMIZATION_LEVEL = 0;
+                               GCC_PREPROCESSOR_DEFINITIONS = (
+                                       "DEBUG=1",
+                                       "$(inherited)",
+                               );
+                               GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+                               GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+                               GCC_WARN_UNDECLARED_SELECTOR = YES;
+                               GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+                               GCC_WARN_UNUSED_FUNCTION = YES;
+                               GCC_WARN_UNUSED_VARIABLE = YES;
+                               IPHONEOS_DEPLOYMENT_TARGET = 15.0;
+                               MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+                               MTL_FAST_MATH = YES;
+                               ONLY_ACTIVE_ARCH = YES;
+                               SDKROOT = iphoneos;
+                               USER_HEADER_SEARCH_PATHS = "";
+                       };
+                       name = Debug;
+               };
+               74EC3A8827081130005DF382 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               ALWAYS_SEARCH_USER_PATHS = NO;
+                               CLANG_ANALYZER_NONNULL = YES;
+                               CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+                               CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
+                               CLANG_CXX_LIBRARY = "libc++";
+                               CLANG_ENABLE_MODULES = YES;
+                               CLANG_ENABLE_OBJC_ARC = YES;
+                               CLANG_ENABLE_OBJC_WEAK = YES;
+                               CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+                               CLANG_WARN_BOOL_CONVERSION = YES;
+                               CLANG_WARN_COMMA = YES;
+                               CLANG_WARN_CONSTANT_CONVERSION = YES;
+                               CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+                               CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+                               CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+                               CLANG_WARN_EMPTY_BODY = YES;
+                               CLANG_WARN_ENUM_CONVERSION = YES;
+                               CLANG_WARN_INFINITE_RECURSION = YES;
+                               CLANG_WARN_INT_CONVERSION = YES;
+                               CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+                               CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+                               CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+                               CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+                               CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+                               CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+                               CLANG_WARN_STRICT_PROTOTYPES = YES;
+                               CLANG_WARN_SUSPICIOUS_MOVE = YES;
+                               CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+                               CLANG_WARN_UNREACHABLE_CODE = YES;
+                               CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+                               COPY_PHASE_STRIP = NO;
+                               DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+                               ENABLE_NS_ASSERTIONS = NO;
+                               ENABLE_STRICT_OBJC_MSGSEND = YES;
+                               GCC_C_LANGUAGE_STANDARD = gnu11;
+                               GCC_NO_COMMON_BLOCKS = YES;
+                               GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+                               GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+                               GCC_WARN_UNDECLARED_SELECTOR = YES;
+                               GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+                               GCC_WARN_UNUSED_FUNCTION = YES;
+                               GCC_WARN_UNUSED_VARIABLE = YES;
+                               IPHONEOS_DEPLOYMENT_TARGET = 15.0;
+                               MTL_ENABLE_DEBUG_INFO = NO;
+                               MTL_FAST_MATH = YES;
+                               SDKROOT = iphoneos;
+                               USER_HEADER_SEARCH_PATHS = "";
+                               VALIDATE_PRODUCT = YES;
+                       };
+                       name = Release;
+               };
+               74EC3A8D27081130005DF382 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       baseConfigurationReference = CC2F5D65EA0FAB6B5347995A /* Pods-CoreTests.debug.xcconfig */;
+                       buildSettings = {
+                               CODE_SIGN_STYLE = Automatic;
+                               CURRENT_PROJECT_VERSION = 1;
+                               GENERATE_INFOPLIST_FILE = YES;
+                               HEADER_SEARCH_PATHS = (
+                                       "$(inherited)",
+                                       "\"${PODS_ROOT}/Headers/Public\"",
+                                       "\"${PODS_ROOT}/Headers/Public/BoringSSL-GRPC\"",
+                                       "\"${PODS_ROOT}/Headers/Public/Libuv-gRPC\"",
+                                       "\"${PODS_ROOT}/Headers/Public/abseil\"",
+                                       "\"${PODS_ROOT}/Headers/Public/gRPC-Core\"",
+                               );
+                               IPHONEOS_DEPLOYMENT_TARGET = 15.0;
+                               LD_RUNPATH_SEARCH_PATHS = (
+                                       "$(inherited)",
+                                       "@executable_path/Frameworks",
+                                       "@loader_path/Frameworks",
+                               );
+                               MARKETING_VERSION = 1.0;
+                               PRODUCT_BUNDLE_IDENTIFIER = com.google.CoreTests;
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                               SWIFT_EMIT_LOC_STRINGS = NO;
+                               TARGETED_DEVICE_FAMILY = "1,2";
+                               USER_HEADER_SEARCH_PATHS = "\"$(PODS_ROOT)/../../../../../\"";
+                       };
+                       name = Debug;
+               };
+               74EC3A8E27081130005DF382 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       baseConfigurationReference = BC32E593C6B40EAC11EDD29E /* Pods-CoreTests.release.xcconfig */;
+                       buildSettings = {
+                               CODE_SIGN_STYLE = Automatic;
+                               CURRENT_PROJECT_VERSION = 1;
+                               GENERATE_INFOPLIST_FILE = YES;
+                               HEADER_SEARCH_PATHS = (
+                                       "$(inherited)",
+                                       "\"${PODS_ROOT}/Headers/Public\"",
+                                       "\"${PODS_ROOT}/Headers/Public/BoringSSL-GRPC\"",
+                                       "\"${PODS_ROOT}/Headers/Public/Libuv-gRPC\"",
+                                       "\"${PODS_ROOT}/Headers/Public/abseil\"",
+                                       "\"${PODS_ROOT}/Headers/Public/gRPC-Core\"",
+                               );
+                               IPHONEOS_DEPLOYMENT_TARGET = 15.0;
+                               LD_RUNPATH_SEARCH_PATHS = (
+                                       "$(inherited)",
+                                       "@executable_path/Frameworks",
+                                       "@loader_path/Frameworks",
+                               );
+                               MARKETING_VERSION = 1.0;
+                               PRODUCT_BUNDLE_IDENTIFIER = com.google.CoreTests;
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                               SWIFT_EMIT_LOC_STRINGS = NO;
+                               TARGETED_DEVICE_FAMILY = "1,2";
+                               USER_HEADER_SEARCH_PATHS = "\"$(PODS_ROOT)/../../../../../\"";
+                       };
+                       name = Release;
+               };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+               74EC3A552708112C005DF382 /* Build configuration list for PBXProject "CoreTests" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               74EC3A8727081130005DF382 /* Debug */,
+                               74EC3A8827081130005DF382 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+               74EC3A8C27081130005DF382 /* Build configuration list for PBXNativeTarget "CoreTests" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               74EC3A8D27081130005DF382 /* Debug */,
+                               74EC3A8E27081130005DF382 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+/* End XCConfigurationList section */
+       };
+       rootObject = 74EC3A522708112C005DF382 /* Project object */;
+}
diff --git a/src/objective-c/tests/CoreTests/CoreTests/EventEngineTimerTests.mm b/src/objective-c/tests/CoreTests/CoreTests/EventEngineTimerTests.mm
new file mode 100644 (file)
index 0000000..d78690c
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#import <XCTest/XCTest.h>
+
+#include <absl/functional/bind_front.h>
+#include <absl/time/time.h>
+
+#include <grpc/event_engine/event_engine.h>
+#include <grpc/grpc.h>
+#include <grpc/test/core/util/test_config.h>
+
+@interface EventEngineTimerTests : XCTestCase
+
+@end
+
+@implementation EventEngineTimerTests
+
++ (void)setUp {
+  grpc_init();
+}
+
++ (void)tearDown {
+  grpc_shutdown();
+}
+
+- (void)setUp {
+}
+
+- (void)tearDown {
+}
+
+- (void)testDummy {
+}
+
+@end
diff --git a/src/objective-c/tests/CoreTests/Podfile b/src/objective-c/tests/CoreTests/Podfile
new file mode 100644 (file)
index 0000000..068d2e9
--- /dev/null
@@ -0,0 +1,25 @@
+source 'https://github.com/CocoaPods/Specs.git'
+
+install! 'cocoapods', :deterministic_uuids => false
+
+GRPC_LOCAL_SRC = '../../../..'
+
+def grpc_deps
+  pod 'gRPC-Core', :path => GRPC_LOCAL_SRC
+  pod 'gRPC-Core/Tests', :path => GRPC_LOCAL_SRC
+end
+
+target 'CoreTests' do
+  platform :ios, '9.0'
+  grpc_deps
+end
+
+post_install do |installer|
+  installer.pods_project.targets.each do |target|
+    if target.name == "CoreTests"
+      target.build_configurations.each do |config|
+        config.build_settings['USER_HEADER_SEARCH_PATHS'] = "$(inherited) $(PODS_ROOT)/../#{GRPC_LOCAL_SRC}"
+      end
+    end
+  end
+end
index 34abc04..95125bd 100644 (file)
@@ -1406,10 +1406,9 @@ static dispatch_once_t initGlobalInterceptorFactory;
                               messageCallback:nil
                                 closeCallback:^(NSDictionary *trailingMetadata, NSError *error) {
                                   XCTAssertNotNil(error);
-                                  XCTAssertEqual(
-                                      error.code, GRPC_STATUS_UNAVAILABLE,
-                                      @"Received status %ld instead of UNAVAILABLE (14).",
-                                      error.code);
+                                  XCTAssertEqual(error.code, GRPC_STATUS_UNAVAILABLE,
+                                                 @"Received status %@ instead of UNAVAILABLE (14).",
+                                                 @(error.code));
                                   [expectation fulfill];
                                 }]
                             callOptions:options];
@@ -1680,41 +1679,37 @@ static dispatch_once_t initGlobalInterceptorFactory;
   options.interceptorFactories = @[ [[DefaultInterceptorFactory alloc] init], factory ];
 
   __block GRPCStreamingProtoCall *call = [_service
-      fullDuplexCallWithResponseHandler:[[InteropTestsBlockCallbacks alloc]
-                                            initWithInitialMetadataCallback:nil
-                                            messageCallback:^(id message) {
-                                              XCTAssertLessThan(index, 4,
-                                                                @"More than 4 responses received.");
-                                              id expected = [RMTStreamingOutputCallResponse
-                                                  messageWithPayloadSize:responses[index]];
-                                              XCTAssertEqualObjects(message, expected);
-                                              index += 1;
-                                              if (index < 4) {
-                                                id request = [RMTStreamingOutputCallRequest
-                                                    messageWithPayloadSize:requests[index]
-                                                     requestedResponseSize:responses[index]];
-                                                [call writeMessage:request];
-                                                [call receiveNextMessage];
-                                              } else {
-                                                [call finish];
-                                              }
-                                            }
-                                            closeCallback:^(NSDictionary *trailingMetadata,
-                                                            NSError *error) {
-                                              XCTAssertNil(error,
-                                                           @"Finished with unexpected error: %@",
-                                                           error);
-                                              XCTAssertEqual(index, 4,
-                                                             @"Received %i responses instead of 4.",
-                                                             index);
-                                              [expectUserCallComplete fulfill];
-                                            }]
+      fullDuplexCallWithResponseHandler:
+          [[InteropTestsBlockCallbacks alloc] initWithInitialMetadataCallback:nil
+              messageCallback:^(id message) {
+                XCTAssertLessThan(index, 4, @"More than 4 responses received.");
+                id expected =
+                    [RMTStreamingOutputCallResponse messageWithPayloadSize:responses[index]];
+                XCTAssertEqualObjects(message, expected);
+                index += 1;
+                if (index < 4) {
+                  id request =
+                      [RMTStreamingOutputCallRequest messageWithPayloadSize:requests[index]
+                                                      requestedResponseSize:responses[index]];
+                  [call writeMessage:request];
+                  [call receiveNextMessage];
+                } else {
+                  [self waitForExpectations:@[ expectResponseCallbackComplete ]
+                                    timeout:TEST_TIMEOUT];
+                  [call finish];
+                }
+              }
+              closeCallback:^(NSDictionary *trailingMetadata, NSError *error) {
+                XCTAssertNil(error, @"Finished with unexpected error: %@", error);
+                XCTAssertEqual(index, 4, @"Received %i responses instead of 4.", index);
+                [expectUserCallComplete fulfill];
+              }]
                             callOptions:options];
   [call start];
   [call receiveNextMessage];
   [call writeMessage:request];
 
-  [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
+  [self waitForExpectations:@[ expectUserCallComplete ] timeout:TEST_TIMEOUT];
   XCTAssertEqual(startCount, 1);
   XCTAssertEqual(writeDataCount, 4);
   XCTAssertEqual(finishCount, 1);
index 6dac4d0..ebd1e24 100644 (file)
@@ -7,12 +7,13 @@ GRPC_LOCAL_SRC = '../../..'
 
 def grpc_deps
   pod 'Protobuf', :path => "#{GRPC_LOCAL_SRC}/third_party/protobuf", :inhibit_warnings => true
-  
+
   pod '!ProtoCompiler',            :path => "#{GRPC_LOCAL_SRC}/src/objective-c"
   pod '!ProtoCompiler-gRPCPlugin', :path => "#{GRPC_LOCAL_SRC}/src/objective-c"
-  
+
   pod 'BoringSSL-GRPC',       :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c", :inhibit_warnings => true
-  
+  pod 'Libuv-gRPC',       :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c", :inhibit_warnings => true
+
   pod 'gRPC/InternalTesting',           :path => GRPC_LOCAL_SRC
   pod 'gRPC-Core',                      :path => GRPC_LOCAL_SRC, :inhibit_warnings => true
   pod 'gRPC-RxLibrary',                 :path => GRPC_LOCAL_SRC
@@ -57,41 +58,14 @@ target 'PerfTests' do
   pod 'CronetFramework', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c"
 end
 
-# gRPC-Core.podspec needs to be modified to be successfully used for local development. A Podfile's
-# pre_install hook lets us do that. The block passed to it runs after the podspecs are downloaded
-# and before they are installed in the user project.
-#
-# This podspec searches for the gRPC core library headers under "$(PODS_ROOT)/gRPC-Core", where
-# Cocoapods normally places the downloaded sources. When doing local development of the libraries,
-# though, Cocoapods just takes the sources from whatever directory was specified using `:path`, and
-# doesn't copy them under $(PODS_ROOT). When using static libraries, one can sometimes rely on the
-# symbolic links to the pods headers that Cocoapods creates under "$(PODS_ROOT)/Headers". But those
-# aren't created when using dynamic frameworks. So our solution is to modify the podspec on the fly
-# to point at the local directory where the sources are.
-#
-# TODO(jcanizales): Send a PR to Cocoapods to get rid of this need.
-pre_install do |installer|
-  # This is the gRPC-Core podspec object, as initialized by its podspec file.
-  grpc_core_spec = installer.pod_targets.find{|t| t.name.start_with?('gRPC-Core')}.root_spec
-
-  # Copied from gRPC-Core.podspec, except for the adjusted src_root:
-  src_root = "$(PODS_ROOT)/../#{GRPC_LOCAL_SRC}"
-  grpc_core_spec.pod_target_xcconfig = {
-    'GRPC_SRC_ROOT' => src_root,
-    'HEADER_SEARCH_PATHS' => '"$(inherited)" "$(GRPC_SRC_ROOT)/include"',
-    'USER_HEADER_SEARCH_PATHS' => '"$(GRPC_SRC_ROOT)"',
-    # If we don't set these two settings, `include/grpc/support/time.h` and
-    # `src/core/lib/gpr/string.h` shadow the system `<time.h>` and `<string.h>`, breaking the
-    # build.
-    'USE_HEADERMAP' => 'NO',
-    'ALWAYS_SEARCH_USER_PATHS' => 'NO',
-  }
-end
-
 post_install do |installer|
   installer.pods_project.targets.each do |target|
     target.build_configurations.each do |config|
       config.build_settings['GCC_TREAT_WARNINGS_AS_ERRORS'] = 'YES'
+      if config.name == 'Test'
+        config.build_settings['GCC_OPTIMIZATION_LEVEL'] = '0'
+        config.build_settings['SWIFT_OPTIMIZATION_LEVEL'] = '-Onone'
+      end
     end
 
     # CocoaPods creates duplicated library targets of gRPC-Core when the test targets include
index c23f16c..d50d783 100644 (file)
@@ -40,6 +40,7 @@
                65EB19E418B39A8374D407BB /* libPods-CronetTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1B1511C20E16A8422B58D61A /* libPods-CronetTests.a */; };
                903163C7FE885838580AEC7A /* libPods-InteropTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D457AD9797664CFA191C3280 /* libPods-InteropTests.a */; };
                953CD2942A3A6D6CE695BE87 /* libPods-MacTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 276873A05AC5479B60DF6079 /* libPods-MacTests.a */; };
+               9BF9672E0D0BF5B42D4F2B72 /* libPods-PerfTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D6F190224A515F9A4D09E4CF /* libPods-PerfTests.a */; };
                ABA946DC22FF62FC00577AEF /* TestCertificates.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 63E240CF1B6C63DC005F3B0E /* TestCertificates.bundle */; };
                ABCB3EE422F23BEF00F0FECE /* InteropTestsRemote.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E7F488822778B04006656AD /* InteropTestsRemote.m */; };
                ABCB3EE522F23BEF00F0FECE /* InteropTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E7F488222778A88006656AD /* InteropTests.m */; };
@@ -82,6 +83,7 @@
                0A4F89D9C90E9C30990218F0 /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = "<group>"; };
                0BDA4BA011779D5D25B5618C /* libPods-InteropTestsLocalCleartextCFStream.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-InteropTestsLocalCleartextCFStream.a"; sourceTree = BUILT_PRODUCTS_DIR; };
                0D2284C3DF7E57F0ED504E39 /* Pods-CoreCronetEnd2EndTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CoreCronetEnd2EndTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-CoreCronetEnd2EndTests/Pods-CoreCronetEnd2EndTests.debug.xcconfig"; sourceTree = "<group>"; };
+               0DEDD2F15237E5322F696B00 /* Pods-PerfTests.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PerfTests.test.xcconfig"; path = "Pods/Target Support Files/Pods-PerfTests/Pods-PerfTests.test.xcconfig"; sourceTree = "<group>"; };
                1286B30AD74CB64CD91FB17D /* Pods-APIv2Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-APIv2Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-APIv2Tests/Pods-APIv2Tests.debug.xcconfig"; sourceTree = "<group>"; };
                1295CCBD1082B4A7CFCED95F /* Pods-InteropTestsMultipleChannels.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsMultipleChannels.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsMultipleChannels/Pods-InteropTestsMultipleChannels.cronet.xcconfig"; sourceTree = "<group>"; };
                12B238CD1702393C2BA5DE80 /* Pods-APIv2Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-APIv2Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-APIv2Tests/Pods-APIv2Tests.release.xcconfig"; sourceTree = "<group>"; };
                7BA53C6D224288D5870FE6F3 /* Pods-InteropTestsLocalCleartextCFStream.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalCleartextCFStream.release.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalCleartextCFStream/Pods-InteropTestsLocalCleartextCFStream.release.xcconfig"; sourceTree = "<group>"; };
                7F4F42EBAF311E9F84FCA32E /* Pods-CronetTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CronetTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-CronetTests/Pods-CronetTests.release.xcconfig"; sourceTree = "<group>"; };
                8809F3EB70C19F2CFA1F4CA6 /* Pods-TvTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TvTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-TvTests/Pods-TvTests.release.xcconfig"; sourceTree = "<group>"; };
+               8AB3DD44BB84D98E7FB28CAE /* Pods-PerfTests.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PerfTests.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-PerfTests/Pods-PerfTests.cronet.xcconfig"; sourceTree = "<group>"; };
                8B498B05C6DA0818B2FA91D4 /* Pods-InteropTestsLocalCleartextCFStream.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalCleartextCFStream.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalCleartextCFStream/Pods-InteropTestsLocalCleartextCFStream.cronet.xcconfig"; sourceTree = "<group>"; };
                8C233E85C3EB45B3CAE52EDF /* Pods-APIv2Tests.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-APIv2Tests.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-APIv2Tests/Pods-APIv2Tests.cronet.xcconfig"; sourceTree = "<group>"; };
                90E63AD3C4A1E3E6BC745096 /* Pods-ChannelTests.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ChannelTests.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-ChannelTests/Pods-ChannelTests.cronet.xcconfig"; sourceTree = "<group>"; };
                D13BEC8181B8E678A1B52F54 /* Pods-InteropTestsLocalSSL.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalSSL.test.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalSSL/Pods-InteropTestsLocalSSL.test.xcconfig"; sourceTree = "<group>"; };
                D457AD9797664CFA191C3280 /* libPods-InteropTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-InteropTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
                D52B92A7108602F170DA8091 /* Pods-ChannelTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ChannelTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-ChannelTests/Pods-ChannelTests.release.xcconfig"; sourceTree = "<group>"; };
+               D6F190224A515F9A4D09E4CF /* libPods-PerfTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-PerfTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
                DB1F4391AF69D20D38D74B67 /* Pods-AllTests.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AllTests.test.xcconfig"; path = "Pods/Target Support Files/Pods-AllTests/Pods-AllTests.test.xcconfig"; sourceTree = "<group>"; };
                DBE059B4AC7A51919467EEC0 /* libPods-InteropTestsRemote.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-InteropTestsRemote.a"; sourceTree = BUILT_PRODUCTS_DIR; };
                DBEDE45BDA60DF1E1C8950C0 /* libPods-InteropTestsLocalSSL.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-InteropTestsLocalSSL.a"; sourceTree = BUILT_PRODUCTS_DIR; };
                E3ACD4D5902745976D9C2229 /* Pods-MacTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MacTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-MacTests/Pods-MacTests.debug.xcconfig"; sourceTree = "<group>"; };
                E4275A759BDBDF143B9B438F /* Pods-InteropTestsRemote.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemote.release.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemote/Pods-InteropTestsRemote.release.xcconfig"; sourceTree = "<group>"; };
                E4FD4606D4AB8D5A314D72F0 /* Pods-InteropTestsLocalCleartextCFStream.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalCleartextCFStream.test.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalCleartextCFStream/Pods-InteropTestsLocalCleartextCFStream.test.xcconfig"; sourceTree = "<group>"; };
+               E6C8237CDCD9B14BAA129905 /* Pods-PerfTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PerfTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-PerfTests/Pods-PerfTests.debug.xcconfig"; sourceTree = "<group>"; };
                E7E4D3FD76E3B745D992AF5F /* Pods-AllTests.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AllTests.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-AllTests/Pods-AllTests.cronet.xcconfig"; sourceTree = "<group>"; };
                EA8B122ACDE73E3AAA0E4A19 /* Pods-InteropTestsMultipleChannels.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsMultipleChannels.test.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsMultipleChannels/Pods-InteropTestsMultipleChannels.test.xcconfig"; sourceTree = "<group>"; };
                EBFFEC04B514CB0D4922DC40 /* Pods-UnitTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-UnitTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-UnitTests/Pods-UnitTests.release.xcconfig"; sourceTree = "<group>"; };
                EC66920112123D2DB1CB7F6C /* Pods-CronetTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CronetTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-CronetTests/Pods-CronetTests.debug.xcconfig"; sourceTree = "<group>"; };
                F3AB031E0E26AC8EF30A2A2A /* libPods-InteropTestsLocalSSLCFStream.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-InteropTestsLocalSSLCFStream.a"; sourceTree = BUILT_PRODUCTS_DIR; };
+               F43089EDDB1893780A21B23F /* Pods-PerfTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PerfTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-PerfTests/Pods-PerfTests.release.xcconfig"; sourceTree = "<group>"; };
                F44AC3F44E3491A8C0D890FE /* libPods-InteropTestsRemoteCFStream.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-InteropTestsRemoteCFStream.a"; sourceTree = BUILT_PRODUCTS_DIR; };
                F6A7EECACBB4849DDD3F450A /* Pods-InteropTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTests/Pods-InteropTests.release.xcconfig"; sourceTree = "<group>"; };
                F9E48EF5ACB1F38825171C5F /* Pods-ChannelTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ChannelTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ChannelTests/Pods-ChannelTests.debug.xcconfig"; sourceTree = "<group>"; };
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
+                               9BF9672E0D0BF5B42D4F2B72 /* libPods-PerfTests.a in Frameworks */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                D457AD9797664CFA191C3280 /* libPods-InteropTests.a */,
                                1B1511C20E16A8422B58D61A /* libPods-CronetTests.a */,
                                2A0A5455106001F60357A4B6 /* libPods-TvTests.a */,
+                               D6F190224A515F9A4D09E4CF /* libPods-PerfTests.a */,
                        );
                        name = Frameworks;
                        sourceTree = "<group>";
                                A52BDBDE1F6643E6FD1F3CBA /* Pods-TvTests.test.xcconfig */,
                                038286E5BBEC3F03D4701CCC /* Pods-TvTests.cronet.xcconfig */,
                                8809F3EB70C19F2CFA1F4CA6 /* Pods-TvTests.release.xcconfig */,
+                               E6C8237CDCD9B14BAA129905 /* Pods-PerfTests.debug.xcconfig */,
+                               0DEDD2F15237E5322F696B00 /* Pods-PerfTests.test.xcconfig */,
+                               8AB3DD44BB84D98E7FB28CAE /* Pods-PerfTests.cronet.xcconfig */,
+                               F43089EDDB1893780A21B23F /* Pods-PerfTests.release.xcconfig */,
                        );
                        name = Pods;
                        sourceTree = "<group>";
                        isa = PBXNativeTarget;
                        buildConfigurationList = B0F2D0BF232991BA008C2575 /* Build configuration list for PBXNativeTarget "PerfTests" */;
                        buildPhases = (
+                               EF897FD09AF53B0FA4708A7C /* [CP] Check Pods Manifest.lock */,
                                B0F2D0B6232991BA008C2575 /* Sources */,
                                B0F2D0B7232991BA008C2575 /* Frameworks */,
                                B0F2D0B8232991BA008C2575 /* Resources */,
+                               3F94C7350AC0722BB72DAB46 /* [CP] Embed Pods Frameworks */,
+                               98B61E497D7FDF9BA05F7D70 /* [CP] Copy Pods Resources */,
                        );
                        buildRules = (
                        );
                        );
                        inputPaths = (
                                "${PODS_ROOT}/Target Support Files/Pods-CronetTests/Pods-CronetTests-resources.sh",
-                               "${PODS_CONFIGURATION_BUILD_DIR}/gRPC.default-GRPCCoreCronet/gRPCCertificates.bundle",
+                               "${PODS_CONFIGURATION_BUILD_DIR}/gRPC-455bf4e3/gRPCCertificates.bundle",
                        );
                        name = "[CP] Copy Pods Resources";
                        outputPaths = (
                        shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-CronetTests/Pods-CronetTests-resources.sh\"\n";
                        showEnvVarsInLog = 0;
                };
+               3F94C7350AC0722BB72DAB46 /* [CP] Embed Pods Frameworks */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputPaths = (
+                               "${PODS_ROOT}/Target Support Files/Pods-PerfTests/Pods-PerfTests-frameworks.sh",
+                               "${PODS_ROOT}/CronetFramework/Cronet.framework",
+                       );
+                       name = "[CP] Embed Pods Frameworks";
+                       outputPaths = (
+                               "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Cronet.framework",
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-PerfTests/Pods-PerfTests-frameworks.sh\"\n";
+                       showEnvVarsInLog = 0;
+               };
                40BCDB09674DF988C708D22B /* [CP] Check Pods Manifest.lock */ = {
                        isa = PBXShellScriptBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        inputPaths = (
                                "${PODS_ROOT}/Target Support Files/Pods-MacTests/Pods-MacTests-resources.sh",
-                               "${PODS_CONFIGURATION_BUILD_DIR}/gRPC-macOS/gRPCCertificates.bundle",
+                               "${PODS_CONFIGURATION_BUILD_DIR}/gRPC-3e6c0528/gRPCCertificates.bundle",
                        );
                        name = "[CP] Copy Pods Resources";
                        outputPaths = (
                        );
                        inputPaths = (
                                "${PODS_ROOT}/Target Support Files/Pods-TvTests/Pods-TvTests-resources.sh",
-                               "${PODS_CONFIGURATION_BUILD_DIR}/gRPC-tvOS/gRPCCertificates.bundle",
+                               "${PODS_CONFIGURATION_BUILD_DIR}/gRPC-a2df4306/gRPCCertificates.bundle",
                        );
                        name = "[CP] Copy Pods Resources";
                        outputPaths = (
                        shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-TvTests/Pods-TvTests-resources.sh\"\n";
                        showEnvVarsInLog = 0;
                };
+               98B61E497D7FDF9BA05F7D70 /* [CP] Copy Pods Resources */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputPaths = (
+                               "${PODS_ROOT}/Target Support Files/Pods-PerfTests/Pods-PerfTests-resources.sh",
+                               "${PODS_CONFIGURATION_BUILD_DIR}/gRPC-455bf4e3/gRPCCertificates.bundle",
+                       );
+                       name = "[CP] Copy Pods Resources";
+                       outputPaths = (
+                               "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/gRPCCertificates.bundle",
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-PerfTests/Pods-PerfTests-resources.sh\"\n";
+                       showEnvVarsInLog = 0;
+               };
                9AD0B5E94F2AA5962EA6AA36 /* [CP] Copy Pods Resources */ = {
                        isa = PBXShellScriptBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        inputPaths = (
                                "${PODS_ROOT}/Target Support Files/Pods-UnitTests/Pods-UnitTests-resources.sh",
-                               "${PODS_CONFIGURATION_BUILD_DIR}/gRPC-iOS/gRPCCertificates.bundle",
+                               "${PODS_CONFIGURATION_BUILD_DIR}/gRPC-ca997730/gRPCCertificates.bundle",
                        );
                        name = "[CP] Copy Pods Resources";
                        outputPaths = (
                        );
                        inputPaths = (
                                "${PODS_ROOT}/Target Support Files/Pods-InteropTests/Pods-InteropTests-resources.sh",
-                               "${PODS_CONFIGURATION_BUILD_DIR}/gRPC-iOS/gRPCCertificates.bundle",
+                               "${PODS_CONFIGURATION_BUILD_DIR}/gRPC-ca997730/gRPCCertificates.bundle",
                        );
                        name = "[CP] Copy Pods Resources";
                        outputPaths = (
                        shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
                        showEnvVarsInLog = 0;
                };
+               EF897FD09AF53B0FA4708A7C /* [CP] Check Pods Manifest.lock */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputFileListPaths = (
+                       );
+                       inputPaths = (
+                               "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+                               "${PODS_ROOT}/Manifest.lock",
+                       );
+                       name = "[CP] Check Pods Manifest.lock";
+                       outputFileListPaths = (
+                       );
+                       outputPaths = (
+                               "$(DERIVED_FILE_DIR)/Pods-PerfTests-checkManifestLockResult.txt",
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
+                       showEnvVarsInLog = 0;
+               };
                F07941C0BAF6A7C67AA60C48 /* [CP] Check Pods Manifest.lock */ = {
                        isa = PBXShellScriptBuildPhase;
                        buildActionMask = 2147483647;
                };
                B0F2D0C0232991BA008C2575 /* Debug */ = {
                        isa = XCBuildConfiguration;
+                       baseConfigurationReference = E6C8237CDCD9B14BAA129905 /* Pods-PerfTests.debug.xcconfig */;
                        buildSettings = {
                                CLANG_ANALYZER_NONNULL = YES;
                                CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
                };
                B0F2D0C1232991BA008C2575 /* Test */ = {
                        isa = XCBuildConfiguration;
+                       baseConfigurationReference = 0DEDD2F15237E5322F696B00 /* Pods-PerfTests.test.xcconfig */;
                        buildSettings = {
                                CLANG_ANALYZER_NONNULL = YES;
                                CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
                };
                B0F2D0C2232991BA008C2575 /* Cronet */ = {
                        isa = XCBuildConfiguration;
+                       baseConfigurationReference = 8AB3DD44BB84D98E7FB28CAE /* Pods-PerfTests.cronet.xcconfig */;
                        buildSettings = {
                                CLANG_ANALYZER_NONNULL = YES;
                                CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
                };
                B0F2D0C3232991BA008C2575 /* Release */ = {
                        isa = XCBuildConfiguration;
+                       baseConfigurationReference = F43089EDDB1893780A21B23F /* Pods-PerfTests.release.xcconfig */;
                        buildSettings = {
                                CLANG_ANALYZER_NONNULL = YES;
                                CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
index a79cfa9..012b4b0 100644 (file)
@@ -563,7 +563,7 @@ static GRPCProtoMethod *kFullDuplexCallMethod;
 
 - (void)testTimeoutBackoffWithTimeout:(double)timeout Backoff:(double)backoff {
   const double maxConnectTime = timeout > backoff ? timeout : backoff;
-  const double kMargin = 0.1;
+  const double kMargin = 0.2;
 
   __weak XCTestExpectation *completion = [self expectationWithDescription:@"Timeout in a second."];
   NSString *const kPhonyAddress = [NSString stringWithFormat:@"8.8.8.8:1"];
index 6dbca6a..95d17cd 100755 (executable)
@@ -16,7 +16,7 @@
 # Don't run this script standalone. Instead, run from the repository root:
 # ./tools/run_tests/run_tests.py -l objc
 
-set -e
+set -ev
 
 # CocoaPods requires the terminal to be using UTF-8 encoding.
 export LANG=en_US.UTF-8
@@ -29,12 +29,20 @@ hash xcodebuild 2>/dev/null || {
     exit 1
 }
 
-# clean the directory
-rm -rf Pods
-rm -rf Tests.xcworkspace
-rm -f Podfile.lock
+# clean pod cache and prior pods
+rm -Rf Pods Podfile.lock Tests.xcworkspace
 rm -f RemoteTestClient/*.{h,m}
+pod cache clean --all
 
 echo "TIME:  $(date)"
-pod install | ./verbose_time.sh
-
+pod install --verbose | ./verbose_time.sh
+
+# verify pod header installation
+if [ -d "./Pods/Headers/Public/gRPC-Core/grpc/impl/codegen" ]
+then
+    echo "grpc/impl/codegen/ has been imported."
+    number_of_files=$(find Pods/Headers/Public/gRPC-Core/grpc/impl/codegen -name "*.h" | wc -l)
+    echo "The number of files in Pods/Headers/Public/gRPC-Core/grpc/impl/codegen/ is $number_of_files"
+else
+    echo "Error: grpc/impl/codegen/ hasn't been imported."
+fi
index 41475b2..53a813d 100755 (executable)
@@ -85,6 +85,7 @@ xcodebuild \
     HOST_PORT_LOCALSSL=localhost:$TLS_PORT \
     HOST_PORT_LOCAL=localhost:$PLAIN_PORT \
     HOST_PORT_REMOTE=grpc-test.sandbox.googleapis.com \
+    GCC_OPTIMIZATION_LEVEL=s \
     test \
     | ./verbose_time.sh \
     | egrep -v "$XCODEBUILD_FILTER" \
index 88be342..fcaacf4 100644 (file)
@@ -22,5 +22,5 @@
 // instead. This file can be regenerated from the template by running
 // `tools/buildgen/generate_projects.sh`.
 
-#define GRPC_OBJC_VERSION_STRING @"1.41.1"
-#define GRPC_C_VERSION_STRING @"19.0.0"
+#define GRPC_OBJC_VERSION_STRING @"1.42.0"
+#define GRPC_C_VERSION_STRING @"20.0.0"
index f5be96a..01ed61d 100644 (file)
@@ -2,7 +2,7 @@
   "name": "grpc/grpc-dev",
   "description": "gRPC library for PHP - for Development use only",
   "license": "Apache-2.0",
-  "version": "1.41.1",
+  "version": "1.42.0",
   "require": {
     "php": ">=7.0.0",
     "google/protobuf": "^v3.3.0"
index 605105e..03aad8f 100644 (file)
@@ -14,7 +14,7 @@
 
 FROM php:7.2-stretch
 
-RUN apt-get -qq update && apt-get -qq install -y \
+RUN apt-get -qq update && apt-get -qq -y upgrade && apt-get -qq install -y \
   autoconf automake git libtool pkg-config \
   valgrind wget zlib1g-dev
 
index edcd669..d2870bd 100644 (file)
@@ -14,7 +14,7 @@
 
 FROM php:7.2-stretch
 
-RUN apt-get -qq update && apt-get -qq install -y \
+RUN apt-get -qq update && apt-get -qq -y upgrade && apt-get -qq install -y \
   autoconf automake git libtool pkg-config \
   valgrind wget zlib1g-dev
 
index 90ca477..e0b8ab4 100644 (file)
@@ -14,7 +14,7 @@
 
 FROM i386/php:7.2
 
-RUN apt-get -qq update && apt-get -qq install -y \
+RUN apt-get -qq update && apt-get -qq -y upgrade && apt-get -qq install -y \
   autoconf automake git libtool pkg-config \
   valgrind wget zlib1g-dev
 
index 1218e44..a114810 100644 (file)
@@ -14,7 +14,7 @@
 
 FROM php:7.4.11-buster
 
-RUN apt-get -qq update && apt-get -qq install -y \
+RUN apt-get -qq update && apt-get -qq -y upgrade && apt-get -qq install -y \
   autoconf automake git libtool pkg-config \
   valgrind wget zlib1g-dev
 
index feb1b64..4d0bbf9 100644 (file)
@@ -14,7 +14,7 @@
 
 FROM debian:stretch
 
-RUN apt-get -qq update && apt-get -qq install -y \
+RUN apt-get -qq update && apt-get -qq -y upgrade && apt-get -qq install -y \
   autoconf build-essential git libtool \
   libcurl4-openssl-dev libedit-dev libsodium-dev \
   libssl-dev libxml2-dev \
index 4369568..c7e6ea5 100644 (file)
@@ -14,7 +14,7 @@
 
 FROM php:7.2-zts-stretch
 
-RUN apt-get -qq update && apt-get -qq install -y \
+RUN apt-get -qq update && apt-get -qq -y upgrade && apt-get -qq install -y \
   autoconf automake git libtool pkg-config \
   wget zlib1g-dev
 
index 330c0d5..d70b75d 100644 (file)
@@ -14,7 +14,7 @@
 
 FROM php:8.0.0-zts-buster
 
-RUN apt-get -qq update && apt-get -qq install -y \
+RUN apt-get -qq update && apt-get -qq -y upgrade && apt-get -qq install -y \
   autoconf automake git libtool pkg-config \
   valgrind wget zlib1g-dev
 
index 34b4c82..7d9de6a 100644 (file)
@@ -139,10 +139,10 @@ PHP_METHOD(ChannelCredentials, createDefault) {
 
 /**
  * Create SSL credentials.
- * @param string $pem_root_certs = "" PEM encoding of the server root certificates (optional)
- * @param string $private_key = "" PEM encoding of the client's
+ * @param string|null $pem_root_certs = null PEM encoding of the server root certificates (optional)
+ * @param string|null $private_key = null PEM encoding of the client's
  *                                              private key (optional)
- * @param string $cert_chain = "" PEM encoding of the client's
+ * @param string|null $cert_chain = null PEM encoding of the client's
  *                                             certificate chain (optional)
  * @return ChannelCredentials The new SSL credentials object
  */
index e29c921..a88f4aa 100644 (file)
@@ -20,6 +20,6 @@
 #ifndef VERSION_H
 #define VERSION_H
 
-#define PHP_GRPC_VERSION "1.41.1"
+#define PHP_GRPC_VERSION "1.42.0"
 
 #endif /* VERSION_H */
index 20477ab..1edb03f 100644 (file)
@@ -31,6 +31,34 @@ abstract class AbstractGeneratedCodeTest extends \PHPUnit\Framework\TestCase
      */
     protected static $client;
 
+    protected static $clientOptions = array(
+        'grpc.service_config' => '{
+            "loadBalancingPolicy": "round_robin",
+            "methodConfig": [
+              {
+                "name": [
+                  {
+                    "service": "math.Math"
+                  }
+                ],
+                "waitForReady": true,
+                "retryPolicy": {
+                  "maxAttempts": 2,
+                  "initialBackoff": "0.2s",
+                  "maxBackoff": "4s",
+                  "backoffMultiplier": 2,
+                  "retryableStatusCodes": [
+                    "UNAVAILABLE",
+                    "RESOURCE_EXHAUSTED",
+                    "DEADLINE_EXCEEDED"
+                  ]
+                }
+              }
+            ]
+          }',
+        'grpc.enable_retries' => 1,
+    );
+
     public function testWaitForNotReady()
     {
         $this->assertFalse(self::$client->waitForReady(1));
@@ -131,6 +159,22 @@ abstract class AbstractGeneratedCodeTest extends \PHPUnit\Framework\TestCase
         $this->assertSame(\Grpc\STATUS_CANCELLED, $status->code);
     }
 
+    public function testRetry()
+    {
+        $metadata = [
+            'response-unavailable' => [
+                'server response STATUS_UNAVAILABLE so client will retry'
+            ],
+        ];
+        $div_arg = new Math\DivArgs();
+        $div_arg->setDividend(7);
+        $div_arg->setDivisor(4);
+        $call = self::$client->Div($div_arg, $metadata);
+        list($response, $status) = $call->wait();
+        $this->assertSame(\Grpc\STATUS_UNAVAILABLE, $status->code);
+        $this->assertSame('1', $status->metadata['unavailable-retry-attempts'][0]);
+    }
+
     public function testCallCredentialsCallback()
     {
         $div_arg = new Math\DivArgs();
index f2e5c8c..72a1376 100755 (executable)
@@ -27,8 +27,8 @@ class GeneratedCodeTest extends AbstractGeneratedCodeTest
                 'credentials' => Grpc\ChannelCredentials::createSsl(
                     file_get_contents(dirname(__FILE__).'/../data/ca.pem')),
                 'grpc.ssl_target_name_override' => 'foo.test.google.fr',
-        
-            ]);
+            ] + self::$clientOptions
+        );
     }
 
     public function tearDown(): void
index 98f293a..c912686 100644 (file)
@@ -34,7 +34,8 @@ class GeneratedCodeWithCallbackTest extends AbstractGeneratedCodeTest
 
                                 return $a_copy;
                               },
-         ]);
+            ] + self::$clientOptions
+        );
     }
 
     public function tearDown(): void
index d91a5a5..7301f0f 100644 (file)
@@ -36,6 +36,21 @@ class MathService extends Math\MathStub
             );
             return null;
         }
+        // for GeneratedCodeTest::testRetry
+        $metadata = $context->clientMetadata();
+        if (array_key_exists('response-unavailable', $metadata)) {
+            $trailingMetadata = array_key_exists('grpc-previous-rpc-attempts', $metadata)
+            ? ['unavailable-retry-attempts' => $metadata['grpc-previous-rpc-attempts']]
+            : null;
+            $context->setStatus(
+                \Grpc\Status::status(
+                    \Grpc\STATUS_UNAVAILABLE,
+                    "unavailable",
+                    $trailingMetadata
+                )
+            );
+            return null;
+        }
         usleep(1000); // for GeneratedCodeTest::testTimeout
         $quotient = intdiv($dividend, $divisor);
         $remainder = $dividend % $divisor;
index 6aa9c12..03a8ce1 100644 (file)
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 load("@rules_proto//proto:defs.bzl", "proto_library")
 load("//bazel:grpc_build_system.bzl", "grpc_package", "grpc_proto_library")
index c79e15d..073c68e 100644 (file)
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 load("//bazel:grpc_build_system.bzl", "grpc_package", "grpc_proto_library")
 load("//bazel:python_rules.bzl", "py_proto_library")
index 96e287f..fd7c7b4 100644 (file)
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 load("@rules_proto//proto:defs.bzl", "proto_library")
 
index 9caa531..702f5b0 100644 (file)
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 load("@rules_proto//proto:defs.bzl", "proto_library")
 load("//bazel:grpc_build_system.bzl", "grpc_package", "grpc_proto_library")
index 0fb1033..c27ad5e 100644 (file)
@@ -14,7 +14,7 @@
 
 load("//bazel:grpc_build_system.bzl", "grpc_package", "grpc_proto_library")
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 grpc_package(
     name = "http_over_grpc",
index 44ffebe..882c8a5 100644 (file)
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 load("@rules_proto//proto:defs.bzl", "proto_library")
 load("//bazel:grpc_build_system.bzl", "grpc_package", "grpc_proto_library")
diff --git a/src/proto/grpc/lookup/v1/BUILD b/src/proto/grpc/lookup/v1/BUILD
new file mode 100644 (file)
index 0000000..767a151
--- /dev/null
@@ -0,0 +1,34 @@
+# 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.
+
+licenses(["notice"])
+
+load("@rules_proto//proto:defs.bzl", "proto_library")
+load("//bazel:grpc_build_system.bzl", "grpc_package", "grpc_proto_library")
+
+grpc_package(
+    name = "src/proto/grpc/lookup/v1",
+    visibility = "public",
+)
+
+grpc_proto_library(
+    name = "rls_proto",
+    srcs = ["rls.proto"],
+    well_known_protos = True,
+)
+
+proto_library(
+    name = "rls_proto_descriptor",
+    srcs = ["rls.proto"],
+)
diff --git a/src/proto/grpc/lookup/v1/rls.proto b/src/proto/grpc/lookup/v1/rls.proto
new file mode 100644 (file)
index 0000000..7d17352
--- /dev/null
@@ -0,0 +1,62 @@
+// Copyright 2020 The gRPC Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+syntax = "proto3";
+
+package grpc.lookup.v1;
+
+option go_package = "google.golang.org/grpc/lookup/grpc_lookup_v1";
+option java_multiple_files = true;
+option java_package = "io.grpc.lookup.v1";
+option java_outer_classname = "RlsProto";
+
+message RouteLookupRequest {
+  // Target type allows the client to specify what kind of target format it
+  // would like from RLS to allow it to find the regional server, e.g. "grpc".
+  string target_type = 3;
+  // Possible reasons for making a request.
+  enum Reason {
+    REASON_UNKNOWN = 0;  // Unused
+    REASON_MISS = 1;     // No data available in local cache
+    REASON_STALE = 2;    // Data in local cache is stale
+  }
+  // Reason for making this request.
+  Reason reason = 5;
+  // For REASON_STALE, the header_data from the stale response, if any.
+  string stale_header_data = 6;
+  // Map of key values extracted via key builders for the gRPC or HTTP request.
+  map<string, string> key_map = 4;
+
+  reserved 1, 2;
+  reserved "server", "path";
+}
+
+message RouteLookupResponse {
+  // Prioritized list (best one first) of addressable entities to use
+  // for routing, using syntax requested by the request target_type.
+  // The targets will be tried in order until a healthy one is found.
+  repeated string targets = 3;
+  // Optional header value to pass along to AFE in the X-Google-RLS-Data header.
+  // Cached with "target" and sent with all requests that match the request key.
+  // Allows the RLS to pass its work product to the eventual target.
+  string header_data = 2;
+
+  reserved 1;
+  reserved "target";
+}
+
+service RouteLookupService {
+  // Lookup returns a target for a single key.
+  rpc RouteLookup(RouteLookupRequest) returns (RouteLookupResponse) {}
+}
index e782455..cb8e8c5 100644 (file)
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 load("@rules_proto//proto:defs.bzl", "proto_library")
 load("//bazel:grpc_build_system.bzl", "grpc_package", "grpc_proto_library")
index ed8c29c..cd4501a 100644 (file)
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 load("//bazel:grpc_build_system.bzl", "grpc_package", "grpc_proto_library")
 
index c67a7f8..9d462f0 100644 (file)
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 load("@grpc_python_dependencies//:requirements.bzl", "requirement")
 load("@rules_proto//proto:defs.bzl", "proto_library")
index d7902c1..90756ad 100644 (file)
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 load("//bazel:grpc_build_system.bzl", "grpc_package", "grpc_proto_library")
 
index 5dd5795..6ae8825 100644 (file)
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 load("//bazel:grpc_build_system.bzl", "grpc_package", "grpc_proto_library")
 
@@ -69,10 +69,3 @@ grpc_proto_library(
     well_known_protos = True,
     deps = ["eds_for_test_proto"],
 )
-
-grpc_proto_library(
-    name = "orca_load_report_for_test_proto",
-    srcs = [
-        "orca_load_report_for_test.proto",
-    ],
-)
diff --git a/src/proto/grpc/testing/xds/orca_load_report_for_test.proto b/src/proto/grpc/testing/xds/orca_load_report_for_test.proto
deleted file mode 100644 (file)
index 1feaedd..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2019 The gRPC Authors
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// This file contains a copy of the ORCA load reporting protos, with the
-// validation options stripped out to avoid the extra dependency on
-// protoc-gen-validate.
-//
-// TODO(juanlishen): This file is a hack to avoid a problem we're
-// currently having where we can't depend on a proto file in an external
-// repo due to bazel limitations.  Once that's fixed, this should be
-// removed.  Until this, it should be used in the gRPC tests only, or else it
-// will cause a conflict due to the same proto messages being defined in
-// multiple files in the same binary.
-
-syntax = "proto3";
-
-package udpa.data.orca.v1;
-
-option java_outer_classname = "OrcaLoadReportProto";
-option java_multiple_files = true;
-option java_package = "io.envoyproxy.udpa.data.orca.v1";
-option go_package = "v1";
-
-// See section `ORCA load report format` of the design document in
-// :ref:`https://github.com/envoyproxy/envoy/issues/6614`.
-
-message OrcaLoadReport {
-  // CPU utilization expressed as a fraction of available CPU resources. This
-  // should be derived from the latest sample or measurement.
-  double cpu_utilization = 1;
-
-  // Memory utilization expressed as a fraction of available memory
-  // resources. This should be derived from the latest sample or measurement.
-  double mem_utilization = 2;
-
-  // Total RPS being served by an endpoint. This should cover all services that an endpoint is
-  // responsible for.
-  uint64 rps = 3;
-
-  // Application specific requests costs. Each value is an absolute cost (e.g. 3487 bytes of
-  // storage) associated with the request.
-  map<string, double> request_cost = 4;
-
-  // Resource utilization values. Each value is expressed as a fraction of total resources
-  // available, derived from the latest sample or measurement.
-  map<string, double> utilization = 5;
-}
index 0d79e5e..c6f15df 100644 (file)
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 load("//bazel:grpc_build_system.bzl", "grpc_package", "grpc_proto_library")
 load("//bazel:python_rules.bzl", "py_grpc_library", "py_proto_library")
index bbdfd4e..79b8bc8 100644 (file)
@@ -21,6 +21,9 @@ package envoy.service.status.v3;
 import "src/proto/grpc/testing/xds/v3/config_dump.proto";
 import "src/proto/grpc/testing/xds/v3/base.proto";
 
+import "google/protobuf/any.proto";
+import "google/protobuf/timestamp.proto";
+
 
 // CSDS is Client Status Discovery Service. It can be used to get the status of
 // an xDS-compliant client from the management server's point of view. It can
@@ -77,10 +80,58 @@ message PerXdsConfig {
 
 // All xds configs for a particular client.
 message ClientConfig {
+  // GenericXdsConfig is used to specify the config status and the dump
+  // of any xDS resource identified by their type URL. It is the generalized
+  // version of the now deprecated ListenersConfigDump, ClustersConfigDump etc
+  // [#next-free-field: 10]
+  message GenericXdsConfig {
+    // Type_url represents the fully qualified name of xDS resource type
+    // like envoy.v3.Cluster, envoy.v3.ClusterLoadAssignment etc.
+    string type_url = 1;
+
+    // Name of the xDS resource
+    string name = 2;
+
+    // This is the :ref:`version_info <envoy_v3_api_field_service.discovery.v3.DiscoveryResponse.version_info>`
+    // in the last processed xDS discovery response. If there are only
+    // static bootstrap listeners, this field will be ""
+    string version_info = 3;
+
+    // The xDS resource config. Actual content depends on the type
+    google.protobuf.Any xds_config = 4;
+
+    // Timestamp when the xDS resource was last updated
+    google.protobuf.Timestamp last_updated = 5;
+
+    // Per xDS resource config status. It is generated by management servers.
+    // It will not be present if the CSDS server is an xDS client.
+    ConfigStatus config_status = 6;
+
+    // Per xDS resource status from the view of a xDS client
+    admin.v3.ClientResourceStatus client_status = 7;
+
+    // Set if the last update failed, cleared after the next successful
+    // update. The *error_state* field contains the rejected version of
+    // this particular resource along with the reason and timestamp. For
+    // successfully updated or acknowledged resource, this field should
+    // be empty.
+    admin.v3.UpdateFailureState error_state = 8;
+
+    // Is static resource is true if it is specified in the config supplied
+    // through the file at the startup.
+    bool is_static_resource = 9;
+  }
+
   // Node for a particular client.
   config.core.v3.Node node = 1;
 
-  repeated PerXdsConfig xds_config = 2;
+  // This field is deprecated in favor of generic_xds_configs which is
+  // much simpler and uniform in structure.
+  repeated PerXdsConfig xds_config = 2 [deprecated = true];
+
+  // Represents generic xDS config and the exact config structure depends on
+  // the type URL (like Cluster if it is CDS)
+  repeated GenericXdsConfig generic_xds_configs = 3;
 }
 
 message ClientStatusResponse {
index 0d6a169..033e64b 100644 (file)
@@ -16,7 +16,7 @@
 
 syntax = "proto3";
 
-package udpa.data.orca.v1;
+package xds.data.orca.v3;
 
 // See section `ORCA load report format` of the design document in
 // :ref:`https://github.com/envoyproxy/envoy/issues/6614`.
index 8b0bd1a..7109fe2 100644 (file)
@@ -103,12 +103,21 @@ message Route {
   // Route matching parameters.
   RouteMatch match = 1;
 
+  message NonForwardingAction {
+  }  
+
   oneof action {
     // Route request to some upstream cluster.
     RouteAction route = 2;
 
     // Return a redirect.
     RedirectAction redirect = 3;
+
+    // An action used when the route will generate a response directly,
+    // without forwarding to an upstream host. This will be used in non-proxy
+    // xDS clients like the gRPC server. It could also be used in the future
+    // in Envoy for a filter that directly generates responses for requests.
+    NonForwardingAction non_forwarding_action = 18;
   }
 
   // The typed_per_filter_config field can be used to provide route-specific
index f759fbb..d5113ae 100644 (file)
@@ -56,7 +56,7 @@ class _EOF:
 
     def __bool__(self):
         return False
-    
+
     def __len__(self):
         return 0
 
@@ -144,7 +144,7 @@ async def generator_to_async_generator(object gen, object loop, object thread_po
         TypeError: StopIteration interacts badly with generators and cannot be
             raised into a Future
     """
-    queue = asyncio.Queue(maxsize=1, loop=loop)
+    queue = asyncio.Queue(maxsize=1)
 
     def yield_to_queue():
         try:
index 4651a6b..fe10c38 100644 (file)
@@ -33,6 +33,7 @@ cdef class RPCState(GrpcCallWrapper):
     cdef tuple trailing_metadata
     cdef object compression_algorithm
     cdef bint disable_next_compression
+    cdef object callbacks
 
     cdef bytes method(self)
     cdef tuple invocation_metadata(self)
index 2b46c0c..2976ca4 100644 (file)
@@ -59,6 +59,7 @@ cdef class RPCState:
         self.trailing_metadata = _IMMUTABLE_EMPTY_METADATA
         self.compression_algorithm = None
         self.disable_next_compression = False
+        self.callbacks = []
 
     cdef bytes method(self):
         return _slice_bytes(self.details.method)
@@ -173,11 +174,16 @@ cdef class _ServicerContext:
 
             if trailing_metadata == _IMMUTABLE_EMPTY_METADATA and self._rpc_state.trailing_metadata:
                 trailing_metadata = self._rpc_state.trailing_metadata
+            else:
+                self._rpc_state.trailing_metadata = trailing_metadata
 
             if details == '' and self._rpc_state.status_details:
                 details = self._rpc_state.status_details
+            else:
+                self._rpc_state.status_details = details
 
             actual_code = get_status_code(code)
+            self._rpc_state.status_code = actual_code
 
             self._rpc_state.status_sent = True
             await _send_error_status_from_server(
@@ -267,6 +273,16 @@ cdef class _ServicerContext:
         else:
             return max(_time_from_timespec(self._rpc_state.details.deadline) - time.time(), 0)
 
+    def add_done_callback(self, callback):
+        cb = functools.partial(callback, self)
+        self._rpc_state.callbacks.append(cb)
+
+    def done(self):
+        return self._rpc_state.status_sent
+
+    def cancelled(self):
+        return self._rpc_state.status_code == StatusCode.cancelled
+
 
 cdef class _SyncServicerContext:
     """Sync servicer context for sync handler compatibility."""
@@ -697,6 +713,7 @@ async def _handle_exceptions(RPCState rpc_state, object rpc_coro, object loop):
             else:
                 status_code = rpc_state.status_code
 
+            rpc_state.status_sent = True
             await _send_error_status_from_server(
                 rpc_state,
                 status_code,
@@ -707,6 +724,19 @@ async def _handle_exceptions(RPCState rpc_state, object rpc_coro, object loop):
             )
 
 
+cdef _add_callback_handler(object rpc_task, RPCState rpc_state):
+
+    def handle_callbacks(object unused_task):
+        try:
+            for callback in rpc_state.callbacks:
+                # The _ServicerContext object is bound in add_done_callback.
+                callback()
+        except:
+            _LOGGER.exception('Error in callback for method [%s]', _decode(rpc_state.method()))
+
+    rpc_task.add_done_callback(handle_callbacks)
+
+
 async def _handle_cancellation_from_core(object rpc_task,
                                          RPCState rpc_state,
                                          object loop):
@@ -733,6 +763,7 @@ async def _schedule_rpc_coro(object rpc_coro,
         rpc_coro,
         loop,
     ))
+    _add_callback_handler(rpc_task, rpc_state)
     await _handle_cancellation_from_core(rpc_task, rpc_state, loop)
 
 
@@ -854,7 +885,7 @@ cdef class AioServer:
         self.add_generic_rpc_handlers(generic_handlers)
         self._serving_task = None
 
-        self._shutdown_lock = asyncio.Lock(loop=self._loop)
+        self._shutdown_lock = asyncio.Lock()
         self._shutdown_completed = self._loop.create_future()
         self._shutdown_callback_wrapper = CallbackWrapper(
             self._shutdown_completed,
@@ -863,7 +894,7 @@ cdef class AioServer:
         self._crash_exception = None
 
         if interceptors:
-            self._interceptors = interceptors
+            self._interceptors = tuple(interceptors)
         else:
             self._interceptors = ()
 
@@ -1008,12 +1039,8 @@ cdef class AioServer:
         else:
             try:
                 await asyncio.wait_for(
-                    asyncio.shield(
-                        self._shutdown_completed,
-                        loop=self._loop
-                    ),
+                    asyncio.shield(self._shutdown_completed),
                     grace,
-                    loop=self._loop,
                 )
             except asyncio.TimeoutError:
                 # Cancels all ongoing calls by the end of grace period.
@@ -1033,12 +1060,8 @@ cdef class AioServer:
         else:
             try:
                 await asyncio.wait_for(
-                    asyncio.shield(
-                        self._shutdown_completed,
-                        loop=self._loop,
-                    ),
+                    asyncio.shield(self._shutdown_completed),
                     timeout,
-                    loop=self._loop,
                 )
             except asyncio.TimeoutError:
                 if self._crash_exception is not None:
index cb5fad9..5eb5f08 100644 (file)
@@ -73,6 +73,7 @@ cdef class CompletionQueue:
       c_attrs.version = 1
       c_attrs.cq_completion_type = GRPC_CQ_NEXT
       c_attrs.cq_polling_type = GRPC_CQ_NON_LISTENING
+      c_attrs.cq_shutdown_cb = NULL
       self.c_completion_queue = grpc_completion_queue_create(
           grpc_completion_queue_factory_lookup(&c_attrs), &c_attrs, NULL);
     else:
index 6698dd6..684e0a3 100644 (file)
@@ -236,6 +236,7 @@ cdef extern from "grpc/grpc.h":
     int version
     grpc_cq_completion_type cq_completion_type
     grpc_cq_polling_type cq_polling_type
+    void* cq_shutdown_cb
 
   ctypedef enum grpc_connectivity_state:
     GRPC_CHANNEL_IDLE
@@ -702,4 +703,5 @@ cdef extern from "grpc/grpc_security_constants.h":
 
 
 cdef extern from "src/core/lib/iomgr/error.h":
-  const grpc_error* GRPC_ERROR_CANCELLED
+  ctypedef grpc_error* grpc_error_handle
+  grpc_error_handle GRPC_ERROR_CANCELLED
index 22b4766..9aa012d 100644 (file)
@@ -357,7 +357,7 @@ def _run_loop(timeout_ms):
     finally:
       g_event.clear()
 
-cdef grpc_error* run_loop(size_t timeout_ms) with gil:
+cdef grpc_error_handle run_loop(size_t timeout_ms) with gil:
   try:
     _run_loop(timeout_ms)
     return grpc_error_none()
index b427554..5f4a51f 100644 (file)
@@ -110,7 +110,7 @@ cdef extern from "src/core/lib/iomgr/timer_custom.h":
 cdef extern from "src/core/lib/iomgr/pollset_custom.h":
   struct grpc_custom_poller_vtable:
     void (*init)()
-    grpc_error* (*poll)(size_t timeout_ms)
+    grpc_error_handle (*poll)(size_t timeout_ms)
     void (*kick)()
     void (*shutdown)()
 
index 84c8ded..07cb321 100644 (file)
@@ -14,4 +14,4 @@
 
 # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc/_grpcio_metadata.py.template`!!!
 
-__version__ = """1.41.1"""
+__version__ = """1.42.0"""
index dc307c8..24be924 100644 (file)
@@ -19,8 +19,8 @@ from typing import Any, Optional
 import grpc
 
 from . import _base_call
-from ._metadata import Metadata
 from ._typing import DeserializingFunction
+from ._typing import MetadataType
 from ._typing import RequestIterableType
 from ._typing import SerializingFunction
 
@@ -34,7 +34,7 @@ class UnaryUnaryMultiCallable(abc.ABC):
         request: Any,
         *,
         timeout: Optional[float] = None,
-        metadata: Optional[Metadata] = None,
+        metadata: Optional[MetadataType] = None,
         credentials: Optional[grpc.CallCredentials] = None,
         wait_for_ready: Optional[bool] = None,
         compression: Optional[grpc.Compression] = None
@@ -73,7 +73,7 @@ class UnaryStreamMultiCallable(abc.ABC):
         request: Any,
         *,
         timeout: Optional[float] = None,
-        metadata: Optional[Metadata] = None,
+        metadata: Optional[MetadataType] = None,
         credentials: Optional[grpc.CallCredentials] = None,
         wait_for_ready: Optional[bool] = None,
         compression: Optional[grpc.Compression] = None
@@ -111,7 +111,7 @@ class StreamUnaryMultiCallable(abc.ABC):
         self,
         request_iterator: Optional[RequestIterableType] = None,
         timeout: Optional[float] = None,
-        metadata: Optional[Metadata] = None,
+        metadata: Optional[MetadataType] = None,
         credentials: Optional[grpc.CallCredentials] = None,
         wait_for_ready: Optional[bool] = None,
         compression: Optional[grpc.Compression] = None
@@ -150,7 +150,7 @@ class StreamStreamMultiCallable(abc.ABC):
         self,
         request_iterator: Optional[RequestIterableType] = None,
         timeout: Optional[float] = None,
-        metadata: Optional[Metadata] = None,
+        metadata: Optional[MetadataType] = None,
         credentials: Optional[grpc.CallCredentials] = None,
         wait_for_ready: Optional[bool] = None,
         compression: Optional[grpc.Compression] = None
index 225def4..263ac8d 100644 (file)
@@ -19,6 +19,8 @@ from typing import Generic, Iterable, Mapping, Optional, Sequence
 import grpc
 
 from ._metadata import Metadata
+from ._typing import DoneCallbackType
+from ._typing import MetadataType
 from ._typing import RequestType
 from ._typing import ResponseType
 
@@ -132,6 +134,7 @@ class Server(abc.ABC):
         """
 
 
+# pylint: disable=too-many-public-methods
 class ServicerContext(Generic[RequestType, ResponseType], abc.ABC):
     """A context object passed to method implementations."""
 
@@ -159,7 +162,8 @@ class ServicerContext(Generic[RequestType, ResponseType], abc.ABC):
         """
 
     @abc.abstractmethod
-    async def send_initial_metadata(self, initial_metadata: Metadata) -> None:
+    async def send_initial_metadata(self,
+                                    initial_metadata: MetadataType) -> None:
         """Sends the initial metadata value to the client.
 
         This method need not be called by implementations if they have no
@@ -174,7 +178,7 @@ class ServicerContext(Generic[RequestType, ResponseType], abc.ABC):
         self,
         code: grpc.StatusCode,
         details: str = '',
-        trailing_metadata: Metadata = tuple()) -> None:
+        trailing_metadata: MetadataType = tuple()) -> None:
         """Raises an exception to terminate the RPC with a non-OK status.
 
         The code and details passed as arguments will supercede any existing
@@ -194,7 +198,7 @@ class ServicerContext(Generic[RequestType, ResponseType], abc.ABC):
         """
 
     @abc.abstractmethod
-    def set_trailing_metadata(self, trailing_metadata: Metadata) -> None:
+    def set_trailing_metadata(self, trailing_metadata: MetadataType) -> None:
         """Sends the trailing metadata for the RPC.
 
         This method need not be called by implementations if they have no
@@ -335,3 +339,35 @@ class ServicerContext(Generic[RequestType, ResponseType], abc.ABC):
           The details string of the RPC.
         """
         raise NotImplementedError()
+
+    def add_done_callback(self, callback: DoneCallbackType) -> None:
+        """Registers a callback to be called on RPC termination.
+
+        This is an EXPERIMENTAL API.
+
+        Args:
+          callback: A callable object will be called with the servicer context
+            object as its only argument.
+        """
+
+    def cancelled(self) -> bool:
+        """Return True if the RPC is cancelled.
+
+        The RPC is cancelled when the cancellation was requested with cancel().
+
+        This is an EXPERIMENTAL API.
+
+        Returns:
+          A bool indicates whether the RPC is cancelled or not.
+        """
+
+    def done(self) -> bool:
+        """Return True if the RPC is done.
+
+        An RPC is done if the RPC is completed, cancelled or aborted.
+
+        This is an EXPERIMENTAL API.
+
+        Returns:
+          A bool indicates if the RPC is done.
+        """
index ef3a624..31f7ea1 100644 (file)
@@ -165,7 +165,7 @@ class Call:
     _loop: asyncio.AbstractEventLoop
     _code: grpc.StatusCode
     _cython_call: cygrpc._AioCall
-    _metadata: Tuple[MetadatumType]
+    _metadata: Tuple[MetadatumType, ...]
     _request_serializer: SerializingFunction
     _response_deserializer: DeserializingFunction
 
@@ -371,7 +371,7 @@ class _StreamRequestMixin(Call):
 
     def _init_stream_request_mixin(
             self, request_iterator: Optional[RequestIterableType]):
-        self._metadata_sent = asyncio.Event(loop=self._loop)
+        self._metadata_sent = asyncio.Event()
         self._done_writing_flag = False
 
         # If user passes in an async iterator, create a consumer Task.
@@ -444,6 +444,8 @@ class _StreamRequestMixin(Call):
                                                self._request_serializer)
         try:
             await self._cython_call.send_serialized_message(serialized_request)
+        except cygrpc.InternalError:
+            await self._raise_for_status()
         except asyncio.CancelledError:
             if not self.cancelled():
                 self.cancel()
index 560df92..442a4ce 100644 (file)
@@ -358,7 +358,7 @@ class Channel(_base_channel.Channel):
         # If needed, try to wait for them to finish.
         # Call objects are not always awaitables.
         if grace and call_tasks:
-            await asyncio.wait(call_tasks, timeout=grace, loop=self._loop)
+            await asyncio.wait(call_tasks, timeout=grace)
 
         # Time to cancel existing calls.
         for call in calls:
index 8d6519f..8614c73 100644 (file)
@@ -475,6 +475,7 @@ class _InterceptedStreamRequestMixin:
 
     _write_to_iterator_async_gen: Optional[AsyncIterable[RequestType]]
     _write_to_iterator_queue: Optional[asyncio.Queue]
+    _status_code_task: Optional[asyncio.Task]
 
     _FINISH_ITERATOR_SENTINEL = object()
 
@@ -488,6 +489,7 @@ class _InterceptedStreamRequestMixin:
             self._write_to_iterator_queue = asyncio.Queue(maxsize=1)
             self._write_to_iterator_async_gen = self._proxy_writes_as_request_iterator(
             )
+            self._status_code_task = None
             request_iterator = self._write_to_iterator_async_gen
         else:
             self._write_to_iterator_queue = None
@@ -503,6 +505,19 @@ class _InterceptedStreamRequestMixin:
                 break
             yield value
 
+    async def _write_to_iterator_queue_interruptible(self, request: RequestType,
+                                                     call: InterceptedCall):
+        # Write the specified 'request' to the request iterator queue using the
+        # specified 'call' to allow for interruption of the write in the case
+        # of abrupt termination of the call.
+        if self._status_code_task is None:
+            self._status_code_task = self._loop.create_task(call.code())
+
+        await asyncio.wait(
+            (self._loop.create_task(self._write_to_iterator_queue.put(request)),
+             self._status_code_task),
+            return_when=asyncio.FIRST_COMPLETED)
+
     async def write(self, request: RequestType) -> None:
         # If no queue was created it means that requests
         # should be expected through an iterators provided
@@ -520,11 +535,7 @@ class _InterceptedStreamRequestMixin:
         elif call._done_writing_flag:
             raise asyncio.InvalidStateError(_RPC_HALF_CLOSED_DETAILS)
 
-        # Write might never end up since the call could abrubtly finish,
-        # we give up on the first awaitable object that finishes.
-        _, _ = await asyncio.wait(
-            (self._write_to_iterator_queue.put(request), call.code()),
-            return_when=asyncio.FIRST_COMPLETED)
+        await self._write_to_iterator_queue_interruptible(request, call)
 
         if call.done():
             raise asyncio.InvalidStateError(_RPC_ALREADY_FINISHED_DETAILS)
@@ -545,12 +556,8 @@ class _InterceptedStreamRequestMixin:
         except asyncio.CancelledError:
             raise asyncio.InvalidStateError(_RPC_ALREADY_FINISHED_DETAILS)
 
-        # Write might never end up since the call could abrubtly finish,
-        # we give up on the first awaitable object that finishes.
-        _, _ = await asyncio.wait((self._write_to_iterator_queue.put(
-            _InterceptedStreamRequestMixin._FINISH_ITERATOR_SENTINEL),
-                                   call.code()),
-                                  return_when=asyncio.FIRST_COMPLETED)
+        await self._write_to_iterator_queue_interruptible(
+            _InterceptedStreamRequestMixin._FINISH_ITERATOR_SENTINEL, call)
 
 
 class InterceptedUnaryUnaryCall(_InterceptedUnaryResponseMixin, InterceptedCall,
index 0687187..f9c0eb1 100644 (file)
@@ -27,7 +27,7 @@ ResponseType = TypeVar('ResponseType')
 SerializingFunction = Callable[[Any], bytes]
 DeserializingFunction = Callable[[bytes], Any]
 MetadatumType = Tuple[MetadataKey, MetadataValue]
-MetadataType = Metadata
+MetadataType = Union[Metadata, Sequence[MetadatumType]]
 ChannelArgumentType = Sequence[Tuple[str, Any]]
 EOFType = type(EOF)
 DoneCallbackType = Callable[[Any], None]
index 774175d..78d603d 100644 (file)
@@ -41,6 +41,7 @@ CORE_SOURCE_FILES = [
     'src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc',
     'src/core/ext/filters/client_channel/lb_policy/priority/priority.cc',
     'src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc',
+    'src/core/ext/filters/client_channel/lb_policy/rls/rls.cc',
     'src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc',
     'src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc',
     'src/core/ext/filters/client_channel/lb_policy/xds/cds.cc',
@@ -51,6 +52,7 @@ CORE_SOURCE_FILES = [
     'src/core/ext/filters/client_channel/local_subchannel_pool.cc',
     'src/core/ext/filters/client_channel/proxy_mapper_registry.cc',
     'src/core/ext/filters/client_channel/resolver.cc',
+    'src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc',
     'src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc',
     'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_event_engine.cc',
     'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc',
@@ -71,12 +73,11 @@ CORE_SOURCE_FILES = [
     'src/core/ext/filters/client_channel/retry_service_config.cc',
     'src/core/ext/filters/client_channel/retry_throttle.cc',
     'src/core/ext/filters/client_channel/server_address.cc',
-    'src/core/ext/filters/client_channel/service_config.cc',
     'src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc',
-    'src/core/ext/filters/client_channel/service_config_parser.cc',
     'src/core/ext/filters/client_channel/subchannel.cc',
     'src/core/ext/filters/client_channel/subchannel_pool_interface.cc',
     'src/core/ext/filters/client_idle/client_idle_filter.cc',
+    'src/core/ext/filters/client_idle/idle_filter_state.cc',
     'src/core/ext/filters/deadline/deadline_filter.cc',
     'src/core/ext/filters/fault_injection/fault_injection_filter.cc',
     'src/core/ext/filters/fault_injection/service_config_parser.cc',
@@ -88,10 +89,9 @@ CORE_SOURCE_FILES = [
     'src/core/ext/filters/http/server/http_server_filter.cc',
     'src/core/ext/filters/max_age/max_age_filter.cc',
     'src/core/ext/filters/message_size/message_size_filter.cc',
-    'src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc',
-    'src/core/ext/filters/workarounds/workaround_utils.cc',
+    'src/core/ext/service_config/service_config.cc',
+    'src/core/ext/service_config/service_config_parser.cc',
     'src/core/ext/transport/chttp2/alpn/alpn.cc',
-    'src/core/ext/transport/chttp2/client/authority.cc',
     'src/core/ext/transport/chttp2/client/chttp2_connector.cc',
     'src/core/ext/transport/chttp2/client/insecure/channel_create.cc',
     'src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc',
@@ -103,7 +103,6 @@ CORE_SOURCE_FILES = [
     'src/core/ext/transport/chttp2/transport/bin_decoder.cc',
     'src/core/ext/transport/chttp2/transport/bin_encoder.cc',
     'src/core/ext/transport/chttp2/transport/chttp2_plugin.cc',
-    'src/core/ext/transport/chttp2/transport/chttp2_slice_allocator.cc',
     'src/core/ext/transport/chttp2/transport/chttp2_transport.cc',
     'src/core/ext/transport/chttp2/transport/context_list.cc',
     'src/core/ext/transport/chttp2/transport/flow_control.cc',
@@ -120,7 +119,6 @@ CORE_SOURCE_FILES = [
     'src/core/ext/transport/chttp2/transport/hpack_utils.cc',
     'src/core/ext/transport/chttp2/transport/http2_settings.cc',
     'src/core/ext/transport/chttp2/transport/huffsyms.cc',
-    'src/core/ext/transport/chttp2/transport/incoming_metadata.cc',
     'src/core/ext/transport/chttp2/transport/parsing.cc',
     'src/core/ext/transport/chttp2/transport/stream_lists.cc',
     'src/core/ext/transport/chttp2/transport/stream_map.cc',
@@ -217,20 +215,22 @@ CORE_SOURCE_FILES = [
     'src/core/ext/upb-generated/src/proto/grpc/gcp/transport_security_common.upb.c',
     'src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.c',
     'src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c',
+    'src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls.upb.c',
     'src/core/ext/upb-generated/udpa/annotations/migrate.upb.c',
     'src/core/ext/upb-generated/udpa/annotations/security.upb.c',
     'src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c',
     'src/core/ext/upb-generated/udpa/annotations/status.upb.c',
     'src/core/ext/upb-generated/udpa/annotations/versioning.upb.c',
-    'src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c',
-    'src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.c',
     'src/core/ext/upb-generated/validate/validate.upb.c',
+    'src/core/ext/upb-generated/xds/annotations/v3/status.upb.c',
     'src/core/ext/upb-generated/xds/core/v3/authority.upb.c',
     'src/core/ext/upb-generated/xds/core/v3/collection_entry.upb.c',
     'src/core/ext/upb-generated/xds/core/v3/context_params.upb.c',
     'src/core/ext/upb-generated/xds/core/v3/resource.upb.c',
     'src/core/ext/upb-generated/xds/core/v3/resource_locator.upb.c',
     'src/core/ext/upb-generated/xds/core/v3/resource_name.upb.c',
+    'src/core/ext/upb-generated/xds/data/orca/v3/orca_load_report.upb.c',
+    'src/core/ext/upb-generated/xds/type/v3/typed_struct.upb.c',
     'src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.c',
     'src/core/ext/upbdefs-generated/envoy/annotations/deprecation.upbdefs.c',
     'src/core/ext/upbdefs-generated/envoy/annotations/resource.upbdefs.c',
@@ -317,20 +317,22 @@ CORE_SOURCE_FILES = [
     'src/core/ext/upbdefs-generated/udpa/annotations/sensitive.upbdefs.c',
     'src/core/ext/upbdefs-generated/udpa/annotations/status.upbdefs.c',
     'src/core/ext/upbdefs-generated/udpa/annotations/versioning.upbdefs.c',
-    'src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.c',
     'src/core/ext/upbdefs-generated/validate/validate.upbdefs.c',
+    'src/core/ext/upbdefs-generated/xds/annotations/v3/status.upbdefs.c',
     'src/core/ext/upbdefs-generated/xds/core/v3/authority.upbdefs.c',
     'src/core/ext/upbdefs-generated/xds/core/v3/collection_entry.upbdefs.c',
     'src/core/ext/upbdefs-generated/xds/core/v3/context_params.upbdefs.c',
     'src/core/ext/upbdefs-generated/xds/core/v3/resource.upbdefs.c',
     'src/core/ext/upbdefs-generated/xds/core/v3/resource_locator.upbdefs.c',
     'src/core/ext/upbdefs-generated/xds/core/v3/resource_name.upbdefs.c',
+    'src/core/ext/upbdefs-generated/xds/type/v3/typed_struct.upbdefs.c',
     'src/core/ext/xds/certificate_provider_registry.cc',
     'src/core/ext/xds/certificate_provider_store.cc',
     'src/core/ext/xds/file_watcher_certificate_provider_factory.cc',
     'src/core/ext/xds/xds_api.cc',
     'src/core/ext/xds/xds_bootstrap.cc',
     'src/core/ext/xds/xds_certificate_provider.cc',
+    'src/core/ext/xds/xds_channel_stack_modifier.cc',
     'src/core/ext/xds/xds_client.cc',
     'src/core/ext/xds/xds_client_stats.cc',
     'src/core/ext/xds/xds_http_fault_filter.cc',
@@ -499,7 +501,6 @@ CORE_SOURCE_FILES = [
     'src/core/lib/iomgr/timer_generic.cc',
     'src/core/lib/iomgr/timer_heap.cc',
     'src/core/lib/iomgr/timer_manager.cc',
-    'src/core/lib/iomgr/udp_server.cc',
     'src/core/lib/iomgr/unix_sockets_posix.cc',
     'src/core/lib/iomgr/unix_sockets_posix_noop.cc',
     'src/core/lib/iomgr/wakeup_fd_eventfd.cc',
@@ -571,10 +572,15 @@ CORE_SOURCE_FILES = [
     'src/core/lib/slice/b64.cc',
     'src/core/lib/slice/percent_encoding.cc',
     'src/core/lib/slice/slice.cc',
+    'src/core/lib/slice/slice_api.cc',
     'src/core/lib/slice/slice_buffer.cc',
     'src/core/lib/slice/slice_intern.cc',
+    'src/core/lib/slice/slice_refcount.cc',
+    'src/core/lib/slice/slice_split.cc',
     'src/core/lib/slice/slice_string_helpers.cc',
+    'src/core/lib/slice/static_slice.cc',
     'src/core/lib/surface/api_trace.cc',
+    'src/core/lib/surface/builtins.cc',
     'src/core/lib/surface/byte_buffer.cc',
     'src/core/lib/surface/byte_buffer_reader.cc',
     'src/core/lib/surface/call.cc',
@@ -594,7 +600,6 @@ CORE_SOURCE_FILES = [
     'src/core/lib/surface/server.cc',
     'src/core/lib/surface/validate_metadata.cc',
     'src/core/lib/surface/version.cc',
-    'src/core/lib/transport/authority_override.cc',
     'src/core/lib/transport/bdp_estimator.cc',
     'src/core/lib/transport/byte_stream.cc',
     'src/core/lib/transport/connectivity_state.cc',
index f07a197..c1c7618 100644 (file)
@@ -14,4 +14,4 @@
 
 # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc_version.py.template`!!!
 
-VERSION = '1.41.1'
+VERSION = '1.42.0'
index 5415450..98a3975 100644 (file)
@@ -14,4 +14,4 @@
 
 # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_admin/grpc_version.py.template`!!!
 
-VERSION = '1.41.1'
+VERSION = '1.42.0'
index 08f2a6e..2d966cd 100644 (file)
@@ -55,5 +55,6 @@ setuptools.setup(name='grpcio-admin',
                  url='https://grpc.io',
                  package_dir=PACKAGE_DIRECTORIES,
                  packages=setuptools.find_packages('.'),
+                 python_requires='>=3.6',
                  install_requires=INSTALL_REQUIRES,
                  setup_requires=SETUP_REQUIRES)
index 07b5873..ba3429b 100644 (file)
@@ -17,6 +17,7 @@ package(default_visibility = ["//visibility:public"])
 
 py_proto_library(
     name = "channelz_py_pb2",
+    imports = ["../../"],
     deps = ["//src/proto/grpc/channelz:channelz_proto_descriptors"],
 )
 
index d58bf33..6578238 100644 (file)
@@ -14,4 +14,4 @@
 
 # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_channelz/grpc_version.py.template`!!!
 
-VERSION = '1.41.1'
+VERSION = '1.42.0'
index fc0f157..cec1ea2 100644 (file)
@@ -98,6 +98,7 @@ setuptools.setup(
     url='https://grpc.io',
     package_dir=PACKAGE_DIRECTORIES,
     packages=setuptools.find_packages('.'),
+    python_requires='>=3.6',
     install_requires=INSTALL_REQUIRES,
     setup_requires=SETUP_REQUIRES,
     cmdclass=COMMAND_CLASS)
index 5f0b308..4c4c27b 100644 (file)
@@ -14,4 +14,4 @@
 
 # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_csds/grpc_version.py.template`!!!
 
-VERSION = '1.41.1'
+VERSION = '1.42.0'
index e0eb60a..c89c6b9 100644 (file)
@@ -56,5 +56,6 @@ setuptools.setup(name='grpcio-csds',
                  url='https://grpc.io',
                  package_dir=PACKAGE_DIRECTORIES,
                  packages=setuptools.find_packages('.'),
+                 python_requires='>=3.6',
                  install_requires=INSTALL_REQUIRES,
                  setup_requires=SETUP_REQUIRES)
index a9ad3f4..f82edaa 100644 (file)
@@ -17,6 +17,7 @@ package(default_visibility = ["//visibility:public"])
 
 py_proto_library(
     name = "health_py_pb2",
+    imports = ["../../"],
     deps = ["//src/proto/grpc/health/v1:health_proto_descriptor"],
 )
 
index 1e0e66f..6253b52 100644 (file)
@@ -14,4 +14,4 @@
 
 # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_health_checking/grpc_version.py.template`!!!
 
-VERSION = '1.41.1'
+VERSION = '1.42.0'
index 4570e5c..7491bd4 100644 (file)
@@ -96,6 +96,7 @@ setuptools.setup(name='grpcio-health-checking',
                  classifiers=CLASSIFIERS,
                  package_dir=PACKAGE_DIRECTORIES,
                  packages=setuptools.find_packages('.'),
+                 python_requires='>=3.6',
                  install_requires=INSTALL_REQUIRES,
                  setup_requires=SETUP_REQUIRES,
                  cmdclass=COMMAND_CLASS)
index b23f577..cdbdb46 100644 (file)
@@ -18,6 +18,7 @@ package(default_visibility = ["//visibility:public"])
 
 py_proto_library(
     name = "reflection_py_pb2",
+    imports = ["../../"],
     deps = ["//src/proto/grpc/reflection/v1alpha:reflection_proto_descriptor"],
 )
 
index 6446b06..9d172d6 100644 (file)
@@ -14,4 +14,4 @@
 
 # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_reflection/grpc_version.py.template`!!!
 
-VERSION = '1.41.1'
+VERSION = '1.42.0'
index 991bf38..f90a3cc 100644 (file)
@@ -97,6 +97,7 @@ setuptools.setup(name='grpcio-reflection',
                  url='https://grpc.io',
                  package_dir=PACKAGE_DIRECTORIES,
                  packages=setuptools.find_packages('.'),
+                 python_requires='>=3.6',
                  install_requires=INSTALL_REQUIRES,
                  setup_requires=SETUP_REQUIRES,
                  cmdclass=COMMAND_CLASS)
index 4781e13..315017a 100644 (file)
@@ -14,4 +14,4 @@
 
 # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_status/grpc_version.py.template`!!!
 
-VERSION = '1.41.1'
+VERSION = '1.42.0'
index da9414c..23bd11c 100644 (file)
@@ -94,5 +94,6 @@ setuptools.setup(name='grpcio-status',
                  classifiers=CLASSIFIERS,
                  package_dir=PACKAGE_DIRECTORIES,
                  packages=setuptools.find_packages('.'),
+                 python_requires='>=3.6',
                  install_requires=INSTALL_REQUIRES,
                  cmdclass=COMMAND_CLASS)
index a7884eb..ed94ed7 100644 (file)
@@ -14,4 +14,4 @@
 
 # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_testing/grpc_version.py.template`!!!
 
-VERSION = '1.41.1'
+VERSION = '1.42.0'
index 1603c8b..2b644c4 100644 (file)
@@ -14,4 +14,4 @@
 
 # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_tests/grpc_version.py.template`!!!
 
-VERSION = '1.41.1'
+VERSION = '1.42.0'
index d94be8c..6dc80bf 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-load("//bazel:python_rules.bzl", "py2and3_test")
-
-py2and3_test(
+py_test(
     name = "test_admin",
     size = "small",
     srcs = ["test_admin.py"],
     main = "test_admin.py",
+    python_version = "PY3",
     deps = [
         "//src/python/grpcio/grpc:grpcio",
         "//src/python/grpcio_admin/grpc_admin",
+        "@com_google_protobuf//:protobuf_python",
     ],
 )
index 5524f2f..adc4878 100644 (file)
@@ -15,6 +15,7 @@
 
 from concurrent.futures import ThreadPoolExecutor
 import logging
+import sys
 import unittest
 
 import grpc
@@ -25,6 +26,8 @@ from grpc_csds import csds_pb2
 from grpc_csds import csds_pb2_grpc
 
 
+@unittest.skipIf(sys.version_info[0] < 3,
+                 'ProtoBuf descriptor has moved on from Python2')
 class TestAdmin(unittest.TestCase):
 
     def setUp(self):
index d16df1c..39c65bf 100644 (file)
 # limitations under the License.
 package(default_visibility = ["//visibility:public"])
 
-load("//bazel:python_rules.bzl", "py2and3_test")
-
-py2and3_test(
+py_test(
     name = "channelz_servicer_test",
     size = "small",
     srcs = ["_channelz_servicer_test.py"],
     imports = ["../../"],
     main = "_channelz_servicer_test.py",
+    python_version = "PY3",
     deps = [
         "//src/python/grpcio/grpc:grpcio",
         "//src/python/grpcio_channelz/grpc_channelz/v1:grpc_channelz",
index a077a2d..565a798 100644 (file)
@@ -14,6 +14,7 @@
 """Tests of grpc_channelz.v1.channelz."""
 
 from concurrent import futures
+import sys
 import unittest
 
 import grpc
@@ -90,6 +91,8 @@ def _close_channel_server_pairs(pairs):
         pair.channel.close()
 
 
+@unittest.skipIf(sys.version_info[0] < 3,
+                 'ProtoBuf descriptor has moved on from Python2')
 class ChannelzServicerTest(unittest.TestCase):
 
     def _send_successful_unary_unary(self, idx):
index 3cf916d..cc9fbbd 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-load("//bazel:python_rules.bzl", "py2and3_test")
-
-py2and3_test(
+py_test(
     name = "test_csds",
     size = "small",
     srcs = ["test_csds.py"],
     main = "test_csds.py",
+    python_version = "PY3",
     deps = [
         "//src/python/grpcio/grpc:grpcio",
         "//src/python/grpcio_csds/grpc_csds",
index 34b575d..3a78b5c 100644 (file)
@@ -16,6 +16,7 @@
 from concurrent.futures import ThreadPoolExecutor
 import logging
 import os
+import sys
 import time
 import unittest
 
@@ -61,6 +62,8 @@ _DUMMY_BOOTSTRAP_FILE = """
 """
 
 
+@unittest.skipIf(sys.version_info[0] < 3,
+                 'ProtoBuf descriptor has moved on from Python2')
 class TestCsds(unittest.TestCase):
 
     def setUp(self):
@@ -85,7 +88,6 @@ class TestCsds(unittest.TestCase):
     def test_has_node(self):
         resp = self.get_xds_config_dump()
         self.assertEqual(1, len(resp.config))
-        self.assertEqual(4, len(resp.config[0].xds_config))
         self.assertEqual('python_test_csds', resp.config[0].node.id)
         self.assertEqual('test', resp.config[0].node.cluster)
 
@@ -104,13 +106,20 @@ class TestCsds(unittest.TestCase):
             config = json_format.MessageToDict(resp)
             ok = False
             try:
-                for xds_config in config["config"][0]["xdsConfig"]:
+                for xds_config in config["config"][0].get("xdsConfig", []):
                     if "listenerConfig" in xds_config:
                         listener = xds_config["listenerConfig"][
                             "dynamicListeners"][0]
                         if listener['clientStatus'] == 'DOES_NOT_EXIST':
                             ok = True
                             break
+                for generic_xds_config in config["config"][0].get(
+                        "genericXdsConfigs", []):
+                    if "Listener" in generic_xds_config["typeUrl"]:
+                        if generic_xds_config[
+                                'clientStatus'] == 'DOES_NOT_EXIST':
+                            ok = True
+                            break
             except KeyError as e:
                 logging.debug("Invalid config: %s\n%s: %s", config, type(e), e)
                 pass
@@ -120,6 +129,8 @@ class TestCsds(unittest.TestCase):
         dummy_channel.close()
 
 
+@unittest.skipIf(sys.version_info[0] < 3,
+                 'ProtoBuf descriptor has moved on from Python2')
 class TestCsdsStream(TestCsds):
 
     def get_xds_config_dump(self):
index 9c588b9..91eeece 100644 (file)
 # limitations under the License.
 package(default_visibility = ["//visibility:public"])
 
-load("//bazel:python_rules.bzl", "py2and3_test")
-
-py2and3_test(
+py_test(
     name = "health_servicer_test",
     size = "small",
     srcs = ["_health_servicer_test.py"],
     imports = ["../../"],
     main = "_health_servicer_test.py",
+    python_version = "PY3",
     deps = [
         "//src/python/grpcio/grpc:grpcio",
         "//src/python/grpcio_health_checking/grpc_health/v1:grpc_health",
index eb187be..d3dfa45 100644 (file)
@@ -14,6 +14,7 @@
 """Tests of grpc_health.v1.health."""
 
 import logging
+import sys
 import threading
 import time
 import unittest
@@ -41,6 +42,8 @@ def _consume_responses(response_iterator, response_queue):
 
 class BaseWatchTests(object):
 
+    @unittest.skipIf(sys.version_info[0] < 3,
+                     'ProtoBuf descriptor has moved on from Python2')
     class WatchTests(unittest.TestCase):
 
         def start_server(self, non_blocking=False, thread_pool=None):
@@ -228,6 +231,8 @@ class BaseWatchTests(object):
             self.assertTrue(response_queue.empty())
 
 
+@unittest.skipIf(sys.version_info[0] < 3,
+                 'ProtoBuf descriptor has moved on from Python2')
 class HealthServicerTest(BaseWatchTests.WatchTests):
 
     def setUp(self):
@@ -268,6 +273,8 @@ class HealthServicerTest(BaseWatchTests.WatchTests):
         self.assertEqual(health.SERVICE_NAME, 'grpc.health.v1.Health')
 
 
+@unittest.skipIf(sys.version_info[0] < 3,
+                 'ProtoBuf descriptor has moved on from Python2')
 class HealthServicerBackwardsCompatibleWatchTest(BaseWatchTests.WatchTests):
 
     def setUp(self):
index 1180a95..084ee1a 100644 (file)
@@ -12,7 +12,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 load("@grpc_python_dependencies//:requirements.bzl", "requirement")
-load("//bazel:python_rules.bzl", "py2and3_test")
 
 package(default_visibility = ["//visibility:public"])
 
@@ -113,7 +112,7 @@ py_binary(
     ],
 )
 
-py2and3_test(
+py_test(
     name = "_insecure_intraop_test",
     size = "small",
     srcs = ["_insecure_intraop_test.py"],
@@ -122,6 +121,7 @@ py2and3_test(
     ],
     imports = ["../../"],
     main = "_insecure_intraop_test.py",
+    python_version = "PY3",
     deps = [
         ":_intraop_test_case",
         ":server",
@@ -132,12 +132,13 @@ py2and3_test(
     ],
 )
 
-py2and3_test(
+py_test(
     name = "_secure_intraop_test",
     size = "small",
     srcs = ["_secure_intraop_test.py"],
     imports = ["../../"],
     main = "_secure_intraop_test.py",
+    python_version = "PY3",
     deps = [
         ":_intraop_test_case",
         ":server",
index 4101dfb..27e5dcd 100644 (file)
@@ -13,6 +13,7 @@
 # limitations under the License.
 """Insecure client-server interoperability as a unit test."""
 
+import sys
 import unittest
 
 import grpc
@@ -24,6 +25,8 @@ from tests.interop import service
 from tests.unit import test_common
 
 
+@unittest.skipIf(sys.version_info[0] < 3,
+                 'ProtoBuf descriptor has moved on from Python2')
 class InsecureIntraopTest(_intraop_test_case.IntraopTestCase,
                           unittest.TestCase):
 
index cdd9b15..0ec88a2 100644 (file)
@@ -13,6 +13,7 @@
 # limitations under the License.
 """Secure client-server interoperability as a unit test."""
 
+import sys
 import unittest
 
 import grpc
@@ -26,6 +27,8 @@ from tests.unit import test_common
 _SERVER_HOST_OVERRIDE = 'foo.test.google.fr'
 
 
+@unittest.skipIf(sys.version_info[0] < 3,
+                 'ProtoBuf descriptor has moved on from Python2')
 class SecureIntraopTest(_intraop_test_case.IntraopTestCase, unittest.TestCase):
 
     def setUp(self):
index bdce2b7..3ad95a7 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 load("@grpc_python_dependencies//:requirements.bzl", "requirement")
-load("//bazel:python_rules.bzl", "py2and3_test")
 
 package(default_visibility = ["//visibility:public"])
 
-py2and3_test(
+py_test(
     name = "_reflection_servicer_test",
     size = "medium",
     srcs = ["_reflection_servicer_test.py"],
     imports = ["../../"],
     main = "_reflection_servicer_test.py",
+    python_version = "PY3",
     deps = [
         "//src/proto/grpc/testing:empty_py_pb2",
         "//src/proto/grpc/testing/proto2:empty2_extensions_proto",
index 53f2857..63b73e2 100644 (file)
@@ -13,6 +13,7 @@
 # limitations under the License.
 """Tests of grpc_reflection.v1alpha.reflection."""
 
+import sys
 import unittest
 
 from google.protobuf import descriptor_pb2
@@ -46,6 +47,8 @@ def _file_descriptor_to_proto(descriptor):
     return proto.SerializeToString()
 
 
+@unittest.skipIf(sys.version_info[0] < 3,
+                 'ProtoBuf descriptor has moved on from Python2')
 class ReflectionServicerTest(unittest.TestCase):
 
     # TODO(https://github.com/grpc/grpc/issues/17844)
index e96ceb3..307cb34 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 load("@grpc_python_dependencies//:requirements.bzl", "requirement")
-load("//bazel:python_rules.bzl", "py2and3_test")
 
 package(default_visibility = ["//visibility:public"])
 
-py2and3_test(
+py_test(
     name = "grpc_status_test",
     size = "small",
     srcs = ["_grpc_status_test.py"],
     imports = ["../../"],
     main = "_grpc_status_test.py",
+    python_version = "PY3",
     deps = [
         "//src/python/grpcio/grpc:grpcio",
         "//src/python/grpcio_status/grpc_status",
index efb1314..a79dd55 100644 (file)
@@ -28,6 +28,7 @@ import unittest
 
 import logging
 import traceback
+import sys
 
 import grpc
 from grpc_status import rpc_status
@@ -113,6 +114,8 @@ class _GenericHandler(grpc.GenericRpcHandler):
             return None
 
 
+@unittest.skipIf(sys.version_info[0] < 3,
+                 'ProtoBuf descriptor has moved on from Python2')
 class StatusTest(unittest.TestCase):
 
     def setUp(self):
index 67d7a90..bf8bdef 100644 (file)
@@ -11,7 +11,7 @@
 # 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.
-load("//bazel:python_rules.bzl", "py2and3_test")
+load("//bazel:internal_python_rules.bzl", "internal_py_grpc_test")
 
 package(default_visibility = ["//visibility:public"])
 
@@ -105,7 +105,7 @@ py_library(
 )
 
 [
-    py2and3_test(
+    internal_py_grpc_test(
         name = test_file_name[:-3],
         size = "small",
         srcs = [test_file_name],
@@ -133,7 +133,7 @@ py_library(
     for test_file_name in GRPCIO_TESTS_UNIT
 ]
 
-py2and3_test(
+internal_py_grpc_test(
     name = "_dynamic_stubs_test",
     size = "small",
     srcs = ["_dynamic_stubs_test.py"],
@@ -144,6 +144,7 @@ py2and3_test(
     imports = ["../../"],
     main = "_dynamic_stubs_test.py",
     deps = [
+        ":test_common",
         "//src/python/grpcio/grpc:grpcio",
         "//src/python/grpcio_tests/tests/testing",
         "//tools/distrib/python/grpcio_tools:grpc_tools",
index 9789afb..cd55db5 100644 (file)
@@ -259,6 +259,8 @@ def _stream_stream_client(channel, multicallable_kwargs, message):
                 i, response))
 
 
+@unittest.skipIf(test_common.running_under_gevent(),
+                 "This test is nondeterministic under gevent.")
 class CompressionTest(unittest.TestCase):
 
     def assertCompressed(self, compression_ratio):
index 9c94be5..128ec51 100644 (file)
@@ -97,6 +97,8 @@ else:
 
 # TODO(https://github.com/grpc/grpc/issues/22257)
 @unittest.skipIf(os.name == "nt", "LocalCredentials not supported on Windows.")
+@unittest.skipIf(test_common.running_under_gevent(),
+                 "ThreadLocals do not work under gevent.")
 class ContextVarsPropagationTest(unittest.TestCase):
 
     def test_propagation_to_auth_plugin(self):
index 4645f0b..933a814 100644 (file)
@@ -21,6 +21,8 @@ import os
 import sys
 import unittest
 
+from tests.unit import test_common
+
 _DATA_DIR = os.path.join("tests", "unit", "data")
 
 
@@ -124,6 +126,8 @@ def _test_grpc_tools_unimportable():
 # when they do not come from the "__main__" module, so this test passes
 # if run directly on Windows, but not if started by the test runner.
 @unittest.skipIf(os.name == "nt", "Windows multiprocessing unsupported")
+@unittest.skipIf(test_common.running_under_gevent(),
+                 "Import paths do not work with gevent runner.")
 class DynamicStubTest(unittest.TestCase):
 
     def test_sunny_day(self):
index ce92fee..5351a2b 100644 (file)
@@ -19,6 +19,8 @@ import unittest
 
 import grpc
 
+from tests.unit import test_common
+
 
 class _GenericHandler(grpc.GenericRpcHandler):
 
@@ -56,6 +58,8 @@ class LocalCredentialsTest(unittest.TestCase):
 
     @unittest.skipIf(os.name == 'nt',
                      'Unix Domain Socket is not supported on Windows')
+    @unittest.skipIf(test_common.running_under_gevent(),
+                     'UDS not supported under gevent.')
     def test_uds(self):
         server_addr = 'unix:/tmp/grpc_fullstack_test'
         channel_creds = grpc.local_channel_credentials(
index 89c028b..8744183 100644 (file)
@@ -188,6 +188,8 @@ def _generic_handler(servicer):
     return grpc.method_handlers_generic_handler(_SERVICE, method_handlers)
 
 
+@unittest.skipIf(test_common.running_under_gevent(),
+                 "Causes deadlock in gevent.")
 class MetadataCodeDetailsTest(unittest.TestCase):
 
     def setUp(self):
index 90d010b..62ab5a5 100644 (file)
@@ -21,6 +21,7 @@ import unittest
 import grpc
 from grpc.framework.foundation import logging_pool
 
+from tests.unit import test_common
 from tests.unit.framework.common import bound_socket
 from tests.unit.framework.common import test_constants
 
@@ -34,6 +35,8 @@ def _handle_unary_unary(unused_request, unused_servicer_context):
     return _RESPONSE
 
 
+@unittest.skipIf(test_common.running_under_gevent(),
+                 "Test is nondeterministic under gevent.")
 class ReconnectTest(unittest.TestCase):
 
     def test_reconnect(self):
index 1f85cd6..0ffa9ef 100644 (file)
@@ -22,6 +22,7 @@ import unittest
 import grpc
 from grpc.framework.foundation import logging_pool
 
+from tests.unit import test_common
 from tests.unit._rpc_test_helpers import BaseRPCTest
 from tests.unit._rpc_test_helpers import Callback
 from tests.unit._rpc_test_helpers import TIMEOUT_SHORT
@@ -36,6 +37,8 @@ from tests.unit._rpc_test_helpers import unary_unary_multi_callable
 from tests.unit.framework.common import test_constants
 
 
+@unittest.skipIf(test_common.running_under_gevent(),
+                 "This test is nondeterministic under gevent.")
 class RPCPart1Test(BaseRPCTest, unittest.TestCase):
 
     def testExpiredStreamRequestBlockingUnaryResponse(self):
index a8e6dde..6a82a95 100644 (file)
@@ -22,6 +22,7 @@ import unittest
 import grpc
 from grpc.framework.foundation import logging_pool
 
+from tests.unit import test_common
 from tests.unit._rpc_test_helpers import BaseRPCTest
 from tests.unit._rpc_test_helpers import Callback
 from tests.unit._rpc_test_helpers import TIMEOUT_SHORT
@@ -36,6 +37,8 @@ from tests.unit._rpc_test_helpers import unary_unary_multi_callable
 from tests.unit.framework.common import test_constants
 
 
+@unittest.skipIf(test_common.running_under_gevent(),
+                 "Causes deadlock under gevent.")
 class RPCPart2Test(BaseRPCTest, unittest.TestCase):
 
     def testDefaultThreadPoolIsUsed(self):
index 3b1e344..dae69cb 100644 (file)
@@ -132,3 +132,14 @@ class WaitGroup(object):
         while self.count > 0:
             self.cv.wait()
         self.cv.release()
+
+
+def running_under_gevent():
+    try:
+        from gevent import monkey
+        import gevent.socket
+    except ImportError:
+        return False
+    else:
+        import socket
+        return socket.socket is gevent.socket.socket
index 4d20c1d..2fc4c32 100644 (file)
@@ -27,7 +27,8 @@
   "unit.compression_test.TestCompression",
   "unit.connectivity_test.TestConnectivityState",
   "unit.context_peer_test.TestContextPeer",
-  "unit.done_callback_test.TestDoneCallback",
+  "unit.done_callback_test.TestClientSideDoneCallback",
+  "unit.done_callback_test.TestServerSideDoneCallback",
   "unit.init_test.TestInit",
   "unit.metadata_test.TestMetadata",
   "unit.outside_init_test.TestOutsideInit",
index 986a6f9..ab7e06f 100644 (file)
@@ -12,5 +12,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-UNREACHABLE_TARGET = '0.0.0.1:1111'
+# If we use an unreachable IP, depending on the network stack, we might not get
+# with an RST fast enough. This used to cause tests to flake under different
+# platforms.
+UNREACHABLE_TARGET = 'foo/bar'
 UNARY_CALL_WITH_SLEEP_VALUE = 0.2
index 64e2d1f..4749f39 100644 (file)
@@ -78,7 +78,7 @@ class TestCompatibility(AioTestBase):
         await self._async_server.stop(None)
 
     async def _run_in_another_thread(self, func: Callable[[], None]):
-        work_done = asyncio.Event(loop=self.loop)
+        work_done = asyncio.Event()
 
         def thread_work():
             func()
index b3a327d..42a070f 100644 (file)
@@ -14,9 +14,7 @@
 """Testing the done callbacks mechanism."""
 
 import asyncio
-import gc
 import logging
-import time
 import unittest
 
 import grpc
@@ -24,7 +22,6 @@ from grpc.experimental import aio
 
 from src.proto.grpc.testing import messages_pb2
 from src.proto.grpc.testing import test_pb2_grpc
-from tests.unit.framework.common import test_constants
 from tests_aio.unit._common import inject_callbacks
 from tests_aio.unit._test_base import AioTestBase
 from tests_aio.unit._test_server import start_test_server
@@ -32,9 +29,13 @@ from tests_aio.unit._test_server import start_test_server
 _NUM_STREAM_RESPONSES = 5
 _REQUEST_PAYLOAD_SIZE = 7
 _RESPONSE_PAYLOAD_SIZE = 42
+_REQUEST = b'\x01\x02\x03'
+_RESPONSE = b'\x04\x05\x06'
+_TEST_METHOD = '/test/Test'
+_FAKE_METHOD = '/test/Fake'
 
 
-class TestDoneCallback(AioTestBase):
+class TestClientSideDoneCallback(AioTestBase):
 
     async def setUp(self):
         address, self._server = await start_test_server()
@@ -121,6 +122,155 @@ class TestDoneCallback(AioTestBase):
         await validation
 
 
+class TestServerSideDoneCallback(AioTestBase):
+
+    async def setUp(self):
+        self._server = aio.server()
+        port = self._server.add_insecure_port('[::]:0')
+        self._channel = aio.insecure_channel('localhost:%d' % port)
+
+    async def tearDown(self):
+        await self._channel.close()
+        await self._server.stop(None)
+
+    async def _register_method_handler(self, method_handler):
+        """Registers method handler and starts the server"""
+        generic_handler = grpc.method_handlers_generic_handler(
+            'test',
+            dict(Test=method_handler),
+        )
+        self._server.add_generic_rpc_handlers((generic_handler,))
+        await self._server.start()
+
+    async def test_unary_unary(self):
+        validation_future = self.loop.create_future()
+
+        async def test_handler(request: bytes, context: aio.ServicerContext):
+            self.assertEqual(_REQUEST, request)
+            validation_future.set_result(inject_callbacks(context))
+            return _RESPONSE
+
+        await self._register_method_handler(
+            grpc.unary_unary_rpc_method_handler(test_handler))
+        response = await self._channel.unary_unary(_TEST_METHOD)(_REQUEST)
+        self.assertEqual(_RESPONSE, response)
+
+        validation = await validation_future
+        await validation
+
+    async def test_unary_stream(self):
+        validation_future = self.loop.create_future()
+
+        async def test_handler(request: bytes, context: aio.ServicerContext):
+            self.assertEqual(_REQUEST, request)
+            validation_future.set_result(inject_callbacks(context))
+            for _ in range(_NUM_STREAM_RESPONSES):
+                yield _RESPONSE
+
+        await self._register_method_handler(
+            grpc.unary_stream_rpc_method_handler(test_handler))
+        call = self._channel.unary_stream(_TEST_METHOD)(_REQUEST)
+        async for response in call:
+            self.assertEqual(_RESPONSE, response)
+
+        validation = await validation_future
+        await validation
+
+    async def test_stream_unary(self):
+        validation_future = self.loop.create_future()
+
+        async def test_handler(request_iterator, context: aio.ServicerContext):
+            validation_future.set_result(inject_callbacks(context))
+
+            async for request in request_iterator:
+                self.assertEqual(_REQUEST, request)
+            return _RESPONSE
+
+        await self._register_method_handler(
+            grpc.stream_unary_rpc_method_handler(test_handler))
+        call = self._channel.stream_unary(_TEST_METHOD)()
+        for _ in range(_NUM_STREAM_RESPONSES):
+            await call.write(_REQUEST)
+        await call.done_writing()
+        self.assertEqual(_RESPONSE, await call)
+
+        validation = await validation_future
+        await validation
+
+    async def test_stream_stream(self):
+        validation_future = self.loop.create_future()
+
+        async def test_handler(request_iterator, context: aio.ServicerContext):
+            validation_future.set_result(inject_callbacks(context))
+
+            async for request in request_iterator:
+                self.assertEqual(_REQUEST, request)
+            return _RESPONSE
+
+        await self._register_method_handler(
+            grpc.stream_stream_rpc_method_handler(test_handler))
+        call = self._channel.stream_stream(_TEST_METHOD)()
+        for _ in range(_NUM_STREAM_RESPONSES):
+            await call.write(_REQUEST)
+        await call.done_writing()
+        async for response in call:
+            self.assertEqual(_RESPONSE, response)
+
+        validation = await validation_future
+        await validation
+
+    async def test_error_in_handler(self):
+        """Errors in the handler still triggers callbacks."""
+        validation_future = self.loop.create_future()
+
+        async def test_handler(request: bytes, context: aio.ServicerContext):
+            self.assertEqual(_REQUEST, request)
+            validation_future.set_result(inject_callbacks(context))
+            raise RuntimeError('A test RuntimeError')
+
+        await self._register_method_handler(
+            grpc.unary_unary_rpc_method_handler(test_handler))
+        with self.assertRaises(aio.AioRpcError) as exception_context:
+            await self._channel.unary_unary(_TEST_METHOD)(_REQUEST)
+        rpc_error = exception_context.exception
+        self.assertEqual(grpc.StatusCode.UNKNOWN, rpc_error.code())
+
+        validation = await validation_future
+        await validation
+
+    async def test_error_in_callback(self):
+        """Errors in the callback won't be propagated to client."""
+        validation_future = self.loop.create_future()
+
+        async def test_handler(request: bytes, context: aio.ServicerContext):
+            self.assertEqual(_REQUEST, request)
+
+            def exception_raiser(unused_context):
+                raise RuntimeError('A test RuntimeError')
+
+            context.add_done_callback(exception_raiser)
+            validation_future.set_result(inject_callbacks(context))
+            return _RESPONSE
+
+        await self._register_method_handler(
+            grpc.unary_unary_rpc_method_handler(test_handler))
+
+        response = await self._channel.unary_unary(_TEST_METHOD)(_REQUEST)
+        self.assertEqual(_RESPONSE, response)
+
+        # Following callbacks won't be invoked, if one of the callback crashed.
+        validation = await validation_future
+        with self.assertRaises(asyncio.TimeoutError):
+            await validation
+
+        # Invoke RPC one more time to ensure the toxic callback won't break the
+        # server.
+        with self.assertRaises(aio.AioRpcError) as exception_context:
+            await self._channel.unary_unary(_FAKE_METHOD)(_REQUEST)
+        rpc_error = exception_context.exception
+        self.assertEqual(grpc.StatusCode.UNIMPLEMENTED, rpc_error.code())
+
+
 if __name__ == '__main__':
     logging.basicConfig(level=logging.DEBUG)
     unittest.main(verbosity=2)
index 8ba3ce1..3be34a7 100644 (file)
@@ -13,9 +13,7 @@
 # limitations under the License.
 
 import asyncio
-import gc
 import logging
-import socket
 import time
 import unittest
 
@@ -40,6 +38,7 @@ _STREAM_STREAM_READER_WRITER = '/test/StreamStreamReaderWriter'
 _STREAM_STREAM_EVILLY_MIXED = '/test/StreamStreamEvillyMixed'
 _UNIMPLEMENTED_METHOD = '/test/UnimplementedMethod'
 _ERROR_IN_STREAM_STREAM = '/test/ErrorInStreamStream'
+_ERROR_IN_STREAM_UNARY = '/test/ErrorInStreamUnary'
 _ERROR_WITHOUT_RAISE_IN_UNARY_UNARY = '/test/ErrorWithoutRaiseInUnaryUnary'
 _ERROR_WITHOUT_RAISE_IN_STREAM_STREAM = '/test/ErrorWithoutRaiseInStreamStream'
 
@@ -91,6 +90,9 @@ class _GenericHandler(grpc.GenericRpcHandler):
             _ERROR_IN_STREAM_STREAM:
                 grpc.stream_stream_rpc_method_handler(
                     self._error_in_stream_stream),
+            _ERROR_IN_STREAM_UNARY:
+                grpc.stream_unary_rpc_method_handler(
+                    self._value_error_in_stream_unary),
             _ERROR_WITHOUT_RAISE_IN_UNARY_UNARY:
                 grpc.unary_unary_rpc_method_handler(
                     self._error_without_raise_in_unary_unary),
@@ -179,6 +181,14 @@ class _GenericHandler(grpc.GenericRpcHandler):
             raise RuntimeError('A testing RuntimeError!')
         yield _RESPONSE
 
+    async def _value_error_in_stream_unary(self, request_iterator, context):
+        request_count = 0
+        async for request in request_iterator:
+            assert _REQUEST == request
+            request_count += 1
+            if request_count >= 1:
+                raise ValueError('The test server has a bug!')
+
     async def _error_without_raise_in_unary_unary(self, request, context):
         assert _REQUEST == request
         context.set_code(grpc.StatusCode.INTERNAL)
@@ -270,6 +280,24 @@ class TestServer(AioTestBase):
         self.assertEqual(_RESPONSE, response)
         self.assertEqual(await call.code(), grpc.StatusCode.OK)
 
+    async def test_stream_unary_async_generator_with_request_iter(self):
+        stream_unary_call = self._channel.stream_unary(_STREAM_UNARY_ASYNC_GEN)
+
+        finished = False
+
+        def request_gen():
+            for _ in range(_NUM_STREAM_REQUESTS):
+                yield _REQUEST
+            nonlocal finished
+            finished = True
+
+        call = stream_unary_call(request_gen())
+
+        response = await call
+        self.assertEqual(_RESPONSE, response)
+        self.assertEqual(await call.code(), grpc.StatusCode.OK)
+        self.assertEqual(finished, True)
+
     async def test_stream_unary_reader_writer(self):
         stream_unary_call = self._channel.stream_unary(
             _STREAM_UNARY_READER_WRITER)
@@ -468,6 +496,25 @@ class TestServer(AioTestBase):
 
         self.assertEqual(grpc.StatusCode.INTERNAL, await call.code())
 
+    async def test_error_in_stream_unary(self):
+        stream_unary_call = self._channel.stream_unary(_ERROR_IN_STREAM_UNARY)
+
+        finished = False
+
+        def request_gen():
+            for _ in range(_NUM_STREAM_REQUESTS):
+                yield _REQUEST
+            nonlocal finished
+            finished = True
+
+        call = stream_unary_call(request_gen())
+
+        with self.assertRaises(aio.AioRpcError) as exception_context:
+            await call
+        rpc_error = exception_context.exception
+        self.assertEqual(grpc.StatusCode.UNKNOWN, rpc_error.code())
+        self.assertEqual(finished, False)
+
     async def test_port_binding_exception(self):
         server = aio.server(options=(('grpc.so_reuseport', 0),))
         port = server.add_insecure_port('localhost:0')
index 68ff95d..d0b832c 100644 (file)
@@ -17,6 +17,9 @@ require 'mkmf'
 
 windows = RUBY_PLATFORM =~ /mingw|mswin/
 bsd = RUBY_PLATFORM =~ /bsd/
+darwin = RUBY_PLATFORM =~ /darwin/
+linux = RUBY_PLATFORM =~ /linux/
+cross_compiling = ENV['RCD_HOST_RUBY_VERSION'] # set by rake-compiler-dock in build containers
 
 grpc_root = File.expand_path(File.join(File.dirname(__FILE__), '../../../..'))
 
@@ -37,17 +40,17 @@ if ENV['LD'].nil? || ENV['LD'].size == 0
     ENV['LD'] = ENV['CC']
 end
 
-if RUBY_PLATFORM =~ /darwin/
+if darwin && !cross_compiling
   ENV['AR'] = 'libtool'
   ENV['ARFLAGS'] = '-o'
- end
+end
 
 ENV['EMBED_OPENSSL'] = 'true'
 ENV['EMBED_ZLIB'] = 'true'
 ENV['EMBED_CARES'] = 'true'
 
 ENV['ARCH_FLAGS'] = RbConfig::CONFIG['ARCH_FLAG']
-if RUBY_PLATFORM =~ /darwin/
+if darwin && !cross_compiling
   if RUBY_PLATFORM =~ /arm64/
     ENV['ARCH_FLAGS'] = '-arch arm64'
   else
@@ -57,7 +60,7 @@ end
 
 ENV['CPPFLAGS'] = '-DGPR_BACKWARDS_COMPATIBILITY_MODE'
 ENV['CPPFLAGS'] += ' -DGRPC_XDS_USER_AGENT_NAME_SUFFIX="\"RUBY\"" '
-ENV['CPPFLAGS'] += ' -DGRPC_XDS_USER_AGENT_VERSION_SUFFIX="\"1.41.1\"" '
+ENV['CPPFLAGS'] += ' -DGRPC_XDS_USER_AGENT_VERSION_SUFFIX="\"1.42.0\"" '
 
 output_dir = File.expand_path(RbConfig::CONFIG['topdir'])
 grpc_lib_dir = File.join(output_dir, 'libs', grpc_config)
@@ -75,8 +78,8 @@ end
 $CFLAGS << ' -I' + File.join(grpc_root, 'include')
 
 ext_export_file = File.join(grpc_root, 'src', 'ruby', 'ext', 'grpc', 'ext-export')
-$LDFLAGS << ' -Wl,--version-script="' + ext_export_file + '.gcc"' if RUBY_PLATFORM =~ /linux/
-$LDFLAGS << ' -Wl,-exported_symbols_list,"' + ext_export_file + '.clang"' if RUBY_PLATFORM =~ /darwin/
+$LDFLAGS << ' -Wl,--version-script="' + ext_export_file + '.gcc"' if linux
+$LDFLAGS << ' -Wl,-exported_symbols_list,"' + ext_export_file + '.clang"' if darwin
 
 $LDFLAGS << ' ' + File.join(grpc_lib_dir, 'libgrpc.a') unless windows
 if grpc_config == 'gcov'
@@ -88,8 +91,8 @@ if grpc_config == 'dbg'
   $CFLAGS << ' -O0 -ggdb3'
 end
 
-$LDFLAGS << ' -Wl,-wrap,memcpy' if RUBY_PLATFORM =~ /linux/
-$LDFLAGS << ' -static-libgcc -static-libstdc++' if RUBY_PLATFORM =~ /linux/
+$LDFLAGS << ' -Wl,-wrap,memcpy' if linux
+$LDFLAGS << ' -static-libgcc -static-libstdc++' if linux
 $LDFLAGS << ' -static' if windows
 
 $CFLAGS << ' -std=c99 '
@@ -102,7 +105,7 @@ puts 'Generating Makefile for ' + output
 create_makefile(output)
 
 strip_tool = RbConfig::CONFIG['STRIP']
-strip_tool = 'strip -x' if RUBY_PLATFORM =~ /darwin/
+strip_tool += ' -x' if darwin
 
 if grpc_config == 'opt'
   File.open('Makefile.new', 'w') do |o|
index f05555a..874a5e9 100644 (file)
@@ -73,6 +73,7 @@ grpc_lame_client_channel_create_type grpc_lame_client_channel_create_import;
 grpc_channel_destroy_type grpc_channel_destroy_import;
 grpc_call_cancel_type grpc_call_cancel_import;
 grpc_call_cancel_with_status_type grpc_call_cancel_with_status_import;
+grpc_call_failed_before_recv_message_type grpc_call_failed_before_recv_message_import;
 grpc_call_ref_type grpc_call_ref_import;
 grpc_call_unref_type grpc_call_unref_import;
 grpc_server_request_call_type grpc_server_request_call_import;
@@ -184,6 +185,7 @@ grpc_tls_server_authorization_check_config_release_type grpc_tls_server_authoriz
 grpc_xds_credentials_create_type grpc_xds_credentials_create_import;
 grpc_xds_server_credentials_create_type grpc_xds_server_credentials_create_import;
 grpc_authorization_policy_provider_static_data_create_type grpc_authorization_policy_provider_static_data_create_import;
+grpc_authorization_policy_provider_file_watcher_create_type grpc_authorization_policy_provider_file_watcher_create_import;
 grpc_authorization_policy_provider_release_type grpc_authorization_policy_provider_release_import;
 grpc_raw_byte_buffer_create_type grpc_raw_byte_buffer_create_import;
 grpc_raw_compressed_byte_buffer_create_type grpc_raw_compressed_byte_buffer_create_import;
@@ -361,6 +363,7 @@ void grpc_rb_load_imports(HMODULE library) {
   grpc_channel_destroy_import = (grpc_channel_destroy_type) GetProcAddress(library, "grpc_channel_destroy");
   grpc_call_cancel_import = (grpc_call_cancel_type) GetProcAddress(library, "grpc_call_cancel");
   grpc_call_cancel_with_status_import = (grpc_call_cancel_with_status_type) GetProcAddress(library, "grpc_call_cancel_with_status");
+  grpc_call_failed_before_recv_message_import = (grpc_call_failed_before_recv_message_type) GetProcAddress(library, "grpc_call_failed_before_recv_message");
   grpc_call_ref_import = (grpc_call_ref_type) GetProcAddress(library, "grpc_call_ref");
   grpc_call_unref_import = (grpc_call_unref_type) GetProcAddress(library, "grpc_call_unref");
   grpc_server_request_call_import = (grpc_server_request_call_type) GetProcAddress(library, "grpc_server_request_call");
@@ -472,6 +475,7 @@ void grpc_rb_load_imports(HMODULE library) {
   grpc_xds_credentials_create_import = (grpc_xds_credentials_create_type) GetProcAddress(library, "grpc_xds_credentials_create");
   grpc_xds_server_credentials_create_import = (grpc_xds_server_credentials_create_type) GetProcAddress(library, "grpc_xds_server_credentials_create");
   grpc_authorization_policy_provider_static_data_create_import = (grpc_authorization_policy_provider_static_data_create_type) GetProcAddress(library, "grpc_authorization_policy_provider_static_data_create");
+  grpc_authorization_policy_provider_file_watcher_create_import = (grpc_authorization_policy_provider_file_watcher_create_type) GetProcAddress(library, "grpc_authorization_policy_provider_file_watcher_create");
   grpc_authorization_policy_provider_release_import = (grpc_authorization_policy_provider_release_type) GetProcAddress(library, "grpc_authorization_policy_provider_release");
   grpc_raw_byte_buffer_create_import = (grpc_raw_byte_buffer_create_type) GetProcAddress(library, "grpc_raw_byte_buffer_create");
   grpc_raw_compressed_byte_buffer_create_import = (grpc_raw_compressed_byte_buffer_create_type) GetProcAddress(library, "grpc_raw_compressed_byte_buffer_create");
index 33c636d..4667bce 100644 (file)
@@ -194,6 +194,9 @@ extern grpc_call_cancel_type grpc_call_cancel_import;
 typedef grpc_call_error(*grpc_call_cancel_with_status_type)(grpc_call* call, grpc_status_code status, const char* description, void* reserved);
 extern grpc_call_cancel_with_status_type grpc_call_cancel_with_status_import;
 #define grpc_call_cancel_with_status grpc_call_cancel_with_status_import
+typedef int(*grpc_call_failed_before_recv_message_type)(const grpc_call* c);
+extern grpc_call_failed_before_recv_message_type grpc_call_failed_before_recv_message_import;
+#define grpc_call_failed_before_recv_message grpc_call_failed_before_recv_message_import
 typedef void(*grpc_call_ref_type)(grpc_call* call);
 extern grpc_call_ref_type grpc_call_ref_import;
 #define grpc_call_ref grpc_call_ref_import
@@ -527,6 +530,9 @@ extern grpc_xds_server_credentials_create_type grpc_xds_server_credentials_creat
 typedef grpc_authorization_policy_provider*(*grpc_authorization_policy_provider_static_data_create_type)(const char* authz_policy, grpc_status_code* code, const char** error_details);
 extern grpc_authorization_policy_provider_static_data_create_type grpc_authorization_policy_provider_static_data_create_import;
 #define grpc_authorization_policy_provider_static_data_create grpc_authorization_policy_provider_static_data_create_import
+typedef grpc_authorization_policy_provider*(*grpc_authorization_policy_provider_file_watcher_create_type)(const char* authz_policy_path, unsigned int refresh_interval_sec, grpc_status_code* code, const char** error_details);
+extern grpc_authorization_policy_provider_file_watcher_create_type grpc_authorization_policy_provider_file_watcher_create_import;
+#define grpc_authorization_policy_provider_file_watcher_create grpc_authorization_policy_provider_file_watcher_create_import
 typedef void(*grpc_authorization_policy_provider_release_type)(grpc_authorization_policy_provider* provider);
 extern grpc_authorization_policy_provider_release_type grpc_authorization_policy_provider_release_import;
 #define grpc_authorization_policy_provider_release grpc_authorization_policy_provider_release_import
index 6ec5d1b..07c2988 100644 (file)
@@ -14,5 +14,5 @@
 
 # GRPC contains the General RPC module.
 module GRPC
-  VERSION = '1.41.1'
+  VERSION = '1.42.0'
 end
index ed4b5b5..d7d03ca 100644 (file)
@@ -1,10 +1,10 @@
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
 # source: src/proto/grpc/testing/test.proto
 
-require 'google/protobuf'
-
 require 'src/proto/grpc/testing/empty_pb'
 require 'src/proto/grpc/testing/messages_pb'
+require 'google/protobuf'
+
 Google::Protobuf::DescriptorPool.generated_pool.build do
   add_file("src/proto/grpc/testing/test.proto", :syntax => :proto3) do
   end
index 3f14f44..c11a500 100644 (file)
@@ -1,9 +1,9 @@
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
 # source: src/proto/grpc/testing/benchmark_service.proto
 
+require 'src/proto/grpc/testing/messages_pb'
 require 'google/protobuf'
 
-require 'src/proto/grpc/testing/messages_pb'
 Google::Protobuf::DescriptorPool.generated_pool.build do
   add_file("src/proto/grpc/testing/benchmark_service.proto", :syntax => :proto3) do
   end
index 0394c8b..c5eb6f9 100644 (file)
@@ -1,10 +1,10 @@
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
 # source: src/proto/grpc/testing/control.proto
 
-require 'google/protobuf'
-
 require 'src/proto/grpc/testing/payloads_pb'
 require 'src/proto/grpc/testing/stats_pb'
+require 'google/protobuf'
+
 Google::Protobuf::DescriptorPool.generated_pool.build do
   add_file("src/proto/grpc/testing/control.proto", :syntax => :proto3) do
     add_message "grpc.testing.PoissonParams" do
index 03461a4..9713db9 100644 (file)
@@ -1,9 +1,9 @@
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
 # source: src/proto/grpc/testing/report_qps_scenario_service.proto
 
+require 'src/proto/grpc/testing/control_pb'
 require 'google/protobuf'
 
-require 'src/proto/grpc/testing/control_pb'
 Google::Protobuf::DescriptorPool.generated_pool.build do
   add_file("src/proto/grpc/testing/report_qps_scenario_service.proto", :syntax => :proto3) do
   end
index 0c1f0e2..32342e5 100644 (file)
@@ -1,9 +1,9 @@
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
 # source: src/proto/grpc/testing/stats.proto
 
+require 'src/proto/grpc/core/stats_pb'
 require 'google/protobuf'
 
-require 'src/proto/grpc/core/stats_pb'
 Google::Protobuf::DescriptorPool.generated_pool.build do
   add_file("src/proto/grpc/testing/stats.proto", :syntax => :proto3) do
     add_message "grpc.testing.ServerStats" do
index 2fdef48..29d9d33 100644 (file)
@@ -1,9 +1,9 @@
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
 # source: src/proto/grpc/testing/worker_service.proto
 
+require 'src/proto/grpc/testing/control_pb'
 require 'google/protobuf'
 
-require 'src/proto/grpc/testing/control_pb'
 Google::Protobuf::DescriptorPool.generated_pool.build do
   add_file("src/proto/grpc/testing/worker_service.proto", :syntax => :proto3) do
   end
index afde507..78b4a7f 100644 (file)
@@ -311,7 +311,7 @@ shared_examples 'basic GRPC message delivery is OK' do
 
   it 'clients can cancel a call on the server' do
     expected_code = StatusCodes::CANCELLED
-    expected_details = 'Cancelled'
+    expected_details = 'CANCELLED'
     cancel_proc = proc { |call| call.cancel }
     client_cancel_test(cancel_proc, expected_code, expected_details)
   end
index 406b1fd..1041502 100644 (file)
@@ -14,6 +14,6 @@
 
 module GRPC
   module Tools
-    VERSION = '1.41.1'
+    VERSION = '1.42.0'
   end
 end
index 0f0883e..41e8d07 100644 (file)
   endif()
 
   if(WIN32)
-    set(_gRPC_BASELIB_LIBRARIES wsock32 ws2_32 crypt32)
+    set(_gRPC_BASELIB_LIBRARIES ws2_32 crypt32)
   endif()
 
   # Create directory for generated .proto files
   # grpcpp_channelz doesn't build with protobuf-lite, so no install required
   # See https://github.com/grpc/grpc/issues/22826
   if(gRPC_INSTALL AND NOT gRPC_USE_PROTO_LITE)
-  % elif tgt.build == 'protoc':
-  if(gRPC_INSTALL AND NOT CMAKE_CROSSCOMPILING)
   % else:
   if(gRPC_INSTALL)
   % endif
index 5afb36c..7e47866 100644 (file)
   GRPC_ABSEIL_DEP = $(LIBDIR)/$(CONFIG)/libgrpc_abseil.a
   GRPC_ABSEIL_MERGE_LIBS = $(LIBDIR)/$(CONFIG)/libgrpc_abseil.a
   ifeq ($(HOST_IS_X86_64),true)
-  ABSL_RANDOM_HWAES_FLAGS = -maes -msse4
+  ABSL_RANDOM_HWAES_FLAGS = -maes
   else
   ABSL_RANDOM_HWAES_FLAGS =
   endif
index 24f176b..7e2fc99 100644 (file)
 
     s.pod_target_xcconfig = {
       'HEADER_SEARCH_PATHS' => '"$(inherited)" "$(PODS_TARGET_SRCROOT)/include"',
-      'USER_HEADER_SEARCH_PATHS' => '"$(PODS_TARGET_SRCROOT)"',
+      'USER_HEADER_SEARCH_PATHS' => '"$(PODS_TARGET_SRCROOT)"'${"\\"}
+          ' "$(PODS_TARGET_SRCROOT)/src/core/ext/upb-generated"'${"\\"}
+          ' "$(PODS_TARGET_SRCROOT)/src/core/ext/upbdefs-generated"'${"\\"}
+          ' "$(PODS_TARGET_SRCROOT)/third_party/**"',
       'GCC_PREPROCESSOR_DEFINITIONS' => '"$(inherited)" "COCOAPODS=1"',
       'CLANG_WARN_STRICT_PROTOTYPES' => 'NO',
       'CLANG_WARN_DOCUMENTATION_COMMENTS' => 'NO',
       ss.header_mappings_dir = '.'
       ss.dependency "#{s.name}/Interface", version
       ss.dependency 'gRPC-Core', version
-      abseil_version = '1.20210324.0'
+      abseil_version = '1.20210324.2'
       % for abseil_spec in grpcpp_abseil_specs:
       ss.dependency '${abseil_spec}', abseil_version
       % endfor
       ss.source_files = "src/cpp/client/cronet_credentials.cc"
     end
 
+    # patch include of openssl to openssl_grpc
+    # patch xxhash.h to silent the -Wdocumentation error
     s.prepare_command = <<-END_OF_COMMAND
+      set -e
       find src/core -type f \\( -path '*.h' -or -path '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include <openssl/(.*)>;#if COCOAPODS==1\\\n  #include <openssl_grpc/\\1>\\\n#else\\\n  #include <openssl/\\1>\\\n#endif;g'
-      find third_party/upb/ -type f \\( -name '*.h' -or -name '*.hpp' -or -name '*.c' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "third_party/(.*)";#if COCOAPODS==1\\\n  #include  "third_party/upb/third_party/\\1"\\\n#else\\\n  #include  "third_party/\\1"\\\n#endif;g'
-      find src/core/ src/cpp/ third_party/upb/ -type f \\( -name '*.h' -or -name '*.hpp' -or -name '*.c' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "upb/(.*)";#if COCOAPODS==1\\\n  #include  "third_party/upb/upb/\\1"\\\n#else\\\n  #include  "upb/\\1"\\\n#endif;g'
-      find src/core/ src/cpp/ third_party/upb/ -type f -name '*.grpc_back' -print0 | xargs -0 rm
-      find src/core/ src/cpp/ third_party/upb/ -type f \\( -name '*.h' -or -name '*.c' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "(.*).upb.h";#if COCOAPODS==1\\\n  #include  "src/core/ext/upb-generated/\\1.upb.h"\\\n#else\\\n  #include  "\\1.upb.h"\\\n#endif;g'
-      find src/core/ src/cpp/ third_party/upb/ -type f \\( -name '*.h' -or -name '*.c' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "(.*).upbdefs.h";#if COCOAPODS==1\\\n  #include  "src/core/ext/upbdefs-generated/\\1.upbdefs.h"\\\n#else\\\n  #include  "\\1.upbdefs.h"\\\n#endif;g'
-      find src/core/ src/cpp/ -type f -name '*.grpc_back' -print0 | xargs -0 rm
-      find third_party/re2/re2/ third_party/re2/util/ -type f \\( -name '*.h' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "re2/(.*)";#if COCOAPODS==1\\\n  #include  "third_party/re2/re2/\\1"\\\n#else\\\n  #include  "re2/\\1"\\\n#endif;g;s;#include "util/(.*)";#if COCOAPODS==1\\\n  #include  "third_party/re2/util/\\1"\\\n#else\\\n  #include  "util/\\1"\\\n#endif;g'
-      find src/core/ -type f \\( -name '*.h' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "re2/(.*)";#if COCOAPODS==1\\\n  #include  "third_party/re2/re2/\\1"\\\n#else\\\n  #include  "re2/\\1"\\\n#endif;g'
-      find src/core/ third_party/re2/ -type f -name '*.grpc_back' -print0 | xargs -0 rm
-      find src/core/ -type f \\( -name '*.h' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "xxhash.h";#if COCOAPODS==1\\\n #include "third_party/xxhash/xxhash.h"\\\n#else\\\n #include "xxhash.h"\\\n#endif;g'
       find third_party/xxhash  -type f -name xxhash.h -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;@param([^,]*),;@param\\1 ,;g'
       find src/core/ third_party/xxhash/ -type f -name '*.grpc_back' -print0 | xargs -0 rm
     END_OF_COMMAND
index 4fc18b8..0ca639c 100644 (file)
     s.requires_arc = false
 
     name = 'grpc'
-    abseil_version = '1.20210324.0'
+    abseil_version = '1.20210324.2'
 
     # When creating a dynamic framework, name it grpc.framework instead of gRPC-Core.framework.
     # This lets users write their includes like `#include <grpc/grpc.h>` as opposed to `#include
     s.module_map = 'include/grpc/module.modulemap'
 
     # To compile the library, we need the user headers search path (quoted includes) to point to the
-    # root of the repo, and the system headers search path (angled includes) to point to `include/`.
-    # Cocoapods effectively clones the repo under `<Podfile dir>/Pods/gRPC-Core/`, and sets a build
-    # variable called `$(PODS_ROOT)` to `<Podfile dir>/Pods/`, so we use that.
-    #
-    # Relying on the file structure under $(PODS_ROOT) isn't officially supported in Cocoapods, as it
-    # is taken as an implementation detail. We've asked for an alternative, and have been told that
-    # what we're doing should keep working: https://github.com/CocoaPods/CocoaPods/issues/4386
-    #
-    # The `src_root` value of `$(PODS_ROOT)/gRPC-Core` assumes Cocoapods is installing this pod from
-    # its remote repo. For local development of this library, enabled by using `:path` in the Podfile,
-    # that assumption is wrong. In such case, the following settings need to be reset with the
-    # appropriate value of `src_root`. This can be accomplished in the `pre_install` hook of the
-    # Podfile; see `src/objective-c/tests/Podfile` for an example.
-    src_root = '$(PODS_ROOT)/gRPC-Core'
+    # root of the repo, third_party/** and two upb generated directories, and the system headers
+    # search path (angled includes) to point to `include/`.
     s.pod_target_xcconfig = {
-      'GRPC_SRC_ROOT' => src_root,
-      'HEADER_SEARCH_PATHS' => '"$(inherited)" "$(GRPC_SRC_ROOT)/include"',
-      'USER_HEADER_SEARCH_PATHS' => '"$(GRPC_SRC_ROOT)"',
+      'HEADER_SEARCH_PATHS' => '"$(inherited)" "$(PODS_TARGET_SRCROOT)/include"',
+      'USER_HEADER_SEARCH_PATHS' => '"$(PODS_TARGET_SRCROOT)"'${"\\"}
+          ' "$(PODS_TARGET_SRCROOT)/src/core/ext/upb-generated"'${"\\"}
+          ' "$(PODS_TARGET_SRCROOT)/src/core/ext/upbdefs-generated"'${"\\"}
+          ' "$(PODS_TARGET_SRCROOT)/third_party/**"',
       # If we don't set these two settings, `include/grpc/support/time.h` and
       # `src/core/lib/gpr/string.h` shadow the system `<time.h>` and `<string.h>`, breaking the
       # build.
       ss.header_mappings_dir = '.'
       ss.libraries = 'z'
       ss.dependency "#{s.name}/Interface", version
-      ss.dependency 'BoringSSL-GRPC', '0.0.21'
+      ss.dependency 'BoringSSL-GRPC', '0.0.22'
+      ss.dependency 'Libuv-gRPC', '0.0.10'
       % for abseil_spec in grpc_abseil_specs:
       ss.dependency '${abseil_spec}', abseil_version
       % endfor
       ss.source_files = ${ruby_multiline_list(grpc_test_util_files, 22)}
     end
 
-    # TODO (mxyan): Instead of this hack, add include path "third_party" to C core's include path?
+    # patch include of openssl to openssl_grpc
+    # patch xxhash.h to silent the -Wdocumentation error
     s.prepare_command = <<-END_OF_COMMAND
+      set -e
       find src/core -type f \\( -path '*.h' -or -path '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include <openssl/(.*)>;#if COCOAPODS==1\\\n  #include <openssl_grpc/\\1>\\\n#else\\\n  #include <openssl/\\1>\\\n#endif;g'
-      find third_party/upb/ -type f \\( -name '*.h' -or -name '*.hpp' -or -name '*.c' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "third_party/(.*)";#if COCOAPODS==1\\\n  #include  "third_party/upb/third_party/\\1"\\\n#else\\\n  #include  "third_party/\\1"\\\n#endif;g'
-      find src/core/ src/cpp/ third_party/upb/ -type f \\( -name '*.h' -or -name '*.hpp' -or -name '*.c' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "upb/(.*)";#if COCOAPODS==1\\\n  #include  "third_party/upb/upb/\\1"\\\n#else\\\n  #include  "upb/\\1"\\\n#endif;g'
-      find src/core/ src/cpp/ third_party/upb/ -type f -name '*.grpc_back' -print0 | xargs -0 rm
-      find src/core/ src/cpp/ third_party/upb/ -type f \\( -name '*.h' -or -name '*.c' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "(.*).upb.h";#if COCOAPODS==1\\\n  #include  "src/core/ext/upb-generated/\\1.upb.h"\\\n#else\\\n  #include  "\\1.upb.h"\\\n#endif;g'
-      find src/core/ src/cpp/ third_party/upb/ -type f \\( -name '*.h' -or -name '*.c' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "(.*).upbdefs.h";#if COCOAPODS==1\\\n  #include  "src/core/ext/upbdefs-generated/\\1.upbdefs.h"\\\n#else\\\n  #include  "\\1.upbdefs.h"\\\n#endif;g'
-      find src/core/ src/cpp/ third_party/upb/ -type f -name '*.grpc_back' -print0 | xargs -0 rm
-      find third_party/re2/re2/ third_party/re2/util/ -type f \\( -name '*.h' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "re2/(.*)";#if COCOAPODS==1\\\n  #include  "third_party/re2/re2/\\1"\\\n#else\\\n  #include  "re2/\\1"\\\n#endif;g;s;#include "util/(.*)";#if COCOAPODS==1\\\n  #include  "third_party/re2/util/\\1"\\\n#else\\\n  #include  "util/\\1"\\\n#endif;g'
-      find src/core/ -type f \\( -name '*.h' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "re2/(.*)";#if COCOAPODS==1\\\n  #include  "third_party/re2/re2/\\1"\\\n#else\\\n  #include  "re2/\\1"\\\n#endif;g'
-      find src/core/ third_party/re2/ -type f -name '*.grpc_back' -print0 | xargs -0 rm
-      find src/core/ -type f \\( -name '*.h' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "xxhash.h";#if COCOAPODS==1\\\n  #include  "third_party/xxhash/xxhash.h"\\\n#else\\\n  #include  "xxhash.h"\\\n#endif;g'
+      find src/core -type f \\( -path '*.h' -or -path '*.cc' -or -path '*.c' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include <uv.h>;#if COCOAPODS==1\\\n  #include <uv/uv.h>\\\n#else\\\n  #include  <uv.h>\\\n#endif;g'
       find third_party/xxhash  -type f -name xxhash.h -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;@param([^,]*),;@param\\1 ,;g'
-      find src/core/ third_party/xxhash/ -type f -name '*.grpc_back' -print0 | xargs -0 rm
+      find src/core/ third_party/xxhash/ third_party/uv/ -type f -name '*.grpc_back' -print0 | xargs -0 rm
     END_OF_COMMAND
   end
index ac543af..d7f625f 100644 (file)
@@ -43,7 +43,7 @@
     s.add_development_dependency 'simplecov',          '~> 0.14.1'
     s.add_development_dependency 'rake',               '~> 13.0'
     s.add_development_dependency 'rake-compiler',      '~> 1.1'
-    s.add_development_dependency 'rake-compiler-dock', '~> 1.0'
+    s.add_development_dependency 'rake-compiler-dock', '~> 1.1'
     s.add_development_dependency 'rspec',              '~> 3.6'
     s.add_development_dependency 'rubocop',            '~> 0.49.1'
     s.add_development_dependency 'signet',             '~> 0.7'
index 27aaacf..165d93a 100644 (file)
     # present in this pod's directory. We use that knowledge to check for the existence of the file
     # and, if absent, compile the plugin from the local sources.
     s.prepare_command = <<-CMD
+      set -e
       #{bazel} build //src/compiler:grpc_cpp_plugin
     CMD
   end
index 34a244c..498f5c2 100644 (file)
     # present in this pod's directory. We use that knowledge to check for the existence of the file
     # and, if absent, compile the plugin from the local sources.
     s.prepare_command = <<-CMD
+      set -e
       if [ ! -f #{plugin} ]; then
         #{bazel} build //src/compiler:grpc_objective_c_plugin
       fi
index 7955357..4ca3927 100644 (file)
@@ -1,7 +1,7 @@
 %YAML 1.2
 --- |
   # Proto Compiler CocoaPods podspec
-  
+
   # Copyright 2016, Google Inc.
   # All rights reserved.
   #
@@ -30,7 +30,7 @@
   # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
   # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-  
+
   Pod::Spec.new do |s|
     # This pod is only a utility that will be used by other pods _at install time_ (not at compile
     # time). Other pods can access it in their `prepare_command` script, under <pods_root>/<pod name>.
       :type => 'New BSD',
       :text => <<-LICENSE
         This license applies to all parts of Protocol Buffers except the following:
-  
+
         - Atomicops support for generic gcc, located in
           src/google/protobuf/stubs/atomicops_internals_generic_gcc.h.
           This file is copyrighted by Red Hat Inc.
-  
+
         - Atomicops support for AIX/POWER, located in
           src/google/protobuf/stubs/atomicops_internals_power.h.
           This file is copyrighted by Bloomberg Finance LP.
-  
+
         Copyright 2014, Google Inc.  All rights reserved.
-  
+
         Redistribution and use in source and binary forms, with or without
         modification, are permitted provided that the following conditions are
         met:
-  
+
             * Redistributions of source code must retain the above copyright
         notice, this list of conditions and the following disclaimer.
             * Redistributions in binary form must reproduce the above
@@ -76,7 +76,7 @@
             * Neither the name of Google Inc. nor the names of its
         contributors may be used to endorse or promote products derived from
         this software without specific prior written permission.
-  
+
         THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
         "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
         LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -88,7 +88,7 @@
         THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
         (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
         OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-  
+
         Code generated by the Protocol Buffer compiler is owned by the owner
         of the input file used when generating it.  This code is not
         standalone and requires a support library to be linked with it.  This
@@ -97,7 +97,7 @@
     }
     # "The name and email addresses of the library maintainers, not the Podspec maintainer."
     s.authors  = { 'The Protocol Buffers contributors' => 'protobuf@googlegroups.com' }
-  
+
     repo = 'google/protobuf'
     file = "protoc-#{v}-osx-x86_64.zip"
     s.source = {
       # TODO(jcanizales): Add sha1 or sha256
       # :sha1 => '??',
     }
-  
+
     s.preserve_paths = 'protoc',
                        'google/**/*.proto' # Well-known protobuf types
-  
+
     # Restrict the protobuf runtime version to the one supported by this version of protoc.
     s.dependency 'Protobuf', '~> 3.0'
     # For the Protobuf dependency not to complain:
     s.osx.deployment_target = '10.10'
     s.tvos.deployment_target = '10.0'
     s.watchos.deployment_target = '4.0'
-  
+
     # This is only for local development of protoc: If the Podfile brings this pod from a local
     # directory using `:path`, CocoaPods won't download the zip file and so the compiler won't be
     # present in this pod's directory. We use that knowledge to check for the existence of the file
     # and, if absent, build it from the local sources.
     repo_root = '../..'
     bazel = "#{repo_root}/tools/bazel"
-    
+
     s.prepare_command = <<-CMD
+      set -e
       if [ ! -f bin/protoc ]; then
         #{bazel} build @com_google_protobuf//:protoc
       else
index 1bb4c5f..ab88383 100644 (file)
@@ -69,7 +69,7 @@
 
   Pod::Spec.new do |s|
     s.name     = 'BoringSSL-GRPC'
-    version = '0.0.21'
+    version = '0.0.22'
     s.version  = version
     s.summary  = 'BoringSSL is a fork of OpenSSL that is designed to meet Google\'s needs.'
     # Adapted from the homepage:
     end
 
     s.prepare_command = <<-END_OF_COMMAND
+      set -e
       # Add a module map and an umbrella header
       mkdir -p src/include/openssl
       cat > src/include/openssl/umbrella.h <<EOF
diff --git a/templates/src/objective-c/Libuv-gRPC.podspec.template b/templates/src/objective-c/Libuv-gRPC.podspec.template
new file mode 100644 (file)
index 0000000..02d2fc7
--- /dev/null
@@ -0,0 +1,153 @@
+%YAML 1.2
+--- |
+  # This file has been automatically generated from a template file.
+  # Please make modifications to
+  # `templates/src/objective-c/libuv-gRPC.podspec.template` instead. This
+  # file can be regenerated from the template by running
+  # `tools/buildgen/generate_projects.sh`.
+
+  # Libuv CocoaPods podspec
+
+  # Copyright 2021, Google Inc.
+  # All rights reserved.
+  #
+  # Redistribution and use in source and binary forms, with or without
+  # modification, are permitted provided that the following conditions are
+  # met:
+  #
+  #     * Redistributions of source code must retain the above copyright
+  # notice, this list of conditions and the following disclaimer.
+  #     * Redistributions in binary form must reproduce the above
+  # copyright notice, this list of conditions and the following disclaimer
+  # in the documentation and/or other materials provided with the
+  # distribution.
+  #     * Neither the name of Google Inc. nor the names of its
+  # contributors may be used to endorse or promote products derived from
+  # this software without specific prior written permission.
+  #
+  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+  #   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+  # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+  # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+  # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+  # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+  # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+  # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  Pod::Spec.new do |spec|
+
+    pod_version           = "0.0.10"
+    libuv_version         = "1.37.0"
+
+    spec.name         = "Libuv-gRPC"
+    spec.version      = pod_version
+    spec.summary      = "gRPC-Only Libuv Pod"
+
+    spec.description  = <<-DESC
+      Libuv pod intended to be used only by gRPC iOS. libuv is a multi-platform
+      support library with a focus on asynchronous I/O. It was primarily developed
+      for use by Node.js, but it's also used by Luvit, Julia, pyuv, and others.
+    DESC
+
+    spec.homepage     = "https://libuv.org/"
+
+    spec.license  = { :type => 'Mixed', :file => 'LICENSE' }
+    spec.author    = "libuv"
+
+    # When using multiple platforms
+    spec.ios.deployment_target = '9.0'
+    spec.osx.deployment_target = '10.10'
+    spec.tvos.deployment_target = '10.0'
+    spec.watchos.deployment_target = '4.0'
+
+    spec.source       = { :git => "https://github.com/libuv/libuv.git", :tag => "v#{libuv_version}" }
+
+    name = 'uv'
+    spec.module_name = name
+    spec.header_mappings_dir = 'include'
+    spec.header_dir = name
+
+    spec.subspec 'Interface' do |ss|
+      ss.header_mappings_dir = 'include'
+      ss.source_files = "include/uv.h",
+                        "include/uv/errno.h",
+                        "include/uv/threadpool.h",
+                        "include/uv/version.h",
+                        "include/uv/tree.h",
+                        "include/uv/unix.h",
+                        "include/uv/darwin.h"
+    end
+
+    spec.subspec 'Implementation' do |ss|
+      ss.header_mappings_dir = 'src'
+      ss.source_files =
+      "src/fs-poll.c",
+      "src/idna.c",
+      "src/inet.c",
+      "src/strscpy.c",
+      "src/threadpool.c",
+      "src/timer.c",
+      "src/uv-data-getter-setters.c",
+      "src/uv-common.c",
+      "src/version.c",
+      "src/unix/async.c",
+      "src/unix/core.c",
+      "src/unix/dl.c",
+      "src/unix/fs.c",
+      "src/unix/getaddrinfo.c",
+      "src/unix/getnameinfo.c",
+      "src/unix/loop.c",
+      "src/unix/loop-watcher.c",
+      "src/unix/pipe.c",
+      "src/unix/poll.c",
+      "src/unix/process.c",
+      "src/unix/signal.c",
+      "src/unix/stream.c",
+      "src/unix/tcp.c",
+      "src/unix/thread.c",
+      "src/unix/tty.c",
+      "src/unix/udp.c",
+      "src/unix/bsd-ifaddrs.c",
+      "src/unix/darwin.c",
+      "src/unix/fsevents.c",
+      "src/unix/kqueue.c",
+      "src/unix/darwin-proctitle.c",
+      "src/unix/proctitle.c",
+      "src/heap-inl.h",
+      "src/idna.h",
+      "src/queue.h",
+      "src/strscpy.h",
+      "src/uv-common.h",
+      "src/unix/atomic-ops.h",
+      "src/unix/internal.h",
+      "src/unix/spinlock.h"
+
+      ss.dependency "#{spec.name}/Interface", pod_version
+    end
+
+    spec.requires_arc = false
+
+    spec.pod_target_xcconfig = {
+      'HEADER_SEARCH_PATHS' => '"$(inherited)" "$(PODS_TARGET_SRCROOT)/include"',
+      'USER_HEADER_SEARCH_PATHS' => '"$(PODS_TARGET_SRCROOT)" "$(PODS_TARGET_SRCROOT)/src" "$(PODS_TARGET_SRCROOT)/include"',
+      'CLANG_WARN_STRICT_PROTOTYPES' => 'NO',
+      'CLANG_WARN_DOCUMENTATION_COMMENTS' => 'NO',
+      'USE_HEADERMAP' => 'NO',
+      'ALWAYS_SEARCH_USER_PATHS' => 'NO',
+      'GCC_TREAT_WARNINGS_AS_ERRORS' => 'NO',
+      'GCC_WARN_INHIBIT_ALL_WARNINGS' => 'YES'
+    }
+
+    spec.libraries = 'c++'
+
+    spec.compiler_flags =
+      "-D_LARGEFILE_SOURCE",
+      "-D_FILE_OFFSET_BITS=64",
+      "-D_GNU_SOURCE",
+      "-D_DARWIN_USE_64_BIT_INODE=1",
+      "-D_DARWIN_UNLIMITED_SELECT=1"
+
+  end
index 8dbfd35..c03ac67 100644 (file)
@@ -16,7 +16,7 @@
 
   FROM php:${settings.php_version.php_current_version()}-${settings.php_version.php_debian_version()}
 
-  RUN apt-get -qq update && apt-get -qq install -y ${'\\'}
+  RUN apt-get -qq update && apt-get -qq -y upgrade && apt-get -qq install -y ${'\\'}
     autoconf automake git libtool pkg-config ${'\\'}
     valgrind wget zlib1g-dev
 
index 4921bce..b891f90 100644 (file)
@@ -16,7 +16,7 @@
 
   FROM php:${settings.php_version.php_current_version()}-${settings.php_version.php_debian_version()}
 
-  RUN apt-get -qq update && apt-get -qq install -y ${'\\'}
+  RUN apt-get -qq update && apt-get -qq -y upgrade && apt-get -qq install -y ${'\\'}
     autoconf automake git libtool pkg-config ${'\\'}
     valgrind wget zlib1g-dev
 
index 21f5de6..f277c67 100644 (file)
@@ -16,7 +16,7 @@
 
   FROM i386/php:${settings.php_version.php_current_version()}
 
-  RUN apt-get -qq update && apt-get -qq install -y ${'\\'}
+  RUN apt-get -qq update && apt-get -qq -y upgrade && apt-get -qq install -y ${'\\'}
     autoconf automake git libtool pkg-config ${'\\'}
     valgrind wget zlib1g-dev
 
index 7e7d286..d9da397 100644 (file)
@@ -16,7 +16,7 @@
 
   FROM php:7.4.11-buster
 
-  RUN apt-get -qq update && apt-get -qq install -y ${'\\'}
+  RUN apt-get -qq update && apt-get -qq -y upgrade && apt-get -qq install -y ${'\\'}
     autoconf automake git libtool pkg-config ${'\\'}
     valgrind wget zlib1g-dev
 
index d048aa6..548872f 100644 (file)
@@ -16,7 +16,7 @@
 
   FROM debian:${settings.php_version.php_debian_version()}
 
-  RUN apt-get -qq update && apt-get -qq install -y ${'\\'}
+  RUN apt-get -qq update && apt-get -qq -y upgrade && apt-get -qq install -y ${'\\'}
     autoconf build-essential git libtool ${'\\'}
     libcurl4-openssl-dev libedit-dev libsodium-dev ${'\\'}
     libssl-dev libxml2-dev ${'\\'}
index 1190d61..92e1144 100644 (file)
@@ -16,7 +16,7 @@
 
   FROM php:${settings.php_version.php_current_version()}-zts-${settings.php_version.php_debian_version()}
 
-  RUN apt-get -qq update && apt-get -qq install -y ${'\\'}
+  RUN apt-get -qq update && apt-get -qq -y upgrade && apt-get -qq install -y ${'\\'}
     autoconf automake git libtool pkg-config ${'\\'}
     wget zlib1g-dev
 
index d8c7ffb..7df1d57 100644 (file)
@@ -16,7 +16,7 @@
 
   FROM php:8.0.0-zts-buster
 
-  RUN apt-get -qq update && apt-get -qq install -y ${'\\'}
+  RUN apt-get -qq update && apt-get -qq -y upgrade && apt-get -qq install -y ${'\\'}
     autoconf automake git libtool pkg-config ${'\\'}
     valgrind wget zlib1g-dev
 
index 1130ba8..03a50d7 100644 (file)
@@ -19,6 +19,9 @@
   
   windows = RUBY_PLATFORM =~ /mingw|mswin/
   bsd = RUBY_PLATFORM =~ /bsd/
+  darwin = RUBY_PLATFORM =~ /darwin/
+  linux = RUBY_PLATFORM =~ /linux/
+  cross_compiling = ENV['RCD_HOST_RUBY_VERSION'] # set by rake-compiler-dock in build containers
   
   grpc_root = File.expand_path(File.join(File.dirname(__FILE__), '../../../..'))
   
       ENV['LD'] = ENV['CC']
   end
   
-  if RUBY_PLATFORM =~ /darwin/
+  if darwin && !cross_compiling
     ENV['AR'] = 'libtool'
     ENV['ARFLAGS'] = '-o'
-   end
+  end
   
   ENV['EMBED_OPENSSL'] = 'true'
   ENV['EMBED_ZLIB'] = 'true'
   ENV['EMBED_CARES'] = 'true'
   
   ENV['ARCH_FLAGS'] = RbConfig::CONFIG['ARCH_FLAG']
-  if RUBY_PLATFORM =~ /darwin/
+  if darwin && !cross_compiling
     if RUBY_PLATFORM =~ /arm64/
       ENV['ARCH_FLAGS'] = '-arch arm64'
     else
@@ -77,8 +80,8 @@
   $CFLAGS << ' -I' + File.join(grpc_root, 'include')
   
   ext_export_file = File.join(grpc_root, 'src', 'ruby', 'ext', 'grpc', 'ext-export')
-  $LDFLAGS << ' -Wl,--version-script="' + ext_export_file + '.gcc"' if RUBY_PLATFORM =~ /linux/
-  $LDFLAGS << ' -Wl,-exported_symbols_list,"' + ext_export_file + '.clang"' if RUBY_PLATFORM =~ /darwin/
+  $LDFLAGS << ' -Wl,--version-script="' + ext_export_file + '.gcc"' if linux
+  $LDFLAGS << ' -Wl,-exported_symbols_list,"' + ext_export_file + '.clang"' if darwin
   
   $LDFLAGS << ' ' + File.join(grpc_lib_dir, 'libgrpc.a') unless windows
   if grpc_config == 'gcov'
@@ -90,8 +93,8 @@
     $CFLAGS << ' -O0 -ggdb3'
   end
   
-  $LDFLAGS << ' -Wl,-wrap,memcpy' if RUBY_PLATFORM =~ /linux/
-  $LDFLAGS << ' -static-libgcc -static-libstdc++' if RUBY_PLATFORM =~ /linux/
+  $LDFLAGS << ' -Wl,-wrap,memcpy' if linux
+  $LDFLAGS << ' -static-libgcc -static-libstdc++' if linux
   $LDFLAGS << ' -static' if windows
   
   $CFLAGS << ' -std=c99 '
   create_makefile(output)
   
   strip_tool = RbConfig::CONFIG['STRIP']
-  strip_tool = 'strip -x' if RUBY_PLATFORM =~ /darwin/
+  strip_tool += ' -x' if darwin
   
   if grpc_config == 'opt'
     File.open('Makefile.new', 'w') do |o|
index 16651c6..c0338ab 100644 (file)
@@ -2,7 +2,7 @@
 # Bazel installation
 
 # Must be in sync with tools/bazel
-ENV BAZEL_VERSION 3.7.1
+ENV BAZEL_VERSION 4.2.1
 
 # The correct bazel version is already preinstalled, no need to use //tools/bazel wrapper.
 ENV DISABLE_BAZEL_WRAPPER 1
index 589084d..999eedf 100644 (file)
@@ -14,7 +14,7 @@
   # See the License for the specific language governing permissions and
   # limitations under the License.
   
-  <%include file="../../debian_8_header.include"/>
+  <%include file="../../debian_9_header.include"/>
   
   <%include file="../../php7_deps.include"/>
   <%include file="../../run_tests_addons.include"/>
diff --git a/templates/tools/dockerfile/libuv_install.include b/templates/tools/dockerfile/libuv_install.include
deleted file mode 100644 (file)
index a249c09..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#================
-# libuv
-RUN cd /tmp \
-    && wget http://dist.libuv.org/dist/v1.9.1/libuv-v1.9.1.tar.gz \
-    && tar -xf libuv-v1.9.1.tar.gz \
-    && cd libuv-v1.9.1 \
-    && sh autogen.sh && ./configure --prefix=/usr && make && make install
\ No newline at end of file
index 0c4c351..7a70623 100644 (file)
@@ -9,6 +9,7 @@ RUN apt-get update && apt-get install -y ${'\\'}
   ccache ${'\\'}
   curl ${'\\'}
   git ${'\\'}
+  libbison-dev ${'\\'}
   libcurl4-openssl-dev ${'\\'}
   libgmp-dev ${'\\'}
   libgmp3-dev ${'\\'}
@@ -20,26 +21,17 @@ RUN apt-get update && apt-get install -y ${'\\'}
   time ${'\\'}
   unzip ${'\\'}
   wget ${'\\'}
-  zip && apt-get clean
-
-# Install other dependencies
-RUN ln -sf /usr/include/x86_64-linux-gnu/gmp.h /usr/include/gmp.h
-RUN wget http://ftp.gnu.org/gnu/bison/bison-3.4.2.tar.gz -O /var/local/bison-3.4.2.tar.gz
-RUN cd /var/local ${'\\'}
-  && tar -zxvf bison-3.4.2.tar.gz ${'\\'}
-  && cd /var/local/bison-3.4.2 ${'\\'}
-  && ./configure ${'\\'}
-  && make ${'\\'}
-  && make install
+  zip ${'\\'}
+  zlib1g-dev && apt-get clean
 
 # Compile PHP7 from source
 RUN git clone https://github.com/php/php-src /var/local/git/php-src
 RUN cd /var/local/git/php-src ${'\\'}
-  && git checkout PHP-7.2.22 ${'\\'}
+  && git checkout PHP-7.2.34 ${'\\'}
   && ./buildconf --force ${'\\'}
   && ./configure ${'\\'}
   --with-gmp ${'\\'}
   --with-openssl ${'\\'}
   --with-zlib ${'\\'}
-  && make ${'\\'}
+  && make -j$(nproc) ${'\\'}
   && make install
diff --git a/templates/tools/dockerfile/test/cxx_clang_12_x64/Dockerfile.template b/templates/tools/dockerfile/test/cxx_clang_12_x64/Dockerfile.template
new file mode 100644 (file)
index 0000000..6da7861
--- /dev/null
@@ -0,0 +1,29 @@
+%YAML 1.2
+--- |
+  # 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.
+  
+  FROM silkeh/clang:12
+  
+  RUN apt-get update && apt-get install -y build-essential curl git golang time wget zip
+  <%include file="../../python_deps.include"/>
+  RUN pip install PyYAML==5.4.1
+  RUN apt-get install python-is-python2
+  <%include file="../../gcp_api_libraries.include"/>
+  <%include file="../../cxx_deps.include"/>
+  <%include file="../../cmake.include"/>
+  <%include file="../../run_tests_addons.include"/>
+  
+  # Define the default command.
+  CMD ["bash"]
diff --git a/templates/tools/dockerfile/test/cxx_clang_4_x64/Dockerfile.template b/templates/tools/dockerfile/test/cxx_clang_4_x64/Dockerfile.template
new file mode 100644 (file)
index 0000000..2f1ae7b
--- /dev/null
@@ -0,0 +1,29 @@
+%YAML 1.2
+--- |
+  # 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.
+  
+  FROM silkeh/clang:4
+  
+  RUN apt-get update && apt-get install -y build-essential curl git golang time wget zip
+  <%include file="../../python_deps.include"/>
+  RUN pip install PyYAML==5.4.1
+  RUN apt-get install python-is-python2
+  <%include file="../../gcp_api_libraries.include"/>
+  <%include file="../../cxx_deps.include"/>
+  <%include file="../../cmake.include"/>
+  <%include file="../../run_tests_addons.include"/>
+  
+  # Define the default command.
+  CMD ["bash"]
diff --git a/templates/tools/dockerfile/test/cxx_gcc_11_x64/Dockerfile.template b/templates/tools/dockerfile/test/cxx_gcc_11_x64/Dockerfile.template
new file mode 100644 (file)
index 0000000..b81bdc6
--- /dev/null
@@ -0,0 +1,29 @@
+%YAML 1.2
+--- |
+  # 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.
+  
+  FROM gcc:11
+  
+  RUN apt-get update && apt-get install -y curl git golang time wget zip
+  <%include file="../../python_deps.include"/>
+  RUN pip install PyYAML==5.4.1
+  RUN apt-get install python-is-python2
+  <%include file="../../gcp_api_libraries.include"/>
+  <%include file="../../cxx_deps.include"/>
+  <%include file="../../cmake.include"/>
+  <%include file="../../run_tests_addons.include"/>
+  
+  # Define the default command.
+  CMD ["bash"]
index 8b8f18f..0577d18 100644 (file)
@@ -22,7 +22,6 @@
   <%include file="../../cxx_deps.include"/>
   <%include file="../../cmake_jessie_backports.include"/>
   <%include file="../../run_tests_addons.include"/>
-  <%include file="../../libuv_install.include"/>
 
   # Install gcc-4.9 and other relevant items
   RUN apt-get update && apt-get -y install gcc gcc-multilib g++ g++-multilib && apt-get clean
diff --git a/templates/tools/dockerfile/test/cxx_ubuntu1804_x64/Dockerfile.template b/templates/tools/dockerfile/test/cxx_ubuntu1804_x64/Dockerfile.template
deleted file mode 100644 (file)
index 1f8d3bd..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-%YAML 1.2
---- |
-  # 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.
-  
-  FROM ubuntu:18.04
-  
-  <%include file="../../apt_get_basic.include"/>
-  <%include file="../../python_deps.include"/>
-  <%include file="../../gcp_api_libraries.include"/>
-  <%include file="../../cxx_deps.include"/>
-  <%include file="../../cmake.include"/>
-  <%include file="../../run_tests_addons.include"/>
-  
-  # Define the default command.
-  CMD ["bash"]
diff --git a/templates/tools/dockerfile/test/php7_debian9_x64/Dockerfile.template b/templates/tools/dockerfile/test/php7_debian9_x64/Dockerfile.template
new file mode 100644 (file)
index 0000000..d39daec
--- /dev/null
@@ -0,0 +1,25 @@
+%YAML 1.2
+--- |
+  # 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 file="../../debian_9_header.include"/>
+  
+  <%include file="../../php7_deps.include"/>
+  <%include file="../../python_deps.include"/>
+  <%include file="../../gcp_api_libraries.include"/>
+  <%include file="../../php_valgrind.include"/>
+  <%include file="../../run_tests_addons.include"/>
+  # Define the default command.
+  CMD ["bash"]
diff --git a/templates/tools/dockerfile/test/php7_jessie_x64/Dockerfile.template b/templates/tools/dockerfile/test/php7_jessie_x64/Dockerfile.template
deleted file mode 100644 (file)
index 8d8b34b..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-%YAML 1.2
---- |
-  # 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 file="../../debian_8_header.include"/>
-  
-  <%include file="../../php7_deps.include"/>
-  <%include file="../../python_deps.include"/>
-  <%include file="../../gcp_api_libraries.include"/>
-  <%include file="../../php_valgrind.include"/>
-  <%include file="../../run_tests_addons.include"/>
-  # Define the default command.
-  CMD ["bash"]
diff --git a/templates/tools/fuzzer/runners.template b/templates/tools/fuzzer/runners.template
deleted file mode 100644 (file)
index ee7f32e..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-%YAML 1.2
----
-foreach: targets
-cond: selected.build == 'fuzzer'
-output_name: ${selected.name}.sh
-template: |
-  #!/bin/bash
-  # 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.
-  #
-
-  flags="-max_total_time=$runtime -artifact_prefix=fuzzer_output/ -max_len=${selected.maxlen} -timeout=120"
-  
-  %if selected.get('dict'):
-  flags="$flags -dict=${selected.dict}"
-  %endif
-
-  if [ "$jobs" != "1" ]
-  then
-    flags="-jobs=$jobs -workers=$jobs $flags"
-  fi
-
-  if [ "$config" == "asan-trace-cmp" ]
-  then
-    flags="-use_traces=1 $flags"
-  fi
-
-  bins/$config/${selected.name} $flags fuzzer_output ${' '.join(selected.corpus_dirs)}
index d47cbda..f8108b6 100644 (file)
@@ -14,7 +14,7 @@
 
 load("//bazel:grpc_build_system.bzl", "grpc_cc_binary", "grpc_cc_library", "grpc_cc_test", "grpc_package")
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 grpc_package(name = "test/core/avl")
 
index 38020cc..1d0689e 100644 (file)
@@ -14,7 +14,7 @@
 
 load("//bazel:grpc_build_system.bzl", "grpc_cc_binary", "grpc_cc_library", "grpc_cc_test")
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 package(
     features = [
index 22879c0..096582f 100644 (file)
@@ -16,7 +16,7 @@ load("//bazel:grpc_build_system.bzl", "grpc_cc_binary", "grpc_cc_library", "grpc
 
 grpc_package(name = "test/core/bad_client")
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 load(":generate_tests.bzl", "grpc_bad_client_tests")
 
index d2cdb2b..85a70b3 100644 (file)
@@ -66,10 +66,12 @@ static void set_done_write(void* arg, grpc_error_handle /*error*/) {
 static void server_setup_transport(void* ts, grpc_transport* transport) {
   thd_args* a = static_cast<thd_args*>(ts);
   grpc_core::ExecCtx exec_ctx;
-  a->server->core_server->SetupTransport(transport,
-                                         /*accepting_pollset=*/nullptr,
-                                         a->server->core_server->channel_args(),
-                                         /*socket_node=*/nullptr);
+  GPR_ASSERT(GRPC_LOG_IF_ERROR(
+      "SetupTransport",
+      a->server->core_server->SetupTransport(
+          transport,
+          /*accepting_pollset=*/nullptr, a->server->core_server->channel_args(),
+          /*socket_node=*/nullptr)));
 }
 
 /* Sets the read_done event */
index a76f55d..85b5c94 100644 (file)
@@ -124,9 +124,9 @@ TEST(BadStreamingId, ClosedStreamId) {
 }  // namespace
 
 int main(int argc, char** argv) {
-  grpc_init();
   grpc::testing::TestEnvironment env(argc, argv);
   ::testing::InitGoogleTest(&argc, argv);
+  grpc_init();
   int retval = RUN_ALL_TESTS();
   grpc_shutdown();
   return retval;
index 188de86..cb140eb 100644 (file)
@@ -99,7 +99,7 @@ size_t g_count = 0;
 
 static void addbuf(const void* data, size_t len) {
   if (g_count + len > g_cap) {
-    g_cap = GPR_MAX(g_count + len, g_cap * 2);
+    g_cap = std::max(g_count + len, g_cap * 2);
     g_buffer = static_cast<char*>(gpr_realloc(g_buffer, g_cap));
   }
   memcpy(g_buffer + g_count, data, len);
index ce3f1d8..7bf1a91 100644 (file)
@@ -104,9 +104,9 @@ TEST(OutOfBounds, WindowUpdate) {
 }  // namespace
 
 int main(int argc, char** argv) {
-  grpc_init();
   grpc::testing::TestEnvironment env(argc, argv);
   ::testing::InitGoogleTest(&argc, argv);
+  grpc_init();
   int retval = RUN_ALL_TESTS();
   grpc_shutdown();
   return retval;
index 04ce10e..e11625b 100644 (file)
@@ -57,9 +57,9 @@ TEST(UnknownFrameType, Test) {
 }  // namespace
 
 int main(int argc, char** argv) {
-  grpc_init();
   grpc::testing::TestEnvironment env(argc, argv);
   ::testing::InitGoogleTest(&argc, argv);
+  grpc_init();
   int retval = RUN_ALL_TESTS();
   grpc_shutdown();
   return retval;
index cff0cfb..81fa27e 100644 (file)
@@ -56,7 +56,7 @@ size_t g_count = 0;
 
 static void addbuf(const void* data, size_t len) {
   if (g_count + len > g_cap) {
-    g_cap = GPR_MAX(g_count + len, g_cap * 2);
+    g_cap = std::max(g_count + len, g_cap * 2);
     g_buffer = static_cast<char*>(gpr_realloc(g_buffer, g_cap));
   }
   memcpy(g_buffer + g_count, data, len);
index 8111c7e..d2e15b9 100644 (file)
@@ -14,7 +14,7 @@
 
 load("//bazel:grpc_build_system.bzl", "grpc_cc_binary", "grpc_cc_library", "grpc_cc_test", "grpc_package")
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 grpc_package(name = "test/core/bad_connection")
 
index 4b4c1a7..5d8e19f 100644 (file)
@@ -74,8 +74,11 @@ static test_ctx g_ctx;
 static void server_setup_transport(grpc_transport* transport) {
   grpc_core::ExecCtx exec_ctx;
   grpc_endpoint_add_to_pollset(g_ctx.ep->server, grpc_cq_pollset(g_ctx.cq));
-  g_ctx.server->core_server->SetupTransport(
-      transport, nullptr, g_ctx.server->core_server->channel_args(), nullptr);
+  GPR_ASSERT(GRPC_LOG_IF_ERROR(
+      "SetupTransport",
+      g_ctx.server->core_server->SetupTransport(
+          transport, nullptr, g_ctx.server->core_server->channel_args(),
+          nullptr)));
 }
 
 static void client_setup_transport(grpc_transport* transport) {
index 757d86c..3bf44cb 100644 (file)
@@ -16,7 +16,7 @@ load("//bazel:grpc_build_system.bzl", "grpc_cc_binary", "grpc_cc_library", "grpc
 
 grpc_package(name = "test/core/bad_ssl")
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 load(":generate_tests.bzl", "grpc_bad_ssl_tests")
 
index 88ddea9..14edcf4 100644 (file)
@@ -16,7 +16,7 @@ load("//bazel:grpc_build_system.bzl", "grpc_cc_binary", "grpc_cc_library", "grpc
 
 grpc_package(name = "test/core/channel")
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 grpc_cc_test(
     name = "channel_args_test",
@@ -45,6 +45,9 @@ grpc_cc_test(
 grpc_cc_test(
     name = "channel_stack_builder_test",
     srcs = ["channel_stack_builder_test.cc"],
+    external_deps = [
+        "gtest",
+    ],
     language = "C++",
     deps = [
         "//:gpr",
index 8680d3c..d683f51 100644 (file)
@@ -72,7 +72,9 @@ static void fake_pointer_arg_destroy(void* arg) {
   gpr_free(fc);
 }
 
-static int fake_pointer_cmp(void* a, void* b) { return GPR_ICMP(a, b); }
+static int fake_pointer_cmp(void* a, void* b) {
+  return grpc_core::QsortCompare(a, b);
+}
 
 static const grpc_arg_pointer_vtable fake_pointer_arg_vtable = {
     fake_pointer_arg_copy, fake_pointer_arg_destroy, fake_pointer_cmp};
index 409e913..f9ad5d9 100644 (file)
 #include <limits.h>
 #include <string.h>
 
+#include <gtest/gtest.h>
+
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
 
+#include "src/core/lib/config/core_configuration.h"
 #include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/surface/channel_init.h"
 #include "test/core/util/test_config.h"
 
-static grpc_error_handle channel_init_func(
-    grpc_channel_element* /*elem*/, grpc_channel_element_args* /*args*/) {
+namespace grpc_core {
+namespace testing {
+namespace {
+
+grpc_error_handle ChannelInitFunc(grpc_channel_element* /*elem*/,
+                                  grpc_channel_element_args* /*args*/) {
   return GRPC_ERROR_NONE;
 }
 
-static grpc_error_handle call_init_func(
-    grpc_call_element* /*elem*/, const grpc_call_element_args* /*args*/) {
+grpc_error_handle CallInitFunc(grpc_call_element* /*elem*/,
+                               const grpc_call_element_args* /*args*/) {
   return GRPC_ERROR_NONE;
 }
 
-static void channel_destroy_func(grpc_channel_element* /*elem*/) {}
+void ChannelDestroyFunc(grpc_channel_element* /*elem*/) {}
 
-static void call_destroy_func(grpc_call_element* /*elem*/,
-                              const grpc_call_final_info* /*final_info*/,
-                              grpc_closure* /*ignored*/) {}
+void CallDestroyFunc(grpc_call_element* /*elem*/,
+                     const grpc_call_final_info* /*final_info*/,
+                     grpc_closure* /*ignored*/) {}
 
 bool g_replacement_fn_called = false;
 bool g_original_fn_called = false;
-void set_arg_once_fn(grpc_channel_stack* /*channel_stack*/,
-                     grpc_channel_element* /*elem*/, void* arg) {
+void SetArgOnceFn(grpc_channel_stack* /*channel_stack*/,
+                  grpc_channel_element* /*elem*/, void* arg) {
   bool* called = static_cast<bool*>(arg);
   // Make sure this function is only called once per arg.
   GPR_ASSERT(*called == false);
   *called = true;
 }
 
-static void test_channel_stack_builder_filter_replace(void) {
+TEST(ChannelStackBuilderTest, ReplaceFilter) {
   grpc_channel* channel =
       grpc_insecure_channel_create("target name isn't used", nullptr, nullptr);
   GPR_ASSERT(channel != nullptr);
@@ -70,12 +77,12 @@ const grpc_channel_filter replacement_filter = {
     grpc_call_next_op,
     grpc_channel_next_op,
     0,
-    call_init_func,
+    CallInitFunc,
     grpc_call_stack_ignore_set_pollset_or_pollset_set,
-    call_destroy_func,
+    CallDestroyFunc,
     0,
-    channel_init_func,
-    channel_destroy_func,
+    ChannelInitFunc,
+    ChannelDestroyFunc,
     grpc_channel_next_get_info,
     "filter_name"};
 
@@ -83,49 +90,47 @@ const grpc_channel_filter original_filter = {
     grpc_call_next_op,
     grpc_channel_next_op,
     0,
-    call_init_func,
+    CallInitFunc,
     grpc_call_stack_ignore_set_pollset_or_pollset_set,
-    call_destroy_func,
+    CallDestroyFunc,
     0,
-    channel_init_func,
-    channel_destroy_func,
+    ChannelInitFunc,
+    ChannelDestroyFunc,
     grpc_channel_next_get_info,
     "filter_name"};
 
-static bool add_replacement_filter(grpc_channel_stack_builder* builder,
-                                   void* arg) {
-  const grpc_channel_filter* filter =
-      static_cast<const grpc_channel_filter*>(arg);
+static bool AddReplacementFilter(grpc_channel_stack_builder* builder) {
   // Get rid of any other version of the filter, as determined by having the
   // same name.
-  GPR_ASSERT(grpc_channel_stack_builder_remove_filter(builder, filter->name));
+  GPR_ASSERT(grpc_channel_stack_builder_remove_filter(builder,
+                                                      replacement_filter.name));
   return grpc_channel_stack_builder_prepend_filter(
-      builder, filter, set_arg_once_fn, &g_replacement_fn_called);
+      builder, &replacement_filter, SetArgOnceFn, &g_replacement_fn_called);
 }
 
-static bool add_original_filter(grpc_channel_stack_builder* builder,
-                                void* arg) {
+bool AddOriginalFilter(grpc_channel_stack_builder* builder) {
   return grpc_channel_stack_builder_prepend_filter(
-      builder, static_cast<const grpc_channel_filter*>(arg), set_arg_once_fn,
-      &g_original_fn_called);
-}
-
-static void init_plugin(void) {
-  grpc_channel_init_register_stage(
-      GRPC_CLIENT_CHANNEL, INT_MAX, add_original_filter,
-      const_cast<grpc_channel_filter*>(&original_filter));
-  grpc_channel_init_register_stage(
-      GRPC_CLIENT_CHANNEL, INT_MAX, add_replacement_filter,
-      const_cast<grpc_channel_filter*>(&replacement_filter));
+      builder, &original_filter, SetArgOnceFn, &g_original_fn_called);
 }
 
-static void destroy_plugin(void) {}
+}  // namespace
+}  // namespace testing
+}  // namespace grpc_core
 
 int main(int argc, char** argv) {
+  ::testing::InitGoogleTest(&argc, argv);
   grpc::testing::TestEnvironment env(argc, argv);
-  grpc_register_plugin(init_plugin, destroy_plugin);
+  grpc_core::CoreConfiguration::RegisterBuilder(
+      [](grpc_core::CoreConfiguration::Builder* builder) {
+        builder->channel_init()->RegisterStage(
+            GRPC_CLIENT_CHANNEL, INT_MAX,
+            grpc_core::testing::AddOriginalFilter);
+        builder->channel_init()->RegisterStage(
+            GRPC_CLIENT_CHANNEL, INT_MAX,
+            grpc_core::testing::AddReplacementFilter);
+      });
   grpc_init();
-  test_channel_stack_builder_filter_replace();
+  int ret = RUN_ALL_TESTS();
   grpc_shutdown();
-  return 0;
+  return ret;
 }
index 8c872c1..0f2861b 100644 (file)
@@ -108,8 +108,10 @@ static void test_create_channel_stack(void) {
 
   channel_stack = static_cast<grpc_channel_stack*>(
       gpr_malloc(grpc_channel_stack_size(&filters, 1)));
-  grpc_channel_stack_init(1, free_channel, channel_stack, &filters, 1,
-                          &chan_args, nullptr, "test", channel_stack);
+  GPR_ASSERT(GRPC_LOG_IF_ERROR(
+      "grpc_channel_stack_init",
+      grpc_channel_stack_init(1, free_channel, channel_stack, &filters, 1,
+                              &chan_args, nullptr, "test", channel_stack)));
   GPR_ASSERT(channel_stack->count == 1);
   channel_elem = grpc_channel_stack_element(channel_stack, 0);
   channel_data = static_cast<int*>(channel_elem->channel_data);
index 5aca1fe..4eda818 100644 (file)
@@ -40,6 +40,7 @@
 #include <grpc/support/string_util.h>
 
 #include "src/core/lib/channel/channel_stack_builder.h"
+#include "src/core/lib/config/core_configuration.h"
 #include "src/core/lib/gpr/string.h"
 #include "src/core/lib/surface/channel_init.h"
 #include "src/core/lib/surface/channel_stack_type.h"
@@ -138,7 +139,7 @@ static int check_stack(const char* file, int line, const char* transport_name,
   {
     grpc_core::ExecCtx exec_ctx;
     grpc_channel_stack_builder_set_channel_arguments(builder, channel_args);
-    GPR_ASSERT(grpc_channel_init_create_stack(
+    GPR_ASSERT(grpc_core::CoreConfiguration::Get().channel_init().CreateStack(
         builder, (grpc_channel_stack_type)channel_stack_type));
   }
 
index 3c2e9ed..c5b6b05 100644 (file)
@@ -58,3 +58,17 @@ grpc_cc_test(
         "//test/core/util:grpc_test_util",
     ],
 )
+
+grpc_cc_test(
+    name = "rls_lb_config_parser_test",
+    srcs = ["rls_lb_config_parser_test.cc"],
+    external_deps = [
+        "gtest",
+    ],
+    language = "C++",
+    tags = ["no_test_ios"],
+    deps = [
+        "//:grpc",
+        "//test/core/util:grpc_test_util",
+    ],
+)
index ac351fe..224df41 100644 (file)
 
 load("//bazel:grpc_build_system.bzl", "grpc_cc_binary", "grpc_cc_library", "grpc_cc_test", "grpc_package")
 
-grpc_package(name = "test/core/client_channel_resolvers")
+grpc_package(name = "test/core/client_channel/resolvers")
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
+
+grpc_cc_test(
+    name = "binder_resolver_test",
+    srcs = ["binder_resolver_test.cc"],
+    external_deps = [
+        "gtest",
+    ],
+    language = "C++",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:grpc_test_util",
+    ],
+)
 
 grpc_cc_test(
     name = "dns_resolver_connectivity_using_ares_test",
diff --git a/test/core/client_channel/resolvers/binder_resolver_test.cc b/test/core/client_channel/resolvers/binder_resolver_test.cc
new file mode 100644 (file)
index 0000000..4065a39
--- /dev/null
@@ -0,0 +1,181 @@
+// 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 <gtest/gtest.h>
+
+#include "src/core/lib/iomgr/port.h"
+#include "test/core/util/test_config.h"
+
+#ifdef GRPC_HAVE_UNIX_SOCKET
+
+#include <sys/un.h>
+
+#include <cstring>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+
+#include "src/core/ext/filters/client_channel/resolver_registry.h"
+#include "src/core/lib/channel/channel_args.h"
+
+// Registers the factory with `grpc_core::ResolverRegistry`. Defined in
+// binder_resolver.cc
+void grpc_resolver_binder_init(void);
+
+namespace {
+
+class BinderResolverTest : public ::testing::Test {
+ public:
+  BinderResolverTest() {
+    factory_ = grpc_core::ResolverRegistry::LookupResolverFactory("binder");
+  }
+  ~BinderResolverTest() override {}
+  static void SetUpTestSuite() {
+    grpc_init();
+    if (grpc_core::ResolverRegistry::LookupResolverFactory("binder") ==
+        nullptr) {
+      // Binder resolver will only be registered on platforms that support
+      // binder transport. If it is not registered on current platform, we
+      // manually register it here for testing purpose.
+      grpc_resolver_binder_init();
+      ASSERT_TRUE(grpc_core::ResolverRegistry::LookupResolverFactory("binder"));
+    }
+  }
+  static void TearDownTestSuite() { grpc_shutdown(); }
+
+  void SetUp() override { ASSERT_TRUE(factory_); }
+
+  class ResultHandler : public grpc_core::Resolver::ResultHandler {
+   public:
+    ResultHandler() = default;
+
+    explicit ResultHandler(const std::string& expected_binder_id)
+        : expect_result_(true), expected_binder_id_(expected_binder_id) {}
+
+    void ReturnResult(grpc_core::Resolver::Result result) override {
+      EXPECT_TRUE(expect_result_);
+      ASSERT_TRUE(result.addresses.size() == 1);
+      grpc_core::ServerAddress addr = result.addresses[0];
+      const struct sockaddr_un* un =
+          reinterpret_cast<const struct sockaddr_un*>(addr.address().addr);
+      EXPECT_EQ(addr.address().len,
+                sizeof(un->sun_family) + expected_binder_id_.length() + 1);
+      EXPECT_EQ(un->sun_family, AF_MAX);
+      EXPECT_EQ(un->sun_path, expected_binder_id_);
+    }
+
+    void ReturnError(grpc_error_handle error) override {
+      GRPC_ERROR_UNREF(error);
+    }
+
+   private:
+    // Whether we expect ReturnResult function to be invoked
+    bool expect_result_ = false;
+
+    std::string expected_binder_id_;
+  };
+
+  void TestSucceeds(const char* string, const std::string& expected_path) {
+    gpr_log(GPR_DEBUG, "test: '%s' should be valid for '%s'", string,
+            factory_->scheme());
+    grpc_core::ExecCtx exec_ctx;
+    absl::StatusOr<grpc_core::URI> uri = grpc_core::URI::Parse(string);
+    ASSERT_TRUE(uri.ok()) << uri.status().ToString();
+    grpc_core::ResolverArgs args;
+    args.uri = std::move(*uri);
+    args.result_handler =
+        absl::make_unique<BinderResolverTest::ResultHandler>(expected_path);
+    grpc_core::OrphanablePtr<grpc_core::Resolver> resolver =
+        factory_->CreateResolver(std::move(args));
+    ASSERT_TRUE(resolver != nullptr);
+    resolver->StartLocked();
+  }
+
+  void TestFails(const char* string) {
+    gpr_log(GPR_DEBUG, "test: '%s' should be invalid for '%s'", string,
+            factory_->scheme());
+    grpc_core::ExecCtx exec_ctx;
+    absl::StatusOr<grpc_core::URI> uri = grpc_core::URI::Parse(string);
+    ASSERT_TRUE(uri.ok()) << uri.status().ToString();
+    grpc_core::ResolverArgs args;
+    args.uri = std::move(*uri);
+    args.result_handler =
+        absl::make_unique<BinderResolverTest::ResultHandler>();
+    grpc_core::OrphanablePtr<grpc_core::Resolver> resolver =
+        factory_->CreateResolver(std::move(args));
+    EXPECT_TRUE(resolver == nullptr);
+  }
+
+ private:
+  grpc_core::ResolverFactory* factory_;
+};
+
+}  // namespace
+
+// Authority is not allowed
+TEST_F(BinderResolverTest, AuthorityPresents) {
+  TestFails("binder://example");
+  TestFails("binder://google.com");
+  TestFails("binder://google.com/test");
+}
+
+// Path cannot be empty
+TEST_F(BinderResolverTest, EmptyPath) {
+  TestFails("binder:");
+  TestFails("binder:/");
+  TestFails("binder://");
+}
+
+TEST_F(BinderResolverTest, PathLength) {
+  // Note that we have a static assert in binder_resolver.cc that checks
+  // sizeof(sockaddr_un::sun_path) is greater than 100
+
+  // 100 character path should be fine
+  TestSucceeds(("binder:l" + std::string(98, 'o') + "g").c_str(),
+               "l" + std::string(98, 'o') + "g");
+
+  // 200 character path most likely will fail
+  TestFails(("binder:l" + std::string(198, 'o') + "g").c_str());
+}
+
+TEST_F(BinderResolverTest, SlashPrefixes) {
+  TestSucceeds("binder:///test", "test");
+  TestSucceeds("binder:////test", "/test");
+}
+
+TEST_F(BinderResolverTest, ValidCases) {
+  TestSucceeds("binder:[[", "[[");
+  TestSucceeds("binder:google!com", "google!com");
+  TestSucceeds("binder:test/", "test/");
+  TestSucceeds("binder:test:", "test:");
+
+  TestSucceeds("binder:e", "e");
+  TestSucceeds("binder:example", "example");
+  TestSucceeds("binder:google.com", "google.com");
+  TestSucceeds("binder:~", "~");
+  TestSucceeds("binder:12345", "12345");
+  TestSucceeds(
+      "binder:abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._"
+      "~",
+      "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~");
+}
+
+#endif
+
+int main(int argc, char** argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  grpc::testing::TestEnvironment env(argc, argv);
+  return RUN_ALL_TESTS();
+}
diff --git a/test/core/client_channel/rls_lb_config_parser_test.cc b/test/core/client_channel/rls_lb_config_parser_test.cc
new file mode 100644 (file)
index 0000000..2b69bff
--- /dev/null
@@ -0,0 +1,550 @@
+//
+// 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 <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <grpc/grpc.h>
+
+#include "src/core/ext/service_config/service_config.h"
+#include "src/core/lib/gpr/env.h"
+#include "test/core/util/test_config.h"
+
+// A regular expression to enter referenced or child errors.
+#ifdef GRPC_ERROR_IS_ABSEIL_STATUS
+#define CHILD_ERROR_TAG ".*children.*"
+#else
+#define CHILD_ERROR_TAG ".*referenced_errors.*"
+#endif
+
+namespace grpc_core {
+namespace {
+
+class RlsConfigParsingTest : public ::testing::Test {
+ public:
+  static void SetUpTestSuite() {
+    gpr_setenv("GRPC_EXPERIMENTAL_ENABLE_RLS_LB_POLICY", "true");
+    grpc_init();
+  }
+
+  static void TearDownTestSuite() {
+    grpc_shutdown_blocking();
+    gpr_unsetenv("GRPC_EXPERIMENTAL_ENABLE_RLS_LB_POLICY");
+  }
+};
+
+TEST_F(RlsConfigParsingTest, ValidConfig) {
+  const char* service_config_json =
+      "{\n"
+      "  \"loadBalancingConfig\":[{\n"
+      "    \"rls\":{\n"
+      "      \"routeLookupConfig\":{\n"
+      "        \"lookupService\":\"rls.example.com:80\",\n"
+      "        \"cacheSizeBytes\":1,\n"
+      "        \"grpcKeybuilders\":[\n"
+      "          {\n"
+      "            \"names\":[\n"
+      "              {\"service\":\"foo\"}\n"
+      "            ]\n"
+      "          }\n"
+      "        ]\n"
+      "      },\n"
+      "      \"childPolicy\":[\n"
+      "        {\"unknown\":{}},\n"  // Okay, since the next one exists.
+      "        {\"grpclb\":{}}\n"
+      "      ],\n"
+      "      \"childPolicyConfigTargetFieldName\":\"target\"\n"
+      "    }\n"
+      "  }]\n"
+      "}\n";
+  grpc_error_handle error = GRPC_ERROR_NONE;
+  auto service_config = ServiceConfig::Create(
+      /*args=*/nullptr, service_config_json, &error);
+  EXPECT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error);
+  EXPECT_NE(service_config, nullptr);
+}
+
+//
+// top-level fields
+//
+
+TEST_F(RlsConfigParsingTest, TopLevelRequiredFieldsMissing) {
+  const char* service_config_json =
+      "{\n"
+      "  \"loadBalancingConfig\":[{\n"
+      "    \"rls\":{\n"
+      "    }\n"
+      "  }]\n"
+      "}\n";
+  grpc_error_handle error = GRPC_ERROR_NONE;
+  auto service_config = ServiceConfig::Create(
+      /*args=*/nullptr, service_config_json, &error);
+  EXPECT_THAT(
+      grpc_error_std_string(error),
+      ::testing::ContainsRegex(
+          "errors parsing RLS LB policy config" CHILD_ERROR_TAG
+          "field:routeLookupConfig error:does not exist.*"
+          "field:childPolicyConfigTargetFieldName error:does not exist.*"
+          "field:childPolicy error:does not exist"));
+  GRPC_ERROR_UNREF(error);
+}
+
+TEST_F(RlsConfigParsingTest, TopLevelFieldsWrongTypes) {
+  const char* service_config_json =
+      "{\n"
+      "  \"loadBalancingConfig\":[{\n"
+      "    \"rls\":{\n"
+      "      \"routeLookupConfig\":1,\n"
+      "      \"childPolicy\":1,\n"
+      "      \"childPolicyConfigTargetFieldName\":1\n"
+      "    }\n"
+      "  }]\n"
+      "}\n";
+  grpc_error_handle error = GRPC_ERROR_NONE;
+  auto service_config = ServiceConfig::Create(
+      /*args=*/nullptr, service_config_json, &error);
+  EXPECT_THAT(
+      grpc_error_std_string(error),
+      ::testing::ContainsRegex(
+          "errors parsing RLS LB policy config" CHILD_ERROR_TAG
+          "field:routeLookupConfig error:type should be OBJECT.*"
+          "field:childPolicyConfigTargetFieldName error:type should be STRING.*"
+          "field:childPolicy error:type should be ARRAY"));
+  GRPC_ERROR_UNREF(error);
+}
+
+TEST_F(RlsConfigParsingTest, TopLevelFieldsInvalidValues) {
+  const char* service_config_json =
+      "{\n"
+      "  \"loadBalancingConfig\":[{\n"
+      "    \"rls\":{\n"
+      "      \"childPolicy\":[\n"
+      "        {\"unknown\":{}}\n"
+      "      ],\n"
+      "      \"childPolicyConfigTargetFieldName\":\"\"\n"
+      "    }\n"
+      "  }]\n"
+      "}\n";
+  grpc_error_handle error = GRPC_ERROR_NONE;
+  auto service_config = ServiceConfig::Create(
+      /*args=*/nullptr, service_config_json, &error);
+  EXPECT_THAT(
+      grpc_error_std_string(error),
+      ::testing::ContainsRegex(
+          "errors parsing RLS LB policy config" CHILD_ERROR_TAG
+          "field:childPolicyConfigTargetFieldName error:must be non-empty.*"
+          "field:childPolicy" CHILD_ERROR_TAG
+          "No known policies in list: unknown"));
+  GRPC_ERROR_UNREF(error);
+}
+
+TEST_F(RlsConfigParsingTest, InvalidChildPolicyConfig) {
+  const char* service_config_json =
+      "{\n"
+      "  \"loadBalancingConfig\":[{\n"
+      "    \"rls\":{\n"
+      "      \"childPolicy\":[\n"
+      "        {\"grpclb\":{\"childPolicy\":1}}\n"
+      "      ],\n"
+      "      \"childPolicyConfigTargetFieldName\":\"serviceName\"\n"
+      "    }\n"
+      "  }]\n"
+      "}\n";
+  grpc_error_handle error = GRPC_ERROR_NONE;
+  auto service_config = ServiceConfig::Create(
+      /*args=*/nullptr, service_config_json, &error);
+  EXPECT_THAT(
+      grpc_error_std_string(error),
+      ::testing::ContainsRegex(
+          "errors parsing RLS LB policy config" CHILD_ERROR_TAG
+          "field:childPolicy" CHILD_ERROR_TAG "GrpcLb Parser" CHILD_ERROR_TAG
+          "field:childPolicy" CHILD_ERROR_TAG "type should be array"));
+  GRPC_ERROR_UNREF(error);
+}
+
+//
+// routeLookupConfig fields
+//
+
+TEST_F(RlsConfigParsingTest, RouteLookupConfigRequiredFieldsMissing) {
+  const char* service_config_json =
+      "{\n"
+      "  \"loadBalancingConfig\":[{\n"
+      "    \"rls\":{\n"
+      "      \"routeLookupConfig\":{\n"
+      "      }\n"
+      "    }\n"
+      "  }]\n"
+      "}\n";
+  grpc_error_handle error = GRPC_ERROR_NONE;
+  auto service_config = ServiceConfig::Create(
+      /*args=*/nullptr, service_config_json, &error);
+  EXPECT_THAT(grpc_error_std_string(error),
+              ::testing::ContainsRegex(
+                  "errors parsing RLS LB policy config" CHILD_ERROR_TAG
+                  "field:routeLookupConfig" CHILD_ERROR_TAG
+                  "field:grpcKeybuilders error:does not exist.*"
+                  "field:lookupService error:does not exist"));
+  GRPC_ERROR_UNREF(error);
+}
+
+TEST_F(RlsConfigParsingTest, RouteLookupConfigFieldsWrongTypes) {
+  const char* service_config_json =
+      "{\n"
+      "  \"loadBalancingConfig\":[{\n"
+      "    \"rls\":{\n"
+      "      \"routeLookupConfig\":{\n"
+      "        \"grpcKeybuilders\":1,\n"
+      "        \"name\":1,\n"
+      "        \"lookupService\":1,\n"
+      "        \"lookupServiceTimeout\":{},\n"
+      "        \"maxAge\":{},\n"
+      "        \"staleAge\":{},\n"
+      "        \"cacheSizeBytes\":\"xxx\",\n"
+      "        \"defaultTarget\":1\n"
+      "      }\n"
+      "    }\n"
+      "  }]\n"
+      "}\n";
+  grpc_error_handle error = GRPC_ERROR_NONE;
+  auto service_config = ServiceConfig::Create(
+      /*args=*/nullptr, service_config_json, &error);
+  EXPECT_THAT(grpc_error_std_string(error),
+              ::testing::ContainsRegex(
+                  "errors parsing RLS LB policy config" CHILD_ERROR_TAG
+                  "field:routeLookupConfig" CHILD_ERROR_TAG
+                  "field:grpcKeybuilders error:type should be ARRAY.*"
+                  "field:lookupService error:type should be STRING.*"
+                  "field:maxAge error:type should be STRING.*"
+                  "field:staleAge error:type should be STRING.*"
+                  "field:cacheSizeBytes error:type should be NUMBER.*"
+                  "field:defaultTarget error:type should be STRING"));
+  GRPC_ERROR_UNREF(error);
+}
+
+TEST_F(RlsConfigParsingTest, RouteLookupConfigFieldsInvalidValues) {
+  const char* service_config_json =
+      "{\n"
+      "  \"loadBalancingConfig\":[{\n"
+      "    \"rls\":{\n"
+      "      \"routeLookupConfig\":{\n"
+      "        \"lookupService\":\"\",\n"
+      "        \"cacheSizeBytes\":0\n"
+      "      }\n"
+      "    }\n"
+      "  }]\n"
+      "}\n";
+  grpc_error_handle error = GRPC_ERROR_NONE;
+  auto service_config = ServiceConfig::Create(
+      /*args=*/nullptr, service_config_json, &error);
+  EXPECT_THAT(grpc_error_std_string(error),
+              ::testing::ContainsRegex(
+                  "errors parsing RLS LB policy config" CHILD_ERROR_TAG
+                  "field:routeLookupConfig" CHILD_ERROR_TAG
+                  "field:lookupService error:must be valid gRPC target URI.*"
+                  "field:cacheSizeBytes error:must be greater than 0"));
+  GRPC_ERROR_UNREF(error);
+}
+
+//
+// grpcKeybuilder fields
+//
+
+TEST_F(RlsConfigParsingTest, GrpcKeybuilderRequiredFieldsMissing) {
+  const char* service_config_json =
+      "{\n"
+      "  \"loadBalancingConfig\":[{\n"
+      "    \"rls\":{\n"
+      "      \"routeLookupConfig\":{\n"
+      "        \"grpcKeybuilders\":[\n"
+      "          {\n"
+      "          }\n"
+      "        ]\n"
+      "      }\n"
+      "    }\n"
+      "  }]\n"
+      "}\n";
+  grpc_error_handle error = GRPC_ERROR_NONE;
+  auto service_config = ServiceConfig::Create(
+      /*args=*/nullptr, service_config_json, &error);
+  EXPECT_THAT(
+      grpc_error_std_string(error),
+      ::testing::ContainsRegex(
+          "errors parsing RLS LB policy config" CHILD_ERROR_TAG
+          "field:routeLookupConfig" CHILD_ERROR_TAG
+          "field:grpcKeybuilders" CHILD_ERROR_TAG "index:0" CHILD_ERROR_TAG
+          "field:names error:does not exist"));
+  GRPC_ERROR_UNREF(error);
+}
+
+TEST_F(RlsConfigParsingTest, GrpcKeybuilderWrongFieldTypes) {
+  const char* service_config_json =
+      "{\n"
+      "  \"loadBalancingConfig\":[{\n"
+      "    \"rls\":{\n"
+      "      \"routeLookupConfig\":{\n"
+      "        \"grpcKeybuilders\":[\n"
+      "          {\n"
+      "            \"names\":1,\n"
+      "            \"headers\":1,\n"
+      "            \"extraKeys\":1,\n"
+      "            \"constantKeys\":1\n"
+      "          }\n"
+      "        ]\n"
+      "      }\n"
+      "    }\n"
+      "  }]\n"
+      "}\n";
+  grpc_error_handle error = GRPC_ERROR_NONE;
+  auto service_config = ServiceConfig::Create(
+      /*args=*/nullptr, service_config_json, &error);
+  EXPECT_THAT(
+      grpc_error_std_string(error),
+      ::testing::ContainsRegex(
+          "errors parsing RLS LB policy config" CHILD_ERROR_TAG
+          "field:routeLookupConfig" CHILD_ERROR_TAG
+          "field:grpcKeybuilders" CHILD_ERROR_TAG "index:0" CHILD_ERROR_TAG
+          "field:names error:type should be ARRAY.*"
+          "field:headers error:type should be ARRAY.*"
+          "field:extraKeys error:type should be OBJECT.*"
+          "field:constantKeys error:type should be OBJECT"));
+  GRPC_ERROR_UNREF(error);
+}
+
+TEST_F(RlsConfigParsingTest, GrpcKeybuilderInvalidValues) {
+  const char* service_config_json =
+      "{\n"
+      "  \"loadBalancingConfig\":[{\n"
+      "    \"rls\":{\n"
+      "      \"routeLookupConfig\":{\n"
+      "        \"grpcKeybuilders\":[\n"
+      "          {\n"
+      "            \"names\":[],\n"
+      "            \"extraKeys\":{\n"
+      "              \"host\":1,\n"
+      "              \"service\":1,\n"
+      "              \"method\":1\n"
+      "            },\n"
+      "            \"constantKeys\":{\n"
+      "              \"key\":1\n"
+      "            }\n"
+      "          }\n"
+      "        ]\n"
+      "      }\n"
+      "    }\n"
+      "  }]\n"
+      "}\n";
+  grpc_error_handle error = GRPC_ERROR_NONE;
+  auto service_config = ServiceConfig::Create(
+      /*args=*/nullptr, service_config_json, &error);
+  EXPECT_THAT(grpc_error_std_string(error),
+              ::testing::ContainsRegex(
+                  "errors parsing RLS LB policy config" CHILD_ERROR_TAG
+                  "field:routeLookupConfig" CHILD_ERROR_TAG
+                  "field:grpcKeybuilders" CHILD_ERROR_TAG
+                  "index:0" CHILD_ERROR_TAG "field:names error:list is empty.*"
+                  "field:extraKeys" CHILD_ERROR_TAG
+                  "field:host error:type should be STRING.*"
+                  "field:service error:type should be STRING.*"
+                  "field:method error:type should be STRING.*"
+                  "field:constantKeys" CHILD_ERROR_TAG
+                  "field:key error:type should be STRING"));
+  GRPC_ERROR_UNREF(error);
+}
+
+TEST_F(RlsConfigParsingTest, GrpcKeybuilderInvalidHeaders) {
+  const char* service_config_json =
+      "{\n"
+      "  \"loadBalancingConfig\":[{\n"
+      "    \"rls\":{\n"
+      "      \"routeLookupConfig\":{\n"
+      "        \"grpcKeybuilders\":[\n"
+      "          {\n"
+      "            \"headers\":[\n"
+      "              1,\n"
+      "              {\n"
+      "                \"key\":1,\n"
+      "                \"names\":1\n"
+      "              },\n"
+      "              {\n"
+      "                \"names\":[]\n"
+      "              },\n"
+      "              {\n"
+      "                \"key\":\"\",\n"
+      "                \"names\":[1, \"\"]\n"
+      "              }\n"
+      "            ],\n"
+      "            \"extraKeys\":{\n"
+      "              \"host\": \"\"\n"
+      "            },\n"
+      "            \"constantKeys\":{\n"
+      "              \"\":\"foo\"\n"
+      "            }\n"
+      "          }\n"
+      "        ]\n"
+      "      }\n"
+      "    }\n"
+      "  }]\n"
+      "}\n";
+  grpc_error_handle error = GRPC_ERROR_NONE;
+  auto service_config = ServiceConfig::Create(
+      /*args=*/nullptr, service_config_json, &error);
+  EXPECT_THAT(
+      grpc_error_std_string(error),
+      ::testing::ContainsRegex(
+          "errors parsing RLS LB policy config" CHILD_ERROR_TAG
+          "field:routeLookupConfig" CHILD_ERROR_TAG
+          "field:grpcKeybuilders" CHILD_ERROR_TAG "index:0" CHILD_ERROR_TAG
+          "field:headers index:0 error:type should be OBJECT.*"
+          "field:headers index:1" CHILD_ERROR_TAG
+          "field:key error:type should be STRING.*"
+          "field:names error:type should be ARRAY.*"
+          "field:headers index:2" CHILD_ERROR_TAG
+          "field:key error:does not exist.*"
+          "field:names error:list is empty.*"
+          "field:headers index:3" CHILD_ERROR_TAG
+          "field:key error:must be non-empty.*"
+          "field:names index:0 error:type should be STRING.*"
+          "field:names index:1 error:header name must be non-empty.*"
+          "field:extraKeys" CHILD_ERROR_TAG
+          "field:host error:must be non-empty.*"
+          "field:constantKeys" CHILD_ERROR_TAG "error:keys must be non-empty"));
+  GRPC_ERROR_UNREF(error);
+}
+
+TEST_F(RlsConfigParsingTest, GrpcKeybuilderNameWrongFieldTypes) {
+  const char* service_config_json =
+      "{\n"
+      "  \"loadBalancingConfig\":[{\n"
+      "    \"rls\":{\n"
+      "      \"routeLookupConfig\":{\n"
+      "        \"grpcKeybuilders\":[\n"
+      "          {\n"
+      "            \"names\":[\n"
+      "              1,\n"
+      "              {\n"
+      "                \"service\":1,\n"
+      "                \"method\":1\n"
+      "              }\n"
+      "            ]\n"
+      "          }\n"
+      "        ]\n"
+      "      }\n"
+      "    }\n"
+      "  }]\n"
+      "}\n";
+  grpc_error_handle error = GRPC_ERROR_NONE;
+  auto service_config = ServiceConfig::Create(
+      /*args=*/nullptr, service_config_json, &error);
+  EXPECT_THAT(
+      grpc_error_std_string(error),
+      ::testing::ContainsRegex(
+          "errors parsing RLS LB policy config" CHILD_ERROR_TAG
+          "field:routeLookupConfig" CHILD_ERROR_TAG
+          "field:grpcKeybuilders" CHILD_ERROR_TAG "index:0" CHILD_ERROR_TAG
+          "field:names index:0 error:type should be OBJECT.*"
+          "field:names index:1" CHILD_ERROR_TAG
+          "field:service error:type should be STRING.*"
+          "field:method error:type should be STRING"));
+  GRPC_ERROR_UNREF(error);
+}
+
+TEST_F(RlsConfigParsingTest, DuplicateMethodNamesInSameKeyBuilder) {
+  const char* service_config_json =
+      "{\n"
+      "  \"loadBalancingConfig\":[{\n"
+      "    \"rls\":{\n"
+      "      \"routeLookupConfig\":{\n"
+      "        \"grpcKeybuilders\":[\n"
+      "          {\n"
+      "            \"names\":[\n"
+      "              {\n"
+      "                \"service\":\"foo\",\n"
+      "                \"method\":\"bar\"\n"
+      "              },\n"
+      "              {\n"
+      "                \"service\":\"foo\",\n"
+      "                \"method\":\"bar\"\n"
+      "              }\n"
+      "            ]\n"
+      "          }\n"
+      "        ]\n"
+      "      }\n"
+      "    }\n"
+      "  }]\n"
+      "}\n";
+  grpc_error_handle error = GRPC_ERROR_NONE;
+  auto service_config = ServiceConfig::Create(
+      /*args=*/nullptr, service_config_json, &error);
+  EXPECT_THAT(
+      grpc_error_std_string(error),
+      ::testing::ContainsRegex(
+          "errors parsing RLS LB policy config" CHILD_ERROR_TAG
+          "field:routeLookupConfig" CHILD_ERROR_TAG
+          "field:grpcKeybuilders" CHILD_ERROR_TAG "index:0" CHILD_ERROR_TAG
+          "field:names error:duplicate entry for /foo/bar"));
+  GRPC_ERROR_UNREF(error);
+}
+
+TEST_F(RlsConfigParsingTest, DuplicateMethodNamesInDifferentKeyBuilders) {
+  const char* service_config_json =
+      "{\n"
+      "  \"loadBalancingConfig\":[{\n"
+      "    \"rls\":{\n"
+      "      \"routeLookupConfig\":{\n"
+      "        \"grpcKeybuilders\":[\n"
+      "          {\n"
+      "            \"names\":[\n"
+      "              {\n"
+      "                \"service\":\"foo\",\n"
+      "                \"method\":\"bar\"\n"
+      "              }\n"
+      "            ]\n"
+      "          },\n"
+      "          {\n"
+      "            \"names\":[\n"
+      "              {\n"
+      "                \"service\":\"foo\",\n"
+      "                \"method\":\"bar\"\n"
+      "              }\n"
+      "            ]\n"
+      "          }\n"
+      "        ]\n"
+      "      }\n"
+      "    }\n"
+      "  }]\n"
+      "}\n";
+  grpc_error_handle error = GRPC_ERROR_NONE;
+  auto service_config = ServiceConfig::Create(
+      /*args=*/nullptr, service_config_json, &error);
+  EXPECT_THAT(
+      grpc_error_std_string(error),
+      ::testing::ContainsRegex(
+          "errors parsing RLS LB policy config" CHILD_ERROR_TAG
+          "field:routeLookupConfig" CHILD_ERROR_TAG
+          "field:grpcKeybuilders" CHILD_ERROR_TAG "index:1" CHILD_ERROR_TAG
+          "field:names error:duplicate entry for /foo/bar"));
+  GRPC_ERROR_UNREF(error);
+}
+
+}  // namespace
+}  // namespace grpc_core
+
+int main(int argc, char** argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  grpc::testing::TestEnvironment env(argc, argv);
+  return RUN_ALL_TESTS();
+}
index d281ccf..b555fc4 100644 (file)
@@ -16,7 +16,7 @@
  *
  */
 
-#include "src/core/ext/filters/client_channel/service_config.h"
+#include "src/core/ext/service_config/service_config.h"
 
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
@@ -27,8 +27,8 @@
 
 #include "src/core/ext/filters/client_channel/resolver_result_parsing.h"
 #include "src/core/ext/filters/client_channel/retry_service_config.h"
-#include "src/core/ext/filters/client_channel/service_config_parser.h"
 #include "src/core/ext/filters/message_size/message_size_filter.h"
+#include "src/core/ext/service_config/service_config_parser.h"
 #include "src/core/lib/gpr/string.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
@@ -43,6 +43,13 @@ namespace testing {
 // Set this channel arg to true to disable parsing.
 #define GRPC_ARG_DISABLE_PARSING "disable_parsing"
 
+// A regular expression to enter referenced or child errors.
+#ifdef GRPC_ERROR_IS_ABSEIL_STATUS
+#define CHILD_ERROR_TAG ".*children.*"
+#else
+#define CHILD_ERROR_TAG ".*referenced_errors.*"
+#endif
+
 class TestParsedConfig1 : public ServiceConfigParser::ParsedConfig {
  public:
   explicit TestParsedConfig1(int value) : value_(value) {}
@@ -152,8 +159,8 @@ class ErrorParser : public ServiceConfigParser::Parser {
 class ServiceConfigTest : public ::testing::Test {
  protected:
   void SetUp() override {
-    ServiceConfigParser::Shutdown();
-    ServiceConfigParser::Init();
+    ServiceConfigParserShutdown();
+    ServiceConfigParserInit();
     EXPECT_EQ(
         ServiceConfigParser::RegisterParser(absl::make_unique<TestParser1>()),
         0);
@@ -204,12 +211,11 @@ TEST_F(ServiceConfigTest, ErrorDuplicateMethodConfigNames) {
       "]}";
   grpc_error_handle error = GRPC_ERROR_NONE;
   auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error);
-  EXPECT_THAT(
-      grpc_error_std_string(error),
-      ::testing::ContainsRegex("Service config parsing error.*referenced_errors"
-                               ".*Method Params.*referenced_errors"
-                               ".*methodConfig.*referenced_errors"
-                               ".*multiple method configs with same name"));
+  EXPECT_THAT(grpc_error_std_string(error),
+              ::testing::ContainsRegex(
+                  "Service config parsing error" CHILD_ERROR_TAG
+                  "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
+                  "multiple method configs with same name"));
   GRPC_ERROR_UNREF(error);
 }
 
@@ -221,12 +227,11 @@ TEST_F(ServiceConfigTest, ErrorDuplicateMethodConfigNamesWithNullMethod) {
       "]}";
   grpc_error_handle error = GRPC_ERROR_NONE;
   auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error);
-  EXPECT_THAT(
-      grpc_error_std_string(error),
-      ::testing::ContainsRegex("Service config parsing error.*referenced_errors"
-                               ".*Method Params.*referenced_errors"
-                               ".*methodConfig.*referenced_errors"
-                               ".*multiple method configs with same name"));
+  EXPECT_THAT(grpc_error_std_string(error),
+              ::testing::ContainsRegex(
+                  "Service config parsing error" CHILD_ERROR_TAG
+                  "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
+                  "multiple method configs with same name"));
   GRPC_ERROR_UNREF(error);
 }
 
@@ -238,12 +243,11 @@ TEST_F(ServiceConfigTest, ErrorDuplicateMethodConfigNamesWithEmptyMethod) {
       "]}";
   grpc_error_handle error = GRPC_ERROR_NONE;
   auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error);
-  EXPECT_THAT(
-      grpc_error_std_string(error),
-      ::testing::ContainsRegex("Service config parsing error.*referenced_errors"
-                               ".*Method Params.*referenced_errors"
-                               ".*methodConfig.*referenced_errors"
-                               ".*multiple method configs with same name"));
+  EXPECT_THAT(grpc_error_std_string(error),
+              ::testing::ContainsRegex(
+                  "Service config parsing error" CHILD_ERROR_TAG
+                  "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
+                  "multiple method configs with same name"));
   GRPC_ERROR_UNREF(error);
 }
 
@@ -255,12 +259,11 @@ TEST_F(ServiceConfigTest, ErrorDuplicateDefaultMethodConfigs) {
       "]}";
   grpc_error_handle error = GRPC_ERROR_NONE;
   auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error);
-  EXPECT_THAT(
-      grpc_error_std_string(error),
-      ::testing::ContainsRegex("Service config parsing error.*referenced_errors"
-                               ".*Method Params.*referenced_errors"
-                               ".*methodConfig.*referenced_errors"
-                               ".*multiple default method configs"));
+  EXPECT_THAT(grpc_error_std_string(error),
+              ::testing::ContainsRegex(
+                  "Service config parsing error" CHILD_ERROR_TAG
+                  "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
+                  "multiple default method configs"));
   GRPC_ERROR_UNREF(error);
 }
 
@@ -272,12 +275,11 @@ TEST_F(ServiceConfigTest, ErrorDuplicateDefaultMethodConfigsWithNullService) {
       "]}";
   grpc_error_handle error = GRPC_ERROR_NONE;
   auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error);
-  EXPECT_THAT(
-      grpc_error_std_string(error),
-      ::testing::ContainsRegex("Service config parsing error.*referenced_errors"
-                               ".*Method Params.*referenced_errors"
-                               ".*methodConfig.*referenced_errors"
-                               ".*multiple default method configs"));
+  EXPECT_THAT(grpc_error_std_string(error),
+              ::testing::ContainsRegex(
+                  "Service config parsing error" CHILD_ERROR_TAG
+                  "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
+                  "multiple default method configs"));
   GRPC_ERROR_UNREF(error);
 }
 
@@ -289,12 +291,11 @@ TEST_F(ServiceConfigTest, ErrorDuplicateDefaultMethodConfigsWithEmptyService) {
       "]}";
   grpc_error_handle error = GRPC_ERROR_NONE;
   auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error);
-  EXPECT_THAT(
-      grpc_error_std_string(error),
-      ::testing::ContainsRegex("Service config parsing error.*referenced_errors"
-                               ".*Method Params.*referenced_errors"
-                               ".*methodConfig.*referenced_errors"
-                               ".*multiple default method configs"));
+  EXPECT_THAT(grpc_error_std_string(error),
+              ::testing::ContainsRegex(
+                  "Service config parsing error" CHILD_ERROR_TAG
+                  "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
+                  "multiple default method configs"));
   GRPC_ERROR_UNREF(error);
 }
 
@@ -345,10 +346,10 @@ TEST_F(ServiceConfigTest, Parser1ErrorInvalidType) {
   grpc_error_handle error = GRPC_ERROR_NONE;
   auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error);
   EXPECT_THAT(grpc_error_std_string(error),
-              ::testing::ContainsRegex(absl::StrCat(
-                  "Service config parsing error.*referenced_errors.*"
-                  "Global Params.*referenced_errors.*",
-                  TestParser1::InvalidTypeErrorMessage())));
+              ::testing::ContainsRegex(
+                  absl::StrCat("Service config parsing error" CHILD_ERROR_TAG
+                               "Global Params" CHILD_ERROR_TAG,
+                               TestParser1::InvalidTypeErrorMessage())));
   GRPC_ERROR_UNREF(error);
 }
 
@@ -357,10 +358,10 @@ TEST_F(ServiceConfigTest, Parser1ErrorInvalidValue) {
   grpc_error_handle error = GRPC_ERROR_NONE;
   auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error);
   EXPECT_THAT(grpc_error_std_string(error),
-              ::testing::ContainsRegex(absl::StrCat(
-                  "Service config parsing error.*referenced_errors.*"
-                  "Global Params.*referenced_errors.*",
-                  TestParser1::InvalidValueErrorMessage())));
+              ::testing::ContainsRegex(
+                  absl::StrCat("Service config parsing error" CHILD_ERROR_TAG
+                               "Global Params" CHILD_ERROR_TAG,
+                               TestParser1::InvalidValueErrorMessage())));
   GRPC_ERROR_UNREF(error);
 }
 
@@ -401,12 +402,12 @@ TEST_F(ServiceConfigTest, Parser2ErrorInvalidType) {
       "\"method_param\":\"5\"}]}";
   grpc_error_handle error = GRPC_ERROR_NONE;
   auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error);
-  EXPECT_THAT(grpc_error_std_string(error),
-              ::testing::ContainsRegex(absl::StrCat(
-                  "Service config parsing error.*referenced_errors\":\\[.*"
-                  "Method Params.*referenced_errors.*methodConfig.*"
-                  "referenced_errors.*",
-                  TestParser2::InvalidTypeErrorMessage())));
+  EXPECT_THAT(
+      grpc_error_std_string(error),
+      ::testing::ContainsRegex(absl::StrCat(
+          "Service config parsing error" CHILD_ERROR_TAG
+          "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG,
+          TestParser2::InvalidTypeErrorMessage())));
   GRPC_ERROR_UNREF(error);
 }
 
@@ -416,12 +417,12 @@ TEST_F(ServiceConfigTest, Parser2ErrorInvalidValue) {
       "\"method_param\":-5}]}";
   grpc_error_handle error = GRPC_ERROR_NONE;
   auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error);
-  EXPECT_THAT(grpc_error_std_string(error),
-              ::testing::ContainsRegex(absl::StrCat(
-                  "Service config parsing error.*referenced_errors\":\\[.*"
-                  "Method Params.*referenced_errors.*methodConfig.*"
-                  "referenced_errors.*",
-                  TestParser2::InvalidValueErrorMessage())));
+  EXPECT_THAT(
+      grpc_error_std_string(error),
+      ::testing::ContainsRegex(absl::StrCat(
+          "Service config parsing error" CHILD_ERROR_TAG
+          "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG,
+          TestParser2::InvalidValueErrorMessage())));
   GRPC_ERROR_UNREF(error);
 }
 
@@ -429,8 +430,8 @@ TEST_F(ServiceConfigTest, Parser2ErrorInvalidValue) {
 class ErroredParsersScopingTest : public ::testing::Test {
  protected:
   void SetUp() override {
-    ServiceConfigParser::Shutdown();
-    ServiceConfigParser::Init();
+    ServiceConfigParserShutdown();
+    ServiceConfigParserInit();
     EXPECT_EQ(
         ServiceConfigParser::RegisterParser(absl::make_unique<ErrorParser>()),
         0);
@@ -447,8 +448,8 @@ TEST_F(ErroredParsersScopingTest, GlobalParams) {
   EXPECT_THAT(
       grpc_error_std_string(error),
       ::testing::ContainsRegex(absl::StrCat(
-          "Service config parsing error.*referenced_errors\":\\[.*"
-          "Global Params.*referenced_errors.*",
+          "Service config parsing error" CHILD_ERROR_TAG
+          "Global Params" CHILD_ERROR_TAG,
           ErrorParser::GlobalError(), ".*", ErrorParser::GlobalError())));
   GRPC_ERROR_UNREF(error);
 }
@@ -460,11 +461,10 @@ TEST_F(ErroredParsersScopingTest, MethodParams) {
   EXPECT_THAT(
       grpc_error_std_string(error),
       ::testing::ContainsRegex(absl::StrCat(
-          "Service config parsing error.*referenced_errors\":\\[.*"
-          "Global Params.*referenced_errors.*",
+          "Service config parsing error" CHILD_ERROR_TAG
+          "Global Params" CHILD_ERROR_TAG,
           ErrorParser::GlobalError(), ".*", ErrorParser::GlobalError(),
-          ".*Method Params.*referenced_errors.*methodConfig.*"
-          "referenced_errors.*",
+          ".*Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG,
           ErrorParser::MethodError(), ".*", ErrorParser::MethodError())));
   GRPC_ERROR_UNREF(error);
 }
@@ -476,8 +476,8 @@ TEST_F(ErroredParsersScopingTest, MethodParams) {
 class ClientChannelParserTest : public ::testing::Test {
  protected:
   void SetUp() override {
-    ServiceConfigParser::Shutdown();
-    ServiceConfigParser::Init();
+    ServiceConfigParserShutdown();
+    ServiceConfigParserInit();
     EXPECT_EQ(
         ServiceConfigParser::RegisterParser(
             absl::make_unique<internal::ClientChannelServiceConfigParser>()),
@@ -551,13 +551,13 @@ TEST_F(ClientChannelParserTest, UnknownLoadBalancingConfig) {
   const char* test_json = "{\"loadBalancingConfig\": [{\"unknown\":{}}]}";
   grpc_error_handle error = GRPC_ERROR_NONE;
   auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error);
-  EXPECT_THAT(grpc_error_std_string(error),
-              ::testing::ContainsRegex(
-                  "Service config parsing error.*referenced_errors.*"
-                  "Global Params.*referenced_errors.*"
-                  "Client channel global parser.*referenced_errors.*"
-                  "field:loadBalancingConfig.*referenced_errors.*"
-                  "No known policies in list: unknown"));
+  EXPECT_THAT(
+      grpc_error_std_string(error),
+      ::testing::ContainsRegex("Service config parsing error" CHILD_ERROR_TAG
+                               "Global Params" CHILD_ERROR_TAG
+                               "Client channel global parser" CHILD_ERROR_TAG
+                               "field:loadBalancingConfig" CHILD_ERROR_TAG
+                               "No known policies in list: unknown"));
   GRPC_ERROR_UNREF(error);
 }
 
@@ -571,13 +571,12 @@ TEST_F(ClientChannelParserTest, InvalidGrpclbLoadBalancingConfig) {
   auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error);
   EXPECT_THAT(grpc_error_std_string(error),
               ::testing::ContainsRegex(
-                  "Service config parsing error.*referenced_errors.*"
-                  "Global Params.*referenced_errors.*"
-                  "Client channel global parser.*referenced_errors.*"
-                  "field:loadBalancingConfig.*referenced_errors.*"
-                  "GrpcLb Parser.*referenced_errors.*"
-                  "field:childPolicy.*referenced_errors.*"
-                  "type should be array"));
+                  "Service config parsing error" CHILD_ERROR_TAG
+                  "Global Params" CHILD_ERROR_TAG
+                  "Client channel global parser" CHILD_ERROR_TAG
+                  "field:loadBalancingConfig" CHILD_ERROR_TAG
+                  "GrpcLb Parser" CHILD_ERROR_TAG
+                  "field:childPolicy" CHILD_ERROR_TAG "type should be array"));
   GRPC_ERROR_UNREF(error);
 }
 
@@ -609,9 +608,9 @@ TEST_F(ClientChannelParserTest, UnknownLoadBalancingPolicy) {
   auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error);
   EXPECT_THAT(grpc_error_std_string(error),
               ::testing::ContainsRegex(
-                  "Service config parsing error.*referenced_errors.*"
-                  "Global Params.*referenced_errors.*"
-                  "Client channel global parser.*referenced_errors.*"
+                  "Service config parsing error" CHILD_ERROR_TAG
+                  "Global Params" CHILD_ERROR_TAG
+                  "Client channel global parser" CHILD_ERROR_TAG
                   "field:loadBalancingPolicy error:Unknown lb policy"));
   GRPC_ERROR_UNREF(error);
 }
@@ -623,9 +622,9 @@ TEST_F(ClientChannelParserTest, LoadBalancingPolicyXdsNotAllowed) {
   auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error);
   EXPECT_THAT(grpc_error_std_string(error),
               ::testing::ContainsRegex(
-                  "Service config parsing error.*referenced_errors.*"
-                  "Global Params.*referenced_errors.*"
-                  "Client channel global parser.*referenced_errors.*"
+                  "Service config parsing error" CHILD_ERROR_TAG
+                  "Global Params" CHILD_ERROR_TAG
+                  "Client channel global parser" CHILD_ERROR_TAG
                   "field:loadBalancingPolicy "
                   "error:xds_cluster_resolver_experimental requires "
                   "a config. Please use loadBalancingConfig instead."));
@@ -669,10 +668,9 @@ TEST_F(ClientChannelParserTest, InvalidTimeout) {
   auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error);
   EXPECT_THAT(grpc_error_std_string(error),
               ::testing::ContainsRegex(
-                  "Service config parsing error.*referenced_errors.*"
-                  "Method Params.*referenced_errors.*"
-                  "methodConfig.*referenced_errors.*"
-                  "Client channel parser.*referenced_errors.*"
+                  "Service config parsing error" CHILD_ERROR_TAG
+                  "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
+                  "Client channel parser" CHILD_ERROR_TAG
                   "field:timeout error:type should be STRING of the form given "
                   "by google.proto.Duration"));
   GRPC_ERROR_UNREF(error);
@@ -721,10 +719,9 @@ TEST_F(ClientChannelParserTest, InvalidWaitForReady) {
   auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error);
   EXPECT_THAT(grpc_error_std_string(error),
               ::testing::ContainsRegex(
-                  "Service config parsing error.*referenced_errors.*"
-                  "Method Params.*referenced_errors.*"
-                  "methodConfig.*referenced_errors.*"
-                  "Client channel parser.*referenced_errors.*"
+                  "Service config parsing error" CHILD_ERROR_TAG
+                  "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
+                  "Client channel parser" CHILD_ERROR_TAG
                   "field:waitForReady error:Type should be true/false"));
   GRPC_ERROR_UNREF(error);
 }
@@ -761,7 +758,7 @@ TEST_F(ClientChannelParserTest, InvalidHealthCheckMultipleEntries) {
   auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error);
   EXPECT_THAT(grpc_error_std_string(error),
               ::testing::ContainsRegex(
-                  "JSON parsing failed.*referenced_errors.*"
+                  "JSON parsing failed" CHILD_ERROR_TAG
                   "duplicate key \"healthCheckConfig\" at index 104"));
   GRPC_ERROR_UNREF(error);
 }
@@ -773,8 +770,8 @@ TEST_F(ClientChannelParserTest, InvalidHealthCheckMultipleEntries) {
 class RetryParserTest : public ::testing::Test {
  protected:
   void SetUp() override {
-    ServiceConfigParser::Shutdown();
-    ServiceConfigParser::Init();
+    ServiceConfigParserShutdown();
+    ServiceConfigParserInit();
     EXPECT_EQ(ServiceConfigParser::RegisterParser(
                   absl::make_unique<internal::RetryServiceConfigParser>()),
               0);
@@ -808,13 +805,13 @@ TEST_F(RetryParserTest, RetryThrottlingMissingFields) {
       "}";
   grpc_error_handle error = GRPC_ERROR_NONE;
   auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error);
-  EXPECT_THAT(grpc_error_std_string(error),
-              ::testing::ContainsRegex(
-                  "Service config parsing error.*referenced_errors.*"
-                  "Global Params.*referenced_errors.*"
-                  "retryThrottling.*referenced_errors.*"
-                  "field:retryThrottling field:maxTokens error:Not found.*"
-                  "field:retryThrottling field:tokenRatio error:Not found"));
+  EXPECT_THAT(
+      grpc_error_std_string(error),
+      ::testing::ContainsRegex(
+          "Service config parsing error" CHILD_ERROR_TAG
+          "Global Params" CHILD_ERROR_TAG "retryThrottling" CHILD_ERROR_TAG
+          "field:retryThrottling field:maxTokens error:Not found"
+          ".*field:retryThrottling field:tokenRatio error:Not found"));
   GRPC_ERROR_UNREF(error);
 }
 
@@ -828,13 +825,13 @@ TEST_F(RetryParserTest, InvalidRetryThrottlingNegativeMaxTokens) {
       "}";
   grpc_error_handle error = GRPC_ERROR_NONE;
   auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error);
-  EXPECT_THAT(grpc_error_std_string(error),
-              ::testing::ContainsRegex(
-                  "Service config parsing error.*referenced_errors.*"
-                  "Global Params.*referenced_errors.*"
-                  "retryThrottling.*referenced_errors.*"
-                  "field:retryThrottling field:maxTokens error:should "
-                  "be greater than zero"));
+  EXPECT_THAT(
+      grpc_error_std_string(error),
+      ::testing::ContainsRegex(
+          "Service config parsing error" CHILD_ERROR_TAG
+          "Global Params" CHILD_ERROR_TAG "retryThrottling" CHILD_ERROR_TAG
+          "field:retryThrottling field:maxTokens error:should "
+          "be greater than zero"));
   GRPC_ERROR_UNREF(error);
 }
 
@@ -848,13 +845,13 @@ TEST_F(RetryParserTest, InvalidRetryThrottlingInvalidTokenRatio) {
       "}";
   grpc_error_handle error = GRPC_ERROR_NONE;
   auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error);
-  EXPECT_THAT(grpc_error_std_string(error),
-              ::testing::ContainsRegex(
-                  "Service config parsing error.*referenced_errors.*"
-                  "Global Params.*referenced_errors.*"
-                  "retryThrottling.*referenced_errors.*"
-                  "field:retryThrottling field:tokenRatio "
-                  "error:Failed parsing"));
+  EXPECT_THAT(
+      grpc_error_std_string(error),
+      ::testing::ContainsRegex("Service config parsing error" CHILD_ERROR_TAG
+                               "Global Params" CHILD_ERROR_TAG
+                               "retryThrottling" CHILD_ERROR_TAG
+                               "field:retryThrottling field:tokenRatio "
+                               "error:Failed parsing"));
   GRPC_ERROR_UNREF(error);
 }
 
@@ -907,9 +904,8 @@ TEST_F(RetryParserTest, InvalidRetryPolicyWrongType) {
   auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error);
   EXPECT_THAT(grpc_error_std_string(error),
               ::testing::ContainsRegex(
-                  "Service config parsing error.*referenced_errors.*"
-                  "Method Params.*referenced_errors.*"
-                  "methodConfig.*referenced_errors.*"
+                  "Service config parsing error" CHILD_ERROR_TAG
+                  "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
                   "field:retryPolicy error:should be of type object"));
   GRPC_ERROR_UNREF(error);
 }
@@ -930,14 +926,13 @@ TEST_F(RetryParserTest, InvalidRetryPolicyRequiredFieldsMissing) {
   auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error);
   EXPECT_THAT(grpc_error_std_string(error),
               ::testing::ContainsRegex(
-                  "Service config parsing error.*referenced_errors.*"
-                  "Method Params.*referenced_errors.*"
-                  "methodConfig.*referenced_errors.*"
-                  "retryPolicy.*referenced_errors.*"
-                  "field:maxAttempts error:required field missing.*"
-                  "field:initialBackoff error:does not exist.*"
-                  "field:maxBackoff error:does not exist.*"
-                  "field:backoffMultiplier error:required field missing"));
+                  "Service config parsing error" CHILD_ERROR_TAG
+                  "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
+                  "retryPolicy" CHILD_ERROR_TAG
+                  ".*field:maxAttempts error:required field missing"
+                  ".*field:initialBackoff error:does not exist"
+                  ".*field:maxBackoff error:does not exist"
+                  ".*field:backoffMultiplier error:required field missing"));
   GRPC_ERROR_UNREF(error);
 }
 
@@ -961,10 +956,9 @@ TEST_F(RetryParserTest, InvalidRetryPolicyMaxAttemptsWrongType) {
   auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error);
   EXPECT_THAT(grpc_error_std_string(error),
               ::testing::ContainsRegex(
-                  "Service config parsing error.*referenced_errors.*"
-                  "Method Params.*referenced_errors.*"
-                  "methodConfig.*referenced_errors.*"
-                  "retryPolicy.*referenced_errors.*"
+                  "Service config parsing error" CHILD_ERROR_TAG
+                  "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
+                  "retryPolicy" CHILD_ERROR_TAG
                   "field:maxAttempts error:should be of type number"));
   GRPC_ERROR_UNREF(error);
 }
@@ -989,10 +983,9 @@ TEST_F(RetryParserTest, InvalidRetryPolicyMaxAttemptsBadValue) {
   auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error);
   EXPECT_THAT(grpc_error_std_string(error),
               ::testing::ContainsRegex(
-                  "Service config parsing error.*referenced_errors.*"
-                  "Method Params.*referenced_errors.*"
-                  "methodConfig.*referenced_errors.*"
-                  "retryPolicy.*referenced_errors.*"
+                  "Service config parsing error" CHILD_ERROR_TAG
+                  "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
+                  "retryPolicy" CHILD_ERROR_TAG
                   "field:maxAttempts error:should be at least 2"));
   GRPC_ERROR_UNREF(error);
 }
@@ -1017,10 +1010,9 @@ TEST_F(RetryParserTest, InvalidRetryPolicyInitialBackoffWrongType) {
   auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error);
   EXPECT_THAT(grpc_error_std_string(error),
               ::testing::ContainsRegex(
-                  "Service config parsing error.*referenced_errors.*"
-                  "Method Params.*referenced_errors.*"
-                  "methodConfig.*referenced_errors.*"
-                  "retryPolicy.*referenced_errors.*"
+                  "Service config parsing error" CHILD_ERROR_TAG
+                  "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
+                  "retryPolicy" CHILD_ERROR_TAG
                   "field:initialBackoff error:type should be STRING of the "
                   "form given by google.proto.Duration"));
   GRPC_ERROR_UNREF(error);
@@ -1046,10 +1038,9 @@ TEST_F(RetryParserTest, InvalidRetryPolicyInitialBackoffBadValue) {
   auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error);
   EXPECT_THAT(grpc_error_std_string(error),
               ::testing::ContainsRegex(
-                  "Service config parsing error.*referenced_errors.*"
-                  "Method Params.*referenced_errors.*"
-                  "methodConfig.*referenced_errors.*"
-                  "retryPolicy.*referenced_errors.*"
+                  "Service config parsing error" CHILD_ERROR_TAG
+                  "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
+                  "retryPolicy" CHILD_ERROR_TAG
                   "field:initialBackoff error:must be greater than 0"));
   GRPC_ERROR_UNREF(error);
 }
@@ -1074,10 +1065,9 @@ TEST_F(RetryParserTest, InvalidRetryPolicyMaxBackoffWrongType) {
   auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error);
   EXPECT_THAT(grpc_error_std_string(error),
               ::testing::ContainsRegex(
-                  "Service config parsing error.*referenced_errors.*"
-                  "Method Params.*referenced_errors.*"
-                  "methodConfig.*referenced_errors.*"
-                  "retryPolicy.*referenced_errors.*"
+                  "Service config parsing error" CHILD_ERROR_TAG
+                  "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
+                  "retryPolicy" CHILD_ERROR_TAG
                   "field:maxBackoff error:type should be STRING of the form "
                   "given by google.proto.Duration"));
   GRPC_ERROR_UNREF(error);
@@ -1103,10 +1093,9 @@ TEST_F(RetryParserTest, InvalidRetryPolicyMaxBackoffBadValue) {
   auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error);
   EXPECT_THAT(grpc_error_std_string(error),
               ::testing::ContainsRegex(
-                  "Service config parsing error.*referenced_errors.*"
-                  "Method Params.*referenced_errors.*"
-                  "methodConfig.*referenced_errors.*"
-                  "retryPolicy.*referenced_errors.*"
+                  "Service config parsing error" CHILD_ERROR_TAG
+                  "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
+                  "retryPolicy" CHILD_ERROR_TAG
                   "field:maxBackoff error:must be greater than 0"));
   GRPC_ERROR_UNREF(error);
 }
@@ -1131,10 +1120,9 @@ TEST_F(RetryParserTest, InvalidRetryPolicyBackoffMultiplierWrongType) {
   auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error);
   EXPECT_THAT(grpc_error_std_string(error),
               ::testing::ContainsRegex(
-                  "Service config parsing error.*referenced_errors.*"
-                  "Method Params.*referenced_errors.*"
-                  "methodConfig.*referenced_errors.*"
-                  "retryPolicy.*referenced_errors.*"
+                  "Service config parsing error" CHILD_ERROR_TAG
+                  "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
+                  "retryPolicy" CHILD_ERROR_TAG
                   "field:backoffMultiplier error:should be of type number"));
   GRPC_ERROR_UNREF(error);
 }
@@ -1159,10 +1147,9 @@ TEST_F(RetryParserTest, InvalidRetryPolicyBackoffMultiplierBadValue) {
   auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error);
   EXPECT_THAT(grpc_error_std_string(error),
               ::testing::ContainsRegex(
-                  "Service config parsing error.*referenced_errors.*"
-                  "Method Params.*referenced_errors.*"
-                  "methodConfig.*referenced_errors.*"
-                  "retryPolicy.*referenced_errors.*"
+                  "Service config parsing error" CHILD_ERROR_TAG
+                  "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
+                  "retryPolicy" CHILD_ERROR_TAG
                   "field:backoffMultiplier error:must be greater than 0"));
   GRPC_ERROR_UNREF(error);
 }
@@ -1187,10 +1174,9 @@ TEST_F(RetryParserTest, InvalidRetryPolicyEmptyRetryableStatusCodes) {
   auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error);
   EXPECT_THAT(grpc_error_std_string(error),
               ::testing::ContainsRegex(
-                  "Service config parsing error.*referenced_errors.*"
-                  "Method Params.*referenced_errors.*"
-                  "methodConfig.*referenced_errors.*"
-                  "retryPolicy.*referenced_errors.*"
+                  "Service config parsing error" CHILD_ERROR_TAG
+                  "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
+                  "retryPolicy" CHILD_ERROR_TAG
                   "field:retryableStatusCodes error:must be non-empty"));
   GRPC_ERROR_UNREF(error);
 }
@@ -1215,10 +1201,9 @@ TEST_F(RetryParserTest, InvalidRetryPolicyRetryableStatusCodesWrongType) {
   auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error);
   EXPECT_THAT(grpc_error_std_string(error),
               ::testing::ContainsRegex(
-                  "Service config parsing error.*referenced_errors.*"
-                  "Method Params.*referenced_errors.*"
-                  "methodConfig.*referenced_errors.*"
-                  "retryPolicy.*referenced_errors.*"
+                  "Service config parsing error" CHILD_ERROR_TAG
+                  "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
+                  "retryPolicy" CHILD_ERROR_TAG
                   "field:retryableStatusCodes error:must be of type array"));
   GRPC_ERROR_UNREF(error);
 }
@@ -1243,13 +1228,11 @@ TEST_F(RetryParserTest, InvalidRetryPolicyUnparseableRetryableStatusCodes) {
   auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error);
   EXPECT_THAT(grpc_error_std_string(error),
               ::testing::ContainsRegex(
-                  "Service config parsing error.*referenced_errors.*"
-                  "Method Params.*referenced_errors.*"
-                  "methodConfig.*referenced_errors.*"
-                  "retryPolicy.*referenced_errors.*"
-                  "field:retryableStatusCodes "
-                  "error:failed to parse status code.*"
-                  "field:retryableStatusCodes "
+                  "Service config parsing error" CHILD_ERROR_TAG
+                  "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
+                  "retryPolicy" CHILD_ERROR_TAG "field:retryableStatusCodes "
+                  "error:failed to parse status code"
+                  ".*field:retryableStatusCodes "
                   "error:status codes should be of type string"));
   GRPC_ERROR_UNREF(error);
 }
@@ -1392,10 +1375,9 @@ TEST_F(RetryParserTest, InvalidRetryPolicyPerAttemptRecvTimeoutUnparseable) {
   auto svc_cfg = ServiceConfig::Create(&args, test_json, &error);
   EXPECT_THAT(grpc_error_std_string(error),
               ::testing::ContainsRegex(
-                  "Service config parsing error.*referenced_errors.*"
-                  "Method Params.*referenced_errors.*"
-                  "methodConfig.*referenced_errors.*"
-                  "retryPolicy.*referenced_errors.*"
+                  "Service config parsing error" CHILD_ERROR_TAG
+                  "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
+                  "retryPolicy" CHILD_ERROR_TAG
                   "field:perAttemptRecvTimeout error:type must be STRING "
                   "of the form given by google.proto.Duration."));
   GRPC_ERROR_UNREF(error);
@@ -1425,10 +1407,9 @@ TEST_F(RetryParserTest, InvalidRetryPolicyPerAttemptRecvTimeoutWrongType) {
   auto svc_cfg = ServiceConfig::Create(&args, test_json, &error);
   EXPECT_THAT(grpc_error_std_string(error),
               ::testing::ContainsRegex(
-                  "Service config parsing error.*referenced_errors.*"
-                  "Method Params.*referenced_errors.*"
-                  "methodConfig.*referenced_errors.*"
-                  "retryPolicy.*referenced_errors.*"
+                  "Service config parsing error" CHILD_ERROR_TAG
+                  "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
+                  "retryPolicy" CHILD_ERROR_TAG
                   "field:perAttemptRecvTimeout error:type must be STRING "
                   "of the form given by google.proto.Duration."));
   GRPC_ERROR_UNREF(error);
@@ -1458,10 +1439,9 @@ TEST_F(RetryParserTest, InvalidRetryPolicyPerAttemptRecvTimeoutBadValue) {
   auto svc_cfg = ServiceConfig::Create(&args, test_json, &error);
   EXPECT_THAT(grpc_error_std_string(error),
               ::testing::ContainsRegex(
-                  "Service config parsing error.*referenced_errors.*"
-                  "Method Params.*referenced_errors.*"
-                  "methodConfig.*referenced_errors.*"
-                  "retryPolicy.*referenced_errors.*"
+                  "Service config parsing error" CHILD_ERROR_TAG
+                  "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
+                  "retryPolicy" CHILD_ERROR_TAG
                   "field:perAttemptRecvTimeout error:must be greater than 0"));
   GRPC_ERROR_UNREF(error);
 }
@@ -1473,8 +1453,8 @@ TEST_F(RetryParserTest, InvalidRetryPolicyPerAttemptRecvTimeoutBadValue) {
 class MessageSizeParserTest : public ::testing::Test {
  protected:
   void SetUp() override {
-    ServiceConfigParser::Shutdown();
-    ServiceConfigParser::Init();
+    ServiceConfigParserShutdown();
+    ServiceConfigParserInit();
     EXPECT_EQ(ServiceConfigParser::RegisterParser(
                   absl::make_unique<MessageSizeParser>()),
               0);
@@ -1519,10 +1499,9 @@ TEST_F(MessageSizeParserTest, InvalidMaxRequestMessageBytes) {
   auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error);
   EXPECT_THAT(grpc_error_std_string(error),
               ::testing::ContainsRegex(
-                  "Service config parsing error.*referenced_errors.*"
-                  "Method Params.*referenced_errors.*"
-                  "methodConfig.*referenced_errors.*"
-                  "Message size parser.*referenced_errors.*"
+                  "Service config parsing error" CHILD_ERROR_TAG
+                  "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
+                  "Message size parser" CHILD_ERROR_TAG
                   "field:maxRequestMessageBytes error:should be non-negative"));
   GRPC_ERROR_UNREF(error);
 }
@@ -1541,10 +1520,9 @@ TEST_F(MessageSizeParserTest, InvalidMaxResponseMessageBytes) {
   auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error);
   EXPECT_THAT(grpc_error_std_string(error),
               ::testing::ContainsRegex(
-                  "Service config parsing error.*referenced_errors.*"
-                  "Method Params.*referenced_errors.*"
-                  "methodConfig.*referenced_errors.*"
-                  "Message size parser.*referenced_errors.*"
+                  "Service config parsing error" CHILD_ERROR_TAG
+                  "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
+                  "Message size parser" CHILD_ERROR_TAG
                   "field:maxResponseMessageBytes error:should be of type "
                   "number"));
   GRPC_ERROR_UNREF(error);
diff --git a/test/core/client_idle/BUILD b/test/core/client_idle/BUILD
new file mode 100644 (file)
index 0000000..d9897f7
--- /dev/null
@@ -0,0 +1,33 @@
+# 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.
+
+load("//bazel:grpc_build_system.bzl", "grpc_cc_test", "grpc_package")
+
+licenses(["notice"])
+
+grpc_package(name = "test/core/client_idle")
+
+grpc_cc_test(
+    name = "idle_filter_state_test",
+    srcs = ["idle_filter_state_test.cc"],
+    external_deps = [
+        "gtest",
+    ],
+    language = "c++",
+    uses_polling = False,
+    deps = [
+        "//:idle_filter_state",
+        "//test/core/util:grpc_suppressions",
+    ],
+)
diff --git a/test/core/client_idle/idle_filter_state_test.cc b/test/core/client_idle/idle_filter_state_test.cc
new file mode 100644 (file)
index 0000000..2911b68
--- /dev/null
@@ -0,0 +1,109 @@
+// 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 "src/core/ext/filters/client_idle/idle_filter_state.h"
+
+#include <stdio.h>
+
+#include <chrono>
+#include <random>
+#include <thread>
+
+#include <gtest/gtest.h>
+
+namespace grpc_core {
+namespace testing {
+
+TEST(IdleFilterStateTest, IdlenessStartsTimer) {
+  IdleFilterState s(false);
+  s.IncreaseCallCount();
+  // First idle should start the timer
+  EXPECT_TRUE(s.DecreaseCallCount());
+  for (int i = 0; i < 10; i++) {
+    // Next idle should not!
+    s.IncreaseCallCount();
+    EXPECT_FALSE(s.DecreaseCallCount());
+  }
+}
+
+TEST(IdleFilterStateTest, TimerStopsAfterIdle) {
+  IdleFilterState s(true);
+  EXPECT_FALSE(s.CheckTimer());
+}
+
+TEST(IdleFilterStateTest, TimerKeepsGoingWithActivity) {
+  IdleFilterState s(true);
+  for (int i = 0; i < 10; i++) {
+    s.IncreaseCallCount();
+    (void)s.DecreaseCallCount();
+    EXPECT_TRUE(s.CheckTimer());
+  }
+  EXPECT_FALSE(s.CheckTimer());
+}
+
+TEST(IdleFilterStateTest, StressTest) {
+  IdleFilterState s(false);
+  std::atomic<bool> done{false};
+  int idle_polls = 0;
+  int thread_jumps = 0;
+  std::vector<std::thread> threads;
+  for (int idx = 0; idx < 100; idx++) {
+    std::thread t([&] {
+      int ctr = 0;
+      auto increase = [&] {
+        s.IncreaseCallCount();
+        ctr++;
+      };
+      auto decrease = [&] {
+        ctr--;
+        if (s.DecreaseCallCount()) {
+          thread_jumps++;
+          if (thread_jumps == 10) done.store(true, std::memory_order_relaxed);
+          EXPECT_EQ(ctr, 0);
+          do {
+            idle_polls++;
+            std::this_thread::sleep_for(std::chrono::milliseconds(10));
+          } while (s.CheckTimer());
+        }
+      };
+      std::mt19937 g{std::random_device()()};
+      while (!done.load(std::memory_order_relaxed)) {
+        std::this_thread::sleep_for(std::chrono::milliseconds(500));
+        for (int i = 0; i < 100; i++) {
+          if (g() & 1) {
+            increase();
+          } else if (ctr > 0) {
+            decrease();
+          }
+        }
+        while (ctr > 0) {
+          decrease();
+        }
+      }
+      while (ctr > 0) {
+        decrease();
+      }
+    });
+    threads.emplace_back(std::move(t));
+  }
+  for (auto& thread : threads) thread.join();
+}
+
+}  // namespace testing
+}  // namespace grpc_core
+
+int main(int argc, char** argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
index 81666f8..94ba177 100644 (file)
@@ -17,7 +17,7 @@ load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
 
 grpc_package(name = "test/core/compression")
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 grpc_cc_test(
     name = "algorithm_test",
index 140e909..2bc5ad2 100644 (file)
@@ -88,7 +88,7 @@ static void test_compression_algorithm_for_level(void) {
   {
     /* accept only identity (aka none) */
     uint32_t accepted_encodings = 0;
-    GPR_BITSET(&accepted_encodings, GRPC_COMPRESS_NONE); /* always */
+    grpc_core::SetBit(&accepted_encodings, GRPC_COMPRESS_NONE); /* always */
 
     GPR_ASSERT(GRPC_COMPRESS_NONE ==
                grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_NONE,
@@ -110,8 +110,8 @@ static void test_compression_algorithm_for_level(void) {
   {
     /* accept only gzip */
     uint32_t accepted_encodings = 0;
-    GPR_BITSET(&accepted_encodings, GRPC_COMPRESS_NONE); /* always */
-    GPR_BITSET(&accepted_encodings, GRPC_COMPRESS_GZIP);
+    grpc_core::SetBit(&accepted_encodings, GRPC_COMPRESS_NONE); /* always */
+    grpc_core::SetBit(&accepted_encodings, GRPC_COMPRESS_GZIP);
 
     GPR_ASSERT(GRPC_COMPRESS_NONE ==
                grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_NONE,
@@ -133,8 +133,8 @@ static void test_compression_algorithm_for_level(void) {
   {
     /* accept only deflate */
     uint32_t accepted_encodings = 0;
-    GPR_BITSET(&accepted_encodings, GRPC_COMPRESS_NONE); /* always */
-    GPR_BITSET(&accepted_encodings, GRPC_COMPRESS_DEFLATE);
+    grpc_core::SetBit(&accepted_encodings, GRPC_COMPRESS_NONE); /* always */
+    grpc_core::SetBit(&accepted_encodings, GRPC_COMPRESS_DEFLATE);
 
     GPR_ASSERT(GRPC_COMPRESS_NONE ==
                grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_NONE,
@@ -156,9 +156,9 @@ static void test_compression_algorithm_for_level(void) {
   {
     /* accept gzip and deflate */
     uint32_t accepted_encodings = 0;
-    GPR_BITSET(&accepted_encodings, GRPC_COMPRESS_NONE); /* always */
-    GPR_BITSET(&accepted_encodings, GRPC_COMPRESS_GZIP);
-    GPR_BITSET(&accepted_encodings, GRPC_COMPRESS_DEFLATE);
+    grpc_core::SetBit(&accepted_encodings, GRPC_COMPRESS_NONE); /* always */
+    grpc_core::SetBit(&accepted_encodings, GRPC_COMPRESS_GZIP);
+    grpc_core::SetBit(&accepted_encodings, GRPC_COMPRESS_DEFLATE);
 
     GPR_ASSERT(GRPC_COMPRESS_NONE ==
                grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_NONE,
@@ -180,8 +180,8 @@ static void test_compression_algorithm_for_level(void) {
   {
     /* accept stream gzip */
     uint32_t accepted_encodings = 0;
-    GPR_BITSET(&accepted_encodings, GRPC_COMPRESS_NONE); /* always */
-    GPR_BITSET(&accepted_encodings, GRPC_COMPRESS_STREAM_GZIP);
+    grpc_core::SetBit(&accepted_encodings, GRPC_COMPRESS_NONE); /* always */
+    grpc_core::SetBit(&accepted_encodings, GRPC_COMPRESS_STREAM_GZIP);
 
     GPR_ASSERT(GRPC_COMPRESS_NONE ==
                grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_NONE,
@@ -203,10 +203,10 @@ static void test_compression_algorithm_for_level(void) {
   {
     /* accept all algorithms */
     uint32_t accepted_encodings = 0;
-    GPR_BITSET(&accepted_encodings, GRPC_COMPRESS_NONE); /* always */
-    GPR_BITSET(&accepted_encodings, GRPC_COMPRESS_GZIP);
-    GPR_BITSET(&accepted_encodings, GRPC_COMPRESS_DEFLATE);
-    GPR_BITSET(&accepted_encodings, GRPC_COMPRESS_STREAM_GZIP);
+    grpc_core::SetBit(&accepted_encodings, GRPC_COMPRESS_NONE); /* always */
+    grpc_core::SetBit(&accepted_encodings, GRPC_COMPRESS_GZIP);
+    grpc_core::SetBit(&accepted_encodings, GRPC_COMPRESS_DEFLATE);
+    grpc_core::SetBit(&accepted_encodings, GRPC_COMPRESS_STREAM_GZIP);
 
     GPR_ASSERT(GRPC_COMPRESS_NONE ==
                grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_NONE,
@@ -288,7 +288,7 @@ static void test_channel_args_compression_algorithm_states(void) {
       grpc_channel_args_compression_algorithm_get_states(ch_args));
 
   for (i = 0; i < GRPC_COMPRESS_ALGORITHMS_COUNT; i++) {
-    GPR_ASSERT(GPR_BITGET(states_bitset, i));
+    GPR_ASSERT(grpc_core::GetBit(states_bitset, i));
   }
 
   /* disable gzip and deflate and stream/gzip */
@@ -309,9 +309,9 @@ static void test_channel_args_compression_algorithm_states(void) {
   for (i = 0; i < GRPC_COMPRESS_ALGORITHMS_COUNT; i++) {
     if (i == GRPC_COMPRESS_GZIP || i == GRPC_COMPRESS_DEFLATE ||
         i == GRPC_COMPRESS_STREAM_GZIP) {
-      GPR_ASSERT(GPR_BITGET(states_bitset, i) == 0);
+      GPR_ASSERT(grpc_core::GetBit(states_bitset, i) == 0);
     } else {
-      GPR_ASSERT(GPR_BITGET(states_bitset, i) != 0);
+      GPR_ASSERT(grpc_core::GetBit(states_bitset, i) != 0);
     }
   }
 
@@ -326,9 +326,9 @@ static void test_channel_args_compression_algorithm_states(void) {
       grpc_channel_args_compression_algorithm_get_states(ch_args_wo_gzip));
   for (i = 0; i < GRPC_COMPRESS_ALGORITHMS_COUNT; i++) {
     if (i == GRPC_COMPRESS_DEFLATE) {
-      GPR_ASSERT(GPR_BITGET(states_bitset, i) == 0);
+      GPR_ASSERT(grpc_core::GetBit(states_bitset, i) == 0);
     } else {
-      GPR_ASSERT(GPR_BITGET(states_bitset, i) != 0);
+      GPR_ASSERT(grpc_core::GetBit(states_bitset, i) != 0);
     }
   }
 
index 0274bcb..62d4cb3 100644 (file)
@@ -16,7 +16,7 @@ load("//bazel:grpc_build_system.bzl", "grpc_cc_binary", "grpc_cc_library", "grpc
 
 grpc_package(name = "test/core/debug")
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 grpc_cc_test(
     name = "stats_test",
index d173b20..801c559 100644 (file)
@@ -14,7 +14,7 @@
 
 load("//bazel:grpc_build_system.bzl", "grpc_cc_binary", "grpc_cc_library", "grpc_cc_test", "grpc_package")
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 grpc_package(name = "test/core/end2end")
 
index 68c9c33..c13f3ac 100644 (file)
@@ -201,8 +201,6 @@ extern void streaming_error_response(grpc_end2end_test_config config);
 extern void streaming_error_response_pre_init(void);
 extern void trailing_metadata(grpc_end2end_test_config config);
 extern void trailing_metadata_pre_init(void);
-extern void workaround_cronet_compression(grpc_end2end_test_config config);
-extern void workaround_cronet_compression_pre_init(void);
 extern void write_buffering(grpc_end2end_test_config config);
 extern void write_buffering_pre_init(void);
 extern void write_buffering_at_end(grpc_end2end_test_config config);
@@ -297,7 +295,6 @@ void grpc_end2end_tests_pre_init(void) {
   stream_compression_ping_pong_streaming_pre_init();
   streaming_error_response_pre_init();
   trailing_metadata_pre_init();
-  workaround_cronet_compression_pre_init();
   write_buffering_pre_init();
   write_buffering_at_end_pre_init();
 }
@@ -396,7 +393,6 @@ void grpc_end2end_tests(int argc, char **argv,
     stream_compression_ping_pong_streaming(config);
     streaming_error_response(config);
     trailing_metadata(config);
-    workaround_cronet_compression(config);
     write_buffering(config);
     write_buffering_at_end(config);
     return;
@@ -747,10 +743,6 @@ void grpc_end2end_tests(int argc, char **argv,
       trailing_metadata(config);
       continue;
     }
-    if (0 == strcmp("workaround_cronet_compression", argv[i])) {
-      workaround_cronet_compression(config);
-      continue;
-    }
     if (0 == strcmp("write_buffering", argv[i])) {
       write_buffering(config);
       continue;
index 3908936..231e55c 100644 (file)
@@ -205,8 +205,6 @@ extern void streaming_error_response(grpc_end2end_test_config config);
 extern void streaming_error_response_pre_init(void);
 extern void trailing_metadata(grpc_end2end_test_config config);
 extern void trailing_metadata_pre_init(void);
-extern void workaround_cronet_compression(grpc_end2end_test_config config);
-extern void workaround_cronet_compression_pre_init(void);
 extern void write_buffering(grpc_end2end_test_config config);
 extern void write_buffering_pre_init(void);
 extern void write_buffering_at_end(grpc_end2end_test_config config);
@@ -303,7 +301,6 @@ void grpc_end2end_tests_pre_init(void) {
   stream_compression_ping_pong_streaming_pre_init();
   streaming_error_response_pre_init();
   trailing_metadata_pre_init();
-  workaround_cronet_compression_pre_init();
   write_buffering_pre_init();
   write_buffering_at_end_pre_init();
 }
@@ -404,7 +401,6 @@ void grpc_end2end_tests(int argc, char **argv,
     stream_compression_ping_pong_streaming(config);
     streaming_error_response(config);
     trailing_metadata(config);
-    workaround_cronet_compression(config);
     write_buffering(config);
     write_buffering_at_end(config);
     return;
@@ -763,10 +759,6 @@ void grpc_end2end_tests(int argc, char **argv,
       trailing_metadata(config);
       continue;
     }
-    if (0 == strcmp("workaround_cronet_compression", argv[i])) {
-      workaround_cronet_compression(config);
-      continue;
-    }
     if (0 == strcmp("write_buffering", argv[i])) {
       write_buffering(config);
       continue;
diff --git a/test/core/end2end/fixtures/h2_full+workarounds.cc b/test/core/end2end/fixtures/h2_full+workarounds.cc
deleted file mode 100644 (file)
index 55a7354..0000000
+++ /dev/null
@@ -1,122 +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 <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/sync.h>
-#include <grpc/support/workaround_list.h>
-
-#include "src/core/ext/filters/client_channel/client_channel.h"
-#include "src/core/ext/filters/http/server/http_server_filter.h"
-#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
-#include "src/core/lib/channel/connected_channel.h"
-#include "src/core/lib/gprpp/host_port.h"
-#include "src/core/lib/surface/channel.h"
-#include "src/core/lib/surface/server.h"
-#include "test/core/end2end/end2end_tests.h"
-#include "test/core/util/port.h"
-#include "test/core/util/test_config.h"
-
-static char* workarounds_arg[GRPC_MAX_WORKAROUND_ID] = {
-    const_cast<char*>(GRPC_ARG_WORKAROUND_CRONET_COMPRESSION)};
-
-struct fullstack_fixture_data {
-  std::string localaddr;
-};
-
-static grpc_end2end_test_fixture chttp2_create_fixture_fullstack(
-    grpc_channel_args* /*client_args*/, grpc_channel_args* /*server_args*/) {
-  grpc_end2end_test_fixture f;
-  int port = grpc_pick_unused_port_or_die();
-  fullstack_fixture_data* ffd = new fullstack_fixture_data();
-  memset(&f, 0, sizeof(f));
-  ffd->localaddr = grpc_core::JoinHostPort("localhost", port);
-  f.fixture_data = ffd;
-  f.cq = grpc_completion_queue_create_for_next(nullptr);
-  f.shutdown_cq = grpc_completion_queue_create_for_pluck(nullptr);
-  return f;
-}
-
-void chttp2_init_client_fullstack(grpc_end2end_test_fixture* f,
-                                  grpc_channel_args* client_args) {
-  fullstack_fixture_data* ffd =
-      static_cast<fullstack_fixture_data*>(f->fixture_data);
-  f->client = grpc_insecure_channel_create(ffd->localaddr.c_str(), client_args,
-                                           nullptr);
-  GPR_ASSERT(f->client);
-}
-
-void chttp2_init_server_fullstack(grpc_end2end_test_fixture* f,
-                                  grpc_channel_args* server_args) {
-  int i;
-  grpc_core::ExecCtx exec_ctx;
-  fullstack_fixture_data* ffd =
-      static_cast<fullstack_fixture_data*>(f->fixture_data);
-  grpc_arg args[GRPC_MAX_WORKAROUND_ID];
-  for (i = 0; i < GRPC_MAX_WORKAROUND_ID; i++) {
-    args[i].key = workarounds_arg[i];
-    args[i].type = GRPC_ARG_INTEGER;
-    args[i].value.integer = 1;
-  }
-  grpc_channel_args* server_args_new =
-      grpc_channel_args_copy_and_add(server_args, args, GRPC_MAX_WORKAROUND_ID);
-  if (f->server) {
-    grpc_server_destroy(f->server);
-  }
-  f->server = grpc_server_create(server_args_new, nullptr);
-  grpc_server_register_completion_queue(f->server, f->cq, nullptr);
-  GPR_ASSERT(
-      grpc_server_add_insecure_http2_port(f->server, ffd->localaddr.c_str()));
-  grpc_server_start(f->server);
-  grpc_channel_args_destroy(server_args_new);
-}
-
-void chttp2_tear_down_fullstack(grpc_end2end_test_fixture* f) {
-  fullstack_fixture_data* ffd =
-      static_cast<fullstack_fixture_data*>(f->fixture_data);
-  delete ffd;
-}
-
-/* All test configurations */
-static grpc_end2end_test_config configs[] = {
-    {"chttp2/fullstack",
-     FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
-         FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
-         FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER |
-         FEATURE_MASK_SUPPORTS_WORKAROUNDS,
-     nullptr, chttp2_create_fixture_fullstack, chttp2_init_client_fullstack,
-     chttp2_init_server_fullstack, chttp2_tear_down_fullstack},
-};
-
-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;
-}
index 61a3955..a4b389c 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "absl/strings/str_format.h"
 
+#include <grpc/grpc_security.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/sync.h>
@@ -81,8 +82,10 @@ void chttp2_init_client_fullstack(grpc_end2end_test_fixture* f,
                         grpc_end2end_http_proxy_get_proxy_name(ffd->proxy));
   }
   gpr_setenv("http_proxy", proxy_uri.c_str());
-  f->client = grpc_insecure_channel_create(ffd->server_addr.c_str(),
-                                           client_args, nullptr);
+  grpc_channel_credentials* creds = grpc_insecure_credentials_create();
+  f->client = grpc_secure_channel_create(creds, ffd->server_addr.c_str(),
+                                         client_args, nullptr);
+  grpc_channel_credentials_release(creds);
   GPR_ASSERT(f->client);
 }
 
index d4fc912..93f4f1b 100644 (file)
@@ -33,6 +33,7 @@
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/gpr/string.h"
 #include "src/core/lib/gprpp/host_port.h"
+#include "src/core/lib/gprpp/memory.h"
 #include "src/core/lib/gprpp/thd.h"
 #include "src/core/lib/http/parser.h"
 #include "src/core/lib/iomgr/closure.h"
@@ -556,8 +557,7 @@ static void on_accept(void* arg, grpc_endpoint* endpoint,
   gpr_free(acceptor);
   grpc_end2end_http_proxy* proxy = static_cast<grpc_end2end_http_proxy*>(arg);
   // Instantiate proxy_connection.
-  proxy_connection* conn =
-      static_cast<proxy_connection*>(gpr_zalloc(sizeof(*conn)));
+  proxy_connection* conn = grpc_core::Zalloc<proxy_connection>();
   gpr_ref(&proxy->users);
   conn->client_endpoint = endpoint;
   conn->proxy = proxy;
index 851d55f..84f6bf4 100644 (file)
@@ -353,8 +353,7 @@ static void on_new_call(void* arg, int success) {
     proxy_call* pc = static_cast<proxy_call*>(gpr_malloc(sizeof(*pc)));
     memset(pc, 0, sizeof(*pc));
     pc->proxy = proxy;
-    GPR_SWAP(grpc_metadata_array, pc->c2p_initial_metadata,
-             proxy->new_call_metadata);
+    std::swap(pc->c2p_initial_metadata, proxy->new_call_metadata);
     pc->c2p = proxy->new_call;
     pc->p2s = grpc_channel_create_call(
         proxy->client, pc->c2p, GRPC_PROPAGATE_DEFAULTS, proxy->cq,
index 4091fcb..3b10d72 100644 (file)
@@ -16,9 +16,25 @@ load("//bazel:grpc_build_system.bzl", "grpc_cc_binary", "grpc_cc_library", "grpc
 
 grpc_package(name = "test/core/end2end/fuzzers")
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
-load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
+load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer", "grpc_proto_fuzzer")
+
+grpc_proto_fuzzer(
+    name = "api_fuzzer",
+    size = "enormous",
+    srcs = ["api_fuzzer.cc"],
+    corpus = "api_fuzzer_corpus",
+    language = "C++",
+    proto = "api_fuzzer.proto",
+    tags = ["no_windows"],
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/end2end:ssl_test_data",
+        "//test/core/util:grpc_test_util",
+    ],
+)
 
 grpc_fuzzer(
     name = "client_fuzzer",
diff --git a/test/core/end2end/fuzzers/api_fuzzer.cc b/test/core/end2end/fuzzers/api_fuzzer.cc
new file mode 100644 (file)
index 0000000..e231c01
--- /dev/null
@@ -0,0 +1,1071 @@
+/*
+ *
+ * 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 <grpc/grpc.h>
+#include <grpc/grpc_security.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+
+#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h"
+#include "src/core/ext/filters/client_channel/server_address.h"
+#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/gpr/env.h"
+#include "src/core/lib/iomgr/executor.h"
+#include "src/core/lib/iomgr/resolve_address.h"
+#include "src/core/lib/iomgr/tcp_client.h"
+#include "src/core/lib/iomgr/timer.h"
+#include "src/core/lib/iomgr/timer_manager.h"
+#include "src/core/lib/slice/slice_internal.h"
+#include "src/core/lib/surface/channel.h"
+#include "src/core/lib/surface/server.h"
+#include "src/core/lib/transport/metadata.h"
+#include "src/libfuzzer/libfuzzer_macro.h"
+#include "test/core/end2end/data/ssl_test_data.h"
+#include "test/core/end2end/fuzzers/api_fuzzer.pb.h"
+#include "test/core/util/passthru_endpoint.h"
+
+////////////////////////////////////////////////////////////////////////////////
+// logging
+
+bool squelch = true;
+bool leak_check = true;
+
+static void dont_log(gpr_log_func_args* /*args*/) {}
+
+////////////////////////////////////////////////////////////////////////////////
+// global state
+
+static gpr_timespec g_now;
+static grpc_server* g_server;
+static grpc_channel* g_channel;
+static grpc_resource_quota* g_resource_quota;
+
+extern gpr_timespec (*gpr_now_impl)(gpr_clock_type clock_type);
+
+static gpr_timespec now_impl(gpr_clock_type clock_type) {
+  GPR_ASSERT(clock_type != GPR_TIMESPAN);
+  gpr_timespec ts = g_now;
+  ts.clock_type = clock_type;
+  return ts;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// dns resolution
+
+typedef struct addr_req {
+  grpc_timer timer;
+  char* addr;
+  grpc_closure* on_done;
+  grpc_resolved_addresses** addrs;
+  std::unique_ptr<grpc_core::ServerAddressList>* addresses;
+} addr_req;
+
+static void finish_resolve(void* arg, grpc_error_handle error) {
+  addr_req* r = static_cast<addr_req*>(arg);
+
+  if (error == GRPC_ERROR_NONE && 0 == strcmp(r->addr, "server")) {
+    if (r->addrs != nullptr) {
+      grpc_resolved_addresses* addrs =
+          static_cast<grpc_resolved_addresses*>(gpr_malloc(sizeof(*addrs)));
+      addrs->naddrs = 1;
+      addrs->addrs = static_cast<grpc_resolved_address*>(
+          gpr_malloc(sizeof(*addrs->addrs)));
+      addrs->addrs[0].len = 0;
+      *r->addrs = addrs;
+    } else if (r->addresses != nullptr) {
+      *r->addresses = absl::make_unique<grpc_core::ServerAddressList>();
+      grpc_resolved_address fake_resolved_address;
+      memset(&fake_resolved_address, 0, sizeof(fake_resolved_address));
+      fake_resolved_address.len = 0;
+      (*r->addresses)->emplace_back(fake_resolved_address, nullptr);
+    }
+    grpc_core::ExecCtx::Run(DEBUG_LOCATION, r->on_done, GRPC_ERROR_NONE);
+  } else {
+    grpc_core::ExecCtx::Run(DEBUG_LOCATION, r->on_done,
+                            GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
+                                "Resolution failed", &error, 1));
+  }
+
+  gpr_free(r->addr);
+  delete r;
+}
+
+void my_resolve_address(const char* addr, const char* /*default_port*/,
+                        grpc_pollset_set* /*interested_parties*/,
+                        grpc_closure* on_done,
+                        grpc_resolved_addresses** addrs) {
+  addr_req* r = new addr_req();
+  r->addr = gpr_strdup(addr);
+  r->on_done = on_done;
+  r->addrs = addrs;
+  grpc_timer_init(
+      &r->timer, GPR_MS_PER_SEC + grpc_core::ExecCtx::Get()->Now(),
+      GRPC_CLOSURE_CREATE(finish_resolve, r, grpc_schedule_on_exec_ctx));
+}
+
+static grpc_address_resolver_vtable fuzzer_resolver = {my_resolve_address,
+                                                       nullptr};
+
+grpc_ares_request* my_dns_lookup_ares_locked(
+    const char* /*dns_server*/, const char* addr, const char* /*default_port*/,
+    grpc_pollset_set* /*interested_parties*/, grpc_closure* on_done,
+    std::unique_ptr<grpc_core::ServerAddressList>* addresses,
+    std::unique_ptr<grpc_core::ServerAddressList>* /*balancer_addresses*/,
+    char** /*service_config_json*/, int /*query_timeout*/,
+    std::shared_ptr<grpc_core::WorkSerializer> /*combiner*/) {
+  addr_req* r = new addr_req();
+  r->addr = gpr_strdup(addr);
+  r->on_done = on_done;
+  r->addrs = nullptr;
+  r->addresses = addresses;
+  grpc_timer_init(
+      &r->timer, GPR_MS_PER_SEC + grpc_core::ExecCtx::Get()->Now(),
+      GRPC_CLOSURE_CREATE(finish_resolve, r, grpc_schedule_on_exec_ctx));
+  return nullptr;
+}
+
+static void my_cancel_ares_request_locked(grpc_ares_request* request) {
+  GPR_ASSERT(request == nullptr);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// client connection
+
+static void sched_connect(grpc_closure* closure,
+                          grpc_slice_allocator* slice_allocator,
+                          grpc_endpoint** ep, gpr_timespec deadline);
+
+typedef struct {
+  grpc_timer timer;
+  grpc_closure* closure;
+  grpc_endpoint** ep;
+  gpr_timespec deadline;
+  grpc_slice_allocator* slice_allocator;
+} future_connect;
+
+static void do_connect(void* arg, grpc_error_handle error) {
+  future_connect* fc = static_cast<future_connect*>(arg);
+  if (error != GRPC_ERROR_NONE) {
+    grpc_slice_allocator_destroy(fc->slice_allocator);
+    *fc->ep = nullptr;
+    grpc_core::ExecCtx::Run(DEBUG_LOCATION, fc->closure, GRPC_ERROR_REF(error));
+  } else if (g_server != nullptr) {
+    grpc_slice_allocator_destroy(fc->slice_allocator);
+    grpc_endpoint* client;
+    grpc_endpoint* server;
+    grpc_passthru_endpoint_create(&client, &server, nullptr);
+    *fc->ep = client;
+
+    grpc_transport* transport = grpc_create_chttp2_transport(
+        nullptr, server, false,
+        grpc_resource_user_create(g_resource_quota, "transport-user"));
+    GPR_ASSERT(GRPC_LOG_IF_ERROR("SetupTransport",
+                                 g_server->core_server->SetupTransport(
+                                     transport, nullptr, nullptr, nullptr)));
+    grpc_chttp2_transport_start_reading(transport, nullptr, nullptr, nullptr);
+
+    grpc_core::ExecCtx::Run(DEBUG_LOCATION, fc->closure, GRPC_ERROR_NONE);
+  } else {
+    sched_connect(fc->closure, fc->slice_allocator, fc->ep, fc->deadline);
+  }
+  gpr_free(fc);
+}
+
+static void sched_connect(grpc_closure* closure,
+                          grpc_slice_allocator* slice_allocator,
+                          grpc_endpoint** ep, gpr_timespec deadline) {
+  if (gpr_time_cmp(deadline, gpr_now(deadline.clock_type)) < 0) {
+    *ep = nullptr;
+    grpc_slice_allocator_destroy(slice_allocator);
+    grpc_core::ExecCtx::Run(
+        DEBUG_LOCATION, closure,
+        GRPC_ERROR_CREATE_FROM_STATIC_STRING("Connect deadline exceeded"));
+    return;
+  }
+
+  future_connect* fc = static_cast<future_connect*>(gpr_malloc(sizeof(*fc)));
+  fc->closure = closure;
+  fc->ep = ep;
+  fc->deadline = deadline;
+  fc->slice_allocator = slice_allocator;
+  grpc_timer_init(
+      &fc->timer, GPR_MS_PER_SEC + grpc_core::ExecCtx::Get()->Now(),
+      GRPC_CLOSURE_CREATE(do_connect, fc, grpc_schedule_on_exec_ctx));
+}
+
+static void my_tcp_client_connect(grpc_closure* closure, grpc_endpoint** ep,
+                                  grpc_slice_allocator* slice_allocator,
+                                  grpc_pollset_set* /*interested_parties*/,
+                                  const grpc_channel_args* /*channel_args*/,
+                                  const grpc_resolved_address* /*addr*/,
+                                  grpc_millis deadline) {
+  sched_connect(closure, slice_allocator, ep,
+                grpc_millis_to_timespec(deadline, GPR_CLOCK_MONOTONIC));
+}
+
+grpc_tcp_client_vtable fuzz_tcp_client_vtable = {my_tcp_client_connect};
+
+////////////////////////////////////////////////////////////////////////////////
+// test driver
+
+class Validator {
+ public:
+  explicit Validator(std::function<void(bool)> impl) : impl_(impl) {}
+
+  virtual ~Validator() {}
+  void Run(bool success) {
+    impl_(success);
+    delete this;
+  }
+
+ private:
+  std::function<void(bool)> impl_;
+};
+
+Validator* MakeValidator(std::function<void(bool)> impl) {
+  return new Validator(std::move(impl));
+}
+
+static Validator* AssertSuccessAndDecrement(int* counter) {
+  return MakeValidator([counter](bool success) {
+    GPR_ASSERT(success);
+    --*counter;
+  });
+}
+
+static Validator* Decrement(int* counter) {
+  return MakeValidator([counter](bool) { --*counter; });
+}
+
+static Validator* ValidateConnectivityWatch(gpr_timespec deadline,
+                                            int* counter) {
+  return MakeValidator([deadline, counter](bool success) {
+    if (!success) {
+      GPR_ASSERT(gpr_time_cmp(gpr_now(deadline.clock_type), deadline) >= 0);
+    }
+    --*counter;
+  });
+}
+
+static void free_non_null(void* p) {
+  GPR_ASSERT(p != nullptr);
+  gpr_free(p);
+}
+
+enum class CallType { CLIENT, SERVER, PENDING_SERVER, TOMBSTONED };
+
+class Call : public std::enable_shared_from_this<Call> {
+ public:
+  explicit Call(CallType type) : type_(type) {}
+  ~Call();
+
+  CallType type() const { return type_; }
+
+  bool done() const {
+    if ((type_ == CallType::TOMBSTONED || call_closed_) && pending_ops_ == 0) {
+      return true;
+    }
+    if (call_ == nullptr && type() != CallType::PENDING_SERVER) return true;
+    return false;
+  }
+
+  void Shutdown() {
+    if (call_ != nullptr) {
+      grpc_call_cancel(call_, nullptr);
+      type_ = CallType::TOMBSTONED;
+    }
+  }
+
+  void SetCall(grpc_call* call) {
+    GPR_ASSERT(call_ == nullptr);
+    call_ = call;
+  }
+
+  grpc_call* call() const { return call_; }
+
+  void RequestCall(grpc_server* server, grpc_completion_queue* cq) {
+    auto* v = FinishedRequestCall();
+    grpc_call_error error = grpc_server_request_call(
+        server, &call_, &call_details_, &recv_initial_metadata_, cq, cq, v);
+    if (error != GRPC_CALL_OK) {
+      v->Run(false);
+    }
+  }
+
+  void* Allocate(size_t size) {
+    void* p = gpr_malloc(size);
+    free_pointers_.push_back(p);
+    return p;
+  }
+
+  template <typename T>
+  T* AllocArray(size_t elems) {
+    return static_cast<T*>(Allocate(sizeof(T) * elems));
+  }
+
+  template <typename T>
+  T* NewCopy(T value) {
+    T* p = AllocArray<T>(1);
+    new (p) T(value);
+    return p;
+  }
+
+  template <typename T>
+  grpc_slice ReadSlice(const T& s) {
+    grpc_slice slice = grpc_slice_from_cpp_string(s.value());
+    if (s.intern()) {
+      auto interned_slice = grpc_slice_intern(slice);
+      grpc_slice_unref(slice);
+      slice = interned_slice;
+    }
+    unref_slices_.push_back(slice);
+    return slice;
+  }
+
+  template <typename M>
+  grpc_metadata_array ReadMetadata(const M& metadata) {
+    grpc_metadata* m = AllocArray<grpc_metadata>(metadata.size());
+    for (int i = 0; i < metadata.size(); ++i) {
+      m[i].key = ReadSlice(metadata[i].key());
+      m[i].value = ReadSlice(metadata[i].value());
+    }
+    return grpc_metadata_array{static_cast<size_t>(metadata.size()),
+                               static_cast<size_t>(metadata.size()), m};
+  }
+
+  absl::optional<grpc_op> ReadOp(
+      const api_fuzzer::BatchOp& batch_op, bool* batch_is_ok,
+      uint8_t* batch_ops, std::vector<std::function<void()>>* unwinders) {
+    grpc_op op;
+    memset(&op, 0, sizeof(op));
+    switch (batch_op.op_case()) {
+      case api_fuzzer::BatchOp::OP_NOT_SET:
+        /* invalid value */
+        return {};
+      case api_fuzzer::BatchOp::kSendInitialMetadata:
+        if (sent_initial_metadata_) {
+          *batch_is_ok = false;
+        } else {
+          sent_initial_metadata_ = true;
+          op.op = GRPC_OP_SEND_INITIAL_METADATA;
+          *batch_ops |= 1 << GRPC_OP_SEND_INITIAL_METADATA;
+          auto ary = ReadMetadata(batch_op.send_initial_metadata().metadata());
+          op.data.send_initial_metadata.count = ary.count;
+          op.data.send_initial_metadata.metadata = ary.metadata;
+        }
+        break;
+      case api_fuzzer::BatchOp::kSendMessage:
+        op.op = GRPC_OP_SEND_MESSAGE;
+        if (send_message_ != nullptr) {
+          *batch_is_ok = false;
+        } else {
+          *batch_ops |= 1 << GRPC_OP_SEND_MESSAGE;
+          auto send = ReadSlice(batch_op.send_message().message());
+          send_message_ = op.data.send_message.send_message =
+              grpc_raw_byte_buffer_create(&send, 1);
+          unwinders->push_back([this]() {
+            grpc_byte_buffer_destroy(send_message_);
+            send_message_ = nullptr;
+          });
+        }
+        break;
+      case api_fuzzer::BatchOp::kSendCloseFromClient:
+        op.op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
+        *batch_ops |= 1 << GRPC_OP_SEND_CLOSE_FROM_CLIENT;
+        break;
+      case api_fuzzer::BatchOp::kSendStatusFromServer: {
+        op.op = GRPC_OP_SEND_STATUS_FROM_SERVER;
+        *batch_ops |= 1 << GRPC_OP_SEND_STATUS_FROM_SERVER;
+        auto ary = ReadMetadata(batch_op.send_status_from_server().metadata());
+        op.data.send_status_from_server.trailing_metadata_count = ary.count;
+        op.data.send_status_from_server.trailing_metadata = ary.metadata;
+        op.data.send_status_from_server.status = static_cast<grpc_status_code>(
+            batch_op.send_status_from_server().status_code());
+        op.data.send_status_from_server.status_details =
+            batch_op.send_status_from_server().has_status_details()
+                ? NewCopy(ReadSlice(
+                      batch_op.send_status_from_server().status_details()))
+                : nullptr;
+      } break;
+      case api_fuzzer::BatchOp::kReceiveInitialMetadata:
+        op.op = GRPC_OP_RECV_INITIAL_METADATA;
+        *batch_ops |= 1 << GRPC_OP_RECV_INITIAL_METADATA;
+        op.data.recv_initial_metadata.recv_initial_metadata =
+            &recv_initial_metadata_;
+        break;
+      case api_fuzzer::BatchOp::kReceiveMessage:
+        if (call_closed_) {
+          *batch_is_ok = false;
+        } else {
+          op.op = GRPC_OP_RECV_MESSAGE;
+          *batch_ops |= 1 << GRPC_OP_RECV_MESSAGE;
+          op.data.recv_message.recv_message = &recv_message_;
+        }
+        break;
+      case api_fuzzer::BatchOp::kReceiveStatusOnClient:
+        op.op = GRPC_OP_RECV_STATUS_ON_CLIENT;
+        op.data.recv_status_on_client.status = &status_;
+        op.data.recv_status_on_client.trailing_metadata =
+            &recv_trailing_metadata_;
+        op.data.recv_status_on_client.status_details = &recv_status_details_;
+        break;
+      case api_fuzzer::BatchOp::kReceiveCloseOnServer:
+        op.op = GRPC_OP_RECV_CLOSE_ON_SERVER;
+        *batch_ops |= 1 << GRPC_OP_RECV_CLOSE_ON_SERVER;
+        op.data.recv_close_on_server.cancelled = &cancelled_;
+        break;
+    }
+    op.reserved = nullptr;
+    op.flags = batch_op.flags();
+    return op;
+  }
+
+  Validator* FinishedBatchValidator(uint8_t has_ops) {
+    ++pending_ops_;
+    auto self = shared_from_this();
+    return MakeValidator([self, has_ops](bool) {
+      --self->pending_ops_;
+      if ((has_ops & (1u << GRPC_OP_RECV_MESSAGE) &&
+           self->recv_message_ != nullptr)) {
+        grpc_byte_buffer_destroy(self->recv_message_);
+        self->recv_message_ = nullptr;
+      }
+      if ((has_ops & (1u << GRPC_OP_SEND_MESSAGE))) {
+        grpc_byte_buffer_destroy(self->send_message_);
+        self->send_message_ = nullptr;
+      }
+      if ((has_ops & (1u << GRPC_OP_RECV_STATUS_ON_CLIENT)) ||
+          (has_ops & (1u << GRPC_OP_RECV_CLOSE_ON_SERVER))) {
+        self->call_closed_ = true;
+      }
+    });
+  }
+
+  Validator* FinishedRequestCall() {
+    ++pending_ops_;
+    auto self = shared_from_this();
+    return MakeValidator([self](bool success) {
+      GPR_ASSERT(self->pending_ops_ > 0);
+      --self->pending_ops_;
+      if (success) {
+        GPR_ASSERT(self->call_ != nullptr);
+        self->type_ = CallType::SERVER;
+      } else {
+        self->type_ = CallType::TOMBSTONED;
+      }
+    });
+  }
+
+ private:
+  CallType type_;
+  grpc_call* call_ = nullptr;
+  grpc_byte_buffer* recv_message_ = nullptr;
+  grpc_status_code status_;
+  grpc_metadata_array recv_initial_metadata_{0, 0, nullptr};
+  grpc_metadata_array recv_trailing_metadata_{0, 0, nullptr};
+  grpc_slice recv_status_details_ = grpc_empty_slice();
+  // set by receive close on server, unset here to trigger
+  // msan if misused
+  int cancelled_;
+  int pending_ops_ = 0;
+  bool sent_initial_metadata_ = false;
+  grpc_call_details call_details_{};
+  grpc_byte_buffer* send_message_ = nullptr;
+  bool call_closed_ = false;
+
+  std::vector<void*> free_pointers_;
+  std::vector<grpc_slice> unref_slices_;
+};
+
+static std::vector<std::shared_ptr<Call>> g_calls;
+static size_t g_active_call = 0;
+
+static Call* ActiveCall() {
+  while (!g_calls.empty()) {
+    if (g_active_call >= g_calls.size()) {
+      g_active_call = 0;
+    }
+    if (g_calls[g_active_call] != nullptr && !g_calls[g_active_call]->done()) {
+      return g_calls[g_active_call].get();
+    }
+    g_calls.erase(g_calls.begin() + g_active_call);
+  }
+  return nullptr;
+}
+
+Call::~Call() {
+  if (call_ != nullptr) {
+    grpc_call_unref(call_);
+  }
+
+  grpc_slice_unref(recv_status_details_);
+  grpc_call_details_destroy(&call_details_);
+
+  for (auto* p : free_pointers_) {
+    gpr_free(p);
+  }
+  for (auto s : unref_slices_) {
+    grpc_slice_unref(s);
+  }
+
+  grpc_metadata_array_destroy(&recv_initial_metadata_);
+  grpc_metadata_array_destroy(&recv_trailing_metadata_);
+}
+
+template <typename ChannelArgContainer>
+grpc_channel_args* ReadArgs(const ChannelArgContainer& args) {
+  grpc_channel_args* res =
+      static_cast<grpc_channel_args*>(gpr_malloc(sizeof(grpc_channel_args)));
+  res->args =
+      static_cast<grpc_arg*>(gpr_malloc(sizeof(grpc_arg) * args.size()));
+  int j = 0;
+  for (int i = 0; i < args.size(); i++) {
+    switch (args[i].value_case()) {
+      case api_fuzzer::ChannelArg::kStr:
+        res->args[j].type = GRPC_ARG_STRING;
+        res->args[j].value.string = gpr_strdup(args[i].str().c_str());
+        break;
+      case api_fuzzer::ChannelArg::kI:
+        res->args[j].type = GRPC_ARG_INTEGER;
+        res->args[j].value.integer = args[i].i();
+        break;
+      case api_fuzzer::ChannelArg::kResourceQuota:
+        if (args[i].key() != GRPC_ARG_RESOURCE_QUOTA) continue;
+        grpc_resource_quota_ref(g_resource_quota);
+        res->args[j].type = GRPC_ARG_POINTER;
+        res->args[j].value.pointer.p = g_resource_quota;
+        res->args[j].value.pointer.vtable = grpc_resource_quota_arg_vtable();
+        break;
+      case api_fuzzer::ChannelArg::VALUE_NOT_SET:
+        res->args[j].type = GRPC_ARG_INTEGER;
+        res->args[j].value.integer = 0;
+        break;
+    }
+    res->args[j].key = gpr_strdup(args[i].key().c_str());
+    ++j;
+  }
+  res->num_args = j;
+  return res;
+}
+
+static const char* ReadCredArtifact(
+    const api_fuzzer::CredArtifact& artifact,
+    std::initializer_list<const char*> builtins) {
+  switch (artifact.type_case()) {
+    case api_fuzzer::CredArtifact::kCustom:
+      return artifact.custom().c_str();
+    case api_fuzzer::CredArtifact::kBuiltin:
+      if (artifact.builtin() < 0) return nullptr;
+      if (artifact.builtin() < static_cast<int>(builtins.size())) {
+        return *(builtins.begin() + artifact.builtin());
+      }
+      return nullptr;
+    case api_fuzzer::CredArtifact::TYPE_NOT_SET:
+      return nullptr;
+  }
+}
+
+static grpc_channel_credentials* ReadSslChannelCreds(
+    const api_fuzzer::SslChannelCreds& creds) {
+  const char* root_certs =
+      creds.has_root_certs()
+          ? ReadCredArtifact(creds.root_certs(), {test_root_cert})
+          : nullptr;
+  const char* private_key =
+      creds.has_private_key()
+          ? ReadCredArtifact(creds.private_key(),
+                             {test_server1_key, test_self_signed_client_key,
+                              test_signed_client_key})
+          : nullptr;
+  const char* certs =
+      creds.has_certs()
+          ? ReadCredArtifact(creds.certs(),
+                             {test_server1_cert, test_self_signed_client_cert,
+                              test_signed_client_cert})
+          : nullptr;
+  grpc_ssl_pem_key_cert_pair key_cert_pair = {private_key, certs};
+  return grpc_ssl_credentials_create(
+      root_certs,
+      private_key != nullptr && certs != nullptr ? &key_cert_pair : nullptr,
+      nullptr, nullptr);
+}
+
+static grpc_call_credentials* ReadCallCreds(
+    const api_fuzzer::CallCreds& creds) {
+  switch (creds.type_case()) {
+    case api_fuzzer::CallCreds::TYPE_NOT_SET:
+      return nullptr;
+    case api_fuzzer::CallCreds::kNull:
+      return nullptr;
+    case api_fuzzer::CallCreds::kCompositeCallCreds: {
+      grpc_call_credentials* out = nullptr;
+      for (const auto& child_creds :
+           creds.composite_call_creds().call_creds()) {
+        grpc_call_credentials* child = ReadCallCreds(child_creds);
+        if (child != nullptr) {
+          if (out == nullptr) {
+            out = child;
+          } else {
+            auto* composed =
+                grpc_composite_call_credentials_create(out, child, nullptr);
+            grpc_call_credentials_release(child);
+            grpc_call_credentials_release(out);
+            out = composed;
+          }
+        }
+      }
+      return out;
+    }
+    case api_fuzzer::CallCreds::kAccessToken:
+      return grpc_access_token_credentials_create(creds.access_token().c_str(),
+                                                  nullptr);
+    case api_fuzzer::CallCreds::kIam:
+      return grpc_google_iam_credentials_create(
+          creds.iam().auth_token().c_str(), creds.iam().auth_selector().c_str(),
+          nullptr);
+      /* TODO(ctiller): more cred types here */
+  }
+}
+
+static grpc_channel_credentials* ReadChannelCreds(
+    const api_fuzzer::ChannelCreds& creds) {
+  switch (creds.type_case()) {
+    case api_fuzzer::ChannelCreds::TYPE_NOT_SET:
+      return nullptr;
+    case api_fuzzer::ChannelCreds::kSslChannelCreds:
+      return ReadSslChannelCreds(creds.ssl_channel_creds());
+    case api_fuzzer::ChannelCreds::kCompositeChannelCreds: {
+      const auto& comp = creds.composite_channel_creds();
+      grpc_channel_credentials* c1 =
+          comp.has_channel_creds() ? ReadChannelCreds(comp.channel_creds())
+                                   : nullptr;
+      grpc_call_credentials* c2 =
+          comp.has_call_creds() ? ReadCallCreds(comp.call_creds()) : nullptr;
+      if (c1 != nullptr && c2 != nullptr) {
+        grpc_channel_credentials* out =
+            grpc_composite_channel_credentials_create(c1, c2, nullptr);
+        grpc_channel_credentials_release(c1);
+        grpc_call_credentials_release(c2);
+        return out;
+      } else if (c1 != nullptr) {
+        return c1;
+      } else if (c2 != nullptr) {
+        grpc_call_credentials_release(c2);
+        return nullptr;
+      } else {
+        return nullptr;
+      }
+      GPR_UNREACHABLE_CODE(return nullptr);
+    }
+    case api_fuzzer::ChannelCreds::kNull:
+      return nullptr;
+  }
+}
+
+DEFINE_PROTO_FUZZER(const api_fuzzer::Msg& msg) {
+  grpc_test_only_set_slice_hash_seed(0);
+  char* grpc_trace_fuzzer = gpr_getenv("GRPC_TRACE_FUZZER");
+  if (squelch && grpc_trace_fuzzer == nullptr) gpr_set_log_function(dont_log);
+  gpr_free(grpc_trace_fuzzer);
+  grpc_set_tcp_client_impl(&fuzz_tcp_client_vtable);
+  gpr_now_impl = now_impl;
+  grpc_init();
+  grpc_timer_manager_set_threading(false);
+  {
+    grpc_core::ExecCtx exec_ctx;
+    grpc_core::Executor::SetThreadingAll(false);
+  }
+  grpc_set_resolver_impl(&fuzzer_resolver);
+  grpc_dns_lookup_ares_locked = my_dns_lookup_ares_locked;
+  grpc_cancel_ares_request_locked = my_cancel_ares_request_locked;
+
+  GPR_ASSERT(g_channel == nullptr);
+  GPR_ASSERT(g_server == nullptr);
+
+  bool server_shutdown = false;
+  int pending_server_shutdowns = 0;
+  int pending_channel_watches = 0;
+  int pending_pings = 0;
+
+  g_resource_quota = grpc_resource_quota_create("api_fuzzer");
+
+  grpc_completion_queue* cq = grpc_completion_queue_create_for_next(nullptr);
+
+  int action_index = 0;
+  auto no_more_actions = [&]() { action_index = msg.actions_size(); };
+
+  auto poll_cq = [&]() -> bool {
+    grpc_event ev = grpc_completion_queue_next(
+        cq, gpr_inf_past(GPR_CLOCK_REALTIME), nullptr);
+    switch (ev.type) {
+      case GRPC_OP_COMPLETE: {
+        static_cast<Validator*>(ev.tag)->Run(ev.success);
+        break;
+      }
+      case GRPC_QUEUE_TIMEOUT:
+        break;
+      case GRPC_QUEUE_SHUTDOWN:
+        return true;
+    }
+    return false;
+  };
+
+  while (action_index < msg.actions_size() || g_channel != nullptr ||
+         g_server != nullptr || pending_channel_watches > 0 ||
+         pending_pings > 0 || ActiveCall() != nullptr) {
+    if (action_index == msg.actions_size()) {
+      if (g_channel != nullptr) {
+        grpc_channel_destroy(g_channel);
+        g_channel = nullptr;
+      }
+      if (g_server != nullptr) {
+        if (!server_shutdown) {
+          grpc_server_shutdown_and_notify(
+              g_server, cq,
+              AssertSuccessAndDecrement(&pending_server_shutdowns));
+          server_shutdown = true;
+          pending_server_shutdowns++;
+        } else if (pending_server_shutdowns == 0) {
+          grpc_server_destroy(g_server);
+          g_server = nullptr;
+        }
+      }
+      for (auto& call : g_calls) {
+        if (call == nullptr) continue;
+        if (call->type() == CallType::PENDING_SERVER) continue;
+        call->Shutdown();
+      }
+
+      g_now = gpr_time_add(g_now, gpr_time_from_seconds(1, GPR_TIMESPAN));
+      grpc_timer_manager_tick();
+      GPR_ASSERT(!poll_cq());
+      continue;
+    }
+
+    grpc_timer_manager_tick();
+
+    const api_fuzzer::Action& action = msg.actions(action_index);
+    action_index++;
+    switch (action.type_case()) {
+      case api_fuzzer::Action::TYPE_NOT_SET:
+        no_more_actions();
+        break;
+      // tickle completion queue
+      case api_fuzzer::Action::kPollCq: {
+        GPR_ASSERT(!poll_cq());
+        break;
+      }
+      // increment global time
+      case api_fuzzer::Action::kAdvanceTime: {
+        g_now = gpr_time_add(
+            g_now, gpr_time_from_micros(action.advance_time(), GPR_TIMESPAN));
+        break;
+      }
+      // create an insecure channel
+      case api_fuzzer::Action::kCreateChannel: {
+        if (g_channel == nullptr) {
+          grpc_channel_args* args =
+              ReadArgs(action.create_channel().channel_args());
+          if (action.create_channel().has_channel_creds()) {
+            grpc_channel_credentials* creds =
+                ReadChannelCreds(action.create_channel().channel_creds());
+            g_channel = grpc_secure_channel_create(
+                creds, action.create_channel().target().c_str(), args, nullptr);
+            grpc_channel_credentials_release(creds);
+          } else {
+            g_channel = grpc_insecure_channel_create(
+                action.create_channel().target().c_str(), args, nullptr);
+          }
+          GPR_ASSERT(g_channel != nullptr);
+          {
+            grpc_core::ExecCtx exec_ctx;
+            grpc_channel_args_destroy(args);
+          }
+        } else {
+          no_more_actions();
+        }
+        break;
+      }
+      // destroy a channel
+      case api_fuzzer::Action::kCloseChannel: {
+        if (g_channel != nullptr) {
+          grpc_channel_destroy(g_channel);
+          g_channel = nullptr;
+        } else {
+          no_more_actions();
+        }
+        break;
+      }
+      // bring up a server
+      case api_fuzzer::Action::kCreateServer: {
+        if (g_server == nullptr) {
+          grpc_channel_args* args =
+              ReadArgs(action.create_server().channel_args());
+          g_server = grpc_server_create(args, nullptr);
+          GPR_ASSERT(g_server != nullptr);
+          {
+            grpc_core::ExecCtx exec_ctx;
+            grpc_channel_args_destroy(args);
+          }
+          grpc_server_register_completion_queue(g_server, cq, nullptr);
+          grpc_server_start(g_server);
+          server_shutdown = false;
+          GPR_ASSERT(pending_server_shutdowns == 0);
+        } else {
+          no_more_actions();
+        }
+        break;
+      }
+      // begin server shutdown
+      case api_fuzzer::Action::kShutdownServer: {
+        if (g_server != nullptr) {
+          grpc_server_shutdown_and_notify(
+              g_server, cq,
+              AssertSuccessAndDecrement(&pending_server_shutdowns));
+          pending_server_shutdowns++;
+          server_shutdown = true;
+        } else {
+          no_more_actions();
+        }
+        break;
+      }
+      // cancel all calls if shutdown
+      case api_fuzzer::Action::kCancelAllCallsIfShutdown: {
+        if (g_server != nullptr && server_shutdown) {
+          grpc_server_cancel_all_calls(g_server);
+        } else {
+          no_more_actions();
+        }
+        break;
+      }
+      // destroy server
+      case api_fuzzer::Action::kDestroyServerIfReady: {
+        if (g_server != nullptr && server_shutdown &&
+            pending_server_shutdowns == 0) {
+          grpc_server_destroy(g_server);
+          g_server = nullptr;
+        } else {
+          no_more_actions();
+        }
+        break;
+      }
+      // check connectivity
+      case api_fuzzer::Action::kCheckConnectivity: {
+        if (g_channel != nullptr) {
+          grpc_channel_check_connectivity_state(g_channel,
+                                                action.check_connectivity());
+        } else {
+          no_more_actions();
+        }
+        break;
+      }
+      // watch connectivity
+      case api_fuzzer::Action::kWatchConnectivity: {
+        if (g_channel != nullptr) {
+          grpc_connectivity_state st =
+              grpc_channel_check_connectivity_state(g_channel, 0);
+          if (st != GRPC_CHANNEL_SHUTDOWN) {
+            gpr_timespec deadline =
+                gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
+                             gpr_time_from_micros(action.watch_connectivity(),
+                                                  GPR_TIMESPAN));
+            grpc_channel_watch_connectivity_state(
+                g_channel, st, deadline, cq,
+                ValidateConnectivityWatch(deadline, &pending_channel_watches));
+            pending_channel_watches++;
+          }
+        } else {
+          no_more_actions();
+        }
+        break;
+      }
+      // create a call
+      case api_fuzzer::Action::kCreateCall: {
+        bool ok = true;
+        if (g_channel == nullptr) ok = false;
+        // If the active call is a server call, then use it as the parent call
+        // to exercise the propagation logic.
+        Call* parent_call = ActiveCall();
+        if (parent_call != nullptr && parent_call->type() != CallType::SERVER) {
+          parent_call = nullptr;
+        }
+        g_calls.emplace_back(new Call(CallType::CLIENT));
+        grpc_slice method =
+            g_calls.back()->ReadSlice(action.create_call().method());
+        if (GRPC_SLICE_LENGTH(method) == 0) {
+          ok = false;
+        }
+        grpc_slice host =
+            g_calls.back()->ReadSlice(action.create_call().host());
+        gpr_timespec deadline = gpr_time_add(
+            gpr_now(GPR_CLOCK_REALTIME),
+            gpr_time_from_micros(action.create_call().timeout(), GPR_TIMESPAN));
+
+        if (ok) {
+          g_calls.back()->SetCall(grpc_channel_create_call(
+              g_channel, parent_call == nullptr ? nullptr : parent_call->call(),
+              action.create_call().propagation_mask(), cq, method, &host,
+              deadline, nullptr));
+        } else {
+          g_calls.pop_back();
+          no_more_actions();
+        }
+        break;
+      }
+      // switch the 'current' call
+      case api_fuzzer::Action::kChangeActiveCall: {
+        g_active_call++;
+        ActiveCall();
+        break;
+      }
+      // queue some ops on a call
+      case api_fuzzer::Action::kQueueBatch: {
+        auto* active_call = ActiveCall();
+        if (active_call == nullptr ||
+            active_call->type() == CallType::PENDING_SERVER ||
+            active_call->call() == nullptr) {
+          no_more_actions();
+          break;
+        }
+        const auto& batch = action.queue_batch().operations();
+        if (batch.size() > 6) {
+          no_more_actions();
+          break;
+        }
+        std::vector<grpc_op> ops;
+        bool ok = true;
+        uint8_t has_ops = 0;
+        std::vector<std::function<void()>> unwinders;
+        for (const auto& batch_op : batch) {
+          auto op = active_call->ReadOp(batch_op, &ok, &has_ops, &unwinders);
+          if (!op.has_value()) continue;
+          ops.push_back(*op);
+        }
+        if (g_channel == nullptr) ok = false;
+        if (ok) {
+          auto* v = active_call->FinishedBatchValidator(has_ops);
+          grpc_call_error error = grpc_call_start_batch(
+              active_call->call(), ops.data(), ops.size(), v, nullptr);
+          if (error != GRPC_CALL_OK) {
+            v->Run(false);
+          }
+        } else {
+          no_more_actions();
+          for (auto& unwind : unwinders) {
+            unwind();
+          }
+        }
+        break;
+      }
+      // cancel current call
+      case api_fuzzer::Action::kCancelCall: {
+        auto* active_call = ActiveCall();
+        if (active_call != nullptr && active_call->call() != nullptr) {
+          grpc_call_cancel(active_call->call(), nullptr);
+        } else {
+          no_more_actions();
+        }
+        break;
+      }
+      // get a calls peer
+      case api_fuzzer::Action::kGetPeer: {
+        auto* active_call = ActiveCall();
+        if (active_call != nullptr && active_call->call() != nullptr) {
+          free_non_null(grpc_call_get_peer(active_call->call()));
+        } else {
+          no_more_actions();
+        }
+        break;
+      }
+      // get a channels target
+      case api_fuzzer::Action::kGetTarget: {
+        if (g_channel != nullptr) {
+          free_non_null(grpc_channel_get_target(g_channel));
+        } else {
+          no_more_actions();
+        }
+        break;
+      }
+      // send a ping on a channel
+      case api_fuzzer::Action::kPing: {
+        if (g_channel != nullptr) {
+          pending_pings++;
+          grpc_channel_ping(g_channel, cq, Decrement(&pending_pings), nullptr);
+        } else {
+          no_more_actions();
+        }
+        break;
+      }
+      // enable a tracer
+      case api_fuzzer::Action::kEnableTracer: {
+        grpc_tracer_set_enabled(action.enable_tracer().c_str(), 1);
+        break;
+      }
+      // disable a tracer
+      case api_fuzzer::Action::kDisableTracer: {
+        grpc_tracer_set_enabled(action.disable_tracer().c_str(), 0);
+        break;
+      }
+      // request a server call
+      case api_fuzzer::Action::kRequestCall: {
+        if (g_server == nullptr) {
+          no_more_actions();
+          break;
+        }
+        g_calls.emplace_back(new Call(CallType::PENDING_SERVER));
+        g_calls.back()->RequestCall(g_server, cq);
+        break;
+      }
+      // destroy a call
+      case api_fuzzer::Action::kDestroyCall: {
+        auto* active_call = ActiveCall();
+        if (active_call != nullptr &&
+            active_call->type() != CallType::PENDING_SERVER &&
+            active_call->call() != nullptr) {
+          g_calls[g_active_call]->Shutdown();
+        } else {
+          no_more_actions();
+        }
+        break;
+      }
+      // resize the buffer pool
+      case api_fuzzer::Action::kResizeResourceQuota: {
+        grpc_resource_quota_resize(g_resource_quota,
+                                   action.resize_resource_quota());
+        break;
+      }
+    }
+  }
+
+  GPR_ASSERT(g_channel == nullptr);
+  GPR_ASSERT(g_server == nullptr);
+  GPR_ASSERT(ActiveCall() == nullptr);
+  GPR_ASSERT(g_calls.empty());
+
+  grpc_completion_queue_shutdown(cq);
+  GPR_ASSERT(poll_cq());
+  grpc_completion_queue_destroy(cq);
+
+  grpc_resource_quota_unref(g_resource_quota);
+
+  grpc_shutdown_blocking();
+}
diff --git a/test/core/end2end/fuzzers/api_fuzzer.dictionary b/test/core/end2end/fuzzers/api_fuzzer.dictionary
new file mode 100644 (file)
index 0000000..c8dcc56
--- /dev/null
@@ -0,0 +1,27 @@
+# tracers
+"api\x00"
+"channel\x00"
+"channel_stack_builder\x00"
+"connectivity_state\x00"
+"flowctl\x00"
+"http\x00"
+"http1\x00"
+"round_robin\x00"
+"secure_endpoint\x00"
+"tcp\x00"
+"transport_security\x00"
+
+# channel args
+"\x00grpc.census\x00"
+"\x00grpc.max_concurrent_streams\x00"
+"\x00grpc.max_message_length\x00"
+"\x00grpc.http2.initial_sequence_number\x00"
+"\x00grpc.http2.lookahead_bytes\x00"
+"\x00grpc.http2.hpack_table_size.decoder\x00"
+"\x00grpc.http2.hpack_table_size.encoder\x00"
+"\x01grpc.default_authority\x00"
+"\x01grpc.primary_user_agent\x00"
+"\x01grpc.secondary_user_agent\x00"
+"\x00grpc.max_reconnect_backoff_ms\x00"
+"\x01grpc.ssl_target_name_override\x00"
+
diff --git a/test/core/end2end/fuzzers/api_fuzzer.proto b/test/core/end2end/fuzzers/api_fuzzer.proto
new file mode 100644 (file)
index 0000000..84968b9
--- /dev/null
@@ -0,0 +1,184 @@
+// 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.
+
+syntax = "proto3";
+
+package api_fuzzer;
+
+message Empty {}
+
+message ByteSlice {
+    bytes value = 1;
+    bool intern = 2;
+}
+
+message StringSlice {
+    string value = 1;
+    bool intern = 2;
+}
+
+message ResourceQuota {}
+
+message ChannelArg {
+    string key = 1;
+    oneof value {
+        string str = 2;
+        int64 i = 3;
+        ResourceQuota resource_quota = 4;
+    }
+}
+
+message CredArtifact {
+    oneof type {
+        string custom = 1;
+        int32 builtin = 2;
+    }
+}
+
+message SslChannelCreds {
+    CredArtifact root_certs = 1;
+    CredArtifact private_key = 2;
+    CredArtifact certs = 3;
+}
+
+message CompositeCallCreds {
+    repeated CallCreds call_creds = 1;
+}
+
+message IAM {
+    string auth_token = 1;
+    string auth_selector = 2;
+}
+
+message CallCreds {
+    oneof type {
+        CompositeCallCreds composite_call_creds = 1;
+        string access_token = 2;
+        IAM iam = 3;
+        Empty null = 4;
+    }
+}
+
+message CompositeChannelCreds {
+    ChannelCreds channel_creds = 1;
+    CallCreds call_creds = 2;
+}
+
+message ChannelCreds {
+    oneof type {
+        SslChannelCreds ssl_channel_creds = 1;
+        CompositeChannelCreds composite_channel_creds = 2;
+        Empty null = 3;
+    }
+}
+
+message Metadatum {
+    StringSlice key = 1;
+    ByteSlice value = 2;
+}
+
+message CreateChannel {
+    string target = 1;
+    repeated ChannelArg channel_args = 2;
+    ChannelCreds channel_creds = 3;
+}
+
+message CreateServer {
+    repeated ChannelArg channel_args = 1;
+}
+
+message CreateCall {
+    uint32 propagation_mask = 1;
+    StringSlice method = 2;
+    StringSlice host = 3;
+    int32 timeout = 4;
+}
+
+message SendInitialMetadata {
+    repeated Metadatum metadata = 1;
+}
+
+message SendMessage {
+    ByteSlice message = 1;
+}
+
+message SendCloseFromClient {
+}
+
+message SendStatusFromServer {
+    repeated Metadatum metadata = 1;
+    uint32 status_code = 2;
+    ByteSlice status_details = 3;
+}
+
+message ReceiveInitialMetadata {
+}
+
+message ReceiveMessage {
+}
+
+message ReceiveStatusOnClient {
+}
+
+message ReceiveCloseOnServer {
+}
+
+message BatchOp {
+    oneof op {
+        SendInitialMetadata send_initial_metadata = 1;
+        SendMessage send_message = 2;
+        SendCloseFromClient send_close_from_client = 3;
+        SendStatusFromServer send_status_from_server = 4;
+        ReceiveInitialMetadata receive_initial_metadata = 5;
+        ReceiveMessage receive_message = 6;
+        ReceiveStatusOnClient receive_status_on_client = 7;
+        ReceiveCloseOnServer receive_close_on_server = 8;
+    }
+    uint32 flags = 100;
+}
+
+message Batch {
+    repeated BatchOp operations = 1;
+}
+
+message Action {
+    oneof type {
+        Empty poll_cq = 1;
+        uint32 advance_time = 2;
+        CreateChannel create_channel = 3;
+        Empty close_channel = 4;
+        CreateServer create_server = 5;
+        Empty shutdown_server = 6;
+        Empty cancel_all_calls_if_shutdown = 7;
+        Empty destroy_server_if_ready = 8;
+        bool check_connectivity = 9;
+        uint32 watch_connectivity = 10;
+        CreateCall create_call = 11;
+        Empty change_active_call = 12;
+        Batch queue_batch = 13;
+        Empty cancel_call = 14;
+        Empty get_peer = 15;
+        Empty get_target = 16;
+        Empty ping = 17;
+        string enable_tracer = 18;
+        string disable_tracer = 19;
+        Empty request_call = 20;
+        Empty destroy_call = 21;
+        uint32 resize_resource_quota = 22;
+    }
+}
+
+message Msg {
+    repeated Action actions = 1;
+}
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/0
new file mode 100644 (file)
index 0000000..8b13789
--- /dev/null
@@ -0,0 +1 @@
+
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/channelz-crash b/test/core/end2end/fuzzers/api_fuzzer_corpus/channelz-crash
new file mode 100644 (file)
index 0000000..0eaa587
--- /dev/null
@@ -0,0 +1,19 @@
+actions {
+  create_channel {
+    target: "\001\000\000\000\323\273`*"
+    channel_args {
+      key: "grpc.channelz_channel_node"
+      resource_quota {
+      }
+    }
+    channel_args {
+      resource_quota {
+      }
+    }
+    channel_args {
+      resource_quota {
+      }
+    }
+  }
+}
+
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-on-unknown-compression-algorithm b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-on-unknown-compression-algorithm
new file mode 100644 (file)
index 0000000..0ef0af8
--- /dev/null
@@ -0,0 +1,19 @@
+actions {
+  create_channel {
+    target: "unix:phttpShttp6\327\227Go" 
+    channel_args {
+      key: "grpc.default_compression_algorithm"
+      i: 4702337453602635775
+    }
+  }
+}
+actions {
+  create_server {}
+}
+actions {
+  check_connectivity: true
+} 
+actions {
+  advance_time: 6881403
+} 
+actions {}
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/create_connection.textproto b/test/core/end2end/fuzzers/api_fuzzer_corpus/create_connection.textproto
new file mode 100644 (file)
index 0000000..294a168
--- /dev/null
@@ -0,0 +1,86 @@
+actions {
+  create_server {}
+}
+actions {
+  create_channel {
+    target: "dns:server"
+  }
+}
+actions {
+  create_call {
+    method: { value: "/foo" }
+    host: { value: "bob" }
+    timeout: 1000000000
+  }
+}
+actions {
+  request_call {}
+}
+actions {
+  queue_batch {
+    operations {
+      send_initial_metadata {}
+    }
+    operations {
+      send_message {}
+    }
+    operations {
+      send_close_from_client {}
+    }
+    operations {
+      receive_initial_metadata {}
+    }
+    operations {
+      receive_message {}
+    }
+    operations {
+      receive_status_on_client {}
+    }
+  }
+}
+actions {
+  change_active_call {}
+}
+actions {
+  advance_time: 10000000
+}
+actions {
+  advance_time: 1000
+}
+actions {
+  advance_time: 10000000
+}
+actions {
+  advance_time: 100000
+}
+actions {
+  poll_cq: {}
+}
+actions {
+  queue_batch {
+    operations {
+      send_initial_metadata {}
+    }
+    operations {
+      send_message {}
+    }
+    operations {
+      send_status_from_server {}
+    }
+    operations {
+      receive_message {}
+    }
+    operations {
+      receive_close_on_server {}
+    }
+  }
+}
+actions {
+  advance_time: 100000
+}
+actions {
+  poll_cq: {}
+}
+actions {
+  advance_time: 100000
+}
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/get-leak b/test/core/end2end/fuzzers/api_fuzzer_corpus/get-leak
new file mode 100644 (file)
index 0000000..2828b2d
--- /dev/null
@@ -0,0 +1,32 @@
+actions {
+  create_server {}
+}
+actions {
+  create_channel {
+  target:
+    "unix:\360\32367\227Go\254"
+  }
+}
+actions {
+  create_call {
+    method {
+      value: "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
+    }
+    timeout: 1000000000
+  }
+}
+actions {
+  queue_batch {
+    operations{
+      send_initial_metadata {} 
+      flags: 64
+    } 
+    operations {
+      send_message {}
+    }
+  }
+}
+actions {
+  advance_time : 10000000
+}
+actions {}
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/shifty-mcshifter b/test/core/end2end/fuzzers/api_fuzzer_corpus/shifty-mcshifter
new file mode 100644 (file)
index 0000000..6c61546
--- /dev/null
@@ -0,0 +1,21 @@
+actions {
+  create_channel {
+    target: "unix:"
+    channel_args {
+      key: "grpc.default_compression_algorithm"
+      i: 71776123355660288
+    }
+  }
+}
+actions {
+  create_server {
+  }
+}
+actions {
+  check_connectivity: true
+}
+actions {
+  advance_time: 6881279
+}
+actions {
+}
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/testcase-4953856886308864 b/test/core/end2end/fuzzers/api_fuzzer_corpus/testcase-4953856886308864
new file mode 100644 (file)
index 0000000..50fd147
--- /dev/null
@@ -0,0 +1,46 @@
+actions {
+  create_channel {
+    target: "unix::\360,\206=\211::::::::::6::::::::::::,:::\354\327:::::::::::::::::::::::::174515::::::::::::::::::::174515:::::::::::::::::, \310\013::::::, \310/::::::::::::::::::::::\177::::::::::::::::::::::::, \310/\032::travel/flights/summary/proto/fac::::::::, \310/\032::::::::::::::74515::::::::::::::\251:::, \310/::::::, \310/:::::::8c\017\303:::::::::::\177::::::::::::::::::::::::, \310/\032::::::::::, \310/\032::::::::::::::::::::::::::::::::::::::::::::::::::?:::::::::::::::::::::::::;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::?:::::::::::::::::::::::::;::::::::::::::"
+    channel_creds {
+      composite_channel_creds {
+        channel_creds {
+          composite_channel_creds {
+            channel_creds {
+              composite_channel_creds {
+                channel_creds {
+                  ssl_channel_creds {
+                  }
+                }
+              }
+            }
+            call_creds {
+              composite_call_creds {
+                call_creds {
+                  composite_call_creds {
+                    call_creds {
+                      access_token: ""
+                    }
+                    call_creds {
+                      iam {
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+        call_creds {
+          composite_call_creds {
+            call_creds {
+              access_token: ""
+            }
+          }
+        }
+      }
+    }
+  }
+}
+actions {
+  check_connectivity: true
+}
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/testcase-5212802075197440 b/test/core/end2end/fuzzers/api_fuzzer_corpus/testcase-5212802075197440
new file mode 100644 (file)
index 0000000..e79c06b
--- /dev/null
@@ -0,0 +1,17 @@
+actions {
+  create_channel {
+    target: "unix::\360,\206::::::::::::\354\327::::::::::::::::::\213\300:::::174515:::::::::::::::::, \310/:::::::::::::::::::::::::::::::::::::::?:::::::::::::::::::::::::;::::::::::::::"
+    channel_args {
+      key: "grpc.channel_credentials"
+      resource_quota {
+      }
+    }
+    channel_creds {
+      ssl_channel_creds {
+      }
+    }
+  }
+}
+actions {
+  check_connectivity: true
+}
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/testcase-6703968097271808 b/test/core/end2end/fuzzers/api_fuzzer_corpus/testcase-6703968097271808
new file mode 100644 (file)
index 0000000..cb144eb
--- /dev/null
@@ -0,0 +1,62 @@
+actions {
+  create_server {
+  }
+}
+actions {
+  create_channel {
+    target: "dns:server"
+  }
+}
+actions {
+  create_call {
+    method {
+      value: "/foo"
+    }
+    timeout: 1000000000
+  }
+}
+actions {
+  queue_batch {
+    operations {
+      send_initial_metadata {
+      }
+    }
+  }
+}
+actions {
+  advance_time: 9541248
+}
+actions {
+  queue_batch {
+    operations {
+      send_close_from_client {
+      }
+    }
+    operations {
+      send_message {
+      }
+    }
+    operations {
+      receive_initial_metadata {
+      }
+      flags: 1895825408
+    }
+  }
+}
+actions {
+  queue_batch {
+    operations {
+      send_message {
+        message {
+          value: "grp[.default_authority"
+          intern: true
+        }
+      }
+    }
+  }
+}
+actions {
+  advance_time: 10000000
+}
+actions {
+}
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/validator-fail b/test/core/end2end/fuzzers/api_fuzzer_corpus/validator-fail
new file mode 100644 (file)
index 0000000..c735e9a
--- /dev/null
@@ -0,0 +1,67 @@
+actions {
+  create_server {
+  }
+}
+actions {
+  create_channel {
+    target: "dns:server"
+  }
+}
+actions {
+  create_call {
+    method {
+      value: "/foo"
+    }
+    timeout: 1000000000
+  }
+}
+actions {
+  request_call {
+  }
+}
+actions {
+  queue_batch {
+    operations {
+      send_initial_metadata {
+      }
+    }
+    operations {
+      send_message {
+      }
+    }
+  }
+}
+actions {
+  change_active_call {
+  }
+}
+actions {
+  advance_time: 10000000
+}
+actions {
+  advance_time: 10000000
+}
+actions {
+  poll_cq {
+  }
+}
+actions {
+  queue_batch {
+    operations {
+      receive_message {
+      }
+    }
+  }
+}
+actions {
+  queue_batch {
+    operations {
+      send_close_from_client {
+      }
+    }
+    operations {
+      receive_close_on_server {
+      }
+    }
+  }
+}
index f6f3d4c..0bad6e6 100644 (file)
@@ -4,7 +4,6 @@
 "\x07:status"
 "\x0A:authority"
 "\x07:scheme"
-"\x02te"
 "\x0Cgrpc-message"
 "\x0Bgrpc-status"
 "\x10grpc-payload-bin"
@@ -42,6 +41,8 @@
 "\x07deflate"
 "\x04gzip"
 "\x0Bstream/gzip"
+"\x02te"
+"\x08trailers"
 "\x03GET"
 "\x04POST"
 "\x01/"
 "\x10www-authenticate"
 "\x010"
 "\x08identity"
-"\x08trailers"
 "\x10application/grpc"
 "\x04grpc"
 "\x03PUT"
 "\x00\x0Dgrpc-encoding\x08identity"
 "\x00\x0Dgrpc-encoding\x04gzip"
 "\x00\x0Dgrpc-encoding\x07deflate"
-"\x00\x02te\x08trailers"
 "\x00\x0Ccontent-type\x10application/grpc"
 "\x00\x07:scheme\x04grpc"
 "\x00\x07:method\x03PUT"
index 4fc9ef2..418676a 100644 (file)
@@ -57,7 +57,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
         nullptr, mock_endpoint, false,
         grpc_resource_user_create(resource_quota, "mock_transport"));
     grpc_resource_quota_unref(resource_quota);
-    server->core_server->SetupTransport(transport, nullptr, nullptr, nullptr);
+    GPR_ASSERT(GRPC_LOG_IF_ERROR("SetupTransport",
+                                 server->core_server->SetupTransport(
+                                     transport, nullptr, nullptr, nullptr)));
     grpc_chttp2_transport_start_reading(transport, nullptr, nullptr, nullptr);
 
     grpc_call* call1 = nullptr;
index 9886135..a2a9d2b 100755 (executable)
@@ -68,7 +68,6 @@ END2END_FIXTURES = {
     "h2_full": _fixture_options(),
     "h2_full+pipe": _fixture_options(_platforms = ["linux"]),
     "h2_full+trace": _fixture_options(tracing = True),
-    "h2_full+workarounds": _fixture_options(),
     "h2_http_proxy": _fixture_options(supports_proxy_auth = True),
     "h2_insecure": _fixture_options(secure = True),
     "h2_oauth2": _fixture_options(),
@@ -135,7 +134,6 @@ END2END_NOSEC_FIXTURES = {
     "h2_full": _fixture_options(secure = False),
     "h2_full+pipe": _fixture_options(secure = False, _platforms = ["linux"], supports_msvc = False),
     "h2_full+trace": _fixture_options(secure = False, tracing = True, supports_msvc = False),
-    "h2_full+workarounds": _fixture_options(secure = False),
     "h2_http_proxy": _fixture_options(secure = False, supports_proxy_auth = True),
     "h2_proxy": _fixture_options(secure = False, includes_proxy = True),
     "h2_sockpair_1byte": _fixture_options(
@@ -356,7 +354,6 @@ END2END_TESTS = {
     "authority_not_supported": _test_options(),
     "filter_latency": _test_options(),
     "filter_status_code": _test_options(),
-    "workaround_cronet_compression": _test_options(),
     "write_buffering": _test_options(needs_write_buffering = True),
     "write_buffering_at_end": _test_options(needs_write_buffering = True),
 }
index e0aaef6..4d4509b 100644 (file)
@@ -123,6 +123,7 @@ static grpc_ares_request* my_dns_lookup_ares_locked(
   } else {
     *addresses = absl::make_unique<grpc_core::ServerAddressList>();
     grpc_sockaddr_in sa;
+    memset(&sa, 0, sizeof(sa));
     sa.sin_family = GRPC_AF_INET;
     sa.sin_addr.s_addr = 0x100007f;
     sa.sin_port = grpc_htons(static_cast<uint16_t>(g_resolve_port));
index 18493e9..be36993 100644 (file)
@@ -414,7 +414,6 @@ static void simple_request_body(grpc_end2end_test_config config,
   // not likely to change much. Some parts of the error, like time created,
   // obviously are not checked.
   GPR_ASSERT(nullptr != strstr(error_string, "xyz"));
-  GPR_ASSERT(nullptr != strstr(error_string, "description"));
   GPR_ASSERT(nullptr != strstr(error_string, "Error received from peer"));
   GPR_ASSERT(nullptr != strstr(error_string, "grpc_message"));
   GPR_ASSERT(nullptr != strstr(error_string, "grpc_status"));
index 1e75b2b..9c744d5 100644 (file)
@@ -34,7 +34,7 @@ static grpc_call_error wait_for_deadline(grpc_call* /*call*/, void* reserved) {
 }
 
 static const cancellation_mode cancellation_modes[] = {
-    {"cancel", grpc_call_cancel, GRPC_STATUS_CANCELLED, "Cancelled"},
+    {"cancel", grpc_call_cancel, GRPC_STATUS_CANCELLED, "CANCELLED"},
     {"deadline", wait_for_deadline, GRPC_STATUS_DEADLINE_EXCEEDED,
      "Deadline Exceeded"},
 };
index 4185d84..cd9be9b 100644 (file)
@@ -399,13 +399,17 @@ static void request_with_payload_template_inner(
   CQ_EXPECT_COMPLETION(cqv, tag(100), true);
   cq_verify(cqv);
 
-  GPR_ASSERT(GPR_BITCOUNT(grpc_call_test_only_get_encodings_accepted_by_peer(
-                 s)) == GRPC_COMPRESS_ALGORITHMS_COUNT);
-  GPR_ASSERT(GPR_BITGET(grpc_call_test_only_get_encodings_accepted_by_peer(s),
+  GPR_ASSERT(grpc_core::BitCount(
+                 grpc_call_test_only_get_encodings_accepted_by_peer(s)) ==
+             GRPC_COMPRESS_ALGORITHMS_COUNT);
+  GPR_ASSERT(
+      grpc_core::GetBit(grpc_call_test_only_get_encodings_accepted_by_peer(s),
                         GRPC_COMPRESS_NONE) != 0);
-  GPR_ASSERT(GPR_BITGET(grpc_call_test_only_get_encodings_accepted_by_peer(s),
+  GPR_ASSERT(
+      grpc_core::GetBit(grpc_call_test_only_get_encodings_accepted_by_peer(s),
                         GRPC_COMPRESS_DEFLATE) != 0);
-  GPR_ASSERT(GPR_BITGET(grpc_call_test_only_get_encodings_accepted_by_peer(s),
+  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;
index c951174..8944c1a 100644 (file)
 #include <grpc/support/time.h>
 
 #include "src/core/lib/channel/channel_stack_builder.h"
+#include "src/core/lib/config/core_configuration.h"
 #include "src/core/lib/surface/channel_init.h"
 #include "test/core/end2end/cq_verifier.h"
 #include "test/core/end2end/end2end_tests.h"
 
-static bool g_enable_filter = false;
-
 static void* tag(intptr_t t) { return reinterpret_cast<void*>(t); }
 
 static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
@@ -251,29 +250,17 @@ static const grpc_channel_filter test_filter = {
  * Registration
  */
 
-static bool maybe_add_filter(grpc_channel_stack_builder* builder,
-                             void* /*arg*/) {
-  if (g_enable_filter) {
-    return grpc_channel_stack_builder_prepend_filter(builder, &test_filter,
-                                                     nullptr, nullptr);
-  } else {
-    return true;
-  }
-}
-
-static void init_plugin(void) {
-  grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, 0, maybe_add_filter,
-                                   nullptr);
-}
-
-static void destroy_plugin(void) {}
-
 void filter_causes_close(grpc_end2end_test_config config) {
-  g_enable_filter = true;
-  test_request(config);
-  g_enable_filter = false;
+  grpc_core::CoreConfiguration::RunWithSpecialConfiguration(
+      [](grpc_core::CoreConfiguration::Builder* builder) {
+        grpc_core::BuildCoreConfiguration(builder);
+        builder->channel_init()->RegisterStage(
+            GRPC_SERVER_CHANNEL, 0, [](grpc_channel_stack_builder* builder) {
+              return grpc_channel_stack_builder_prepend_filter(
+                  builder, &test_filter, nullptr, nullptr);
+            });
+      },
+      [config] { test_request(config); });
 }
 
-void filter_causes_close_pre_init(void) {
-  grpc_register_plugin(init_plugin, destroy_plugin);
-}
+void filter_causes_close_pre_init(void) {}
index d9528bc..a071a2f 100644 (file)
 #include <grpc/support/time.h>
 
 #include "src/core/lib/channel/channel_stack_builder.h"
+#include "src/core/lib/config/core_configuration.h"
 #include "src/core/lib/surface/channel_init.h"
 #include "test/core/end2end/cq_verifier.h"
 #include "test/core/end2end/end2end_tests.h"
 
 enum { TIMEOUT = 200000 };
 
-static bool g_enable_filter = false;
-
 static void* tag(intptr_t t) { return reinterpret_cast<void*>(t); }
 
 static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
@@ -274,48 +273,31 @@ static const grpc_channel_filter test_filter = {
  * Registration
  */
 
-static bool maybe_add_filter(grpc_channel_stack_builder* builder, void* arg) {
-  grpc_channel_filter* filter = static_cast<grpc_channel_filter*>(arg);
-  if (g_enable_filter) {
-    // 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.
-    grpc_channel_stack_builder_iterator* it =
-        grpc_channel_stack_builder_create_iterator_at_last(builder);
-    GPR_ASSERT(grpc_channel_stack_builder_move_prev(it));
-    const bool retval = grpc_channel_stack_builder_add_filter_before(
-        it, filter, nullptr, nullptr);
-    grpc_channel_stack_builder_iterator_destroy(it);
-    return retval;
-  } else {
-    return true;
-  }
-}
-
-static void init_plugin(void) {
-  grpc_channel_init_register_stage(
-      GRPC_CLIENT_CHANNEL, INT_MAX, maybe_add_filter,
-      const_cast<grpc_channel_filter*>(&test_filter));
-  grpc_channel_init_register_stage(
-      GRPC_CLIENT_SUBCHANNEL, INT_MAX, maybe_add_filter,
-      const_cast<grpc_channel_filter*>(&test_filter));
-  grpc_channel_init_register_stage(
-      GRPC_CLIENT_DIRECT_CHANNEL, INT_MAX, maybe_add_filter,
-      const_cast<grpc_channel_filter*>(&test_filter));
-  grpc_channel_init_register_stage(
-      GRPC_SERVER_CHANNEL, INT_MAX, maybe_add_filter,
-      const_cast<grpc_channel_filter*>(&test_filter));
-}
-
-static void destroy_plugin(void) {}
-
 void filter_context(grpc_end2end_test_config config) {
-  g_enable_filter = true;
-  test_request(config);
-  g_enable_filter = false;
+  grpc_core::CoreConfiguration::RunWithSpecialConfiguration(
+      [](grpc_core::CoreConfiguration::Builder* builder) {
+        grpc_core::BuildCoreConfiguration(builder);
+        for (auto type : {GRPC_CLIENT_CHANNEL, GRPC_CLIENT_SUBCHANNEL,
+                          GRPC_CLIENT_DIRECT_CHANNEL, GRPC_SERVER_CHANNEL}) {
+          builder->channel_init()->RegisterStage(
+              type, INT_MAX, [](grpc_channel_stack_builder* 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.
+                grpc_channel_stack_builder_iterator* it =
+                    grpc_channel_stack_builder_create_iterator_at_last(builder);
+                GPR_ASSERT(grpc_channel_stack_builder_move_prev(it));
+                const bool retval =
+                    grpc_channel_stack_builder_add_filter_before(
+                        it, &test_filter, nullptr, nullptr);
+                grpc_channel_stack_builder_iterator_destroy(it);
+                return retval;
+              });
+        }
+      },
+      [config] { test_request(config); });
 }
 
-void filter_context_pre_init(void) {
-  grpc_register_plugin(init_plugin, destroy_plugin);
-}
+void filter_context_pre_init(void) {}
index 30ee08d..d252c2d 100644 (file)
@@ -27,6 +27,7 @@
 #include <grpc/support/time.h>
 
 #include "src/core/lib/channel/channel_stack_builder.h"
+#include "src/core/lib/config/core_configuration.h"
 #include "src/core/lib/surface/channel_init.h"
 #include "test/core/end2end/cq_verifier.h"
 #include "test/core/end2end/end2end_tests.h"
@@ -456,76 +457,6 @@ static const grpc_channel_filter test_filter = {
  * Registration
  */
 
-static bool maybe_add_server_channel_filter(grpc_channel_stack_builder* builder,
-                                            void* /*arg*/) {
-  if (g_enable_server_channel_filter) {
-    // 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.
-    grpc_channel_stack_builder_iterator* it =
-        grpc_channel_stack_builder_create_iterator_at_last(builder);
-    GPR_ASSERT(grpc_channel_stack_builder_move_prev(it));
-    const bool retval = grpc_channel_stack_builder_add_filter_before(
-        it, &test_filter, nullptr, nullptr);
-    grpc_channel_stack_builder_iterator_destroy(it);
-    return retval;
-  } else {
-    return true;
-  }
-}
-
-static bool maybe_add_client_channel_filter(grpc_channel_stack_builder* builder,
-                                            void* /*arg*/) {
-  if (g_enable_client_channel_filter) {
-    // 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.
-    grpc_channel_stack_builder_iterator* it =
-        grpc_channel_stack_builder_create_iterator_at_last(builder);
-    GPR_ASSERT(grpc_channel_stack_builder_move_prev(it));
-    const bool retval = grpc_channel_stack_builder_add_filter_before(
-        it, &test_filter, nullptr, nullptr);
-    grpc_channel_stack_builder_iterator_destroy(it);
-    return retval;
-  } else {
-    return true;
-  }
-}
-
-static bool maybe_add_client_subchannel_filter(
-    grpc_channel_stack_builder* builder, void* /*arg*/) {
-  if (g_enable_client_subchannel_filter) {
-    // 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 client channel filter
-    // must be the last one.  So we add it right before the last one.
-    grpc_channel_stack_builder_iterator* it =
-        grpc_channel_stack_builder_create_iterator_at_last(builder);
-    GPR_ASSERT(grpc_channel_stack_builder_move_prev(it));
-    const bool retval = grpc_channel_stack_builder_add_filter_before(
-        it, &test_filter, nullptr, nullptr);
-    grpc_channel_stack_builder_iterator_destroy(it);
-    return retval;
-  } else {
-    return true;
-  }
-}
-
-static void init_plugin(void) {
-  grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX,
-                                   maybe_add_server_channel_filter, nullptr);
-  grpc_channel_init_register_stage(GRPC_CLIENT_CHANNEL, INT_MAX,
-                                   maybe_add_client_channel_filter, nullptr);
-  grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL, INT_MAX,
-                                   maybe_add_client_subchannel_filter, nullptr);
-  grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL, INT_MAX,
-                                   maybe_add_client_channel_filter, nullptr);
-}
-
-static void destroy_plugin(void) {}
-
 static void filter_init_fails_internal(grpc_end2end_test_config config) {
   gpr_log(GPR_INFO, "Testing SERVER_CHANNEL filter.");
   g_enable_server_channel_filter = true;
@@ -552,13 +483,37 @@ static void filter_init_fails_internal(grpc_end2end_test_config config) {
 }
 
 void filter_init_fails(grpc_end2end_test_config config) {
-  filter_init_fails_internal(config);
-  gpr_log(GPR_INFO, "Testing with channel filter init error");
-  g_channel_filter_init_failure = true;
-  filter_init_fails_internal(config);
-  g_channel_filter_init_failure = false;
+  grpc_core::CoreConfiguration::RunWithSpecialConfiguration(
+      [](grpc_core::CoreConfiguration::Builder* builder) {
+        grpc_core::BuildCoreConfiguration(builder);
+        auto register_stage = [builder](grpc_channel_stack_type type,
+                                        bool* enable) {
+          builder->channel_init()->RegisterStage(
+              type, INT_MAX, [enable](grpc_channel_stack_builder* builder) {
+                if (!*enable) return true;
+                // Want to add the filter as close to the end as possible,
+                // to make sure that all of the filters work well together.
+                // However, we can't add it at the very end, because either the
+                // client_channel filter or connected_channel filter must be the
+                // last one.  So we add it right before the last one.
+                grpc_channel_stack_builder_iterator* it =
+                    grpc_channel_stack_builder_create_iterator_at_last(builder);
+                GPR_ASSERT(grpc_channel_stack_builder_move_prev(it));
+                const bool retval =
+                    grpc_channel_stack_builder_add_filter_before(
+                        it, &test_filter, nullptr, nullptr);
+                grpc_channel_stack_builder_iterator_destroy(it);
+                return retval;
+              });
+        };
+        register_stage(GRPC_SERVER_CHANNEL, &g_enable_server_channel_filter);
+        register_stage(GRPC_CLIENT_CHANNEL, &g_enable_client_channel_filter);
+        register_stage(GRPC_CLIENT_SUBCHANNEL,
+                       &g_enable_client_subchannel_filter);
+        register_stage(GRPC_CLIENT_DIRECT_CHANNEL,
+                       &g_enable_client_channel_filter);
+      },
+      [config] { filter_init_fails_internal(config); });
 }
 
-void filter_init_fails_pre_init(void) {
-  grpc_register_plugin(init_plugin, destroy_plugin);
-}
+void filter_init_fails_pre_init(void) {}
index 7dfaca5..d87db6f 100644 (file)
 #include <grpc/support/time.h>
 
 #include "src/core/lib/channel/channel_stack_builder.h"
+#include "src/core/lib/config/core_configuration.h"
 #include "src/core/lib/surface/channel_init.h"
 #include "test/core/end2end/cq_verifier.h"
 #include "test/core/end2end/end2end_tests.h"
 
 enum { TIMEOUT = 200000 };
 
-static bool g_enable_filter = false;
 static gpr_mu g_mu;
 static gpr_timespec g_client_latency;
 static gpr_timespec g_server_latency;
@@ -304,46 +304,34 @@ static const grpc_channel_filter test_server_filter = {
  * Registration
  */
 
-static bool maybe_add_filter(grpc_channel_stack_builder* builder, void* arg) {
-  grpc_channel_filter* filter = static_cast<grpc_channel_filter*>(arg);
-  if (g_enable_filter) {
-    // 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.
-    grpc_channel_stack_builder_iterator* it =
-        grpc_channel_stack_builder_create_iterator_at_last(builder);
-    GPR_ASSERT(grpc_channel_stack_builder_move_prev(it));
-    const bool retval = grpc_channel_stack_builder_add_filter_before(
-        it, filter, nullptr, nullptr);
-    grpc_channel_stack_builder_iterator_destroy(it);
-    return retval;
-  } else {
-    return true;
-  }
-}
-
-static void init_plugin(void) {
-  gpr_mu_init(&g_mu);
-  grpc_channel_init_register_stage(
-      GRPC_CLIENT_CHANNEL, INT_MAX, maybe_add_filter,
-      const_cast<grpc_channel_filter*>(&test_client_filter));
-  grpc_channel_init_register_stage(
-      GRPC_CLIENT_DIRECT_CHANNEL, INT_MAX, maybe_add_filter,
-      const_cast<grpc_channel_filter*>(&test_client_filter));
-  grpc_channel_init_register_stage(
-      GRPC_SERVER_CHANNEL, INT_MAX, maybe_add_filter,
-      const_cast<grpc_channel_filter*>(&test_server_filter));
-}
-
-static void destroy_plugin(void) { gpr_mu_destroy(&g_mu); }
-
 void filter_latency(grpc_end2end_test_config config) {
-  g_enable_filter = true;
-  test_request(config);
-  g_enable_filter = false;
+  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_channel_stack_builder* 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.
+                grpc_channel_stack_builder_iterator* it =
+                    grpc_channel_stack_builder_create_iterator_at_last(builder);
+                GPR_ASSERT(grpc_channel_stack_builder_move_prev(it));
+                const bool retval =
+                    grpc_channel_stack_builder_add_filter_before(
+                        it, filter, nullptr, nullptr);
+                grpc_channel_stack_builder_iterator_destroy(it);
+                return retval;
+              });
+        };
+        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) {
-  grpc_register_plugin(init_plugin, destroy_plugin);
-}
+void filter_latency_pre_init(void) { gpr_mu_init(&g_mu); }
index db9d5cb..aac5681 100644 (file)
 #include <grpc/support/time.h>
 
 #include "src/core/lib/channel/channel_stack_builder.h"
+#include "src/core/lib/config/core_configuration.h"
 #include "src/core/lib/surface/call.h"
 #include "src/core/lib/surface/channel_init.h"
 #include "test/core/end2end/cq_verifier.h"
 #include "test/core/end2end/end2end_tests.h"
 
-static bool g_enable_filter = false;
 static gpr_mu g_mu;
 static grpc_call_stack* g_client_call_stack;
 static grpc_call_stack* g_server_call_stack;
@@ -109,6 +109,9 @@ static void end_test(grpc_end2end_test_fixture* f) {
 
 // Simple request via a server filter that saves the reported status code.
 static void test_request(grpc_end2end_test_config config) {
+  g_client_code_recv = false;
+  g_server_code_recv = false;
+
   grpc_call* c;
   grpc_call* s;
   grpc_end2end_test_fixture f =
@@ -263,10 +266,11 @@ static void server_start_transport_stream_op_batch(
   if (data->call == g_server_call_stack) {
     if (op->send_initial_metadata) {
       auto* batch = op->payload->send_initial_metadata.send_initial_metadata;
-      if (batch->idx.named.status != nullptr) {
+      if (batch->legacy_index()->named.status != nullptr) {
         /* Replace the HTTP status with 404 */
-        grpc_metadata_batch_substitute(batch, batch->idx.named.status,
-                                       GRPC_MDELEM_STATUS_404);
+        GPR_ASSERT(GRPC_LOG_IF_ERROR(
+            "Substitute", batch->Substitute(batch->legacy_index()->named.status,
+                                            GRPC_MDELEM_STATUS_404)));
       }
     }
   }
@@ -348,56 +352,38 @@ static const grpc_channel_filter test_server_filter = {
  * Registration
  */
 
-static bool maybe_add_filter(grpc_channel_stack_builder* builder, void* arg) {
-  grpc_channel_filter* filter = static_cast<grpc_channel_filter*>(arg);
-  if (g_enable_filter) {
-    // 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.
-    grpc_channel_stack_builder_iterator* it =
-        grpc_channel_stack_builder_create_iterator_at_last(builder);
-    GPR_ASSERT(grpc_channel_stack_builder_move_prev(it));
-    const bool retval = grpc_channel_stack_builder_add_filter_before(
-        it, filter, nullptr, nullptr);
-    grpc_channel_stack_builder_iterator_destroy(it);
-    return retval;
-  } else {
-    return true;
-  }
+void filter_status_code(grpc_end2end_test_config 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_channel_stack_builder* 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.
+                grpc_channel_stack_builder_iterator* it =
+                    grpc_channel_stack_builder_create_iterator_at_last(builder);
+                GPR_ASSERT(grpc_channel_stack_builder_move_prev(it));
+                const bool retval =
+                    grpc_channel_stack_builder_add_filter_before(
+                        it, filter, nullptr, nullptr);
+                grpc_channel_stack_builder_iterator_destroy(it);
+                return retval;
+              });
+        };
+        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); });
 }
 
-static void init_plugin(void) {
+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);
-  g_client_code_recv = false;
-  g_server_code_recv = false;
-
-  grpc_channel_init_register_stage(
-      GRPC_CLIENT_CHANNEL, INT_MAX, maybe_add_filter,
-      const_cast<grpc_channel_filter*>(&test_client_filter));
-  grpc_channel_init_register_stage(
-      GRPC_CLIENT_DIRECT_CHANNEL, INT_MAX, maybe_add_filter,
-      const_cast<grpc_channel_filter*>(&test_client_filter));
-  grpc_channel_init_register_stage(
-      GRPC_SERVER_CHANNEL, INT_MAX, maybe_add_filter,
-      const_cast<grpc_channel_filter*>(&test_server_filter));
-}
-
-static void destroy_plugin(void) {
-  gpr_cv_destroy(&g_client_code_cv);
-  gpr_cv_destroy(&g_server_code_cv);
-  gpr_mu_destroy(&g_mu);
-}
-
-void filter_status_code(grpc_end2end_test_config config) {
-  g_enable_filter = true;
-  test_request(config);
-  g_enable_filter = false;
-}
-
-void filter_status_code_pre_init(void) {
-  grpc_register_plugin(init_plugin, destroy_plugin);
 }
index 320816f..bcbe792 100644 (file)
@@ -31,6 +31,7 @@
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/channel/channel_stack.h"
 #include "src/core/lib/channel/channel_stack_builder.h"
+#include "src/core/lib/config/core_configuration.h"
 #include "src/core/lib/gpr/string.h"
 #include "src/core/lib/gpr/useful.h"
 #include "src/core/lib/iomgr/exec_ctx.h"
@@ -305,11 +306,7 @@ grpc_channel_filter FailSendOpsFilter::kFilterVtable = {
     "FailSendOpsFilter",
 };
 
-bool g_enable_filter = false;
-
-bool MaybeAddFilter(grpc_channel_stack_builder* builder, void* /*arg*/) {
-  // Skip if filter is not enabled.
-  if (!g_enable_filter) return true;
+bool MaybeAddFilter(grpc_channel_stack_builder* builder) {
   // Skip on proxy (which explicitly disables retries).
   const grpc_channel_args* args =
       grpc_channel_stack_builder_get_channel_arguments(builder);
@@ -321,24 +318,22 @@ bool MaybeAddFilter(grpc_channel_stack_builder* builder, void* /*arg*/) {
       builder, &FailSendOpsFilter::kFilterVtable, nullptr, nullptr);
 }
 
-void InitPlugin(void) {
-  grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL, 0, MaybeAddFilter,
-                                   nullptr);
-}
-
-void DestroyPlugin(void) {}
-
 }  // namespace
 
 void retry_cancel_with_multiple_send_batches(grpc_end2end_test_config config) {
   GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL);
-  g_enable_filter = true;
-  for (size_t i = 0; i < GPR_ARRAY_SIZE(cancellation_modes); ++i) {
-    test_retry_cancel_with_multiple_send_batches(config, cancellation_modes[i]);
-  }
-  g_enable_filter = false;
+  grpc_core::CoreConfiguration::RunWithSpecialConfiguration(
+      [](grpc_core::CoreConfiguration::Builder* builder) {
+        grpc_core::BuildCoreConfiguration(builder);
+        builder->channel_init()->RegisterStage(GRPC_CLIENT_SUBCHANNEL, 0,
+                                               MaybeAddFilter);
+      },
+      [config]() {
+        for (size_t i = 0; i < GPR_ARRAY_SIZE(cancellation_modes); ++i) {
+          test_retry_cancel_with_multiple_send_batches(config,
+                                                       cancellation_modes[i]);
+        }
+      });
 }
 
-void retry_cancel_with_multiple_send_batches_pre_init(void) {
-  grpc_register_plugin(InitPlugin, DestroyPlugin);
-}
+void retry_cancel_with_multiple_send_batches_pre_init(void) {}
index a8f20e0..ecd4979 100644 (file)
@@ -27,6 +27,7 @@
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/channel/channel_stack.h"
 #include "src/core/lib/channel/channel_stack_builder.h"
+#include "src/core/lib/config/core_configuration.h"
 #include "src/core/lib/gpr/string.h"
 #include "src/core/lib/gpr/useful.h"
 #include "src/core/lib/iomgr/exec_ctx.h"
@@ -337,11 +338,7 @@ grpc_channel_filter InjectStatusFilter::kFilterVtable = {
     "InjectStatusFilter",
 };
 
-bool g_enable_filter = false;
-
-bool MaybeAddFilter(grpc_channel_stack_builder* builder, void* /*arg*/) {
-  // Skip if filter is not enabled.
-  if (!g_enable_filter) return true;
+bool AddFilter(grpc_channel_stack_builder* builder) {
   // Skip on proxy (which explicitly disables retries).
   const grpc_channel_args* args =
       grpc_channel_stack_builder_get_channel_arguments(builder);
@@ -353,22 +350,17 @@ bool MaybeAddFilter(grpc_channel_stack_builder* builder, void* /*arg*/) {
       builder, &InjectStatusFilter::kFilterVtable, nullptr, nullptr);
 }
 
-void InitPlugin(void) {
-  grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL, 0, MaybeAddFilter,
-                                   nullptr);
-}
-
-void DestroyPlugin(void) {}
-
 }  // namespace
 
 void retry_recv_trailing_metadata_error(grpc_end2end_test_config config) {
   GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL);
-  g_enable_filter = true;
-  test_retry_recv_trailing_metadata_error(config);
-  g_enable_filter = false;
+  grpc_core::CoreConfiguration::RunWithSpecialConfiguration(
+      [](grpc_core::CoreConfiguration::Builder* builder) {
+        grpc_core::BuildCoreConfiguration(builder);
+        builder->channel_init()->RegisterStage(GRPC_CLIENT_SUBCHANNEL, 0,
+                                               AddFilter);
+      },
+      [config] { test_retry_recv_trailing_metadata_error(config); });
 }
 
-void retry_recv_trailing_metadata_error_pre_init() {
-  grpc_register_plugin(InitPlugin, DestroyPlugin);
-}
+void retry_recv_trailing_metadata_error_pre_init() {}
index 6abcc12..c090240 100644 (file)
@@ -29,6 +29,7 @@
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/channel/channel_stack.h"
 #include "src/core/lib/channel/channel_stack_builder.h"
+#include "src/core/lib/config/core_configuration.h"
 #include "src/core/lib/gpr/string.h"
 #include "src/core/lib/gpr/useful.h"
 #include "src/core/lib/iomgr/exec_ctx.h"
@@ -355,38 +356,29 @@ grpc_channel_filter FailFirstSendOpFilter::kFilterVtable = {
     "FailFirstSendOpFilter",
 };
 
-bool g_enable_filter = false;
-
-bool MaybeAddFilter(grpc_channel_stack_builder* builder, void* /*arg*/) {
-  // Skip if filter is not enabled.
-  if (!g_enable_filter) return true;
-  // Skip on proxy (which explicitly disables retries).
-  const grpc_channel_args* args =
-      grpc_channel_stack_builder_get_channel_arguments(builder);
-  if (!grpc_channel_args_find_bool(args, GRPC_ARG_ENABLE_RETRIES, true)) {
-    return true;
-  }
-  // Install filter.
-  return grpc_channel_stack_builder_prepend_filter(
-      builder, &FailFirstSendOpFilter::kFilterVtable, nullptr, nullptr);
-}
-
-void InitPlugin(void) {
-  grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL, 0, MaybeAddFilter,
-                                   nullptr);
-}
-
-void DestroyPlugin(void) {}
-
 }  // namespace
 
 void retry_send_op_fails(grpc_end2end_test_config config) {
   GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL);
-  g_enable_filter = true;
-  test_retry_send_op_fails(config);
-  g_enable_filter = false;
+  grpc_core::CoreConfiguration::RunWithSpecialConfiguration(
+      [](grpc_core::CoreConfiguration::Builder* builder) {
+        grpc_core::BuildCoreConfiguration(builder);
+        builder->channel_init()->RegisterStage(
+            GRPC_CLIENT_SUBCHANNEL, 0, [](grpc_channel_stack_builder* builder) {
+              // Skip on proxy (which explicitly disables retries).
+              const grpc_channel_args* args =
+                  grpc_channel_stack_builder_get_channel_arguments(builder);
+              if (!grpc_channel_args_find_bool(args, GRPC_ARG_ENABLE_RETRIES,
+                                               true)) {
+                return true;
+              }
+              // Install filter.
+              return grpc_channel_stack_builder_prepend_filter(
+                  builder, &FailFirstSendOpFilter::kFilterVtable, nullptr,
+                  nullptr);
+            });
+      },
+      [config] { test_retry_send_op_fails(config); });
 }
 
-void retry_send_op_fails_pre_init(void) {
-  grpc_register_plugin(InitPlugin, DestroyPlugin);
-}
+void retry_send_op_fails_pre_init(void) {}
index 6ab5e0b..19e228b 100644 (file)
@@ -27,6 +27,7 @@
 #include "src/core/lib/security/credentials/credentials.h"
 #include "test/core/end2end/cq_verifier.h"
 #include "test/core/end2end/end2end_tests.h"
+#include "test/core/util/tls_utils.h"
 
 static void* tag(intptr_t t) { return reinterpret_cast<void*>(t); }
 
@@ -84,7 +85,7 @@ static void end_test(grpc_end2end_test_fixture* f) {
   grpc_completion_queue_destroy(f->shutdown_cq);
 }
 
-static void test_allow_authorized_request(grpc_end2end_test_config config) {
+static void test_allow_authorized_request(grpc_end2end_test_fixture f) {
   grpc_call* c;
   grpc_call* s;
   grpc_op ops[6];
@@ -99,36 +100,6 @@ static void test_allow_authorized_request(grpc_end2end_test_config config) {
   grpc_slice details = grpc_empty_slice();
   int was_cancelled = 2;
 
-  const char* authz_policy =
-      "{"
-      "  \"name\": \"authz\","
-      "  \"allow_rules\": ["
-      "    {"
-      "      \"name\": \"allow_foo\","
-      "      \"request\": {"
-      "        \"paths\": ["
-      "          \"*/foo\""
-      "        ]"
-      "      }"
-      "    }"
-      "  ]"
-      "}";
-  grpc_status_code code;
-  const char* error_details;
-  grpc_authorization_policy_provider* provider =
-      grpc_authorization_policy_provider_static_data_create(authz_policy, &code,
-                                                            &error_details);
-  GPR_ASSERT(GRPC_STATUS_OK == code);
-  grpc_arg args[] = {
-      grpc_channel_arg_pointer_create(
-          const_cast<char*>(GRPC_ARG_AUTHORIZATION_POLICY_PROVIDER), provider,
-          grpc_authorization_policy_provider_arg_vtable()),
-  };
-  grpc_channel_args server_args = {GPR_ARRAY_SIZE(args), args};
-
-  grpc_end2end_test_fixture f = begin_test(
-      config, "test_allow_authorized_request", nullptr, &server_args);
-  grpc_authorization_policy_provider_release(provider);
   cq_verifier* cqv = cq_verifier_create(f.cq);
 
   gpr_timespec deadline = five_seconds_from_now();
@@ -217,12 +188,9 @@ static void test_allow_authorized_request(grpc_end2end_test_config config) {
   grpc_call_unref(c);
   grpc_call_unref(s);
   cq_verifier_destroy(cqv);
-
-  end_test(&f);
-  config.tear_down_data(&f);
 }
 
-static void test_deny_unauthorized_request(grpc_end2end_test_config config) {
+static void test_deny_unauthorized_request(grpc_end2end_test_fixture f) {
   grpc_call* c;
   grpc_op ops[6];
   grpc_op* op;
@@ -233,51 +201,11 @@ static void test_deny_unauthorized_request(grpc_end2end_test_config config) {
   grpc_call_error error;
   grpc_slice details = grpc_empty_slice();
 
-  const char* authz_policy =
-      "{"
-      "  \"name\": \"authz\","
-      "  \"allow_rules\": ["
-      "    {"
-      "      \"name\": \"allow_foo\","
-      "      \"request\": {"
-      "        \"paths\": ["
-      "          \"*/foo\""
-      "        ]"
-      "      }"
-      "    }"
-      "  ],"
-      "  \"deny_rules\": ["
-      "    {"
-      "      \"name\": \"deny_bar\","
-      "      \"request\": {"
-      "        \"paths\": ["
-      "          \"*/bar\""
-      "        ]"
-      "      }"
-      "    }"
-      "  ]"
-      "}";
-  grpc_status_code code;
-  const char* error_details;
-  grpc_authorization_policy_provider* provider =
-      grpc_authorization_policy_provider_static_data_create(authz_policy, &code,
-                                                            &error_details);
-  GPR_ASSERT(GRPC_STATUS_OK == code);
-  grpc_arg args[] = {
-      grpc_channel_arg_pointer_create(
-          const_cast<char*>(GRPC_ARG_AUTHORIZATION_POLICY_PROVIDER), provider,
-          grpc_authorization_policy_provider_arg_vtable()),
-  };
-  grpc_channel_args server_args = {GPR_ARRAY_SIZE(args), args};
-
-  grpc_end2end_test_fixture f = begin_test(
-      config, "test_deny_unauthorized_request", nullptr, &server_args);
-  grpc_authorization_policy_provider_release(provider);
   cq_verifier* cqv = cq_verifier_create(f.cq);
 
   gpr_timespec deadline = five_seconds_from_now();
   c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-                               grpc_slice_from_static_string("/bar"), nullptr,
+                               grpc_slice_from_static_string("/foo"), nullptr,
                                deadline, nullptr);
   GPR_ASSERT(c);
 
@@ -325,29 +253,65 @@ static void test_deny_unauthorized_request(grpc_end2end_test_config config) {
 
   grpc_call_unref(c);
   cq_verifier_destroy(cqv);
+}
+
+static void test_static_init_allow_authorized_request(
+    grpc_end2end_test_config config) {
+  const char* authz_policy =
+      "{"
+      "  \"name\": \"authz\","
+      "  \"allow_rules\": ["
+      "    {"
+      "      \"name\": \"allow_foo\","
+      "      \"request\": {"
+      "        \"paths\": ["
+      "          \"*/foo\""
+      "        ]"
+      "      }"
+      "    }"
+      "  ]"
+      "}";
+  grpc_status_code code = GRPC_STATUS_OK;
+  const char* error_details;
+  grpc_authorization_policy_provider* provider =
+      grpc_authorization_policy_provider_static_data_create(authz_policy, &code,
+                                                            &error_details);
+  GPR_ASSERT(GRPC_STATUS_OK == code);
+  grpc_arg args[] = {
+      grpc_channel_arg_pointer_create(
+          const_cast<char*>(GRPC_ARG_AUTHORIZATION_POLICY_PROVIDER), provider,
+          grpc_authorization_policy_provider_arg_vtable()),
+  };
+  grpc_channel_args server_args = {GPR_ARRAY_SIZE(args), args};
+
+  grpc_end2end_test_fixture f =
+      begin_test(config, "test_static_init_allow_authorized_request", nullptr,
+                 &server_args);
+  grpc_authorization_policy_provider_release(provider);
+  test_allow_authorized_request(f);
 
   end_test(&f);
   config.tear_down_data(&f);
 }
 
-static void test_deny_request_no_match_in_policy(
+static void test_static_init_deny_unauthorized_request(
     grpc_end2end_test_config config) {
-  grpc_call* c;
-  grpc_op ops[6];
-  grpc_op* op;
-  grpc_metadata_array initial_metadata_recv;
-  grpc_metadata_array trailing_metadata_recv;
-  grpc_status_code status;
-  const char* error_string = nullptr;
-  grpc_call_error error;
-  grpc_slice details = grpc_empty_slice();
-
   const char* authz_policy =
       "{"
       "  \"name\": \"authz\","
       "  \"allow_rules\": ["
       "    {"
-      "      \"name\": \"allow_foo\","
+      "      \"name\": \"allow_bar\","
+      "      \"request\": {"
+      "        \"paths\": ["
+      "          \"*/bar\""
+      "        ]"
+      "      }"
+      "    }"
+      "  ],"
+      "  \"deny_rules\": ["
+      "    {"
+      "      \"name\": \"deny_foo\","
       "      \"request\": {"
       "        \"paths\": ["
       "          \"*/foo\""
@@ -356,7 +320,46 @@ static void test_deny_request_no_match_in_policy(
       "    }"
       "  ]"
       "}";
-  grpc_status_code code;
+  grpc_status_code code = GRPC_STATUS_OK;
+  const char* error_details;
+  grpc_authorization_policy_provider* provider =
+      grpc_authorization_policy_provider_static_data_create(authz_policy, &code,
+                                                            &error_details);
+  GPR_ASSERT(GRPC_STATUS_OK == code);
+  grpc_arg args[] = {
+      grpc_channel_arg_pointer_create(
+          const_cast<char*>(GRPC_ARG_AUTHORIZATION_POLICY_PROVIDER), provider,
+          grpc_authorization_policy_provider_arg_vtable()),
+  };
+  grpc_channel_args server_args = {GPR_ARRAY_SIZE(args), args};
+
+  grpc_end2end_test_fixture f =
+      begin_test(config, "test_static_init_deny_unauthorized_request", nullptr,
+                 &server_args);
+  grpc_authorization_policy_provider_release(provider);
+  test_deny_unauthorized_request(f);
+
+  end_test(&f);
+  config.tear_down_data(&f);
+}
+
+static void test_static_init_deny_request_no_match_in_policy(
+    grpc_end2end_test_config config) {
+  const char* authz_policy =
+      "{"
+      "  \"name\": \"authz\","
+      "  \"allow_rules\": ["
+      "    {"
+      "      \"name\": \"allow_bar\","
+      "      \"request\": {"
+      "        \"paths\": ["
+      "          \"*/bar\""
+      "        ]"
+      "      }"
+      "    }"
+      "  ]"
+      "}";
+  grpc_status_code code = GRPC_STATUS_OK;
   const char* error_details;
   grpc_authorization_policy_provider* provider =
       grpc_authorization_policy_provider_static_data_create(authz_policy, &code,
@@ -369,70 +372,351 @@ static void test_deny_request_no_match_in_policy(
   };
   grpc_channel_args server_args = {GPR_ARRAY_SIZE(args), args};
 
+  grpc_end2end_test_fixture f =
+      begin_test(config, "test_static_init_deny_request_no_match_in_policy",
+                 nullptr, &server_args);
+  grpc_authorization_policy_provider_release(provider);
+  test_deny_unauthorized_request(f);
+
+  end_test(&f);
+  config.tear_down_data(&f);
+}
+
+static void test_file_watcher_init_allow_authorized_request(
+    grpc_end2end_test_config config) {
+  const char* authz_policy =
+      "{"
+      "  \"name\": \"authz\","
+      "  \"allow_rules\": ["
+      "    {"
+      "      \"name\": \"allow_foo\","
+      "      \"request\": {"
+      "        \"paths\": ["
+      "          \"*/foo\""
+      "        ]"
+      "      }"
+      "    }"
+      "  ]"
+      "}";
+  grpc_core::testing::TmpFile tmp_policy(authz_policy);
+  grpc_status_code code = GRPC_STATUS_OK;
+  const char* error_details;
+  grpc_authorization_policy_provider* provider =
+      grpc_authorization_policy_provider_file_watcher_create(
+          tmp_policy.name().c_str(), /*refresh_interval_sec=*/1, &code,
+          &error_details);
+  GPR_ASSERT(GRPC_STATUS_OK == code);
+  grpc_arg args[] = {
+      grpc_channel_arg_pointer_create(
+          const_cast<char*>(GRPC_ARG_AUTHORIZATION_POLICY_PROVIDER), provider,
+          grpc_authorization_policy_provider_arg_vtable()),
+  };
+  grpc_channel_args server_args = {GPR_ARRAY_SIZE(args), args};
+
+  grpc_end2end_test_fixture f =
+      begin_test(config, "test_file_watcher_init_allow_authorized_request",
+                 nullptr, &server_args);
+  grpc_authorization_policy_provider_release(provider);
+  test_allow_authorized_request(f);
+
+  end_test(&f);
+  config.tear_down_data(&f);
+}
+
+static void test_file_watcher_init_deny_unauthorized_request(
+    grpc_end2end_test_config config) {
+  const char* authz_policy =
+      "{"
+      "  \"name\": \"authz\","
+      "  \"allow_rules\": ["
+      "    {"
+      "      \"name\": \"allow_bar\","
+      "      \"request\": {"
+      "        \"paths\": ["
+      "          \"*/bar\""
+      "        ]"
+      "      }"
+      "    }"
+      "  ],"
+      "  \"deny_rules\": ["
+      "    {"
+      "      \"name\": \"deny_foo\","
+      "      \"request\": {"
+      "        \"paths\": ["
+      "          \"*/foo\""
+      "        ]"
+      "      }"
+      "    }"
+      "  ]"
+      "}";
+  grpc_core::testing::TmpFile tmp_policy(authz_policy);
+  grpc_status_code code = GRPC_STATUS_OK;
+  const char* error_details;
+  grpc_authorization_policy_provider* provider =
+      grpc_authorization_policy_provider_file_watcher_create(
+          tmp_policy.name().c_str(), /*refresh_interval_sec=*/1, &code,
+          &error_details);
+  GPR_ASSERT(GRPC_STATUS_OK == code);
+  grpc_arg args[] = {
+      grpc_channel_arg_pointer_create(
+          const_cast<char*>(GRPC_ARG_AUTHORIZATION_POLICY_PROVIDER), provider,
+          grpc_authorization_policy_provider_arg_vtable()),
+  };
+  grpc_channel_args server_args = {GPR_ARRAY_SIZE(args), args};
+
+  grpc_end2end_test_fixture f =
+      begin_test(config, "test_file_watcher_init_deny_unauthorized_request",
+                 nullptr, &server_args);
+  grpc_authorization_policy_provider_release(provider);
+  test_deny_unauthorized_request(f);
+
+  end_test(&f);
+  config.tear_down_data(&f);
+}
+
+static void test_file_watcher_init_deny_request_no_match_in_policy(
+    grpc_end2end_test_config config) {
+  const char* authz_policy =
+      "{"
+      "  \"name\": \"authz\","
+      "  \"allow_rules\": ["
+      "    {"
+      "      \"name\": \"allow_bar\","
+      "      \"request\": {"
+      "        \"paths\": ["
+      "          \"*/bar\""
+      "        ]"
+      "      }"
+      "    }"
+      "  ]"
+      "}";
+  grpc_core::testing::TmpFile tmp_policy(authz_policy);
+  grpc_status_code code = GRPC_STATUS_OK;
+  const char* error_details;
+  grpc_authorization_policy_provider* provider =
+      grpc_authorization_policy_provider_file_watcher_create(
+          tmp_policy.name().c_str(), /*refresh_interval_sec=*/1, &code,
+          &error_details);
+  GPR_ASSERT(GRPC_STATUS_OK == code);
+  grpc_arg args[] = {
+      grpc_channel_arg_pointer_create(
+          const_cast<char*>(GRPC_ARG_AUTHORIZATION_POLICY_PROVIDER), provider,
+          grpc_authorization_policy_provider_arg_vtable()),
+  };
+  grpc_channel_args server_args = {GPR_ARRAY_SIZE(args), args};
+
   grpc_end2end_test_fixture f = begin_test(
-      config, "test_deny_request_no_match_in_policy", nullptr, &server_args);
+      config, "test_file_watcher_init_deny_request_no_match_in_policy", nullptr,
+      &server_args);
   grpc_authorization_policy_provider_release(provider);
-  cq_verifier* cqv = cq_verifier_create(f.cq);
+  test_deny_unauthorized_request(f);
 
-  gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-                               grpc_slice_from_static_string("/bar"), nullptr,
-                               deadline, nullptr);
-  GPR_ASSERT(c);
+  end_test(&f);
+  config.tear_down_data(&f);
+}
 
-  grpc_metadata_array_init(&initial_metadata_recv);
-  grpc_metadata_array_init(&trailing_metadata_recv);
+static void test_file_watcher_valid_policy_reload(
+    grpc_end2end_test_config config) {
+  const char* authz_policy =
+      "{"
+      "  \"name\": \"authz\","
+      "  \"allow_rules\": ["
+      "    {"
+      "      \"name\": \"allow_foo\","
+      "      \"request\": {"
+      "        \"paths\": ["
+      "          \"*/foo\""
+      "        ]"
+      "      }"
+      "    }"
+      "  ]"
+      "}";
+  grpc_core::testing::TmpFile tmp_policy(authz_policy);
+  grpc_status_code code = GRPC_STATUS_OK;
+  const char* error_details;
+  grpc_authorization_policy_provider* provider =
+      grpc_authorization_policy_provider_file_watcher_create(
+          tmp_policy.name().c_str(), /*refresh_interval_sec=*/1, &code,
+          &error_details);
+  GPR_ASSERT(GRPC_STATUS_OK == code);
+  grpc_arg args[] = {
+      grpc_channel_arg_pointer_create(
+          const_cast<char*>(GRPC_ARG_AUTHORIZATION_POLICY_PROVIDER), provider,
+          grpc_authorization_policy_provider_arg_vtable()),
+  };
+  grpc_channel_args server_args = {GPR_ARRAY_SIZE(args), args};
 
-  memset(ops, 0, sizeof(ops));
-  op = ops;
-  op->op = GRPC_OP_SEND_INITIAL_METADATA;
-  op->data.send_initial_metadata.count = 0;
-  op->flags = 0;
-  op->reserved = nullptr;
-  op++;
-  op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
-  op->flags = 0;
-  op->reserved = nullptr;
-  op++;
-  op->op = GRPC_OP_RECV_INITIAL_METADATA;
-  op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv;
-  op->flags = 0;
-  op->reserved = nullptr;
-  op++;
-  op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
-  op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
-  op->data.recv_status_on_client.status = &status;
-  op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.error_string = &error_string;
-  op->flags = 0;
-  op->reserved = nullptr;
-  op++;
-  error = grpc_call_start_batch(c, ops, static_cast<size_t>(op - ops), tag(1),
-                                nullptr);
-  GPR_ASSERT(GRPC_CALL_OK == error);
-  CQ_EXPECT_COMPLETION(cqv, tag(1), 1);
-  cq_verify(cqv);
+  grpc_end2end_test_fixture f = begin_test(
+      config, "test_file_watcher_valid_policy_reload", nullptr, &server_args);
+  grpc_authorization_policy_provider_release(provider);
+  test_allow_authorized_request(f);
+  // Replace existing policy in file with a different authorization policy.
+  authz_policy =
+      "{"
+      "  \"name\": \"authz\","
+      "  \"allow_rules\": ["
+      "    {"
+      "      \"name\": \"allow_bar\","
+      "      \"request\": {"
+      "        \"paths\": ["
+      "          \"*/bar\""
+      "        ]"
+      "      }"
+      "    }"
+      "  ],"
+      "  \"deny_rules\": ["
+      "    {"
+      "      \"name\": \"deny_foo\","
+      "      \"request\": {"
+      "        \"paths\": ["
+      "          \"*/foo\""
+      "        ]"
+      "      }"
+      "    }"
+      "  ]"
+      "}";
+  tmp_policy.RewriteFile(authz_policy);
+  // Wait 2 seconds for the provider's refresh thread to read the updated files.
+  gpr_sleep_until(grpc_timeout_seconds_to_deadline(2));
+  test_deny_unauthorized_request(f);
 
-  GPR_ASSERT(GRPC_STATUS_PERMISSION_DENIED == status);
-  GPR_ASSERT(0 ==
-             grpc_slice_str_cmp(details, "Unauthorized RPC request rejected."));
+  end_test(&f);
+  config.tear_down_data(&f);
+}
 
-  grpc_slice_unref(details);
-  gpr_free(const_cast<char*>(error_string));
-  grpc_metadata_array_destroy(&initial_metadata_recv);
-  grpc_metadata_array_destroy(&trailing_metadata_recv);
+static void test_file_watcher_invalid_policy_skip_reload(
+    grpc_end2end_test_config config) {
+  const char* authz_policy =
+      "{"
+      "  \"name\": \"authz\","
+      "  \"allow_rules\": ["
+      "    {"
+      "      \"name\": \"allow_foo\","
+      "      \"request\": {"
+      "        \"paths\": ["
+      "          \"*/foo\""
+      "        ]"
+      "      }"
+      "    }"
+      "  ]"
+      "}";
+  grpc_core::testing::TmpFile tmp_policy(authz_policy);
+  grpc_status_code code = GRPC_STATUS_OK;
+  const char* error_details;
+  grpc_authorization_policy_provider* provider =
+      grpc_authorization_policy_provider_file_watcher_create(
+          tmp_policy.name().c_str(), /*refresh_interval_sec=*/1, &code,
+          &error_details);
+  GPR_ASSERT(GRPC_STATUS_OK == code);
+  grpc_arg args[] = {
+      grpc_channel_arg_pointer_create(
+          const_cast<char*>(GRPC_ARG_AUTHORIZATION_POLICY_PROVIDER), provider,
+          grpc_authorization_policy_provider_arg_vtable()),
+  };
+  grpc_channel_args server_args = {GPR_ARRAY_SIZE(args), args};
 
-  grpc_call_unref(c);
-  cq_verifier_destroy(cqv);
+  grpc_end2end_test_fixture f =
+      begin_test(config, "test_file_watcher_invalid_policy_skip_reload",
+                 nullptr, &server_args);
+  grpc_authorization_policy_provider_release(provider);
+  test_allow_authorized_request(f);
+  // Replace exisiting policy in file with an invalid policy.
+  authz_policy = "{}";
+  tmp_policy.RewriteFile(authz_policy);
+  // Wait 2 seconds for the provider's refresh thread to read the updated files.
+  gpr_sleep_until(grpc_timeout_seconds_to_deadline(2));
+  test_allow_authorized_request(f);
+
+  end_test(&f);
+  config.tear_down_data(&f);
+}
+
+static void test_file_watcher_recovers_from_failure(
+    grpc_end2end_test_config config) {
+  const char* authz_policy =
+      "{"
+      "  \"name\": \"authz\","
+      "  \"allow_rules\": ["
+      "    {"
+      "      \"name\": \"allow_foo\","
+      "      \"request\": {"
+      "        \"paths\": ["
+      "          \"*/foo\""
+      "        ]"
+      "      }"
+      "    }"
+      "  ]"
+      "}";
+  grpc_core::testing::TmpFile tmp_policy(authz_policy);
+  grpc_status_code code = GRPC_STATUS_OK;
+  const char* error_details;
+  grpc_authorization_policy_provider* provider =
+      grpc_authorization_policy_provider_file_watcher_create(
+          tmp_policy.name().c_str(), /*refresh_interval_sec=*/1, &code,
+          &error_details);
+  GPR_ASSERT(GRPC_STATUS_OK == code);
+  grpc_arg args[] = {
+      grpc_channel_arg_pointer_create(
+          const_cast<char*>(GRPC_ARG_AUTHORIZATION_POLICY_PROVIDER), provider,
+          grpc_authorization_policy_provider_arg_vtable()),
+  };
+  grpc_channel_args server_args = {GPR_ARRAY_SIZE(args), args};
+
+  grpc_end2end_test_fixture f = begin_test(
+      config, "test_file_watcher_valid_policy_reload", nullptr, &server_args);
+  grpc_authorization_policy_provider_release(provider);
+  test_allow_authorized_request(f);
+  // Replace exisiting policy in file with an invalid policy.
+  authz_policy = "{}";
+  tmp_policy.RewriteFile(authz_policy);
+  // Wait 2 seconds for the provider's refresh thread to read the updated files.
+  gpr_sleep_until(grpc_timeout_seconds_to_deadline(2));
+  test_allow_authorized_request(f);
+  // Recover from reload errors, by replacing invalid policy in file with a
+  // valid policy.
+  authz_policy =
+      "{"
+      "  \"name\": \"authz\","
+      "  \"allow_rules\": ["
+      "    {"
+      "      \"name\": \"allow_bar\","
+      "      \"request\": {"
+      "        \"paths\": ["
+      "          \"*/bar\""
+      "        ]"
+      "      }"
+      "    }"
+      "  ],"
+      "  \"deny_rules\": ["
+      "    {"
+      "      \"name\": \"deny_foo\","
+      "      \"request\": {"
+      "        \"paths\": ["
+      "          \"*/foo\""
+      "        ]"
+      "      }"
+      "    }"
+      "  ]"
+      "}";
+  tmp_policy.RewriteFile(authz_policy);
+  // Wait 2 seconds for the provider's refresh thread to read the updated files.
+  gpr_sleep_until(grpc_timeout_seconds_to_deadline(2));
+  test_deny_unauthorized_request(f);
 
   end_test(&f);
   config.tear_down_data(&f);
 }
 
 void sdk_authz(grpc_end2end_test_config config) {
-  test_allow_authorized_request(config);
-  test_deny_unauthorized_request(config);
-  test_deny_request_no_match_in_policy(config);
+  test_static_init_allow_authorized_request(config);
+  test_static_init_deny_unauthorized_request(config);
+  test_static_init_deny_request_no_match_in_policy(config);
+  test_file_watcher_init_allow_authorized_request(config);
+  test_file_watcher_init_deny_unauthorized_request(config);
+  test_file_watcher_init_deny_request_no_match_in_policy(config);
+  test_file_watcher_valid_policy_reload(config);
+  test_file_watcher_invalid_policy_skip_reload(config);
+  test_file_watcher_recovers_from_failure(config);
 }
 
 void sdk_authz_pre_init(void) {}
index df5d40e..3a0b75f 100644 (file)
@@ -219,7 +219,6 @@ static void simple_request_body(grpc_end2end_test_config config,
   // not likely to change much. Some parts of the error, like time created,
   // obviously are not checked.
   GPR_ASSERT(nullptr != strstr(error_string, "xyz"));
-  GPR_ASSERT(nullptr != strstr(error_string, "description"));
   GPR_ASSERT(nullptr != strstr(error_string, "Error received from peer"));
   GPR_ASSERT(nullptr != strstr(error_string, "grpc_message"));
   GPR_ASSERT(nullptr != strstr(error_string, "grpc_status"));
index 965b7e5..35aba3f 100644 (file)
@@ -384,18 +384,24 @@ static void request_with_payload_template(
   CQ_EXPECT_COMPLETION(cqv, tag(100), true);
   cq_verify(cqv);
 
-  GPR_ASSERT(GPR_BITCOUNT(grpc_call_test_only_get_encodings_accepted_by_peer(
-                 s)) == GRPC_COMPRESS_ALGORITHMS_COUNT);
-  GPR_ASSERT(GPR_BITGET(grpc_call_test_only_get_encodings_accepted_by_peer(s),
+  GPR_ASSERT(grpc_core::BitCount(
+                 grpc_call_test_only_get_encodings_accepted_by_peer(s)) ==
+             GRPC_COMPRESS_ALGORITHMS_COUNT);
+  GPR_ASSERT(
+      grpc_core::GetBit(grpc_call_test_only_get_encodings_accepted_by_peer(s),
                         GRPC_COMPRESS_NONE) != 0);
-  GPR_ASSERT(GPR_BITGET(grpc_call_test_only_get_encodings_accepted_by_peer(s),
+  GPR_ASSERT(
+      grpc_core::GetBit(grpc_call_test_only_get_encodings_accepted_by_peer(s),
                         GRPC_COMPRESS_DEFLATE) != 0);
-  GPR_ASSERT(GPR_BITGET(grpc_call_test_only_get_encodings_accepted_by_peer(s),
+  GPR_ASSERT(
+      grpc_core::GetBit(grpc_call_test_only_get_encodings_accepted_by_peer(s),
                         GRPC_COMPRESS_GZIP) != 0);
-  GPR_ASSERT(GPR_BITGET(grpc_call_test_only_get_encodings_accepted_by_peer(s),
+  GPR_ASSERT(
+      grpc_core::GetBit(grpc_call_test_only_get_encodings_accepted_by_peer(s),
                         GRPC_COMPRESS_STREAM_GZIP) != 0);
-  GPR_ASSERT(GPR_BITCOUNT(grpc_call_test_only_get_encodings_accepted_by_peer(
-                 s)) == GRPC_COMPRESS_ALGORITHMS_COUNT);
+  GPR_ASSERT(grpc_core::BitCount(
+                 grpc_call_test_only_get_encodings_accepted_by_peer(s)) ==
+             GRPC_COMPRESS_ALGORITHMS_COUNT);
 
   memset(ops, 0, sizeof(ops));
   op = ops;
diff --git a/test/core/end2end/tests/workaround_cronet_compression.cc b/test/core/end2end/tests/workaround_cronet_compression.cc
deleted file mode 100644 (file)
index a2e7476..0000000
+++ /dev/null
@@ -1,416 +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 <string.h>
-
-#include <grpc/byte_buffer.h>
-#include <grpc/byte_buffer_reader.h>
-#include <grpc/compression.h>
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-#include <grpc/support/time.h>
-
-#include "src/core/lib/channel/channel_args.h"
-#include "src/core/lib/compression/compression_args.h"
-#include "src/core/lib/surface/call.h"
-#include "src/core/lib/surface/call_test_only.h"
-#include "src/core/lib/transport/static_metadata.h"
-#include "test/core/end2end/cq_verifier.h"
-#include "test/core/end2end/end2end_tests.h"
-
-static void* tag(intptr_t t) { return reinterpret_cast<void*>(t); }
-
-static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
-                                            const char* test_name,
-                                            grpc_channel_args* client_args,
-                                            grpc_channel_args* server_args) {
-  grpc_end2end_test_fixture f;
-  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
-  f = config.create_fixture(client_args, server_args);
-  config.init_server(&f, server_args);
-  config.init_client(&f, client_args);
-  return f;
-}
-
-static gpr_timespec n_seconds_from_now(int n) {
-  return grpc_timeout_seconds_to_deadline(n);
-}
-
-static gpr_timespec five_seconds_from_now(void) {
-  return n_seconds_from_now(5);
-}
-
-static void drain_cq(grpc_completion_queue* cq) {
-  grpc_event ev;
-  do {
-    ev = grpc_completion_queue_next(cq, five_seconds_from_now(), nullptr);
-  } while (ev.type != GRPC_QUEUE_SHUTDOWN);
-}
-
-static void shutdown_server(grpc_end2end_test_fixture* f) {
-  if (!f->server) return;
-  grpc_server_shutdown_and_notify(f->server, f->shutdown_cq, tag(1000));
-  GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_cq, tag(1000),
-                                         grpc_timeout_seconds_to_deadline(5),
-                                         nullptr)
-                 .type == GRPC_OP_COMPLETE);
-  grpc_server_destroy(f->server);
-  f->server = nullptr;
-}
-
-static void shutdown_client(grpc_end2end_test_fixture* f) {
-  if (!f->client) return;
-  grpc_channel_destroy(f->client);
-  f->client = nullptr;
-}
-
-static void end_test(grpc_end2end_test_fixture* f) {
-  shutdown_server(f);
-  shutdown_client(f);
-
-  grpc_completion_queue_shutdown(f->cq);
-  drain_cq(f->cq);
-  grpc_completion_queue_destroy(f->cq);
-  grpc_completion_queue_destroy(f->shutdown_cq);
-}
-
-static void request_with_payload_template(
-    grpc_end2end_test_config config, const char* test_name,
-    uint32_t client_send_flags_bitmask,
-    grpc_compression_algorithm default_client_channel_compression_algorithm,
-    grpc_compression_algorithm default_server_channel_compression_algorithm,
-    grpc_compression_algorithm expected_algorithm_from_client,
-    grpc_compression_algorithm expected_algorithm_from_server,
-    grpc_metadata* client_init_metadata, bool set_server_level,
-    grpc_compression_level server_compression_level, char* user_agent_override,
-    bool decompress_in_core) {
-  grpc_call* c;
-  grpc_call* s;
-  grpc_slice request_payload_slice;
-  grpc_byte_buffer* request_payload;
-  grpc_channel_args* client_args;
-  grpc_channel_args* server_args;
-  grpc_end2end_test_fixture f;
-  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;
-  cq_verifier* cqv;
-  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_channel_args_set_channel_default_compression_algorithm(
-      nullptr, default_client_channel_compression_algorithm);
-  server_args = grpc_channel_args_set_channel_default_compression_algorithm(
-      nullptr, default_server_channel_compression_algorithm);
-  if (!decompress_in_core) {
-    grpc_arg disable_decompression_in_core_arg =
-        grpc_channel_arg_integer_create(
-            const_cast<char*>(GRPC_ARG_ENABLE_PER_MESSAGE_DECOMPRESSION), 0);
-    grpc_channel_args* old_client_args = client_args;
-    grpc_channel_args* old_server_args = server_args;
-    client_args = grpc_channel_args_copy_and_add(
-        client_args, &disable_decompression_in_core_arg, 1);
-    server_args = grpc_channel_args_copy_and_add(
-        server_args, &disable_decompression_in_core_arg, 1);
-    grpc_channel_args_destroy(old_client_args);
-    grpc_channel_args_destroy(old_server_args);
-  }
-
-  if (user_agent_override) {
-    grpc_channel_args* client_args_old = client_args;
-    grpc_arg arg;
-    arg.key = const_cast<char*>(GRPC_ARG_PRIMARY_USER_AGENT_STRING);
-    arg.type = GRPC_ARG_STRING;
-    arg.value.string = user_agent_override;
-    client_args = grpc_channel_args_copy_and_add(client_args_old, &arg, 1);
-    grpc_channel_args_destroy(client_args_old);
-  }
-
-  f = begin_test(config, test_name, client_args, server_args);
-  cqv = cq_verifier_create(f.cq);
-
-  gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-                               grpc_slice_from_static_string("/foo"), nullptr,
-                               deadline, nullptr);
-  GPR_ASSERT(c);
-
-  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;
-  if (client_init_metadata != nullptr) {
-    op->data.send_initial_metadata.count = 1;
-    op->data.send_initial_metadata.metadata = client_init_metadata;
-  } else {
-    op->data.send_initial_metadata.count = 0;
-  }
-  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), 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, tag(100));
-  GPR_ASSERT(GRPC_CALL_OK == error);
-  CQ_EXPECT_COMPLETION(cqv, tag(100), true);
-  cq_verify(cqv);
-
-  GPR_ASSERT(GPR_BITCOUNT(grpc_call_test_only_get_encodings_accepted_by_peer(
-                 s)) == GRPC_COMPRESS_ALGORITHMS_COUNT);
-  GPR_ASSERT(GPR_BITGET(grpc_call_test_only_get_encodings_accepted_by_peer(s),
-                        GRPC_COMPRESS_NONE) != 0);
-  GPR_ASSERT(GPR_BITGET(grpc_call_test_only_get_encodings_accepted_by_peer(s),
-                        GRPC_COMPRESS_DEFLATE) != 0);
-  GPR_ASSERT(GPR_BITGET(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;
-  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), tag(101),
-                                nullptr);
-  GPR_ASSERT(GRPC_CALL_OK == error);
-
-  for (int i = 0; i < 2; i++) {
-    request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1);
-    response_payload = grpc_raw_byte_buffer_create(&response_payload_slice, 1);
-
-    memset(ops, 0, sizeof(ops));
-    op = ops;
-    op->op = GRPC_OP_SEND_MESSAGE;
-    op->data.send_message.send_message = request_payload;
-    op->flags = client_send_flags_bitmask;
-    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), tag(2),
-                                  nullptr);
-    GPR_ASSERT(GRPC_CALL_OK == error);
-
-    memset(ops, 0, sizeof(ops));
-    op = ops;
-    op->op = GRPC_OP_RECV_MESSAGE;
-    op->data.recv_message.recv_message = &request_payload_recv;
-    op->flags = 0;
-    op->reserved = nullptr;
-    op++;
-    error = grpc_call_start_batch(s, ops, static_cast<size_t>(op - ops),
-                                  tag(102), nullptr);
-    GPR_ASSERT(GRPC_CALL_OK == error);
-    CQ_EXPECT_COMPLETION(cqv, tag(102), 1);
-    cq_verify(cqv);
-
-    GPR_ASSERT(request_payload_recv->type == GRPC_BB_RAW);
-    GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, request_str));
-    GPR_ASSERT(request_payload_recv->data.raw.compression ==
-               (decompress_in_core ? GRPC_COMPRESS_NONE
-                                   : expected_algorithm_from_client));
-
-    memset(ops, 0, sizeof(ops));
-    op = ops;
-    op->op = GRPC_OP_SEND_MESSAGE;
-    op->data.send_message.send_message = response_payload;
-    op->flags = 0;
-    op->reserved = nullptr;
-    op++;
-    error = grpc_call_start_batch(s, ops, static_cast<size_t>(op - ops),
-                                  tag(103), nullptr);
-    GPR_ASSERT(GRPC_CALL_OK == error);
-    CQ_EXPECT_COMPLETION(cqv, tag(103), 1);
-    CQ_EXPECT_COMPLETION(cqv, tag(2), 1);
-    cq_verify(cqv);
-
-    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));
-    }
-
-    grpc_byte_buffer_destroy(request_payload);
-    grpc_byte_buffer_destroy(response_payload);
-    grpc_byte_buffer_destroy(request_payload_recv);
-    grpc_byte_buffer_destroy(response_payload_recv);
-  }
-
-  grpc_slice_unref(request_payload_slice);
-  grpc_slice_unref(response_payload_slice);
-
-  memset(ops, 0, sizeof(ops));
-  op = ops;
-  op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
-  op->flags = 0;
-  op->reserved = nullptr;
-  op++;
-  error = grpc_call_start_batch(c, ops, static_cast<size_t>(op - ops), tag(3),
-                                nullptr);
-  GPR_ASSERT(GRPC_CALL_OK == error);
-
-  memset(ops, 0, sizeof(ops));
-  op = ops;
-  op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
-  op->data.send_status_from_server.trailing_metadata_count = 0;
-  op->data.send_status_from_server.status = GRPC_STATUS_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), tag(104),
-                                nullptr);
-  GPR_ASSERT(GRPC_CALL_OK == error);
-
-  CQ_EXPECT_COMPLETION(cqv, tag(1), 1);
-  CQ_EXPECT_COMPLETION(cqv, tag(3), 1);
-  CQ_EXPECT_COMPLETION(cqv, tag(101), 1);
-  CQ_EXPECT_COMPLETION(cqv, tag(104), 1);
-  cq_verify(cqv);
-
-  GPR_ASSERT(status == GRPC_STATUS_OK);
-  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
-  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  GPR_ASSERT(was_cancelled == 0);
-
-  grpc_slice_unref(details);
-  grpc_metadata_array_destroy(&initial_metadata_recv);
-  grpc_metadata_array_destroy(&trailing_metadata_recv);
-  grpc_metadata_array_destroy(&request_metadata_recv);
-  grpc_call_details_destroy(&call_details);
-
-  grpc_call_unref(c);
-  grpc_call_unref(s);
-
-  cq_verifier_destroy(cqv);
-  grpc_channel_args_destroy(client_args);
-  grpc_channel_args_destroy(server_args);
-  end_test(&f);
-  config.tear_down_data(&f);
-}
-
-typedef struct workaround_cronet_compression_config {
-  char* user_agent_override;
-  grpc_compression_algorithm expected_algorithm_from_server;
-} workaround_cronet_compression_config;
-
-static workaround_cronet_compression_config workaround_configs[] = {
-    {nullptr, GRPC_COMPRESS_GZIP},
-    {const_cast<char*>(
-         "grpc-objc/1.3.0-dev grpc-c/3.0.0-dev (ios; cronet_http; gentle)"),
-     GRPC_COMPRESS_NONE},
-    {const_cast<char*>(
-         "grpc-objc/1.3.0-dev grpc-c/3.0.0-dev (ios; chttp2; gentle)"),
-     GRPC_COMPRESS_GZIP},
-    {const_cast<char*>(
-         "grpc-objc/1.4.0 grpc-c/3.0.0-dev (ios; cronet_http; gentle)"),
-     GRPC_COMPRESS_GZIP}};
-static const size_t workaround_configs_num =
-    sizeof(workaround_configs) / sizeof(*workaround_configs);
-
-static void test_workaround_cronet_compression(
-    grpc_end2end_test_config config) {
-  for (uint32_t i = 0; i < workaround_configs_num; i++) {
-    request_with_payload_template(
-        config, "test_invoke_request_with_compressed_payload", 0,
-        GRPC_COMPRESS_GZIP, GRPC_COMPRESS_GZIP, GRPC_COMPRESS_GZIP,
-        workaround_configs[i].expected_algorithm_from_server, nullptr, false,
-        /* ignored */ GRPC_COMPRESS_LEVEL_NONE,
-        workaround_configs[i].user_agent_override, true);
-    request_with_payload_template(
-        config,
-        "test_invoke_request_with_compressed_payload_with_compression_disabled",
-        0, GRPC_COMPRESS_GZIP, GRPC_COMPRESS_GZIP, GRPC_COMPRESS_GZIP,
-        workaround_configs[i].expected_algorithm_from_server, nullptr, false,
-        /* ignored */ GRPC_COMPRESS_LEVEL_NONE,
-        workaround_configs[i].user_agent_override, false);
-  }
-}
-
-void workaround_cronet_compression(grpc_end2end_test_config config) {
-  if (config.feature_mask & FEATURE_MASK_SUPPORTS_WORKAROUNDS) {
-    test_workaround_cronet_compression(config);
-  }
-}
-
-void workaround_cronet_compression_pre_init(void) {}
index 15bd7fe..af352f0 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright 2017 gRPC authors.
+# 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.
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-load("//bazel:grpc_build_system.bzl", "grpc_cc_test", "grpc_package")
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_package")
 
 licenses(["notice"])
 
@@ -28,3 +28,21 @@ grpc_cc_test(
         "//test/core/util:grpc_test_util",
     ],
 )
+
+grpc_cc_library(
+    name = "event_engine_test_suite",
+    testonly = 1,
+    srcs = [
+        "test_suite/event_engine_test.cc",
+        "test_suite/timer_test.cc",
+    ],
+    hdrs = ["test_suite/event_engine_test.h"],
+    external_deps = [
+        "gtest",
+    ],
+    language = "C++",
+    deps = [
+        "//:grpc",
+        "//test/core/util:grpc_test_util",
+    ],
+)
diff --git a/test/core/event_engine/test_suite/README.md b/test/core/event_engine/test_suite/README.md
new file mode 100644 (file)
index 0000000..8931a0c
--- /dev/null
@@ -0,0 +1,35 @@
+A reusable test suite for EventEngine implementations.
+
+To exercise a custom EventEngine, simply link against `:event_engine_test_suite`
+and provide a testing `main` function that sets a custom EventEngine factory:
+
+```
+#include "path/to/my_custom_event_engine.h"
+#include "src/core/event_engine/test_suite/event_engine_test.h"
+
+int main(int argc, char** argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  SetEventEngineFactory(
+      []() { return absl::make_unique<MyCustomEventEngine>(); });
+  auto result = RUN_ALL_TESTS();
+  return result;
+}
+```
+
+And add a target to the `BUILD` file:
+
+```
+grpc_cc_test(
+    name = "my_custom_event_engine_test",
+    srcs = ["test_suite/my_custom_event_engine_test.cc"],
+    external_deps = [
+        "gtest",
+    ],
+    language = "C++",
+    uses_polling = False,
+    deps = [
+        ":event_engine_test_suite",
+        "//:grpc",
+    ],
+)
+```
diff --git a/test/core/event_engine/test_suite/event_engine_test.cc b/test/core/event_engine/test_suite/event_engine_test.cc
new file mode 100644 (file)
index 0000000..5ba038f
--- /dev/null
@@ -0,0 +1,28 @@
+// 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 "test/core/event_engine/test_suite/event_engine_test.h"
+
+#include <gtest/gtest.h>
+
+#include <grpc/event_engine/event_engine.h>
+
+std::function<std::unique_ptr<grpc_event_engine::experimental::EventEngine>()>*
+    g_ee_factory = nullptr;
+
+void SetEventEngineFactory(
+    std::function<
+        std::unique_ptr<grpc_event_engine::experimental::EventEngine>()>
+        factory) {
+  testing::AddGlobalTestEnvironment(new EventEngineTestEnvironment(factory));
+}
diff --git a/test/core/event_engine/test_suite/event_engine_test.h b/test/core/event_engine/test_suite/event_engine_test.h
new file mode 100644 (file)
index 0000000..743217b
--- /dev/null
@@ -0,0 +1,60 @@
+// 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.
+
+#ifndef GRPC_TEST_CORE_EVENT_ENGINE_TEST_SUITE_EVENT_ENGINE_TEST_H
+#define GRPC_TEST_CORE_EVENT_ENGINE_TEST_SUITE_EVENT_ENGINE_TEST_H
+#include <gtest/gtest.h>
+
+#include <grpc/event_engine/event_engine.h>
+
+#include "src/core/lib/gprpp/sync.h"
+
+extern std::function<
+    std::unique_ptr<grpc_event_engine::experimental::EventEngine>()>*
+    g_ee_factory;
+
+// Manages the lifetime of the global EventEngine factory.
+class EventEngineTestEnvironment : public testing::Environment {
+ public:
+  explicit EventEngineTestEnvironment(
+      std::function<
+          std::unique_ptr<grpc_event_engine::experimental::EventEngine>()>
+          factory)
+      : factory_(factory) {}
+
+  void SetUp() override { g_ee_factory = &factory_; }
+
+  void TearDown() override { g_ee_factory = nullptr; }
+
+ private:
+  std::function<std::unique_ptr<grpc_event_engine::experimental::EventEngine>()>
+      factory_;
+};
+
+class EventEngineTest : public testing::Test {
+ protected:
+  std::unique_ptr<grpc_event_engine::experimental::EventEngine>
+  NewEventEngine() {
+    GPR_ASSERT(g_ee_factory != nullptr);
+    return (*g_ee_factory)();
+  }
+};
+
+// Set a custom factory for the EventEngine test suite.
+void SetEventEngineFactory(
+    std::function<
+        std::unique_ptr<grpc_event_engine::experimental::EventEngine>()>
+        factory);
+
+#endif  // GRPC_TEST_CORE_EVENT_ENGINE_TEST_SUITE_EVENT_ENGINE_TEST_H
diff --git a/test/core/event_engine/test_suite/timer_test.cc b/test/core/event_engine/test_suite/timer_test.cc
new file mode 100644 (file)
index 0000000..088dc2c
--- /dev/null
@@ -0,0 +1,173 @@
+// 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 <random>
+#include <thread>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "absl/functional/bind_front.h"
+#include "absl/time/time.h"
+
+#include <grpc/event_engine/event_engine.h>
+#include <grpc/support/log.h>
+
+#include "src/core/lib/gprpp/sync.h"
+#include "test/core/event_engine/test_suite/event_engine_test.h"
+
+using ::testing::ElementsAre;
+
+class EventEngineTimerTest : public EventEngineTest {
+ public:
+  void ScheduleCheckCB(absl::Time when, std::atomic<int>* call_count,
+                       std::atomic<int>* fail_count, int total_expected);
+
+ protected:
+  grpc_core::Mutex mu_;
+  grpc_core::CondVar cv_;
+  bool signaled_ ABSL_GUARDED_BY(mu_) = false;
+};
+
+TEST_F(EventEngineTimerTest, ImmediateCallbackIsExecutedQuickly) {
+  auto engine = this->NewEventEngine();
+  grpc_core::MutexLock lock(&mu_);
+  engine->RunAt(absl::Now(), [this]() {
+    grpc_core::MutexLock lock(&mu_);
+    signaled_ = true;
+    cv_.Signal();
+  });
+  cv_.WaitWithTimeout(&mu_, absl::Seconds(5));
+  ASSERT_TRUE(signaled_);
+}
+
+TEST_F(EventEngineTimerTest, SupportsCancellation) {
+  auto engine = this->NewEventEngine();
+  auto handle = engine->RunAt(absl::InfiniteFuture(), []() {});
+  ASSERT_TRUE(engine->Cancel(handle));
+}
+
+TEST_F(EventEngineTimerTest, CancelledCallbackIsNotExecuted) {
+  {
+    auto engine = this->NewEventEngine();
+    auto handle = engine->RunAt(absl::InfiniteFuture(), [this]() {
+      grpc_core::MutexLock lock(&mu_);
+      signaled_ = true;
+    });
+    ASSERT_TRUE(engine->Cancel(handle));
+  }
+  // The engine is deleted, and all closures should have been flushed
+  grpc_core::MutexLock lock(&mu_);
+  ASSERT_FALSE(signaled_);
+}
+
+TEST_F(EventEngineTimerTest, TimersRespectScheduleOrdering) {
+  // Note: this is a brittle test if the first call to `RunAt` takes longer than
+  // the second callback's wait time.
+  std::vector<uint8_t> ordered;
+  uint8_t count = 0;
+  grpc_core::MutexLock lock(&mu_);
+  {
+    auto engine = this->NewEventEngine();
+    engine->RunAt(absl::Now() + absl::Seconds(1), [&]() {
+      grpc_core::MutexLock lock(&mu_);
+      ordered.push_back(2);
+      ++count;
+      cv_.Signal();
+    });
+    engine->RunAt(absl::Now(), [&]() {
+      grpc_core::MutexLock lock(&mu_);
+      ordered.push_back(1);
+      ++count;
+      cv_.Signal();
+    });
+    // Ensure both callbacks have run. Simpler than a mutex.
+    while (count != 2) {
+      cv_.WaitWithTimeout(&mu_, absl::Microseconds(100));
+    }
+  }
+  // The engine is deleted, and all closures should have been flushed beforehand
+  ASSERT_THAT(ordered, ElementsAre(1, 2));
+}
+
+TEST_F(EventEngineTimerTest, CancellingExecutedCallbackIsNoopAndReturnsFalse) {
+  auto engine = this->NewEventEngine();
+  grpc_core::MutexLock lock(&mu_);
+  auto handle = engine->RunAt(absl::Now(), [this]() {
+    grpc_core::MutexLock lock(&mu_);
+    signaled_ = true;
+    cv_.Signal();
+  });
+  cv_.WaitWithTimeout(&mu_, absl::Seconds(10));
+  ASSERT_TRUE(signaled_);
+  // The callback has run, and now we'll try to cancel it.
+  ASSERT_FALSE(engine->Cancel(handle));
+}
+
+void EventEngineTimerTest::ScheduleCheckCB(absl::Time when,
+                                           std::atomic<int>* call_count,
+                                           std::atomic<int>* fail_count,
+                                           int total_expected) {
+  // TODO(hork): make the EventEngine the time source of truth! libuv supports
+  // millis, absl::Time reports in nanos. This generic test will be hard-coded
+  // to the lowest common denominator until EventEngines can compare relative
+  // times with supported resolution.
+  int64_t now_millis = absl::ToUnixMillis(absl::Now());
+  int64_t when_millis = absl::ToUnixMillis(when);
+  EXPECT_LE(when_millis, now_millis);
+  if (when_millis > now_millis) ++(*fail_count);
+  if (++(*call_count) == total_expected) {
+    grpc_core::MutexLock lock(&mu_);
+    signaled_ = true;
+    cv_.Signal();
+  }
+}
+
+TEST_F(EventEngineTimerTest, StressTestTimersNotCalledBeforeScheduled) {
+  auto engine = this->NewEventEngine();
+  constexpr int thread_count = 100;
+  constexpr int call_count_per_thread = 100;
+  constexpr float timeout_min_seconds = 1;
+  constexpr float timeout_max_seconds = 10;
+  std::atomic<int> call_count{0};
+  std::atomic<int> failed_call_count{0};
+  std::vector<std::thread> threads;
+  threads.reserve(thread_count);
+  for (int thread_n = 0; thread_n < thread_count; ++thread_n) {
+    threads.emplace_back([&]() {
+      std::random_device rd;
+      std::mt19937 gen(rd());
+      std::uniform_real_distribution<> dis(timeout_min_seconds,
+                                           timeout_max_seconds);
+      for (int call_n = 0; call_n < call_count_per_thread; ++call_n) {
+        absl::Time when = absl::Now() + absl::Seconds(dis(gen));
+        engine->RunAt(
+            when, absl::bind_front(&EventEngineTimerTest::ScheduleCheckCB, this,
+                                   when, &call_count, &failed_call_count,
+                                   thread_count * call_count_per_thread));
+      }
+    });
+  }
+  for (auto& t : threads) {
+    t.join();
+  }
+  grpc_core::MutexLock lock(&mu_);
+  // to protect against spurious wakeups.
+  while (!signaled_) {
+    cv_.Wait(&mu_);
+  }
+  gpr_log(GPR_DEBUG, "failed timer count: %d of %d", failed_call_count.load(),
+          thread_count * call_count);
+  ASSERT_EQ(0, failed_call_count.load());
+}
index d037142..a1ebec9 100644 (file)
@@ -16,7 +16,7 @@ load("//bazel:grpc_build_system.bzl", "grpc_cc_binary", "grpc_cc_library", "grpc
 
 grpc_package(name = "test/core/fling")
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
 
index 21b5891..f9d2392 100644 (file)
@@ -14,7 +14,7 @@
 
 load("//bazel:grpc_build_system.bzl", "grpc_cc_binary", "grpc_cc_library", "grpc_cc_test", "grpc_package")
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 grpc_package(name = "test/core/gpr")
 
@@ -148,10 +148,12 @@ grpc_cc_test(
 grpc_cc_test(
     name = "useful_test",
     srcs = ["useful_test.cc"],
+    external_deps = ["gtest"],
     language = "C++",
     uses_polling = False,
     deps = [
-        "//:gpr",
-        "//test/core/util:grpc_test_util",
+        "//:gpr_platform",
+        "//:useful",
+        "//test/core/util:grpc_suppressions",
     ],
 )
index 8be6100..2d7d670 100644 (file)
  *
  */
 
-#include <grpc/support/port_platform.h>
+#include <grpc/impl/codegen/port_platform.h>
 
 #include "src/core/lib/gpr/useful.h"
 
-#include <grpc/support/log.h>
+#include <gtest/gtest.h>
 
-#include "test/core/util/test_config.h"
+namespace grpc_core {
 
-int main(int argc, char** argv) {
+TEST(UsefulTest, ClampWorks) {
+  EXPECT_EQ(grpc_core::Clamp(1, 0, 2), 1);
+  EXPECT_EQ(grpc_core::Clamp(0, 0, 2), 0);
+  EXPECT_EQ(grpc_core::Clamp(2, 0, 2), 2);
+  EXPECT_EQ(grpc_core::Clamp(-1, 0, 2), 0);
+  EXPECT_EQ(grpc_core::Clamp(3, 0, 2), 2);
+}
+
+TEST(UsefulTest, Rotate) {
+  EXPECT_EQ(grpc_core::RotateLeft(0x80000001u, 1u), 3);
+  EXPECT_EQ(grpc_core::RotateRight(0x80000001u, 1u), 0xc0000000);
+}
+
+TEST(UsefulTest, ArraySize) {
   int four[4];
   int five[5];
+
+  EXPECT_EQ(GPR_ARRAY_SIZE(four), 4);
+  EXPECT_EQ(GPR_ARRAY_SIZE(five), 5);
+}
+
+TEST(UsefulTest, BitOps) {
   uint32_t bitset = 0;
-  grpc::testing::TestEnvironment env(argc, argv);
-
-  GPR_ASSERT(GPR_MIN(1, 2) == 1);
-  GPR_ASSERT(GPR_MAX(1, 2) == 2);
-  GPR_ASSERT(GPR_MIN(2, 1) == 1);
-  GPR_ASSERT(GPR_MAX(2, 1) == 2);
-  GPR_ASSERT(GPR_CLAMP(1, 0, 2) == 1);
-  GPR_ASSERT(GPR_CLAMP(0, 0, 2) == 0);
-  GPR_ASSERT(GPR_CLAMP(2, 0, 2) == 2);
-  GPR_ASSERT(GPR_CLAMP(-1, 0, 2) == 0);
-  GPR_ASSERT(GPR_CLAMP(3, 0, 2) == 2);
-  GPR_ASSERT(GPR_ROTL((uint32_t)0x80000001, 1) == 3);
-  GPR_ASSERT(GPR_ROTR((uint32_t)0x80000001, 1) == 0xc0000000);
-  GPR_ASSERT(GPR_ARRAY_SIZE(four) == 4);
-  GPR_ASSERT(GPR_ARRAY_SIZE(five) == 5);
-
-  GPR_ASSERT(GPR_BITCOUNT((1u << 31) - 1) == 31);
-  GPR_ASSERT(GPR_BITCOUNT(1u << 3) == 1);
-  GPR_ASSERT(GPR_BITCOUNT(0) == 0);
-
-  GPR_ASSERT(GPR_BITSET(&bitset, 3) == 8);
-  GPR_ASSERT(GPR_BITCOUNT(bitset) == 1);
-  GPR_ASSERT(GPR_BITGET(bitset, 3) == 1);
-  GPR_ASSERT(GPR_BITSET(&bitset, 1) == 10);
-  GPR_ASSERT(GPR_BITCOUNT(bitset) == 2);
-  GPR_ASSERT(GPR_BITCLEAR(&bitset, 3) == 2);
-  GPR_ASSERT(GPR_BITCOUNT(bitset) == 1);
-  GPR_ASSERT(GPR_BITGET(bitset, 3) == 0);
-
-  return 0;
+
+  EXPECT_EQ(grpc_core::BitCount((1u << 31) - 1), 31);
+  EXPECT_EQ(grpc_core::BitCount(1u << 3), 1);
+  EXPECT_EQ(grpc_core::BitCount(0), 0);
+  EXPECT_EQ(grpc_core::SetBit(&bitset, 3), 8);
+  EXPECT_EQ(grpc_core::BitCount(bitset), 1);
+  EXPECT_EQ(grpc_core::GetBit(bitset, 3), 1);
+  EXPECT_EQ(grpc_core::SetBit(&bitset, 1), 10);
+  EXPECT_EQ(grpc_core::BitCount(bitset), 2);
+  EXPECT_EQ(grpc_core::ClearBit(&bitset, 3), 2);
+  EXPECT_EQ(grpc_core::BitCount(bitset), 1);
+  EXPECT_EQ(grpc_core::GetBit(bitset, 3), 0);
+  EXPECT_EQ(grpc_core::BitCount(std::numeric_limits<uint64_t>::max()), 64);
+}
+
+}  // namespace grpc_core
+
+int main(int argc, char** argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
 }
index 5401357..12d99c6 100644 (file)
 load("//bazel:grpc_build_system.bzl", "grpc_cc_binary", "grpc_cc_library", "grpc_cc_test", "grpc_package")
 load("//bazel:custom_exec_properties.bzl", "LARGE_MACHINE")
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 grpc_package(name = "test/core/gprpp")
 
+load("//test/core/util:grpc_fuzzer.bzl", "grpc_proto_fuzzer")
+
 grpc_cc_test(
     name = "examine_stack_test",
     srcs = ["examine_stack_test.cc"],
@@ -283,3 +285,30 @@ grpc_cc_test(
         "//test/core/util:grpc_suppressions",
     ],
 )
+
+grpc_cc_test(
+    name = "chunked_vector_test",
+    srcs = ["chunked_vector_test.cc"],
+    external_deps = ["gtest"],
+    language = "c++",
+    uses_polling = False,
+    deps = [
+        "//:chunked_vector",
+        "//:gpr_base",
+        "//test/core/util:grpc_suppressions",
+    ],
+)
+
+grpc_proto_fuzzer(
+    name = "chunked_vector_fuzzer",
+    srcs = ["chunked_vector_fuzzer.cc"],
+    corpus = "chunked_vector_corpora",
+    language = "C++",
+    proto = "chunked_vector_fuzzer.proto",
+    tags = ["no_windows"],
+    uses_polling = False,
+    deps = [
+        "//:chunked_vector",
+        "//test/core/util:grpc_test_util",
+    ],
+)
index 88f365c..dd6204e 100644 (file)
 
 #include "src/core/lib/gprpp/bitset.h"
 
+#include <random>
+
 #include <gtest/gtest.h>
 
 namespace grpc_core {
 namespace testing {
 
 // Stand in type to make the size to test a type
-template <std::size_t K>
+template <size_t K>
 struct Size {
-  static constexpr std::size_t kBits = K;
+  static constexpr size_t kBits = K;
 };
 
 using TestSizes = ::testing::Types<
@@ -53,27 +55,48 @@ TYPED_TEST(BitSetTest, NoneAtInit) {
 }
 
 TYPED_TEST(BitSetTest, OneBit) {
-  constexpr std::size_t kBits = TypeParam::kBits;
-  for (std::size_t i = 0; i < kBits; i++) {
+  constexpr size_t kBits = TypeParam::kBits;
+  for (size_t i = 0; i < kBits; i++) {
     BitSet<kBits> b;
     b.set(i);
     EXPECT_FALSE(b.none());
-    for (std::size_t j = 0; j < kBits; j++) {
+    for (size_t j = 0; j < kBits; j++) {
       EXPECT_EQ(b.is_set(j), i == j);
     }
   }
 }
 
 TYPED_TEST(BitSetTest, AllSet) {
-  constexpr std::size_t kBits = TypeParam::kBits;
+  constexpr size_t kBits = TypeParam::kBits;
   BitSet<kBits> b;
-  for (std::size_t i = 0; i < kBits; i++) {
+  for (size_t i = 0; i < kBits; i++) {
     EXPECT_FALSE(b.all());
     b.set(i);
   }
   EXPECT_TRUE(b.all());
 }
 
+TYPED_TEST(BitSetTest, Count) {
+  constexpr size_t kBits = TypeParam::kBits;
+  BitSet<kBits> b;
+  std::set<size_t> bits_set;
+  std::random_device rd;
+  std::uniform_int_distribution<size_t> dist(0, kBits - 1);
+  for (size_t i = 0; i < 4 * kBits; i++) {
+    size_t bit = dist(rd);
+    bits_set.insert(bit);
+    b.set(bit);
+    EXPECT_EQ(b.count(), bits_set.size());
+  }
+}
+
+TEST(EmptyBitSet, Empty) {
+  BitSet<0> b;
+  EXPECT_TRUE(b.all());
+  EXPECT_TRUE(b.none());
+  EXPECT_EQ(b.count(), 0);
+}
+
 }  // namespace testing
 }  // namespace grpc_core
 
diff --git a/test/core/gprpp/chunked_vector_corpora/crash-a0868ce3a0f76feefcc715148ed9e71fa0738c2a b/test/core/gprpp/chunked_vector_corpora/crash-a0868ce3a0f76feefcc715148ed9e71fa0738c2a
new file mode 100644 (file)
index 0000000..f8a94db
--- /dev/null
@@ -0,0 +1,14 @@
+actions {
+  move {
+    from: 875700282
+    to: 3473408
+  }
+}
+actions {
+  emplace_back {
+  }
+}
+actions {
+  clear {
+  }
+}
diff --git a/test/core/gprpp/chunked_vector_corpora/testcase-5405829431427072 b/test/core/gprpp/chunked_vector_corpora/testcase-5405829431427072
new file mode 100644 (file)
index 0000000..6ec84ff
--- /dev/null
@@ -0,0 +1,79 @@
+actions {
+  emplace_back {
+  }
+}
+actions {
+  emplace_back {
+  }
+}
+actions {
+  emplace_back {
+  }
+}
+actions {
+  emplace_back {
+  }
+}
+actions {
+  emplace_back {
+  }
+}
+actions {
+  emplace_back {
+    value: 2
+  }
+}
+actions {
+  emplace_back {
+  }
+}
+actions {
+  emplace_back {
+  }
+}
+actions {
+  emplace_back {
+  }
+}
+actions {
+  emplace_back {
+    value: 537540660
+  }
+}
+actions {
+  emplace_back {
+  }
+}
+actions {
+  emplace_back {
+  }
+}
+actions {
+  emplace_back {
+  }
+}
+actions {
+  emplace_back {
+    value: 28929
+  }
+}
+actions {
+  emplace_back {
+  }
+}
+actions {
+  emplace_back {
+  }
+}
+actions {
+  emplace_back {
+  }
+}
+actions {
+  emplace_back {
+  }
+}
+actions {
+  pop_back {
+  }
+}
diff --git a/test/core/gprpp/chunked_vector_fuzzer.cc b/test/core/gprpp/chunked_vector_fuzzer.cc
new file mode 100644 (file)
index 0000000..1704e3e
--- /dev/null
@@ -0,0 +1,152 @@
+// 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 <vector>
+
+#include "src/core/lib/gprpp/chunked_vector.h"
+#include "src/libfuzzer/libfuzzer_macro.h"
+#include "test/core/gprpp/chunked_vector_fuzzer.pb.h"
+
+bool squelch = true;
+bool leak_check = true;
+
+static constexpr size_t kChunkSize = 17;
+using IntHdl = std::shared_ptr<int>;
+
+namespace grpc_core {
+struct Comparison {
+  explicit Comparison(Arena* arena) : chunked(arena) {}
+
+  ChunkedVector<IntHdl, kChunkSize> chunked;
+  std::vector<IntHdl> std;
+
+  // Check that both chunked and std are equivalent.
+  void AssertOk() const {
+    GPR_ASSERT(std.size() == chunked.size());
+    auto it_chunked = chunked.cbegin();
+    auto it_std = std.cbegin();
+    while (it_std != std.cend()) {
+      GPR_ASSERT(**it_std == **it_chunked);
+      ++it_chunked;
+      ++it_std;
+    }
+    GPR_ASSERT(it_chunked == chunked.cend());
+  }
+};
+
+class Fuzzer {
+ public:
+  Fuzzer() = default;
+  ~Fuzzer() = default;
+
+  void Act(const chunked_vector_fuzzer::Action& action) {
+    switch (action.action_type_case()) {
+      case chunked_vector_fuzzer::Action::kEmplaceBack: {
+        // Add some value to the back of a comparison, assert that both vectors
+        // are equivalent.
+        auto* c = Mutate(action.emplace_back().vector());
+        c->chunked.EmplaceBack(
+            std::make_shared<int>(action.emplace_back().value()));
+        c->std.emplace_back(
+            std::make_shared<int>(action.emplace_back().value()));
+        c->AssertOk();
+      } break;
+      case chunked_vector_fuzzer::Action::kPopBack: {
+        // Remove some value to the back of a comparison, assert that both
+        // vectors are equivalent.
+        auto* c = Mutate(action.pop_back().vector());
+        if (c->chunked.size() > 0) {
+          c->chunked.PopBack();
+          c->std.pop_back();
+          c->AssertOk();
+        }
+      } break;
+      case chunked_vector_fuzzer::Action::kCopy: {
+        // Copy one vector into another, assert both everything stays
+        // equivalent.
+        auto it_from = vectors_.find(action.copy().from());
+        if (it_from == vectors_.end()) {
+          it_from =
+              vectors_.emplace(action.copy().from(), Comparison(arena_.get()))
+                  .first;
+        }
+        auto it_to = vectors_.find(action.copy().to());
+        if (it_to == vectors_.end()) {
+          it_to = vectors_.emplace(action.copy().to(), it_from->second).first;
+        } else {
+          it_to->second = it_from->second;
+        }
+        it_from->second.AssertOk();
+        it_to->second.AssertOk();
+      } break;
+      case chunked_vector_fuzzer::Action::kMove: {
+        // Move one vector into another, assert both everything stays
+        // equivalent.
+        auto it_from = vectors_.find(action.move().from());
+        if (it_from == vectors_.end()) {
+          it_from =
+              vectors_.emplace(action.move().from(), Comparison(arena_.get()))
+                  .first;
+        }
+        auto it_to = vectors_.find(action.move().to());
+        if (it_to == vectors_.end()) {
+          it_to =
+              vectors_.emplace(action.move().to(), std::move(it_from->second))
+                  .first;
+        } else {
+          it_to->second = it_from->second;
+        }
+        it_from->second.AssertOk();
+        it_to->second.AssertOk();
+      } break;
+      case chunked_vector_fuzzer::Action::kClear: {
+        // Clear a vector, assert that both underlying vectors are equivalent.
+        auto* c = Mutate(action.clear().vector());
+        c->chunked.Clear();
+        c->std.clear();
+        c->AssertOk();
+      } break;
+      case chunked_vector_fuzzer::Action::kSwap: {
+        // Swap two vectors, assert that both underlying vectors are equivalent.
+        auto* from = Mutate(action.swap().from());
+        auto* to = Mutate(action.swap().to());
+        from->chunked.Swap(&to->chunked);
+        from->std.swap(to->std);
+        from->AssertOk();
+      } break;
+      case chunked_vector_fuzzer::Action::ACTION_TYPE_NOT_SET:
+        break;
+    }
+  }
+
+ private:
+  Comparison* Mutate(int index) {
+    auto it = vectors_.find(index);
+    if (it != vectors_.end()) {
+      return &it->second;
+    }
+    return &vectors_.emplace(index, Comparison(arena_.get())).first->second;
+  }
+
+  ScopedArenaPtr arena_ = MakeScopedArena(128);
+  std::map<int, Comparison> vectors_;
+};
+}  // namespace grpc_core
+
+DEFINE_PROTO_FUZZER(const chunked_vector_fuzzer::Msg& msg) {
+  grpc_core::Fuzzer fuzzer;
+  for (int i = 0; i < msg.actions_size(); i++) {
+    fuzzer.Act(msg.actions(i));
+  }
+}
diff --git a/test/core/gprpp/chunked_vector_fuzzer.proto b/test/core/gprpp/chunked_vector_fuzzer.proto
new file mode 100644 (file)
index 0000000..236b464
--- /dev/null
@@ -0,0 +1,50 @@
+// 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.
+syntax = "proto3";
+
+package chunked_vector_fuzzer;
+
+message EmplaceBack {
+    int32 vector = 1;
+    int32 value = 2;
+}
+
+message PopBack {
+    int32 vector = 1;
+    int32 value = 2;
+}
+
+message Copy {
+    int32 from = 1;
+    int32 to = 2;
+}
+
+message ClearVector {
+    int32 vector = 1;
+}
+
+message Action {
+    oneof action_type {
+        EmplaceBack emplace_back = 1;
+        PopBack pop_back = 2;
+        Copy copy = 3;
+        Copy move = 4;
+        ClearVector clear = 5;
+        Copy swap = 6;
+    }
+}
+
+message Msg {
+    repeated Action actions = 1;
+}
diff --git a/test/core/gprpp/chunked_vector_test.cc b/test/core/gprpp/chunked_vector_test.cc
new file mode 100644 (file)
index 0000000..274bc0f
--- /dev/null
@@ -0,0 +1,154 @@
+// 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 "src/core/lib/gprpp/chunked_vector.h"
+
+#include <gtest/gtest.h>
+
+namespace grpc_core {
+namespace testing {
+
+static constexpr size_t kInitialArenaSize = 1024;
+static constexpr size_t kChunkSize = 3;
+
+TEST(ChunkedVector, Noop) {
+  auto arena = MakeScopedArena(kInitialArenaSize);
+  ChunkedVector<int, kChunkSize> v(arena.get());
+  EXPECT_EQ(0, v.size());
+}
+
+TEST(ChunkedVector, Stack) {
+  auto arena = MakeScopedArena(kInitialArenaSize);
+  ChunkedVector<int, kChunkSize> v(arena.get());
+
+  // Populate 2 chunks of memory, and 2/3 of a final chunk.
+  EXPECT_EQ(0, v.size());
+  v.EmplaceBack(1);
+  EXPECT_EQ(1, v.size());
+  v.EmplaceBack(2);
+  EXPECT_EQ(2, v.size());
+  v.EmplaceBack(3);
+  EXPECT_EQ(3, v.size());
+  v.EmplaceBack(4);
+  EXPECT_EQ(4, v.size());
+  v.EmplaceBack(5);
+  EXPECT_EQ(5, v.size());
+  v.EmplaceBack(6);
+  EXPECT_EQ(6, v.size());
+  v.EmplaceBack(7);
+  EXPECT_EQ(7, v.size());
+  v.EmplaceBack(8);
+  EXPECT_EQ(8, v.size());
+
+  // Now pop all of them out and check the expected ordering.
+  EXPECT_EQ(8, v.PopBack());
+  EXPECT_EQ(7, v.size());
+  EXPECT_EQ(7, v.PopBack());
+  EXPECT_EQ(6, v.size());
+  EXPECT_EQ(6, v.PopBack());
+  EXPECT_EQ(5, v.size());
+  EXPECT_EQ(5, v.PopBack());
+  EXPECT_EQ(4, v.size());
+  EXPECT_EQ(4, v.PopBack());
+  EXPECT_EQ(3, v.size());
+  EXPECT_EQ(3, v.PopBack());
+  EXPECT_EQ(2, v.size());
+  EXPECT_EQ(2, v.PopBack());
+  EXPECT_EQ(1, v.size());
+  EXPECT_EQ(1, v.PopBack());
+  EXPECT_EQ(0, v.size());
+}
+
+TEST(ChunkedVector, Iterate) {
+  auto arena = MakeScopedArena(kInitialArenaSize);
+  ChunkedVector<int, kChunkSize> v(arena.get());
+  v.EmplaceBack(1);
+  v.EmplaceBack(2);
+  v.EmplaceBack(3);
+  v.EmplaceBack(4);
+  v.EmplaceBack(5);
+  v.EmplaceBack(6);
+  v.EmplaceBack(7);
+  v.EmplaceBack(8);
+
+  auto it = v.begin();
+  EXPECT_EQ(1, *it);
+  ++it;
+  EXPECT_EQ(2, *it);
+  ++it;
+  EXPECT_EQ(3, *it);
+  ++it;
+  EXPECT_EQ(4, *it);
+  ++it;
+  EXPECT_EQ(5, *it);
+  ++it;
+  EXPECT_EQ(6, *it);
+  ++it;
+  EXPECT_EQ(7, *it);
+  ++it;
+  EXPECT_EQ(8, *it);
+  ++it;
+  EXPECT_EQ(v.end(), it);
+}
+
+TEST(ChunkedVector, ConstIterate) {
+  auto arena = MakeScopedArena(kInitialArenaSize);
+  ChunkedVector<int, kChunkSize> v(arena.get());
+  v.EmplaceBack(1);
+  v.EmplaceBack(2);
+  v.EmplaceBack(3);
+  v.EmplaceBack(4);
+  v.EmplaceBack(5);
+  v.EmplaceBack(6);
+  v.EmplaceBack(7);
+  v.EmplaceBack(8);
+
+  auto it = v.cbegin();
+  EXPECT_EQ(1, *it);
+  ++it;
+  EXPECT_EQ(2, *it);
+  ++it;
+  EXPECT_EQ(3, *it);
+  ++it;
+  EXPECT_EQ(4, *it);
+  ++it;
+  EXPECT_EQ(5, *it);
+  ++it;
+  EXPECT_EQ(6, *it);
+  ++it;
+  EXPECT_EQ(7, *it);
+  ++it;
+  EXPECT_EQ(8, *it);
+  ++it;
+  EXPECT_EQ(v.cend(), it);
+}
+
+TEST(ChunkedVector, Clear) {
+  auto arena = MakeScopedArena(kInitialArenaSize);
+  ChunkedVector<int, kChunkSize> v(arena.get());
+  v.EmplaceBack(1);
+  EXPECT_EQ(v.size(), 1);
+  v.Clear();
+  EXPECT_EQ(v.size(), 0);
+  EXPECT_EQ(v.begin(), v.end());
+}
+
+}  // namespace testing
+
+}  // namespace grpc_core
+
+int main(int argc, char** argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
index 0f59b2a..9e15386 100644 (file)
@@ -160,6 +160,16 @@ TEST(StatusUtilTest, AllocPtr) {
   }
 }
 
+TEST(StatusUtilTest, AllocHeapPtr) {
+  absl::Status statuses[] = {absl::OkStatus(), absl::CancelledError(),
+                             absl::AbortedError("Message")};
+  for (const auto& s : statuses) {
+    uintptr_t p = internal::StatusAllocHeapPtr(s);
+    EXPECT_EQ(s, internal::StatusGetFromHeapPtr(p));
+    internal::StatusFreeHeapPtr(p);
+  }
+}
+
 }  // namespace
 }  // namespace grpc_core
 
index 22cb905..a355a9c 100644 (file)
@@ -24,6 +24,8 @@
 namespace grpc_core {
 namespace testing {
 
+TEST(Table, InstantiateEmpty) { Table<>(); }
+
 TEST(Table, NoOp) {
   Table<int, double, std::string> t;
   EXPECT_EQ(t.get<int>(), nullptr);
@@ -112,6 +114,18 @@ TEST(Table, SameTypes) {
   EXPECT_EQ(t.get<2>(), nullptr);
 }
 
+TEST(Table, ForEach) {
+  Table<int, int, int> t;
+  t.set<0>(1);
+  t.set<1>(2);
+  t.set<2>(3);
+  int i = 1;
+  t.ForEach([&i](int x) {
+    EXPECT_EQ(x, i);
+    i++;
+  });
+}
+
 #if !defined(_MSC_VER)
 // Test suite proving this is memory efficient compared to
 // tuple<optional<Ts>...>
index 8ead408..49ff638 100644 (file)
@@ -16,7 +16,7 @@ load("//bazel:grpc_build_system.bzl", "grpc_cc_binary", "grpc_cc_library", "grpc
 
 grpc_package(name = "test/core/handshake")
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 grpc_cc_test(
     name = "client_ssl_test",
index 219eaf4..e1ffdd7 100644 (file)
@@ -16,7 +16,7 @@ load("//bazel:grpc_build_system.bzl", "grpc_cc_binary", "grpc_cc_library", "grpc
 
 grpc_package(name = "test/core/http")
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
 
@@ -60,7 +60,7 @@ grpc_fuzzer(
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
 
index b06aedd..5be930a 100644 (file)
@@ -15,7 +15,7 @@
 load("//bazel:grpc_build_system.bzl", "grpc_cc_binary", "grpc_cc_library", "grpc_cc_test", "grpc_package")
 load("//bazel:custom_exec_properties.bzl", "LARGE_MACHINE")
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
 
@@ -68,6 +68,9 @@ grpc_cc_test(
 grpc_cc_test(
     name = "error_test",
     srcs = ["error_test.cc"],
+    external_deps = [
+        "gtest",
+    ],
     language = "C++",
     uses_polling = False,
     deps = [
@@ -348,18 +351,6 @@ grpc_cc_test(
 )
 
 grpc_cc_test(
-    name = "udp_server_test",
-    srcs = ["udp_server_test.cc"],
-    language = "C++",
-    tags = ["no_windows"],
-    deps = [
-        "//:gpr",
-        "//:grpc",
-        "//test/core/util:grpc_test_util",
-    ],
-)
-
-grpc_cc_test(
     name = "stranded_event_test",
     srcs = ["stranded_event_test.cc"],
     external_deps = [
index 78a6df6..2a0e5a1 100644 (file)
@@ -347,7 +347,7 @@ void grpc_endpoint_tests(grpc_endpoint_test_config config,
   read_and_write_test(config, 10000000, 100000, 8192, false);
   read_and_write_test(config, 1000000, 100000, 1, false);
   read_and_write_test(config, 100000000, 100000, 1, true);
-  for (i = 1; i < 1000; i = GPR_MAX(i + 1, i * 5 / 4)) {
+  for (i = 1; i < 1000; i = std::max(i + 1, i * 5 / 4)) {
     read_and_write_test(config, 40320, i, i, false);
   }
   g_pollset = nullptr;
index cb3e30e..cbe80f2 100644 (file)
 
 #include <string.h>
 
+#include <gmock/gmock.h>
+
 #include <grpc/grpc.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 
 #include "test/core/util/test_config.h"
 
-static void test_set_get_int() {
+TEST(ErrorTest, SetGetInt) {
   grpc_error_handle error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test");
-  GPR_ASSERT(error);
+  EXPECT_NE(error, GRPC_ERROR_NONE);
   intptr_t i = 0;
-  GPR_ASSERT(grpc_error_get_int(error, GRPC_ERROR_INT_FILE_LINE, &i));
-  GPR_ASSERT(i);  // line set will never be 0
-  GPR_ASSERT(!grpc_error_get_int(error, GRPC_ERROR_INT_ERRNO, &i));
-  GPR_ASSERT(!grpc_error_get_int(error, GRPC_ERROR_INT_SIZE, &i));
+#ifndef NDEBUG
+  // GRPC_ERROR_INT_FILE_LINE is for debug only
+  EXPECT_TRUE(grpc_error_get_int(error, GRPC_ERROR_INT_FILE_LINE, &i));
+  EXPECT_TRUE(i);  // line set will never be 0
+#endif
+  EXPECT_TRUE(!grpc_error_get_int(error, GRPC_ERROR_INT_ERRNO, &i));
+  EXPECT_TRUE(!grpc_error_get_int(error, GRPC_ERROR_INT_SIZE, &i));
 
   intptr_t errnumber = 314;
   error = grpc_error_set_int(error, GRPC_ERROR_INT_ERRNO, errnumber);
-  GPR_ASSERT(grpc_error_get_int(error, GRPC_ERROR_INT_ERRNO, &i));
-  GPR_ASSERT(i == errnumber);
+  EXPECT_TRUE(grpc_error_get_int(error, GRPC_ERROR_INT_ERRNO, &i));
+  EXPECT_EQ(i, errnumber);
 
   intptr_t http = 2;
   error = grpc_error_set_int(error, GRPC_ERROR_INT_HTTP2_ERROR, http);
-  GPR_ASSERT(grpc_error_get_int(error, GRPC_ERROR_INT_HTTP2_ERROR, &i));
-  GPR_ASSERT(i == http);
+  EXPECT_TRUE(grpc_error_get_int(error, GRPC_ERROR_INT_HTTP2_ERROR, &i));
+  EXPECT_EQ(i, http);
 
   GRPC_ERROR_UNREF(error);
 }
 
-static void test_set_get_str() {
+TEST(ErrorTest, SetGetStr) {
   grpc_error_handle error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test");
 
-  grpc_slice str;
-  GPR_ASSERT(!grpc_error_get_str(error, GRPC_ERROR_STR_SYSCALL, &str));
-  GPR_ASSERT(!grpc_error_get_str(error, GRPC_ERROR_STR_TSI_ERROR, &str));
-
-  GPR_ASSERT(grpc_error_get_str(error, GRPC_ERROR_STR_FILE, &str));
-  GPR_ASSERT(strstr((char*)GRPC_SLICE_START_PTR(str),
-                    "error_test.c"));  // __FILE__ expands differently on
-                                       // Windows. All should at least
-                                       // contain error_test.c
-
-  GPR_ASSERT(grpc_error_get_str(error, GRPC_ERROR_STR_DESCRIPTION, &str));
-  GPR_ASSERT(!strncmp((char*)GRPC_SLICE_START_PTR(str), "Test",
-                      GRPC_SLICE_LENGTH(str)));
+  std::string str;
+  EXPECT_TRUE(!grpc_error_get_str(error, GRPC_ERROR_STR_SYSCALL, &str));
+  EXPECT_TRUE(!grpc_error_get_str(error, GRPC_ERROR_STR_TSI_ERROR, &str));
+#ifndef NDEBUG
+  // GRPC_ERROR_STR_FILE is for debug only
+  EXPECT_TRUE(grpc_error_get_str(error, GRPC_ERROR_STR_FILE, &str));
+  EXPECT_THAT(str, testing::HasSubstr("error_test.c"));
+  // __FILE__ expands differently on
+  // Windows. All should at least
+  // contain error_test.c
+#endif
+  EXPECT_TRUE(grpc_error_get_str(error, GRPC_ERROR_STR_DESCRIPTION, &str));
+  EXPECT_EQ(str, "Test");
 
-  error = grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE,
-                             grpc_slice_from_static_string("longer message"));
-  GPR_ASSERT(grpc_error_get_str(error, GRPC_ERROR_STR_GRPC_MESSAGE, &str));
-  GPR_ASSERT(!strncmp((char*)GRPC_SLICE_START_PTR(str), "longer message",
-                      GRPC_SLICE_LENGTH(str)));
+  error =
+      grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE, "longer message");
+  EXPECT_TRUE(grpc_error_get_str(error, GRPC_ERROR_STR_GRPC_MESSAGE, &str));
+  EXPECT_EQ(str, "longer message");
 
   GRPC_ERROR_UNREF(error);
 }
 
-static void test_copy_and_unref() {
+TEST(ErrorTest, CopyAndUnRef) {
   // error1 has one ref
-  grpc_error_handle error1 = grpc_error_set_str(
-      GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test"), GRPC_ERROR_STR_GRPC_MESSAGE,
-      grpc_slice_from_static_string("message"));
-  grpc_slice str;
-  GPR_ASSERT(grpc_error_get_str(error1, GRPC_ERROR_STR_GRPC_MESSAGE, &str));
-  GPR_ASSERT(!strncmp((char*)GRPC_SLICE_START_PTR(str), "message",
-                      GRPC_SLICE_LENGTH(str)));
+  grpc_error_handle error1 =
+      grpc_error_set_str(GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test"),
+                         GRPC_ERROR_STR_GRPC_MESSAGE, "message");
+  std::string str;
+  EXPECT_TRUE(grpc_error_get_str(error1, GRPC_ERROR_STR_GRPC_MESSAGE, &str));
+  EXPECT_EQ(str, "message");
 
   // error 1 has two refs
-  GRPC_ERROR_REF(error1);
+  (void)GRPC_ERROR_REF(error1);
   // this gives error3 a ref to the new error, and decrements error1 to one ref
-  grpc_error_handle error3 = grpc_error_set_str(
-      error1, GRPC_ERROR_STR_SYSCALL, grpc_slice_from_static_string("syscall"));
-  GPR_ASSERT(error3 != error1);  // should not be the same because of extra ref
-  GPR_ASSERT(grpc_error_get_str(error3, GRPC_ERROR_STR_GRPC_MESSAGE, &str));
-  GPR_ASSERT(!strncmp((char*)GRPC_SLICE_START_PTR(str), "message",
-                      GRPC_SLICE_LENGTH(str)));
+  grpc_error_handle error3 =
+      grpc_error_set_str(error1, GRPC_ERROR_STR_SYSCALL, "syscall");
+  EXPECT_NE(error3, error1);  // should not be the same because of extra ref
+  EXPECT_TRUE(grpc_error_get_str(error3, GRPC_ERROR_STR_GRPC_MESSAGE, &str));
+  EXPECT_EQ(str, "message");
 
   // error 1 should not have a syscall but 3 should
-  GPR_ASSERT(!grpc_error_get_str(error1, GRPC_ERROR_STR_SYSCALL, &str));
-  GPR_ASSERT(grpc_error_get_str(error3, GRPC_ERROR_STR_SYSCALL, &str));
-  GPR_ASSERT(!strncmp((char*)GRPC_SLICE_START_PTR(str), "syscall",
-                      GRPC_SLICE_LENGTH(str)));
+  EXPECT_TRUE(!grpc_error_get_str(error1, GRPC_ERROR_STR_SYSCALL, &str));
+  EXPECT_TRUE(grpc_error_get_str(error3, GRPC_ERROR_STR_SYSCALL, &str));
+  EXPECT_EQ(str, "syscall");
 
   GRPC_ERROR_UNREF(error1);
   GRPC_ERROR_UNREF(error3);
 }
 
-static void test_create_referencing() {
-  grpc_error_handle child = grpc_error_set_str(
-      GRPC_ERROR_CREATE_FROM_STATIC_STRING("Child"),
-      GRPC_ERROR_STR_GRPC_MESSAGE, grpc_slice_from_static_string("message"));
+TEST(ErrorTest, CreateReferencing) {
+  grpc_error_handle child =
+      grpc_error_set_str(GRPC_ERROR_CREATE_FROM_STATIC_STRING("Child"),
+                         GRPC_ERROR_STR_GRPC_MESSAGE, "message");
   grpc_error_handle parent =
       GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Parent", &child, 1);
-  GPR_ASSERT(parent);
+  EXPECT_NE(parent, GRPC_ERROR_NONE);
 
   GRPC_ERROR_UNREF(child);
   GRPC_ERROR_UNREF(parent);
 }
 
-static void test_create_referencing_many() {
+TEST(ErrorTest, CreateReferencingMany) {
   grpc_error_handle children[3];
-  children[0] = grpc_error_set_str(
-      GRPC_ERROR_CREATE_FROM_STATIC_STRING("Child1"),
-      GRPC_ERROR_STR_GRPC_MESSAGE, grpc_slice_from_static_string("message"));
+  children[0] =
+      grpc_error_set_str(GRPC_ERROR_CREATE_FROM_STATIC_STRING("Child1"),
+                         GRPC_ERROR_STR_GRPC_MESSAGE, "message");
   children[1] =
       grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("Child2"),
                          GRPC_ERROR_INT_HTTP2_ERROR, 5);
-  children[2] = grpc_error_set_str(
-      GRPC_ERROR_CREATE_FROM_STATIC_STRING("Child3"),
-      GRPC_ERROR_STR_GRPC_MESSAGE, grpc_slice_from_static_string("message 3"));
+  children[2] =
+      grpc_error_set_str(GRPC_ERROR_CREATE_FROM_STATIC_STRING("Child3"),
+                         GRPC_ERROR_STR_GRPC_MESSAGE, "message 3");
 
   grpc_error_handle parent =
       GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Parent", children, 3);
-  GPR_ASSERT(parent);
+  EXPECT_NE(parent, GRPC_ERROR_NONE);
 
   for (size_t i = 0; i < 3; ++i) {
     GRPC_ERROR_UNREF(children[i]);
@@ -138,29 +139,26 @@ static void test_create_referencing_many() {
   GRPC_ERROR_UNREF(parent);
 }
 
-static void print_error_string() {
+TEST(ErrorTest, PrintErrorString) {
   grpc_error_handle error =
       grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error"),
                          GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNIMPLEMENTED);
   error = grpc_error_set_int(error, GRPC_ERROR_INT_SIZE, 666);
-  error = grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE,
-                             grpc_slice_from_static_string("message"));
+  error = grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE, "message");
   // gpr_log(GPR_DEBUG, "%s", grpc_error_std_string(error).c_str());
   GRPC_ERROR_UNREF(error);
 }
 
-static void print_error_string_reference() {
+TEST(ErrorTest, PrintErrorStringReference) {
   grpc_error_handle children[2];
   children[0] = grpc_error_set_str(
       grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("1"),
                          GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNIMPLEMENTED),
-      GRPC_ERROR_STR_GRPC_MESSAGE,
-      grpc_slice_from_static_string("message for child 1"));
+      GRPC_ERROR_STR_GRPC_MESSAGE, "message for child 1");
   children[1] = grpc_error_set_str(
       grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("2sd"),
                          GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_INTERNAL),
-      GRPC_ERROR_STR_GRPC_MESSAGE,
-      grpc_slice_from_static_string("message for child 2"));
+      GRPC_ERROR_STR_GRPC_MESSAGE, "message for child 2");
 
   grpc_error_handle parent =
       GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Parent", children, 2);
@@ -171,23 +169,24 @@ static void print_error_string_reference() {
   GRPC_ERROR_UNREF(parent);
 }
 
-static void test_os_error() {
+TEST(ErrorTest, TestOsError) {
   int fake_errno = 5;
   const char* syscall = "syscall name";
   grpc_error_handle error = GRPC_OS_ERROR(fake_errno, syscall);
 
   intptr_t i = 0;
-  GPR_ASSERT(grpc_error_get_int(error, GRPC_ERROR_INT_ERRNO, &i));
-  GPR_ASSERT(i == fake_errno);
+  EXPECT_TRUE(grpc_error_get_int(error, GRPC_ERROR_INT_ERRNO, &i));
+  EXPECT_EQ(i, fake_errno);
 
-  grpc_slice str;
-  GPR_ASSERT(grpc_error_get_str(error, GRPC_ERROR_STR_SYSCALL, &str));
-  GPR_ASSERT(!strncmp((char*)GRPC_SLICE_START_PTR(str), syscall,
-                      GRPC_SLICE_LENGTH(str)));
+  std::string str;
+  EXPECT_TRUE(grpc_error_get_str(error, GRPC_ERROR_STR_SYSCALL, &str));
+  EXPECT_EQ(str, syscall);
   GRPC_ERROR_UNREF(error);
 }
 
-static void test_overflow() {
+TEST(ErrorTest, Overflow) {
+  // absl::Status doesn't have a limit so there is no overflow
+#ifndef GRPC_ERROR_IS_ABSEIL_STATUS
   grpc_error_handle error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Overflow");
 
   for (size_t i = 0; i < 150; ++i) {
@@ -196,37 +195,28 @@ static void test_overflow() {
   }
 
   error = grpc_error_set_int(error, GRPC_ERROR_INT_HTTP2_ERROR, 5);
-  error =
-      grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE,
-                         grpc_slice_from_static_string("message for child 2"));
+  error = grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE,
+                             "message for child 2");
   error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS, 5);
 
   intptr_t i;
-  GPR_ASSERT(grpc_error_get_int(error, GRPC_ERROR_INT_HTTP2_ERROR, &i));
-  GPR_ASSERT(i == 5);
-  GPR_ASSERT(!grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, &i));
+  EXPECT_TRUE(grpc_error_get_int(error, GRPC_ERROR_INT_HTTP2_ERROR, &i));
+  EXPECT_EQ(i, 5);
+  EXPECT_TRUE(!grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, &i));
 
   error = grpc_error_set_int(error, GRPC_ERROR_INT_HTTP2_ERROR, 10);
-  GPR_ASSERT(grpc_error_get_int(error, GRPC_ERROR_INT_HTTP2_ERROR, &i));
-  GPR_ASSERT(i == 10);
+  EXPECT_TRUE(grpc_error_get_int(error, GRPC_ERROR_INT_HTTP2_ERROR, &i));
+  EXPECT_EQ(i, 10);
 
   GRPC_ERROR_UNREF(error);
-  ;
+#endif
 }
 
 int main(int argc, char** argv) {
   grpc::testing::TestEnvironment env(argc, argv);
+  ::testing::InitGoogleTest(&argc, argv);
   grpc_init();
-  test_set_get_int();
-  test_set_get_str();
-  test_copy_and_unref();
-  print_error_string();
-  print_error_string_reference();
-  test_os_error();
-  test_create_referencing();
-  test_create_referencing_many();
-  test_overflow();
+  int retval = RUN_ALL_TESTS();
   grpc_shutdown();
-
-  return 0;
+  return retval;
 }
index faaafc9..ea7d00d 100644 (file)
@@ -135,7 +135,8 @@ static bool compare_slice_buffer_with_buffer(grpc_slice_buffer *slices, const ch
     r = accept(svr_fd, reinterpret_cast<struct sockaddr *>(addr),
                reinterpret_cast<socklen_t *>(&resolved_addr.len));
   } while (r == -1 && errno == EINTR);
-  XCTAssertGreaterThanOrEqual(r, 0);
+  XCTAssertGreaterThanOrEqual(r, 0, @"connection failed with return code %@ and errno %@", @(r),
+                              @(errno));
   svr_fd_ = r;
 
   /* wait for the connection callback to finish */
index b47e02f..d4ba3ca 100644 (file)
@@ -13,24 +13,6 @@ target 'CFStreamTests' do
   pod 'BoringSSL-GRPC', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c", :inhibit_warnings => true
 end
 
-pre_install do |installer|
-  # This is the gRPC-Core podspec object, as initialized by its podspec file.
-  grpc_core_spec = installer.pod_targets.find{|t| t.name == 'gRPC-Core'}.root_spec
-
-  # Copied from gRPC-Core.podspec, except for the adjusted src_root:
-  src_root = "$(PODS_ROOT)/../#{GRPC_LOCAL_SRC}"
-  grpc_core_spec.pod_target_xcconfig = {
-    'GRPC_SRC_ROOT' => src_root,
-    'HEADER_SEARCH_PATHS' => '"$(inherited)" "$(GRPC_SRC_ROOT)/include"',
-    'USER_HEADER_SEARCH_PATHS' => '"$(GRPC_SRC_ROOT)"',
-    # If we don't set these two settings, `include/grpc/support/time.h` and
-    # `src/core/lib/gpr/string.h` shadow the system `<time.h>` and `<string.h>`, breaking the
-    # build.
-    'USE_HEADERMAP' => 'NO',
-    'ALWAYS_SEARCH_USER_PATHS' => 'NO',
-  }
-end
-
 post_install do |installer|
   installer.pods_project.targets.each do |target|
     target.build_configurations.each do |config|
index a008dc5..f426245 100755 (executable)
@@ -16,7 +16,7 @@
 # Don't run this script standalone. Instead, run from the repository root:
 # ./tools/run_tests/run_tests.py -l objc
 
-set -e
+set -ev
 
 # CocoaPods requires the terminal to be using UTF-8 encoding.
 export LANG=en_US.UTF-8
@@ -29,19 +29,18 @@ hash xcodebuild 2>/dev/null || {
     exit 1
 }
 
-# clean the directory
-rm -rf Pods
-rm -rf CFStreamTests.xcworkspace
-rm -f Podfile.lock
+# clean up pod cache and existing pods
+rm -Rf Pods Podfile.lock CFStreamTests.xcworkspace
+pod cache clean --all
 
 echo "TIME:  $(date)"
-pod install
+pod install --verbose
 
 # ios-test-cfstream-tests flakes sometimes because of missing files in gRPC-Core,
 # add some log to help find out the root cause.
 # TODO(yulinliang): Delete it after solving the issue.
 if [ -d "./Pods/Headers/Public/gRPC-Core/grpc/impl/codegen" ]
-then 
+then
     echo "grpc/impl/codegen/ has been imported."
     number_of_files=$(find Pods/Headers/Public/gRPC-Core/grpc/impl/codegen -name "*.h" | wc -l)
     echo "The number of files in Pods/Headers/Public/gRPC-Core/grpc/impl/codegen/ is $number_of_files"
index d63ae78..0344d86 100644 (file)
@@ -51,7 +51,7 @@ class ProducerThread {
       GPR_ASSERT(items_[i]->done);
       delete items_[i];
     }
-    gpr_free(items_);
+    delete[] items_;
   }
 
   void Start() { thd_.Start(); }
@@ -59,8 +59,7 @@ class ProducerThread {
 
  private:
   void Run() {
-    items_ =
-        static_cast<WorkItem**>(gpr_zalloc(num_items_ * sizeof(WorkItem*)));
+    items_ = new WorkItem*[num_items_];
     for (int i = 0; i < num_items_; ++i) {
       items_[i] = new WorkItem(start_index_ + i);
       queue_->Put(items_[i]);
@@ -175,10 +174,8 @@ static void test_many_thread(void) {
   const int num_producer_threads = 10;
   const int num_consumer_threads = 20;
   grpc_core::InfLenFIFOQueue queue;
-  ProducerThread** producer_threads = static_cast<ProducerThread**>(
-      gpr_zalloc(num_producer_threads * sizeof(ProducerThread*)));
-  ConsumerThread** consumer_threads = static_cast<ConsumerThread**>(
-      gpr_zalloc(num_consumer_threads * sizeof(ConsumerThread*)));
+  ProducerThread** producer_threads = new ProducerThread*[num_producer_threads];
+  ConsumerThread** consumer_threads = new ConsumerThread*[num_consumer_threads];
 
   gpr_log(GPR_DEBUG, "Fork ProducerThreads...");
   for (int i = 0; i < num_producer_threads; ++i) {
@@ -211,11 +208,11 @@ static void test_many_thread(void) {
     // Destructor of ProducerThread will do the check of WorkItems
     delete producer_threads[i];
   }
-  gpr_free(producer_threads);
+  delete[] producer_threads;
   for (int i = 0; i < num_consumer_threads; ++i) {
     delete consumer_threads[i];
   }
-  gpr_free(consumer_threads);
+  delete[] consumer_threads;
   gpr_log(GPR_DEBUG, "Done.");
 }
 
index b960fc1..aa4b180 100644 (file)
@@ -91,7 +91,7 @@ static int compare_test_mutator(grpc_socket_mutator* a,
       reinterpret_cast<struct test_socket_mutator*>(a);
   struct test_socket_mutator* mb =
       reinterpret_cast<struct test_socket_mutator*>(b);
-  return GPR_ICMP(ma->option_value, mb->option_value);
+  return grpc_core::QsortCompare(ma->option_value, mb->option_value);
 }
 
 static const grpc_socket_mutator_vtable mutator_vtable = {
index 26ca182..4d7e371 100644 (file)
@@ -580,7 +580,7 @@ void run_tests(void) {
   write_test(100000, 1, true);
   write_test(100, 137, true);
 
-  for (i = 1; i < 1000; i = GPR_MAX(i + 1, i * 5 / 4)) {
+  for (i = 1; i < 1000; i = std::max(i + 1, i * 5 / 4)) {
     write_test(40320, i, false);
     write_test(40320, i, true);
   }
index 9c116d1..f83a370 100644 (file)
@@ -39,6 +39,7 @@
 #include <grpc/support/time.h>
 
 #include "src/core/lib/address_utils/sockaddr_utils.h"
+#include "src/core/lib/gprpp/memory.h"
 #include "src/core/lib/iomgr/error.h"
 #include "src/core/lib/iomgr/iomgr.h"
 #include "src/core/lib/iomgr/resolve_address.h"
@@ -456,8 +457,7 @@ int main(int argc, char** argv) {
   struct ifaddrs* ifa = nullptr;
   struct ifaddrs* ifa_it;
   // Zalloc dst_addrs to avoid oversized frames.
-  test_addrs* dst_addrs =
-      static_cast<test_addrs*>(gpr_zalloc(sizeof(*dst_addrs)));
+  test_addrs* dst_addrs = grpc_core::Zalloc<test_addrs>();
   grpc::testing::TestEnvironment env(argc, argv);
   grpc_init();
   // wait a few seconds to make sure IPv6 link-local addresses can be bound
index 60f4bdd..82da474 100644 (file)
@@ -140,7 +140,7 @@ static elem_struct* search_elems(elem_struct* elems, size_t count,
   for (size_t i = 0; i < count * 2; i++) {
     size_t a = static_cast<size_t>(rand()) % count;
     size_t b = static_cast<size_t>(rand()) % count;
-    GPR_SWAP(size_t, search_order[a], search_order[b]);
+    std::swap(search_order[a], search_order[b]);
   }
   elem_struct* out = nullptr;
   for (size_t i = 0; out == nullptr && i < count; i++) {
index 3113907..b7640ee 100644 (file)
@@ -224,7 +224,7 @@ int main(int argc, char** argv) {
     grpc::testing::TestEnvironment env(argc, argv);
     grpc_core::ExecCtx::GlobalInit();
     grpc_core::ExecCtx exec_ctx;
-    grpc_determine_iomgr_platform();
+    grpc_set_default_iomgr_platform();
     grpc_iomgr_platform_init();
     gpr_set_log_verbosity(GPR_LOG_SEVERITY_DEBUG);
     add_test();
@@ -245,7 +245,7 @@ int main(int argc, char** argv) {
                                          gpr_clock_type::GPR_CLOCK_MONOTONIC));
     grpc_core::ExecCtx::TestOnlyGlobalInit(new_start);
     grpc_core::ExecCtx exec_ctx;
-    grpc_determine_iomgr_platform();
+    grpc_set_default_iomgr_platform();
     grpc_iomgr_platform_init();
     gpr_set_log_verbosity(GPR_LOG_SEVERITY_DEBUG);
     long_running_service_cleanup_test();
diff --git a/test/core/iomgr/udp_server_test.cc b/test/core/iomgr/udp_server_test.cc
deleted file mode 100644 (file)
index 6eb1232..0000000
+++ /dev/null
@@ -1,393 +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 "src/core/lib/iomgr/port.h"
-
-// This test won't work except with posix sockets enabled
-#ifdef GRPC_POSIX_SOCKET_UDP_SERVER
-
-#include <netinet/in.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <unistd.h>
-
-#include <vector>
-
-#include <grpc/grpc.h>
-#include <grpc/support/alloc.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/gpr/useful.h"
-#include "src/core/lib/gprpp/memory.h"
-#include "src/core/lib/iomgr/ev_posix.h"
-#include "src/core/lib/iomgr/iomgr.h"
-#include "src/core/lib/iomgr/socket_factory_posix.h"
-#include "src/core/lib/iomgr/socket_utils_posix.h"
-#include "src/core/lib/iomgr/udp_server.h"
-#include "test/core/util/test_config.h"
-
-#define LOG_TEST(x) gpr_log(GPR_INFO, "%s", #x)
-
-static grpc_pollset* g_pollset;
-static gpr_mu* g_mu;
-static int g_number_of_reads = 0;
-static int g_number_of_writes = 0;
-static int g_number_of_bytes_read = 0;
-static int g_number_of_orphan_calls = 0;
-static int g_number_of_starts = 0;
-
-int rcv_buf_size = 1024;
-int snd_buf_size = 1024;
-
-static int g_num_listeners = 1;
-
-class TestGrpcUdpHandler : public GrpcUdpHandler {
- public:
-  TestGrpcUdpHandler(grpc_fd* emfd, void* user_data)
-      : GrpcUdpHandler(emfd, user_data), emfd_(emfd) {
-    g_number_of_starts++;
-  }
-  ~TestGrpcUdpHandler() override {}
-
- protected:
-  bool Read() override {
-    char read_buffer[512];
-    ssize_t byte_count;
-
-    gpr_mu_lock(g_mu);
-    byte_count =
-        recv(grpc_fd_wrapped_fd(emfd()), read_buffer, sizeof(read_buffer), 0);
-
-    g_number_of_reads++;
-    g_number_of_bytes_read += static_cast<int>(byte_count);
-
-    gpr_log(GPR_DEBUG, "receive %zu on handler %p", byte_count, this);
-    GPR_ASSERT(GRPC_LOG_IF_ERROR("pollset_kick",
-                                 grpc_pollset_kick(g_pollset, nullptr)));
-    gpr_mu_unlock(g_mu);
-    return false;
-  }
-
-  void OnCanWrite(void* /*user_data*/,
-                  grpc_closure* /*notify_on_write_closure*/) override {
-    gpr_mu_lock(g_mu);
-    g_number_of_writes++;
-
-    GPR_ASSERT(GRPC_LOG_IF_ERROR("pollset_kick",
-                                 grpc_pollset_kick(g_pollset, nullptr)));
-    gpr_mu_unlock(g_mu);
-  }
-
-  void OnFdAboutToOrphan(grpc_closure* orphan_fd_closure,
-                         void* /*user_data*/) override {
-    gpr_log(GPR_INFO, "gRPC FD about to be orphaned: %d",
-            grpc_fd_wrapped_fd(emfd()));
-    grpc_core::ExecCtx::Run(DEBUG_LOCATION, orphan_fd_closure, GRPC_ERROR_NONE);
-    g_number_of_orphan_calls++;
-  }
-
-  grpc_fd* emfd() { return emfd_; }
-
- private:
-  grpc_fd* emfd_;
-};
-
-class TestGrpcUdpHandlerFactory : public GrpcUdpHandlerFactory {
- public:
-  GrpcUdpHandler* CreateUdpHandler(grpc_fd* emfd, void* user_data) override {
-    gpr_log(GPR_INFO, "create udp handler for fd %d", grpc_fd_wrapped_fd(emfd));
-    return new TestGrpcUdpHandler(emfd, user_data);
-  }
-
-  void DestroyUdpHandler(GrpcUdpHandler* handler) override {
-    gpr_log(GPR_INFO, "Destroy handler");
-    delete reinterpret_cast<TestGrpcUdpHandler*>(handler);
-  }
-};
-
-TestGrpcUdpHandlerFactory handler_factory;
-
-struct test_socket_factory {
-  grpc_socket_factory base;
-  int number_of_socket_calls;
-  int number_of_bind_calls;
-};
-typedef struct test_socket_factory test_socket_factory;
-
-static int test_socket_factory_socket(grpc_socket_factory* factory, int domain,
-                                      int type, int protocol) {
-  test_socket_factory* f = reinterpret_cast<test_socket_factory*>(factory);
-  f->number_of_socket_calls++;
-  return socket(domain, type, protocol);
-}
-
-static int test_socket_factory_bind(grpc_socket_factory* factory, int sockfd,
-                                    const grpc_resolved_address* addr) {
-  test_socket_factory* f = reinterpret_cast<test_socket_factory*>(factory);
-  f->number_of_bind_calls++;
-  return bind(sockfd,
-              reinterpret_cast<struct sockaddr*>(const_cast<char*>(addr->addr)),
-              static_cast<socklen_t>(addr->len));
-}
-
-static int test_socket_factory_compare(grpc_socket_factory* a,
-                                       grpc_socket_factory* b) {
-  return GPR_ICMP(a, b);
-}
-
-static void test_socket_factory_destroy(grpc_socket_factory* factory) {
-  test_socket_factory* f = reinterpret_cast<test_socket_factory*>(factory);
-  gpr_free(f);
-}
-
-static const grpc_socket_factory_vtable test_socket_factory_vtable = {
-    test_socket_factory_socket, test_socket_factory_bind,
-    test_socket_factory_compare, test_socket_factory_destroy};
-
-static test_socket_factory* test_socket_factory_create(void) {
-  test_socket_factory* factory = static_cast<test_socket_factory*>(
-      gpr_malloc(sizeof(test_socket_factory)));
-  grpc_socket_factory_init(&factory->base, &test_socket_factory_vtable);
-  factory->number_of_socket_calls = 0;
-  factory->number_of_bind_calls = 0;
-  return factory;
-}
-
-static void destroy_pollset(void* p, grpc_error_handle /*error*/) {
-  grpc_pollset_destroy(static_cast<grpc_pollset*>(p));
-}
-
-static void shutdown_and_destroy_pollset() {
-  gpr_mu_lock(g_mu);
-  auto closure = GRPC_CLOSURE_CREATE(destroy_pollset, g_pollset,
-                                     grpc_schedule_on_exec_ctx);
-  grpc_pollset_shutdown(g_pollset, closure);
-  gpr_mu_unlock(g_mu);
-  /* Flush exec_ctx to run |destroyed| */
-  grpc_core::ExecCtx::Get()->Flush();
-}
-
-static void test_no_op(void) {
-  grpc_pollset_init(g_pollset, &g_mu);
-  grpc_core::ExecCtx exec_ctx;
-  grpc_udp_server* s = grpc_udp_server_create(nullptr);
-  LOG_TEST("test_no_op");
-  grpc_udp_server_destroy(s, nullptr);
-  shutdown_and_destroy_pollset();
-}
-
-static void test_no_op_with_start(void) {
-  grpc_pollset_init(g_pollset, &g_mu);
-  grpc_core::ExecCtx exec_ctx;
-  grpc_udp_server* s = grpc_udp_server_create(nullptr);
-  LOG_TEST("test_no_op_with_start");
-  std::vector<grpc_pollset*> empty_pollset;
-  grpc_udp_server_start(s, &empty_pollset, nullptr);
-  grpc_udp_server_destroy(s, nullptr);
-  shutdown_and_destroy_pollset();
-}
-
-static void test_no_op_with_port(void) {
-  grpc_pollset_init(g_pollset, &g_mu);
-  g_number_of_orphan_calls = 0;
-  grpc_core::ExecCtx exec_ctx;
-  grpc_resolved_address resolved_addr;
-  struct sockaddr_in* addr =
-      reinterpret_cast<struct sockaddr_in*>(resolved_addr.addr);
-  grpc_udp_server* s = grpc_udp_server_create(nullptr);
-  LOG_TEST("test_no_op_with_port");
-
-  memset(&resolved_addr, 0, sizeof(resolved_addr));
-  resolved_addr.len = static_cast<socklen_t>(sizeof(struct sockaddr_in));
-  addr->sin_family = AF_INET;
-  GPR_ASSERT(grpc_udp_server_add_port(s, &resolved_addr, rcv_buf_size,
-                                      snd_buf_size, &handler_factory,
-                                      g_num_listeners) > 0);
-
-  grpc_udp_server_destroy(s, nullptr);
-
-  /* The server haven't start listening, so no udp handler to be notified. */
-  GPR_ASSERT(g_number_of_orphan_calls == 0);
-  shutdown_and_destroy_pollset();
-}
-
-static void test_no_op_with_port_and_socket_factory(void) {
-  grpc_pollset_init(g_pollset, &g_mu);
-  g_number_of_orphan_calls = 0;
-  grpc_core::ExecCtx exec_ctx;
-  grpc_resolved_address resolved_addr;
-  struct sockaddr_in* addr =
-      reinterpret_cast<struct sockaddr_in*>(resolved_addr.addr);
-
-  test_socket_factory* socket_factory = test_socket_factory_create();
-  grpc_arg socket_factory_arg =
-      grpc_socket_factory_to_arg(&socket_factory->base);
-  grpc_channel_args* channel_args =
-      grpc_channel_args_copy_and_add(nullptr, &socket_factory_arg, 1);
-  grpc_udp_server* s = grpc_udp_server_create(channel_args);
-  grpc_channel_args_destroy(channel_args);
-
-  LOG_TEST("test_no_op_with_port_and_socket_factory");
-
-  memset(&resolved_addr, 0, sizeof(resolved_addr));
-  resolved_addr.len = static_cast<socklen_t>(sizeof(struct sockaddr_in));
-  addr->sin_family = AF_INET;
-  GPR_ASSERT(grpc_udp_server_add_port(s, &resolved_addr, rcv_buf_size,
-                                      snd_buf_size, &handler_factory,
-                                      g_num_listeners) > 0);
-  GPR_ASSERT(socket_factory->number_of_socket_calls == g_num_listeners);
-  GPR_ASSERT(socket_factory->number_of_bind_calls == g_num_listeners);
-
-  grpc_udp_server_destroy(s, nullptr);
-
-  grpc_socket_factory_unref(&socket_factory->base);
-
-  /* The server haven't start listening, so no udp handler to be notified. */
-  GPR_ASSERT(g_number_of_orphan_calls == 0);
-  shutdown_and_destroy_pollset();
-}
-
-static void test_no_op_with_port_and_start(void) {
-  grpc_pollset_init(g_pollset, &g_mu);
-  g_number_of_orphan_calls = 0;
-  grpc_core::ExecCtx exec_ctx;
-  grpc_resolved_address resolved_addr;
-  struct sockaddr_in* addr =
-      reinterpret_cast<struct sockaddr_in*>(resolved_addr.addr);
-  grpc_udp_server* s = grpc_udp_server_create(nullptr);
-  LOG_TEST("test_no_op_with_port_and_start");
-
-  memset(&resolved_addr, 0, sizeof(resolved_addr));
-  resolved_addr.len = static_cast<socklen_t>(sizeof(struct sockaddr_in));
-  addr->sin_family = AF_INET;
-  GPR_ASSERT(grpc_udp_server_add_port(s, &resolved_addr, rcv_buf_size,
-                                      snd_buf_size, &handler_factory,
-                                      g_num_listeners) > 0);
-
-  std::vector<grpc_pollset*> empty_pollset;
-  grpc_udp_server_start(s, &empty_pollset, nullptr);
-  GPR_ASSERT(g_number_of_starts == g_num_listeners);
-  grpc_udp_server_destroy(s, nullptr);
-
-  /* The server had a single FD, which is orphaned exactly once in *
-   * grpc_udp_server_destroy. */
-  GPR_ASSERT(g_number_of_orphan_calls == g_num_listeners);
-  shutdown_and_destroy_pollset();
-}
-
-static void test_receive(int number_of_clients) {
-  grpc_pollset_init(g_pollset, &g_mu);
-  grpc_core::ExecCtx exec_ctx;
-  grpc_resolved_address resolved_addr;
-  struct sockaddr_storage* addr =
-      reinterpret_cast<struct sockaddr_storage*>(resolved_addr.addr);
-  int clifd, svrfd;
-  grpc_udp_server* s = grpc_udp_server_create(nullptr);
-  int i;
-  grpc_millis deadline;
-  LOG_TEST("test_receive");
-  gpr_log(GPR_INFO, "clients=%d", number_of_clients);
-
-  g_number_of_bytes_read = 0;
-  g_number_of_orphan_calls = 0;
-
-  memset(&resolved_addr, 0, sizeof(resolved_addr));
-  resolved_addr.len = static_cast<socklen_t>(sizeof(struct sockaddr_storage));
-  addr->ss_family = AF_INET;
-  GPR_ASSERT(grpc_udp_server_add_port(s, &resolved_addr, rcv_buf_size,
-                                      snd_buf_size, &handler_factory,
-                                      g_num_listeners) > 0);
-
-  svrfd = grpc_udp_server_get_fd(s, 0);
-  GPR_ASSERT(svrfd >= 0);
-  GPR_ASSERT(getsockname(svrfd, (struct sockaddr*)addr,
-                         (socklen_t*)&resolved_addr.len) == 0);
-  GPR_ASSERT(resolved_addr.len <= sizeof(struct sockaddr_storage));
-
-  std::vector<grpc_pollset*> test_pollsets;
-  test_pollsets.emplace_back(g_pollset);
-  grpc_udp_server_start(s, &test_pollsets, nullptr);
-
-  gpr_mu_lock(g_mu);
-
-  for (i = 0; i < number_of_clients; i++) {
-    deadline =
-        grpc_timespec_to_millis_round_up(grpc_timeout_seconds_to_deadline(10));
-
-    int number_of_bytes_read_before = g_number_of_bytes_read;
-    /* Create a socket, send a packet to the UDP server. */
-    clifd = socket(addr->ss_family, SOCK_DGRAM, 0);
-    GPR_ASSERT(clifd >= 0);
-    GPR_ASSERT(connect(clifd, (struct sockaddr*)addr,
-                       (socklen_t)resolved_addr.len) == 0);
-    GPR_ASSERT(5 == write(clifd, "hello", 5));
-    while (g_number_of_bytes_read < (number_of_bytes_read_before + 5) &&
-           deadline > grpc_core::ExecCtx::Get()->Now()) {
-      grpc_pollset_worker* worker = nullptr;
-      GPR_ASSERT(GRPC_LOG_IF_ERROR(
-          "pollset_work", grpc_pollset_work(g_pollset, &worker, deadline)));
-      gpr_mu_unlock(g_mu);
-      grpc_core::ExecCtx::Get()->Flush();
-      gpr_mu_lock(g_mu);
-    }
-    close(clifd);
-  }
-  GPR_ASSERT(g_number_of_bytes_read == 5 * number_of_clients);
-
-  gpr_mu_unlock(g_mu);
-
-  grpc_udp_server_destroy(s, nullptr);
-
-  /* The server had a single FD, which is orphaned exactly once in *
-   * grpc_udp_server_destroy. */
-  GPR_ASSERT(g_number_of_orphan_calls == g_num_listeners);
-  shutdown_and_destroy_pollset();
-}
-
-int main(int argc, char** argv) {
-  grpc::testing::TestEnvironment env(argc, argv);
-  grpc_init();
-  if (grpc_is_socket_reuse_port_supported()) {
-    g_num_listeners = 10;
-  }
-  {
-    grpc_core::ExecCtx exec_ctx;
-    g_pollset = static_cast<grpc_pollset*>(gpr_zalloc(grpc_pollset_size()));
-
-    test_no_op();
-    test_no_op_with_start();
-    test_no_op_with_port();
-    test_no_op_with_port_and_socket_factory();
-    test_no_op_with_port_and_start();
-    test_receive(1);
-    test_receive(10);
-
-    gpr_free(g_pollset);
-  }
-  grpc_shutdown();
-  return 0;
-}
-
-#else /* GRPC_POSIX_SOCKET_UDP_SERVER */
-
-int main(int argc, char** argv) { return 1; }
-
-#endif /* GRPC_POSIX_SOCKET_UDP_SERVER */
index 7a5ce5b..0925874 100644 (file)
@@ -107,8 +107,8 @@ TEST(WorkSerializerTest, ExecuteMany) {
 
 int main(int argc, char** argv) {
   grpc::testing::TestEnvironment env(argc, argv);
-  grpc_init();
   ::testing::InitGoogleTest(&argc, argv);
+  grpc_init();
   int retval = RUN_ALL_TESTS();
   grpc_shutdown();
   return retval;
index ab5b002..5ad82ce 100644 (file)
@@ -16,7 +16,7 @@ load("//bazel:grpc_build_system.bzl", "grpc_cc_binary", "grpc_cc_library", "grpc
 
 grpc_package(name = "test/core/json")
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
 
index a7c2c17..ce82754 100644 (file)
@@ -16,7 +16,7 @@ load("//bazel:grpc_build_system.bzl", "grpc_cc_binary", "grpc_cc_library", "grpc
 
 grpc_package(name = "test/core/nanopb")
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
 
index 04dcd11..259cb79 100644 (file)
@@ -22,7 +22,7 @@ grpc_package(
     ],
 )
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 grpc_cc_binary(
     name = "low_level_ping_pong",
index 3382027..838f21a 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-load("//bazel:grpc_build_system.bzl", "grpc_cc_test", "grpc_package")
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_package")
 
 licenses(["notice"])
 
 grpc_package(name = "test/core/promise")
 
+load("//test/core/util:grpc_fuzzer.bzl", "grpc_proto_fuzzer")
+
+grpc_cc_library(
+    name = "test_wakeup_schedulers",
+    testonly = True,
+    hdrs = ["test_wakeup_schedulers.h"],
+    external_deps = ["gtest"],
+    visibility = ["//test/core:__subpackages__"],
+    deps = [
+        "//:gpr_base",
+        "//test/core/util:grpc_suppressions",
+    ],
+)
+
 grpc_cc_test(
     name = "poll_test",
     srcs = ["poll_test.cc"],
@@ -121,6 +135,7 @@ grpc_cc_test(
     uses_polling = False,
     deps = [
         "//:loop",
+        "//:seq",
         "//test/core/util:grpc_suppressions",
     ],
 )
@@ -180,6 +195,7 @@ grpc_cc_test(
     language = "c++",
     uses_polling = False,
     deps = [
+        "test_wakeup_schedulers",
         "//:activity",
         "//:join",
         "//:promise",
@@ -196,6 +212,7 @@ grpc_cc_test(
     language = "c++",
     uses_polling = False,
     deps = [
+        "test_wakeup_schedulers",
         "//:join",
         "//:latch",
         "//:seq",
@@ -210,6 +227,7 @@ grpc_cc_test(
     language = "c++",
     uses_polling = False,
     deps = [
+        "test_wakeup_schedulers",
         "//:observable",
         "//:promise",
         "//:seq",
@@ -224,6 +242,7 @@ grpc_cc_test(
     language = "c++",
     uses_polling = False,
     deps = [
+        "test_wakeup_schedulers",
         "//:for_each",
         "//:join",
         "//:map",
@@ -241,6 +260,7 @@ grpc_cc_test(
     language = "c++",
     uses_polling = False,
     deps = [
+        "test_wakeup_schedulers",
         "//:join",
         "//:pipe",
         "//:promise",
@@ -248,3 +268,35 @@ grpc_cc_test(
         "//test/core/util:grpc_suppressions",
     ],
 )
+
+grpc_proto_fuzzer(
+    name = "promise_fuzzer",
+    srcs = ["promise_fuzzer.cc"],
+    corpus = "promise_fuzzer_corpus",
+    language = "C++",
+    proto = "promise_fuzzer.proto",
+    tags = ["no_windows"],
+    uses_polling = False,
+    deps = [
+        "//:activity",
+        "//:join",
+        "//:map",
+        "//:promise",
+        "//:race",
+        "//:seq",
+        "//test/core/util:grpc_test_util",
+    ],
+)
+
+grpc_cc_test(
+    name = "exec_ctx_wakeup_scheduler_test",
+    srcs = ["exec_ctx_wakeup_scheduler_test.cc"],
+    external_deps = ["gtest"],
+    language = "c++",
+    uses_polling = False,
+    deps = [
+        "//:activity",
+        "//:exec_ctx_wakeup_scheduler",
+        "//test/core/util:grpc_suppressions",
+    ],
+)
index 3375b2f..017a789 100644 (file)
@@ -21,6 +21,7 @@
 #include "src/core/lib/promise/promise.h"
 #include "src/core/lib/promise/seq.h"
 #include "src/core/lib/promise/wait_set.h"
+#include "test/core/promise/test_wakeup_schedulers.h"
 
 using testing::_;
 using testing::Mock;
@@ -30,11 +31,6 @@ using testing::StrictMock;
 
 namespace grpc_core {
 
-class MockCallbackScheduler {
- public:
-  MOCK_METHOD(void, Schedule, (std::function<void()>));
-};
-
 // A simple Barrier type: stalls progress until it is 'cleared'.
 class Barrier {
  public:
@@ -101,7 +97,7 @@ TEST(ActivityTest, ImmediatelyCompleteWithSuccess) {
   StrictMock<MockFunction<void(absl::Status)>> on_done;
   EXPECT_CALL(on_done, Call(absl::OkStatus()));
   MakeActivity(
-      [] { return [] { return absl::OkStatus(); }; }, NoCallbackScheduler(),
+      [] { return [] { return absl::OkStatus(); }; }, NoWakeupScheduler(),
       [&on_done](absl::Status status) { on_done.Call(std::move(status)); });
 }
 
@@ -109,8 +105,7 @@ TEST(ActivityTest, ImmediatelyCompleteWithFailure) {
   StrictMock<MockFunction<void(absl::Status)>> on_done;
   EXPECT_CALL(on_done, Call(absl::CancelledError()));
   MakeActivity(
-      [] { return [] { return absl::CancelledError(); }; },
-      NoCallbackScheduler(),
+      [] { return [] { return absl::CancelledError(); }; }, NoWakeupScheduler(),
       [&on_done](absl::Status status) { on_done.Call(std::move(status)); });
 }
 
@@ -119,7 +114,7 @@ TEST(ActivityTest, DropImmediately) {
   EXPECT_CALL(on_done, Call(absl::CancelledError()));
   MakeActivity(
       [] { return []() -> Poll<absl::Status> { return Pending(); }; },
-      NoCallbackScheduler(),
+      NoWakeupScheduler(),
       [&on_done](absl::Status status) { on_done.Call(std::move(status)); });
 }
 
@@ -127,7 +122,7 @@ TEST(ActivityTest, Cancel) {
   StrictMock<MockFunction<void(absl::Status)>> on_done;
   auto activity = MakeActivity(
       [] { return []() -> Poll<absl::Status> { return Pending(); }; },
-      NoCallbackScheduler(),
+      NoWakeupScheduler(),
       [&on_done](absl::Status status) { on_done.Call(std::move(status)); });
   EXPECT_CALL(on_done, Call(absl::CancelledError()));
   activity->Cancel();
@@ -153,7 +148,7 @@ TYPED_TEST(BarrierTest, Barrier) {
           return absl::OkStatus();
         });
       },
-      NoCallbackScheduler(),
+      InlineWakeupScheduler(),
       [&on_done](absl::Status status) { on_done.Call(std::move(status)); });
   // Clearing the barrier should let the activity proceed to return a result.
   EXPECT_CALL(on_done, Call(absl::OkStatus()));
@@ -165,7 +160,8 @@ TYPED_TEST(BarrierTest, BarrierPing) {
   typename TestFixture::Type b2;
   StrictMock<MockFunction<void(absl::Status)>> on_done1;
   StrictMock<MockFunction<void(absl::Status)>> on_done2;
-  MockCallbackScheduler scheduler;
+  MockCallbackScheduler scheduler1;
+  MockCallbackScheduler scheduler2;
   auto activity1 = MakeActivity(
       [&b1, &b2] {
         return Seq(b1.Wait(), [&b2](typename TestFixture::Type::Result) {
@@ -174,7 +170,7 @@ TYPED_TEST(BarrierTest, BarrierPing) {
           return absl::OkStatus();
         });
       },
-      [&scheduler](std::function<void()> f) { scheduler.Schedule(f); },
+      UseMockCallbackScheduler{&scheduler1},
       [&on_done1](absl::Status status) { on_done1.Call(std::move(status)); });
   auto activity2 = MakeActivity(
       [&b2] {
@@ -182,17 +178,21 @@ TYPED_TEST(BarrierTest, BarrierPing) {
           return absl::OkStatus();
         });
       },
-      [&scheduler](std::function<void()> f) { scheduler.Schedule(f); },
+      UseMockCallbackScheduler{&scheduler2},
       [&on_done2](absl::Status status) { on_done2.Call(std::move(status)); });
-  EXPECT_CALL(on_done1, Call(absl::OkStatus()));
   // Since barrier triggers inside activity1 promise, activity2 wakeup will be
   // scheduled from a callback.
-  std::function<void()> cb;
-  EXPECT_CALL(scheduler, Schedule(_)).WillOnce(SaveArg<0>(&cb));
+  std::function<void()> cb1;
+  std::function<void()> cb2;
+  EXPECT_CALL(scheduler1, Schedule(_)).WillOnce(SaveArg<0>(&cb1));
   b1.Clear();
+  Mock::VerifyAndClearExpectations(&scheduler1);
+  EXPECT_CALL(on_done1, Call(absl::OkStatus()));
+  EXPECT_CALL(scheduler2, Schedule(_)).WillOnce(SaveArg<0>(&cb2));
+  cb1();
   Mock::VerifyAndClearExpectations(&on_done1);
   EXPECT_CALL(on_done2, Call(absl::OkStatus()));
-  cb();
+  cb2();
 }
 
 TYPED_TEST(BarrierTest, WakeSelf) {
@@ -210,7 +210,7 @@ TYPED_TEST(BarrierTest, WakeSelf) {
                      return absl::OkStatus();
                    });
       },
-      NoCallbackScheduler(),
+      NoWakeupScheduler(),
       [&on_done](absl::Status status) { on_done.Call(std::move(status)); });
 }
 
@@ -225,12 +225,33 @@ TYPED_TEST(BarrierTest, WakeAfterDestruction) {
             return absl::OkStatus();
           });
         },
-        NoCallbackScheduler(),
+        InlineWakeupScheduler(),
         [&on_done](absl::Status status) { on_done.Call(std::move(status)); });
   }
   b.Clear();
 }
 
+TEST(ActivityTest, ForceWakeup) {
+  StrictMock<MockFunction<void(absl::Status)>> on_done;
+  int run_count = 0;
+  auto activity = MakeActivity(
+      [&run_count]() -> Poll<absl::Status> {
+        ++run_count;
+        switch (run_count) {
+          case 1:
+            return Pending{};
+          case 2:
+            return absl::OkStatus();
+          default:
+            abort();
+        }
+      },
+      InlineWakeupScheduler(),
+      [&on_done](absl::Status status) { on_done.Call(std::move(status)); });
+  EXPECT_CALL(on_done, Call(absl::OkStatus()));
+  activity->ForceWakeup();
+}
+
 struct TestContext {
   bool* done;
 };
@@ -246,12 +267,67 @@ TEST(ActivityTest, WithContext) {
         *GetContext<TestContext>()->done = true;
         return Immediate(absl::OkStatus());
       },
-      NoCallbackScheduler(),
+      NoWakeupScheduler(),
       [&on_done](absl::Status status) { on_done.Call(std::move(status)); },
       TestContext{&done});
   EXPECT_TRUE(done);
 }
 
+TEST(ActivityTest, CanCancelDuringExecution) {
+  ActivityPtr activity;
+  StrictMock<MockFunction<void(absl::Status)>> on_done;
+  int run_count = 0;
+
+  activity = MakeActivity(
+      [&activity, &run_count]() -> Poll<absl::Status> {
+        ++run_count;
+        switch (run_count) {
+          case 1:
+            return Pending{};
+          case 2:
+            activity.reset();
+            return Pending{};
+          default:
+            abort();
+        }
+      },
+      InlineWakeupScheduler(),
+      [&on_done](absl::Status status) { on_done.Call(std::move(status)); });
+
+  EXPECT_CALL(on_done, Call(absl::CancelledError()));
+  activity->ForceWakeup();
+}
+
+TEST(ActivityTest, CanCancelDuringSuccessfulExecution) {
+  ActivityPtr activity;
+  StrictMock<MockFunction<void(absl::Status)>> on_done;
+  int run_count = 0;
+
+  activity = MakeActivity(
+      [&activity, &run_count]() -> Poll<absl::Status> {
+        ++run_count;
+        switch (run_count) {
+          case 1:
+            return Pending{};
+          case 2:
+            activity.reset();
+            return absl::OkStatus();
+          default:
+            abort();
+        }
+      },
+      InlineWakeupScheduler(),
+      [&on_done](absl::Status status) { on_done.Call(std::move(status)); });
+
+  EXPECT_CALL(on_done, Call(absl::OkStatus()));
+  activity->ForceWakeup();
+}
+
+TEST(WakerTest, CanWakeupEmptyWaker) {
+  // Empty wakers should not do anything upon wakeup.
+  Waker().Wakeup();
+}
+
 }  // namespace grpc_core
 
 int main(int argc, char** argv) {
diff --git a/test/core/promise/benchmark/BUILD b/test/core/promise/benchmark/BUILD
new file mode 100644 (file)
index 0000000..ad34a1f
--- /dev/null
@@ -0,0 +1,52 @@
+# 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.
+
+licenses(["notice"])
+
+load("//bazel:grpc_build_system.bzl", "grpc_cc_test", "grpc_package")
+
+grpc_package(name = "test/core/promise/benchmark")
+
+load("//test/cpp/microbenchmarks:grpc_benchmark_config.bzl", "grpc_benchmark_args")
+
+grpc_cc_test(
+    name = "competition",
+    srcs = [
+        "competition.cc",
+        "filter_stack.cc",
+        "filter_stack.h",
+    ],
+    args = grpc_benchmark_args(),
+    external_deps = [
+        "benchmark",
+        "absl/synchronization",
+    ],
+    tags = [
+        "no_mac",
+        "no_windows",
+    ],
+    uses_polling = False,
+    deps = [
+        "//:activity",
+        "//:for_each",
+        "//:join",
+        "//:latch",
+        "//:pipe",
+        "//:seq",
+        "//:try_join",
+        "//:try_seq",
+        "//test/core/promise:test_wakeup_schedulers",
+        "//test/core/util:grpc_suppressions",
+    ],
+)
diff --git a/test/core/promise/benchmark/competition.cc b/test/core/promise/benchmark/competition.cc
new file mode 100644 (file)
index 0000000..648c907
--- /dev/null
@@ -0,0 +1,492 @@
+// 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.
+
+/* This benchmark exists to ensure that immediately-firing alarms are fast */
+
+#include <benchmark/benchmark.h>
+
+#include "absl/synchronization/mutex.h"
+
+#include "src/core/lib/promise/activity.h"
+#include "src/core/lib/promise/context.h"
+#include "src/core/lib/promise/for_each.h"
+#include "src/core/lib/promise/join.h"
+#include "src/core/lib/promise/latch.h"
+#include "src/core/lib/promise/pipe.h"
+#include "src/core/lib/promise/seq.h"
+#include "src/core/lib/promise/try_join.h"
+#include "src/core/lib/promise/try_seq.h"
+#include "test/core/promise/benchmark/filter_stack.h"
+#include "test/core/promise/test_wakeup_schedulers.h"
+
+namespace filter_stack {
+
+Filter passthrough_filter = {
+    CallNextOp, NoCallData, NoCallData, NoChannelData, NoChannelData, 0, 0,
+};
+
+struct Interject {
+  Closure c;
+  Closure* next;
+
+  static void Callback(void* p, absl::Status status) {
+    auto* i = static_cast<Interject*>(p);
+    i->next->Run(std::move(status));
+  }
+
+  static void Init(CallElem* elem) {
+    auto* i = static_cast<Interject*>(elem->call_data);
+    i->c.f = Callback;
+    i->c.p = i;
+  }
+
+  static void Destroy(CallElem*) {}
+
+  static void StartOp(CallElem* elem, Op* op) {
+    auto* i = static_cast<Interject*>(elem->call_data);
+    if (op->recv_initial_metadata) {
+      i->next = op->on_complete;
+      op->on_complete = &i->c;
+    }
+    CallNextOp(elem, op);
+  }
+};
+
+Filter interject_filter = {
+    Interject::StartOp,
+    Interject::Init,
+    Interject::Destroy,
+    NoChannelData,
+    NoChannelData,
+    sizeof(Interject),
+    0,
+};
+
+struct InterjectPipe {
+  Closure c_init_metadata;
+  Closure* next_init_metadata;
+  Closure c_payload;
+  Closure* next_payload;
+  Closure c_trailing_metadata;
+  Closure* next_trailing_metadata;
+
+  static void CallbackInitMetadata(void* p, absl::Status status) {
+    auto* i = static_cast<InterjectPipe*>(p);
+    i->next_init_metadata->Run(std::move(status));
+  }
+
+  static void CallbackPayload(void* p, absl::Status status) {
+    auto* i = static_cast<InterjectPipe*>(p);
+    i->next_payload->Run(std::move(status));
+  }
+
+  static void CallbackTrailingMetadata(void* p, absl::Status status) {
+    auto* i = static_cast<InterjectPipe*>(p);
+    i->next_trailing_metadata->Run(std::move(status));
+  }
+
+  static void Init(CallElem* elem) {
+    auto* i = static_cast<InterjectPipe*>(elem->call_data);
+    i->c_init_metadata.f = CallbackInitMetadata;
+    i->c_init_metadata.p = i;
+    i->c_payload.f = CallbackPayload;
+    i->c_payload.p = i;
+    i->c_trailing_metadata.f = CallbackTrailingMetadata;
+    i->c_trailing_metadata.p = i;
+  }
+
+  static void Destroy(CallElem*) {}
+
+  static void StartOp(CallElem* elem, Op* op) {
+    auto* i = static_cast<InterjectPipe*>(elem->call_data);
+    if (op->recv_trailing_metadata) {
+      i->next_trailing_metadata = op->on_complete;
+      op->on_complete = &i->c_trailing_metadata;
+    }
+    if (op->recv_message) {
+      i->next_payload = op->on_complete;
+      op->on_complete = &i->c_payload;
+    }
+    if (op->recv_initial_metadata) {
+      i->next_init_metadata = op->on_complete;
+      op->on_complete = &i->c_init_metadata;
+    }
+    CallNextOp(elem, op);
+  }
+};
+
+Filter interject_pipe = {
+    InterjectPipe::StartOp,
+    InterjectPipe::Init,
+    InterjectPipe::Destroy,
+    NoChannelData,
+    NoChannelData,
+    sizeof(InterjectPipe),
+    0,
+};
+
+void EndOp(CallElem*, Op* op) { op->on_complete->Run(absl::OkStatus()); }
+
+Filter end_filter = {EndOp,         NoCallData, NoCallData, NoChannelData,
+                     NoChannelData, 0,          0};
+
+static void unary(benchmark::State& state,
+                  std::initializer_list<Filter*> filters) {
+  auto* channel =
+      MakeChannel(const_cast<Filter**>(&*filters.begin()), filters.size());
+  for (auto _ : state) {
+    auto* call = MakeCall(channel);
+    Op op;
+    Op::Payload payload;
+    op.recv_initial_metadata = true;
+    op.recv_message = true;
+    op.recv_trailing_metadata = true;
+    op.payload = &payload;
+    Closure done = {call, +[](void* p, absl::Status status) {
+                      if (!status.ok()) abort();
+                      FreeCall(static_cast<CallStack*>(p));
+                    }};
+    op.on_complete = &done;
+    RunOp(call, &op);
+  }
+  FreeChannel(channel);
+}
+
+static void BM_FilterStack_Passthrough3_Unary(benchmark::State& state) {
+  unary(state, {&passthrough_filter, &passthrough_filter, &passthrough_filter,
+                &end_filter});
+}
+BENCHMARK(BM_FilterStack_Passthrough3_Unary);
+
+static void BM_FilterStack_Passthrough10_Unary(benchmark::State& state) {
+  unary(state, {&passthrough_filter, &passthrough_filter, &passthrough_filter,
+                &passthrough_filter, &passthrough_filter, &passthrough_filter,
+                &passthrough_filter, &passthrough_filter, &passthrough_filter,
+                &passthrough_filter, &end_filter});
+}
+BENCHMARK(BM_FilterStack_Passthrough10_Unary);
+
+static void BM_FilterStack_Interject3_Unary(benchmark::State& state) {
+  unary(state,
+        {&interject_filter, &interject_filter, &interject_filter, &end_filter});
+}
+BENCHMARK(BM_FilterStack_Interject3_Unary);
+
+static void BM_FilterStack_Interject10_Unary(benchmark::State& state) {
+  unary(state, {&interject_filter, &interject_filter, &interject_filter,
+                &interject_filter, &interject_filter, &interject_filter,
+                &interject_filter, &interject_filter, &interject_filter,
+                &interject_filter, &end_filter});
+}
+BENCHMARK(BM_FilterStack_Interject10_Unary);
+
+static void BM_FilterStack_Interject30_Unary(benchmark::State& state) {
+  unary(state, {&interject_filter, &interject_filter, &interject_filter,
+                &interject_filter, &interject_filter, &interject_filter,
+                &interject_filter, &interject_filter, &interject_filter,
+                &interject_filter, &interject_filter, &interject_filter,
+                &interject_filter, &interject_filter, &interject_filter,
+                &interject_filter, &interject_filter, &interject_filter,
+                &interject_filter, &interject_filter, &interject_filter,
+                &interject_filter, &interject_filter, &interject_filter,
+                &interject_filter, &interject_filter, &interject_filter,
+                &interject_filter, &interject_filter, &interject_filter,
+                &end_filter});
+}
+BENCHMARK(BM_FilterStack_Interject30_Unary);
+
+static void BM_FilterStack_Interject3Pipe_Unary(benchmark::State& state) {
+  unary(state,
+        {&interject_pipe, &interject_pipe, &interject_pipe, &end_filter});
+}
+BENCHMARK(BM_FilterStack_Interject3Pipe_Unary);
+
+static void BM_FilterStack_Interject10Pipe_Unary(benchmark::State& state) {
+  unary(state,
+        {&interject_pipe, &interject_pipe, &interject_pipe, &interject_pipe,
+         &interject_pipe, &interject_pipe, &interject_pipe, &interject_pipe,
+         &interject_pipe, &interject_pipe, &end_filter});
+}
+BENCHMARK(BM_FilterStack_Interject10Pipe_Unary);
+
+static void BM_FilterStack_Interject30Pipe_Unary(benchmark::State& state) {
+  unary(state,
+        {&interject_pipe, &interject_pipe, &interject_pipe, &interject_pipe,
+         &interject_pipe, &interject_pipe, &interject_pipe, &interject_pipe,
+         &interject_pipe, &interject_pipe, &interject_pipe, &interject_pipe,
+         &interject_pipe, &interject_pipe, &interject_pipe, &interject_pipe,
+         &interject_pipe, &interject_pipe, &interject_pipe, &interject_pipe,
+         &interject_pipe, &interject_pipe, &interject_pipe, &interject_pipe,
+         &interject_pipe, &interject_pipe, &interject_pipe, &interject_pipe,
+         &interject_pipe, &interject_pipe, &end_filter});
+}
+BENCHMARK(BM_FilterStack_Interject30Pipe_Unary);
+
+}  // namespace filter_stack
+
+namespace grpc_core {
+
+namespace activity_stack {
+struct RPCIO {
+  Latch<int> recv_initial_metadata;
+};
+
+struct RPCP {
+  Pipe<int> pipe;
+};
+}  // namespace activity_stack
+
+template <>
+struct ContextType<activity_stack::RPCIO> {};
+
+template <>
+struct ContextType<activity_stack::RPCP> {};
+
+namespace activity_stack {
+
+template <typename MakeCall>
+static void unary(benchmark::State& state, MakeCall make_call) {
+  printf("activity stack size: %d\n", static_cast<int>(make_call()->Size()));
+  for (auto _ : state) {
+    make_call();
+  }
+}
+
+static void BM_ActivityStack_Passthrough3_Unary(benchmark::State& state) {
+  unary(state, []() {
+    return MakeActivity(
+        []() {
+          auto one = []() { return absl::OkStatus(); };
+          return TrySeq(one, one, one);
+        },
+        NoWakeupScheduler(),
+        [](absl::Status status) {
+          if (!status.ok()) abort();
+        });
+  });
+}
+BENCHMARK(BM_ActivityStack_Passthrough3_Unary);
+
+static void BM_ActivityStack_Passthrough10_Unary(benchmark::State& state) {
+  unary(state, []() {
+    return MakeActivity(
+        []() {
+          auto one = []() { return absl::OkStatus(); };
+          return TrySeq(one, one, one, one, one, one, one, one, one, one);
+        },
+        NoWakeupScheduler(),
+        [](absl::Status status) {
+          if (!status.ok()) abort();
+        });
+  });
+}
+BENCHMARK(BM_ActivityStack_Passthrough10_Unary);
+
+static void BM_ActivityStack_Interject3Latches_Unary(benchmark::State& state) {
+  unary(state, []() {
+    RPCIO rpcio;
+    return MakeActivity(
+        []() {
+          auto one = []() {
+            return GetContext<RPCIO>()->recv_initial_metadata.Wait();
+          };
+          return Seq(Join(one(), one(), one(),
+                          []() {
+                            GetContext<RPCIO>()->recv_initial_metadata.Set(42);
+                            return true;
+                          }),
+                     []() { return absl::OkStatus(); });
+        },
+        NoWakeupScheduler(),
+        [](absl::Status status) {
+          if (!status.ok()) abort();
+        },
+        std::move(rpcio));
+  });
+}
+BENCHMARK(BM_ActivityStack_Interject3Latches_Unary);
+
+static void BM_ActivityStack_Interject10Latches_Unary(benchmark::State& state) {
+  unary(state, []() {
+    RPCIO rpcio;
+    return MakeActivity(
+        []() {
+          auto one = []() {
+            return GetContext<RPCIO>()->recv_initial_metadata.Wait();
+          };
+          return Seq(Join(one(), one(), one(), one(), one(), one(), one(),
+                          one(), one(), one(),
+                          []() {
+                            GetContext<RPCIO>()->recv_initial_metadata.Set(42);
+                            return true;
+                          }),
+                     []() { return absl::OkStatus(); });
+        },
+        NoWakeupScheduler(),
+        [](absl::Status status) {
+          if (!status.ok()) abort();
+        },
+        std::move(rpcio));
+  });
+}
+BENCHMARK(BM_ActivityStack_Interject10Latches_Unary);
+
+static void BM_ActivityStack_Interject30Latches_Unary(benchmark::State& state) {
+  unary(state, []() {
+    RPCIO rpcio;
+    return MakeActivity(
+        []() {
+          auto one = []() {
+            return GetContext<RPCIO>()->recv_initial_metadata.Wait();
+          };
+          return Seq(
+              Join(one(), one(), one(), one(), one(), one(), one(), one(),
+                   one(), one(), one(), one(), one(), one(), one(), one(),
+                   one(), one(), one(), one(), one(), one(), one(), one(),
+                   one(), one(), one(), one(), one(), one(),
+                   []() {
+                     GetContext<RPCIO>()->recv_initial_metadata.Set(42);
+                     return true;
+                   }),
+              []() { return absl::OkStatus(); });
+        },
+        NoWakeupScheduler(),
+        [](absl::Status status) {
+          if (!status.ok()) abort();
+        },
+        std::move(rpcio));
+  });
+}
+BENCHMARK(BM_ActivityStack_Interject30Latches_Unary);
+
+static void BM_ActivityStack_Interject3Filters_Unary(benchmark::State& state) {
+  unary(state, []() {
+    RPCP rpcio;
+    return MakeActivity(
+        []() {
+          auto one = []() {
+            return GetContext<RPCP>()->pipe.sender.Filter(
+                [](int i) { return absl::StatusOr<int>(i); });
+          };
+          return TryJoin(
+              one(), one(), one(),
+              Seq(
+                  GetContext<RPCP>()->pipe.sender.Push(42),
+                  []() { return GetContext<RPCP>()->pipe.sender.Push(43); },
+                  []() { return GetContext<RPCP>()->pipe.sender.Push(44); },
+                  []() {
+                    auto x = std::move(GetContext<RPCP>()->pipe.sender);
+                    return absl::OkStatus();
+                  }),
+              Seq(
+                  GetContext<RPCP>()->pipe.receiver.Next(),
+                  []() { return GetContext<RPCP>()->pipe.receiver.Next(); },
+                  []() { return GetContext<RPCP>()->pipe.receiver.Next(); },
+                  []() { return absl::OkStatus(); }));
+        },
+        NoWakeupScheduler(),
+        [](absl::Status status) {
+          if (!status.ok()) abort();
+        },
+        std::move(rpcio));
+  });
+}
+BENCHMARK(BM_ActivityStack_Interject3Filters_Unary);
+
+static void BM_ActivityStack_Interject10Filters_Unary(benchmark::State& state) {
+  unary(state, []() {
+    RPCP rpcio;
+    return MakeActivity(
+        []() {
+          auto one = []() {
+            return GetContext<RPCP>()->pipe.sender.Filter(
+                [](int i) { return absl::StatusOr<int>(i); });
+          };
+          return TryJoin(
+              one(), one(), one(), one(), one(), one(), one(), one(), one(),
+              one(),
+              Seq(
+                  GetContext<RPCP>()->pipe.sender.Push(42),
+                  []() { return GetContext<RPCP>()->pipe.sender.Push(43); },
+                  []() { return GetContext<RPCP>()->pipe.sender.Push(44); },
+                  []() {
+                    auto x = std::move(GetContext<RPCP>()->pipe.sender);
+                    return absl::OkStatus();
+                  }),
+              Seq(
+                  GetContext<RPCP>()->pipe.receiver.Next(),
+                  []() { return GetContext<RPCP>()->pipe.receiver.Next(); },
+                  []() { return GetContext<RPCP>()->pipe.receiver.Next(); },
+                  []() { return absl::OkStatus(); }));
+        },
+        NoWakeupScheduler(),
+        [](absl::Status status) {
+          if (!status.ok()) abort();
+        },
+        std::move(rpcio));
+  });
+}
+BENCHMARK(BM_ActivityStack_Interject10Filters_Unary);
+
+static void BM_ActivityStack_Interject30Filters_Unary(benchmark::State& state) {
+  unary(state, []() {
+    RPCP rpcio;
+    return MakeActivity(
+        []() {
+          auto one = []() {
+            return GetContext<RPCP>()->pipe.sender.Filter(
+                [](int i) { return absl::StatusOr<int>(i); });
+          };
+          return TryJoin(
+              one(), one(), one(), one(), one(), one(), one(), one(), one(),
+              one(), one(), one(), one(), one(), one(), one(), one(), one(),
+              one(), one(), one(), one(), one(), one(), one(), one(), one(),
+              one(), one(), one(),
+              Seq(
+                  GetContext<RPCP>()->pipe.sender.Push(42),
+                  []() { return GetContext<RPCP>()->pipe.sender.Push(43); },
+                  []() { return GetContext<RPCP>()->pipe.sender.Push(44); },
+                  []() {
+                    auto x = std::move(GetContext<RPCP>()->pipe.sender);
+                    return absl::OkStatus();
+                  }),
+              Seq(
+                  GetContext<RPCP>()->pipe.receiver.Next(),
+                  []() { return GetContext<RPCP>()->pipe.receiver.Next(); },
+                  []() { return GetContext<RPCP>()->pipe.receiver.Next(); },
+                  []() { return absl::OkStatus(); }));
+        },
+        NoWakeupScheduler(),
+        [](absl::Status status) {
+          if (!status.ok()) abort();
+        },
+        std::move(rpcio));
+  });
+}
+BENCHMARK(BM_ActivityStack_Interject30Filters_Unary);
+
+}  // namespace activity_stack
+}  // namespace grpc_core
+
+// Some distros have RunSpecifiedBenchmarks under the benchmark namespace,
+// and others do not. This allows us to support both modes.
+namespace benchmark {
+void RunTheBenchmarksNamespaced() { RunSpecifiedBenchmarks(); }
+}  // namespace benchmark
+
+int main(int argc, char** argv) {
+  ::benchmark::Initialize(&argc, argv);
+  benchmark::RunTheBenchmarksNamespaced();
+  return 0;
+}
diff --git a/test/core/promise/benchmark/filter_stack.cc b/test/core/promise/benchmark/filter_stack.cc
new file mode 100644 (file)
index 0000000..fe438e4
--- /dev/null
@@ -0,0 +1,102 @@
+// 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 "test/core/promise/benchmark/filter_stack.h"
+
+namespace filter_stack {
+
+ChannelStack* MakeChannel(Filter** filters, size_t num_filters) {
+  size_t size = sizeof(ChannelStack) + num_filters * sizeof(ChannelElem);
+  size_t call_size = sizeof(CallStack) + num_filters * sizeof(CallElem);
+  for (size_t i = 0; i < num_filters; i++) {
+    size += filters[i]->sizeof_channel_data;
+    call_size += filters[i]->sizeof_call_data;
+  }
+  char* data = new char[size];
+  ChannelStack* stk = reinterpret_cast<ChannelStack*>(data);
+  new (data) ChannelStack{0, num_filters, call_size};
+  data += sizeof(ChannelStack);
+  char* user_data = data + num_filters * sizeof(ChannelElem);
+  for (size_t i = 0; i < num_filters; i++) {
+    new (data) ChannelElem{filters[i], user_data};
+    filters[i]->init_channel_data(reinterpret_cast<ChannelElem*>(data));
+    data += sizeof(ChannelElem);
+    user_data += filters[i]->sizeof_channel_data;
+  }
+  printf("CALL STACK SIZE: %d\n", static_cast<int>(call_size));
+  return stk;
+}
+
+void FreeChannel(ChannelStack* stk) {
+  ChannelElem* elems = reinterpret_cast<ChannelElem*>(stk + 1);
+  for (size_t i = 0; i < stk->num_elems; i++) {
+    elems[i].filter->destroy_channel_data(&elems[i]);
+  }
+  stk->~ChannelStack();
+  delete[] reinterpret_cast<char*>(stk);
+}
+
+CallStack* MakeCall(ChannelStack* stk) {
+  char* data = new char[stk->call_stack_size];
+  CallStack* call = reinterpret_cast<CallStack*>(data);
+  new (data) CallStack{{1}, stk->num_elems, {}};
+  data += sizeof(CallStack);
+  ChannelElem* channel_elems = reinterpret_cast<ChannelElem*>(stk + 1);
+  char* user_data = data + stk->num_elems * sizeof(CallElem);
+  for (size_t i = 0; i < stk->num_elems; i++) {
+    new (data) CallElem{channel_elems[i].filter, channel_elems[i].channel_data,
+                        user_data};
+    channel_elems[i].filter->init_call_data(reinterpret_cast<CallElem*>(data));
+    data += sizeof(CallElem);
+    user_data += channel_elems[i].filter->sizeof_call_data;
+  }
+  return call;
+}
+
+static void RefCall(CallStack* stk) {
+  stk->refcount.fetch_add(1, std::memory_order_relaxed);
+}
+
+static void UnrefCall(CallStack* stk) {
+  if (stk->refcount.fetch_sub(1, std::memory_order_acq_rel) == 1) {
+    CallElem* elems = reinterpret_cast<CallElem*>(stk + 1);
+    for (size_t i = 0; i < stk->num_elems; i++) {
+      elems[i].filter->destroy_call_data(&elems[i]);
+    }
+    stk->~CallStack();
+    delete[] reinterpret_cast<char*>(stk);
+  }
+}
+
+void FreeCall(CallStack* stk) { UnrefCall(stk); }
+
+void NoChannelData(ChannelElem*) {}
+void NoCallData(CallElem*) {}
+
+static void StartOp(CallElem* elem, Op* op) {
+  elem->filter->start_transport_stream_op_batch(elem, op);
+}
+
+void CallNextOp(CallElem* elem, Op* op) { StartOp(elem + 1, op); }
+
+void RunOp(CallStack* stk, Op* op) {
+  RefCall(stk);
+  {
+    absl::MutexLock lock(&stk->mutex);
+    StartOp(reinterpret_cast<CallElem*>(stk + 1), op);
+  }
+  UnrefCall(stk);
+}
+
+}  // namespace filter_stack
diff --git a/test/core/promise/benchmark/filter_stack.h b/test/core/promise/benchmark/filter_stack.h
new file mode 100644 (file)
index 0000000..52a7d68
--- /dev/null
@@ -0,0 +1,108 @@
+// 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.
+
+#ifndef FILTER_STACK_H
+#define FILTER_STACK_H
+
+#include "absl/status/status.h"
+#include "absl/synchronization/mutex.h"
+
+namespace filter_stack {
+
+struct Filter;
+
+struct ChannelStack {
+  uint64_t refcount;
+  size_t num_elems;
+  size_t call_stack_size;
+};
+
+struct CallStack {
+  std::atomic<size_t> refcount;
+  size_t num_elems;
+  absl::Mutex mutex;
+};
+
+struct ChannelElem {
+  Filter* filter;
+  void* channel_data;
+};
+
+struct CallElem {
+  Filter* filter;
+  void* channel_data;
+  void* call_data;
+};
+
+struct Closure {
+  void* p;
+  void (*f)(void* p, absl::Status);
+  void Run(absl::Status status) { f(p, std::move(status)); }
+};
+
+struct Op {
+  struct Payload {};
+
+  Op()
+      : send_initial_metadata(false),
+        send_trailing_metadata(false),
+        send_message(false),
+        recv_initial_metadata(false),
+        recv_message(false),
+        recv_trailing_metadata(false),
+        cancel_stream(false),
+        is_traced(false) {}
+
+  Op(const Op&) = delete;
+  Op& operator=(const Op&) = delete;
+
+  Payload* payload = nullptr;
+
+  Closure* on_complete = nullptr;
+
+  bool send_initial_metadata : 1;
+  bool send_trailing_metadata : 1;
+  bool send_message : 1;
+  bool recv_initial_metadata : 1;
+  bool recv_message : 1;
+  bool recv_trailing_metadata : 1;
+  bool cancel_stream : 1;
+  bool is_traced : 1;
+};
+
+struct Filter {
+  void (*start_transport_stream_op_batch)(CallElem* elem, Op* op);
+  void (*init_call_data)(CallElem* elem);
+  void (*destroy_call_data)(CallElem* elem);
+  void (*init_channel_data)(ChannelElem* elem);
+  void (*destroy_channel_data)(ChannelElem* elem);
+  size_t sizeof_call_data;
+  size_t sizeof_channel_data;
+};
+
+ChannelStack* MakeChannel(Filter** filters, size_t num_filters);
+void FreeChannel(ChannelStack* stk);
+CallStack* MakeCall(ChannelStack* stk);
+void FreeCall(CallStack* stk);
+
+void NoChannelData(ChannelElem*);
+void NoCallData(CallElem*);
+
+void CallNextOp(CallElem* elem, Op* op);
+
+void RunOp(CallStack* stk, Op* op);
+
+}  // namespace filter_stack
+
+#endif
diff --git a/test/core/promise/exec_ctx_wakeup_scheduler_test.cc b/test/core/promise/exec_ctx_wakeup_scheduler_test.cc
new file mode 100644 (file)
index 0000000..ea3568c
--- /dev/null
@@ -0,0 +1,66 @@
+// 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 "src/core/lib/promise/exec_ctx_wakeup_scheduler.h"
+
+#include <gtest/gtest.h>
+
+#include "src/core/lib/promise/activity.h"
+
+namespace grpc_core {
+
+TEST(ExecCtxWakeupSchedulerTest, Works) {
+  int state = 0;
+  bool done = false;
+  auto activity = MakeActivity(
+      [&state]() mutable -> Poll<absl::Status> {
+        ++state;
+        switch (state) {
+          case 1:
+            return Pending();
+          case 2:
+            return absl::OkStatus();
+          default:
+            abort();
+        }
+      },
+      ExecCtxWakeupScheduler(),
+      [&done](absl::Status status) {
+        EXPECT_EQ(status, absl::OkStatus());
+        done = true;
+      });
+
+  EXPECT_EQ(state, 1);
+  EXPECT_FALSE(done);
+  {
+    ExecCtx exec_ctx;
+    EXPECT_FALSE(exec_ctx.HasWork());
+    activity->ForceWakeup();
+    EXPECT_TRUE(exec_ctx.HasWork());
+    EXPECT_EQ(state, 1);
+    EXPECT_FALSE(done);
+  }
+  EXPECT_EQ(state, 2);
+  EXPECT_TRUE(done);
+}
+
+}  // namespace grpc_core
+
+int main(int argc, char** argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  grpc_core::ExecCtx::GlobalInit();
+  int r = RUN_ALL_TESTS();
+  grpc_core::ExecCtx::GlobalShutdown();
+  return r;
+}
index 1d112e5..d668c3d 100644 (file)
@@ -22,6 +22,7 @@
 #include "src/core/lib/promise/observable.h"
 #include "src/core/lib/promise/pipe.h"
 #include "src/core/lib/promise/seq.h"
+#include "test/core/promise/test_wakeup_schedulers.h"
 
 using testing::Mock;
 using testing::MockFunction;
@@ -57,7 +58,7 @@ TEST(ForEachTest, SendThriceWithPipe) {
                         })),
             JustElem<1>());
       },
-      NoCallbackScheduler(),
+      NoWakeupScheduler(),
       [&on_done](absl::Status status) { on_done.Call(std::move(status)); });
   Mock::VerifyAndClearExpectations(&on_done);
   EXPECT_EQ(num_received, 3);
index c1032df..a3054a1 100644 (file)
@@ -19,6 +19,7 @@
 
 #include "src/core/lib/promise/join.h"
 #include "src/core/lib/promise/seq.h"
+#include "test/core/promise/test_wakeup_schedulers.h"
 
 using testing::MockFunction;
 using testing::StrictMock;
@@ -41,7 +42,7 @@ TEST(LatchTest, Works) {
                      return absl::OkStatus();
                    });
       },
-      NoCallbackScheduler(),
+      NoWakeupScheduler(),
       [&on_done](absl::Status status) { on_done.Call(std::move(status)); });
 }
 
index 4d7b846..5e6cf44 100644 (file)
@@ -16,6 +16,8 @@
 
 #include <gtest/gtest.h>
 
+#include "src/core/lib/promise/seq.h"
+
 namespace grpc_core {
 
 TEST(LoopTest, CountToFive) {
@@ -40,6 +42,12 @@ TEST(LoopTest, FactoryCountToFive) {
   EXPECT_EQ(i, 5);
 }
 
+TEST(LoopTest, LoopOfSeq) {
+  auto x =
+      Loop(Seq([]() { return 42; }, [](int i) -> LoopCtl<int> { return i; }))();
+  EXPECT_EQ(x, Poll<int>(42));
+}
+
 }  // namespace grpc_core
 
 int main(int argc, char** argv) {
index 9044366..3eb120b 100644 (file)
@@ -19,6 +19,7 @@
 
 #include "src/core/lib/promise/promise.h"
 #include "src/core/lib/promise/seq.h"
+#include "test/core/promise/test_wakeup_schedulers.h"
 
 using testing::MockFunction;
 using testing::StrictMock;
@@ -65,7 +66,7 @@ TEST(ObservableTest, CanPushAndGet) {
           return i == 42 ? absl::OkStatus() : absl::UnknownError("expected 42");
         });
       },
-      NoCallbackScheduler(),
+      InlineWakeupScheduler(),
       [&on_done](absl::Status status) { on_done.Call(std::move(status)); });
   EXPECT_CALL(on_done, Call(absl::OkStatus()));
   observable.Push(42);
@@ -88,7 +89,7 @@ TEST(ObservableTest, CanNext) {
                             : absl::UnknownError("expected 1");
             });
       },
-      NoCallbackScheduler(),
+      InlineWakeupScheduler(),
       [&on_done](absl::Status status) { on_done.Call(std::move(status)); });
   observable.Push(42);
   EXPECT_CALL(on_done, Call(absl::OkStatus()));
@@ -112,7 +113,7 @@ TEST(ObservableTest, CanWatch) {
               }
             });
       },
-      NoCallbackScheduler(),
+      InlineWakeupScheduler(),
       [&on_done](absl::Status status) { on_done.Call(std::move(status)); });
   observable.Push(1);
   observable.Push(2);
index c6c699e..ba38fbe 100644 (file)
@@ -22,6 +22,7 @@
 #include "src/core/lib/promise/join.h"
 #include "src/core/lib/promise/promise.h"
 #include "src/core/lib/promise/seq.h"
+#include "test/core/promise/test_wakeup_schedulers.h"
 
 using testing::MockFunction;
 using testing::StrictMock;
@@ -44,7 +45,7 @@ TEST(PipeTest, CanSendAndReceive) {
               return absl::OkStatus();
             });
       },
-      NoCallbackScheduler(),
+      NoWakeupScheduler(),
       [&on_done](absl::Status status) { on_done.Call(std::move(status)); });
 }
 
@@ -64,7 +65,7 @@ TEST(PipeTest, CanReceiveAndSend) {
               return absl::OkStatus();
             });
       },
-      NoCallbackScheduler(),
+      NoWakeupScheduler(),
       [&on_done](absl::Status status) { on_done.Call(std::move(status)); });
 }
 
@@ -95,7 +96,7 @@ TEST(PipeTest, CanSeeClosedOnSend) {
               return absl::OkStatus();
             });
       },
-      NoCallbackScheduler(),
+      NoWakeupScheduler(),
       [&on_done](absl::Status status) { on_done.Call(std::move(status)); });
 }
 
@@ -125,7 +126,7 @@ TEST(PipeTest, CanSeeClosedOnReceive) {
               return absl::OkStatus();
             });
       },
-      NoCallbackScheduler(),
+      NoWakeupScheduler(),
       [&on_done](absl::Status status) { on_done.Call(std::move(status)); });
 }
 
@@ -167,7 +168,7 @@ TEST(PipeTest, CanFilter) {
               return absl::OkStatus();
             });
       },
-      NoCallbackScheduler(),
+      NoWakeupScheduler(),
       [&on_done](absl::Status status) { on_done.Call(std::move(status)); });
 }
 
diff --git a/test/core/promise/promise_fuzzer.cc b/test/core/promise/promise_fuzzer.cc
new file mode 100644 (file)
index 0000000..78a0da9
--- /dev/null
@@ -0,0 +1,317 @@
+// 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 "src/core/lib/promise/activity.h"
+#include "src/core/lib/promise/join.h"
+#include "src/core/lib/promise/map.h"
+#include "src/core/lib/promise/promise.h"
+#include "src/core/lib/promise/race.h"
+#include "src/core/lib/promise/seq.h"
+#include "src/libfuzzer/libfuzzer_macro.h"
+#include "test/core/promise/promise_fuzzer.pb.h"
+
+bool squelch = true;
+bool leak_check = true;
+
+namespace grpc_core {
+// Return type for infallible promises.
+// We choose this so that it's easy to construct, and will trigger asan failures
+// if misused, and is copyable.
+using IntHdl = std::shared_ptr<int>;
+
+template <typename T>
+using PromiseFactory = std::function<Promise<T>(T)>;
+
+namespace {
+class Fuzzer {
+ public:
+  void Run(const promise_fuzzer::Msg& msg) {
+    // If there's no promise we can't construct and activity and... we're done.
+    if (!msg.has_promise()) {
+      return;
+    }
+    // Construct activity.
+    activity_ = MakeActivity(
+        [msg, this] {
+          return Seq(MakePromise(msg.promise()),
+                     [] { return absl::OkStatus(); });
+        },
+        Scheduler{this},
+        [this](absl::Status status) {
+          // Must only be called once
+          GPR_ASSERT(!done_);
+          // If we became certain of the eventual status, verify it.
+          if (expected_status_.has_value()) {
+            GPR_ASSERT(status == *expected_status_);
+          }
+          // Mark ourselves done.
+          done_ = true;
+        });
+    for (int i = 0; !done_ && activity_ != nullptr && i < msg.actions_size();
+         i++) {
+      // Do some things
+      const auto& action = msg.actions(i);
+      switch (action.action_type_case()) {
+        // Force a wakeup
+        case promise_fuzzer::Action::kForceWakeup:
+          activity_->ForceWakeup();
+          break;
+        // Cancel from the outside
+        case promise_fuzzer::Action::kCancel:
+          ExpectCancelled();
+          activity_.reset();
+          break;
+        // Flush any pending wakeups
+        case promise_fuzzer::Action::kFlushWakeup:
+          if (wakeup_ != nullptr) absl::exchange(wakeup_, nullptr)();
+          break;
+        // Drop some wakeups (external system closed?)
+        case promise_fuzzer::Action::kDropWaker: {
+          int n = action.drop_waker();
+          auto v = std::move(wakers_[n]);
+          wakers_.erase(n);
+          break;
+        }
+        // Wakeup some wakeups
+        case promise_fuzzer::Action::kAwakeWaker: {
+          int n = action.awake_waker();
+          auto v = std::move(wakers_[n]);
+          wakers_.erase(n);
+          for (auto& w : v) {
+            w.Wakeup();
+          }
+          break;
+        }
+        case promise_fuzzer::Action::ACTION_TYPE_NOT_SET:
+          break;
+      }
+    }
+    ExpectCancelled();
+    activity_.reset();
+    if (wakeup_ != nullptr) absl::exchange(wakeup_, nullptr)();
+    GPR_ASSERT(done_);
+  }
+
+ private:
+  // Schedule wakeups against the fuzzer
+  struct Scheduler {
+    Fuzzer* fuzzer;
+    // Schedule a wakeup
+    template <typename ActivityType>
+    void ScheduleWakeup(ActivityType* activity) {
+      GPR_ASSERT(activity == fuzzer->activity_.get());
+      GPR_ASSERT(fuzzer->wakeup_ == nullptr);
+      fuzzer->wakeup_ = [activity]() { activity->RunScheduledWakeup(); };
+    }
+  };
+
+  // We know that if not already finished, the status when finished will be
+  // cancelled.
+  void ExpectCancelled() {
+    if (!done_ && !expected_status_.has_value()) {
+      expected_status_ = absl::CancelledError();
+    }
+  }
+
+  // Construct a promise factory from a protobuf
+  PromiseFactory<IntHdl> MakePromiseFactory(
+      const promise_fuzzer::PromiseFactory& p) {
+    switch (p.promise_factory_type_case()) {
+      case promise_fuzzer::PromiseFactory::kPromise:
+        return [p, this](IntHdl) { return MakePromise(p.promise()); };
+      case promise_fuzzer::PromiseFactory::kLast:
+        return [](IntHdl h) { return [h]() { return h; }; };
+      case promise_fuzzer::PromiseFactory::PROMISE_FACTORY_TYPE_NOT_SET:
+        break;
+    }
+    return [](IntHdl) {
+      return []() -> Poll<IntHdl> { return std::make_shared<int>(42); };
+    };
+  }
+
+  // Construct a promise from a protobuf
+  Promise<IntHdl> MakePromise(const promise_fuzzer::Promise& p) {
+    switch (p.promise_type_case()) {
+      case promise_fuzzer::Promise::kSeq:
+        switch (p.seq().promise_factories_size()) {
+          case 1:
+            return Seq(MakePromise(p.seq().first()),
+                       MakePromiseFactory(p.seq().promise_factories(0)));
+          case 2:
+            return Seq(MakePromise(p.seq().first()),
+                       MakePromiseFactory(p.seq().promise_factories(0)),
+                       MakePromiseFactory(p.seq().promise_factories(1)));
+          case 3:
+            return Seq(MakePromise(p.seq().first()),
+                       MakePromiseFactory(p.seq().promise_factories(0)),
+                       MakePromiseFactory(p.seq().promise_factories(1)),
+                       MakePromiseFactory(p.seq().promise_factories(2)));
+          case 4:
+            return Seq(MakePromise(p.seq().first()),
+                       MakePromiseFactory(p.seq().promise_factories(0)),
+                       MakePromiseFactory(p.seq().promise_factories(1)),
+                       MakePromiseFactory(p.seq().promise_factories(2)),
+                       MakePromiseFactory(p.seq().promise_factories(3)));
+          case 5:
+            return Seq(MakePromise(p.seq().first()),
+                       MakePromiseFactory(p.seq().promise_factories(0)),
+                       MakePromiseFactory(p.seq().promise_factories(1)),
+                       MakePromiseFactory(p.seq().promise_factories(2)),
+                       MakePromiseFactory(p.seq().promise_factories(3)),
+                       MakePromiseFactory(p.seq().promise_factories(4)));
+          case 6:
+            return Seq(MakePromise(p.seq().first()),
+                       MakePromiseFactory(p.seq().promise_factories(0)),
+                       MakePromiseFactory(p.seq().promise_factories(1)),
+                       MakePromiseFactory(p.seq().promise_factories(2)),
+                       MakePromiseFactory(p.seq().promise_factories(3)),
+                       MakePromiseFactory(p.seq().promise_factories(4)),
+                       MakePromiseFactory(p.seq().promise_factories(5)));
+        }
+        break;
+      case promise_fuzzer::Promise::kJoin:
+        switch (p.join().promises_size()) {
+          case 1:
+            return Map(Join(MakePromise(p.join().promises(0))),
+                       [](std::tuple<IntHdl> t) { return std::get<0>(t); });
+          case 2:
+            return Map(
+                Join(MakePromise(p.join().promises(0)),
+                     MakePromise(p.join().promises(1))),
+                [](std::tuple<IntHdl, IntHdl> t) { return std::get<0>(t); });
+          case 3:
+            return Map(Join(MakePromise(p.join().promises(0)),
+                            MakePromise(p.join().promises(1)),
+                            MakePromise(p.join().promises(2))),
+                       [](std::tuple<IntHdl, IntHdl, IntHdl> t) {
+                         return std::get<0>(t);
+                       });
+          case 4:
+            return Map(Join(MakePromise(p.join().promises(0)),
+                            MakePromise(p.join().promises(1)),
+                            MakePromise(p.join().promises(2)),
+                            MakePromise(p.join().promises(3))),
+                       [](std::tuple<IntHdl, IntHdl, IntHdl, IntHdl> t) {
+                         return std::get<0>(t);
+                       });
+          case 5:
+            return Map(
+                Join(MakePromise(p.join().promises(0)),
+                     MakePromise(p.join().promises(1)),
+                     MakePromise(p.join().promises(2)),
+                     MakePromise(p.join().promises(3)),
+                     MakePromise(p.join().promises(4))),
+                [](std::tuple<IntHdl, IntHdl, IntHdl, IntHdl, IntHdl> t) {
+                  return std::get<0>(t);
+                });
+          case 6:
+            return Map(
+                Join(MakePromise(p.join().promises(0)),
+                     MakePromise(p.join().promises(1)),
+                     MakePromise(p.join().promises(2)),
+                     MakePromise(p.join().promises(3)),
+                     MakePromise(p.join().promises(4)),
+                     MakePromise(p.join().promises(5))),
+                [](std::tuple<IntHdl, IntHdl, IntHdl, IntHdl, IntHdl, IntHdl>
+                       t) { return std::get<0>(t); });
+        }
+        break;
+      case promise_fuzzer::Promise::kRace:
+        switch (p.race().promises_size()) {
+          case 1:
+            return Race(MakePromise(p.race().promises(0)));
+          case 2:
+            return Race(MakePromise(p.race().promises(0)),
+                        MakePromise(p.race().promises(1)));
+          case 3:
+            return Race(MakePromise(p.race().promises(0)),
+                        MakePromise(p.race().promises(1)),
+                        MakePromise(p.race().promises(2)));
+          case 4:
+            return Race(MakePromise(p.race().promises(0)),
+                        MakePromise(p.race().promises(1)),
+                        MakePromise(p.race().promises(2)),
+                        MakePromise(p.race().promises(3)));
+          case 5:
+            return Race(MakePromise(p.race().promises(0)),
+                        MakePromise(p.race().promises(1)),
+                        MakePromise(p.race().promises(2)),
+                        MakePromise(p.race().promises(3)),
+                        MakePromise(p.race().promises(4)));
+          case 6:
+            return Race(MakePromise(p.race().promises(0)),
+                        MakePromise(p.race().promises(1)),
+                        MakePromise(p.race().promises(2)),
+                        MakePromise(p.race().promises(3)),
+                        MakePromise(p.race().promises(4)),
+                        MakePromise(p.race().promises(5)));
+        }
+        break;
+      case promise_fuzzer::Promise::kNever:
+        return Never<IntHdl>();
+      case promise_fuzzer::Promise::kSleepFirstN: {
+        int n = p.sleep_first_n();
+        return [n]() mutable -> Poll<IntHdl> {
+          if (n <= 0) return std::make_shared<int>(0);
+          n--;
+          return Pending{};
+        };
+      }
+      case promise_fuzzer::Promise::kCancelFromInside:
+        return [this]() -> Poll<IntHdl> {
+          this->activity_.reset();
+          return Pending{};
+        };
+      case promise_fuzzer::Promise::kWaitOnceOnWaker: {
+        bool called = false;
+        auto config = p.wait_once_on_waker();
+        return [this, config, called]() mutable -> Poll<IntHdl> {
+          if (!called) {
+            if (config.owning()) {
+              wakers_[config.waker()].push_back(
+                  Activity::current()->MakeOwningWaker());
+            } else {
+              wakers_[config.waker()].push_back(
+                  Activity::current()->MakeNonOwningWaker());
+            }
+            return Pending();
+          }
+          return std::make_shared<int>(3);
+        };
+      }
+      case promise_fuzzer::Promise::PromiseTypeCase::PROMISE_TYPE_NOT_SET:
+        break;
+    }
+    return [] { return std::make_shared<int>(42); };
+  }
+
+  // Activity under test
+  ActivityPtr activity_;
+  // Scheduled wakeup (may be nullptr if no wakeup scheduled)
+  std::function<void()> wakeup_;
+  // If we are certain of the final status, then that. Otherwise, nullopt if we
+  // don't know.
+  absl::optional<absl::Status> expected_status_;
+  // Has on_done been called?
+  bool done_ = false;
+  // Wakers that may be scheduled
+  std::map<int, std::vector<Waker>> wakers_;
+};
+}  // namespace
+
+}  // namespace grpc_core
+
+DEFINE_PROTO_FUZZER(const promise_fuzzer::Msg& msg) {
+  grpc_core::Fuzzer().Run(msg);
+}
diff --git a/test/core/promise/promise_fuzzer.proto b/test/core/promise/promise_fuzzer.proto
new file mode 100644 (file)
index 0000000..3b236d8
--- /dev/null
@@ -0,0 +1,91 @@
+// 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.
+
+syntax = "proto3";
+
+package promise_fuzzer;
+
+message Seq {
+    Promise first = 1;
+    repeated PromiseFactory promise_factories = 2;
+}
+
+message Join {
+    repeated Promise promises = 1;
+}
+
+message Race {
+    repeated Promise promises = 1;
+}
+
+message Last {}
+
+message PromiseFactory {
+    oneof promise_factory_type {
+        // Return a specific promise
+        Promise promise = 1;
+        // Return the result of the last thing
+        Last last = 2;
+    }
+}
+
+message Never {}
+
+message ScheduleWaker {
+  bool owning = 1;
+  int32 waker = 2;
+}
+
+message Promise {
+    oneof promise_type {
+        // Seq combinator
+        Seq seq = 1;
+        // Join combinator
+        Join join = 2;
+        // Race combinator
+        Race race = 3;
+        // Never complete
+        Never never = 4;
+        // Sleep n times, then wakeup
+        int32 sleep_first_n = 5;
+        // Cancel and be pending
+        Cancel cancel_from_inside = 6;
+        // Wait for waker n, then continue
+        ScheduleWaker wait_once_on_waker = 7;
+    }
+}
+
+message Cancel {}
+
+message Wakeup {}
+
+message Action {
+    oneof action_type {
+        // Activity::ForceWakeup
+        Wakeup force_wakeup = 1;
+        // Cancel the activity
+        Cancel cancel = 2;
+        // Flush any pending scheduled wakeups
+        Wakeup flush_wakeup = 3;
+        // Awake waker n if it exists
+        int32 awake_waker = 4;
+        // Drop waker n if it exists
+        int32 drop_waker = 5;
+    }
+}
+
+message Msg {
+    Promise promise = 1;
+    repeated Action actions = 2;
+}
diff --git a/test/core/promise/promise_fuzzer_corpus/b858cb282617fb0956d960215c8e84d1ccf909c6 b/test/core/promise/promise_fuzzer_corpus/b858cb282617fb0956d960215c8e84d1ccf909c6
new file mode 100644 (file)
index 0000000..0519ecb
--- /dev/null
@@ -0,0 +1 @@
\ No newline at end of file
diff --git a/test/core/promise/promise_fuzzer_corpus/crash-4758aec0c3e382d4fb3e398d634d8da72ed0d574 b/test/core/promise/promise_fuzzer_corpus/crash-4758aec0c3e382d4fb3e398d634d8da72ed0d574
new file mode 100644 (file)
index 0000000..9b9d8c0
--- /dev/null
@@ -0,0 +1,20 @@
+promise {
+  race {
+    promises {
+      cancel_from_inside {
+      }
+    }
+    promises {
+      sleep_first_n: 0
+    }
+    promises {
+      sleep_first_n: 2097151999
+    }
+    promises {
+    }
+  }
+}
+actions {
+  flush_wakeup {
+  }
+}
diff --git a/test/core/promise/promise_fuzzer_corpus/leak-90b749c0ca79c7a11d25f4b6f0594af99fe4a78f b/test/core/promise/promise_fuzzer_corpus/leak-90b749c0ca79c7a11d25f4b6f0594af99fe4a78f
new file mode 100644 (file)
index 0000000..623431d
--- /dev/null
@@ -0,0 +1,12 @@
+promise {
+  never {
+  }
+}
+actions {
+  force_wakeup {
+  }
+}
+actions {
+  force_wakeup {
+  }
+}
diff --git a/test/core/promise/test_wakeup_schedulers.h b/test/core/promise/test_wakeup_schedulers.h
new file mode 100644 (file)
index 0000000..7105af4
--- /dev/null
@@ -0,0 +1,64 @@
+// 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.
+
+#ifndef GRPC_TEST_CORE_PROMISE_TEST_WAKEUP_SCHEDULERS_H
+#define GRPC_TEST_CORE_PROMISE_TEST_WAKEUP_SCHEDULERS_H
+
+#include <gmock/gmock.h>
+
+namespace grpc_core {
+
+// A wakeup scheduler that simply crashes.
+// Useful for very limited tests.
+struct NoWakeupScheduler {
+  template <typename ActivityType>
+  void ScheduleWakeup(ActivityType*) {
+    abort();
+  }
+};
+
+// A wakeup scheduler that simply runs the callback immediately.
+// Useful for unit testing, probably not so much for real systems due to lock
+// ordering problems.
+struct InlineWakeupScheduler {
+  template <typename ActivityType>
+  void ScheduleWakeup(ActivityType* activity) {
+    activity->RunScheduledWakeup();
+  }
+};
+
+// Mock for something that can schedule callbacks.
+class MockCallbackScheduler {
+ public:
+  MOCK_METHOD(void, Schedule, (std::function<void()>));
+};
+
+// WakeupScheduler that schedules wakeups against a MockCallbackScheduler.
+// Usage:
+// TEST(..., ...) {
+//   MockCallbackScheduler scheduler;
+//   auto activity = MakeActivity(...,
+//                                UseMockCallbackScheduler(&scheduler),
+//                                ...);
+struct UseMockCallbackScheduler {
+  MockCallbackScheduler* scheduler;
+  template <typename ActivityType>
+  void ScheduleWakeup(ActivityType* activity) {
+    scheduler->Schedule([activity] { activity->RunScheduledWakeup(); });
+  }
+};
+
+}  // namespace grpc_core
+
+#endif
diff --git a/test/core/resource_quota/BUILD b/test/core/resource_quota/BUILD
new file mode 100644 (file)
index 0000000..69b4df4
--- /dev/null
@@ -0,0 +1,104 @@
+# 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.
+
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_package")
+
+licenses(["notice"])
+
+grpc_package(name = "test/core/resource_quota")
+
+load("//test/core/util:grpc_fuzzer.bzl", "grpc_proto_fuzzer")
+
+grpc_cc_library(
+    name = "call_checker",
+    testonly = True,
+    hdrs = ["call_checker.h"],
+    language = "c++",
+    deps = ["//:gpr"],
+)
+
+grpc_cc_test(
+    name = "memory_quota_test",
+    srcs = ["memory_quota_test.cc"],
+    external_deps = [
+        "gtest",
+    ],
+    language = "c++",
+    uses_polling = False,
+    deps = [
+        "call_checker",
+        "//:memory_quota",
+        "//test/core/util:grpc_suppressions",
+    ],
+)
+
+grpc_cc_test(
+    name = "thread_quota_test",
+    srcs = ["thread_quota_test.cc"],
+    external_deps = [
+        "gtest",
+    ],
+    language = "c++",
+    uses_polling = False,
+    deps = [
+        "//:thread_quota",
+        "//test/core/util:grpc_suppressions",
+    ],
+)
+
+grpc_cc_test(
+    name = "resource_quota_test",
+    srcs = ["resource_quota_test.cc"],
+    external_deps = [
+        "gtest",
+    ],
+    language = "c++",
+    uses_polling = False,
+    deps = [
+        "//:resource_quota",
+        "//test/core/util:grpc_suppressions",
+    ],
+)
+
+grpc_cc_test(
+    name = "memory_quota_stress_test",
+    srcs = ["memory_quota_stress_test.cc"],
+    language = "c++",
+    # We only run this test under Linux, and really only care about the
+    # TSAN results.
+    tags = [
+        "no_mac",
+        "no_windows",
+    ],
+    uses_polling = False,
+    deps = [
+        "//:memory_quota",
+        "//test/core/util:grpc_suppressions",
+    ],
+)
+
+grpc_proto_fuzzer(
+    name = "memory_quota_fuzzer",
+    srcs = ["memory_quota_fuzzer.cc"],
+    corpus = "memory_quota_fuzzer_corpus",
+    language = "C++",
+    proto = "memory_quota_fuzzer.proto",
+    tags = ["no_windows"],
+    uses_polling = False,
+    deps = [
+        "call_checker",
+        "//:memory_quota",
+        "//test/core/util:grpc_test_util",
+    ],
+)
diff --git a/test/core/resource_quota/call_checker.h b/test/core/resource_quota/call_checker.h
new file mode 100644 (file)
index 0000000..5fbf769
--- /dev/null
@@ -0,0 +1,52 @@
+// 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.
+
+#ifndef LOCAL_GOOGLE_HOME_CTILLER_GRPC_TEST_CORE_RESOURCE_QUOTA_CALL_CHECKER_H_
+#define LOCAL_GOOGLE_HOME_CTILLER_GRPC_TEST_CORE_RESOURCE_QUOTA_CALL_CHECKER_H_
+
+#include <memory>
+
+#include <grpc/support/log.h>
+
+namespace grpc_core {
+namespace testing {
+
+// Utility to help check a function is called.
+// Usage:
+// auto checker = CallChecker::Make();
+// auto f = [checker]() {
+//   checker.Called();
+// };
+// Will crash if: f never called, or f called more than once.
+class CallChecker {
+ public:
+  ~CallChecker() { GPR_ASSERT(called_); }
+
+  void Called() {
+    GPR_ASSERT(!called_);
+    called_ = true;
+  }
+
+  static std::shared_ptr<CallChecker> Make() {
+    return std::make_shared<CallChecker>();
+  }
+
+ private:
+  bool called_ = false;
+};
+
+}  // namespace testing
+}  // namespace grpc_core
+
+#endif  // LOCAL_GOOGLE_HOME_CTILLER_GRPC_TEST_CORE_RESOURCE_QUOTA_CALL_CHECKER_H_
diff --git a/test/core/resource_quota/memory_quota_fuzzer.cc b/test/core/resource_quota/memory_quota_fuzzer.cc
new file mode 100644 (file)
index 0000000..b3326f5
--- /dev/null
@@ -0,0 +1,181 @@
+// 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 <map>
+
+#include "src/core/lib/gpr/useful.h"
+#include "src/core/lib/iomgr/exec_ctx.h"
+#include "src/core/lib/resource_quota/memory_quota.h"
+#include "src/libfuzzer/libfuzzer_macro.h"
+#include "test/core/resource_quota/call_checker.h"
+#include "test/core/resource_quota/memory_quota_fuzzer.pb.h"
+
+bool squelch = true;
+bool leak_check = true;
+
+namespace grpc_core {
+namespace testing {
+namespace {
+ReclamationPass MapReclamationPass(memory_quota_fuzzer::Reclaimer::Pass pass) {
+  switch (pass) {
+    case memory_quota_fuzzer::Reclaimer::BENIGN:
+      return ReclamationPass::kBenign;
+    case memory_quota_fuzzer::Reclaimer::IDLE:
+      return ReclamationPass::kIdle;
+    case memory_quota_fuzzer::Reclaimer::DESTRUCTIVE:
+      return ReclamationPass::kDestructive;
+    default:
+      return ReclamationPass::kBenign;
+  }
+}
+
+class Fuzzer {
+ public:
+  void Run(const memory_quota_fuzzer::Msg& msg) {
+    grpc_core::ExecCtx exec_ctx;
+    RunMsg(msg);
+    do {
+      memory_quotas_.clear();
+      memory_allocators_.clear();
+      allocations_.clear();
+      exec_ctx.Flush();
+    } while (!memory_quotas_.empty() || !memory_allocators_.empty() ||
+             !allocations_.empty());
+  }
+
+ private:
+  void RunMsg(const memory_quota_fuzzer::Msg& msg) {
+    for (int i = 0; i < msg.actions_size(); ++i) {
+      const auto& action = msg.actions(i);
+      switch (action.action_type_case()) {
+        case memory_quota_fuzzer::Action::kFlushExecCtx:
+          ExecCtx::Get()->Flush();
+          break;
+        case memory_quota_fuzzer::Action::kCreateQuota:
+          memory_quotas_.emplace(action.quota(), MemoryQuota());
+          break;
+        case memory_quota_fuzzer::Action::kDeleteQuota:
+          memory_quotas_.erase(action.quota());
+          break;
+        case memory_quota_fuzzer::Action::kCreateAllocator:
+          WithQuota(action.quota(), [this, action](MemoryQuota* q) {
+            memory_allocators_.emplace(action.allocator(),
+                                       q->CreateMemoryOwner());
+          });
+          break;
+        case memory_quota_fuzzer::Action::kDeleteAllocator:
+          memory_allocators_.erase(action.allocator());
+          break;
+        case memory_quota_fuzzer::Action::kSetQuotaSize:
+          WithQuota(action.quota(), [action](MemoryQuota* q) {
+            q->SetSize(Clamp(action.set_quota_size(), uint64_t{0},
+                             uint64_t{std::numeric_limits<ssize_t>::max()}));
+          });
+          break;
+        case memory_quota_fuzzer::Action::kRebindQuota:
+          WithQuota(action.quota(), [this, action](MemoryQuota* q) {
+            WithAllocator(action.allocator(),
+                          [q](MemoryOwner* a) { a->Rebind(q); });
+          });
+          break;
+        case memory_quota_fuzzer::Action::kCreateAllocation: {
+          auto min = action.create_allocation().min();
+          auto max = action.create_allocation().max();
+          if (min > max) break;
+          if (max > MemoryRequest::max_allowed_size()) break;
+          MemoryRequest req(min, max);
+          WithAllocator(
+              action.allocator(), [this, action, req](MemoryOwner* a) {
+                auto alloc = a->allocator()->MakeReservation(req);
+                allocations_.emplace(action.allocation(), std::move(alloc));
+              });
+        } break;
+        case memory_quota_fuzzer::Action::kDeleteAllocation:
+          allocations_.erase(action.allocation());
+          break;
+        case memory_quota_fuzzer::Action::kPostReclaimer: {
+          std::function<void(absl::optional<ReclamationSweep>)> reclaimer;
+          auto cfg = action.post_reclaimer();
+          if (cfg.synchronous()) {
+            reclaimer = [this, cfg](absl::optional<ReclamationSweep>) {
+              RunMsg(cfg.msg());
+            };
+          } else {
+            reclaimer = [cfg, this](absl::optional<ReclamationSweep> sweep) {
+              struct Args {
+                absl::optional<ReclamationSweep> sweep;
+                memory_quota_fuzzer::Msg msg;
+                Fuzzer* fuzzer;
+              };
+              auto* args = new Args{std::move(sweep), cfg.msg(), this};
+              auto* closure = GRPC_CLOSURE_CREATE(
+                  [](void* arg, grpc_error_handle) {
+                    auto* args = static_cast<Args*>(arg);
+                    args->fuzzer->RunMsg(args->msg);
+                    delete args;
+                  },
+                  args, nullptr);
+              ExecCtx::Get()->Run(DEBUG_LOCATION, closure, GRPC_ERROR_NONE);
+            };
+            auto pass = MapReclamationPass(cfg.pass());
+            WithAllocator(
+                action.allocator(), [pass, reclaimer](MemoryOwner* a) {
+                  // ensure called exactly once
+                  auto call_checker = CallChecker::Make();
+                  a->PostReclaimer(pass,
+                                   [reclaimer, call_checker](
+                                       absl::optional<ReclamationSweep> sweep) {
+                                     call_checker->Called();
+                                     reclaimer(std::move(sweep));
+                                   });
+                });
+          }
+        } break;
+        case memory_quota_fuzzer::Action::ACTION_TYPE_NOT_SET:
+          break;
+      }
+    }
+  }
+
+  template <typename F>
+  void WithQuota(int quota, F f) {
+    auto it = memory_quotas_.find(quota);
+    if (it == memory_quotas_.end()) return;
+    f(&it->second);
+  }
+
+  template <typename F>
+  void WithAllocator(int allocator, F f) {
+    auto it = memory_allocators_.find(allocator);
+    if (it == memory_allocators_.end()) return;
+    f(&it->second);
+  }
+
+  std::map<int, MemoryQuota> memory_quotas_;
+  std::map<int, MemoryOwner> memory_allocators_;
+  std::map<int, MemoryAllocator::Reservation> allocations_;
+};
+
+}  // namespace
+}  // namespace testing
+}  // namespace grpc_core
+
+static void dont_log(gpr_log_func_args* /*args*/) {}
+
+DEFINE_PROTO_FUZZER(const memory_quota_fuzzer::Msg& msg) {
+  if (squelch) gpr_set_log_function(dont_log);
+  gpr_log_verbosity_init();
+  grpc_tracer_init();
+  grpc_core::testing::Fuzzer().Run(msg);
+}
diff --git a/test/core/resource_quota/memory_quota_fuzzer.proto b/test/core/resource_quota/memory_quota_fuzzer.proto
new file mode 100644 (file)
index 0000000..63d8a2e
--- /dev/null
@@ -0,0 +1,57 @@
+// 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.
+
+syntax = "proto3";
+
+package memory_quota_fuzzer;
+
+message Empty {}
+
+message Reclaimer {
+    enum Pass {
+        BENIGN = 0;
+        IDLE = 1;
+        DESTRUCTIVE = 2;
+    }
+    bool synchronous = 1;
+    Pass pass = 2;
+    Msg msg = 3;
+}
+
+message AllocationRequest {
+    uint32 min = 1;
+    uint32 max = 2;
+}
+
+message Action {
+    int32 quota = 1;
+    int32 allocator = 2;
+    int32 allocation = 3;
+    oneof action_type {
+        Empty flush_exec_ctx = 7;
+        Empty create_quota = 10;
+        Empty delete_quota = 11;
+        Empty create_allocator = 12;
+        Empty delete_allocator = 13;
+        uint64 set_quota_size = 14;
+        Empty rebind_quota = 15;
+        AllocationRequest create_allocation = 16;
+        Empty delete_allocation = 17;
+        Reclaimer post_reclaimer = 18;
+    }
+}
+
+message Msg {
+    repeated Action actions = 2;
+}
diff --git a/test/core/resource_quota/memory_quota_fuzzer_corpus/0 b/test/core/resource_quota/memory_quota_fuzzer_corpus/0
new file mode 100644 (file)
index 0000000..8b13789
--- /dev/null
@@ -0,0 +1 @@
+
diff --git a/test/core/resource_quota/memory_quota_fuzzer_corpus/nullchk b/test/core/resource_quota/memory_quota_fuzzer_corpus/nullchk
new file mode 100644 (file)
index 0000000..0b2ed44
--- /dev/null
@@ -0,0 +1,21 @@
+actions {
+  create_quota {}
+}
+actions {
+  create_allocator {}
+}
+actions {
+  post_reclaimer {
+    msg {
+      actions {
+        create_quota {}
+      }
+      actions {
+        create_allocator {}
+      }
+      actions {
+        post_reclaimer {}
+      }
+    }
+  }
+}
diff --git a/test/core/resource_quota/memory_quota_fuzzer_corpus/testcase-4574576847224832 b/test/core/resource_quota/memory_quota_fuzzer_corpus/testcase-4574576847224832
new file mode 100644 (file)
index 0000000..27d9241
--- /dev/null
@@ -0,0 +1,859 @@
+actions {
+  quota: 7496448
+}
+actions {
+  quota: 2048
+  allocator: 2162720
+  create_quota {
+  }
+}
+actions {
+  quota: 2048
+  allocator: 144
+  allocation: 4225395
+}
+actions {
+  quota: 2048
+  allocation: 8
+}
+actions {
+  quota: 262152
+  allocator: 117440513
+  allocation: 6
+}
+actions {
+  quota: 2048
+  allocator: 111
+  allocation: 2048
+}
+actions {
+  quota: 2048
+  allocator: 6
+  allocation: 2048
+  set_quota_size: 0
+}
+actions {
+  allocator: 175972352
+}
+actions {
+  quota: 2048
+  allocator: 2048
+}
+actions {
+  quota: 2049
+  allocator: 2048
+  allocation: 3
+}
+actions {
+  quota: 2048
+  allocator: 2048
+  allocation: 2048
+}
+actions {
+  quota: 16713728
+  allocator: 2048
+}
+actions {
+  allocator: 30768
+}
+actions {
+  quota: 2048
+  allocator: 6
+  allocation: 117440513
+}
+actions {
+  quota: 2048
+  allocator: 2048
+  allocation: 9459968
+}
+actions {
+  allocator: 6
+  allocation: -65536
+}
+actions {
+  quota: 2048
+  allocator: 218103807
+  allocation: 2048
+}
+actions {
+  quota: 111
+}
+actions {
+  quota: 6
+  allocator: 6
+  allocation: 3
+  delete_quota {
+  }
+}
+actions {
+  quota: 2162720
+  allocator: 1
+  allocation: 9437184
+  delete_allocator {
+  }
+}
+actions {
+  quota: 2048
+  allocator: 111
+  allocation: -196608
+}
+actions {
+  quota: 111
+  allocator: 6
+  allocation: 2048
+}
+actions {
+}
+actions {
+  quota: 2048
+  allocator: 6
+  allocation: 2048
+  set_quota_size: 2785017856
+}
+actions {
+  quota: 2048
+  allocator: 117440513
+  allocation: 2048
+}
+actions {
+  quota: 2048
+  allocator: 111
+  allocation: -196608
+  create_allocation {
+    max: 1986199552
+  }
+}
+actions {
+  quota: 2048
+  allocator: 111
+  allocation: 2048
+  set_quota_size: 0
+}
+actions {
+  allocation: 256
+}
+actions {
+  quota: 2048
+  allocator: 2048
+  allocation: 2048
+}
+actions {
+  quota: 2048
+  allocator: 117440513
+  allocation: 9437184
+}
+actions {
+  quota: 2048
+  allocator: 507
+  allocation: -65536
+}
+actions {
+  quota: 2048
+  allocator: 28416
+  allocation: 2048
+  set_quota_size: 0
+}
+actions {
+}
+actions {
+  quota: 2048
+  allocator: 6
+  allocation: 2048
+  create_allocator {
+  }
+}
+actions {
+  quota: 2048
+  allocator: 65543
+  allocation: 2048
+  create_allocator {
+  }
+}
+actions {
+  quota: 2048
+  allocator: 111
+  allocation: -196608
+}
+actions {
+  quota: 2048
+  allocator: 111
+  allocation: 6
+  set_quota_size: 0
+}
+actions {
+}
+actions {
+  quota: 2048
+  allocator: 1
+}
+actions {
+  quota: 2048
+  allocator: 2099835
+  allocation: 9437184
+  create_allocator {
+  }
+}
+actions {
+  quota: 2048
+  allocator: 111
+  allocation: 2048
+  create_allocator {
+  }
+}
+actions {
+  quota: 2048
+  allocator: 111
+  allocation: 2048
+}
+actions {
+  delete_quota {
+  }
+}
+actions {
+  quota: 2048
+  allocator: -2
+  allocation: 2048
+  set_quota_size: 0
+}
+actions {
+  quota: 2048
+  allocator: 1
+  allocation: 2048
+}
+actions {
+  quota: 2048
+  allocator: 111
+  allocation: 2048
+}
+actions {
+  quota: 2048
+  allocator: 111
+  allocation: 2099488
+  create_allocation {
+  }
+}
+actions {
+  allocator: 61295
+}
+actions {
+  quota: 2048
+  allocation: 2048
+  create_allocator {
+  }
+}
+actions {
+  quota: 2048
+  allocator: 117440513
+  allocation: 9437184
+  set_quota_size: 2785017856
+}
+actions {
+  quota: 2048
+  allocator: 6
+  allocation: 9437184
+}
+actions {
+  quota: -5
+  allocator: 111
+  allocation: 2048
+  set_quota_size: 0
+}
+actions {
+}
+actions {
+  quota: 2048
+  allocator: 6
+  allocation: 2048
+  create_allocator {
+  }
+}
+actions {
+  allocator: 117440513
+  allocation: 9437184
+  create_allocator {
+  }
+}
+actions {
+  quota: 2048
+  allocator: 111
+  allocation: 111
+}
+actions {
+  quota: 2048
+  allocator: 4
+  allocation: 2048
+}
+actions {
+  quota: 6
+}
+actions {
+  quota: 2048
+  allocator: 6
+  allocation: 16775680
+  create_allocator {
+  }
+}
+actions {
+  quota: 2048
+  allocator: 117440513
+  create_allocator {
+  }
+}
+actions {
+  quota: 2048
+  allocator: 111
+  allocation: -196608
+}
+actions {
+  quota: 2048
+  allocator: 65
+  set_quota_size: 0
+}
+actions {
+}
+actions {
+  quota: 2048
+  allocator: 6
+  allocation: 2048
+  post_reclaimer {
+    pass: IDLE
+    msg {
+      actions {
+        post_reclaimer {
+          pass: IDLE
+          msg {
+            actions {
+              create_allocation {
+              }
+            }
+            actions {
+              create_allocation {
+              }
+            }
+            actions {
+              quota: 2048
+              allocation: 3
+              delete_quota {
+              }
+            }
+            actions {
+              post_reclaimer {
+                pass: IDLE
+                msg {
+                  actions {
+                    allocation: 1862299392
+                    create_allocation {
+                      max: 14624
+                    }
+                  }
+                  actions {
+                    create_allocation {
+                    }
+                  }
+                  actions {
+                    delete_quota {
+                    }
+                  }
+                  actions {
+                    post_reclaimer {
+                      msg {
+                        actions {
+                          create_allocation {
+                            max: 14624
+                          }
+                        }
+                        actions {
+                          create_allocation {
+                          }
+                        }
+                        actions {
+                          quota: 2048
+                          allocator: 2048
+                          set_quota_size: 0
+                        }
+                        actions {
+                          quota: 2048
+                          allocation: 3
+                        }
+                        actions {
+                          post_reclaimer {
+                            pass: IDLE
+                            msg {
+                              actions {
+                                create_allocation {
+                                  max: 14624
+                                }
+                              }
+                              actions {
+                              }
+                              actions {
+                              }
+                              actions {
+                                set_quota_size: 0
+                              }
+                            }
+                          }
+                        }
+                        actions {
+                          create_allocation {
+                          }
+                        }
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+      actions {
+        allocator: -256
+        allocation: 2048
+      }
+      actions {
+        quota: 111
+        create_allocation {
+          max: 14624
+        }
+      }
+    }
+  }
+}
+actions {
+  quota: 536832
+  allocator: 117440513
+  allocation: 9437184
+  create_allocator {
+  }
+}
+actions {
+  quota: 2048
+  allocator: 111
+  allocation: -9671427
+  create_allocation {
+    max: 1024
+  }
+}
+actions {
+  quota: 2048
+  allocator: 111
+  allocation: 2048
+}
+actions {
+}
+actions {
+  quota: 2048
+  allocator: 28416
+  allocation: 12544
+  create_allocator {
+  }
+}
+actions {
+  quota: -5
+  allocator: 2048
+  allocation: 9437184
+}
+actions {
+  quota: 2048
+  allocator: -196608
+  allocation: -196608
+}
+actions {
+  quota: 2048
+  allocator: 6
+  allocation: 2048
+  post_reclaimer {
+    msg {
+      actions {
+      }
+      actions {
+        create_allocation {
+        }
+      }
+      actions {
+        quota: 111
+        allocator: 4
+        allocation: 536870912
+      }
+      actions {
+        quota: 2048
+        allocator: -5
+        allocation: 65
+        create_allocator {
+        }
+      }
+      actions {
+        quota: 4259840
+        allocator: -5
+        allocation: 771763712
+        create_allocator {
+        }
+      }
+      actions {
+        allocator: 2048
+        post_reclaimer {
+          pass: DESTRUCTIVE
+          msg {
+            actions {
+            }
+            actions {
+              allocation: 65
+              create_allocation {
+              }
+            }
+            actions {
+              create_allocation {
+              }
+            }
+            actions {
+              quota: 2
+              post_reclaimer {
+                pass: IDLE
+                msg {
+                  actions {
+                  }
+                  actions {
+                    create_allocation {
+                    }
+                  }
+                  actions {
+                    quota: 2048
+                    allocation: 3
+                  }
+                  actions {
+                    allocation: 2048
+                    post_reclaimer {
+                      pass: IDLE
+                      msg {
+                        actions {
+                          create_allocation {
+                            max: 14624
+                          }
+                        }
+                        actions {
+                          create_allocation {
+                          }
+                        }
+                        actions {
+                        }
+                        actions {
+                        }
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+}
+actions {
+  quota: 111
+}
+actions {
+  quota: 2048
+  allocator: 6
+  allocation: 2048
+  create_allocator {
+  }
+}
+actions {
+  quota: 2048
+  allocator: 2048
+  allocation: 9437184
+  create_allocator {
+  }
+}
+actions {
+  quota: 2048
+  allocator: 6
+  allocation: -196608
+}
+actions {
+  quota: 2048
+  allocator: 111
+  allocation: 2048
+  set_quota_size: 0
+}
+actions {
+  quota: 2048
+  allocator: 8
+  allocation: 9437184
+}
+actions {
+  quota: 2048
+  allocation: 301989889
+  create_allocator {
+  }
+}
+actions {
+  quota: 2048
+  allocator: 2048
+  allocation: 9437184
+  create_allocation {
+    max: 14624
+  }
+}
+actions {
+  quota: 111
+  allocator: 117440513
+  allocation: -1869611008
+  create_allocation {
+    max: 1986199552
+  }
+}
+actions {
+  quota: 2048
+  allocator: 111
+}
+actions {
+  allocator: 111
+  flush_exec_ctx {
+  }
+}
+actions {
+  quota: 9437184
+  allocator: 4
+}
+actions {
+  quota: 2048
+  allocator: 16779008
+  allocation: 6
+  rebind_quota {
+  }
+}
+actions {
+  allocator: 79
+  allocation: 2048
+}
+actions {
+  quota: 2048
+  allocator: 111
+  allocation: 2048
+  set_quota_size: 16646144
+}
+actions {
+}
+actions {
+  quota: 2048
+  allocator: 6
+  allocation: 12544
+  create_allocator {
+  }
+}
+actions {
+  quota: 2048
+  allocator: 1792
+  allocation: 9437184
+}
+actions {
+  quota: 65
+  allocator: 6
+  allocation: -196608
+  post_reclaimer {
+  }
+}
+actions {
+  quota: 2048
+  allocator: 6
+  allocation: 2048
+  post_reclaimer {
+    msg {
+      actions {
+        create_quota {
+        }
+      }
+      actions {
+        create_allocation {
+        }
+      }
+      actions {
+        allocator: 111
+        allocation: 536870912
+      }
+      actions {
+        quota: 2048
+        allocator: -5
+        allocation: 2048
+      }
+      actions {
+        quota: 4259840
+        allocator: -5
+        allocation: 65
+        create_allocation {
+          min: 32
+          max: 32
+        }
+      }
+      actions {
+        allocator: 2048
+        post_reclaimer {
+          pass: DESTRUCTIVE
+          msg {
+            actions {
+            }
+            actions {
+              allocation: 65
+              create_allocation {
+              }
+            }
+            actions {
+              allocator: 908081664
+              delete_allocation {
+              }
+            }
+            actions {
+              quota: 111
+              post_reclaimer {
+                pass: IDLE
+                msg {
+                  actions {
+                    post_reclaimer {
+                      msg {
+                        actions {
+                          create_allocation {
+                          }
+                        }
+                        actions {
+                          create_allocation {
+                          }
+                        }
+                        actions {
+                          quota: 2048
+                          allocation: 3
+                          delete_quota {
+                          }
+                        }
+                        actions {
+                          post_reclaimer {
+                            pass: IDLE
+                            msg {
+                              actions {
+                                allocation: 1862299392
+                                create_allocation {
+                                  max: 32
+                                }
+                              }
+                              actions {
+                                create_allocation {
+                                }
+                              }
+                              actions {
+                                delete_quota {
+                                }
+                              }
+                              actions {
+                                post_reclaimer {
+                                  pass: IDLE
+                                  msg {
+                                    actions {
+                                      create_allocation {
+                                        max: 14624
+                                      }
+                                    }
+                                    actions {
+                                      create_allocation {
+                                      }
+                                    }
+                                    actions {
+                                      quota: 2048
+                                      allocator: 111
+                                      allocation: 111
+                                      set_quota_size: 0
+                                    }
+                                    actions {
+                                      quota: 2048
+                                      allocation: 3
+                                    }
+                                    actions {
+                                      post_reclaimer {
+                                        pass: IDLE
+                                        msg {
+                                          actions {
+                                            create_allocation {
+                                              max: 14624
+                                            }
+                                          }
+                                          actions {
+                                            create_allocation {
+                                            }
+                                          }
+                                          actions {
+                                          }
+                                          actions {
+                                            set_quota_size: 0
+                                          }
+                                        }
+                                      }
+                                    }
+                                    actions {
+                                      create_allocation {
+                                      }
+                                    }
+                                  }
+                                }
+                              }
+                            }
+                          }
+                        }
+                      }
+                    }
+                  }
+                  actions {
+                    allocator: 61295
+                  }
+                  actions {
+                    create_allocation {
+                      max: 14624
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+}
+actions {
+}
+actions {
+  quota: 204
+  create_allocation {
+    max: 1
+  }
+}
+actions {
+  allocator: 111
+  allocation: 9437184
+  create_allocation {
+    max: 3
+  }
+}
+actions {
+  quota: 2048
+  allocator: 111
+  flush_exec_ctx {
+  }
+}
+actions {
+  allocator: 111
+  create_quota {
+  }
+}
+actions {
+  quota: 9437184
+}
+actions {
+  quota: 2048
+  allocator: 16779008
+  allocation: -7706983
+  create_allocator {
+  }
+}
+
diff --git a/test/core/resource_quota/memory_quota_fuzzer_corpus/testcase-4574576847224832-after-creduce b/test/core/resource_quota/memory_quota_fuzzer_corpus/testcase-4574576847224832-after-creduce
new file mode 100644 (file)
index 0000000..fd17f6e
--- /dev/null
@@ -0,0 +1,9 @@
+actions {
+  create_quota {}
+}
+actions {
+  create_allocator {}
+}
+actions {
+  create_allocation {}
+}
diff --git a/test/core/resource_quota/memory_quota_fuzzer_corpus/testcase-5651890842501120 b/test/core/resource_quota/memory_quota_fuzzer_corpus/testcase-5651890842501120
new file mode 100644 (file)
index 0000000..adbbc74
--- /dev/null
@@ -0,0 +1,58 @@
+actions {
+  allocator: 15
+  allocation: 15
+  create_quota {
+  }
+}
+actions {
+  allocation: 72
+  create_allocator {
+  }
+}
+actions {
+  set_quota_size: 0
+}
+actions {
+  quota: 655360
+  post_reclaimer {
+    pass: DESTRUCTIVE
+    msg {
+      actions {
+        allocation: 1024
+        post_reclaimer {
+          pass: DESTRUCTIVE
+          msg {
+            actions {
+              quota: 83
+              allocation: 4
+              create_quota {
+              }
+            }
+            actions {
+              post_reclaimer {
+                msg {
+                  actions {
+                    quota: 83
+                    allocation: 4
+                    rebind_quota {
+                    }
+                  }
+                  actions {
+                    delete_quota {
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+}
+actions {
+  quota: 32840
+  allocation: 72
+  flush_exec_ctx {
+  }
+}
diff --git a/test/core/resource_quota/memory_quota_fuzzer_corpus/testcase-replenish-nullchk b/test/core/resource_quota/memory_quota_fuzzer_corpus/testcase-replenish-nullchk
new file mode 100644 (file)
index 0000000..e3df978
--- /dev/null
@@ -0,0 +1,1601 @@
+actions {
+  quota: 2
+  create_quota {
+  }
+}
+actions {
+  quota: 2
+  allocator: 8704
+  allocation: 2
+  set_quota_size: 171798691840
+}
+actions {
+  quota: 2
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+}
+actions {
+  quota: 2
+  allocator: -1610612735
+  create_allocator {
+  }
+}
+actions {
+  quota: -1610612735
+  allocation: 7
+}
+actions {
+  quota: 2
+  allocator: 10682370
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocation: 3
+  create_allocator {
+  }
+}
+actions {
+  allocator: 44
+  allocation: 2
+  flush_exec_ctx {
+  }
+}
+actions {
+  quota: 2
+}
+actions {
+  quota: 2
+  allocator: 2
+  allocation: 2
+  post_reclaimer {
+    pass: DESTRUCTIVE
+  }
+}
+actions {
+}
+actions {
+  quota: 2
+  allocator: 2
+}
+actions {
+  quota: 2
+  allocator: 7
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  allocator: 44
+  delete_quota {
+  }
+}
+actions {
+  allocation: 2
+}
+actions {
+  rebind_quota {
+  }
+}
+actions {
+  quota: 2
+  allocator: 45
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+}
+actions {
+  quota: 2
+  allocator: 2
+  allocation: 2
+  flush_exec_ctx {
+  }
+}
+actions {
+  delete_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 2
+  delete_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 7
+}
+actions {
+  quota: 2
+  allocator: 8704
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocation: 7
+  set_quota_size: 0
+}
+actions {
+  quota: 2
+  allocator: 44
+  allocation: 2
+}
+actions {
+  quota: 2
+}
+actions {
+  quota: 2
+  allocator: 2
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  delete_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 2
+  delete_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: -2147483641
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  allocator: 7
+  delete_allocator {
+  }
+}
+actions {
+  allocation: 2
+}
+actions {
+  rebind_quota {
+  }
+}
+actions {
+  quota: 2
+  allocator: 44
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+}
+actions {
+  quota: 2
+  allocator: 2
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  create_quota {
+  }
+}
+actions {
+  quota: 2
+  allocator: 2
+  delete_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 7
+}
+actions {
+  quota: 2
+  allocation: 2
+}
+actions {
+  quota: 44
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  allocator: 7
+  delete_allocator {
+  }
+}
+actions {
+  allocation: 2
+}
+actions {
+  rebind_quota {
+  }
+}
+actions {
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 44
+}
+actions {
+  quota: 2
+  allocator: 8704
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocation: 7
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 44
+  allocation: 2
+}
+actions {
+}
+actions {
+  quota: 2
+  allocator: 2
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+}
+actions {
+  quota: 2
+  allocator: 2
+  delete_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 7
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  allocator: 7
+  delete_allocator {
+  }
+}
+actions {
+  allocation: 7
+}
+actions {
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 44
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+}
+actions {
+  quota: 2
+  allocator: 2
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  delete_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 2
+  delete_allocator {
+  }
+}
+actions {
+  allocator: 7
+}
+actions {
+  quota: 2
+  allocator: 8704
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocation: 7
+}
+actions {
+  quota: 2
+  allocator: 44
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+}
+actions {
+  quota: 2
+  allocator: 2
+  allocation: 2
+}
+actions {
+  quota: 2
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+}
+actions {
+  quota: 2
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocation: 42
+}
+actions {
+  quota: 2
+  allocator: 44
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+}
+actions {
+  quota: 2
+  allocator: 2097152
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  delete_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 2
+  delete_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 7
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  allocator: 7
+  delete_allocator {
+  }
+}
+actions {
+  allocation: 2
+}
+actions {
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 44
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+}
+actions {
+  quota: 2
+  allocator: 2
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  allocation: 44
+  delete_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 2
+  delete_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 7
+}
+actions {
+  quota: 2
+  allocator: 8704
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  create: 2
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocation: 7
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  create_allocator {
+  }
+}
+actions {
+}
+actions {
+  quota: 2
+  allocator: 2
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+}
+actions {
+  quota: 2
+  allocator: 2
+  set_quota_size: 171790
+}
+actions {
+  quota: 2
+  allocator: 2
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocation: 140
+  create_allocator {
+  }
+}
+actions {
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  quota: 67108864
+}
+actions {
+  quota: 2
+  allocator: 2
+  allocation: 2
+  delete_quota {
+  }
+}
+actions {
+}
+actions {
+  quota: 10
+  allocator: 2
+  delete_allocator {
+  }
+}
+actions {
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  allocator: 7
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  allocator: 7
+  delete_allocator {
+  }
+}
+actions {
+  allocation: 2
+}
+actions {
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 45
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+}
+actions {
+  quota: 2
+  allocator: 2
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  delete_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 2
+  delete_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 7
+}
+actions {
+  quota: 2
+  allocator: 2
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocation: 7
+}
+actions {
+  quota: 2
+  allocator: 44
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+}
+actions {
+  quota: 2
+  allocator: 2
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  delete_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 2
+  delete_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 7
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  allocator: 7
+  flush_exec_ctx {
+  }
+}
+actions {
+  quota: 2097152
+  allocation: 2
+}
+actions {
+  create_quota {
+  }
+}
+actions {
+  quota: 2
+  allocator: 44
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+}
+actions {
+  quota: 2
+  allocator: 2
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  delete_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 2
+  delete_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 7
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocation: 2
+}
+actions {
+  quota: 2
+  allocation: 2
+}
+actions {
+  allocator: 7
+  delete_allocator {
+  }
+}
+actions {
+  allocation: 2
+}
+actions {
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 44
+  create_quota {
+  }
+}
+actions {
+  quota: 2
+  allocator: 8704
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocation: 7
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 44
+  allocation: 2
+}
+actions {
+}
+actions {
+  quota: 2
+  allocator: 2
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  delete_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 2
+  delete_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 7
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  allocator: 7
+  delete_allocator {
+  }
+}
+actions {
+  allocation: 2
+}
+actions {
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 44
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+}
+actions {
+  quota: 2
+  allocator: 2
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+}
+actions {
+  quota: 2
+  allocator: 2
+  delete_allocator {
+  }
+}
+actions {
+  quota: 2
+}
+actions {
+  quota: 2
+  allocator: 8704
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  create_allocator {
+  }
+}
+actions {
+  allocation: 7
+}
+actions {
+  quota: 2
+  allocator: 44
+  allocation: 2
+}
+actions {
+}
+actions {
+  quota: 2
+  allocator: 2
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  delete_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 2
+  delete_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 2
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  allocation: 2
+}
+actions {
+  quota: 6
+}
+actions {
+  quota: 45
+  allocator: 2
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+}
+actions {
+}
+actions {
+  delete_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 2
+  delete_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 2
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  quota: 67108864
+}
+actions {
+  quota: 2
+  allocator: 2
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+}
+actions {
+  quota: 2
+  allocator: 2
+  delete_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 7
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  allocator: 7
+  delete_allocator {
+  }
+}
+actions {
+  allocation: 2
+}
+actions {
+}
+actions {
+  quota: 2
+  allocator: 44
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+}
+actions {
+  quota: 2
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  delete_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 2
+  delete_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 7
+}
+actions {
+  quota: 2
+  allocator: 8704
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 44
+  allocation: 2
+}
+actions {
+}
+actions {
+  quota: 2
+  allocator: 2
+  allocation: 2
+}
+actions {
+  quota: 2
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  delete_allocator {
+  }
+}
+actions {
+  quota: 2
+}
+actions {
+  quota: 2
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocation: 7
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 44
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+}
+actions {
+  quota: 2
+  allocator: 2
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  delete_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 2
+  delete_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 7
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  allocator: 7
+  delete_allocator {
+  }
+}
+actions {
+  allocation: 2
+}
+actions {
+}
+actions {
+  quota: 2
+  allocator: 44
+  allocation: 15
+  create_allocator {
+  }
+}
+actions {
+}
+actions {
+  allocator: 2
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  delte_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 2
+  delete_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 7
+}
+actions {
+  quota: 2
+  allocator: 8704
+  allocation: 2
+  create_allocation {
+    max: 788529152
+  }
+}
+actions {
+  quota: 2
+  allocator: 131200
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocation: 7
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: -9437190
+  rebind_quota {
+  }
+}
+actions {
+}
+actions {
+  quota: 2
+  allocator: 2
+  allocation: 2
+  create_allocation {
+    max: 1936942413
+  }
+}
+actions {
+  create_allocation {
+  }
+}
+actions {
+  quota: 2
+  allocator: 2
+  set_quota_size: 171798691840
+}
+actions {
+  quota: 2
+  allocator: 2
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocation: 140
+  create_allocator {
+  }
+}
+actions {
+  allocator: 262144
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  quota: 67108864
+}
+actions {
+  quota: 2
+  allocator: 2
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  allocator: 2
+}
+actions {
+  quota: 10
+  allocator: 2
+  delete_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 7
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocation: 2
+}
+actions {
+  allocator: 7
+  delete_allocator {
+  }
+}
+actions {
+  allocation: 2
+}
+actions {
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 45
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+}
+actions {
+  quota: 2
+  allocator: 2
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  allocation: 2304
+  delete_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 2
+  delete_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 7
+}
+actions {
+  quota: 2
+  allocator: 8704
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocation: 7
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 44
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+}
+actions {
+  quota: 2
+  allocator: 2
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  delete_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 2
+  delete_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 7
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  allocator: 7
+  allocation: 44
+  delete_allocator {
+  }
+}
+actions {
+  quota: 2097152
+  allocation: 2
+}
+actions {
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 262188
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+}
+actions {
+  quota: 2
+  allocator: 2
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  rebind_quota {
+  }
+}
+actions {
+  quota: 2
+  allocator: 2
+  delete_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 7
+  rebind_quota {
+  }
+}
+actions {
+  quota: 2
+  allocation: 2
+}
+actions {
+  quota: 2
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  allocator: 7
+  delete_allocator {
+  }
+}
+actions {
+  allocation: 2
+}
+actions {
+  allocator: 7610368
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 44
+  rebind_quota {
+  }
+}
+actions {
+  quota: 2
+  allocator: 8704
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  quota: 8704
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocation: 7
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 44
+  allocation: 2567
+}
+actions {
+}
+actions {
+  quota: 2
+  allocator: 2
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  delete_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 2
+  delete_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 7
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  allocator: 7
+  delete_allocator {
+  }
+}
+actions {
+  allocation: 2
+}
+actions {
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 44
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+}
+actions {
+  quota: 2
+  allocator: 2
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  delete_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 2
+  delete_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 7
+}
+actions {
+  quota: 2
+  allocator: 8704
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+}
+actions {
+}
+actions {
+  delete_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 2
+  delete_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 2
+  create_quota {
+  }
+}
+actions {
+  quota: 2
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  quota: 67108864
+}
+actions {
+  quota: 2
+  allocator: 2
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+}
+actions {
+  quota: 2
+  allocator: 2
+  delete_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 7
+  create_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  allocator: 7
+  create_allocator {
+  }
+}
+actions {
+  allocation: 2
+}
+actions {
+}
+actions {
+  quota: 2
+  allocator: 44
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+}
+actions {
+  quota: 2
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  delete_allocator {
+  }
+}
+actions {
+  quota: 2
+  allocator: 7
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+}
+actions {
+  quota: 2
+  allocation: 2
+  create_allocator {
+  }
+}
+actions {
+  allocation: 2
+}
+actions {
+  allocation: 2
+  delete_allocator {
+  }
+}
+
diff --git a/test/core/resource_quota/memory_quota_fuzzer_corpus/testcase-replenish-nullchk-after-creduce b/test/core/resource_quota/memory_quota_fuzzer_corpus/testcase-replenish-nullchk-after-creduce
new file mode 100644 (file)
index 0000000..f941e8a
--- /dev/null
@@ -0,0 +1,15 @@
+actions {
+  create_quota {}
+}
+actions {
+  create_allocator {}
+}
+actions{set_quota_size : 790} actions {
+  delete_quota {}
+}
+actions {
+  create_allocation {
+  max:
+    2
+  }
+}
diff --git a/test/core/resource_quota/memory_quota_stress_test.cc b/test/core/resource_quota/memory_quota_stress_test.cc
new file mode 100644 (file)
index 0000000..7929792
--- /dev/null
@@ -0,0 +1,223 @@
+// 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 <random>
+#include <thread>
+
+#include "src/core/lib/iomgr/exec_ctx.h"
+#include "src/core/lib/resource_quota/memory_quota.h"
+
+namespace grpc_core {
+
+namespace {
+class StressTest {
+ public:
+  // Create a stress test with some size.
+  StressTest(size_t num_quotas, size_t num_allocators) {
+    for (size_t i = 0; i < num_quotas; ++i) {
+      quotas_.emplace_back();
+    }
+    std::random_device g;
+    std::uniform_int_distribution<size_t> dist(0, num_quotas - 1);
+    for (size_t i = 0; i < num_allocators; ++i) {
+      allocators_.emplace_back(quotas_[dist(g)].CreateMemoryOwner());
+    }
+  }
+
+  // Run the thread for some period of time.
+  void Run(int seconds) {
+    std::vector<std::thread> threads;
+
+    // A few threads constantly rebinding allocators to different quotas.
+    threads.reserve(2 + 2 + 3 * allocators_.size());
+    for (int i = 0; i < 2; i++) threads.push_back(Run(Rebinder));
+    // And another few threads constantly resizing quotas.
+    for (int i = 0; i < 2; i++) threads.push_back(Run(Resizer));
+
+    // For each (allocator, pass), start a thread continuously allocating from
+    // that allocator. Whenever the first allocation is made, schedule a
+    // reclaimer for that pass.
+    for (size_t i = 0; i < allocators_.size(); i++) {
+      auto* allocator = &allocators_[i];
+      for (ReclamationPass pass :
+           {ReclamationPass::kBenign, ReclamationPass::kIdle,
+            ReclamationPass::kDestructive}) {
+        threads.push_back(Run([allocator, pass](StatePtr st) mutable {
+          if (st->RememberReservation(allocator->allocator()->MakeReservation(
+                  st->RandomRequest()))) {
+            allocator->PostReclaimer(
+                pass, [st](absl::optional<ReclamationSweep> sweep) {
+                  if (!sweep.has_value()) return;
+                  st->ForgetReservations();
+                });
+          }
+        }));
+      }
+    }
+
+    // All threads started, wait for the alloted time.
+    std::this_thread::sleep_for(std::chrono::seconds(seconds));
+
+    // Toggle the completion bit, and then wait for the threads.
+    done_.store(true, std::memory_order_relaxed);
+    while (!threads.empty()) {
+      threads.back().join();
+      threads.pop_back();
+    }
+  }
+
+ private:
+  // Per-thread state.
+  // Not everything is used on every thread, but it's not terrible having the
+  // extra state around and it does simplify things somewhat.
+  class State {
+   public:
+    explicit State(StressTest* test)
+        : test_(test),
+          quotas_distribution_(0, test_->quotas_.size() - 1),
+          allocators_distribution_(0, test_->allocators_.size() - 1),
+          size_distribution_(1, 4 * 1024 * 1024),
+          quota_size_distribution_(1024 * 1024, size_t(8) * 1024 * 1024 * 1024),
+          choose_variable_size_(1, 100) {}
+
+    // Choose a random quota, and return an owned pointer to it.
+    // Not thread-safe, only callable from the owning thread.
+    MemoryQuota* RandomQuota() {
+      return &test_->quotas_[quotas_distribution_(g_)];
+    }
+
+    // Choose a random allocator, and return a borrowed pointer to it.
+    // Not thread-safe, only callable from the owning thread.
+    MemoryOwner* RandomAllocator() {
+      return &test_->allocators_[allocators_distribution_(g_)];
+    }
+
+    // Random memory request size - 1% of allocations are chosen to be variable
+    // sized - the rest are fixed (since variable sized create some contention
+    // problems between allocator threads of different passes on the same
+    // allocator).
+    // Not thread-safe, only callable from the owning thread.
+    MemoryRequest RandomRequest() {
+      size_t a = size_distribution_(g_);
+      if (choose_variable_size_(g_) == 1) {
+        size_t b = size_distribution_(g_);
+        return MemoryRequest(std::min(a, b), std::max(a, b));
+      }
+      return MemoryRequest(a);
+    }
+
+    // Choose a new size for a backing quota.
+    // Not thread-safe, only callable from the owning thread.
+    size_t RandomQuotaSize() { return quota_size_distribution_(g_); }
+
+    // Remember a reservation, return true if it's the first remembered since
+    // the last reclamation.
+    // Thread-safe.
+    bool RememberReservation(MemoryAllocator::Reservation reservation)
+        ABSL_LOCKS_EXCLUDED(mu_) {
+      MutexLock lock(&mu_);
+      bool was_empty = reservations_.empty();
+      reservations_.emplace_back(std::move(reservation));
+      return was_empty;
+    }
+
+    // Return all reservations made until this moment, so that they can be
+    // dropped.
+    std::vector<MemoryAllocator::Reservation> ForgetReservations()
+        ABSL_LOCKS_EXCLUDED(mu_) {
+      MutexLock lock(&mu_);
+      return std::move(reservations_);
+    }
+
+   private:
+    // Owning test.
+    StressTest* const test_;
+    // Random number generator.
+    std::mt19937 g_{std::random_device()()};
+    // Distribution to choose a quota.
+    std::uniform_int_distribution<size_t> quotas_distribution_;
+    // Distribution to choose an allocator.
+    std::uniform_int_distribution<size_t> allocators_distribution_;
+    // Distribution to choose an allocation size.
+    std::uniform_int_distribution<size_t> size_distribution_;
+    // Distribution to choose a quota size.
+    std::uniform_int_distribution<size_t> quota_size_distribution_;
+    // Distribution to choose whether to make a variable-sized allocation.
+    std::uniform_int_distribution<size_t> choose_variable_size_;
+
+    // Mutex to protect the reservation list.
+    Mutex mu_;
+    // Reservations remembered by this thread.
+    std::vector<MemoryAllocator::Reservation> reservations_
+        ABSL_GUARDED_BY(mu_);
+  };
+  // Type alias since we always pass around these shared pointers.
+  using StatePtr = std::shared_ptr<State>;
+
+  // Choose one allocator, one quota, rebind the allocator to the quota.
+  static void Rebinder(StatePtr st) {
+    auto* allocator = st->RandomAllocator();
+    auto* quota = st->RandomQuota();
+    allocator->Rebind(quota);
+  }
+
+  // Choose one allocator, resize it to a randomly chosen size.
+  static void Resizer(StatePtr st) {
+    auto* quota = st->RandomQuota();
+    size_t size = st->RandomQuotaSize();
+    quota->SetSize(size);
+  }
+
+  // Create a thread that repeatedly runs a function until the test is done.
+  // We create one instance of State that we pass as a StatePtr to said
+  // function as the current overall state for this thread.
+  // Monitors done_ to see when we should stop.
+  // Ensures there's an ExecCtx for each iteration of the loop.
+  template <typename Fn>
+  std::thread Run(Fn fn) {
+    return std::thread([this, fn]() mutable {
+      auto state = std::make_shared<State>(this);
+      while (!done_.load(std::memory_order_relaxed)) {
+        ExecCtx exec_ctx;
+        fn(state);
+      }
+    });
+  }
+
+  // Flag for when the test is completed.
+  std::atomic<bool> done_{false};
+
+  // Memory quotas to test against. We build this up at construction time, but
+  // then don't resize, so we can load from it continuously from all of the
+  // threads.
+  std::vector<MemoryQuota> quotas_;
+  // Memory allocators to test against. Similarly, built at construction time,
+  // and then the shape of this vector is not changed.
+  std::vector<MemoryOwner> allocators_;
+};
+}  // namespace
+
+}  // namespace grpc_core
+
+int main(int, char**) {
+  if (sizeof(void*) != 8) {
+    gpr_log(
+        GPR_ERROR,
+        "This test assumes 64-bit processors in the values it uses for sizes. "
+        "Since this test is mostly aimed at TSAN coverage, and that's mostly "
+        "platform independent, we simply skip this test in 32-bit builds.");
+    return 0;
+  }
+  grpc_core::StressTest(16, 64).Run(8);
+}
diff --git a/test/core/resource_quota/memory_quota_test.cc b/test/core/resource_quota/memory_quota_test.cc
new file mode 100644 (file)
index 0000000..c1e9985
--- /dev/null
@@ -0,0 +1,191 @@
+// 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 "src/core/lib/resource_quota/memory_quota.h"
+
+#include <gtest/gtest.h>
+
+#include "absl/synchronization/notification.h"
+
+#include "src/core/lib/iomgr/exec_ctx.h"
+#include "src/core/lib/slice/slice_refcount.h"
+#include "test/core/resource_quota/call_checker.h"
+
+namespace grpc_core {
+namespace testing {
+
+//
+// Helpers
+//
+
+template <size_t kSize>
+struct Sized {
+  char blah[kSize];
+  virtual ~Sized() {}
+};
+
+//
+// MemoryRequestTest
+//
+
+TEST(MemoryRequestTest, ConversionFromSize) {
+  MemoryRequest request = 3;
+  EXPECT_EQ(request.min(), 3);
+  EXPECT_EQ(request.max(), 3);
+}
+
+TEST(MemoryRequestTest, MinMax) {
+  MemoryRequest request(3, 7);
+  EXPECT_EQ(request.min(), 3);
+  EXPECT_EQ(request.max(), 7);
+}
+
+//
+// MemoryQuotaTest
+//
+
+TEST(MemoryQuotaTest, NoOp) { MemoryQuota(); }
+
+TEST(MemoryQuotaTest, CreateAllocatorNoOp) {
+  MemoryQuota memory_quota;
+  auto memory_allocator = memory_quota.CreateMemoryAllocator();
+}
+
+TEST(MemoryQuotaTest, CreateObjectFromAllocator) {
+  MemoryQuota memory_quota;
+  auto memory_allocator = memory_quota.CreateMemoryAllocator();
+  auto object = memory_allocator.MakeUnique<Sized<4096>>();
+}
+
+TEST(MemoryQuotaTest, CreateSomeObjectsAndExpectReclamation) {
+  ExecCtx exec_ctx;
+
+  MemoryQuota memory_quota;
+  memory_quota.SetSize(4096);
+  auto memory_allocator = memory_quota.CreateMemoryOwner();
+  auto object = memory_allocator.allocator()->MakeUnique<Sized<2048>>();
+
+  auto checker1 = CallChecker::Make();
+  memory_allocator.PostReclaimer(
+      ReclamationPass::kDestructive,
+      [&object, checker1](absl::optional<ReclamationSweep> sweep) {
+        checker1->Called();
+        EXPECT_TRUE(sweep.has_value());
+        object.reset();
+      });
+  auto object2 = memory_allocator.allocator()->MakeUnique<Sized<2048>>();
+  exec_ctx.Flush();
+  EXPECT_EQ(object.get(), nullptr);
+
+  auto checker2 = CallChecker::Make();
+  memory_allocator.PostReclaimer(
+      ReclamationPass::kDestructive,
+      [&object2, checker2](absl::optional<ReclamationSweep> sweep) {
+        checker2->Called();
+        EXPECT_TRUE(sweep.has_value());
+        object2.reset();
+      });
+  auto object3 = memory_allocator.allocator()->MakeUnique<Sized<2048>>();
+  exec_ctx.Flush();
+  EXPECT_EQ(object2.get(), nullptr);
+}
+
+TEST(MemoryQuotaTest, BasicRebind) {
+  ExecCtx exec_ctx;
+
+  MemoryQuota memory_quota;
+  memory_quota.SetSize(4096);
+  MemoryQuota memory_quota2;
+  memory_quota2.SetSize(4096);
+
+  auto memory_allocator = memory_quota2.CreateMemoryOwner();
+  auto object = memory_allocator.allocator()->MakeUnique<Sized<2048>>();
+
+  memory_allocator.Rebind(&memory_quota);
+  auto memory_allocator2 = memory_quota2.CreateMemoryOwner();
+
+  auto checker1 = CallChecker::Make();
+  memory_allocator2.PostReclaimer(
+      ReclamationPass::kDestructive,
+      [checker1](absl::optional<ReclamationSweep> sweep) {
+        checker1->Called();
+        // Taken memory should be reassigned to
+        // memory_quota, so this should be cancelled
+        EXPECT_FALSE(sweep.has_value());
+      });
+
+  auto checker2 = CallChecker::Make();
+  memory_allocator.PostReclaimer(
+      ReclamationPass::kDestructive,
+      [&object, checker2](absl::optional<ReclamationSweep> sweep) {
+        checker2->Called();
+        EXPECT_TRUE(sweep.has_value());
+        // The new memory allocator should reclaim
+        // the object allocated against the previous
+        // quota because that's now part of this
+        // quota.
+        object.reset();
+      });
+
+  auto object2 = memory_allocator.allocator()->MakeUnique<Sized<2048>>();
+  exec_ctx.Flush();
+  EXPECT_EQ(object.get(), nullptr);
+}
+
+TEST(MemoryQuotaTest, ReserveRangeNoPressure) {
+  MemoryQuota memory_quota;
+  auto memory_allocator = memory_quota.CreateMemoryAllocator();
+  size_t total = 0;
+  for (int i = 0; i < 10000; i++) {
+    auto n = memory_allocator.Reserve(MemoryRequest(100, 40000));
+    EXPECT_EQ(n, 40000);
+    total += n;
+  }
+  memory_allocator.Release(total);
+}
+
+TEST(MemoryQuotaTest, MakeSlice) {
+  MemoryQuota memory_quota;
+  auto memory_allocator = memory_quota.CreateMemoryAllocator();
+  std::vector<grpc_slice> slices;
+  for (int i = 1; i < 1000; i++) {
+    int min = i;
+    int max = 10 * i - 9;
+    slices.push_back(memory_allocator.MakeSlice(MemoryRequest(min, max)));
+  }
+  for (grpc_slice slice : slices) {
+    grpc_slice_unref_internal(slice);
+  }
+}
+
+TEST(MemoryQuotaTest, ContainerAllocator) {
+  MemoryQuota memory_quota;
+  auto memory_allocator = memory_quota.CreateMemoryAllocator();
+  Vector<int> vec(&memory_allocator);
+  for (int i = 0; i < 100000; i++) {
+    vec.push_back(i);
+  }
+}
+
+}  // namespace testing
+}  // namespace grpc_core
+
+// Hook needed to run ExecCtx outside of iomgr.
+void grpc_set_default_iomgr_platform() {}
+
+int main(int argc, char** argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  gpr_log_verbosity_init();
+  return RUN_ALL_TESTS();
+}
diff --git a/test/core/resource_quota/resource_quota_test.cc b/test/core/resource_quota/resource_quota_test.cc
new file mode 100644 (file)
index 0000000..07852a3
--- /dev/null
@@ -0,0 +1,37 @@
+// 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 "src/core/lib/resource_quota/resource_quota.h"
+
+#include <gtest/gtest.h>
+
+namespace grpc_core {
+namespace testing {
+
+TEST(ResourceQuotaTest, Works) {
+  auto q = MakeRefCounted<ResourceQuota>();
+  EXPECT_NE(q->thread_quota(), nullptr);
+  EXPECT_NE(q->memory_quota(), nullptr);
+}
+
+}  // namespace testing
+}  // namespace grpc_core
+
+// Hook needed to run ExecCtx outside of iomgr.
+void grpc_set_default_iomgr_platform() {}
+
+int main(int argc, char** argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
diff --git a/test/core/resource_quota/thread_quota_test.cc b/test/core/resource_quota/thread_quota_test.cc
new file mode 100644 (file)
index 0000000..a2014be
--- /dev/null
@@ -0,0 +1,45 @@
+// 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 "src/core/lib/resource_quota/thread_quota.h"
+
+#include <gtest/gtest.h>
+
+namespace grpc_core {
+namespace testing {
+
+TEST(ThreadQuotaTest, Works) {
+  auto q = MakeRefCounted<ThreadQuota>();
+  EXPECT_TRUE(q->Reserve(128));
+  q->SetMax(10);
+  EXPECT_FALSE(q->Reserve(128));
+  EXPECT_FALSE(q->Reserve(1));
+  q->Release(118);
+  EXPECT_FALSE(q->Reserve(1));
+  q->Release(1);
+  EXPECT_TRUE(q->Reserve(1));
+  EXPECT_FALSE(q->Reserve(1));
+  q->Release(10);
+}
+
+}  // namespace testing
+}  // namespace grpc_core
+
+// Hook needed to run ExecCtx outside of iomgr.
+void grpc_set_default_iomgr_platform() {}
+
+int main(int argc, char** argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
index 3885b24..d5db0d7 100644 (file)
@@ -14,7 +14,7 @@
 
 load("//bazel:grpc_build_system.bzl", "grpc_cc_binary", "grpc_cc_library", "grpc_cc_test", "grpc_package")
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 grpc_package(name = "test/core/security")
 
@@ -280,7 +280,7 @@ grpc_cc_test(
     deps = [
         "//:gpr",
         "//:grpc",
-        "//:grpc_base_c",
+        "//:grpc_base",
         "//:grpc_secure",
         "//:tsi",
         "//:tsi_interface",
@@ -454,6 +454,11 @@ grpc_cc_test(
 grpc_cc_test(
     name = "grpc_authorization_policy_provider_test",
     srcs = ["grpc_authorization_policy_provider_test.cc"],
+    data = [
+        "//test/core/security/authorization/test_policies:invalid_policy.json",
+        "//test/core/security/authorization/test_policies:valid_policy_1.json",
+        "//test/core/security/authorization/test_policies:valid_policy_2.json",
+    ],
     external_deps = ["gtest"],
     language = "C++",
     deps = [
diff --git a/test/core/security/authorization/test_policies/BUILD b/test/core/security/authorization/test_policies/BUILD
new file mode 100644 (file)
index 0000000..28a7435
--- /dev/null
@@ -0,0 +1,21 @@
+# 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.
+
+licenses(["notice"])
+
+exports_files([
+    "invalid_policy.json",
+    "valid_policy_1.json",
+    "valid_policy_2.json",
+])
diff --git a/test/core/security/authorization/test_policies/invalid_policy.json b/test/core/security/authorization/test_policies/invalid_policy.json
new file mode 100644 (file)
index 0000000..0967ef4
--- /dev/null
@@ -0,0 +1 @@
+{}
diff --git a/test/core/security/authorization/test_policies/valid_policy_1.json b/test/core/security/authorization/test_policies/valid_policy_1.json
new file mode 100644 (file)
index 0000000..7f277df
--- /dev/null
@@ -0,0 +1,40 @@
+{
+      "name": "authz",
+      "allow_rules": 
+      [
+            {
+                  "name": "allow_echo",
+                  "request": 
+                  {
+                        "paths": 
+                        [
+                              "*/Echo"
+                        ],
+                        "headers":
+                        [
+                              {
+                                    "key": "key-foo",
+                                    "values": ["foo1", "foo2"]
+                              },
+                              {
+                                    "key": "key-bar",
+                                    "values": ["bar1"]
+                              }
+                        ]
+                  }
+            }
+      ],
+      "deny_rules":
+      [
+            {
+                  "name": "deny_clientstreamingecho",
+                  "request":
+                  {
+                        "paths":
+                        [
+                              "*/ClientStreamingEcho"
+                        ]
+                  }
+            }
+      ]
+}
diff --git a/test/core/security/authorization/test_policies/valid_policy_2.json b/test/core/security/authorization/test_policies/valid_policy_2.json
new file mode 100644 (file)
index 0000000..4337ed4
--- /dev/null
@@ -0,0 +1,26 @@
+{
+      "name": "authz",
+      "allow_rules": 
+      [
+            {
+                  "name": "allow_foo",
+                  "request": 
+                  {
+                        "paths": 
+                        [
+                              "*/foo"
+                        ]
+                  }
+            },
+            {
+                  "name": "allow_bar",
+                  "request": 
+                  {
+                        "paths": 
+                        [
+                              "*/bar"
+                        ]
+                  }
+            }
+      ]
+}
index dc3646d..6f4a3ef 100644 (file)
@@ -19,6 +19,8 @@
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 
+#include <grpc/grpc_security_constants.h>
+
 #include "src/core/lib/security/authorization/evaluate_args.h"
 #include "src/core/lib/security/authorization/matchers.h"
 #include "test/core/util/evaluate_args_test_util.h"
@@ -341,7 +343,7 @@ TEST_F(AuthorizationMatchersTest,
 
 TEST_F(AuthorizationMatchersTest, AuthenticatedMatcherSuccessfulUriSanMatches) {
   args_.AddPropertyToAuthContext(GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME,
-                                 GRPC_SSL_TRANSPORT_SECURITY_TYPE);
+                                 GRPC_TLS_TRANSPORT_SECURITY_TYPE);
   args_.AddPropertyToAuthContext(GRPC_PEER_URI_PROPERTY_NAME,
                                  "spiffe://foo.abc");
   args_.AddPropertyToAuthContext(GRPC_PEER_URI_PROPERTY_NAME,
@@ -357,7 +359,7 @@ TEST_F(AuthorizationMatchersTest, AuthenticatedMatcherSuccessfulUriSanMatches) {
 
 TEST_F(AuthorizationMatchersTest, AuthenticatedMatcherFailedUriSanMatches) {
   args_.AddPropertyToAuthContext(GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME,
-                                 GRPC_SSL_TRANSPORT_SECURITY_TYPE);
+                                 GRPC_TLS_TRANSPORT_SECURITY_TYPE);
   args_.AddPropertyToAuthContext(GRPC_PEER_URI_PROPERTY_NAME,
                                  "spiffe://bar.abc");
   EvaluateArgs args = args_.MakeEvaluateArgs();
index cb97292..699f32f 100644 (file)
@@ -246,13 +246,10 @@ TEST(GrpcAwsRequestSignerTest, InvalidUrl) {
   grpc_core::AwsRequestSigner signer("access_key_id", "secret_access_key",
                                      "token", "POST", "invalid_url",
                                      "us-east-1", "", {}, &error);
-  grpc_slice expected_error_description =
-      grpc_slice_from_static_string("Invalid Aws request url.");
-  grpc_slice actual_error_description;
+  std::string actual_error_description;
   GPR_ASSERT(grpc_error_get_str(error, GRPC_ERROR_STR_DESCRIPTION,
                                 &actual_error_description));
-  EXPECT_TRUE(grpc_slice_cmp(expected_error_description,
-                             actual_error_description) == 0);
+  EXPECT_EQ(actual_error_description, "Invalid Aws request url.");
   GRPC_ERROR_UNREF(error);
 }
 
@@ -262,13 +259,11 @@ TEST(GrpcAwsRequestSignerTest, DuplicateRequestDate) {
       "access_key_id", "secret_access_key", "token", "POST", "invalid_url",
       "us-east-1", "", {{"date", kBotoTestDate}, {"x-amz-date", kAmzTestDate}},
       &error);
-  grpc_slice expected_error_description = grpc_slice_from_static_string(
-      "Only one of {date, x-amz-date} can be specified, not both.");
-  grpc_slice actual_error_description;
+  std::string actual_error_description;
   GPR_ASSERT(grpc_error_get_str(error, GRPC_ERROR_STR_DESCRIPTION,
                                 &actual_error_description));
-  EXPECT_TRUE(grpc_slice_cmp(expected_error_description,
-                             actual_error_description) == 0);
+  EXPECT_EQ(actual_error_description,
+            "Only one of {date, x-amz-date} can be specified, not both.");
   GRPC_ERROR_UNREF(error);
 }
 
index cb5bc3a..19267a2 100644 (file)
@@ -449,102 +449,116 @@ static void test_oauth2_token_fetcher_creds_parsing_missing_token_lifetime(
   grpc_http_response_destroy(&response);
 }
 
-typedef struct {
-  const char* key;
-  const char* value;
-} expected_md;
+namespace {
 
-typedef struct {
-  grpc_error_handle expected_error;
-  const expected_md* expected;
-  size_t expected_size;
-  grpc_credentials_mdelem_array md_array;
-  grpc_closure on_request_metadata;
-  grpc_call_credentials* creds;
-  grpc_polling_entity pollent;
-} request_metadata_state;
-
-static void check_metadata(const expected_md* expected,
-                           grpc_credentials_mdelem_array* md_array) {
-  for (size_t i = 0; i < md_array->size; ++i) {
-    size_t j;
-    for (j = 0; j < md_array->size; ++j) {
-      if (0 ==
-          grpc_slice_str_cmp(GRPC_MDKEY(md_array->md[j]), expected[i].key)) {
-        GPR_ASSERT(grpc_slice_str_cmp(GRPC_MDVALUE(md_array->md[j]),
-                                      expected[i].value) == 0);
-        break;
-      }
-    }
-    if (j == md_array->size) {
-      gpr_log(GPR_ERROR, "key %s not found", expected[i].key);
-      GPR_ASSERT(0);
+class RequestMetadataState {
+ public:
+  static RequestMetadataState* NewInstance(
+      grpc_error_handle expected_error,
+      std::map<std::string, std::string> expected) {
+    RequestMetadataState* state = new RequestMetadataState(
+        expected_error, std::move(expected),
+        grpc_polling_entity_create_from_pollset_set(grpc_pollset_set_create()));
+    return state;
+  }
+
+ private:
+  RequestMetadataState(grpc_error_handle expected_error,
+                       std::map<std::string, std::string> expected,
+                       grpc_polling_entity pollent)
+      : expected_error_(expected_error),
+        expected_(expected),
+        pollent_(pollent) {
+    GRPC_CLOSURE_INIT(&on_request_metadata_, OnRequestMetadata, this,
+                      grpc_schedule_on_exec_ctx);
+  }
+
+ public:
+  ~RequestMetadataState() {
+    grpc_credentials_mdelem_array_destroy(&md_array_);
+    grpc_pollset_set_destroy(grpc_polling_entity_pollset_set(&pollent_));
+  }
+
+  void RunRequestMetadataTest(grpc_call_credentials* creds,
+                              grpc_auth_metadata_context auth_md_ctx) {
+    grpc_error_handle error = GRPC_ERROR_NONE;
+    if (creds->get_request_metadata(&pollent_, auth_md_ctx, &md_array_,
+                                    &on_request_metadata_, &error)) {
+      // Synchronous result.  Invoke the callback directly.
+      CheckRequestMetadata(error);
+      GRPC_ERROR_UNREF(error);
     }
   }
-}
 
-static void check_request_metadata(void* arg, grpc_error_handle error) {
-  request_metadata_state* state = static_cast<request_metadata_state*>(arg);
-  gpr_log(GPR_INFO, "expected_error: %s",
-          grpc_error_std_string(state->expected_error).c_str());
-  gpr_log(GPR_INFO, "actual_error: %s", grpc_error_std_string(error).c_str());
-  if (state->expected_error == GRPC_ERROR_NONE) {
-    GPR_ASSERT(error == GRPC_ERROR_NONE);
-  } else {
-    grpc_slice expected_error;
-    GPR_ASSERT(grpc_error_get_str(state->expected_error,
-                                  GRPC_ERROR_STR_DESCRIPTION, &expected_error));
-    grpc_slice actual_error;
-    GPR_ASSERT(
-        grpc_error_get_str(error, GRPC_ERROR_STR_DESCRIPTION, &actual_error));
-    GPR_ASSERT(grpc_slice_cmp(expected_error, actual_error) == 0);
-    GRPC_ERROR_UNREF(state->expected_error);
+ private:
+  static void OnRequestMetadata(void* arg, grpc_error_handle error) {
+    RequestMetadataState* state = static_cast<RequestMetadataState*>(arg);
+    state->CheckRequestMetadata(error);
   }
-  gpr_log(GPR_INFO, "expected_size=%" PRIdPTR " actual_size=%" PRIdPTR,
-          state->expected_size, state->md_array.size);
-  GPR_ASSERT(state->md_array.size == state->expected_size);
-  check_metadata(state->expected, &state->md_array);
-  grpc_credentials_mdelem_array_destroy(&state->md_array);
-  grpc_pollset_set_destroy(grpc_polling_entity_pollset_set(&state->pollent));
-  gpr_free(state);
-}
-
-static request_metadata_state* make_request_metadata_state(
-    grpc_error_handle expected_error, const expected_md* expected,
-    size_t expected_size) {
-  request_metadata_state* state =
-      static_cast<request_metadata_state*>(gpr_zalloc(sizeof(*state)));
-  state->expected_error = expected_error;
-  state->expected = expected;
-  state->expected_size = expected_size;
-  state->pollent =
-      grpc_polling_entity_create_from_pollset_set(grpc_pollset_set_create());
-  GRPC_CLOSURE_INIT(&state->on_request_metadata, check_request_metadata, state,
-                    grpc_schedule_on_exec_ctx);
-  return state;
-}
-
-static void run_request_metadata_test(grpc_call_credentials* creds,
-                                      grpc_auth_metadata_context auth_md_ctx,
-                                      request_metadata_state* state) {
-  grpc_error_handle error = GRPC_ERROR_NONE;
-  if (creds->get_request_metadata(&state->pollent, auth_md_ctx,
-                                  &state->md_array, &state->on_request_metadata,
-                                  &error)) {
-    // Synchronous result.  Invoke the callback directly.
-    check_request_metadata(state, error);
-    GRPC_ERROR_UNREF(error);
+
+  void CheckRequestMetadata(grpc_error_handle error) {
+    gpr_log(GPR_INFO, "expected_error: %s",
+            grpc_error_std_string(expected_error_).c_str());
+    gpr_log(GPR_INFO, "actual_error: %s", grpc_error_std_string(error).c_str());
+    if (expected_error_ == GRPC_ERROR_NONE) {
+      GPR_ASSERT(error == GRPC_ERROR_NONE);
+    } else {
+      std::string expected_error;
+      GPR_ASSERT(grpc_error_get_str(expected_error_, GRPC_ERROR_STR_DESCRIPTION,
+                                    &expected_error));
+      std::string actual_error;
+      GPR_ASSERT(
+          grpc_error_get_str(error, GRPC_ERROR_STR_DESCRIPTION, &actual_error));
+      GPR_ASSERT(expected_error == actual_error);
+      GRPC_ERROR_UNREF(expected_error_);
+    }
+    gpr_log(GPR_INFO, "expected_size=%" PRIdPTR " actual_size=%" PRIdPTR,
+            expected_.size(), md_array_.size);
+    GPR_ASSERT(md_array_.size == expected_.size());
+    CheckMetadata(expected_, &md_array_);
+    delete this;
+  }
+
+  static void CheckMetadata(const std::map<std::string, std::string>& expected,
+                            grpc_credentials_mdelem_array* md_array) {
+    for (auto const& i : expected) {
+      size_t j;
+      for (j = 0; j < md_array->size; ++j) {
+        absl::string_view actual_key =
+            grpc_core::StringViewFromSlice(GRPC_MDKEY(md_array->md[j]));
+        if (actual_key == i.first) {
+          absl::string_view actual_value =
+              grpc_core::StringViewFromSlice(GRPC_MDVALUE(md_array->md[j]));
+          GPR_ASSERT(actual_value == i.second);
+          break;
+        }
+      }
+      if (j == md_array->size) {
+        gpr_log(GPR_ERROR, "key %s not found", i.first.c_str());
+        GPR_ASSERT(0);
+      }
+    }
   }
-}
+
+ private:
+  grpc_error_handle expected_error_;
+  std::map<std::string, std::string> expected_;
+  grpc_credentials_mdelem_array md_array_;
+  grpc_closure on_request_metadata_;
+  grpc_polling_entity pollent_;
+};
+
+}  // namespace
 
 static void test_google_iam_creds(void) {
   grpc_core::ExecCtx exec_ctx;
-  expected_md emd[] = {{GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY,
-                        test_google_iam_authorization_token},
-                       {GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY,
-                        test_google_iam_authority_selector}};
-  request_metadata_state* state =
-      make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
+  std::map<std::string, std::string> emd = {
+      {GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY,
+       test_google_iam_authorization_token},
+      {GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY,
+       test_google_iam_authority_selector}};
+  RequestMetadataState* state =
+      RequestMetadataState::NewInstance(GRPC_ERROR_NONE, emd);
   grpc_call_credentials* creds = grpc_google_iam_credentials_create(
       test_google_iam_authorization_token, test_google_iam_authority_selector,
       nullptr);
@@ -552,15 +566,16 @@ static void test_google_iam_creds(void) {
   GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
   grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
                                             nullptr, nullptr};
-  run_request_metadata_test(creds, auth_md_ctx, state);
+  state->RunRequestMetadataTest(creds, auth_md_ctx);
   creds->Unref();
 }
 
 static void test_access_token_creds(void) {
   grpc_core::ExecCtx exec_ctx;
-  expected_md emd[] = {{GRPC_AUTHORIZATION_METADATA_KEY, "Bearer blah"}};
-  request_metadata_state* state =
-      make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
+  std::map<std::string, std::string> emd = {
+      {GRPC_AUTHORIZATION_METADATA_KEY, "Bearer blah"}};
+  RequestMetadataState* state =
+      RequestMetadataState::NewInstance(GRPC_ERROR_NONE, emd);
   grpc_call_credentials* creds =
       grpc_access_token_credentials_create("blah", nullptr);
   grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
@@ -568,7 +583,7 @@ static void test_access_token_creds(void) {
   GPR_ASSERT(strcmp(creds->type(), GRPC_CALL_CREDENTIALS_TYPE_OAUTH2) == 0);
   /* Check security level. */
   GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
-  run_request_metadata_test(creds, auth_md_ctx, state);
+  state->RunRequestMetadataTest(creds, auth_md_ctx);
   creds->Unref();
 }
 
@@ -610,14 +625,14 @@ static void test_channel_oauth2_composite_creds(void) {
 
 static void test_oauth2_google_iam_composite_creds(void) {
   grpc_core::ExecCtx exec_ctx;
-  expected_md emd[] = {
+  std::map<std::string, std::string> emd = {
       {GRPC_AUTHORIZATION_METADATA_KEY, test_oauth2_bearer_token},
       {GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY,
        test_google_iam_authorization_token},
       {GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY,
        test_google_iam_authority_selector}};
-  request_metadata_state* state =
-      make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
+  RequestMetadataState* state =
+      RequestMetadataState::NewInstance(GRPC_ERROR_NONE, emd);
   grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
                                             nullptr, nullptr};
   grpc_call_credentials* oauth2_creds = grpc_md_only_test_credentials_create(
@@ -648,7 +663,7 @@ static void test_oauth2_google_iam_composite_creds(void) {
              0);
   GPR_ASSERT(strcmp(creds_list[1]->type(), GRPC_CALL_CREDENTIALS_TYPE_IAM) ==
              0);
-  run_request_metadata_test(composite_creds, auth_md_ctx, state);
+  state->RunRequestMetadataTest(composite_creds, auth_md_ctx);
   composite_creds->Unref();
 }
 
@@ -755,7 +770,7 @@ static int httpcli_get_should_not_be_called(
 
 static void test_compute_engine_creds_success() {
   grpc_core::ExecCtx exec_ctx;
-  expected_md emd[] = {
+  std::map<std::string, std::string> emd = {
       {"authorization", "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_"}};
   const char expected_creds_debug_string[] =
       "GoogleComputeEngineTokenFetcherCredentials{"
@@ -768,19 +783,18 @@ static void test_compute_engine_creds_success() {
   GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
 
   /* First request: http get should be called. */
-  request_metadata_state* state =
-      make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
+  RequestMetadataState* state =
+      RequestMetadataState::NewInstance(GRPC_ERROR_NONE, emd);
   grpc_httpcli_set_override(compute_engine_httpcli_get_success_override,
                             httpcli_post_should_not_be_called);
-  run_request_metadata_test(creds, auth_md_ctx, state);
+  state->RunRequestMetadataTest(creds, auth_md_ctx);
   grpc_core::ExecCtx::Get()->Flush();
 
   /* Second request: the cached token should be served directly. */
-  state =
-      make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
+  state = RequestMetadataState::NewInstance(GRPC_ERROR_NONE, emd);
   grpc_httpcli_set_override(httpcli_get_should_not_be_called,
                             httpcli_post_should_not_be_called);
-  run_request_metadata_test(creds, auth_md_ctx, state);
+  state->RunRequestMetadataTest(creds, auth_md_ctx);
   grpc_core::ExecCtx::Get()->Flush();
 
   GPR_ASSERT(
@@ -794,17 +808,17 @@ static void test_compute_engine_creds_failure(void) {
   const char expected_creds_debug_string[] =
       "GoogleComputeEngineTokenFetcherCredentials{"
       "OAuth2TokenFetcherCredentials}";
-  request_metadata_state* state = make_request_metadata_state(
+  RequestMetadataState* state = RequestMetadataState::NewInstance(
       GRPC_ERROR_CREATE_FROM_STATIC_STRING(
           "Error occurred when fetching oauth2 token."),
-      nullptr, 0);
+      {});
   grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
                                             nullptr, nullptr};
   grpc_call_credentials* creds =
       grpc_google_compute_engine_credentials_create(nullptr);
   grpc_httpcli_set_override(compute_engine_httpcli_get_failure_override,
                             httpcli_post_should_not_be_called);
-  run_request_metadata_test(creds, auth_md_ctx, state);
+  state->RunRequestMetadataTest(creds, auth_md_ctx);
   GPR_ASSERT(
       strcmp(creds->debug_string().c_str(), expected_creds_debug_string) == 0);
   creds->Unref();
@@ -855,7 +869,7 @@ static int token_httpcli_post_failure(const grpc_httpcli_request* /*request*/,
 
 static void test_refresh_token_creds_success(void) {
   grpc_core::ExecCtx exec_ctx;
-  expected_md emd[] = {
+  std::map<std::string, std::string> emd = {
       {"authorization", "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_"}};
   const char expected_creds_debug_string[] =
       "GoogleRefreshToken{ClientID:32555999999.apps.googleusercontent.com,"
@@ -869,19 +883,18 @@ static void test_refresh_token_creds_success(void) {
   GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
 
   /* First request: http put should be called. */
-  request_metadata_state* state =
-      make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
+  RequestMetadataState* state =
+      RequestMetadataState::NewInstance(GRPC_ERROR_NONE, emd);
   grpc_httpcli_set_override(httpcli_get_should_not_be_called,
                             refresh_token_httpcli_post_success);
-  run_request_metadata_test(creds, auth_md_ctx, state);
+  state->RunRequestMetadataTest(creds, auth_md_ctx);
   grpc_core::ExecCtx::Get()->Flush();
 
   /* Second request: the cached token should be served directly. */
-  state =
-      make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
+  state = RequestMetadataState::NewInstance(GRPC_ERROR_NONE, emd);
   grpc_httpcli_set_override(httpcli_get_should_not_be_called,
                             httpcli_post_should_not_be_called);
-  run_request_metadata_test(creds, auth_md_ctx, state);
+  state->RunRequestMetadataTest(creds, auth_md_ctx);
   grpc_core::ExecCtx::Get()->Flush();
   GPR_ASSERT(
       strcmp(creds->debug_string().c_str(), expected_creds_debug_string) == 0);
@@ -895,17 +908,17 @@ static void test_refresh_token_creds_failure(void) {
   const char expected_creds_debug_string[] =
       "GoogleRefreshToken{ClientID:32555999999.apps.googleusercontent.com,"
       "OAuth2TokenFetcherCredentials}";
-  request_metadata_state* state = make_request_metadata_state(
+  RequestMetadataState* state = RequestMetadataState::NewInstance(
       GRPC_ERROR_CREATE_FROM_STATIC_STRING(
           "Error occurred when fetching oauth2 token."),
-      nullptr, 0);
+      {});
   grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
                                             nullptr, nullptr};
   grpc_call_credentials* creds = grpc_google_refresh_token_credentials_create(
       test_refresh_token_str, nullptr);
   grpc_httpcli_set_override(httpcli_get_should_not_be_called,
                             token_httpcli_post_failure);
-  run_request_metadata_test(creds, auth_md_ctx, state);
+  state->RunRequestMetadataTest(creds, auth_md_ctx);
   GPR_ASSERT(
       strcmp(creds->debug_string().c_str(), expected_creds_debug_string) == 0);
 
@@ -1100,7 +1113,7 @@ static char* write_tmp_jwt_file(const char* jwt_contents) {
 
 static void test_sts_creds_success(void) {
   grpc_core::ExecCtx exec_ctx;
-  expected_md emd[] = {
+  std::map<std::string, std::string> emd = {
       {"authorization", "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_"}};
   const char expected_creds_debug_string[] =
       "StsTokenFetcherCredentials{Path:/v1/"
@@ -1127,19 +1140,18 @@ static void test_sts_creds_success(void) {
   GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
 
   /* First request: http put should be called. */
-  request_metadata_state* state =
-      make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
+  RequestMetadataState* state =
+      RequestMetadataState::NewInstance(GRPC_ERROR_NONE, emd);
   grpc_httpcli_set_override(httpcli_get_should_not_be_called,
                             sts_token_httpcli_post_success);
-  run_request_metadata_test(creds, auth_md_ctx, state);
+  state->RunRequestMetadataTest(creds, auth_md_ctx);
   grpc_core::ExecCtx::Get()->Flush();
 
   /* Second request: the cached token should be served directly. */
-  state =
-      make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
+  state = RequestMetadataState::NewInstance(GRPC_ERROR_NONE, emd);
   grpc_httpcli_set_override(httpcli_get_should_not_be_called,
                             httpcli_post_should_not_be_called);
-  run_request_metadata_test(creds, auth_md_ctx, state);
+  state->RunRequestMetadataTest(creds, auth_md_ctx);
   grpc_core::ExecCtx::Get()->Flush();
   GPR_ASSERT(
       strcmp(creds->debug_string().c_str(), expected_creds_debug_string) == 0);
@@ -1171,13 +1183,13 @@ static void test_sts_creds_token_file_not_found(void) {
   /* Check security level. */
   GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
 
-  request_metadata_state* state = make_request_metadata_state(
+  RequestMetadataState* state = RequestMetadataState::NewInstance(
       GRPC_ERROR_CREATE_FROM_STATIC_STRING(
           "Error occurred when fetching oauth2 token."),
-      nullptr, 0);
+      {});
   grpc_httpcli_set_override(httpcli_get_should_not_be_called,
                             httpcli_post_should_not_be_called);
-  run_request_metadata_test(creds, auth_md_ctx, state);
+  state->RunRequestMetadataTest(creds, auth_md_ctx);
   grpc_core::ExecCtx::Get()->Flush();
 
   /* Cleanup. */
@@ -1187,7 +1199,7 @@ static void test_sts_creds_token_file_not_found(void) {
 
 static void test_sts_creds_no_actor_token_success(void) {
   grpc_core::ExecCtx exec_ctx;
-  expected_md emd[] = {
+  std::map<std::string, std::string> emd = {
       {"authorization", "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_"}};
   const char expected_creds_debug_string[] =
       "StsTokenFetcherCredentials{Path:/v1/"
@@ -1213,19 +1225,18 @@ static void test_sts_creds_no_actor_token_success(void) {
   GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
 
   /* First request: http put should be called. */
-  request_metadata_state* state =
-      make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
+  RequestMetadataState* state =
+      RequestMetadataState::NewInstance(GRPC_ERROR_NONE, emd);
   grpc_httpcli_set_override(httpcli_get_should_not_be_called,
                             sts_token_httpcli_post_success_no_actor_token);
-  run_request_metadata_test(creds, auth_md_ctx, state);
+  state->RunRequestMetadataTest(creds, auth_md_ctx);
   grpc_core::ExecCtx::Get()->Flush();
 
   /* Second request: the cached token should be served directly. */
-  state =
-      make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
+  state = RequestMetadataState::NewInstance(GRPC_ERROR_NONE, emd);
   grpc_httpcli_set_override(httpcli_get_should_not_be_called,
                             httpcli_post_should_not_be_called);
-  run_request_metadata_test(creds, auth_md_ctx, state);
+  state->RunRequestMetadataTest(creds, auth_md_ctx);
   grpc_core::ExecCtx::Get()->Flush();
   GPR_ASSERT(
       strcmp(creds->debug_string().c_str(), expected_creds_debug_string) == 0);
@@ -1240,10 +1251,10 @@ static void test_sts_creds_load_token_failure(void) {
       "StsTokenFetcherCredentials{Path:/v1/"
       "token-exchange,Authority:foo.com:5555,OAuth2TokenFetcherCredentials}";
   grpc_core::ExecCtx exec_ctx;
-  request_metadata_state* state = make_request_metadata_state(
+  RequestMetadataState* state = RequestMetadataState::NewInstance(
       GRPC_ERROR_CREATE_FROM_STATIC_STRING(
           "Error occurred when fetching oauth2 token."),
-      nullptr, 0);
+      {});
   grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
                                             nullptr, nullptr};
   char* test_signed_jwt_path = write_tmp_jwt_file(test_signed_jwt);
@@ -1261,7 +1272,7 @@ static void test_sts_creds_load_token_failure(void) {
   grpc_call_credentials* creds = grpc_sts_credentials_create(&options, nullptr);
   grpc_httpcli_set_override(httpcli_get_should_not_be_called,
                             httpcli_post_should_not_be_called);
-  run_request_metadata_test(creds, auth_md_ctx, state);
+  state->RunRequestMetadataTest(creds, auth_md_ctx);
   GPR_ASSERT(
       strcmp(creds->debug_string().c_str(), expected_creds_debug_string) == 0);
 
@@ -1275,10 +1286,10 @@ static void test_sts_creds_http_failure(void) {
       "StsTokenFetcherCredentials{Path:/v1/"
       "token-exchange,Authority:foo.com:5555,OAuth2TokenFetcherCredentials}";
   grpc_core::ExecCtx exec_ctx;
-  request_metadata_state* state = make_request_metadata_state(
+  RequestMetadataState* state = RequestMetadataState::NewInstance(
       GRPC_ERROR_CREATE_FROM_STATIC_STRING(
           "Error occurred when fetching oauth2 token."),
-      nullptr, 0);
+      {});
   grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
                                             nullptr, nullptr};
   char* test_signed_jwt_path = write_tmp_jwt_file(test_signed_jwt);
@@ -1297,7 +1308,7 @@ static void test_sts_creds_http_failure(void) {
       grpc_sts_credentials_create(&valid_options, nullptr);
   grpc_httpcli_set_override(httpcli_get_should_not_be_called,
                             token_httpcli_post_failure);
-  run_request_metadata_test(creds, auth_md_ctx, state);
+  state->RunRequestMetadataTest(creds, auth_md_ctx);
   GPR_ASSERT(
       strcmp(creds->debug_string().c_str(), expected_creds_debug_string) == 0);
   creds->Unref();
@@ -1425,33 +1436,32 @@ static void test_jwt_creds_success(void) {
   grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
                                             nullptr, nullptr};
   std::string expected_md_value = absl::StrCat("Bearer ", test_signed_jwt);
-  expected_md emd[] = {{"authorization", expected_md_value.c_str()}};
+  std::map<std::string, std::string> emd = {
+      {"authorization", expected_md_value.c_str()}};
   grpc_call_credentials* creds =
       grpc_service_account_jwt_access_credentials_create(
           json_key_string, grpc_max_auth_token_lifetime(), nullptr);
 
   /* First request: jwt_encode_and_sign should be called. */
-  request_metadata_state* state =
-      make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
+  RequestMetadataState* state =
+      RequestMetadataState::NewInstance(GRPC_ERROR_NONE, emd);
   grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_success);
-  run_request_metadata_test(creds, auth_md_ctx, state);
+  state->RunRequestMetadataTest(creds, auth_md_ctx);
   grpc_core::ExecCtx::Get()->Flush();
 
   /* Second request: the cached token should be served directly. */
-  state =
-      make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
+  state = RequestMetadataState::NewInstance(GRPC_ERROR_NONE, emd);
   grpc_jwt_encode_and_sign_set_override(
       encode_and_sign_jwt_should_not_be_called);
-  run_request_metadata_test(creds, auth_md_ctx, state);
+  state->RunRequestMetadataTest(creds, auth_md_ctx);
   grpc_core::ExecCtx::Get()->Flush();
 
   /* Third request: Different service url so jwt_encode_and_sign should be
      called again (no caching). */
-  state =
-      make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
+  state = RequestMetadataState::NewInstance(GRPC_ERROR_NONE, emd);
   auth_md_ctx.service_url = other_test_service_url;
   grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_success);
-  run_request_metadata_test(creds, auth_md_ctx, state);
+  state->RunRequestMetadataTest(creds, auth_md_ctx);
   grpc_core::ExecCtx::Get()->Flush();
   GPR_ASSERT(strncmp(expected_creds_debug_string_prefix,
                      creds->debug_string().c_str(),
@@ -1469,15 +1479,14 @@ static void test_jwt_creds_signing_failure(void) {
   grpc_core::ExecCtx exec_ctx;
   grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
                                             nullptr, nullptr};
-  request_metadata_state* state = make_request_metadata_state(
-      GRPC_ERROR_CREATE_FROM_STATIC_STRING("Could not generate JWT."), nullptr,
-      0);
+  RequestMetadataState* state = RequestMetadataState::NewInstance(
+      GRPC_ERROR_CREATE_FROM_STATIC_STRING("Could not generate JWT."), {});
   grpc_call_credentials* creds =
       grpc_service_account_jwt_access_credentials_create(
           json_key_string, grpc_max_auth_token_lifetime(), nullptr);
 
   grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_failure);
-  run_request_metadata_test(creds, auth_md_ctx, state);
+  state->RunRequestMetadataTest(creds, auth_md_ctx);
 
   gpr_free(json_key_string);
   GPR_ASSERT(strncmp(expected_creds_debug_string_prefix,
@@ -1641,10 +1650,10 @@ static std::string null_well_known_creds_path_getter(void) { return ""; }
 
 static void test_google_default_creds_gce(void) {
   grpc_core::ExecCtx exec_ctx;
-  expected_md emd[] = {
+  std::map<std::string, std::string> emd = {
       {"authorization", "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_"}};
-  request_metadata_state* state =
-      make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
+  RequestMetadataState* state =
+      RequestMetadataState::NewInstance(GRPC_ERROR_NONE, emd);
   grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
                                             nullptr, nullptr};
   grpc_flush_cached_google_default_credentials();
@@ -1665,7 +1674,7 @@ static void test_google_default_creds_gce(void) {
   GPR_ASSERT(creds->call_creds() != nullptr);
   grpc_httpcli_set_override(compute_engine_httpcli_get_success_override,
                             httpcli_post_should_not_be_called);
-  run_request_metadata_test(creds->mutable_call_creds(), auth_md_ctx, state);
+  state->RunRequestMetadataTest(creds->mutable_call_creds(), auth_md_ctx);
   grpc_core::ExecCtx::Get()->Flush();
 
   GPR_ASSERT(g_test_gce_tenancy_checker_called == true);
@@ -1678,10 +1687,10 @@ static void test_google_default_creds_gce(void) {
 
 static void test_google_default_creds_non_gce(void) {
   grpc_core::ExecCtx exec_ctx;
-  expected_md emd[] = {
+  std::map<std::string, std::string> emd = {
       {"authorization", "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_"}};
-  request_metadata_state* state =
-      make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
+  RequestMetadataState* state =
+      RequestMetadataState::NewInstance(GRPC_ERROR_NONE, emd);
   grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
                                             nullptr, nullptr};
   grpc_flush_cached_google_default_credentials();
@@ -1703,7 +1712,7 @@ static void test_google_default_creds_non_gce(void) {
   GPR_ASSERT(creds->call_creds() != nullptr);
   grpc_httpcli_set_override(compute_engine_httpcli_get_success_override,
                             httpcli_post_should_not_be_called);
-  run_request_metadata_test(creds->mutable_call_creds(), auth_md_ctx, state);
+  state->RunRequestMetadataTest(creds->mutable_call_creds(), auth_md_ctx);
   grpc_core::ExecCtx::Get()->Flush();
   GPR_ASSERT(g_test_gce_tenancy_checker_called == true);
   /* Cleanup. */
@@ -1746,10 +1755,10 @@ static void test_no_google_default_creds(void) {
 }
 
 static void test_google_default_creds_call_creds_specified(void) {
-  expected_md emd[] = {
+  std::map<std::string, std::string> emd = {
       {"authorization", "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_"}};
-  request_metadata_state* state =
-      make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
+  RequestMetadataState* state =
+      RequestMetadataState::NewInstance(GRPC_ERROR_NONE, emd);
   grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
                                             nullptr, nullptr};
   grpc_core::ExecCtx exec_ctx;
@@ -1770,8 +1779,9 @@ static void test_google_default_creds_call_creds_specified(void) {
   GPR_ASSERT(channel_creds->call_creds() != nullptr);
   grpc_httpcli_set_override(compute_engine_httpcli_get_success_override,
                             httpcli_post_should_not_be_called);
-  run_request_metadata_test(channel_creds->mutable_call_creds(), auth_md_ctx,
-                            state);
+  state->RunRequestMetadataTest(channel_creds->mutable_call_creds(),
+                                auth_md_ctx);
+
   grpc_core::ExecCtx::Get()->Flush();
   channel_creds->Unref();
   grpc_httpcli_set_override(nullptr, nullptr);
@@ -1806,9 +1816,9 @@ struct fake_call_creds : public grpc_call_credentials {
 };
 
 static void test_google_default_creds_not_default(void) {
-  expected_md emd[] = {{"foo", "oof"}};
-  request_metadata_state* state =
-      make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
+  std::map<std::string, std::string> emd = {{"foo", "oof"}};
+  RequestMetadataState* state =
+      RequestMetadataState::NewInstance(GRPC_ERROR_NONE, emd);
   grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
                                             nullptr, nullptr};
   grpc_core::ExecCtx exec_ctx;
@@ -1827,8 +1837,8 @@ static void test_google_default_creds_not_default(void) {
   GPR_ASSERT(g_test_gce_tenancy_checker_called == false);
   GPR_ASSERT(channel_creds != nullptr);
   GPR_ASSERT(channel_creds->call_creds() != nullptr);
-  run_request_metadata_test(channel_creds->mutable_call_creds(), auth_md_ctx,
-                            state);
+  state->RunRequestMetadataTest(channel_creds->mutable_call_creds(),
+                                auth_md_ctx);
   grpc_core::ExecCtx::Get()->Flush();
   channel_creds->Unref();
   grpc_httpcli_set_override(nullptr, nullptr);
@@ -1840,7 +1850,8 @@ typedef enum {
   PLUGIN_DESTROY_CALLED_STATE
 } plugin_state;
 
-static const expected_md plugin_md[] = {{"foo", "bar"}, {"hi", "there"}};
+static const std::map<std::string, std::string> plugin_md = {{"foo", "bar"},
+                                                             {"hi", "there"}};
 
 static int plugin_get_metadata_success(
     void* state, grpc_auth_metadata_context context,
@@ -1852,16 +1863,17 @@ static int plugin_get_metadata_success(
   GPR_ASSERT(strcmp(context.method_name, test_method) == 0);
   GPR_ASSERT(context.channel_auth_context == nullptr);
   GPR_ASSERT(context.reserved == nullptr);
-  GPR_ASSERT(GPR_ARRAY_SIZE(plugin_md) <
-             GRPC_METADATA_CREDENTIALS_PLUGIN_SYNC_MAX);
+  GPR_ASSERT(plugin_md.size() < GRPC_METADATA_CREDENTIALS_PLUGIN_SYNC_MAX);
   plugin_state* s = static_cast<plugin_state*>(state);
   *s = PLUGIN_GET_METADATA_CALLED_STATE;
-  for (size_t i = 0; i < GPR_ARRAY_SIZE(plugin_md); ++i) {
+  size_t i = 0;
+  for (auto const& md : plugin_md) {
     memset(&creds_md[i], 0, sizeof(grpc_metadata));
-    creds_md[i].key = grpc_slice_from_copied_string(plugin_md[i].key);
-    creds_md[i].value = grpc_slice_from_copied_string(plugin_md[i].value);
+    creds_md[i].key = grpc_slice_from_copied_string(md.first.c_str());
+    creds_md[i].value = grpc_slice_from_copied_string(md.second.c_str());
+    i += 1;
   }
-  *num_creds_md = GPR_ARRAY_SIZE(plugin_md);
+  *num_creds_md = plugin_md.size();
   return true;  // Synchronous return.
 }
 
@@ -1917,8 +1929,8 @@ static void test_metadata_plugin_success(void) {
   grpc_core::ExecCtx exec_ctx;
   grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
                                             nullptr, nullptr};
-  request_metadata_state* md_state = make_request_metadata_state(
-      GRPC_ERROR_NONE, plugin_md, GPR_ARRAY_SIZE(plugin_md));
+  RequestMetadataState* md_state =
+      RequestMetadataState::NewInstance(GRPC_ERROR_NONE, plugin_md);
 
   plugin.state = &state;
   plugin.get_metadata = plugin_get_metadata_success;
@@ -1930,7 +1942,7 @@ static void test_metadata_plugin_success(void) {
   /* Check security level. */
   GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
   GPR_ASSERT(state == PLUGIN_INITIAL_STATE);
-  run_request_metadata_test(creds, auth_md_ctx, md_state);
+  md_state->RunRequestMetadataTest(creds, auth_md_ctx);
   GPR_ASSERT(state == PLUGIN_GET_METADATA_CALLED_STATE);
   GPR_ASSERT(
       strcmp(creds->debug_string().c_str(), expected_creds_debug_string) == 0);
@@ -1948,11 +1960,11 @@ static void test_metadata_plugin_failure(void) {
   grpc_core::ExecCtx exec_ctx;
   grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
                                             nullptr, nullptr};
-  request_metadata_state* md_state = make_request_metadata_state(
+  RequestMetadataState* md_state = RequestMetadataState::NewInstance(
       GRPC_ERROR_CREATE_FROM_CPP_STRING(
           absl::StrCat("Getting metadata from plugin failed with error: ",
                        plugin_error_details)),
-      nullptr, 0);
+      {});
 
   plugin.state = &state;
   plugin.get_metadata = plugin_get_metadata_failure;
@@ -1962,7 +1974,7 @@ static void test_metadata_plugin_failure(void) {
   grpc_call_credentials* creds = grpc_metadata_credentials_create_from_plugin(
       plugin, GRPC_PRIVACY_AND_INTEGRITY, nullptr);
   GPR_ASSERT(state == PLUGIN_INITIAL_STATE);
-  run_request_metadata_test(creds, auth_md_ctx, md_state);
+  md_state->RunRequestMetadataTest(creds, auth_md_ctx);
   GPR_ASSERT(state == PLUGIN_GET_METADATA_CALLED_STATE);
   GPR_ASSERT(
       strcmp(creds->debug_string().c_str(), expected_creds_debug_string) == 0);
@@ -2153,8 +2165,8 @@ validate_external_account_creds_token_exchage_request_with_url_encode(
           "3Agrant-type%3Atoken-exchange&requested_token_type=urn%3Aietf%"
           "3Aparams%3Aoauth%3Atoken-type%3Aaccess_token&subject_token_type="
           "subject_token_type_!%40%23%24&subject_token=test_subject_token&"
-          "scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcloud-platform") ==
-      0);
+          "scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcloud-platform&"
+          "options=%7B%7D") == 0);
 
   // Check the rest of the request.
   GPR_ASSERT(strcmp(request->host, "foo.com:5555") == 0);
@@ -2342,7 +2354,8 @@ class TestExternalAccountCredentials final
 };
 
 static void test_external_account_creds_success(void) {
-  expected_md emd[] = {{"authorization", "Bearer token_exchange_access_token"}};
+  std::map<std::string, std::string> emd = {
+      {"authorization", "Bearer token_exchange_access_token"}};
   grpc_core::ExecCtx exec_ctx;
   grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
                                             nullptr, nullptr};
@@ -2358,29 +2371,30 @@ static void test_external_account_creds_success(void) {
       "quota_project_id",                 // quota_project_id;
       "client_id",                        // client_id;
       "client_secret",                    // client_secret;
+      "",                                 // workforce_pool_user_project;
   };
   TestExternalAccountCredentials creds(options, {});
   /* Check security level. */
   GPR_ASSERT(creds.min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
   /* First request: http put should be called. */
-  request_metadata_state* state =
-      make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
+  RequestMetadataState* state =
+      RequestMetadataState::NewInstance(GRPC_ERROR_NONE, emd);
   grpc_httpcli_set_override(httpcli_get_should_not_be_called,
                             external_account_creds_httpcli_post_success);
-  run_request_metadata_test(&creds, auth_md_ctx, state);
+  state->RunRequestMetadataTest(&creds, auth_md_ctx);
   grpc_core::ExecCtx::Get()->Flush();
   /* Second request: the cached token should be served directly. */
-  state =
-      make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
+  state = RequestMetadataState::NewInstance(GRPC_ERROR_NONE, emd);
   grpc_httpcli_set_override(httpcli_get_should_not_be_called,
                             httpcli_post_should_not_be_called);
-  run_request_metadata_test(&creds, auth_md_ctx, state);
+  state->RunRequestMetadataTest(&creds, auth_md_ctx);
   grpc_core::ExecCtx::Get()->Flush();
   grpc_httpcli_set_override(nullptr, nullptr);
 }
 
 static void test_external_account_creds_success_with_url_encode(void) {
-  expected_md emd[] = {{"authorization", "Bearer token_exchange_access_token"}};
+  std::map<std::string, std::string> emd = {
+      {"authorization", "Bearer token_exchange_access_token"}};
   grpc_core::ExecCtx exec_ctx;
   grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
                                             nullptr, nullptr};
@@ -2396,20 +2410,21 @@ static void test_external_account_creds_success_with_url_encode(void) {
       "quota_project_id",                       // quota_project_id;
       "client_id",                              // client_id;
       "client_secret",                          // client_secret;
+      "",                                       // workforce_pool_user_project;
   };
   TestExternalAccountCredentials creds(options, {});
-  request_metadata_state* state =
-      make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
+  RequestMetadataState* state =
+      RequestMetadataState::NewInstance(GRPC_ERROR_NONE, emd);
   grpc_httpcli_set_override(httpcli_get_should_not_be_called,
                             external_account_creds_httpcli_post_success);
-  run_request_metadata_test(&creds, auth_md_ctx, state);
+  state->RunRequestMetadataTest(&creds, auth_md_ctx);
   grpc_core::ExecCtx::Get()->Flush();
   grpc_httpcli_set_override(nullptr, nullptr);
 }
 
 static void
 test_external_account_creds_success_with_service_account_impersonation(void) {
-  expected_md emd[] = {
+  std::map<std::string, std::string> emd = {
       {"authorization", "Bearer service_account_impersonation_access_token"}};
   grpc_core::ExecCtx exec_ctx;
   grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
@@ -2426,16 +2441,17 @@ test_external_account_creds_success_with_service_account_impersonation(void) {
       "quota_project_id",  // quota_project_id;
       "client_id",         // client_id;
       "client_secret",     // client_secret;
+      "",                  // workforce_pool_user_project;
   };
   TestExternalAccountCredentials creds(options, {"scope_1", "scope_2"});
   /* Check security level. */
   GPR_ASSERT(creds.min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
   /* First request: http put should be called. */
-  request_metadata_state* state =
-      make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
+  RequestMetadataState* state =
+      RequestMetadataState::NewInstance(GRPC_ERROR_NONE, emd);
   grpc_httpcli_set_override(httpcli_get_should_not_be_called,
                             external_account_creds_httpcli_post_success);
-  run_request_metadata_test(&creds, auth_md_ctx, state);
+  state->RunRequestMetadataTest(&creds, auth_md_ctx);
   grpc_core::ExecCtx::Get()->Flush();
   grpc_httpcli_set_override(nullptr, nullptr);
 }
@@ -2456,6 +2472,7 @@ static void test_external_account_creds_failure_invalid_token_url(void) {
       "quota_project_id",  // quota_project_id;
       "client_id",         // client_id;
       "client_secret",     // client_secret;
+      "",                  // workforce_pool_user_project;
   };
   TestExternalAccountCredentials creds(options, {});
   grpc_httpcli_set_override(httpcli_get_should_not_be_called,
@@ -2465,9 +2482,9 @@ static void test_external_account_creds_failure_invalid_token_url(void) {
   grpc_error_handle expected_error =
       GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
           "Error occurred when fetching oauth2 token.", &error, 1);
-  request_metadata_state* state =
-      make_request_metadata_state(expected_error, nullptr, 0);
-  run_request_metadata_test(&creds, auth_md_ctx, state);
+  RequestMetadataState* state =
+      RequestMetadataState::NewInstance(expected_error, {});
+  state->RunRequestMetadataTest(&creds, auth_md_ctx);
   GRPC_ERROR_UNREF(error);
   grpc_core::ExecCtx::Get()->Flush();
   grpc_httpcli_set_override(nullptr, nullptr);
@@ -2491,6 +2508,7 @@ test_external_account_creds_failure_invalid_service_account_impersonation_url(
       "quota_project_id",                           // quota_project_id;
       "client_id",                                  // client_id;
       "client_secret",                              // client_secret;
+      "",  // workforce_pool_user_project;
   };
   TestExternalAccountCredentials creds(options, {});
   grpc_httpcli_set_override(httpcli_get_should_not_be_called,
@@ -2501,9 +2519,9 @@ test_external_account_creds_failure_invalid_service_account_impersonation_url(
   grpc_error_handle expected_error =
       GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
           "Error occurred when fetching oauth2 token.", &error, 1);
-  request_metadata_state* state =
-      make_request_metadata_state(expected_error, nullptr, 0);
-  run_request_metadata_test(&creds, auth_md_ctx, state);
+  RequestMetadataState* state =
+      RequestMetadataState::NewInstance(expected_error, {});
+  state->RunRequestMetadataTest(&creds, auth_md_ctx);
   GRPC_ERROR_UNREF(error);
   grpc_core::ExecCtx::Get()->Flush();
   grpc_httpcli_set_override(nullptr, nullptr);
@@ -2527,6 +2545,7 @@ test_external_account_creds_failure_token_exchange_response_missing_access_token
       "quota_project_id",  // quota_project_id;
       "client_id",         // client_id;
       "client_secret",     // client_secret;
+      "",                  // workforce_pool_user_project;
   };
   TestExternalAccountCredentials creds(options, {});
   grpc_httpcli_set_override(
@@ -2539,16 +2558,17 @@ test_external_account_creds_failure_token_exchange_response_missing_access_token
   grpc_error_handle expected_error =
       GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
           "Error occurred when fetching oauth2 token.", &error, 1);
-  request_metadata_state* state =
-      make_request_metadata_state(expected_error, nullptr, 0);
-  run_request_metadata_test(&creds, auth_md_ctx, state);
+  RequestMetadataState* state =
+      RequestMetadataState::NewInstance(expected_error, {});
+  state->RunRequestMetadataTest(&creds, auth_md_ctx);
   GRPC_ERROR_UNREF(error);
   grpc_core::ExecCtx::Get()->Flush();
   grpc_httpcli_set_override(nullptr, nullptr);
 }
 
 static void test_url_external_account_creds_success_format_text(void) {
-  expected_md emd[] = {{"authorization", "Bearer token_exchange_access_token"}};
+  std::map<std::string, std::string> emd = {
+      {"authorization", "Bearer token_exchange_access_token"}};
   grpc_core::ExecCtx exec_ctx;
   grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
                                             nullptr, nullptr};
@@ -2568,24 +2588,26 @@ static void test_url_external_account_creds_success_format_text(void) {
       "quota_project_id",                 // quota_project_id;
       "client_id",                        // client_id;
       "client_secret",                    // client_secret;
+      "",                                 // workforce_pool_user_project;
   };
   auto creds =
       grpc_core::UrlExternalAccountCredentials::Create(options, {}, &error);
   GPR_ASSERT(creds != nullptr);
   GPR_ASSERT(error == GRPC_ERROR_NONE);
   GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
-  request_metadata_state* state =
-      make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
+  RequestMetadataState* state =
+      RequestMetadataState::NewInstance(GRPC_ERROR_NONE, emd);
   grpc_httpcli_set_override(url_external_account_creds_httpcli_get_success,
                             external_account_creds_httpcli_post_success);
-  run_request_metadata_test(creds.get(), auth_md_ctx, state);
+  state->RunRequestMetadataTest(creds.get(), auth_md_ctx);
   grpc_core::ExecCtx::Get()->Flush();
   grpc_httpcli_set_override(nullptr, nullptr);
 }
 
 static void
 test_url_external_account_creds_success_with_qurey_params_format_text(void) {
-  expected_md emd[] = {{"authorization", "Bearer token_exchange_access_token"}};
+  std::map<std::string, std::string> emd = {
+      {"authorization", "Bearer token_exchange_access_token"}};
   grpc_core::ExecCtx exec_ctx;
   grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
                                             nullptr, nullptr};
@@ -2605,23 +2627,25 @@ test_url_external_account_creds_success_with_qurey_params_format_text(void) {
       "quota_project_id",                 // quota_project_id;
       "client_id",                        // client_id;
       "client_secret",                    // client_secret;
+      "",                                 // workforce_pool_user_project;
   };
   auto creds =
       grpc_core::UrlExternalAccountCredentials::Create(options, {}, &error);
   GPR_ASSERT(creds != nullptr);
   GPR_ASSERT(error == GRPC_ERROR_NONE);
   GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
-  request_metadata_state* state =
-      make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
+  RequestMetadataState* state =
+      RequestMetadataState::NewInstance(GRPC_ERROR_NONE, emd);
   grpc_httpcli_set_override(url_external_account_creds_httpcli_get_success,
                             external_account_creds_httpcli_post_success);
-  run_request_metadata_test(creds.get(), auth_md_ctx, state);
+  state->RunRequestMetadataTest(creds.get(), auth_md_ctx);
   grpc_core::ExecCtx::Get()->Flush();
   grpc_httpcli_set_override(nullptr, nullptr);
 }
 
 static void test_url_external_account_creds_success_format_json(void) {
-  expected_md emd[] = {{"authorization", "Bearer token_exchange_access_token"}};
+  std::map<std::string, std::string> emd = {
+      {"authorization", "Bearer token_exchange_access_token"}};
   grpc_core::ExecCtx exec_ctx;
   grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
                                             nullptr, nullptr};
@@ -2641,17 +2665,18 @@ static void test_url_external_account_creds_success_format_json(void) {
       "quota_project_id",                 // quota_project_id;
       "client_id",                        // client_id;
       "client_secret",                    // client_secret;
+      "",                                 // workforce_pool_user_project;
   };
   auto creds =
       grpc_core::UrlExternalAccountCredentials::Create(options, {}, &error);
   GPR_ASSERT(creds != nullptr);
   GPR_ASSERT(error == GRPC_ERROR_NONE);
   GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
-  request_metadata_state* state =
-      make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
+  RequestMetadataState* state =
+      RequestMetadataState::NewInstance(GRPC_ERROR_NONE, emd);
   grpc_httpcli_set_override(url_external_account_creds_httpcli_get_success,
                             external_account_creds_httpcli_post_success);
-  run_request_metadata_test(creds.get(), auth_md_ctx, state);
+  state->RunRequestMetadataTest(creds.get(), auth_md_ctx);
   grpc_core::ExecCtx::Get()->Flush();
   grpc_httpcli_set_override(nullptr, nullptr);
 }
@@ -2673,21 +2698,21 @@ test_url_external_account_creds_failure_invalid_credential_source_url(void) {
       "quota_project_id",                 // quota_project_id;
       "client_id",                        // client_id;
       "client_secret",                    // client_secret;
+      "",                                 // workforce_pool_user_project;
   };
   auto creds =
       grpc_core::UrlExternalAccountCredentials::Create(options, {}, &error);
   GPR_ASSERT(creds == nullptr);
-  grpc_slice actual_error_slice;
-  GPR_ASSERT(grpc_error_get_str(error, GRPC_ERROR_STR_DESCRIPTION,
-                                &actual_error_slice));
-  absl::string_view actual_error =
-      grpc_core::StringViewFromSlice(actual_error_slice);
+  std::string actual_error;
+  GPR_ASSERT(
+      grpc_error_get_str(error, GRPC_ERROR_STR_DESCRIPTION, &actual_error));
   GPR_ASSERT(absl::StartsWith(actual_error, "Invalid credential source url."));
   GRPC_ERROR_UNREF(error);
 }
 
 static void test_file_external_account_creds_success_format_text(void) {
-  expected_md emd[] = {{"authorization", "Bearer token_exchange_access_token"}};
+  std::map<std::string, std::string> emd = {
+      {"authorization", "Bearer token_exchange_access_token"}};
   grpc_core::ExecCtx exec_ctx;
   grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
                                             nullptr, nullptr};
@@ -2710,17 +2735,18 @@ static void test_file_external_account_creds_success_format_text(void) {
       "quota_project_id",                 // quota_project_id;
       "client_id",                        // client_id;
       "client_secret",                    // client_secret;
+      "",                                 // workforce_pool_user_project;
   };
   auto creds =
       grpc_core::FileExternalAccountCredentials::Create(options, {}, &error);
   GPR_ASSERT(creds != nullptr);
   GPR_ASSERT(error == GRPC_ERROR_NONE);
   GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
-  request_metadata_state* state =
-      make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
+  RequestMetadataState* state =
+      RequestMetadataState::NewInstance(GRPC_ERROR_NONE, emd);
   grpc_httpcli_set_override(httpcli_get_should_not_be_called,
                             external_account_creds_httpcli_post_success);
-  run_request_metadata_test(creds.get(), auth_md_ctx, state);
+  state->RunRequestMetadataTest(creds.get(), auth_md_ctx);
   grpc_core::ExecCtx::Get()->Flush();
   grpc_httpcli_set_override(nullptr, nullptr);
   GRPC_ERROR_UNREF(error);
@@ -2728,7 +2754,8 @@ static void test_file_external_account_creds_success_format_text(void) {
 }
 
 static void test_file_external_account_creds_success_format_json(void) {
-  expected_md emd[] = {{"authorization", "Bearer token_exchange_access_token"}};
+  std::map<std::string, std::string> emd = {
+      {"authorization", "Bearer token_exchange_access_token"}};
   grpc_core::ExecCtx exec_ctx;
   grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
                                             nullptr, nullptr};
@@ -2759,17 +2786,18 @@ static void test_file_external_account_creds_success_format_json(void) {
       "quota_project_id",                 // quota_project_id;
       "client_id",                        // client_id;
       "client_secret",                    // client_secret;
+      "",                                 // workforce_pool_user_project;
   };
   auto creds =
       grpc_core::FileExternalAccountCredentials::Create(options, {}, &error);
   GPR_ASSERT(creds != nullptr);
   GPR_ASSERT(error == GRPC_ERROR_NONE);
   GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
-  request_metadata_state* state =
-      make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
+  RequestMetadataState* state =
+      RequestMetadataState::NewInstance(GRPC_ERROR_NONE, emd);
   grpc_httpcli_set_override(httpcli_get_should_not_be_called,
                             external_account_creds_httpcli_post_success);
-  run_request_metadata_test(creds.get(), auth_md_ctx, state);
+  state->RunRequestMetadataTest(creds.get(), auth_md_ctx);
   grpc_core::ExecCtx::Get()->Flush();
   grpc_httpcli_set_override(nullptr, nullptr);
   GRPC_ERROR_UNREF(error);
@@ -2795,6 +2823,7 @@ static void test_file_external_account_creds_failure_file_not_found(void) {
       "quota_project_id",                 // quota_project_id;
       "client_id",                        // client_id;
       "client_secret",                    // client_secret;
+      "",                                 // workforce_pool_user_project;
   };
   auto creds =
       grpc_core::FileExternalAccountCredentials::Create(options, {}, &error);
@@ -2806,9 +2835,9 @@ static void test_file_external_account_creds_failure_file_not_found(void) {
   grpc_error_handle expected_error =
       GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
           "Error occurred when fetching oauth2 token.", &error, 1);
-  request_metadata_state* state =
-      make_request_metadata_state(expected_error, nullptr, 0);
-  run_request_metadata_test(creds.get(), auth_md_ctx, state);
+  RequestMetadataState* state =
+      RequestMetadataState::NewInstance(expected_error, {});
+  state->RunRequestMetadataTest(creds.get(), auth_md_ctx);
   grpc_core::ExecCtx::Get()->Flush();
   grpc_httpcli_set_override(nullptr, nullptr);
   GRPC_ERROR_UNREF(error);
@@ -2845,6 +2874,7 @@ static void test_file_external_account_creds_failure_invalid_json_content(
       "quota_project_id",                 // quota_project_id;
       "client_id",                        // client_id;
       "client_secret",                    // client_secret;
+      "",                                 // workforce_pool_user_project;
   };
   auto creds =
       grpc_core::FileExternalAccountCredentials::Create(options, {}, &error);
@@ -2857,9 +2887,9 @@ static void test_file_external_account_creds_failure_invalid_json_content(
   grpc_error_handle expected_error =
       GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
           "Error occurred when fetching oauth2 token.", &error, 1);
-  request_metadata_state* state =
-      make_request_metadata_state(expected_error, nullptr, 0);
-  run_request_metadata_test(creds.get(), auth_md_ctx, state);
+  RequestMetadataState* state =
+      RequestMetadataState::NewInstance(expected_error, {});
+  state->RunRequestMetadataTest(creds.get(), auth_md_ctx);
   grpc_core::ExecCtx::Get()->Flush();
   grpc_httpcli_set_override(nullptr, nullptr);
   GRPC_ERROR_UNREF(error);
@@ -2867,7 +2897,8 @@ static void test_file_external_account_creds_failure_invalid_json_content(
 }
 
 static void test_aws_external_account_creds_success(void) {
-  expected_md emd[] = {{"authorization", "Bearer token_exchange_access_token"}};
+  std::map<std::string, std::string> emd = {
+      {"authorization", "Bearer token_exchange_access_token"}};
   grpc_core::ExecCtx exec_ctx;
   grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
                                             nullptr, nullptr};
@@ -2886,24 +2917,26 @@ static void test_aws_external_account_creds_success(void) {
       "quota_project_id",                 // quota_project_id;
       "client_id",                        // client_id;
       "client_secret",                    // client_secret;
+      "",                                 // workforce_pool_user_project;
   };
   auto creds =
       grpc_core::AwsExternalAccountCredentials::Create(options, {}, &error);
   GPR_ASSERT(creds != nullptr);
   GPR_ASSERT(error == GRPC_ERROR_NONE);
   GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
-  request_metadata_state* state =
-      make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
+  RequestMetadataState* state =
+      RequestMetadataState::NewInstance(GRPC_ERROR_NONE, emd);
   grpc_httpcli_set_override(aws_external_account_creds_httpcli_get_success,
                             aws_external_account_creds_httpcli_post_success);
-  run_request_metadata_test(creds.get(), auth_md_ctx, state);
+  state->RunRequestMetadataTest(creds.get(), auth_md_ctx);
   grpc_core::ExecCtx::Get()->Flush();
   grpc_httpcli_set_override(nullptr, nullptr);
 }
 
 static void test_aws_external_account_creds_success_path_region_env_keys_url(
     void) {
-  expected_md emd[] = {{"authorization", "Bearer token_exchange_access_token"}};
+  std::map<std::string, std::string> emd = {
+      {"authorization", "Bearer token_exchange_access_token"}};
   grpc_core::ExecCtx exec_ctx;
   grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
                                             nullptr, nullptr};
@@ -2923,17 +2956,18 @@ static void test_aws_external_account_creds_success_path_region_env_keys_url(
       "quota_project_id",                 // quota_project_id;
       "client_id",                        // client_id;
       "client_secret",                    // client_secret;
+      "",                                 // workforce_pool_user_project;
   };
   auto creds =
       grpc_core::AwsExternalAccountCredentials::Create(options, {}, &error);
   GPR_ASSERT(creds != nullptr);
   GPR_ASSERT(error == GRPC_ERROR_NONE);
   GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
-  request_metadata_state* state =
-      make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
+  RequestMetadataState* state =
+      RequestMetadataState::NewInstance(GRPC_ERROR_NONE, emd);
   grpc_httpcli_set_override(aws_external_account_creds_httpcli_get_success,
                             aws_external_account_creds_httpcli_post_success);
-  run_request_metadata_test(creds.get(), auth_md_ctx, state);
+  state->RunRequestMetadataTest(creds.get(), auth_md_ctx);
   grpc_core::ExecCtx::Get()->Flush();
   grpc_httpcli_set_override(nullptr, nullptr);
   gpr_unsetenv("AWS_REGION");
@@ -2941,7 +2975,8 @@ static void test_aws_external_account_creds_success_path_region_env_keys_url(
 
 static void
 test_aws_external_account_creds_success_path_default_region_env_keys_url(void) {
-  expected_md emd[] = {{"authorization", "Bearer token_exchange_access_token"}};
+  std::map<std::string, std::string> emd = {
+      {"authorization", "Bearer token_exchange_access_token"}};
   grpc_core::ExecCtx exec_ctx;
   grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
                                             nullptr, nullptr};
@@ -2961,17 +2996,18 @@ test_aws_external_account_creds_success_path_default_region_env_keys_url(void) {
       "quota_project_id",                 // quota_project_id;
       "client_id",                        // client_id;
       "client_secret",                    // client_secret;
+      "",                                 // workforce_pool_user_project;
   };
   auto creds =
       grpc_core::AwsExternalAccountCredentials::Create(options, {}, &error);
   GPR_ASSERT(creds != nullptr);
   GPR_ASSERT(error == GRPC_ERROR_NONE);
   GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
-  request_metadata_state* state =
-      make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
+  RequestMetadataState* state =
+      RequestMetadataState::NewInstance(GRPC_ERROR_NONE, emd);
   grpc_httpcli_set_override(aws_external_account_creds_httpcli_get_success,
                             aws_external_account_creds_httpcli_post_success);
-  run_request_metadata_test(creds.get(), auth_md_ctx, state);
+  state->RunRequestMetadataTest(creds.get(), auth_md_ctx);
   grpc_core::ExecCtx::Get()->Flush();
   grpc_httpcli_set_override(nullptr, nullptr);
   gpr_unsetenv("AWS_DEFAULT_REGION");
@@ -2980,7 +3016,8 @@ test_aws_external_account_creds_success_path_default_region_env_keys_url(void) {
 static void
 test_aws_external_account_creds_success_path_duplicate_region_env_keys_url(
     void) {
-  expected_md emd[] = {{"authorization", "Bearer token_exchange_access_token"}};
+  std::map<std::string, std::string> emd = {
+      {"authorization", "Bearer token_exchange_access_token"}};
   grpc_core::ExecCtx exec_ctx;
   grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
                                             nullptr, nullptr};
@@ -3002,17 +3039,18 @@ test_aws_external_account_creds_success_path_duplicate_region_env_keys_url(
       "quota_project_id",                 // quota_project_id;
       "client_id",                        // client_id;
       "client_secret",                    // client_secret;
+      "",                                 // workforce_pool_user_project;
   };
   auto creds =
       grpc_core::AwsExternalAccountCredentials::Create(options, {}, &error);
   GPR_ASSERT(creds != nullptr);
   GPR_ASSERT(error == GRPC_ERROR_NONE);
   GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
-  request_metadata_state* state =
-      make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
+  RequestMetadataState* state =
+      RequestMetadataState::NewInstance(GRPC_ERROR_NONE, emd);
   grpc_httpcli_set_override(aws_external_account_creds_httpcli_get_success,
                             aws_external_account_creds_httpcli_post_success);
-  run_request_metadata_test(creds.get(), auth_md_ctx, state);
+  state->RunRequestMetadataTest(creds.get(), auth_md_ctx);
   grpc_core::ExecCtx::Get()->Flush();
   grpc_httpcli_set_override(nullptr, nullptr);
   gpr_unsetenv("AWS_REGION");
@@ -3021,7 +3059,8 @@ test_aws_external_account_creds_success_path_duplicate_region_env_keys_url(
 
 static void test_aws_external_account_creds_success_path_region_url_keys_env(
     void) {
-  expected_md emd[] = {{"authorization", "Bearer token_exchange_access_token"}};
+  std::map<std::string, std::string> emd = {
+      {"authorization", "Bearer token_exchange_access_token"}};
   grpc_core::ExecCtx exec_ctx;
   grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
                                             nullptr, nullptr};
@@ -3043,17 +3082,18 @@ static void test_aws_external_account_creds_success_path_region_url_keys_env(
       "quota_project_id",                 // quota_project_id;
       "client_id",                        // client_id;
       "client_secret",                    // client_secret;
+      "",                                 // workforce_pool_user_project;
   };
   auto creds =
       grpc_core::AwsExternalAccountCredentials::Create(options, {}, &error);
   GPR_ASSERT(creds != nullptr);
   GPR_ASSERT(error == GRPC_ERROR_NONE);
   GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
-  request_metadata_state* state =
-      make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
+  RequestMetadataState* state =
+      RequestMetadataState::NewInstance(GRPC_ERROR_NONE, emd);
   grpc_httpcli_set_override(aws_external_account_creds_httpcli_get_success,
                             aws_external_account_creds_httpcli_post_success);
-  run_request_metadata_test(creds.get(), auth_md_ctx, state);
+  state->RunRequestMetadataTest(creds.get(), auth_md_ctx);
   grpc_core::ExecCtx::Get()->Flush();
   grpc_httpcli_set_override(nullptr, nullptr);
   gpr_unsetenv("AWS_ACCESS_KEY_ID");
@@ -3063,7 +3103,8 @@ static void test_aws_external_account_creds_success_path_region_url_keys_env(
 
 static void test_aws_external_account_creds_success_path_region_env_keys_env(
     void) {
-  expected_md emd[] = {{"authorization", "Bearer token_exchange_access_token"}};
+  std::map<std::string, std::string> emd = {
+      {"authorization", "Bearer token_exchange_access_token"}};
   grpc_core::ExecCtx exec_ctx;
   grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
                                             nullptr, nullptr};
@@ -3086,17 +3127,18 @@ static void test_aws_external_account_creds_success_path_region_env_keys_env(
       "quota_project_id",                 // quota_project_id;
       "client_id",                        // client_id;
       "client_secret",                    // client_secret;
+      "",                                 // workforce_pool_user_project;
   };
   auto creds =
       grpc_core::AwsExternalAccountCredentials::Create(options, {}, &error);
   GPR_ASSERT(creds != nullptr);
   GPR_ASSERT(error == GRPC_ERROR_NONE);
   GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
-  request_metadata_state* state =
-      make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
+  RequestMetadataState* state =
+      RequestMetadataState::NewInstance(GRPC_ERROR_NONE, emd);
   grpc_httpcli_set_override(aws_external_account_creds_httpcli_get_success,
                             aws_external_account_creds_httpcli_post_success);
-  run_request_metadata_test(creds.get(), auth_md_ctx, state);
+  state->RunRequestMetadataTest(creds.get(), auth_md_ctx);
   grpc_core::ExecCtx::Get()->Flush();
   grpc_httpcli_set_override(nullptr, nullptr);
   gpr_unsetenv("AWS_REGION");
@@ -3107,7 +3149,8 @@ static void test_aws_external_account_creds_success_path_region_env_keys_env(
 
 static void
 test_aws_external_account_creds_success_path_default_region_env_keys_env(void) {
-  expected_md emd[] = {{"authorization", "Bearer token_exchange_access_token"}};
+  std::map<std::string, std::string> emd = {
+      {"authorization", "Bearer token_exchange_access_token"}};
   grpc_core::ExecCtx exec_ctx;
   grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
                                             nullptr, nullptr};
@@ -3130,17 +3173,18 @@ test_aws_external_account_creds_success_path_default_region_env_keys_env(void) {
       "quota_project_id",                 // quota_project_id;
       "client_id",                        // client_id;
       "client_secret",                    // client_secret;
+      "",                                 // workforce_pool_user_project;
   };
   auto creds =
       grpc_core::AwsExternalAccountCredentials::Create(options, {}, &error);
   GPR_ASSERT(creds != nullptr);
   GPR_ASSERT(error == GRPC_ERROR_NONE);
   GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
-  request_metadata_state* state =
-      make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
+  RequestMetadataState* state =
+      RequestMetadataState::NewInstance(GRPC_ERROR_NONE, emd);
   grpc_httpcli_set_override(aws_external_account_creds_httpcli_get_success,
                             aws_external_account_creds_httpcli_post_success);
-  run_request_metadata_test(creds.get(), auth_md_ctx, state);
+  state->RunRequestMetadataTest(creds.get(), auth_md_ctx);
   grpc_core::ExecCtx::Get()->Flush();
   grpc_httpcli_set_override(nullptr, nullptr);
   gpr_unsetenv("AWS_DEFAULT_REGION");
@@ -3152,7 +3196,8 @@ test_aws_external_account_creds_success_path_default_region_env_keys_env(void) {
 static void
 test_aws_external_account_creds_success_path_duplicate_region_env_keys_env(
     void) {
-  expected_md emd[] = {{"authorization", "Bearer token_exchange_access_token"}};
+  std::map<std::string, std::string> emd = {
+      {"authorization", "Bearer token_exchange_access_token"}};
   grpc_core::ExecCtx exec_ctx;
   grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
                                             nullptr, nullptr};
@@ -3177,17 +3222,18 @@ test_aws_external_account_creds_success_path_duplicate_region_env_keys_env(
       "quota_project_id",                 // quota_project_id;
       "client_id",                        // client_id;
       "client_secret",                    // client_secret;
+      "",                                 // workforce_pool_user_project;
   };
   auto creds =
       grpc_core::AwsExternalAccountCredentials::Create(options, {}, &error);
   GPR_ASSERT(creds != nullptr);
   GPR_ASSERT(error == GRPC_ERROR_NONE);
   GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
-  request_metadata_state* state =
-      make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
+  RequestMetadataState* state =
+      RequestMetadataState::NewInstance(GRPC_ERROR_NONE, emd);
   grpc_httpcli_set_override(aws_external_account_creds_httpcli_get_success,
                             aws_external_account_creds_httpcli_post_success);
-  run_request_metadata_test(creds.get(), auth_md_ctx, state);
+  state->RunRequestMetadataTest(creds.get(), auth_md_ctx);
   grpc_core::ExecCtx::Get()->Flush();
   grpc_httpcli_set_override(nullptr, nullptr);
   gpr_unsetenv("AWS_REGION");
@@ -3215,16 +3261,16 @@ static void test_aws_external_account_creds_failure_unmatched_environment_id(
       "quota_project_id",                 // quota_project_id;
       "client_id",                        // client_id;
       "client_secret",                    // client_secret;
+      "",                                 // workforce_pool_user_project;
   };
   auto creds =
       grpc_core::AwsExternalAccountCredentials::Create(options, {}, &error);
   GPR_ASSERT(creds == nullptr);
-  grpc_slice expected_error_slice =
-      grpc_slice_from_static_string("environment_id does not match.");
-  grpc_slice actual_error_slice;
-  GPR_ASSERT(grpc_error_get_str(error, GRPC_ERROR_STR_DESCRIPTION,
-                                &actual_error_slice));
-  GPR_ASSERT(grpc_slice_cmp(expected_error_slice, actual_error_slice) == 0);
+  std::string expected_error = "environment_id does not match.";
+  std::string actual_error;
+  GPR_ASSERT(
+      grpc_error_get_str(error, GRPC_ERROR_STR_DESCRIPTION, &actual_error));
+  GPR_ASSERT(expected_error == actual_error);
   GRPC_ERROR_UNREF(error);
 }
 
@@ -3248,6 +3294,7 @@ static void test_aws_external_account_creds_failure_invalid_region_url(void) {
       "quota_project_id",                 // quota_project_id;
       "client_id",                        // client_id;
       "client_secret",                    // client_secret;
+      "",                                 // workforce_pool_user_project;
   };
   auto creds =
       grpc_core::AwsExternalAccountCredentials::Create(options, {}, &error);
@@ -3259,11 +3306,11 @@ static void test_aws_external_account_creds_failure_invalid_region_url(void) {
   grpc_error_handle expected_error =
       GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
           "Error occurred when fetching oauth2 token.", &error, 1);
-  request_metadata_state* state =
-      make_request_metadata_state(expected_error, nullptr, 0);
+  RequestMetadataState* state =
+      RequestMetadataState::NewInstance(expected_error, {});
   grpc_httpcli_set_override(aws_external_account_creds_httpcli_get_success,
                             aws_external_account_creds_httpcli_post_success);
-  run_request_metadata_test(creds.get(), auth_md_ctx, state);
+  state->RunRequestMetadataTest(creds.get(), auth_md_ctx);
   grpc_core::ExecCtx::Get()->Flush();
   grpc_httpcli_set_override(nullptr, nullptr);
   GRPC_ERROR_UNREF(error);
@@ -3289,6 +3336,7 @@ static void test_aws_external_account_creds_failure_invalid_url(void) {
       "quota_project_id",                 // quota_project_id;
       "client_id",                        // client_id;
       "client_secret",                    // client_secret;
+      "",                                 // workforce_pool_user_project;
   };
   auto creds =
       grpc_core::AwsExternalAccountCredentials::Create(options, {}, &error);
@@ -3299,11 +3347,11 @@ static void test_aws_external_account_creds_failure_invalid_url(void) {
   grpc_error_handle expected_error =
       GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
           "Error occurred when fetching oauth2 token.", &error, 1);
-  request_metadata_state* state =
-      make_request_metadata_state(expected_error, nullptr, 0);
+  RequestMetadataState* state =
+      RequestMetadataState::NewInstance(expected_error, {});
   grpc_httpcli_set_override(aws_external_account_creds_httpcli_get_success,
                             aws_external_account_creds_httpcli_post_success);
-  run_request_metadata_test(creds.get(), auth_md_ctx, state);
+  state->RunRequestMetadataTest(creds.get(), auth_md_ctx);
   grpc_core::ExecCtx::Get()->Flush();
   grpc_httpcli_set_override(nullptr, nullptr);
   GRPC_ERROR_UNREF(error);
@@ -3329,6 +3377,7 @@ static void test_aws_external_account_creds_failure_missing_role_name(void) {
       "quota_project_id",                 // quota_project_id;
       "client_id",                        // client_id;
       "client_secret",                    // client_secret;
+      "",                                 // workforce_pool_user_project;
   };
   auto creds =
       grpc_core::AwsExternalAccountCredentials::Create(options, {}, &error);
@@ -3340,11 +3389,11 @@ static void test_aws_external_account_creds_failure_missing_role_name(void) {
   grpc_error_handle expected_error =
       GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
           "Error occurred when fetching oauth2 token.", &error, 1);
-  request_metadata_state* state =
-      make_request_metadata_state(expected_error, nullptr, 0);
+  RequestMetadataState* state =
+      RequestMetadataState::NewInstance(expected_error, {});
   grpc_httpcli_set_override(aws_external_account_creds_httpcli_get_success,
                             aws_external_account_creds_httpcli_post_success);
-  run_request_metadata_test(creds.get(), auth_md_ctx, state);
+  state->RunRequestMetadataTest(creds.get(), auth_md_ctx);
   grpc_core::ExecCtx::Get()->Flush();
   grpc_httpcli_set_override(nullptr, nullptr);
   GRPC_ERROR_UNREF(error);
@@ -3372,6 +3421,7 @@ test_aws_external_account_creds_failure_invalid_regional_cred_verification_url(
       "quota_project_id",                 // quota_project_id;
       "client_id",                        // client_id;
       "client_secret",                    // client_secret;
+      "",                                 // workforce_pool_user_project;
   };
   auto creds =
       grpc_core::AwsExternalAccountCredentials::Create(options, {}, &error);
@@ -3383,11 +3433,11 @@ test_aws_external_account_creds_failure_invalid_regional_cred_verification_url(
   grpc_error_handle expected_error =
       GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
           "Error occurred when fetching oauth2 token.", &error, 1);
-  request_metadata_state* state =
-      make_request_metadata_state(expected_error, nullptr, 0);
+  RequestMetadataState* state =
+      RequestMetadataState::NewInstance(expected_error, {});
   grpc_httpcli_set_override(aws_external_account_creds_httpcli_get_success,
                             aws_external_account_creds_httpcli_post_success);
-  run_request_metadata_test(creds.get(), auth_md_ctx, state);
+  state->RunRequestMetadataTest(creds.get(), auth_md_ctx);
   grpc_core::ExecCtx::Get()->Flush();
   grpc_httpcli_set_override(nullptr, nullptr);
   GRPC_ERROR_UNREF(error);
@@ -3479,6 +3529,50 @@ test_external_account_credentials_create_failure_invalid_options_credential_sour
   GPR_ASSERT(creds == nullptr);
 }
 
+static void test_external_account_credentials_create_success_workforce_pool(
+    void) {
+  const char* url_options_string =
+      "{\"type\":\"external_account\",\"audience\":\"//iam.googleapis.com/"
+      "locations/location/workforcePools/pool/providers/provider\",\"subject_"
+      "token_type\":\"subject_token_type\",\"service_account_impersonation_"
+      "url\":\"service_account_impersonation_url\",\"token_url\":\"https://"
+      "foo.com:5555/token\",\"token_info_url\":\"https://foo.com:5555/"
+      "token_info\",\"credential_source\":{\"url\":\"https://foo.com:5555/"
+      "generate_subject_token_format_json\",\"headers\":{\"Metadata-Flavor\":"
+      "\"Google\"},\"format\":{\"type\":\"json\",\"subject_token_field_name\":"
+      "\"access_token\"}},\"quota_project_id\":\"quota_"
+      "project_id\",\"client_id\":\"client_id\",\"client_secret\":\"client_"
+      "secret\",\"workforce_pool_user_project\":\"workforce_pool_user_"
+      "project\"}";
+  const char* url_scopes_string = "scope1,scope2";
+  grpc_call_credentials* url_creds = grpc_external_account_credentials_create(
+      url_options_string, url_scopes_string);
+  GPR_ASSERT(url_creds != nullptr);
+  url_creds->Unref();
+}
+
+static void
+test_external_account_credentials_create_failure_invalid_workforce_pool_audience(
+    void) {
+  const char* url_options_string =
+      "{\"type\":\"external_account\",\"audience\":\"invalid_workforce_pool_"
+      "audience\",\"subject_"
+      "token_type\":\"subject_token_type\",\"service_account_impersonation_"
+      "url\":\"service_account_impersonation_url\",\"token_url\":\"https://"
+      "foo.com:5555/token\",\"token_info_url\":\"https://foo.com:5555/"
+      "token_info\",\"credential_source\":{\"url\":\"https://foo.com:5555/"
+      "generate_subject_token_format_json\",\"headers\":{\"Metadata-Flavor\":"
+      "\"Google\"},\"format\":{\"type\":\"json\",\"subject_token_field_name\":"
+      "\"access_token\"}},\"quota_project_id\":\"quota_"
+      "project_id\",\"client_id\":\"client_id\",\"client_secret\":\"client_"
+      "secret\",\"workforce_pool_user_project\":\"workforce_pool_user_"
+      "project\"}";
+  const char* url_scopes_string = "scope1,scope2";
+  grpc_call_credentials* url_creds = grpc_external_account_credentials_create(
+      url_options_string, url_scopes_string);
+  GPR_ASSERT(url_creds == nullptr);
+}
+
 int main(int argc, char** argv) {
   grpc::testing::TestEnvironment env(argc, argv);
   grpc_init();
@@ -3558,6 +3652,8 @@ int main(int argc, char** argv) {
   test_external_account_credentials_create_failure_invalid_json_format();
   test_external_account_credentials_create_failure_invalid_options_format();
   test_external_account_credentials_create_failure_invalid_options_credential_source();
+  test_external_account_credentials_create_success_workforce_pool();
+  test_external_account_credentials_create_failure_invalid_workforce_pool_audience();
   grpc_shutdown();
   return 0;
 }
index 480b3fe..d041053 100644 (file)
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 exports_files([
     "bundle.pem",
index f298a35..3f1c87c 100644 (file)
 
 #include "src/core/lib/security/authorization/grpc_authorization_engine.h"
 #include "test/core/util/test_config.h"
+#include "test/core/util/tls_utils.h"
+
+#define VALID_POLICY_PATH_1 \
+  "test/core/security/authorization/test_policies/valid_policy_1.json"
+#define VALID_POLICY_PATH_2 \
+  "test/core/security/authorization/test_policies/valid_policy_2.json"
+#define INVALID_POLICY_PATH \
+  "test/core/security/authorization/test_policies/invalid_policy.json"
 
 namespace grpc_core {
 
 TEST(AuthorizationPolicyProviderTest, StaticDataInitializationSuccessful) {
-  const char* authz_policy =
-      "{"
-      "  \"name\": \"authz\","
-      "  \"allow_rules\": ["
-      "    {"
-      "      \"name\": \"allow_policy\""
-      "    }"
-      "  ]"
-      "}";
-  auto provider = StaticDataAuthorizationPolicyProvider::Create(authz_policy);
+  auto provider = StaticDataAuthorizationPolicyProvider::Create(
+      testing::GetFileContents(VALID_POLICY_PATH_1));
   ASSERT_TRUE(provider.ok());
   auto engines = (*provider)->engines();
-  ASSERT_NE(engines.allow_engine, nullptr);
-  EXPECT_EQ(dynamic_cast<GrpcAuthorizationEngine*>(engines.allow_engine.get())
-                ->action(),
-            Rbac::Action::kAllow);
-  ASSERT_NE(engines.deny_engine, nullptr);
-  EXPECT_EQ(dynamic_cast<GrpcAuthorizationEngine*>(engines.deny_engine.get())
-                ->action(),
-            Rbac::Action::kDeny);
+  auto* allow_engine =
+      dynamic_cast<GrpcAuthorizationEngine*>(engines.allow_engine.get());
+  ASSERT_NE(allow_engine, nullptr);
+  EXPECT_EQ(allow_engine->action(), Rbac::Action::kAllow);
+  EXPECT_EQ(allow_engine->num_policies(), 1);
+  auto* deny_engine =
+      dynamic_cast<GrpcAuthorizationEngine*>(engines.deny_engine.get());
+  ASSERT_NE(deny_engine, nullptr);
+  EXPECT_EQ(deny_engine->action(), Rbac::Action::kDeny);
+  EXPECT_EQ(deny_engine->num_policies(), 1);
 }
 
 TEST(AuthorizationPolicyProviderTest,
      StaticDataInitializationFailedInvalidPolicy) {
-  const char* authz_policy = "{}";
-  auto provider = StaticDataAuthorizationPolicyProvider::Create(authz_policy);
+  auto provider = StaticDataAuthorizationPolicyProvider::Create(
+      testing::GetFileContents(INVALID_POLICY_PATH));
+  EXPECT_EQ(provider.status().code(), absl::StatusCode::kInvalidArgument);
+  EXPECT_EQ(provider.status().message(), "\"name\" field is not present.");
+}
+
+TEST(AuthorizationPolicyProviderTest,
+     FileWatcherInitializationSuccessValidPolicy) {
+  auto tmp_authz_policy = absl::make_unique<testing::TmpFile>(
+      testing::GetFileContents(VALID_POLICY_PATH_1));
+  auto provider = FileWatcherAuthorizationPolicyProvider::Create(
+      tmp_authz_policy->name(), /*refresh_interval_sec=*/1);
+  ASSERT_TRUE(provider.ok());
+  auto engines = (*provider)->engines();
+  auto* allow_engine =
+      dynamic_cast<GrpcAuthorizationEngine*>(engines.allow_engine.get());
+  ASSERT_NE(allow_engine, nullptr);
+  EXPECT_EQ(allow_engine->action(), Rbac::Action::kAllow);
+  EXPECT_EQ(allow_engine->num_policies(), 1);
+  auto* deny_engine =
+      dynamic_cast<GrpcAuthorizationEngine*>(engines.deny_engine.get());
+  ASSERT_NE(deny_engine, nullptr);
+  EXPECT_EQ(deny_engine->action(), Rbac::Action::kDeny);
+  EXPECT_EQ(deny_engine->num_policies(), 1);
+}
+
+TEST(AuthorizationPolicyProviderTest,
+     FileWatcherInitializationFailedInvalidPolicy) {
+  auto tmp_authz_policy = absl::make_unique<testing::TmpFile>(
+      testing::GetFileContents(INVALID_POLICY_PATH));
+  auto provider = FileWatcherAuthorizationPolicyProvider::Create(
+      tmp_authz_policy->name(), /*refresh_interval_sec=*/1);
   EXPECT_EQ(provider.status().code(), absl::StatusCode::kInvalidArgument);
   EXPECT_EQ(provider.status().message(), "\"name\" field is not present.");
 }
 
+TEST(AuthorizationPolicyProviderTest, FileWatcherSuccessValidPolicyRefresh) {
+  auto tmp_authz_policy = absl::make_unique<testing::TmpFile>(
+      testing::GetFileContents(VALID_POLICY_PATH_1));
+  auto provider = FileWatcherAuthorizationPolicyProvider::Create(
+      tmp_authz_policy->name(), /*refresh_interval_sec=*/1);
+  ASSERT_TRUE(provider.ok());
+  auto engines = (*provider)->engines();
+  auto* allow_engine =
+      dynamic_cast<GrpcAuthorizationEngine*>(engines.allow_engine.get());
+  ASSERT_NE(allow_engine, nullptr);
+  EXPECT_EQ(allow_engine->action(), Rbac::Action::kAllow);
+  EXPECT_EQ(allow_engine->num_policies(), 1);
+  auto* deny_engine =
+      dynamic_cast<GrpcAuthorizationEngine*>(engines.deny_engine.get());
+  ASSERT_NE(deny_engine, nullptr);
+  EXPECT_EQ(deny_engine->action(), Rbac::Action::kDeny);
+  EXPECT_EQ(deny_engine->num_policies(), 1);
+  // Rewrite the file with a different valid authorization policy.
+  tmp_authz_policy->RewriteFile(testing::GetFileContents(VALID_POLICY_PATH_2));
+  // Wait 2 seconds for the provider's refresh thread to read the updated files.
+  gpr_sleep_until(grpc_timeout_seconds_to_deadline(2));
+  engines = (*provider)->engines();
+  allow_engine =
+      dynamic_cast<GrpcAuthorizationEngine*>(engines.allow_engine.get());
+  ASSERT_NE(allow_engine, nullptr);
+  EXPECT_EQ(allow_engine->action(), Rbac::Action::kAllow);
+  EXPECT_EQ(allow_engine->num_policies(), 2);
+  deny_engine =
+      dynamic_cast<GrpcAuthorizationEngine*>(engines.deny_engine.get());
+  ASSERT_NE(deny_engine, nullptr);
+  EXPECT_EQ(deny_engine->action(), Rbac::Action::kDeny);
+  EXPECT_EQ(deny_engine->num_policies(), 0);
+}
+
+TEST(AuthorizationPolicyProviderTest,
+     FileWatcherInvalidPolicyRefreshSkipReload) {
+  auto tmp_authz_policy = absl::make_unique<testing::TmpFile>(
+      testing::GetFileContents(VALID_POLICY_PATH_1));
+  auto provider = FileWatcherAuthorizationPolicyProvider::Create(
+      tmp_authz_policy->name(), /*refresh_interval_sec=*/1);
+  ASSERT_TRUE(provider.ok());
+  auto engines = (*provider)->engines();
+  auto* allow_engine =
+      dynamic_cast<GrpcAuthorizationEngine*>(engines.allow_engine.get());
+  ASSERT_NE(allow_engine, nullptr);
+  EXPECT_EQ(allow_engine->action(), Rbac::Action::kAllow);
+  EXPECT_EQ(allow_engine->num_policies(), 1);
+  auto* deny_engine =
+      dynamic_cast<GrpcAuthorizationEngine*>(engines.deny_engine.get());
+  ASSERT_NE(deny_engine, nullptr);
+  EXPECT_EQ(deny_engine->action(), Rbac::Action::kDeny);
+  EXPECT_EQ(deny_engine->num_policies(), 1);
+  // Skips the following policy update, and continues to use the valid policy.
+  tmp_authz_policy->RewriteFile(testing::GetFileContents(INVALID_POLICY_PATH));
+  // Wait 2 seconds for the provider's refresh thread to read the updated files.
+  gpr_sleep_until(grpc_timeout_seconds_to_deadline(2));
+  engines = (*provider)->engines();
+  allow_engine =
+      dynamic_cast<GrpcAuthorizationEngine*>(engines.allow_engine.get());
+  ASSERT_NE(allow_engine, nullptr);
+  EXPECT_EQ(allow_engine->action(), Rbac::Action::kAllow);
+  EXPECT_EQ(allow_engine->num_policies(), 1);
+  deny_engine =
+      dynamic_cast<GrpcAuthorizationEngine*>(engines.deny_engine.get());
+  ASSERT_NE(deny_engine, nullptr);
+  EXPECT_EQ(deny_engine->action(), Rbac::Action::kDeny);
+  EXPECT_EQ(deny_engine->num_policies(), 1);
+}
+
+TEST(AuthorizationPolicyProviderTest, FileWatcherRecoversFromFailure) {
+  auto tmp_authz_policy = absl::make_unique<testing::TmpFile>(
+      testing::GetFileContents(VALID_POLICY_PATH_1));
+  auto provider = FileWatcherAuthorizationPolicyProvider::Create(
+      tmp_authz_policy->name(), /*refresh_interval_sec=*/1);
+  ASSERT_TRUE(provider.ok());
+  auto engines = (*provider)->engines();
+  auto* allow_engine =
+      dynamic_cast<GrpcAuthorizationEngine*>(engines.allow_engine.get());
+  ASSERT_NE(allow_engine, nullptr);
+  EXPECT_EQ(allow_engine->action(), Rbac::Action::kAllow);
+  EXPECT_EQ(allow_engine->num_policies(), 1);
+  auto* deny_engine =
+      dynamic_cast<GrpcAuthorizationEngine*>(engines.deny_engine.get());
+  ASSERT_NE(deny_engine, nullptr);
+  EXPECT_EQ(deny_engine->action(), Rbac::Action::kDeny);
+  EXPECT_EQ(deny_engine->num_policies(), 1);
+  // Skips the following policy update, and continues to use the valid policy.
+  tmp_authz_policy->RewriteFile(testing::GetFileContents(INVALID_POLICY_PATH));
+  // Wait 2 seconds for the provider's refresh thread to read the updated files.
+  gpr_sleep_until(grpc_timeout_seconds_to_deadline(2));
+  engines = (*provider)->engines();
+  allow_engine =
+      dynamic_cast<GrpcAuthorizationEngine*>(engines.allow_engine.get());
+  ASSERT_NE(allow_engine, nullptr);
+  EXPECT_EQ(allow_engine->action(), Rbac::Action::kAllow);
+  EXPECT_EQ(allow_engine->num_policies(), 1);
+  deny_engine =
+      dynamic_cast<GrpcAuthorizationEngine*>(engines.deny_engine.get());
+  ASSERT_NE(deny_engine, nullptr);
+  EXPECT_EQ(deny_engine->action(), Rbac::Action::kDeny);
+  EXPECT_EQ(deny_engine->num_policies(), 1);
+  // Rewrite the file with a valid authorization policy.
+  tmp_authz_policy->RewriteFile(testing::GetFileContents(VALID_POLICY_PATH_2));
+  // Wait 2 seconds for the provider's refresh thread to read the updated files.
+  gpr_sleep_until(grpc_timeout_seconds_to_deadline(2));
+  engines = (*provider)->engines();
+  allow_engine =
+      dynamic_cast<GrpcAuthorizationEngine*>(engines.allow_engine.get());
+  ASSERT_NE(allow_engine, nullptr);
+  EXPECT_EQ(allow_engine->action(), Rbac::Action::kAllow);
+  EXPECT_EQ(allow_engine->num_policies(), 2);
+  deny_engine =
+      dynamic_cast<GrpcAuthorizationEngine*>(engines.deny_engine.get());
+  ASSERT_NE(deny_engine, nullptr);
+  EXPECT_EQ(deny_engine->action(), Rbac::Action::kDeny);
+  EXPECT_EQ(deny_engine->num_policies(), 0);
+}
+
 }  // namespace grpc_core
 
 int main(int argc, char** argv) {
+  grpc::testing::TestEnvironment env(argc, argv);
   ::testing::InitGoogleTest(&argc, argv);
-  return RUN_ALL_TESTS();
+  grpc_init();
+  int ret = RUN_ALL_TESTS();
+  grpc_shutdown();
+  return ret;
 }
index 17aac54..24a25a1 100644 (file)
@@ -137,18 +137,13 @@ class GrpcTlsCertificateDistributorTest : public ::testing::Test {
       std::string root_error_str;
       std::string identity_error_str;
       if (root_cert_error != GRPC_ERROR_NONE) {
-        grpc_slice root_error_slice;
         GPR_ASSERT(grpc_error_get_str(
-            root_cert_error, GRPC_ERROR_STR_DESCRIPTION, &root_error_slice));
-        root_error_str = std::string(StringViewFromSlice(root_error_slice));
+            root_cert_error, GRPC_ERROR_STR_DESCRIPTION, &root_error_str));
       }
       if (identity_cert_error != GRPC_ERROR_NONE) {
-        grpc_slice identity_error_slice;
         GPR_ASSERT(grpc_error_get_str(identity_cert_error,
                                       GRPC_ERROR_STR_DESCRIPTION,
-                                      &identity_error_slice));
-        identity_error_str =
-            std::string(StringViewFromSlice(identity_error_slice));
+                                      &identity_error_str));
       }
       state_->error_queue.emplace_back(std::move(root_error_str),
                                        std::move(identity_error_str));
index 40e6f03..a13e807 100644 (file)
@@ -139,18 +139,13 @@ class GrpcTlsCertificateProviderTest : public ::testing::Test {
       std::string root_error_str;
       std::string identity_error_str;
       if (root_cert_error != GRPC_ERROR_NONE) {
-        grpc_slice root_error_slice;
         GPR_ASSERT(grpc_error_get_str(
-            root_cert_error, GRPC_ERROR_STR_DESCRIPTION, &root_error_slice));
-        root_error_str = std::string(StringViewFromSlice(root_error_slice));
+            root_cert_error, GRPC_ERROR_STR_DESCRIPTION, &root_error_str));
       }
       if (identity_cert_error != GRPC_ERROR_NONE) {
-        grpc_slice identity_error_slice;
         GPR_ASSERT(grpc_error_get_str(identity_cert_error,
                                       GRPC_ERROR_STR_DESCRIPTION,
-                                      &identity_error_slice));
-        identity_error_str =
-            std::string(StringViewFromSlice(identity_error_slice));
+                                      &identity_error_str));
       }
       state_->error_queue.emplace_back(std::move(root_error_str),
                                        std::move(identity_error_str));
index 1ede053..ef09559 100644 (file)
@@ -376,6 +376,106 @@ TEST_F(TlsSecurityConnectorTest, TlsCheckHostNameFail) {
   GRPC_ERROR_UNREF(error);
 }
 
+TEST_F(TlsSecurityConnectorTest,
+       CompareChannelSecurityConnectorSucceedsOnSameCredentials) {
+  grpc_core::RefCountedPtr<grpc_tls_certificate_distributor> distributor =
+      grpc_core::MakeRefCounted<grpc_tls_certificate_distributor>();
+  distributor->SetKeyMaterials(kRootCertName, root_cert_0_, absl::nullopt);
+  grpc_core::RefCountedPtr<::grpc_tls_certificate_provider> provider =
+      grpc_core::MakeRefCounted<TlsTestCertificateProvider>(distributor);
+  auto options = grpc_core::MakeRefCounted<grpc_tls_credentials_options>();
+  options->set_certificate_provider(provider);
+  options->set_watch_root_cert(true);
+  options->set_root_cert_name(kRootCertName);
+  grpc_core::RefCountedPtr<TlsCredentials> credential =
+      grpc_core::MakeRefCounted<TlsCredentials>(options);
+  grpc_core::RefCountedPtr<grpc_channel_security_connector> connector =
+      credential->create_security_connector(nullptr, kTargetName, nullptr,
+                                            nullptr);
+  grpc_core::RefCountedPtr<grpc_channel_security_connector> other_connector =
+      credential->create_security_connector(nullptr, kTargetName, nullptr,
+                                            nullptr);
+  // Comparing the equality of security connectors generated from the same
+  // channel credentials with same settings should succeed.
+  EXPECT_EQ(connector->cmp(other_connector.get()), 0);
+}
+
+TEST_F(TlsSecurityConnectorTest,
+       CompareChannelSecurityConnectorFailsOnDifferentChannelCredentials) {
+  grpc_core::RefCountedPtr<grpc_tls_certificate_distributor> distributor =
+      grpc_core::MakeRefCounted<grpc_tls_certificate_distributor>();
+  distributor->SetKeyMaterials(kRootCertName, root_cert_0_, absl::nullopt);
+  grpc_core::RefCountedPtr<::grpc_tls_certificate_provider> provider =
+      grpc_core::MakeRefCounted<TlsTestCertificateProvider>(distributor);
+  auto options = grpc_core::MakeRefCounted<grpc_tls_credentials_options>();
+  options->set_certificate_provider(provider);
+  options->set_watch_root_cert(true);
+  options->set_root_cert_name(kRootCertName);
+  grpc_core::RefCountedPtr<TlsCredentials> credential =
+      grpc_core::MakeRefCounted<TlsCredentials>(options);
+  grpc_core::RefCountedPtr<grpc_channel_security_connector> connector =
+      credential->create_security_connector(nullptr, kTargetName, nullptr,
+                                            nullptr);
+  grpc_core::RefCountedPtr<TlsCredentials> other_credential =
+      grpc_core::MakeRefCounted<TlsCredentials>(options);
+  grpc_core::RefCountedPtr<grpc_channel_security_connector> other_connector =
+      other_credential->create_security_connector(nullptr, kTargetName, nullptr,
+                                                  nullptr);
+  // Comparing the equality of security connectors generated from different
+  // channel credentials should fail.
+  EXPECT_NE(connector->cmp(other_connector.get()), 0);
+}
+
+TEST_F(TlsSecurityConnectorTest,
+       CompareChannelSecurityConnectorFailsOnDifferentCallCredentials) {
+  grpc_core::RefCountedPtr<grpc_tls_certificate_distributor> distributor =
+      grpc_core::MakeRefCounted<grpc_tls_certificate_distributor>();
+  distributor->SetKeyMaterials(kRootCertName, root_cert_0_, absl::nullopt);
+  grpc_core::RefCountedPtr<::grpc_tls_certificate_provider> provider =
+      grpc_core::MakeRefCounted<TlsTestCertificateProvider>(distributor);
+  auto options = grpc_core::MakeRefCounted<grpc_tls_credentials_options>();
+  options->set_certificate_provider(provider);
+  options->set_watch_root_cert(true);
+  options->set_root_cert_name(kRootCertName);
+  grpc_core::RefCountedPtr<TlsCredentials> credential =
+      grpc_core::MakeRefCounted<TlsCredentials>(options);
+  grpc_core::RefCountedPtr<grpc_channel_security_connector> connector =
+      credential->create_security_connector(nullptr, kTargetName, nullptr,
+                                            nullptr);
+  grpc_call_credentials* call_creds =
+      grpc_md_only_test_credentials_create("", "", true);
+  grpc_core::RefCountedPtr<grpc_channel_security_connector> other_connector =
+      credential->create_security_connector(
+          grpc_core::RefCountedPtr<grpc_call_credentials>(call_creds),
+          kTargetName, nullptr, nullptr);
+  // Comparing the equality of security connectors generated with different call
+  // credentials should fail.
+  EXPECT_NE(connector->cmp(other_connector.get()), 0);
+}
+
+TEST_F(TlsSecurityConnectorTest,
+       CompareChannelSecurityConnectorFailsOnDifferentTargetNames) {
+  grpc_core::RefCountedPtr<grpc_tls_certificate_distributor> distributor =
+      grpc_core::MakeRefCounted<grpc_tls_certificate_distributor>();
+  distributor->SetKeyMaterials(kRootCertName, root_cert_0_, absl::nullopt);
+  grpc_core::RefCountedPtr<::grpc_tls_certificate_provider> provider =
+      grpc_core::MakeRefCounted<TlsTestCertificateProvider>(distributor);
+  auto options = grpc_core::MakeRefCounted<grpc_tls_credentials_options>();
+  options->set_certificate_provider(provider);
+  options->set_watch_root_cert(true);
+  options->set_root_cert_name(kRootCertName);
+  grpc_core::RefCountedPtr<TlsCredentials> credential =
+      grpc_core::MakeRefCounted<TlsCredentials>(options);
+  grpc_core::RefCountedPtr<grpc_channel_security_connector> connector =
+      credential->create_security_connector(nullptr, kTargetName, nullptr,
+                                            nullptr);
+  grpc_core::RefCountedPtr<grpc_channel_security_connector> other_connector =
+      credential->create_security_connector(nullptr, "", nullptr, nullptr);
+  // Comparing the equality of security connectors generated with different
+  // target names should fail.
+  EXPECT_NE(connector->cmp(other_connector.get()), 0);
+}
+
 // Tests for ServerSecurityConnector.
 TEST_F(TlsSecurityConnectorTest,
        RootAndIdentityCertsObtainedWhenCreateServerSecurityConnector) {
@@ -543,6 +643,54 @@ TEST_F(TlsSecurityConnectorTest, CreateServerSecurityConnectorFailNoOptions) {
   EXPECT_EQ(connector, nullptr);
 }
 
+TEST_F(TlsSecurityConnectorTest,
+       CompareServerSecurityConnectorSucceedsOnSameCredentials) {
+  grpc_core::RefCountedPtr<grpc_tls_certificate_distributor> distributor =
+      grpc_core::MakeRefCounted<grpc_tls_certificate_distributor>();
+  distributor->SetKeyMaterials(kIdentityCertName, absl::nullopt,
+                               identity_pairs_0_);
+  grpc_core::RefCountedPtr<::grpc_tls_certificate_provider> provider =
+      grpc_core::MakeRefCounted<TlsTestCertificateProvider>(distributor);
+  auto options = grpc_core::MakeRefCounted<grpc_tls_credentials_options>();
+  options->set_certificate_provider(provider);
+  options->set_watch_identity_pair(true);
+  options->set_identity_cert_name(kIdentityCertName);
+  grpc_core::RefCountedPtr<TlsServerCredentials> credential =
+      grpc_core::MakeRefCounted<TlsServerCredentials>(options);
+  grpc_core::RefCountedPtr<grpc_server_security_connector> connector =
+      credential->create_security_connector(nullptr);
+  grpc_core::RefCountedPtr<grpc_server_security_connector> other_connector =
+      credential->create_security_connector(nullptr);
+  // Comparing the equality of security connectors generated from the same
+  // server credentials with same settings should succeed.
+  EXPECT_EQ(connector->cmp(other_connector.get()), 0);
+}
+
+TEST_F(TlsSecurityConnectorTest,
+       CompareServerSecurityConnectorFailsOnDifferentServerCredentials) {
+  grpc_core::RefCountedPtr<grpc_tls_certificate_distributor> distributor =
+      grpc_core::MakeRefCounted<grpc_tls_certificate_distributor>();
+  distributor->SetKeyMaterials(kIdentityCertName, absl::nullopt,
+                               identity_pairs_0_);
+  grpc_core::RefCountedPtr<::grpc_tls_certificate_provider> provider =
+      grpc_core::MakeRefCounted<TlsTestCertificateProvider>(distributor);
+  auto options = grpc_core::MakeRefCounted<grpc_tls_credentials_options>();
+  options->set_certificate_provider(provider);
+  options->set_watch_identity_pair(true);
+  options->set_identity_cert_name(kIdentityCertName);
+  grpc_core::RefCountedPtr<TlsServerCredentials> credential =
+      grpc_core::MakeRefCounted<TlsServerCredentials>(options);
+  grpc_core::RefCountedPtr<grpc_server_security_connector> connector =
+      credential->create_security_connector(nullptr);
+  grpc_core::RefCountedPtr<TlsServerCredentials> other_credential =
+      grpc_core::MakeRefCounted<TlsServerCredentials>(options);
+  grpc_core::RefCountedPtr<grpc_server_security_connector> other_connector =
+      other_credential->create_security_connector(nullptr);
+  // Comparing the equality of security connectors generated from different
+  // server credentials should fail.
+  EXPECT_NE(connector->cmp(other_connector.get()), 0);
+}
+
 }  // namespace testing
 }  // namespace grpc
 
diff --git a/test/core/server_config_selector/BUILD b/test/core/server_config_selector/BUILD
new file mode 100644 (file)
index 0000000..33650c8
--- /dev/null
@@ -0,0 +1,35 @@
+# 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.
+
+load("//bazel:grpc_build_system.bzl", "grpc_cc_test", "grpc_package")
+
+licenses(["notice"])
+
+grpc_package(name = "test/core/server_config_selector")
+
+grpc_cc_test(
+    name = "server_config_selector_test",
+    srcs = ["server_config_selector_test.cc"],
+    external_deps = [
+        "gtest",
+    ],
+    language = "C++",
+    uses_polling = False,
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//:grpc_server_config_selector",
+        "//test/core/util:grpc_test_util",
+    ],
+)
diff --git a/test/core/server_config_selector/server_config_selector_test.cc b/test/core/server_config_selector/server_config_selector_test.cc
new file mode 100644 (file)
index 0000000..74c7659
--- /dev/null
@@ -0,0 +1,81 @@
+//
+//
+// 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 "src/core/ext/filters/server_config_selector/server_config_selector.h"
+
+#include <gtest/gtest.h>
+
+#include <grpc/grpc.h>
+#include <grpc/support/log.h>
+
+#include "src/core/lib/channel/channel_args.h"
+#include "test/core/util/test_config.h"
+
+namespace grpc {
+namespace testing {
+namespace {
+
+using grpc_core::ServerConfigSelector;
+using grpc_core::ServerConfigSelectorProvider;
+
+class TestServerConfigSelectorProvider : public ServerConfigSelectorProvider {
+  absl::StatusOr<grpc_core::RefCountedPtr<ServerConfigSelector>> Watch(
+      std::unique_ptr<ServerConfigSelectorWatcher> /* watcher */) override {
+    return absl::UnavailableError("Test ServerConfigSelector");
+  }
+
+  void CancelWatch() override {}
+};
+
+// Test that ServerConfigSelectorProvider can be safely copied to channel args
+// and destroyed
+TEST(ServerConfigSelectorProviderTest, CopyChannelArgs) {
+  auto server_config_selector_provider =
+      grpc_core::MakeRefCounted<TestServerConfigSelectorProvider>();
+  grpc_arg arg = server_config_selector_provider->MakeChannelArg();
+  grpc_channel_args* args = grpc_channel_args_copy_and_add(nullptr, &arg, 1);
+  EXPECT_EQ(server_config_selector_provider,
+            ServerConfigSelectorProvider::GetFromChannelArgs(*args));
+  grpc_channel_args_destroy(args);
+}
+
+// Test compare on channel args with the same ServerConfigSelectorProvider
+TEST(ServerConfigSelectorProviderTest, ChannelArgsCompare) {
+  auto server_config_selector_provider =
+      grpc_core::MakeRefCounted<TestServerConfigSelectorProvider>();
+  grpc_arg arg = server_config_selector_provider->MakeChannelArg();
+  grpc_channel_args* args = grpc_channel_args_copy_and_add(nullptr, &arg, 1);
+  grpc_channel_args* new_args = grpc_channel_args_copy(args);
+  EXPECT_EQ(ServerConfigSelectorProvider::GetFromChannelArgs(*new_args),
+            ServerConfigSelectorProvider::GetFromChannelArgs(*args));
+  grpc_channel_args_destroy(args);
+  grpc_channel_args_destroy(new_args);
+}
+
+}  // namespace
+}  // namespace testing
+}  // namespace grpc
+
+int main(int argc, char** argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  grpc::testing::TestEnvironment env(argc, argv);
+  grpc_init();
+  int ret = RUN_ALL_TESTS();
+  grpc_shutdown();
+  return ret;
+}
index 9be57ab..da209fb 100644 (file)
@@ -16,7 +16,7 @@ load("//bazel:grpc_build_system.bzl", "grpc_cc_binary", "grpc_cc_library", "grpc
 
 grpc_package(name = "test/core/slice")
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
 
@@ -87,6 +87,18 @@ grpc_cc_test(
     uses_polling = False,
     deps = [
         "//:gpr",
+        "//:slice",
+        "//test/core/util:grpc_suppressions",
+    ],
+)
+
+grpc_cc_test(
+    name = "slice_intern_test",
+    srcs = ["slice_intern_test.cc"],
+    language = "C++",
+    uses_polling = False,
+    deps = [
+        "//:gpr",
         "//:grpc",
         "//test/core/util:grpc_test_util",
     ],
@@ -99,6 +111,18 @@ grpc_cc_test(
     uses_polling = False,
     deps = [
         "//:gpr",
+        "//:slice",
+        "//test/core/util:grpc_suppressions",
+    ],
+)
+
+grpc_cc_test(
+    name = "slice_split_test",
+    srcs = ["slice_split_test.cc"],
+    language = "C++",
+    uses_polling = False,
+    deps = [
+        "//:gpr",
         "//:grpc",
         "//test/core/util:grpc_test_util",
     ],
diff --git a/test/core/slice/slice_intern_test.cc b/test/core/slice/slice_intern_test.cc
new file mode 100644 (file)
index 0000000..277351c
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ *
+ * 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 <inttypes.h>
+#include <string.h>
+
+#include <grpc/grpc.h>
+#include <grpc/slice.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+
+#include "src/core/lib/gprpp/memory.h"
+#include "src/core/lib/slice/slice_internal.h"
+#include "src/core/lib/transport/static_metadata.h"
+#include "test/core/util/test_config.h"
+
+#define LOG_TEST_NAME(x) gpr_log(GPR_INFO, "%s", x);
+
+static void test_slice_interning(void) {
+  LOG_TEST_NAME("test_slice_interning");
+
+  grpc_init();
+  grpc_slice src1 = grpc_slice_from_copied_string("hello123456789123456789");
+  grpc_slice src2 = grpc_slice_from_copied_string("hello123456789123456789");
+
+  // Explicitly checking that the slices are at different addresses prevents
+  // failure with windows opt 64bit build.
+  // See https://github.com/grpc/grpc/issues/20519
+  GPR_ASSERT(&src1 != &src2);
+  GPR_ASSERT(GRPC_SLICE_START_PTR(src1) != GRPC_SLICE_START_PTR(src2));
+
+  grpc_slice interned1 = grpc_slice_intern(src1);
+  grpc_slice interned2 = grpc_slice_intern(src2);
+  GPR_ASSERT(GRPC_SLICE_START_PTR(interned1) ==
+             GRPC_SLICE_START_PTR(interned2));
+  GPR_ASSERT(GRPC_SLICE_START_PTR(interned1) != GRPC_SLICE_START_PTR(src1));
+  GPR_ASSERT(GRPC_SLICE_START_PTR(interned2) != GRPC_SLICE_START_PTR(src2));
+  grpc_slice_unref(src1);
+  grpc_slice_unref(src2);
+  grpc_slice_unref(interned1);
+  grpc_slice_unref(interned2);
+  grpc_shutdown();
+}
+
+static void test_static_slice_interning(void) {
+  LOG_TEST_NAME("test_static_slice_interning");
+
+  // grpc_init/grpc_shutdown deliberately omitted: they should not be necessary
+  // to intern a static slice
+
+  for (size_t i = 0; i < GRPC_STATIC_MDSTR_COUNT; i++) {
+    GPR_ASSERT(grpc_slice_is_equivalent(
+        grpc_core::g_static_metadata_slice_table[i],
+        grpc_slice_intern(grpc_core::g_static_metadata_slice_table[i])));
+  }
+}
+
+static void test_static_slice_copy_interning(void) {
+  LOG_TEST_NAME("test_static_slice_copy_interning");
+
+  grpc_init();
+
+  for (size_t i = 0; i < GRPC_STATIC_MDSTR_COUNT; i++) {
+    grpc_slice copy =
+        grpc_slice_dup(grpc_core::g_static_metadata_slice_table[i]);
+    GPR_ASSERT(grpc_core::g_static_metadata_slice_table[i].refcount !=
+               copy.refcount);
+    GPR_ASSERT(grpc_core::g_static_metadata_slice_table[i].refcount ==
+               grpc_slice_intern(copy).refcount);
+    grpc_slice_unref(copy);
+  }
+
+  grpc_shutdown();
+}
+
+int main(int argc, char** argv) {
+  grpc::testing::TestEnvironment env(argc, argv);
+  grpc_init();
+  test_slice_interning();
+  test_static_slice_interning();
+  test_static_slice_copy_interning();
+  grpc_shutdown();
+  return 0;
+}
diff --git a/test/core/slice/slice_split_test.cc b/test/core/slice/slice_split_test.cc
new file mode 100644 (file)
index 0000000..6e349ac
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ *
+ * 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 "src/core/lib/slice/slice_split.h"
+
+#include <limits.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+
+#include "src/core/lib/gpr/string.h"
+#include "test/core/util/test_config.h"
+
+#define LOG_TEST_NAME(x) gpr_log(GPR_INFO, "%s", x)
+
+static void test_strsplit(void) {
+  grpc_slice_buffer* parts;
+  grpc_slice str;
+
+  LOG_TEST_NAME("test_strsplit");
+
+  parts =
+      static_cast<grpc_slice_buffer*>(gpr_malloc(sizeof(grpc_slice_buffer)));
+  grpc_slice_buffer_init(parts);
+
+  str = grpc_slice_from_copied_string("one, two, three, four");
+  grpc_slice_split(str, ", ", parts);
+  GPR_ASSERT(4 == parts->count);
+  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[0], "one"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[1], "two"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[2], "three"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[3], "four"));
+  grpc_slice_buffer_reset_and_unref(parts);
+  grpc_slice_unref(str);
+
+  /* separator not present in string */
+  str = grpc_slice_from_copied_string("one two three four");
+  grpc_slice_split(str, ", ", parts);
+  GPR_ASSERT(1 == parts->count);
+  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[0], "one two three four"));
+  grpc_slice_buffer_reset_and_unref(parts);
+  grpc_slice_unref(str);
+
+  /* separator at the end */
+  str = grpc_slice_from_copied_string("foo,");
+  grpc_slice_split(str, ",", parts);
+  GPR_ASSERT(2 == parts->count);
+  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[0], "foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[1], ""));
+  grpc_slice_buffer_reset_and_unref(parts);
+  grpc_slice_unref(str);
+
+  /* separator at the beginning */
+  str = grpc_slice_from_copied_string(",foo");
+  grpc_slice_split(str, ",", parts);
+  GPR_ASSERT(2 == parts->count);
+  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[0], ""));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[1], "foo"));
+  grpc_slice_buffer_reset_and_unref(parts);
+  grpc_slice_unref(str);
+
+  /* standalone separator */
+  str = grpc_slice_from_copied_string(",");
+  grpc_slice_split(str, ",", parts);
+  GPR_ASSERT(2 == parts->count);
+  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[0], ""));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[1], ""));
+  grpc_slice_buffer_reset_and_unref(parts);
+  grpc_slice_unref(str);
+
+  /* empty input */
+  str = grpc_slice_from_copied_string("");
+  grpc_slice_split(str, ", ", parts);
+  GPR_ASSERT(1 == parts->count);
+  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[0], ""));
+  grpc_slice_buffer_reset_and_unref(parts);
+  grpc_slice_unref(str);
+
+  grpc_slice_buffer_destroy(parts);
+  gpr_free(parts);
+}
+
+static void test_strsplit_nospace(void) {
+  grpc_slice_buffer* parts;
+  grpc_slice str;
+
+  LOG_TEST_NAME("test_strsplit_nospace");
+
+  parts =
+      static_cast<grpc_slice_buffer*>(gpr_malloc(sizeof(grpc_slice_buffer)));
+  grpc_slice_buffer_init(parts);
+
+  str = grpc_slice_from_copied_string("one  ,two,   three  , four");
+  grpc_slice_split_without_space(str, ",", parts);
+  GPR_ASSERT(4 == parts->count);
+  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[0], "one"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[1], "two"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[2], "three"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[3], "four"));
+  grpc_slice_buffer_reset_and_unref(parts);
+  grpc_slice_unref(str);
+
+  /* separator not present in string */
+  str = grpc_slice_from_copied_string("one two three four ");
+  grpc_slice_split_without_space(str, ",", parts);
+  GPR_ASSERT(1 == parts->count);
+  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[0], "one two three four"));
+  grpc_slice_buffer_reset_and_unref(parts);
+  grpc_slice_unref(str);
+
+  /* separator at the end */
+  str = grpc_slice_from_copied_string("foo,");
+  grpc_slice_split_without_space(str, ",", parts);
+  GPR_ASSERT(2 == parts->count);
+  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[0], "foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[1], ""));
+  grpc_slice_buffer_reset_and_unref(parts);
+  grpc_slice_unref(str);
+
+  /* separator at the beginning */
+  str = grpc_slice_from_copied_string(" , foo");
+  grpc_slice_split_without_space(str, ",", parts);
+  GPR_ASSERT(2 == parts->count);
+  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[0], ""));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[1], "foo"));
+  grpc_slice_buffer_reset_and_unref(parts);
+  grpc_slice_unref(str);
+
+  /* standalone separator */
+  str = grpc_slice_from_copied_string(", ");
+  grpc_slice_split_without_space(str, ", ", parts);
+  GPR_ASSERT(2 == parts->count);
+  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[0], ""));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[1], ""));
+  grpc_slice_buffer_reset_and_unref(parts);
+  grpc_slice_unref(str);
+
+  /* empty input */
+  str = grpc_slice_from_copied_string("");
+  grpc_slice_split_without_space(str, ",", parts);
+  GPR_ASSERT(1 == parts->count);
+  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[0], ""));
+  grpc_slice_buffer_reset_and_unref(parts);
+  grpc_slice_unref(str);
+
+  grpc_slice_buffer_destroy(parts);
+  gpr_free(parts);
+}
+
+int main(int argc, char** argv) {
+  grpc::testing::TestEnvironment env(argc, argv);
+  test_strsplit();
+  test_strsplit_nospace();
+  return 0;
+}
index 1bbc094..53b229c 100644 (file)
@@ -28,7 +28,7 @@
 #include <grpc/support/string_util.h>
 
 #include "src/core/lib/gpr/string.h"
-#include "test/core/util/test_config.h"
+#include "src/core/lib/slice/slice_internal.h"
 
 #define LOG_TEST_NAME(x) gpr_log(GPR_INFO, "%s", x)
 
@@ -37,7 +37,7 @@ static void expect_slice_dump(grpc_slice slice, uint32_t flags,
   char* got = grpc_dump_slice(slice, flags);
   GPR_ASSERT(0 == strcmp(got, result));
   gpr_free(got);
-  grpc_slice_unref(slice);
+  grpc_slice_unref_internal(slice);
 }
 
 static void test_dump_slice(void) {
@@ -60,144 +60,7 @@ static void test_dump_slice(void) {
                     GPR_DUMP_HEX | GPR_DUMP_ASCII, "01 '.'");
 }
 
-static void test_strsplit(void) {
-  grpc_slice_buffer* parts;
-  grpc_slice str;
-
-  LOG_TEST_NAME("test_strsplit");
-
-  parts =
-      static_cast<grpc_slice_buffer*>(gpr_malloc(sizeof(grpc_slice_buffer)));
-  grpc_slice_buffer_init(parts);
-
-  str = grpc_slice_from_copied_string("one, two, three, four");
-  grpc_slice_split(str, ", ", parts);
-  GPR_ASSERT(4 == parts->count);
-  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[0], "one"));
-  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[1], "two"));
-  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[2], "three"));
-  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[3], "four"));
-  grpc_slice_buffer_reset_and_unref(parts);
-  grpc_slice_unref(str);
-
-  /* separator not present in string */
-  str = grpc_slice_from_copied_string("one two three four");
-  grpc_slice_split(str, ", ", parts);
-  GPR_ASSERT(1 == parts->count);
-  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[0], "one two three four"));
-  grpc_slice_buffer_reset_and_unref(parts);
-  grpc_slice_unref(str);
-
-  /* separator at the end */
-  str = grpc_slice_from_copied_string("foo,");
-  grpc_slice_split(str, ",", parts);
-  GPR_ASSERT(2 == parts->count);
-  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[0], "foo"));
-  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[1], ""));
-  grpc_slice_buffer_reset_and_unref(parts);
-  grpc_slice_unref(str);
-
-  /* separator at the beginning */
-  str = grpc_slice_from_copied_string(",foo");
-  grpc_slice_split(str, ",", parts);
-  GPR_ASSERT(2 == parts->count);
-  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[0], ""));
-  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[1], "foo"));
-  grpc_slice_buffer_reset_and_unref(parts);
-  grpc_slice_unref(str);
-
-  /* standalone separator */
-  str = grpc_slice_from_copied_string(",");
-  grpc_slice_split(str, ",", parts);
-  GPR_ASSERT(2 == parts->count);
-  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[0], ""));
-  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[1], ""));
-  grpc_slice_buffer_reset_and_unref(parts);
-  grpc_slice_unref(str);
-
-  /* empty input */
-  str = grpc_slice_from_copied_string("");
-  grpc_slice_split(str, ", ", parts);
-  GPR_ASSERT(1 == parts->count);
-  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[0], ""));
-  grpc_slice_buffer_reset_and_unref(parts);
-  grpc_slice_unref(str);
-
-  grpc_slice_buffer_destroy(parts);
-  gpr_free(parts);
-}
-
-static void test_strsplit_nospace(void) {
-  grpc_slice_buffer* parts;
-  grpc_slice str;
-
-  LOG_TEST_NAME("test_strsplit_nospace");
-
-  parts =
-      static_cast<grpc_slice_buffer*>(gpr_malloc(sizeof(grpc_slice_buffer)));
-  grpc_slice_buffer_init(parts);
-
-  str = grpc_slice_from_copied_string("one  ,two,   three  , four");
-  grpc_slice_split_without_space(str, ",", parts);
-  GPR_ASSERT(4 == parts->count);
-  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[0], "one"));
-  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[1], "two"));
-  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[2], "three"));
-  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[3], "four"));
-  grpc_slice_buffer_reset_and_unref(parts);
-  grpc_slice_unref(str);
-
-  /* separator not present in string */
-  str = grpc_slice_from_copied_string("one two three four ");
-  grpc_slice_split_without_space(str, ",", parts);
-  GPR_ASSERT(1 == parts->count);
-  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[0], "one two three four"));
-  grpc_slice_buffer_reset_and_unref(parts);
-  grpc_slice_unref(str);
-
-  /* separator at the end */
-  str = grpc_slice_from_copied_string("foo,");
-  grpc_slice_split_without_space(str, ",", parts);
-  GPR_ASSERT(2 == parts->count);
-  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[0], "foo"));
-  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[1], ""));
-  grpc_slice_buffer_reset_and_unref(parts);
-  grpc_slice_unref(str);
-
-  /* separator at the beginning */
-  str = grpc_slice_from_copied_string(" , foo");
-  grpc_slice_split_without_space(str, ",", parts);
-  GPR_ASSERT(2 == parts->count);
-  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[0], ""));
-  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[1], "foo"));
-  grpc_slice_buffer_reset_and_unref(parts);
-  grpc_slice_unref(str);
-
-  /* standalone separator */
-  str = grpc_slice_from_copied_string(", ");
-  grpc_slice_split_without_space(str, ", ", parts);
-  GPR_ASSERT(2 == parts->count);
-  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[0], ""));
-  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[1], ""));
-  grpc_slice_buffer_reset_and_unref(parts);
-  grpc_slice_unref(str);
-
-  /* empty input */
-  str = grpc_slice_from_copied_string("");
-  grpc_slice_split_without_space(str, ",", parts);
-  GPR_ASSERT(1 == parts->count);
-  GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[0], ""));
-  grpc_slice_buffer_reset_and_unref(parts);
-  grpc_slice_unref(str);
-
-  grpc_slice_buffer_destroy(parts);
-  gpr_free(parts);
-}
-
-int main(int argc, char** argv) {
-  grpc::testing::TestEnvironment env(argc, argv);
+int main(int, char**) {
   test_dump_slice();
-  test_strsplit();
-  test_strsplit_nospace();
   return 0;
 }
index c5c8c5c..3da56f1 100644 (file)
@@ -28,8 +28,6 @@
 
 #include "src/core/lib/gprpp/memory.h"
 #include "src/core/lib/slice/slice_internal.h"
-#include "src/core/lib/transport/static_metadata.h"
-#include "test/core/util/test_config.h"
 
 #define LOG_TEST_NAME(x) gpr_log(GPR_INFO, "%s", x);
 
@@ -56,7 +54,7 @@ static void test_slice_malloc_returns_something_sensible(void) {
       GRPC_SLICE_START_PTR(slice)[i] = static_cast<uint8_t>(i);
     }
     /* And finally we must succeed in destroying the slice */
-    grpc_slice_unref(slice);
+    grpc_slice_unref_internal(slice);
   }
 }
 
@@ -69,7 +67,7 @@ static void test_slice_new_returns_something_sensible(void) {
   GPR_ASSERT(slice.refcount);
   GPR_ASSERT(slice.data.refcounted.bytes == &x);
   GPR_ASSERT(slice.data.refcounted.length == 1);
-  grpc_slice_unref(slice);
+  grpc_slice_unref_internal(slice);
 }
 
 /* destroy function that sets a mark to indicate it was called. */
@@ -89,7 +87,7 @@ static void test_slice_new_with_user_data(void) {
   GPR_ASSERT(GRPC_SLICE_START_PTR(slice)[1] == 1);
 
   /* unref should cause destroy function to run. */
-  grpc_slice_unref(slice);
+  grpc_slice_unref_internal(slice);
   GPR_ASSERT(marker == 1);
 }
 
@@ -115,15 +113,15 @@ static void test_slice_new_with_len_returns_something_sensible(void) {
      make sure that that the destroy callback (i.e do_nothing_with_len_1()) is
      not called until the last unref operation */
   for (i = 0; i < num_refs; i++) {
-    grpc_slice_ref(slice);
+    grpc_slice_ref_internal(slice);
   }
   for (i = 0; i < num_refs; i++) {
-    grpc_slice_unref(slice);
+    grpc_slice_unref_internal(slice);
   }
   GPR_ASSERT(do_nothing_with_len_1_calls == 0); /* Shouldn't be called yet */
 
   /* last unref */
-  grpc_slice_unref(slice);
+  grpc_slice_unref_internal(slice);
   GPR_ASSERT(do_nothing_with_len_1_calls == 1);
 }
 
@@ -151,10 +149,10 @@ static void test_slice_sub_works(unsigned length) {
       for (k = 0; k < j - i; k++) {
         GPR_ASSERT(GRPC_SLICE_START_PTR(sub)[k] == (uint8_t)(i + k));
       }
-      grpc_slice_unref(sub);
+      grpc_slice_unref_internal(sub);
     }
   }
-  grpc_slice_unref(slice);
+  grpc_slice_unref_internal(slice);
 }
 
 static void check_head_tail(grpc_slice slice, grpc_slice head,
@@ -185,14 +183,14 @@ static void test_slice_split_head_works(size_t length) {
   /* Ensure that for all subsets length is correct and that we start on the
      correct byte. Additionally check that no copies were made. */
   for (i = 0; i < length; i++) {
-    tail = grpc_slice_ref(slice);
+    tail = grpc_slice_ref_internal(slice);
     head = grpc_slice_split_head(&tail, i);
     check_head_tail(slice, head, tail);
-    grpc_slice_unref(tail);
-    grpc_slice_unref(head);
+    grpc_slice_unref_internal(tail);
+    grpc_slice_unref_internal(head);
   }
 
-  grpc_slice_unref(slice);
+  grpc_slice_unref_internal(slice);
 }
 
 static void test_slice_split_tail_works(size_t length) {
@@ -213,14 +211,14 @@ static void test_slice_split_tail_works(size_t length) {
   /* Ensure that for all subsets length is correct and that we start on the
      correct byte. Additionally check that no copies were made. */
   for (i = 0; i < length; i++) {
-    head = grpc_slice_ref(slice);
+    head = grpc_slice_ref_internal(slice);
     tail = grpc_slice_split_tail(&head, i);
     check_head_tail(slice, head, tail);
-    grpc_slice_unref(tail);
-    grpc_slice_unref(head);
+    grpc_slice_unref_internal(tail);
+    grpc_slice_unref_internal(head);
   }
 
-  grpc_slice_unref(slice);
+  grpc_slice_unref_internal(slice);
 }
 
 static void test_slice_from_copied_string_works(void) {
@@ -233,69 +231,12 @@ static void test_slice_from_copied_string_works(void) {
   GPR_ASSERT(strlen(text) == GRPC_SLICE_LENGTH(slice));
   GPR_ASSERT(
       0 == memcmp(text, GRPC_SLICE_START_PTR(slice), GRPC_SLICE_LENGTH(slice)));
-  grpc_slice_unref(slice);
-}
-
-static void test_slice_interning(void) {
-  LOG_TEST_NAME("test_slice_interning");
-
-  grpc_init();
-  grpc_slice src1 = grpc_slice_from_copied_string("hello123456789123456789");
-  grpc_slice src2 = grpc_slice_from_copied_string("hello123456789123456789");
-
-  // Explicitly checking that the slices are at different addresses prevents
-  // failure with windows opt 64bit build.
-  // See https://github.com/grpc/grpc/issues/20519
-  GPR_ASSERT(&src1 != &src2);
-  GPR_ASSERT(GRPC_SLICE_START_PTR(src1) != GRPC_SLICE_START_PTR(src2));
-
-  grpc_slice interned1 = grpc_slice_intern(src1);
-  grpc_slice interned2 = grpc_slice_intern(src2);
-  GPR_ASSERT(GRPC_SLICE_START_PTR(interned1) ==
-             GRPC_SLICE_START_PTR(interned2));
-  GPR_ASSERT(GRPC_SLICE_START_PTR(interned1) != GRPC_SLICE_START_PTR(src1));
-  GPR_ASSERT(GRPC_SLICE_START_PTR(interned2) != GRPC_SLICE_START_PTR(src2));
-  grpc_slice_unref(src1);
-  grpc_slice_unref(src2);
-  grpc_slice_unref(interned1);
-  grpc_slice_unref(interned2);
-  grpc_shutdown();
-}
-
-static void test_static_slice_interning(void) {
-  LOG_TEST_NAME("test_static_slice_interning");
-
-  // grpc_init/grpc_shutdown deliberately omitted: they should not be necessary
-  // to intern a static slice
-
-  for (size_t i = 0; i < GRPC_STATIC_MDSTR_COUNT; i++) {
-    GPR_ASSERT(grpc_slice_is_equivalent(
-        grpc_static_slice_table()[i],
-        grpc_slice_intern(grpc_static_slice_table()[i])));
-  }
-}
-
-static void test_static_slice_copy_interning(void) {
-  LOG_TEST_NAME("test_static_slice_copy_interning");
-
-  grpc_init();
-
-  for (size_t i = 0; i < GRPC_STATIC_MDSTR_COUNT; i++) {
-    grpc_slice copy = grpc_slice_dup(grpc_static_slice_table()[i]);
-    GPR_ASSERT(grpc_static_slice_table()[i].refcount != copy.refcount);
-    GPR_ASSERT(grpc_static_slice_table()[i].refcount ==
-               grpc_slice_intern(copy).refcount);
-    grpc_slice_unref(copy);
-  }
-
-  grpc_shutdown();
+  grpc_slice_unref_internal(slice);
 }
 
 static void test_moved_string_slice(void) {
   LOG_TEST_NAME("test_moved_string_slice");
 
-  grpc_init();
-
   // Small string should be inlined.
   constexpr char kSmallStr[] = "hello12345";
   char* small_ptr = strdup(kSmallStr);
@@ -304,7 +245,7 @@ static void test_moved_string_slice(void) {
   GPR_ASSERT(GRPC_SLICE_LENGTH(small) == strlen(kSmallStr));
   GPR_ASSERT(GRPC_SLICE_START_PTR(small) !=
              reinterpret_cast<uint8_t*>(small_ptr));
-  grpc_slice_unref(small);
+  grpc_slice_unref_internal(small);
 
   // Large string should be move the reference.
   constexpr char kSLargeStr[] = "hello123456789123456789123456789";
@@ -314,7 +255,7 @@ static void test_moved_string_slice(void) {
   GPR_ASSERT(GRPC_SLICE_LENGTH(large) == strlen(kSLargeStr));
   GPR_ASSERT(GRPC_SLICE_START_PTR(large) ==
              reinterpret_cast<uint8_t*>(large_ptr));
-  grpc_slice_unref(large);
+  grpc_slice_unref_internal(large);
 
   // Moved buffer must respect the provided length not the actual length of the
   // string.
@@ -324,9 +265,7 @@ static void test_moved_string_slice(void) {
   GPR_ASSERT(GRPC_SLICE_LENGTH(small) == strlen(kSmallStr));
   GPR_ASSERT(GRPC_SLICE_START_PTR(small) !=
              reinterpret_cast<uint8_t*>(large_ptr));
-  grpc_slice_unref(small);
-
-  grpc_shutdown();
+  grpc_slice_unref_internal(small);
 }
 
 void test_string_view_from_slice() {
@@ -336,10 +275,8 @@ void test_string_view_from_slice() {
   GPR_ASSERT(std::string(sv) == kStr);
 }
 
-int main(int argc, char** argv) {
+int main(int, char**) {
   unsigned length;
-  grpc::testing::TestEnvironment env(argc, argv);
-  grpc_init();
   test_slice_malloc_returns_something_sensible();
   test_slice_new_returns_something_sensible();
   test_slice_new_with_user_data();
@@ -350,11 +287,7 @@ int main(int argc, char** argv) {
     test_slice_split_tail_works(length);
   }
   test_slice_from_copied_string_works();
-  test_slice_interning();
-  test_static_slice_interning();
-  test_static_slice_copy_interning();
   test_moved_string_slice();
   test_string_view_from_slice();
-  grpc_shutdown();
   return 0;
 }
index e3b5165..3307af1 100644 (file)
@@ -14,7 +14,7 @@
 
 load("//bazel:grpc_build_system.bzl", "grpc_cc_binary", "grpc_cc_library", "grpc_cc_test", "grpc_package")
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 grpc_package(name = "test/core/surface")
 
index 7b89ab3..24bf65d 100644 (file)
@@ -85,7 +85,7 @@ int main(int argc, char** argv) {
 
   test_transport_op(chan);
 
-  GPR_ASSERT(GRPC_CHANNEL_SHUTDOWN ==
+  GPR_ASSERT(GRPC_CHANNEL_TRANSIENT_FAILURE ==
              grpc_channel_check_connectivity_state(chan, 0));
 
   cq = grpc_completion_queue_create_for_next(nullptr);
index 36ccd2e..209264f 100644 (file)
@@ -119,6 +119,7 @@ int main(int argc, char **argv) {
   printf("%lx", (unsigned long) grpc_channel_destroy);
   printf("%lx", (unsigned long) grpc_call_cancel);
   printf("%lx", (unsigned long) grpc_call_cancel_with_status);
+  printf("%lx", (unsigned long) grpc_call_failed_before_recv_message);
   printf("%lx", (unsigned long) grpc_call_ref);
   printf("%lx", (unsigned long) grpc_call_unref);
   printf("%lx", (unsigned long) grpc_server_request_call);
@@ -228,6 +229,7 @@ int main(int argc, char **argv) {
   printf("%lx", (unsigned long) grpc_xds_credentials_create);
   printf("%lx", (unsigned long) grpc_xds_server_credentials_create);
   printf("%lx", (unsigned long) grpc_authorization_policy_provider_static_data_create);
+  printf("%lx", (unsigned long) grpc_authorization_policy_provider_file_watcher_create);
   printf("%lx", (unsigned long) grpc_authorization_policy_provider_release);
   printf("%lx", (unsigned long) grpc_raw_byte_buffer_create);
   printf("%lx", (unsigned long) grpc_raw_compressed_byte_buffer_create);
index a0d5a54..97a7337 100644 (file)
@@ -44,10 +44,7 @@ void test_unknown_scheme_target(void) {
 }
 
 void test_security_connector_already_in_arg(void) {
-  grpc_arg arg;
-  arg.type = GRPC_ARG_POINTER;
-  arg.value.pointer.p = nullptr;
-  arg.key = const_cast<char*>(GRPC_ARG_SECURITY_CONNECTOR);
+  grpc_arg arg = grpc_security_connector_to_arg(nullptr);
   grpc_channel_args args;
   args.num_args = 1;
   args.args = &arg;
index 3eeb4f9..ecb3a8e 100644 (file)
@@ -14,7 +14,7 @@
 
 load("//bazel:grpc_build_system.bzl", "grpc_cc_binary", "grpc_cc_library", "grpc_cc_test", "grpc_package")
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 grpc_package(name = "test/core/transport")
 
@@ -78,6 +78,34 @@ grpc_cc_test(
 )
 
 grpc_cc_test(
+    name = "metadata_map_test",
+    srcs = ["metadata_map_test.cc"],
+    external_deps = [
+        "gtest",
+    ],
+    language = "C++",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:grpc_test_util",
+    ],
+)
+
+grpc_cc_test(
+    name = "parsed_metadata_test",
+    srcs = ["parsed_metadata_test.cc"],
+    external_deps = [
+        "gtest",
+    ],
+    language = "C++",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:grpc_test_util",
+    ],
+)
+
+grpc_cc_test(
     name = "metadata_test",
     srcs = ["metadata_test.cc"],
     language = "C++",
index 1f1e226..6d5cc9a 100644 (file)
@@ -126,7 +126,7 @@ TEST_P(BdpEstimatorRandomTest, GetEstimateRandomValues) {
     if (sample > max) max = sample;
     AddSample(&est, sample);
     if (i >= 3) {
-      EXPECT_LE(est.EstimateBdp(), GPR_MAX(65536, 2 * NextPow2(max)))
+      EXPECT_LE(est.EstimateBdp(), std::max(int64_t(65536), 2 * NextPow2(max)))
           << " min:" << min << " max:" << max << " sample:" << sample;
     }
   }
index 8ccb707..e69964d 100644 (file)
@@ -32,9 +32,7 @@ grpc_cc_library(
     ],
     language = "C++",
     deps = [
-        "//src/core/ext/transport/binder/wire_format:binder",
-        "//src/core/ext/transport/binder/wire_format:wire_reader",
-        "//src/core/ext/transport/binder/wire_format:wire_writer",
+        "//:grpc++_binder",
     ],
 )
 
@@ -49,7 +47,7 @@ grpc_cc_test(
     uses_polling = False,
     deps = [
         ":mock_objects",
-        "//src/core/ext/transport/binder/wire_format:wire_writer",
+        "//:grpc++_binder",
         "//test/core/util:grpc_test_util",
     ],
 )
@@ -65,7 +63,7 @@ grpc_cc_test(
     uses_polling = False,
     deps = [
         ":mock_objects",
-        "//src/core/ext/transport/binder/wire_format:wire_reader",
+        "//:grpc++_binder",
         "//test/core/util:grpc_test_util",
     ],
 )
@@ -80,7 +78,7 @@ grpc_cc_test(
     language = "C++",
     uses_polling = False,
     deps = [
-        "//src/core/ext/transport/binder/utils:transport_stream_receiver",
+        "//:grpc++_binder",
         "//test/core/util:grpc_test_util",
     ],
 )
@@ -98,7 +96,24 @@ grpc_cc_test(
     deps = [
         ":mock_objects",
         "//:grpc",
-        "//src/core/ext/transport/binder/transport:binder_transport",
+        "//:grpc++_binder",
+        "//test/core/util:grpc_test_util",
+    ],
+)
+
+grpc_cc_test(
+    name = "endpoint_binder_pool_test",
+    srcs = ["endpoint_binder_pool_test.cc"],
+    external_deps = [
+        "absl/memory",
+        "gtest",
+    ],
+    language = "C++",
+    uses_polling = False,
+    deps = [
+        ":mock_objects",
+        "//:grpc",
+        "//:grpc++_binder",
         "//test/core/util:grpc_test_util",
     ],
 )
index 56084bc..73ef4ca 100644 (file)
@@ -29,6 +29,7 @@
 #include "absl/synchronization/notification.h"
 
 #include <grpc/grpc.h>
+#include <grpcpp/security/binder_security_policy.h>
 
 #include "src/core/ext/transport/binder/transport/binder_stream.h"
 #include "test/core/transport/binder/mock_objects.h"
@@ -46,7 +47,9 @@ class BinderTransportTest : public ::testing::Test {
   BinderTransportTest()
       : arena_(grpc_core::Arena::Create(/* initial_size = */ 1)),
         transport_(grpc_create_binder_transport_client(
-            absl::make_unique<NiceMock<MockBinder>>())) {
+            absl::make_unique<NiceMock<MockBinder>>(),
+            std::make_shared<
+                grpc::experimental::binder::UntrustedSecurityPolicy>())) {
     auto* gbt = reinterpret_cast<grpc_binder_transport*>(transport_);
     gbt->wire_writer = absl::make_unique<MockWireWriter>();
     GRPC_STREAM_REF_INIT(&ref_, 1, nullptr, nullptr, "phony ref");
@@ -145,16 +148,16 @@ MATCHER_P(GrpcErrorMessageContains, msg, "") {
 
 // Verify that the lower-level metadata has the same content as the gRPC
 // metadata.
-void VerifyMetadataEqual(const Metadata& md, grpc_metadata_batch grpc_md) {
-  grpc_linked_mdelem* elm = grpc_md.list.head;
-  for (size_t i = 0; i < md.size(); ++i) {
-    ASSERT_NE(elm, nullptr);
-    EXPECT_EQ(grpc_core::StringViewFromSlice(GRPC_MDKEY(elm->md)), md[i].first);
-    EXPECT_EQ(grpc_core::StringViewFromSlice(GRPC_MDVALUE(elm->md)),
+void VerifyMetadataEqual(const Metadata& md,
+                         const grpc_metadata_batch& grpc_md) {
+  size_t i = 0;
+  grpc_md.ForEach([&](grpc_mdelem mdelm) {
+    EXPECT_EQ(grpc_core::StringViewFromSlice(GRPC_MDKEY(mdelm)), md[i].first);
+    EXPECT_EQ(grpc_core::StringViewFromSlice(GRPC_MDVALUE(mdelm)),
               md[i].second);
-    elm = elm->next;
-  }
-  EXPECT_EQ(elm, nullptr);
+    i++;
+  });
+  EXPECT_EQ(md.size(), i);
 }
 
 // RAII helper classes for constructing gRPC metadata and receiving callbacks.
@@ -163,7 +166,6 @@ struct MakeSendInitialMetadata {
                           const std::string& method_ref,
                           grpc_transport_stream_op_batch* op)
       : storage(initial_metadata.size()) {
-    grpc_metadata_batch_init(&grpc_initial_metadata);
     size_t i = 0;
     for (const auto& md : initial_metadata) {
       const std::string& key = md.first;
@@ -187,13 +189,12 @@ struct MakeSendInitialMetadata {
     op->payload->send_initial_metadata.send_initial_metadata =
         &grpc_initial_metadata;
   }
-  ~MakeSendInitialMetadata() {
-    grpc_metadata_batch_destroy(&grpc_initial_metadata);
-  }
+  ~MakeSendInitialMetadata() {}
 
   std::vector<grpc_linked_mdelem> storage;
   grpc_linked_mdelem method_ref_storage;
-  grpc_metadata_batch grpc_initial_metadata{};
+  grpc_core::ScopedArenaPtr arena = grpc_core::MakeScopedArena(1024);
+  grpc_metadata_batch grpc_initial_metadata{arena.get()};
 };
 
 struct MakeSendMessage {
@@ -218,21 +219,20 @@ struct MakeSendTrailingMetadata {
   explicit MakeSendTrailingMetadata(const Metadata& trailing_metadata,
                                     grpc_transport_stream_op_batch* op) {
     EXPECT_TRUE(trailing_metadata.empty());
-    grpc_metadata_batch_init(&grpc_trailing_metadata);
 
     op->send_trailing_metadata = true;
     op->payload->send_trailing_metadata.send_trailing_metadata =
         &grpc_trailing_metadata;
   }
 
-  grpc_metadata_batch grpc_trailing_metadata{};
+  grpc_core::ScopedArenaPtr arena = grpc_core::MakeScopedArena(1024);
+  grpc_metadata_batch grpc_trailing_metadata{arena.get()};
 };
 
 struct MakeRecvInitialMetadata {
   explicit MakeRecvInitialMetadata(grpc_transport_stream_op_batch* op,
                                    Expectation* call_before = nullptr)
       : ready(&notification) {
-    grpc_metadata_batch_init(&grpc_initial_metadata);
     op->recv_initial_metadata = true;
     op->payload->recv_initial_metadata.recv_initial_metadata =
         &grpc_initial_metadata;
@@ -245,12 +245,11 @@ struct MakeRecvInitialMetadata {
     }
   }
 
-  ~MakeRecvInitialMetadata() {
-    grpc_metadata_batch_destroy(&grpc_initial_metadata);
-  }
+  ~MakeRecvInitialMetadata() {}
 
   MockGrpcClosure ready;
-  grpc_metadata_batch grpc_initial_metadata;
+  grpc_core::ScopedArenaPtr arena = grpc_core::MakeScopedArena(1024);
+  grpc_metadata_batch grpc_initial_metadata{arena.get()};
   absl::Notification notification;
 };
 
@@ -277,7 +276,6 @@ struct MakeRecvTrailingMetadata {
   explicit MakeRecvTrailingMetadata(grpc_transport_stream_op_batch* op,
                                     Expectation* call_before = nullptr)
       : ready(&notification) {
-    grpc_metadata_batch_init(&grpc_trailing_metadata);
     op->recv_trailing_metadata = true;
     op->payload->recv_trailing_metadata.recv_trailing_metadata =
         &grpc_trailing_metadata;
@@ -290,12 +288,11 @@ struct MakeRecvTrailingMetadata {
     }
   }
 
-  ~MakeRecvTrailingMetadata() {
-    grpc_metadata_batch_destroy(&grpc_trailing_metadata);
-  }
+  ~MakeRecvTrailingMetadata() {}
 
   MockGrpcClosure ready;
-  grpc_metadata_batch grpc_trailing_metadata;
+  grpc_core::ScopedArenaPtr arena = grpc_core::MakeScopedArena(1024);
+  grpc_metadata_batch grpc_trailing_metadata{arena.get()};
   absl::Notification notification;
 };
 
@@ -525,7 +522,7 @@ TEST_F(BinderTransportTest, PerformRecvMessage) {
 
   EXPECT_TRUE(recv_message.grpc_message->Next(SIZE_MAX, nullptr));
   grpc_slice slice;
-  recv_message.grpc_message->Pull(&slice);
+  EXPECT_EQ(recv_message.grpc_message->Pull(&slice), GRPC_ERROR_NONE);
   EXPECT_EQ(kMessage,
             std::string(reinterpret_cast<char*>(GRPC_SLICE_START_PTR(slice)),
                         GRPC_SLICE_LENGTH(slice)));
@@ -589,7 +586,7 @@ TEST_F(BinderTransportTest, PerformRecvAll) {
                       recv_trailing_metadata.grpc_trailing_metadata);
   EXPECT_TRUE(recv_message.grpc_message->Next(SIZE_MAX, nullptr));
   grpc_slice slice;
-  recv_message.grpc_message->Pull(&slice);
+  EXPECT_EQ(recv_message.grpc_message->Pull(&slice), GRPC_ERROR_NONE);
   EXPECT_EQ(kMessage,
             std::string(reinterpret_cast<char*>(GRPC_SLICE_START_PTR(slice)),
                         GRPC_SLICE_LENGTH(slice)));
@@ -666,7 +663,7 @@ TEST_F(BinderTransportTest, PerformAllOps) {
 
   EXPECT_TRUE(recv_message.grpc_message->Next(SIZE_MAX, nullptr));
   grpc_slice slice;
-  recv_message.grpc_message->Pull(&slice);
+  EXPECT_EQ(recv_message.grpc_message->Pull(&slice), GRPC_ERROR_NONE);
   EXPECT_EQ(kRecvMessage,
             std::string(reinterpret_cast<char*>(GRPC_SLICE_START_PTR(slice)),
                         GRPC_SLICE_LENGTH(slice)));
index 15b242e..025b6ef 100644 (file)
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_package", "grpc_proto_library")
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_package")
 
 licenses(["notice"])
 
@@ -36,8 +36,7 @@ grpc_cc_library(
     ],
     deps = [
         "//:gpr_base",
-        "//src/core/ext/transport/binder/wire_format:binder",
-        "//src/core/ext/transport/binder/wire_format:wire_reader",
+        "//:grpc++_binder",
     ],
 )
 
@@ -66,29 +65,8 @@ grpc_cc_library(
     deps = [
         ":fake_binder",
         "//:grpc++_base",
-        "//:grpc_base_c",
-        "//src/core/ext/transport/binder/transport:binder_transport",
-        "//src/core/ext/transport/binder/wire_format:wire_reader",
-    ],
-)
-
-grpc_proto_library(
-    name = "echo_grpc_proto",
-    srcs = ["echo.proto"],
-)
-
-grpc_cc_library(
-    name = "echo_service",
-    testonly = 1,
-    srcs = ["echo_service.cc"],
-    hdrs = ["echo_service.h"],
-    external_deps = [
-        "absl/strings",
-        "absl/strings:str_format",
-        "absl/time",
-    ],
-    deps = [
-        ":echo_grpc_proto",
+        "//:grpc++_binder",
+        "//:grpc_base",
     ],
 )
 
@@ -102,12 +80,11 @@ grpc_cc_test(
     ],
     language = "C++",
     deps = [
-        ":echo_service",
         ":end2end_binder_channel",
         ":fake_binder",
-        "//src/core/ext/transport/binder/transport:binder_transport",
-        "//src/core/ext/transport/binder/wire_format:wire_reader",
+        "//:grpc++_binder",
         "//test/core/util:grpc_test_util",
+        "//test/cpp/end2end:test_service_impl",
     ],
 )
 
@@ -119,9 +96,7 @@ grpc_cc_test(
     ],
     deps = [
         "//:grpc++",
-        "//src/core/ext/transport/binder/client:grpc_transport_binder_client_impl",
-        "//src/core/ext/transport/binder/server:grpc_transport_binder_server",
-        "//test/core/transport/binder/end2end:echo_service",
+        "//:grpc++_binder",
         "//test/core/transport/binder/end2end:fake_binder",
         "//test/core/util:grpc_test_util",
         "//test/cpp/end2end:test_service_impl",
index 46f5d1b..e1d930e 100644 (file)
 
 #include <grpcpp/grpcpp.h>
 #include <grpcpp/impl/grpc_library.h>
+#include <grpcpp/security/binder_credentials.h>
+#include <grpcpp/security/binder_security_policy.h>
 
 #include "src/core/ext/transport/binder/client/channel_create_impl.h"
 #include "src/core/ext/transport/binder/server/binder_server.h"
-#include "src/core/ext/transport/binder/server/binder_server_credentials.h"
-#include "test/core/transport/binder/end2end/echo_service.h"
 #include "test/core/transport/binder/end2end/fake_binder.h"
 #include "test/core/util/test_config.h"
 #include "test/cpp/end2end/test_service_impl.h"
@@ -47,7 +47,9 @@ class BinderServerCredentialsImpl final : public ServerCredentials {
           return absl::make_unique<
               grpc_binder::end2end_testing::FakeTransactionReceiver>(
               nullptr, std::move(transact_cb));
-        });
+        },
+        std::make_shared<
+            grpc::experimental::binder::UntrustedSecurityPolicy>());
   }
 
   void SetAuthMetadataProcessor(
@@ -72,8 +74,10 @@ std::shared_ptr<grpc::Channel> CreateBinderChannel(
 
   return grpc::CreateChannelInternal(
       "",
-      grpc::internal::CreateChannelFromBinderImpl(std::move(endpoint_binder),
-                                                  nullptr),
+      grpc::internal::CreateDirectBinderChannelImplForTesting(
+          std::move(endpoint_binder), nullptr,
+          std::make_shared<
+              grpc::experimental::binder::UntrustedSecurityPolicy>()),
       std::vector<std::unique_ptr<
           grpc::experimental::ClientInterceptorFactoryInterface>>());
 }
@@ -96,22 +100,26 @@ class BinderServerTest : public ::testing::Test {
   static void TearDownTestSuite() { grpc_shutdown(); }
 };
 
-#ifndef GPR_ANDROID
-TEST(BinderServerCredentialsTest, FailedInNonAndroidEnvironments) {
+#ifndef GPR_SUPPORT_BINDER_TRANSPORT
+TEST(BinderServerCredentialsTest,
+     FailedInEnvironmentsNotSupportingBinderTransport) {
   grpc::ServerBuilder server_builder;
   grpc::testing::TestServiceImpl service;
   server_builder.RegisterService(&service);
   server_builder.AddListeningPort(
-      "binder://fail", grpc::experimental::BinderServerCredentials());
+      "binder:fail",
+      grpc::experimental::BinderServerCredentials(
+          std::make_shared<
+              grpc::experimental::binder::UntrustedSecurityPolicy>()));
   EXPECT_EQ(server_builder.BuildAndStart(), nullptr);
 }
-#endif  // !GPR_ANDROID
+#endif  // !GPR_SUPPORT_BINDER_TRANSPORT
 
 TEST_F(BinderServerTest, BuildAndStart) {
   grpc::ServerBuilder server_builder;
-  grpc_binder::end2end_testing::EchoServer service;
+  grpc::testing::TestServiceImpl service;
   server_builder.RegisterService(&service);
-  server_builder.AddListeningPort("binder://example.service",
+  server_builder.AddListeningPort("binder:example.service",
                                   grpc::testing::BinderServerCredentials());
   std::unique_ptr<grpc::Server> server = server_builder.BuildAndStart();
   EXPECT_NE(grpc::experimental::binder::GetEndpointBinder("example.service"),
@@ -123,7 +131,7 @@ TEST_F(BinderServerTest, BuildAndStart) {
 
 TEST_F(BinderServerTest, BuildAndStartFailed) {
   grpc::ServerBuilder server_builder;
-  grpc_binder::end2end_testing::EchoServer service;
+  grpc::testing::TestServiceImpl service;
   server_builder.RegisterService(&service);
   // Error: binder address should begin with binder:
   server_builder.AddListeningPort("localhost:12345",
@@ -134,9 +142,9 @@ TEST_F(BinderServerTest, BuildAndStartFailed) {
 
 TEST_F(BinderServerTest, CreateChannelWithEndpointBinder) {
   grpc::ServerBuilder server_builder;
-  grpc_binder::end2end_testing::EchoServer service;
+  grpc::testing::TestServiceImpl service;
   server_builder.RegisterService(&service);
-  server_builder.AddListeningPort("binder://example.service",
+  server_builder.AddListeningPort("binder:example.service",
                                   grpc::testing::BinderServerCredentials());
   std::unique_ptr<grpc::Server> server = server_builder.BuildAndStart();
   void* raw_endpoint_binder =
@@ -147,25 +155,24 @@ TEST_F(BinderServerTest, CreateChannelWithEndpointBinder) {
               raw_endpoint_binder));
   std::shared_ptr<grpc::Channel> channel =
       grpc::testing::CreateBinderChannel(std::move(endpoint_binder));
-  std::unique_ptr<grpc_binder::end2end_testing::EchoService::Stub> stub =
-      grpc_binder::end2end_testing::EchoService::NewStub(channel);
-  grpc_binder::end2end_testing::EchoRequest request;
-  grpc_binder::end2end_testing::EchoResponse response;
+  std::unique_ptr<grpc::testing::EchoTestService::Stub> stub =
+      grpc::testing::EchoTestService::NewStub(channel);
+  grpc::testing::EchoRequest request;
+  grpc::testing::EchoResponse response;
   grpc::ClientContext context;
-  request.set_text("BinderServerBuilder");
-  grpc::Status status = stub->EchoUnaryCall(&context, request, &response);
+  request.set_message("BinderServerBuilder");
+  grpc::Status status = stub->Echo(&context, request, &response);
   EXPECT_TRUE(status.ok());
-  EXPECT_EQ(response.text(), "BinderServerBuilder");
+  EXPECT_EQ(response.message(), "BinderServerBuilder");
   server->Shutdown();
 }
 
 TEST_F(BinderServerTest, CreateChannelWithEndpointBinderMultipleConnections) {
   grpc::ServerBuilder server_builder;
-  grpc_binder::end2end_testing::EchoServer service;
+  grpc::testing::TestServiceImpl service;
   server_builder.RegisterService(&service);
-  server_builder.AddListeningPort(
-      "binder://example.service.multiple.connections",
-      grpc::testing::BinderServerCredentials());
+  server_builder.AddListeningPort("binder:example.service.multiple.connections",
+                                  grpc::testing::BinderServerCredentials());
   std::unique_ptr<grpc::Server> server = server_builder.BuildAndStart();
   void* raw_endpoint_binder = grpc::experimental::binder::GetEndpointBinder(
       "example.service.multiple.connections");
@@ -178,15 +185,16 @@ TEST_F(BinderServerTest, CreateChannelWithEndpointBinderMultipleConnections) {
                 raw_endpoint_binder));
     std::shared_ptr<grpc::Channel> channel =
         grpc::testing::CreateBinderChannel(std::move(endpoint_binder));
-    std::unique_ptr<grpc_binder::end2end_testing::EchoService::Stub> stub =
-        grpc_binder::end2end_testing::EchoService::NewStub(channel);
-    grpc_binder::end2end_testing::EchoRequest request;
-    grpc_binder::end2end_testing::EchoResponse response;
+    std::unique_ptr<grpc::testing::EchoTestService::Stub> stub =
+        grpc::testing::EchoTestService::NewStub(channel);
+    grpc::testing::EchoRequest request;
+    grpc::testing::EchoResponse response;
     grpc::ClientContext context;
-    request.set_text(absl::StrFormat("BinderServerBuilder-%d", id));
-    grpc::Status status = stub->EchoUnaryCall(&context, request, &response);
+    request.set_message(absl::StrFormat("BinderServerBuilder-%d", id));
+    grpc::Status status = stub->Echo(&context, request, &response);
     EXPECT_TRUE(status.ok());
-    EXPECT_EQ(response.text(), absl::StrFormat("BinderServerBuilder-%d", id));
+    EXPECT_EQ(response.message(),
+              absl::StrFormat("BinderServerBuilder-%d", id));
   };
 
   std::vector<std::thread> threads(kNumThreads);
diff --git a/test/core/transport/binder/end2end/echo.proto b/test/core/transport/binder/end2end/echo.proto
deleted file mode 100644 (file)
index 6669e1f..0000000
+++ /dev/null
@@ -1,38 +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.
-
-// A simple RPC service that echos what the client passes in. The request and
-// the response simply contains the text represented in a string.
-//
-// This service is for end-to-end testing with fake binder tunnels.
-syntax = "proto3";
-
-// TODO(waynetu): This can be replaced by EchoTestService in
-// src/proto/grpc/testing/echo.proto
-package grpc_binder.end2end_testing;
-
-message EchoRequest {
-  string text = 1;
-}
-
-message EchoResponse {
-  string text = 1;
-}
-
-service EchoService {
-  rpc EchoUnaryCall(EchoRequest) returns (EchoResponse);
-  rpc EchoServerStreamingCall(EchoRequest) returns (stream EchoResponse);
-  rpc EchoClientStreamingCall(stream EchoRequest) returns (EchoResponse);
-  rpc EchoBiDirStreamingCall(stream EchoRequest) returns (stream EchoResponse);
-}
diff --git a/test/core/transport/binder/end2end/echo_service.cc b/test/core/transport/binder/end2end/echo_service.cc
deleted file mode 100644 (file)
index def23f5..0000000
+++ /dev/null
@@ -1,83 +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 "test/core/transport/binder/end2end/echo_service.h"
-
-#include <string>
-
-#include "absl/strings/str_format.h"
-#include "absl/time/time.h"
-
-namespace grpc_binder {
-namespace end2end_testing {
-
-const absl::string_view EchoServer::kCancelledText = "cancel";
-const absl::string_view EchoServer::kTimeoutText = "timeout";
-const size_t EchoServer::kServerStreamingCounts = 100;
-
-grpc::Status EchoServer::EchoUnaryCall(grpc::ServerContext* /*context*/,
-                                       const EchoRequest* request,
-                                       EchoResponse* response) {
-  const std::string& data = request->text();
-  if (data == kCancelledText) {
-    return grpc::Status::CANCELLED;
-  }
-  if (data == kTimeoutText) {
-    absl::SleepFor(absl::Seconds(5));
-  }
-  response->set_text(data);
-  return grpc::Status::OK;
-}
-
-grpc::Status EchoServer::EchoServerStreamingCall(
-    grpc::ServerContext* /*context*/, const EchoRequest* request,
-    grpc::ServerWriter<EchoResponse>* writer) {
-  const std::string& data = request->text();
-  if (data == kTimeoutText) {
-    absl::SleepFor(absl::Seconds(5));
-  }
-  for (size_t i = 0; i < kServerStreamingCounts; ++i) {
-    EchoResponse response;
-    response.set_text(absl::StrFormat("%s(%d)", data, i));
-    writer->Write(response);
-  }
-  return grpc::Status::OK;
-}
-
-grpc::Status EchoServer::EchoClientStreamingCall(
-    grpc::ServerContext* /*context*/, grpc::ServerReader<EchoRequest>* reader,
-    EchoResponse* response) {
-  EchoRequest request;
-  std::string result = "";
-  while (reader->Read(&request)) {
-    result += request.text();
-  }
-  response->set_text(result);
-  return grpc::Status::OK;
-}
-
-grpc::Status EchoServer::EchoBiDirStreamingCall(
-    grpc::ServerContext* /*context*/,
-    grpc::ServerReaderWriter<EchoResponse, EchoRequest>* stream) {
-  EchoRequest request;
-  while (stream->Read(&request)) {
-    EchoResponse response;
-    response.set_text(request.text());
-    stream->Write(response);
-  }
-  return grpc::Status::OK;
-}
-
-}  // namespace end2end_testing
-}  // namespace grpc_binder
diff --git a/test/core/transport/binder/end2end/echo_service.h b/test/core/transport/binder/end2end/echo_service.h
deleted file mode 100644 (file)
index 1dbfe39..0000000
+++ /dev/null
@@ -1,52 +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.
-
-#ifndef TEST_CORE_TRANSPORT_BINDER_END2END_ECHO_SERVICE_H
-#define TEST_CORE_TRANSPORT_BINDER_END2END_ECHO_SERVICE_H
-
-#include "absl/strings/string_view.h"
-
-#include "test/core/transport/binder/end2end/echo.grpc.pb.h"
-
-namespace grpc_binder {
-namespace end2end_testing {
-
-// TODO(waynetu): Replace this with TestServiceImpl declared in
-// test/cpp/end2end/test_service_impl.h
-class EchoServer final : public EchoService::Service {
- public:
-  static const absl::string_view kCancelledText;
-  static const absl::string_view kTimeoutText;
-
-  grpc::Status EchoUnaryCall(grpc::ServerContext* context,
-                             const EchoRequest* request,
-                             EchoResponse* response) override;
-
-  static const size_t kServerStreamingCounts;
-
-  grpc::Status EchoServerStreamingCall(
-      grpc::ServerContext* context, const EchoRequest* request,
-      grpc::ServerWriter<EchoResponse>* writer) override;
-  grpc::Status EchoClientStreamingCall(grpc::ServerContext* context,
-                                       grpc::ServerReader<EchoRequest>* reader,
-                                       EchoResponse* response) override;
-  grpc::Status EchoBiDirStreamingCall(
-      grpc::ServerContext* context,
-      grpc::ServerReaderWriter<EchoResponse, EchoRequest>* stream) override;
-};
-
-}  // namespace end2end_testing
-}  // namespace grpc_binder
-
-#endif  // TEST_CORE_TRANSPORT_BINDER_END2END_ECHO_SERVICE_H_
index b3bb4c2..da9a7d0 100644 (file)
 
 #include "src/core/ext/transport/binder/transport/binder_transport.h"
 #include "src/core/ext/transport/binder/wire_format/wire_reader_impl.h"
-#include "test/core/transport/binder/end2end/echo_service.h"
 #include "test/core/transport/binder/end2end/fake_binder.h"
 #include "test/core/transport/binder/end2end/testing_channel_create.h"
 #include "test/core/util/test_config.h"
+#include "test/cpp/end2end/test_service_impl.h"
 
 namespace grpc_binder {
 
@@ -41,12 +41,24 @@ class End2EndBinderTransportTest
   End2EndBinderTransportTest() {
     end2end_testing::g_transaction_processor =
         new end2end_testing::TransactionProcessor(GetParam());
+    service_ = absl::make_unique<grpc::testing::TestServiceImpl>();
+    grpc::ServerBuilder builder;
+    builder.RegisterService(service_.get());
+    server_ = builder.BuildAndStart();
   }
 
   ~End2EndBinderTransportTest() override {
+    server_->Shutdown();
+    service_.reset();
     delete end2end_testing::g_transaction_processor;
   }
 
+  std::unique_ptr<grpc::testing::EchoTestService::Stub> NewStub() {
+    grpc::ChannelArguments args;
+    std::shared_ptr<grpc::Channel> channel = BinderChannel(server_.get(), args);
+    return grpc::testing::EchoTestService::NewStub(channel);
+  }
+
   static void SetUpTestSuite() { grpc_init(); }
   static void TearDownTestSuite() { grpc_shutdown(); }
 
@@ -54,11 +66,11 @@ class End2EndBinderTransportTest
       grpc::Server* server, const grpc::ChannelArguments& args) {
     return end2end_testing::BinderChannelForTesting(server, args);
   }
-};
 
-using end2end_testing::EchoRequest;
-using end2end_testing::EchoResponse;
-using end2end_testing::EchoService;
+ protected:
+  std::unique_ptr<grpc::testing::TestServiceImpl> service_;
+  std::unique_ptr<grpc::Server> server_;
+};
 
 }  // namespace
 
@@ -74,79 +86,54 @@ TEST_P(End2EndBinderTransportTest, SetupTransport) {
   grpc_transport_destroy(server_transport);
 }
 
-TEST_P(End2EndBinderTransportTest, UnaryCallThroughFakeBinderChannel) {
-  grpc::ChannelArguments args;
-  grpc::ServerBuilder builder;
-  end2end_testing::EchoServer service;
-  builder.RegisterService(&service);
-  std::unique_ptr<grpc::Server> server = builder.BuildAndStart();
-  std::shared_ptr<grpc::Channel> channel = BinderChannel(server.get(), args);
-  std::unique_ptr<EchoService::Stub> stub = EchoService::NewStub(channel);
+TEST_P(End2EndBinderTransportTest, UnaryCall) {
+  std::unique_ptr<grpc::testing::EchoTestService::Stub> stub = NewStub();
   grpc::ClientContext context;
-  EchoRequest request;
-  EchoResponse response;
-  request.set_text("it works!");
-  grpc::Status status = stub->EchoUnaryCall(&context, request, &response);
+  grpc::testing::EchoRequest request;
+  grpc::testing::EchoResponse response;
+  request.set_message("UnaryCall");
+  grpc::Status status = stub->Echo(&context, request, &response);
   EXPECT_TRUE(status.ok());
-  EXPECT_EQ(response.text(), "it works!");
-
-  server->Shutdown();
+  EXPECT_EQ(response.message(), "UnaryCall");
 }
 
-TEST_P(End2EndBinderTransportTest,
-       UnaryCallThroughFakeBinderChannelNonOkStatus) {
-  grpc::ChannelArguments args;
-  grpc::ServerBuilder builder;
-  end2end_testing::EchoServer service;
-  builder.RegisterService(&service);
-  std::unique_ptr<grpc::Server> server = builder.BuildAndStart();
-  std::shared_ptr<grpc::Channel> channel = BinderChannel(server.get(), args);
-  std::unique_ptr<EchoService::Stub> stub = EchoService::NewStub(channel);
+TEST_P(End2EndBinderTransportTest, UnaryCallWithNonOkStatus) {
+  std::unique_ptr<grpc::testing::EchoTestService::Stub> stub = NewStub();
   grpc::ClientContext context;
-  EchoRequest request;
-  EchoResponse response;
-  request.set_text(std::string(end2end_testing::EchoServer::kCancelledText));
+  grpc::testing::EchoRequest request;
+  grpc::testing::EchoResponse response;
+  request.set_message("UnaryCallWithNonOkStatus");
+  request.mutable_param()->mutable_expected_error()->set_code(
+      grpc::StatusCode::INTERNAL);
+  request.mutable_param()->mutable_expected_error()->set_error_message(
+      "expected to fail");
   // Server will not response the client with message data, however, since all
   // callbacks after the trailing metadata are cancelled, we shall not be
   // blocked here.
-  grpc::Status status = stub->EchoUnaryCall(&context, request, &response);
+  grpc::Status status = stub->Echo(&context, request, &response);
   EXPECT_FALSE(status.ok());
-
-  server->Shutdown();
+  EXPECT_EQ(status.error_code(), grpc::StatusCode::INTERNAL);
+  EXPECT_THAT(status.error_message(), ::testing::HasSubstr("expected to fail"));
 }
 
-TEST_P(End2EndBinderTransportTest,
-       UnaryCallThroughFakeBinderChannelServerTimeout) {
-  grpc::ChannelArguments args;
-  grpc::ServerBuilder builder;
-  end2end_testing::EchoServer service;
-  builder.RegisterService(&service);
-  std::unique_ptr<grpc::Server> server = builder.BuildAndStart();
-  std::shared_ptr<grpc::Channel> channel = BinderChannel(server.get(), args);
-  std::unique_ptr<EchoService::Stub> stub = EchoService::NewStub(channel);
+TEST_P(End2EndBinderTransportTest, UnaryCallServerTimeout) {
+  std::unique_ptr<grpc::testing::EchoTestService::Stub> stub = NewStub();
   grpc::ClientContext context;
   context.set_deadline(absl::ToChronoTime(absl::Now() + absl::Seconds(1)));
-  EchoRequest request;
-  EchoResponse response;
-  request.set_text(std::string(end2end_testing::EchoServer::kTimeoutText));
-  grpc::Status status = stub->EchoUnaryCall(&context, request, &response);
+  grpc::testing::EchoRequest request;
+  grpc::testing::EchoResponse response;
+  request.set_message("UnaryCallServerTimeout");
+  // Server will sleep for 2 seconds before responding us.
+  request.mutable_param()->set_server_sleep_us(2000000);
+  // Disable cancellation check because the request will time out.
+  request.mutable_param()->set_skip_cancelled_check(true);
+  grpc::Status status = stub->Echo(&context, request, &response);
   EXPECT_FALSE(status.ok());
-  EXPECT_EQ(status.error_message(), "Deadline Exceeded");
-
-  server->Shutdown();
+  EXPECT_EQ(status.error_code(), grpc::StatusCode::DEADLINE_EXCEEDED);
 }
 
-// Temporarily disabled due to a potential deadlock in our design.
-// TODO(waynetu): Enable this test once the issue is resolved.
-TEST_P(End2EndBinderTransportTest,
-       UnaryCallThroughFakeBinderChannelClientTimeout) {
-  grpc::ChannelArguments args;
-  grpc::ServerBuilder builder;
-  end2end_testing::EchoServer service;
-  builder.RegisterService(&service);
-  std::unique_ptr<grpc::Server> server = builder.BuildAndStart();
-  std::shared_ptr<grpc::Channel> channel = BinderChannel(server.get(), args);
-  std::unique_ptr<EchoService::Stub> stub = EchoService::NewStub(channel);
+TEST_P(End2EndBinderTransportTest, UnaryCallClientTimeout) {
+  std::unique_ptr<grpc::testing::EchoTestService::Stub> stub = NewStub();
 
   // Set transaction delay to a large number. This happens after the channel
   // creation so that we don't need to wait that long for client and server to
@@ -155,112 +142,314 @@ TEST_P(End2EndBinderTransportTest,
 
   grpc::ClientContext context;
   context.set_deadline(absl::ToChronoTime(absl::Now() + absl::Seconds(1)));
-  EchoRequest request;
-  EchoResponse response;
-  request.set_text("normal-text");
-  grpc::Status status = stub->EchoUnaryCall(&context, request, &response);
+  grpc::testing::EchoRequest request;
+  grpc::testing::EchoResponse response;
+  request.set_message("UnaryCallClientTimeout");
+  grpc::Status status = stub->Echo(&context, request, &response);
   EXPECT_FALSE(status.ok());
-  EXPECT_EQ(status.error_message(), "Deadline Exceeded");
+  EXPECT_EQ(status.error_code(), grpc::StatusCode::DEADLINE_EXCEEDED);
+}
+
+TEST_P(End2EndBinderTransportTest, UnaryCallUnimplemented) {
+  std::unique_ptr<grpc::testing::EchoTestService::Stub> stub = NewStub();
 
-  server->Shutdown();
+  grpc::ClientContext context;
+  grpc::testing::EchoRequest request;
+  grpc::testing::EchoResponse response;
+  request.set_message("UnaryCallUnimplemented");
+  grpc::Status status = stub->Unimplemented(&context, request, &response);
+  EXPECT_FALSE(status.ok());
+  EXPECT_EQ(status.error_code(), grpc::StatusCode::UNIMPLEMENTED);
 }
 
-TEST_P(End2EndBinderTransportTest,
-       ServerStreamingCallThroughFakeBinderChannel) {
-  grpc::ChannelArguments args;
-  grpc::ServerBuilder builder;
-  end2end_testing::EchoServer service;
-  builder.RegisterService(&service);
-  std::unique_ptr<grpc::Server> server = builder.BuildAndStart();
-  std::shared_ptr<grpc::Channel> channel = BinderChannel(server.get(), args);
-  std::unique_ptr<EchoService::Stub> stub = EchoService::NewStub(channel);
+TEST_P(End2EndBinderTransportTest, UnaryCallClientCancel) {
+  std::unique_ptr<grpc::testing::EchoTestService::Stub> stub = NewStub();
+
+  grpc::ClientContext context;
+  grpc::testing::EchoRequest request;
+  grpc::testing::EchoResponse response;
+  request.set_message("UnaryCallClientCancel");
+  context.TryCancel();
+  grpc::Status status = stub->Unimplemented(&context, request, &response);
+  EXPECT_FALSE(status.ok());
+  EXPECT_EQ(status.error_code(), grpc::StatusCode::CANCELLED);
+}
+
+TEST_P(End2EndBinderTransportTest, UnaryCallEchoMetadataInitially) {
+  std::unique_ptr<grpc::testing::EchoTestService::Stub> stub = NewStub();
+
+  grpc::ClientContext context;
+  grpc::testing::EchoRequest request;
+  grpc::testing::EchoResponse response;
+  request.set_message("UnaryCallEchoMetadataInitially");
+  request.mutable_param()->set_echo_metadata_initially(true);
+  context.AddMetadata("key1", "value1");
+  context.AddMetadata("key2", "value2");
+  grpc::Status status = stub->Echo(&context, request, &response);
+  const auto& initial_metadata = context.GetServerInitialMetadata();
+  EXPECT_EQ(initial_metadata.find("key1")->second, "value1");
+  EXPECT_EQ(initial_metadata.find("key2")->second, "value2");
+}
+
+TEST_P(End2EndBinderTransportTest, UnaryCallEchoMetadata) {
+  std::unique_ptr<grpc::testing::EchoTestService::Stub> stub = NewStub();
+
+  grpc::ClientContext context;
+  grpc::testing::EchoRequest request;
+  grpc::testing::EchoResponse response;
+  request.set_message("UnaryCallEchoMetadata");
+  request.mutable_param()->set_echo_metadata(true);
+  context.AddMetadata("key1", "value1");
+  context.AddMetadata("key2", "value2");
+  grpc::Status status = stub->Echo(&context, request, &response);
+  const auto& initial_metadata = context.GetServerTrailingMetadata();
+  EXPECT_EQ(initial_metadata.find("key1")->second, "value1");
+  EXPECT_EQ(initial_metadata.find("key2")->second, "value2");
+}
+
+TEST_P(End2EndBinderTransportTest, UnaryCallResponseMessageLength) {
+  std::unique_ptr<grpc::testing::EchoTestService::Stub> stub = NewStub();
+
+  for (size_t response_length : {1, 2, 5, 10, 100, 1000000}) {
+    grpc::ClientContext context;
+    grpc::testing::EchoRequest request;
+    grpc::testing::EchoResponse response;
+    request.set_message("UnaryCallResponseMessageLength");
+    request.mutable_param()->set_response_message_length(response_length);
+    grpc::Status status = stub->Echo(&context, request, &response);
+    EXPECT_EQ(response.message().length(), response_length);
+  }
+}
+
+TEST_P(End2EndBinderTransportTest, UnaryCallTryCancel) {
+  std::unique_ptr<grpc::testing::EchoTestService::Stub> stub = NewStub();
+
+  grpc::ClientContext context;
+  context.AddMetadata(grpc::testing::kServerTryCancelRequest,
+                      std::to_string(grpc::testing::CANCEL_BEFORE_PROCESSING));
+  grpc::testing::EchoRequest request;
+  grpc::testing::EchoResponse response;
+  request.set_message("UnaryCallTryCancel");
+  grpc::Status status = stub->Echo(&context, request, &response);
+  EXPECT_FALSE(status.ok());
+  EXPECT_EQ(status.error_code(), grpc::StatusCode::CANCELLED);
+}
+
+TEST_P(End2EndBinderTransportTest, ServerStreamingCall) {
+  std::unique_ptr<grpc::testing::EchoTestService::Stub> stub = NewStub();
+  constexpr size_t kServerResponseStreamsToSend = 100;
   grpc::ClientContext context;
-  EchoRequest request;
-  request.set_text("it works!");
-  std::unique_ptr<grpc::ClientReader<EchoResponse>> reader =
-      stub->EchoServerStreamingCall(&context, request);
-  EchoResponse response;
+  context.AddMetadata(grpc::testing::kServerResponseStreamsToSend,
+                      std::to_string(kServerResponseStreamsToSend));
+  grpc::testing::EchoRequest request;
+  request.set_message("ServerStreamingCall");
+  std::unique_ptr<grpc::ClientReader<grpc::testing::EchoResponse>> reader =
+      stub->ResponseStream(&context, request);
+  grpc::testing::EchoResponse response;
   size_t cnt = 0;
   while (reader->Read(&response)) {
-    EXPECT_EQ(response.text(), absl::StrFormat("it works!(%d)", cnt));
+    EXPECT_EQ(response.message(), "ServerStreamingCall" + std::to_string(cnt));
     cnt++;
   }
-  EXPECT_EQ(cnt, end2end_testing::EchoServer::kServerStreamingCounts);
+  EXPECT_EQ(cnt, kServerResponseStreamsToSend);
   grpc::Status status = reader->Finish();
   EXPECT_TRUE(status.ok());
+}
 
-  server->Shutdown();
+TEST_P(End2EndBinderTransportTest, ServerStreamingCallCoalescingApi) {
+  std::unique_ptr<grpc::testing::EchoTestService::Stub> stub = NewStub();
+  constexpr size_t kServerResponseStreamsToSend = 100;
+  grpc::ClientContext context;
+  context.AddMetadata(grpc::testing::kServerResponseStreamsToSend,
+                      std::to_string(kServerResponseStreamsToSend));
+  context.AddMetadata(grpc::testing::kServerUseCoalescingApi, "1");
+  grpc::testing::EchoRequest request;
+  request.set_message("ServerStreamingCallCoalescingApi");
+  std::unique_ptr<grpc::ClientReader<grpc::testing::EchoResponse>> reader =
+      stub->ResponseStream(&context, request);
+  grpc::testing::EchoResponse response;
+  size_t cnt = 0;
+  while (reader->Read(&response)) {
+    EXPECT_EQ(response.message(),
+              "ServerStreamingCallCoalescingApi" + std::to_string(cnt));
+    cnt++;
+  }
+  EXPECT_EQ(cnt, kServerResponseStreamsToSend);
+  grpc::Status status = reader->Finish();
+  EXPECT_TRUE(status.ok());
 }
 
 TEST_P(End2EndBinderTransportTest,
-       ServerStreamingCallThroughFakeBinderChannelServerTimeout) {
-  grpc::ChannelArguments args;
-  grpc::ServerBuilder builder;
-  end2end_testing::EchoServer service;
-  builder.RegisterService(&service);
-  std::unique_ptr<grpc::Server> server = builder.BuildAndStart();
-  std::shared_ptr<grpc::Channel> channel = BinderChannel(server.get(), args);
-  std::unique_ptr<EchoService::Stub> stub = EchoService::NewStub(channel);
+       ServerStreamingCallTryCancelBeforeProcessing) {
+  std::unique_ptr<grpc::testing::EchoTestService::Stub> stub = NewStub();
+  constexpr size_t kServerResponseStreamsToSend = 100;
   grpc::ClientContext context;
-  context.set_deadline(absl::ToChronoTime(absl::Now() + absl::Seconds(1)));
-  EchoRequest request;
-  request.set_text(std::string(end2end_testing::EchoServer::kTimeoutText));
-  std::unique_ptr<grpc::ClientReader<EchoResponse>> reader =
-      stub->EchoServerStreamingCall(&context, request);
-  EchoResponse response;
+  context.AddMetadata(grpc::testing::kServerResponseStreamsToSend,
+                      std::to_string(kServerResponseStreamsToSend));
+  context.AddMetadata(grpc::testing::kServerTryCancelRequest,
+                      std::to_string(grpc::testing::CANCEL_BEFORE_PROCESSING));
+  grpc::testing::EchoRequest request;
+  request.set_message("ServerStreamingCallTryCancelBeforeProcessing");
+  std::unique_ptr<grpc::ClientReader<grpc::testing::EchoResponse>> reader =
+      stub->ResponseStream(&context, request);
+  grpc::testing::EchoResponse response;
   EXPECT_FALSE(reader->Read(&response));
   grpc::Status status = reader->Finish();
   EXPECT_FALSE(status.ok());
-  EXPECT_EQ(status.error_message(), "Deadline Exceeded");
+  EXPECT_EQ(status.error_code(), grpc::StatusCode::CANCELLED);
+}
 
-  server->Shutdown();
+TEST_P(End2EndBinderTransportTest,
+       ServerSteramingCallTryCancelDuringProcessing) {
+  std::unique_ptr<grpc::testing::EchoTestService::Stub> stub = NewStub();
+  constexpr size_t kServerResponseStreamsToSend = 2;
+  grpc::ClientContext context;
+  context.AddMetadata(grpc::testing::kServerResponseStreamsToSend,
+                      std::to_string(kServerResponseStreamsToSend));
+  context.AddMetadata(grpc::testing::kServerTryCancelRequest,
+                      std::to_string(grpc::testing::CANCEL_DURING_PROCESSING));
+  grpc::testing::EchoRequest request;
+  request.set_message("ServerStreamingCallTryCancelDuringProcessing");
+  std::unique_ptr<grpc::ClientReader<grpc::testing::EchoResponse>> reader =
+      stub->ResponseStream(&context, request);
+  grpc::testing::EchoResponse response;
+  size_t cnt = 0;
+  while (reader->Read(&response)) {
+    EXPECT_EQ(
+        response.message(),
+        "ServerStreamingCallTryCancelDuringProcessing" + std::to_string(cnt));
+    cnt++;
+  }
+  grpc::Status status = reader->Finish();
+  EXPECT_FALSE(status.ok());
+  EXPECT_EQ(status.error_code(), grpc::StatusCode::CANCELLED);
 }
 
 TEST_P(End2EndBinderTransportTest,
-       ClientStreamingCallThroughFakeBinderChannel) {
-  grpc::ChannelArguments args;
-  grpc::ServerBuilder builder;
-  end2end_testing::EchoServer service;
-  builder.RegisterService(&service);
-  std::unique_ptr<grpc::Server> server = builder.BuildAndStart();
-  std::shared_ptr<grpc::Channel> channel = BinderChannel(server.get(), args);
-  std::unique_ptr<EchoService::Stub> stub = EchoService::NewStub(channel);
+       ServerSteramingCallTryCancelAfterProcessing) {
+  std::unique_ptr<grpc::testing::EchoTestService::Stub> stub = NewStub();
+  constexpr size_t kServerResponseStreamsToSend = 100;
+  grpc::ClientContext context;
+  context.AddMetadata(grpc::testing::kServerResponseStreamsToSend,
+                      std::to_string(kServerResponseStreamsToSend));
+  context.AddMetadata(grpc::testing::kServerTryCancelRequest,
+                      std::to_string(grpc::testing::CANCEL_AFTER_PROCESSING));
+  grpc::testing::EchoRequest request;
+  request.set_message("ServerStreamingCallTryCancelAfterProcessing");
+  std::unique_ptr<grpc::ClientReader<grpc::testing::EchoResponse>> reader =
+      stub->ResponseStream(&context, request);
+  grpc::testing::EchoResponse response;
+  size_t cnt = 0;
+  while (reader->Read(&response)) {
+    EXPECT_EQ(
+        response.message(),
+        "ServerStreamingCallTryCancelAfterProcessing" + std::to_string(cnt));
+    cnt++;
+  }
+  EXPECT_EQ(cnt, kServerResponseStreamsToSend);
+  grpc::Status status = reader->Finish();
+  EXPECT_FALSE(status.ok());
+  EXPECT_EQ(status.error_code(), grpc::StatusCode::CANCELLED);
+}
+
+TEST_P(End2EndBinderTransportTest, ClientStreamingCall) {
+  std::unique_ptr<grpc::testing::EchoTestService::Stub> stub = NewStub();
   grpc::ClientContext context;
-  EchoResponse response;
-  std::unique_ptr<grpc::ClientWriter<EchoRequest>> writer =
-      stub->EchoClientStreamingCall(&context, &response);
+  grpc::testing::EchoResponse response;
+  std::unique_ptr<grpc::ClientWriter<grpc::testing::EchoRequest>> writer =
+      stub->RequestStream(&context, &response);
   constexpr size_t kClientStreamingCounts = 100;
   std::string expected = "";
   for (size_t i = 0; i < kClientStreamingCounts; ++i) {
-    EchoRequest request;
-    request.set_text(absl::StrFormat("it works!(%d)", i));
-    writer->Write(request);
-    expected += absl::StrFormat("it works!(%d)", i);
+    grpc::testing::EchoRequest request;
+    request.set_message("ClientStreamingCall" + std::to_string(i));
+    EXPECT_TRUE(writer->Write(request));
+    expected += "ClientStreamingCall" + std::to_string(i);
   }
   writer->WritesDone();
   grpc::Status status = writer->Finish();
   EXPECT_TRUE(status.ok());
-  EXPECT_EQ(response.text(), expected);
+  EXPECT_EQ(response.message(), expected);
+}
+
+TEST_P(End2EndBinderTransportTest,
+       ClientStreamingCallTryCancelBeforeProcessing) {
+  std::unique_ptr<grpc::testing::EchoTestService::Stub> stub = NewStub();
+  grpc::ClientContext context;
+  context.AddMetadata(grpc::testing::kServerTryCancelRequest,
+                      std::to_string(grpc::testing::CANCEL_BEFORE_PROCESSING));
+  grpc::testing::EchoResponse response;
+  std::unique_ptr<grpc::ClientWriter<grpc::testing::EchoRequest>> writer =
+      stub->RequestStream(&context, &response);
+  constexpr size_t kClientStreamingCounts = 100;
+  for (size_t i = 0; i < kClientStreamingCounts; ++i) {
+    grpc::testing::EchoRequest request;
+    request.set_message("ClientStreamingCallBeforeProcessing" +
+                        std::to_string(i));
+    writer->Write(request);
+  }
+  writer->WritesDone();
+  grpc::Status status = writer->Finish();
+  EXPECT_FALSE(status.ok());
+  EXPECT_EQ(status.error_code(), grpc::StatusCode::CANCELLED);
+}
 
-  server->Shutdown();
+TEST_P(End2EndBinderTransportTest,
+       ClientStreamingCallTryCancelDuringProcessing) {
+  std::unique_ptr<grpc::testing::EchoTestService::Stub> stub = NewStub();
+  grpc::ClientContext context;
+  context.AddMetadata(grpc::testing::kServerTryCancelRequest,
+                      std::to_string(grpc::testing::CANCEL_DURING_PROCESSING));
+  grpc::testing::EchoResponse response;
+  std::unique_ptr<grpc::ClientWriter<grpc::testing::EchoRequest>> writer =
+      stub->RequestStream(&context, &response);
+  constexpr size_t kClientStreamingCounts = 100;
+  for (size_t i = 0; i < kClientStreamingCounts; ++i) {
+    grpc::testing::EchoRequest request;
+    request.set_message("ClientStreamingCallDuringProcessing" +
+                        std::to_string(i));
+    writer->Write(request);
+  }
+  writer->WritesDone();
+  grpc::Status status = writer->Finish();
+  EXPECT_FALSE(status.ok());
+  EXPECT_EQ(status.error_code(), grpc::StatusCode::CANCELLED);
+}
+
+TEST_P(End2EndBinderTransportTest,
+       ClientStreamingCallTryCancelAfterProcessing) {
+  std::unique_ptr<grpc::testing::EchoTestService::Stub> stub = NewStub();
+  grpc::ClientContext context;
+  context.AddMetadata(grpc::testing::kServerTryCancelRequest,
+                      std::to_string(grpc::testing::CANCEL_AFTER_PROCESSING));
+  grpc::testing::EchoResponse response;
+  std::unique_ptr<grpc::ClientWriter<grpc::testing::EchoRequest>> writer =
+      stub->RequestStream(&context, &response);
+  constexpr size_t kClientStreamingCounts = 100;
+  for (size_t i = 0; i < kClientStreamingCounts; ++i) {
+    grpc::testing::EchoRequest request;
+    request.set_message("ClientStreamingCallAfterProcessing" +
+                        std::to_string(i));
+    writer->Write(request);
+  }
+  writer->WritesDone();
+  grpc::Status status = writer->Finish();
+  EXPECT_FALSE(status.ok());
+  EXPECT_EQ(status.error_code(), grpc::StatusCode::CANCELLED);
 }
 
-TEST_P(End2EndBinderTransportTest, BiDirStreamingCallThroughFakeBinderChannel) {
-  grpc::ChannelArguments args;
-  grpc::ServerBuilder builder;
-  end2end_testing::EchoServer service;
-  builder.RegisterService(&service);
-  std::unique_ptr<grpc::Server> server = builder.BuildAndStart();
-  std::shared_ptr<grpc::Channel> channel = BinderChannel(server.get(), args);
-  std::unique_ptr<EchoService::Stub> stub = EchoService::NewStub(channel);
+TEST_P(End2EndBinderTransportTest, BiDirStreamingCall) {
+  std::unique_ptr<grpc::testing::EchoTestService::Stub> stub = NewStub();
   grpc::ClientContext context;
-  EchoResponse response;
-  std::shared_ptr<grpc::ClientReaderWriter<EchoRequest, EchoResponse>> stream =
-      stub->EchoBiDirStreamingCall(&context);
+  std::shared_ptr<grpc::ClientReaderWriter<grpc::testing::EchoRequest,
+                                           grpc::testing::EchoResponse>>
+      stream = stub->BidiStream(&context);
   constexpr size_t kBiDirStreamingCounts = 100;
 
   struct WriterArgs {
-    std::shared_ptr<grpc::ClientReaderWriter<EchoRequest, EchoResponse>> stream;
+    std::shared_ptr<grpc::ClientReaderWriter<grpc::testing::EchoRequest,
+                                             grpc::testing::EchoResponse>>
+        stream;
     size_t bi_dir_streaming_counts;
   } writer_args;
 
@@ -269,10 +458,9 @@ TEST_P(End2EndBinderTransportTest, BiDirStreamingCallThroughFakeBinderChannel) {
 
   auto writer_fn = [](void* arg) {
     const WriterArgs& args = *static_cast<WriterArgs*>(arg);
-    EchoResponse response;
     for (size_t i = 0; i < args.bi_dir_streaming_counts; ++i) {
-      EchoRequest request;
-      request.set_text(absl::StrFormat("it works!(%d)", i));
+      grpc::testing::EchoRequest request;
+      request.set_message("BiDirStreamingCall" + std::to_string(i));
       args.stream->Write(request);
     }
     args.stream->WritesDone();
@@ -282,37 +470,78 @@ TEST_P(End2EndBinderTransportTest, BiDirStreamingCallThroughFakeBinderChannel) {
                                   static_cast<void*>(&writer_args));
   writer_thread.Start();
   for (size_t i = 0; i < kBiDirStreamingCounts; ++i) {
-    EchoResponse response;
+    grpc::testing::EchoResponse response;
     EXPECT_TRUE(stream->Read(&response));
-    EXPECT_EQ(response.text(), absl::StrFormat("it works!(%d)", i));
+    EXPECT_EQ(response.message(), "BiDirStreamingCall" + std::to_string(i));
   }
   grpc::Status status = stream->Finish();
   EXPECT_TRUE(status.ok());
   writer_thread.Join();
+}
+
+TEST_P(End2EndBinderTransportTest, BiDirStreamingCallServerFinishesHalfway) {
+  std::unique_ptr<grpc::testing::EchoTestService::Stub> stub = NewStub();
+  constexpr size_t kBiDirStreamingCounts = 100;
+  grpc::ClientContext context;
+  context.AddMetadata(grpc::testing::kServerFinishAfterNReads,
+                      std::to_string(kBiDirStreamingCounts / 2));
+  std::shared_ptr<grpc::ClientReaderWriter<grpc::testing::EchoRequest,
+                                           grpc::testing::EchoResponse>>
+      stream = stub->BidiStream(&context);
+
+  struct WriterArgs {
+    std::shared_ptr<grpc::ClientReaderWriter<grpc::testing::EchoRequest,
+                                             grpc::testing::EchoResponse>>
+        stream;
+    size_t bi_dir_streaming_counts;
+  } writer_args;
+
+  writer_args.stream = stream;
+  writer_args.bi_dir_streaming_counts = kBiDirStreamingCounts;
 
-  server->Shutdown();
+  auto writer_fn = [](void* arg) {
+    const WriterArgs& args = *static_cast<WriterArgs*>(arg);
+    for (size_t i = 0; i < args.bi_dir_streaming_counts; ++i) {
+      grpc::testing::EchoRequest request;
+      request.set_message("BiDirStreamingCallServerFinishesHalfway" +
+                          std::to_string(i));
+      if (!args.stream->Write(request)) {
+        return;
+      }
+    }
+    args.stream->WritesDone();
+  };
+
+  grpc_core::Thread writer_thread("writer-thread", writer_fn,
+                                  static_cast<void*>(&writer_args));
+  writer_thread.Start();
+  for (size_t i = 0; i < kBiDirStreamingCounts / 2; ++i) {
+    grpc::testing::EchoResponse response;
+    EXPECT_TRUE(stream->Read(&response));
+    EXPECT_EQ(response.message(),
+              "BiDirStreamingCallServerFinishesHalfway" + std::to_string(i));
+  }
+  grpc::testing::EchoResponse response;
+  EXPECT_FALSE(stream->Read(&response));
+  writer_thread.Join();
+  grpc::Status status = stream->Finish();
+  EXPECT_TRUE(status.ok());
 }
 
 TEST_P(End2EndBinderTransportTest, LargeMessages) {
-  grpc::ChannelArguments args;
-  grpc::ServerBuilder builder;
-  end2end_testing::EchoServer service;
-  builder.RegisterService(&service);
-  std::unique_ptr<grpc::Server> server = builder.BuildAndStart();
-  std::shared_ptr<grpc::Channel> channel = BinderChannel(server.get(), args);
-  std::unique_ptr<EchoService::Stub> stub = EchoService::NewStub(channel);
+  std::unique_ptr<grpc::testing::EchoTestService::Stub> stub = NewStub();
   for (size_t size = 1; size <= 1024 * 1024; size *= 4) {
     grpc::ClientContext context;
-    EchoRequest request;
-    EchoResponse response;
-    request.set_text(std::string(size, 'a'));
-    grpc::Status status = stub->EchoUnaryCall(&context, request, &response);
+    grpc::testing::EchoRequest request;
+    grpc::testing::EchoResponse response;
+    request.set_message(std::string(size, 'a'));
+    grpc::Status status = stub->Echo(&context, request, &response);
     EXPECT_TRUE(status.ok());
-    EXPECT_EQ(response.text().size(), size);
-    EXPECT_TRUE(std::all_of(response.text().begin(), response.text().end(),
+    EXPECT_EQ(response.message().size(), size);
+    EXPECT_TRUE(std::all_of(response.message().begin(),
+                            response.message().end(),
                             [](char c) { return c == 'a'; }));
   }
-  server->Shutdown();
 }
 
 INSTANTIATE_TEST_SUITE_P(
index b455f94..6d0d1cd 100644 (file)
@@ -24,59 +24,42 @@ namespace end2end_testing {
 
 TransactionProcessor* g_transaction_processor = nullptr;
 
-FakeWritableParcel::FakeWritableParcel() : data_(1) {}
-
-int32_t FakeWritableParcel::GetDataPosition() const { return data_position_; }
-
 int32_t FakeWritableParcel::GetDataSize() const { return data_size_; }
 
-absl::Status FakeWritableParcel::SetDataPosition(int32_t pos) {
-  if (data_.size() < static_cast<size_t>(pos) + 1) {
-    data_.resize(pos + 1);
-  }
-  data_position_ = pos;
-  return absl::OkStatus();
-}
-
 absl::Status FakeWritableParcel::WriteInt32(int32_t data) {
-  data_[data_position_] = data;
-  SetDataPosition(data_position_ + 1).IgnoreError();
-  data_size_ += 4;
+  data_.push_back(data);
+  data_size_ += sizeof(int32_t);
   return absl::OkStatus();
 }
 
 absl::Status FakeWritableParcel::WriteInt64(int64_t data) {
-  data_[data_position_] = data;
-  SetDataPosition(data_position_ + 1).IgnoreError();
-  data_size_ += 8;
+  data_.push_back(data);
+  data_size_ += sizeof(int64_t);
   return absl::OkStatus();
 }
 
 absl::Status FakeWritableParcel::WriteBinder(HasRawBinder* binder) {
-  data_[data_position_] = binder->GetRawBinder();
-  SetDataPosition(data_position_ + 1).IgnoreError();
-  data_size_ += 8;
+  data_.push_back(binder->GetRawBinder());
+  data_size_ += sizeof(void*);
   return absl::OkStatus();
 }
 
 absl::Status FakeWritableParcel::WriteString(absl::string_view s) {
-  data_[data_position_] = std::string(s);
-  SetDataPosition(data_position_ + 1).IgnoreError();
+  data_.push_back(std::string(s));
   data_size_ += s.size();
   return absl::OkStatus();
 }
 
 absl::Status FakeWritableParcel::WriteByteArray(const int8_t* buffer,
                                                 int32_t length) {
-  data_[data_position_] = std::vector<int8_t>(buffer, buffer + length);
-  SetDataPosition(data_position_ + 1).IgnoreError();
+  data_.push_back(std::vector<int8_t>(buffer, buffer + length));
   data_size_ += length;
   return absl::OkStatus();
 }
 
 int32_t FakeReadableParcel::GetDataSize() const { return data_size_; }
 
-absl::Status FakeReadableParcel::ReadInt32(int32_t* data) const {
+absl::Status FakeReadableParcel::ReadInt32(int32_t* data) {
   if (data_position_ >= data_.size() ||
       !absl::holds_alternative<int32_t>(data_[data_position_])) {
     return absl::InternalError("ReadInt32 failed");
@@ -85,7 +68,7 @@ absl::Status FakeReadableParcel::ReadInt32(int32_t* data) const {
   return absl::OkStatus();
 }
 
-absl::Status FakeReadableParcel::ReadInt64(int64_t* data) const {
+absl::Status FakeReadableParcel::ReadInt64(int64_t* data) {
   if (data_position_ >= data_.size() ||
       !absl::holds_alternative<int64_t>(data_[data_position_])) {
     return absl::InternalError("ReadInt64 failed");
@@ -94,8 +77,7 @@ absl::Status FakeReadableParcel::ReadInt64(int64_t* data) const {
   return absl::OkStatus();
 }
 
-absl::Status FakeReadableParcel::ReadBinder(
-    std::unique_ptr<Binder>* data) const {
+absl::Status FakeReadableParcel::ReadBinder(std::unique_ptr<Binder>* data) {
   if (data_position_ >= data_.size() ||
       !absl::holds_alternative<void*>(data_[data_position_])) {
     return absl::InternalError("ReadBinder failed");
@@ -106,18 +88,16 @@ absl::Status FakeReadableParcel::ReadBinder(
   return absl::OkStatus();
 }
 
-absl::Status FakeReadableParcel::ReadString(char data[111]) const {
+absl::Status FakeReadableParcel::ReadString(std::string* str) {
   if (data_position_ >= data_.size() ||
       !absl::holds_alternative<std::string>(data_[data_position_])) {
     return absl::InternalError("ReadString failed");
   }
-  const std::string& s = absl::get<std::string>(data_[data_position_++]);
-  if (s.size() >= 100) return absl::InternalError("ReadString failed");
-  std::memcpy(data, s.data(), s.size());
+  *str = absl::get<std::string>(data_[data_position_++]);
   return absl::OkStatus();
 }
 
-absl::Status FakeReadableParcel::ReadByteArray(std::string* data) const {
+absl::Status FakeReadableParcel::ReadByteArray(std::string* data) {
   if (data_position_ >= data_.size() ||
       !absl::holds_alternative<std::vector<int8_t>>(data_[data_position_])) {
     return absl::InternalError("ReadByteArray failed");
index c18149b..09efcf8 100644 (file)
@@ -82,10 +82,7 @@ using FakeData = std::vector<
 // MoveData().
 class FakeWritableParcel final : public WritableParcel {
  public:
-  FakeWritableParcel();
-  int32_t GetDataPosition() const override;
   int32_t GetDataSize() const override;
-  absl::Status SetDataPosition(int32_t pos) override;
   absl::Status WriteInt32(int32_t data) override;
   absl::Status WriteInt64(int64_t data) override;
   absl::Status WriteBinder(HasRawBinder* binder) override;
@@ -96,7 +93,6 @@ class FakeWritableParcel final : public WritableParcel {
 
  private:
   FakeData data_;
-  size_t data_position_ = 0;
   int32_t data_size_ = 0;
 };
 
@@ -109,11 +105,11 @@ class FakeReadableParcel final : public ReadableParcel {
   explicit FakeReadableParcel(FakeData data) : data_(std::move(data)) {
     for (auto& d : data_) {
       if (absl::holds_alternative<int32_t>(d)) {
-        data_size_ += 4;
+        data_size_ += sizeof(int32_t);
       } else if (absl::holds_alternative<int64_t>(d)) {
-        data_size_ += 8;
+        data_size_ += sizeof(int64_t);
       } else if (absl::holds_alternative<void*>(d)) {
-        data_size_ += 8;
+        data_size_ += sizeof(void*);
       } else if (absl::holds_alternative<std::string>(d)) {
         data_size_ += absl::get<std::string>(d).size();
       } else {
@@ -123,15 +119,15 @@ class FakeReadableParcel final : public ReadableParcel {
   }
 
   int32_t GetDataSize() const override;
-  absl::Status ReadInt32(int32_t* data) const override;
-  absl::Status ReadInt64(int64_t* data) const override;
-  absl::Status ReadBinder(std::unique_ptr<Binder>* data) const override;
-  absl::Status ReadByteArray(std::string* data) const override;
-  absl::Status ReadString(char data[111]) const override;
+  absl::Status ReadInt32(int32_t* data) override;
+  absl::Status ReadInt64(int64_t* data) override;
+  absl::Status ReadBinder(std::unique_ptr<Binder>* data) override;
+  absl::Status ReadByteArray(std::string* data) override;
+  absl::Status ReadString(std::string* str) override;
 
  private:
   const FakeData data_;
-  mutable size_t data_position_ = 0;
+  size_t data_position_ = 0;
   int32_t data_size_ = 0;
 };
 
@@ -186,9 +182,9 @@ class PersistentFakeTransactionReceiver {
       TransactionReceiver::OnTransactCb cb,
       std::unique_ptr<FakeBinderTunnel> tunnel);
 
-  absl::Status Receive(BinderTransportTxCode tx_code,
-                       const ReadableParcel* parcel) {
-    return callback_(static_cast<transaction_code_t>(tx_code), parcel);
+  absl::Status Receive(BinderTransportTxCode tx_code, ReadableParcel* parcel) {
+    return callback_(static_cast<transaction_code_t>(tx_code), parcel,
+                     /*uid=*/0);
   }
 
  private:
@@ -215,7 +211,6 @@ class FakeBinder final : public Binder {
   absl::Status Transact(BinderTransportTxCode tx_code) override;
 
   WritableParcel* GetWritableParcel() const override { return input_.get(); }
-  ReadableParcel* GetReadableParcel() const override { return output_.get(); }
 
   std::unique_ptr<TransactionReceiver> ConstructTxReceiver(
       grpc_core::RefCountedPtr<WireReader> wire_reader_ref,
@@ -226,7 +221,6 @@ class FakeBinder final : public Binder {
  private:
   FakeEndpoint* endpoint_;
   std::unique_ptr<FakeWritableParcel> input_;
-  std::unique_ptr<FakeReadableParcel> output_;
 };
 
 // A transaction processor.
index b02e8bc..1c32a04 100644 (file)
 
 namespace grpc_binder {
 namespace end2end_testing {
-
-TEST(FakeBinderTestWithoutTransaction, WritableParcelDataPosition) {
-  std::unique_ptr<WritableParcel> parcel =
-      absl::make_unique<FakeWritableParcel>();
-  EXPECT_EQ(parcel->GetDataPosition(), 0);
-  EXPECT_TRUE(parcel->WriteInt32(0).ok());
-  EXPECT_EQ(parcel->GetDataPosition(), 1);
-  EXPECT_TRUE(parcel->WriteInt32(1).ok());
-  EXPECT_TRUE(parcel->WriteInt32(2).ok());
-  EXPECT_EQ(parcel->GetDataPosition(), 3);
-  EXPECT_TRUE(parcel->WriteString("").ok());
-  EXPECT_EQ(parcel->GetDataPosition(), 4);
-  EXPECT_TRUE(parcel->SetDataPosition(0).ok());
-  const char kBuffer[] = "test";
-  EXPECT_TRUE(parcel
-                  ->WriteByteArray(reinterpret_cast<const int8_t*>(kBuffer),
-                                   strlen(kBuffer))
-                  .ok());
-  EXPECT_EQ(parcel->GetDataPosition(), 1);
-  EXPECT_TRUE(parcel->SetDataPosition(100).ok());
-  EXPECT_EQ(parcel->GetDataPosition(), 100);
-}
-
 namespace {
 
 class FakeBinderTest : public ::testing::TestWithParam<absl::Duration> {
@@ -71,7 +48,7 @@ TEST_P(FakeBinderTest, SendInt32) {
   std::unique_ptr<Binder> sender;
   std::unique_ptr<TransactionReceiver> tx_receiver;
   std::tie(sender, tx_receiver) = NewBinderPair(
-      [&](transaction_code_t tx_code, const ReadableParcel* parcel) {
+      [&](transaction_code_t tx_code, ReadableParcel* parcel, int /*uid*/) {
         EXPECT_EQ(tx_code, kTxCode);
         int value = 0;
         EXPECT_TRUE(parcel->ReadInt32(&value).ok());
@@ -96,12 +73,11 @@ TEST_P(FakeBinderTest, SendString) {
   std::unique_ptr<Binder> sender;
   std::unique_ptr<TransactionReceiver> tx_receiver;
   std::tie(sender, tx_receiver) = NewBinderPair(
-      [&](transaction_code_t tx_code, const ReadableParcel* parcel) {
+      [&](transaction_code_t tx_code, ReadableParcel* parcel, int /*uid*/) {
         EXPECT_EQ(tx_code, kTxCode);
-        char value[111];
-        memset(value, 0, sizeof(value));
-        EXPECT_TRUE(parcel->ReadString(value).ok());
-        EXPECT_STREQ(value, kValue);
+        std::string value;
+        EXPECT_TRUE(parcel->ReadString(&value).ok());
+        EXPECT_STREQ(value.c_str(), kValue);
         called++;
         return absl::OkStatus();
       });
@@ -122,7 +98,7 @@ TEST_P(FakeBinderTest, SendByteArray) {
   std::unique_ptr<Binder> sender;
   std::unique_ptr<TransactionReceiver> tx_receiver;
   std::tie(sender, tx_receiver) = NewBinderPair(
-      [&](transaction_code_t tx_code, const ReadableParcel* parcel) {
+      [&](transaction_code_t tx_code, ReadableParcel* parcel, int /*uid*/) {
         EXPECT_EQ(tx_code, kTxCode);
         std::string value;
         EXPECT_TRUE(parcel->ReadByteArray(&value).ok());
@@ -152,7 +128,7 @@ TEST_P(FakeBinderTest, SendMultipleItems) {
   std::unique_ptr<Binder> sender;
   std::unique_ptr<TransactionReceiver> tx_receiver;
   std::tie(sender, tx_receiver) = NewBinderPair(
-      [&](transaction_code_t tx_code, const ReadableParcel* parcel) {
+      [&](transaction_code_t tx_code, ReadableParcel* parcel, int /*uid*/) {
         int value_result;
         EXPECT_EQ(tx_code, kTxCode);
         EXPECT_TRUE(parcel->ReadInt32(&value_result).ok());
@@ -160,10 +136,9 @@ TEST_P(FakeBinderTest, SendMultipleItems) {
         std::string byte_array_result;
         EXPECT_TRUE(parcel->ReadByteArray(&byte_array_result).ok());
         EXPECT_EQ(byte_array_result, kByteArray);
-        char string_result[111];
-        memset(string_result, 0, sizeof(string_result));
-        EXPECT_TRUE(parcel->ReadString(string_result).ok());
-        EXPECT_STREQ(string_result, kString);
+        std::string string_result;
+        EXPECT_TRUE(parcel->ReadString(&string_result).ok());
+        EXPECT_STREQ(string_result.c_str(), kString);
         called++;
         return absl::OkStatus();
       });
@@ -189,7 +164,7 @@ TEST_P(FakeBinderTest, SendBinder) {
   std::unique_ptr<Binder> sender;
   std::unique_ptr<TransactionReceiver> tx_receiver;
   std::tie(sender, tx_receiver) = NewBinderPair(
-      [&](transaction_code_t tx_code, const ReadableParcel* parcel) {
+      [&](transaction_code_t tx_code, ReadableParcel* parcel, int /*uid*/) {
         EXPECT_EQ(tx_code, kTxCode);
         std::unique_ptr<Binder> binder;
         EXPECT_TRUE(parcel->ReadBinder(&binder).ok());
@@ -205,7 +180,7 @@ TEST_P(FakeBinderTest, SendBinder) {
   std::unique_ptr<TransactionReceiver> tx_receiver2 =
       absl::make_unique<FakeTransactionReceiver>(
           nullptr,
-          [&](transaction_code_t tx_code, const ReadableParcel* parcel) {
+          [&](transaction_code_t tx_code, ReadableParcel* parcel, int /*uid*/) {
             int value;
             EXPECT_TRUE(parcel->ReadInt32(&value).ok());
             EXPECT_EQ(value, kValue);
@@ -231,7 +206,7 @@ TEST_P(FakeBinderTest, SendTransactionAfterDestruction) {
   {
     std::unique_ptr<TransactionReceiver> tx_receiver;
     std::tie(sender, tx_receiver) = NewBinderPair(
-        [&](transaction_code_t tx_code, const ReadableParcel* parcel) {
+        [&](transaction_code_t tx_code, ReadableParcel* parcel, int /*uid*/) {
           EXPECT_EQ(tx_code, kTxCode);
           int value;
           EXPECT_TRUE(parcel->ReadInt32(&value).ok());
@@ -303,8 +278,8 @@ TEST_P(FakeBinderTest, StressTest) {
       std::vector<std::vector<int>>* cnt = th_arg->global_cnts;
       std::tie(binder, tx_receiver) =
           NewBinderPair([tid, p, cnt, expected_tx_code](
-                            transaction_code_t tx_code,
-                            const ReadableParcel* parcel) mutable {
+                            transaction_code_t tx_code, ReadableParcel* parcel,
+                            int /*uid*/) mutable {
             EXPECT_EQ(tx_code, expected_tx_code);
             int value;
             EXPECT_TRUE(parcel->ReadInt32(&value).ok());
index 04f09f5..bbf5732 100644 (file)
@@ -16,6 +16,8 @@
 
 #include <utility>
 
+#include <grpcpp/security/binder_security_policy.h>
+
 #include "src/core/ext/transport/binder/transport/binder_transport.h"
 #include "src/core/ext/transport/binder/wire_format/wire_reader_impl.h"
 #include "src/core/lib/channel/channel_args.h"
@@ -33,10 +35,12 @@ class ServerSetupTransportHelper {
  public:
   ServerSetupTransportHelper()
       : wire_reader_(absl::make_unique<WireReaderImpl>(
-            /*transport_stream_receiver=*/nullptr, /*is_client=*/false)) {
+            /*transport_stream_receiver=*/nullptr, /*is_client=*/false,
+            std::make_shared<
+                grpc::experimental::binder::UntrustedSecurityPolicy>())) {
     std::tie(endpoint_binder_, tx_receiver_) = NewBinderPair(
-        [this](transaction_code_t tx_code, const ReadableParcel* parcel) {
-          return this->wire_reader_->ProcessTransaction(tx_code, parcel);
+        [this](transaction_code_t tx_code, ReadableParcel* parcel, int uid) {
+          return this->wire_reader_->ProcessTransaction(tx_code, parcel, uid);
         });
   }
   std::unique_ptr<Binder> WaitForClientBinder() {
@@ -75,13 +79,16 @@ CreateClientServerBindersPairForTesting() {
         ThreadArgs* args = static_cast<ThreadArgs*>(arg);
         std::unique_ptr<Binder> endpoint_binder =
             std::move(args->endpoint_binder);
-        *args->client_transport =
-            grpc_create_binder_transport_client(std::move(endpoint_binder));
+        *args->client_transport = grpc_create_binder_transport_client(
+            std::move(endpoint_binder),
+            std::make_shared<
+                grpc::experimental::binder::UntrustedSecurityPolicy>());
       },
       &args);
   client_thread.Start();
-  grpc_transport* server_transport =
-      grpc_create_binder_transport_server(helper.WaitForClientBinder());
+  grpc_transport* server_transport = grpc_create_binder_transport_server(
+      helper.WaitForClientBinder(),
+      std::make_shared<grpc::experimental::binder::UntrustedSecurityPolicy>());
   client_thread.Join();
   return std::make_pair(client_transport, server_transport);
 }
diff --git a/test/core/transport/binder/endpoint_binder_pool_test.cc b/test/core/transport/binder/endpoint_binder_pool_test.cc
new file mode 100644 (file)
index 0000000..e0f671a
--- /dev/null
@@ -0,0 +1,76 @@
+// 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 "src/core/ext/transport/binder/client/endpoint_binder_pool.h"
+
+#include <cassert>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "absl/memory/memory.h"
+
+#include "src/core/ext/transport/binder/client/endpoint_binder_pool.h"
+#include "test/core/transport/binder/mock_objects.h"
+#include "test/core/util/test_config.h"
+
+namespace grpc_binder {
+
+class CallbackChecker {
+ public:
+  MOCK_METHOD(void, Cb, (std::unique_ptr<grpc_binder::Binder>), ());
+};
+
+TEST(EndpointBinderPoolTest, AddBeforeGet) {
+  EndpointBinderPool pool;
+  auto b = absl::make_unique<grpc_binder::MockBinder>();
+  CallbackChecker cc;
+  pool.AddEndpointBinder("test", std::move(b));
+  // TODO(mingcl): Use pointer matcher to verify it is `b` being passed back
+  // here. It is only available in newer gtest version
+  EXPECT_CALL(cc, Cb(testing::_));
+  pool.GetEndpointBinder(
+      "test", std::bind(&CallbackChecker::Cb, &cc, std::placeholders::_1));
+}
+
+TEST(EndpointBinderPoolTest, GetBeforeAdd) {
+  EndpointBinderPool pool;
+  auto b = absl::make_unique<grpc_binder::MockBinder>();
+  CallbackChecker cc;
+  EXPECT_CALL(cc, Cb(testing::_)).Times(0);
+  pool.GetEndpointBinder(
+      "test", std::bind(&CallbackChecker::Cb, &cc, std::placeholders::_1));
+  EXPECT_CALL(cc, Cb(testing::_)).Times(1);
+  pool.AddEndpointBinder("test", std::move(b));
+}
+
+TEST(EndpointBinderPoolTest, ExpectNotCalled) {
+  EndpointBinderPool pool;
+  auto b = absl::make_unique<grpc_binder::MockBinder>();
+  CallbackChecker cc;
+  EXPECT_CALL(cc, Cb(testing::_)).Times(0);
+  pool.GetEndpointBinder(
+      "test", std::bind(&CallbackChecker::Cb, &cc, std::placeholders::_1));
+}
+
+}  // namespace grpc_binder
+
+int main(int argc, char** argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  grpc::testing::TestEnvironment env(argc, argv);
+  return RUN_ALL_TESTS();
+}
index 98261b0..4fb0355 100644 (file)
@@ -33,7 +33,6 @@ MockReadableParcel::MockReadableParcel() {
 }
 
 MockWritableParcel::MockWritableParcel() {
-  ON_CALL(*this, SetDataPosition).WillByDefault(Return(absl::OkStatus()));
   ON_CALL(*this, WriteInt32).WillByDefault(Return(absl::OkStatus()));
   ON_CALL(*this, WriteBinder).WillByDefault(Return(absl::OkStatus()));
   ON_CALL(*this, WriteString).WillByDefault(Return(absl::OkStatus()));
@@ -44,7 +43,6 @@ MockBinder::MockBinder() {
   ON_CALL(*this, PrepareTransaction).WillByDefault(Return(absl::OkStatus()));
   ON_CALL(*this, Transact).WillByDefault(Return(absl::OkStatus()));
   ON_CALL(*this, GetWritableParcel).WillByDefault(Return(&mock_input_));
-  ON_CALL(*this, GetReadableParcel).WillByDefault(Return(&mock_output_));
   ON_CALL(*this, ConstructTxReceiver)
       .WillByDefault(
           [this](grpc_core::RefCountedPtr<WireReader> /*wire_reader_ref*/,
index 39f70c3..9a341ac 100644 (file)
@@ -26,9 +26,7 @@ namespace grpc_binder {
 
 class MockWritableParcel : public WritableParcel {
  public:
-  MOCK_METHOD(int32_t, GetDataPosition, (), (const, override));
   MOCK_METHOD(int32_t, GetDataSize, (), (const, override));
-  MOCK_METHOD(absl::Status, SetDataPosition, (int32_t), (override));
   MOCK_METHOD(absl::Status, WriteInt32, (int32_t), (override));
   MOCK_METHOD(absl::Status, WriteInt64, (int64_t), (override));
   MOCK_METHOD(absl::Status, WriteBinder, (HasRawBinder*), (override));
@@ -42,12 +40,11 @@ class MockWritableParcel : public WritableParcel {
 class MockReadableParcel : public ReadableParcel {
  public:
   MOCK_METHOD(int32_t, GetDataSize, (), (const, override));
-  MOCK_METHOD(absl::Status, ReadInt32, (int32_t*), (const, override));
-  MOCK_METHOD(absl::Status, ReadInt64, (int64_t*), (const, override));
-  MOCK_METHOD(absl::Status, ReadBinder, (std::unique_ptr<Binder>*),
-              (const, override));
-  MOCK_METHOD(absl::Status, ReadByteArray, (std::string*), (const, override));
-  MOCK_METHOD(absl::Status, ReadString, (char[111]), (const, override));
+  MOCK_METHOD(absl::Status, ReadInt32, (int32_t*), (override));
+  MOCK_METHOD(absl::Status, ReadInt64, (int64_t*), (override));
+  MOCK_METHOD(absl::Status, ReadBinder, (std::unique_ptr<Binder>*), (override));
+  MOCK_METHOD(absl::Status, ReadByteArray, (std::string*), (override));
+  MOCK_METHOD(absl::Status, ReadString, (std::string*), (override));
 
   MockReadableParcel();
 };
@@ -58,7 +55,6 @@ class MockBinder : public Binder {
   MOCK_METHOD(absl::Status, PrepareTransaction, (), (override));
   MOCK_METHOD(absl::Status, Transact, (BinderTransportTxCode), (override));
   MOCK_METHOD(WritableParcel*, GetWritableParcel, (), (const, override));
-  MOCK_METHOD(ReadableParcel*, GetReadableParcel, (), (const, override));
   MOCK_METHOD(std::unique_ptr<TransactionReceiver>, ConstructTxReceiver,
               (grpc_core::RefCountedPtr<WireReader>,
                TransactionReceiver::OnTransactCb),
@@ -80,8 +76,9 @@ class MockTransactionReceiver : public TransactionReceiver {
  public:
   explicit MockTransactionReceiver(OnTransactCb transact_cb,
                                    BinderTransportTxCode code,
-                                   const ReadableParcel* output) {
-    transact_cb(static_cast<transaction_code_t>(code), output).IgnoreError();
+                                   ReadableParcel* output) {
+    transact_cb(static_cast<transaction_code_t>(code), output, /*uid=*/0)
+        .IgnoreError();
   }
 
   MOCK_METHOD(void*, GetRawBinder, (), (override));
index 47c6d5d..cc6f739 100644 (file)
@@ -18,6 +18,7 @@
 // top-level metadata. The following tests verify that the interactions between
 // WireReaderImpl and both the output (readable) parcel and the transport stream
 // receiver are correct in all possible situations.
+
 #include <memory>
 #include <string>
 #include <thread>
@@ -27,6 +28,8 @@
 
 #include "absl/memory/memory.h"
 
+#include <grpcpp/security/binder_security_policy.h>
+
 #include "src/core/ext/transport/binder/wire_format/wire_reader_impl.h"
 #include "test/core/transport/binder/mock_objects.h"
 #include "test/core/util/test_config.h"
@@ -45,7 +48,10 @@ class WireReaderTest : public ::testing::Test {
   WireReaderTest()
       : transport_stream_receiver_(
             std::make_shared<StrictMock<MockTransportStreamReceiver>>()),
-        wire_reader_(transport_stream_receiver_, /*is_client=*/true) {}
+        wire_reader_(
+            transport_stream_receiver_, /*is_client=*/true,
+            std::make_shared<
+                grpc::experimental::binder::UntrustedSecurityPolicy>()) {}
 
  protected:
   void ExpectReadInt32(int result) {
@@ -75,7 +81,8 @@ class WireReaderTest : public ::testing::Test {
   template <typename T>
   absl::Status CallProcessTransaction(T tx_code) {
     return wire_reader_.ProcessTransaction(
-        static_cast<transaction_code_t>(tx_code), &mock_readable_parcel_);
+        static_cast<transaction_code_t>(tx_code), &mock_readable_parcel_,
+        /*uid=*/0);
   }
 
   std::shared_ptr<StrictMock<MockTransportStreamReceiver>>
index ad6709a..59cdf3f 100644 (file)
 
 load("//bazel:grpc_build_system.bzl", "grpc_cc_binary", "grpc_cc_library", "grpc_cc_test", "grpc_package")
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 grpc_package(name = "test/core/transport/chttp2")
 
-load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
+load("//test/core/util:grpc_fuzzer.bzl", "grpc_proto_fuzzer")
 load("//bazel:custom_exec_properties.bzl", "LARGE_MACHINE")
 
-grpc_fuzzer(
+grpc_proto_fuzzer(
     name = "hpack_parser_fuzzer",
     srcs = ["hpack_parser_fuzzer_test.cc"],
     corpus = "hpack_parser_corpus",
+    proto = "hpack_parser_fuzzer.proto",
     tags = ["no_windows"],
     deps = [
         "//:grpc",
@@ -113,6 +114,7 @@ grpc_cc_test(
 grpc_cc_test(
     name = "hpack_parser_test",
     srcs = ["hpack_parser_test.cc"],
+    external_deps = ["gtest"],
     language = "C++",
     uses_polling = False,
     deps = [
@@ -125,6 +127,7 @@ grpc_cc_test(
 grpc_cc_test(
     name = "hpack_parser_table_test",
     srcs = ["hpack_parser_table_test.cc"],
+    external_deps = ["gtest"],
     language = "C++",
     uses_polling = False,
     deps = [
index e839c9f..d59248c 100644 (file)
@@ -161,35 +161,25 @@ static void verify(const verify_params params, const char* expected,
   va_list l;
   grpc_linked_mdelem* e =
       static_cast<grpc_linked_mdelem*>(gpr_malloc(sizeof(*e) * nheaders));
-  grpc_metadata_batch b;
-
-  grpc_metadata_batch_init(&b);
+  auto arena = grpc_core::MakeScopedArena(1024);
+  grpc_metadata_batch b(arena.get());
 
   va_start(l, nheaders);
   for (i = 0; i < nheaders; i++) {
     char* key = va_arg(l, char*);
     char* value = va_arg(l, char*);
-    if (i) {
-      e[i - 1].next = &e[i];
-      e[i].prev = &e[i - 1];
-    }
     grpc_slice value_slice = grpc_slice_from_static_string(value);
     if (!params.only_intern_key) {
       value_slice = grpc_slice_intern(value_slice);
     }
     e[i].md = grpc_mdelem_from_slices(
         grpc_slice_intern(grpc_slice_from_static_string(key)), value_slice);
+    GPR_ASSERT(GRPC_ERROR_NONE == b.LinkTail(&e[i]));
   }
-  e[0].prev = nullptr;
-  e[nheaders - 1].next = nullptr;
   va_end(l);
 
-  b.list.head = &e[0];
-  b.list.tail = &e[nheaders - 1];
-  b.list.count = nheaders;
-
   if (cap_to_delete == num_to_delete) {
-    cap_to_delete = GPR_MAX(2 * cap_to_delete, 1000);
+    cap_to_delete = std::max(2 * cap_to_delete, size_t(1000));
     to_delete = static_cast<void**>(
         gpr_realloc(to_delete, sizeof(*to_delete) * cap_to_delete));
   }
@@ -210,7 +200,6 @@ static void verify(const verify_params params, const char* expected,
   verify_frames(output, params.eof);
   merged = grpc_slice_merge(output.slices, output.count);
   grpc_slice_buffer_destroy_internal(&output);
-  grpc_metadata_batch_destroy(&b);
 
   if (!grpc_slice_eq(merged, expect)) {
     char* expect_str = grpc_dump_slice(expect, GPR_DUMP_HEX | GPR_DUMP_ASCII);
@@ -255,20 +244,17 @@ static void test_basic_headers() {
 
 static void verify_continuation_headers(const char* key, const char* value,
                                         bool is_eof) {
+  auto arena = grpc_core::MakeScopedArena(1024);
   grpc_slice_buffer output;
   grpc_mdelem elem = grpc_mdelem_from_slices(
       grpc_slice_intern(grpc_slice_from_static_string(key)),
       grpc_slice_intern(grpc_slice_from_static_string(value)));
-  grpc_linked_mdelem* e =
-      static_cast<grpc_linked_mdelem*>(gpr_malloc(sizeof(*e)));
-  grpc_metadata_batch b;
-  grpc_metadata_batch_init(&b);
-  e[0].md = elem;
-  e[0].prev = nullptr;
-  e[0].next = nullptr;
-  b.list.head = &e[0];
-  b.list.tail = &e[0];
-  b.list.count = 1;
+  grpc_linked_mdelem e;
+  e.md = elem;
+  e.prev = nullptr;
+  e.next = nullptr;
+  grpc_metadata_batch b(arena.get());
+  GPR_ASSERT(GRPC_ERROR_NONE == b.LinkTail(&e));
   grpc_slice_buffer_init(&output);
 
   grpc_transport_one_way_stats stats;
@@ -282,8 +268,6 @@ static void verify_continuation_headers(const char* key, const char* value,
   g_compressor->EncodeHeaders(hopt, b, &output);
   verify_frames(output, is_eof);
   grpc_slice_buffer_destroy_internal(&output);
-  grpc_metadata_batch_destroy(&b);
-  gpr_free(e);
 }
 
 static void test_continuation_headers() {
@@ -343,22 +327,19 @@ static void test_decode_table_overflow() {
 static void verify_table_size_change_match_elem_size(const char* key,
                                                      const char* value,
                                                      bool use_true_binary) {
+  auto arena = grpc_core::MakeScopedArena(1024);
   grpc_slice_buffer output;
   grpc_mdelem elem = grpc_mdelem_from_slices(
       grpc_slice_intern(grpc_slice_from_static_string(key)),
       grpc_slice_intern(grpc_slice_from_static_string(value)));
   size_t elem_size = grpc_core::MetadataSizeInHPackTable(elem, use_true_binary);
   size_t initial_table_size = g_compressor->test_only_table_size();
-  grpc_linked_mdelem* e =
-      static_cast<grpc_linked_mdelem*>(gpr_malloc(sizeof(*e)));
-  grpc_metadata_batch b;
-  grpc_metadata_batch_init(&b);
-  e[0].md = elem;
-  e[0].prev = nullptr;
-  e[0].next = nullptr;
-  b.list.head = &e[0];
-  b.list.tail = &e[0];
-  b.list.count = 1;
+  grpc_linked_mdelem e;
+  e.md = elem;
+  e.prev = nullptr;
+  e.next = nullptr;
+  grpc_metadata_batch b(arena.get());
+  GPR_ASSERT(GRPC_ERROR_NONE == b.LinkTail(&e));
   grpc_slice_buffer_init(&output);
 
   grpc_transport_one_way_stats stats;
@@ -372,11 +353,9 @@ static void verify_table_size_change_match_elem_size(const char* key,
   g_compressor->EncodeHeaders(hopt, b, &output);
   verify_frames(output, false);
   grpc_slice_buffer_destroy_internal(&output);
-  grpc_metadata_batch_destroy(&b);
 
   GPR_ASSERT(g_compressor->test_only_table_size() ==
              elem_size + initial_table_size);
-  gpr_free(e);
 }
 
 static void test_encode_header_size() {
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/0141fcddc9807ee093313b2256f1306fbbdc6cda b/test/core/transport/chttp2/hpack_parser_corpus/0141fcddc9807ee093313b2256f1306fbbdc6cda
deleted file mode 100644 (file)
index 76b1250..0000000
+++ /dev/null
@@ -1 +0,0 @@
-(?¤\1f¤¤\1fÛ¤Ûð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/0255050a9ccb25f46d6c1bf6a5a8a4c0c7635599 b/test/core/transport/chttp2/hpack_parser_corpus/0255050a9ccb25f46d6c1bf6a5a8a4c0c7635599
deleted file mode 100644 (file)
index e28a586..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/0255050a9ccb25f46d6c1bf6a5a8a4c0c7635599 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/0320a995a8c76c64c8a0e0297f632b76d9bc92d6 b/test/core/transport/chttp2/hpack_parser_corpus/0320a995a8c76c64c8a0e0297f632b76d9bc92d6
deleted file mode 100644 (file)
index 0ea34c4..0000000
+++ /dev/null
@@ -1 +0,0 @@
\1f!\83Ûð¤\1f!\83¶Ûð*c
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/042091aeac4cc255506b96fa11c7354e699fde76 b/test/core/transport/chttp2/hpack_parser_corpus/042091aeac4cc255506b96fa11c7354e699fde76
deleted file mode 100644 (file)
index ce65ec6..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin;?0c!(\aðK   ð[N!\8bc[:¤\10\að¤\ f-\\19!õG!):[(!!¤
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/051268ade45dbed0aab896d7d9f4d10ba89d3b09 b/test/core/transport/chttp2/hpack_parser_corpus/051268ade45dbed0aab896d7d9f4d10ba89d3b09
deleted file mode 100644 (file)
index 70967ff..0000000
+++ /dev/null
@@ -1 +0,0 @@
-*¤\10¤¤\10\að¤\ f-bin\8bc[)(\að¤\ f-bin-'bin       !!?¤\1fÛð!\10\að{(-binð      !\      !å7é\e;?Gí([(!!\ð*¤\ f¤Ûð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/0696e7bf7837d98de01c915d3c9d80e5d21b30d2 b/test/core/transport/chttp2/hpack_parser_corpus/0696e7bf7837d98de01c915d3c9d80e5d21b30d2
deleted file mode 100644 (file)
index a7936f2..0000000
+++ /dev/null
@@ -1 +0,0 @@
-\10\að[(-bin!     ð(!\    ?* ¤®@\b\10\a:ð[\ 6
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/06995c2f3f01c7ec50547415dc324c64030b7a3e b/test/core/transport/chttp2/hpack_parser_corpus/06995c2f3f01c7ec50547415dc324c64030b7a3e
deleted file mode 100644 (file)
index be20eb5..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/06995c2f3f01c7ec50547415dc324c64030b7a3e and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/06f7ce769fe07804fc842462d4be8c1aa2ba82c2 b/test/core/transport/chttp2/hpack_parser_corpus/06f7ce769fe07804fc842462d4be8c1aa2ba82c2
deleted file mode 100644 (file)
index 0edc9f9..0000000
+++ /dev/null
@@ -1 +0,0 @@
\80¤\88(cc
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/0781b055c85ab8fbd0a3d0080a32e394af8761c4 b/test/core/transport/chttp2/hpack_parser_corpus/0781b055c85ab8fbd0a3d0080a32e394af8761c4
deleted file mode 100644 (file)
index ebb1e88..0000000
+++ /dev/null
@@ -1 +0,0 @@
\1f!\83Ûðð¤\1f!\83Ûððc
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/080e1f19e6061c5bcac31add2095f87f6ce46129 b/test/core/transport/chttp2/hpack_parser_corpus/080e1f19e6061c5bcac31add2095f87f6ce46129
deleted file mode 100644 (file)
index e880d55..0000000
+++ /dev/null
@@ -1 +0,0 @@
-;?'c\að[(!      ð[N!\   !åGý!*(!        !åGýA)(!)í!¼*)åGýI)(Ù;)\8a
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/0828169ba82152a8907f1001e3d98804397d4610 b/test/core/transport/chttp2/hpack_parser_corpus/0828169ba82152a8907f1001e3d98804397d4610
deleted file mode 100644 (file)
index af778fb..0000000
+++ /dev/null
@@ -1 +0,0 @@
\1f¤Ûð!ð        cc'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/08ffc4a4160e9fe6f322c28870a89a41fd9c37d7 b/test/core/transport/chttp2/hpack_parser_corpus/08ffc4a4160e9fe6f322c28870a89a41fd9c37d7
deleted file mode 100644 (file)
index e0c8806..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/08ffc4a4160e9fe6f322c28870a89a41fd9c37d7 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/090a7a758898a6e7c9108b7e8a1cb9cda383e707 b/test/core/transport/chttp2/hpack_parser_corpus/090a7a758898a6e7c9108b7e8a1cb9cda383e707
deleted file mode 100644 (file)
index 93f599d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8bc[)(-'bin  !!?¤\1fÛð!\10\að{(-binð      !\      !å\1fé\e;?Gí[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/0940663729501b750a18542e1041cc26385c6148 b/test/core/transport/chttp2/hpack_parser_corpus/0940663729501b750a18542e1041cc26385c6148
deleted file mode 100644 (file)
index 1e92896..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8bäc[ò)('-bi.        *)!?¤\1fÛâ!\10\að{(-bi\n!    !       ðå\1fé\e;?Gí:[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/0a10bd140c6c5fb109a0816ca061739688a6db9a b/test/core/transport/chttp2/hpack_parser_corpus/0a10bd140c6c5fb109a0816ca061739688a6db9a
deleted file mode 100644 (file)
index 94a6997..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/0a10bd140c6c5fb109a0816ca061739688a6db9a and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/0a4d3fda02cdcb7adad1daa80d65780c9c8d1464 b/test/core/transport/chttp2/hpack_parser_corpus/0a4d3fda02cdcb7adad1daa80d65780c9c8d1464
deleted file mode 100644 (file)
index 389f58b..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/0a4d3fda02cdcb7adad1daa80d65780c9c8d1464 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/0ad812832efa33e086874fbf3496664d3f1b4dbe b/test/core/transport/chttp2/hpack_parser_corpus/0ad812832efa33e086874fbf3496664d3f1b4dbe
deleted file mode 100644 (file)
index e4ec780..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/0ad812832efa33e086874fbf3496664d3f1b4dbe and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/0c9996d4fef87bacd7a001e99a515b3ba3d5788f b/test/core/transport/chttp2/hpack_parser_corpus/0c9996d4fef87bacd7a001e99a515b3ba3d5788f
deleted file mode 100644 (file)
index 229a890..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/0c9996d4fef87bacd7a001e99a515b3ba3d5788f and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/0d6210208831fe55951af56cdeee3d54a91a5361 b/test/core/transport/chttp2/hpack_parser_corpus/0d6210208831fe55951af56cdeee3d54a91a5361
deleted file mode 100644 (file)
index 001fd0b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-f\13!(!! i[Ñ!å
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/0d784965b2262df7ed7a1eb57b92a718cc76bde8 b/test/core/transport/chttp2/hpack_parser_corpus/0d784965b2262df7ed7a1eb57b92a718cc76bde8
deleted file mode 100644 (file)
index 398077e..0000000
+++ /dev/null
@@ -1 +0,0 @@
\1fÊ!ð  c'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/0dc9e41eedf35ccedf4e2b0d230ead7c4d72fdb2 b/test/core/transport/chttp2/hpack_parser_corpus/0dc9e41eedf35ccedf4e2b0d230ead7c4d72fdb2
deleted file mode 100644 (file)
index 6019162..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/0dc9e41eedf35ccedf4e2b0d230ead7c4d72fdb2 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/0dd470c8939ed535de6b36f7b7bfb68aeace493e b/test/core/transport/chttp2/hpack_parser_corpus/0dd470c8939ed535de6b36f7b7bfb68aeace493e
deleted file mode 100644 (file)
index ca7cbd0..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8bc[)('-bh   *!!?¤\1fÛâ!\10\að{(-bi\n!    !       ðå\1fé\e;?Gí:[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/0e61e471fa6d3405daef4276ee00cf5fc189f378 b/test/core/transport/chttp2/hpack_parser_corpus/0e61e471fa6d3405daef4276ee00cf5fc189f378
deleted file mode 100644 (file)
index 203837b..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/0e61e471fa6d3405daef4276ee00cf5fc189f378 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/0e9196f951874edbb5ed098739ea5c8b6c0751c2 b/test/core/transport/chttp2/hpack_parser_corpus/0e9196f951874edbb5ed098739ea5c8b6c0751c2
deleted file mode 100644 (file)
index 8a3ef9e..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/0e9196f951874edbb5ed098739ea5c8b6c0751c2 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/11442d93a554b9e7f9ab02782bbf9443bf6e1ddc b/test/core/transport/chttp2/hpack_parser_corpus/11442d93a554b9e7f9ab02782bbf9443bf6e1ddc
deleted file mode 100644 (file)
index fdeb10a..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/11442d93a554b9e7f9ab02782bbf9443bf6e1ddc and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/11833b795d04eda5a3af56ef7b3c3a26a8ee3444 b/test/core/transport/chttp2/hpack_parser_corpus/11833b795d04eda5a3af56ef7b3c3a26a8ee3444
deleted file mode 100644 (file)
index 480a056..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8b)['(-cbin  !!?¤\1fÛð!\10\að{(-binð      !\      !å\1fé\e;?Gí:[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/141272316382b0f3e9ec841c735b84e7aa517c3e b/test/core/transport/chttp2/hpack_parser_corpus/141272316382b0f3e9ec841c735b84e7aa517c3e
deleted file mode 100644 (file)
index f706bd9..0000000
+++ /dev/null
@@ -1 +0,0 @@
-;?0c!(\aðK      ð[N!\\19!õG![(!!  !åGýA)(!)í!*åG\80¾ýA))Ù+©\8a
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/15ae43369798e48c396dfe7d53a21878b96e66c8 b/test/core/transport/chttp2/hpack_parser_corpus/15ae43369798e48c396dfe7d53a21878b96e66c8
deleted file mode 100644 (file)
index e4c217c..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/15ae43369798e48c396dfe7d53a21878b96e66c8 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/166bf1843c229d34a2880d234dd166c27bdc11fd b/test/core/transport/chttp2/hpack_parser_corpus/166bf1843c229d34a2880d234dd166c27bdc11fd
deleted file mode 100644 (file)
index 64fdd96..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8bí¤-[c'!)¤\10bi\a
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/179e8ac763b4051a953a38b6b3b1f1e1f6cc6c9e b/test/core/transport/chttp2/hpack_parser_corpus/179e8ac763b4051a953a38b6b3b1f1e1f6cc6c9e
deleted file mode 100644 (file)
index b576e9f..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/179e8ac763b4051a953a38b6b3b1f1e1f6cc6c9e and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/17faf0ba8a491a835d35977a9007b90ab7d30d2a b/test/core/transport/chttp2/hpack_parser_corpus/17faf0ba8a491a835d35977a9007b90ab7d30d2a
deleted file mode 100644 (file)
index 4830972..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/17faf0ba8a491a835d35977a9007b90ab7d30d2a and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/188f6cf2470e95b228341de305ef839b27f01a5c b/test/core/transport/chttp2/hpack_parser_corpus/188f6cf2470e95b228341de305ef839b27f01a5c
deleted file mode 100644 (file)
index 75aa45a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-;?0c\að[(!      ð[N!\   !åGý![(!!       !åGýA)(!)í!¼*)åGýA)(Ù;)\8a
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/1ab3e52adace335d02e2b5130eb4f7c918add7fd b/test/core/transport/chttp2/hpack_parser_corpus/1ab3e52adace335d02e2b5130eb4f7c918add7fd
deleted file mode 100644 (file)
index 914e443..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8bc[')(-'bin !!?¤\1fÛð!\10\að{(-banð      !\      !(å\1fé\e\96;?Gí:[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/1b5150514364e2c17f5a4edac1b7af99b936f55a b/test/core/transport/chttp2/hpack_parser_corpus/1b5150514364e2c17f5a4edac1b7af99b936f55a
deleted file mode 100644 (file)
index fc2f5a5..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/1b5150514364e2c17f5a4edac1b7af99b936f55a and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/1e8befb98cbaba059d6771abd1680e19484e7723 b/test/core/transport/chttp2/hpack_parser_corpus/1e8befb98cbaba059d6771abd1680e19484e7723
deleted file mode 100644 (file)
index 6ae0cd1..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/1e8befb98cbaba059d6771abd1680e19484e7723 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/1e9b962969c359bc2ff766704c8ca8e25f5eccfc b/test/core/transport/chttp2/hpack_parser_corpus/1e9b962969c359bc2ff766704c8ca8e25f5eccfc
deleted file mode 100644 (file)
index 970a912..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/1e9b962969c359bc2ff766704c8ca8e25f5eccfc and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/1f80af104acf41b912bf4a48fb938267e3718719 b/test/core/transport/chttp2/hpack_parser_corpus/1f80af104acf41b912bf4a48fb938267e3718719
deleted file mode 100644 (file)
index ae0ab51..0000000
+++ /dev/null
@@ -1 +0,0 @@
-?*®@\b:[\a\10ð\ 6øc  (!!\þ;ð\ 1!~      \1fÛåG¤\ f¤Ûðý!Ðam¤
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/1fcc4afd6f48e83d61ea74970df3ca9dcd8ec291 b/test/core/transport/chttp2/hpack_parser_corpus/1fcc4afd6f48e83d61ea74970df3ca9dcd8ec291
deleted file mode 100644 (file)
index 68b2d0e..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/1fcc4afd6f48e83d61ea74970df3ca9dcd8ec291 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/213a734ccdb813b18ad9f2dd99b7f9967ee1460b b/test/core/transport/chttp2/hpack_parser_corpus/213a734ccdb813b18ad9f2dd99b7f9967ee1460b
deleted file mode 100644 (file)
index 64ab9ba..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8b\99[)('-bin  !!?¤\1fÛð!\10\að{(-bi\n!     !       ðå\1fé\e;?Gí:[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/2151945f43991c27e123c45dc72b93752a47e65f b/test/core/transport/chttp2/hpack_parser_corpus/2151945f43991c27e123c45dc72b93752a47e65f
deleted file mode 100644 (file)
index 2715d4e..0000000
+++ /dev/null
@@ -1 +0,0 @@
-\10\að[(-bin!     ð(!\    !åGý:[(!'ð[(!!  ð[(*!   !å!ýGåGýA)(\13[(  !!å
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/21545d998c27a5a1572a89a552937752432b1c14 b/test/core/transport/chttp2/hpack_parser_corpus/21545d998c27a5a1572a89a552937752432b1c14
deleted file mode 100644 (file)
index ccb7d82..0000000
+++ /dev/null
@@ -1 +0,0 @@
-*¤\10\að¤\ f-bén'\1f\83'c)[ði(bn-!?¤\1fÛð!        ð(!\c
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/23c7443fa1ab713e7c34ec50222b1b8cceaedc65 b/test/core/transport/chttp2/hpack_parser_corpus/23c7443fa1ab713e7c34ec50222b1b8cceaedc65
deleted file mode 100644 (file)
index 2b22f5c..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8b-[c'()bin  !!?¤\1fÛð!;\að{(-binð      !\      !\98\1fé\e;?Gí:[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/2445bb2c6779712dc9e14c01fecb7103f8732858 b/test/core/transport/chttp2/hpack_parser_corpus/2445bb2c6779712dc9e14c01fecb7103f8732858
deleted file mode 100644 (file)
index 7112c43..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/2445bb2c6779712dc9e14c01fecb7103f8732858 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/244b0a20500e31d3c538418800db816b07f4d210 b/test/core/transport/chttp2/hpack_parser_corpus/244b0a20500e31d3c538418800db816b07f4d210
deleted file mode 100644 (file)
index f58d558..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8bc[)(-'bin  1!?¤\1fÛð!;\10\a*ð{(-binð    !\      !å\1fé\e;?Gí:[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/2461b9fa6b5bc4b6424dec5b9a18d4ec7c309112 b/test/core/transport/chttp2/hpack_parser_corpus/2461b9fa6b5bc4b6424dec5b9a18d4ec7c309112
deleted file mode 100644 (file)
index bbd1dae..0000000
+++ /dev/null
@@ -1 +0,0 @@
-?* ¤®@\b\10\a:ð[\ 6øc        (;þ!!\ð !~      \1fÛåGý!ðcm:'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/24ec2f3e17d3850564788f3fed17a5c586c44658 b/test/core/transport/chttp2/hpack_parser_corpus/24ec2f3e17d3850564788f3fed17a5c586c44658
deleted file mode 100644 (file)
index 6b6a742..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/24ec2f3e17d3850564788f3fed17a5c586c44658 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/2537b8d6b902b8dfc6e17f194cf7d05ddecf74cf b/test/core/transport/chttp2/hpack_parser_corpus/2537b8d6b902b8dfc6e17f194cf7d05ddecf74cf
deleted file mode 100644 (file)
index c0cee4f..0000000
+++ /dev/null
@@ -1 +0,0 @@
\1f!\83ÛðФ\1f!\83:[oððc
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/253ad01acea4b7038edc3f2a8c4a0c0f5c4dcd05 b/test/core/transport/chttp2/hpack_parser_corpus/253ad01acea4b7038edc3f2a8c4a0c0f5c4dcd05
deleted file mode 100644 (file)
index cf1dac3..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8bc[)(-'bin  !!?¤\1fÛð!\10\að{(-binð      !\      !å7é\e;?Gí([(!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/256d0bbdbed22f5867a6f503bf082011e61ee12b b/test/core/transport/chttp2/hpack_parser_corpus/256d0bbdbed22f5867a6f503bf082011e61ee12b
deleted file mode 100644 (file)
index c5d69b5..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/256d0bbdbed22f5867a6f503bf082011e61ee12b and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/26f0e88adbd8f8cdf778131a35b33ecf8711fa49 b/test/core/transport/chttp2/hpack_parser_corpus/26f0e88adbd8f8cdf778131a35b33ecf8711fa49
deleted file mode 100644 (file)
index 598576b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤p\83Ûðð¤\1f!\83Û')ðc
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/2e5dd8fb9d2a31fad9d681eda697d085b647b57c b/test/core/transport/chttp2/hpack_parser_corpus/2e5dd8fb9d2a31fad9d681eda697d085b647b57c
deleted file mode 100644 (file)
index 689d7f2..0000000
+++ /dev/null
@@ -1 +0,0 @@
\1f!\83ðñ¤\1f!\83Ûð±ðc
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/2fdfd2abf30c636ec8c841f1ac26594e25664f0f b/test/core/transport/chttp2/hpack_parser_corpus/2fdfd2abf30c636ec8c841f1ac26594e25664f0f
deleted file mode 100644 (file)
index 57727ac..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/2fdfd2abf30c636ec8c841f1ac26594e25664f0f and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/311dac5092e36134d3490f98aa4207425e0ee941 b/test/core/transport/chttp2/hpack_parser_corpus/311dac5092e36134d3490f98aa4207425e0ee941
deleted file mode 100644 (file)
index 6c900ea..0000000
+++ /dev/null
@@ -1 +0,0 @@
-\10\að[(! ð[(!\   !åGý:[(!!\13[(    !åGýA)(!)í!¸*!! )
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/320fe6224a5b691c0425e34b6b14e8c6fe9f9620 b/test/core/transport/chttp2/hpack_parser_corpus/320fe6224a5b691c0425e34b6b14e8c6fe9f9620
deleted file mode 100644 (file)
index b706187..0000000
+++ /dev/null
@@ -1 +0,0 @@
-* ¤®@\b\10\að[:\ 6øc 8;'þ!!\ð        !~      \1fÛDGý!ðkm'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/3255f1c7441a7150dc3c33022bfbe8c956c7b7b1 b/test/core/transport/chttp2/hpack_parser_corpus/3255f1c7441a7150dc3c33022bfbe8c956c7b7b1
deleted file mode 100644 (file)
index b1c0905..0000000
+++ /dev/null
@@ -1 +0,0 @@
-;?'c\að[(!      ð[N!\   !åEý!*(!!       !åGýA)(!)í!¼*)åGýI)(Ù;)\8a
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/33bc9db104eb72891fb096f34cbac191b3f9918d b/test/core/transport/chttp2/hpack_parser_corpus/33bc9db104eb72891fb096f34cbac191b3f9918d
deleted file mode 100644 (file)
index 21f59d4..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/33bc9db104eb72891fb096f34cbac191b3f9918d and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/342ff1db70a7616b4ef76c03a42802c6702c18cb b/test/core/transport/chttp2/hpack_parser_corpus/342ff1db70a7616b4ef76c03a42802c6702c18cb
deleted file mode 100644 (file)
index d692193..0000000
+++ /dev/null
@@ -1 +0,0 @@
-)\a:;!\9cÊ'ÒØ)*;}v)7IÏ!¤);\1e\96-M*±äâ!'d*Cu\18\ e«\91X$0\ e):ó*;:äÝ;;();:]ïæ@
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/344c011df992ccfc0ec682c14a1cb2d7959998c7 b/test/core/transport/chttp2/hpack_parser_corpus/344c011df992ccfc0ec682c14a1cb2d7959998c7
deleted file mode 100644 (file)
index 982af7b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-;¤¤\10\að¤\ f-bin\8bc*[)¤\ f¤¤(\10\að
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/35775efb9d0d68fa07987b9a84934389b528e436 b/test/core/transport/chttp2/hpack_parser_corpus/35775efb9d0d68fa07987b9a84934389b528e436
deleted file mode 100644 (file)
index cd20401..0000000
+++ /dev/null
@@ -1 +0,0 @@
-?¤\1fÓð!Üð       c'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/3650168db6fe115fb1e73eed4b76cd224d977d01 b/test/core/transport/chttp2/hpack_parser_corpus/3650168db6fe115fb1e73eed4b76cd224d977d01
deleted file mode 100644 (file)
index 99507d2..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8bc)(-'bin   !!?¤\1fÛð!\10\að{(-binð      !\      !å\1fé\e;?Gí:[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/38228bf98cdb50fd3fa830ba5a9d4c7399063dff b/test/core/transport/chttp2/hpack_parser_corpus/38228bf98cdb50fd3fa830ba5a9d4c7399063dff
deleted file mode 100644 (file)
index 6fdb662..0000000
+++ /dev/null
@@ -1 +0,0 @@
-* ¤®@\b\10\a:ð[(øc (;þ!!\  !cåGý:
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/38717bee901151b22a10beb12c6623ccc844d3c2 b/test/core/transport/chttp2/hpack_parser_corpus/38717bee901151b22a10beb12c6623ccc844d3c2
deleted file mode 100644 (file)
index 164b22a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-;?.\10\að[(-bin!  ð(!¤\   !åGý:[(!'ð[(!'c\að!      ðc[
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/3a4bb427a85bdc5bf66ac71db073c99e0dc9f881 b/test/core/transport/chttp2/hpack_parser_corpus/3a4bb427a85bdc5bf66ac71db073c99e0dc9f881
deleted file mode 100644 (file)
index 54400a3..0000000
+++ /dev/null
@@ -1 +0,0 @@
\10\að[('!       ð(!\    !åGý:(!'ð[(!!   ¤\1f[ð!ð  cð[(!!\1f !åGý!åGý'A)(\13[( '!!å
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/3ab48621d9b8f075369099a8ec7517bd23fd6e70 b/test/core/transport/chttp2/hpack_parser_corpus/3ab48621d9b8f075369099a8ec7517bd23fd6e70
deleted file mode 100644 (file)
index b243e62..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8bc[)(-'bin  A!!?¤\1fÛð!\10\ab{ði-(nð     !\      !å\1fé\e;?Gí!!:[((\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/3aec8d9311130dfbb6584fe6e619579c21992b5f b/test/core/transport/chttp2/hpack_parser_corpus/3aec8d9311130dfbb6584fe6e619579c21992b5f
deleted file mode 100644 (file)
index 345b8b2..0000000
+++ /dev/null
@@ -1 +0,0 @@
\ f¤Ûð¤\83
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/3b14837f22905dcb04f93aed2aa69bf95924fb9d b/test/core/transport/chttp2/hpack_parser_corpus/3b14837f22905dcb04f93aed2aa69bf95924fb9d
deleted file mode 100644 (file)
index dceaf04..0000000
+++ /dev/null
@@ -1 +0,0 @@
-f\13*!(\81!!       i[Ñ!
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/3be63c163805927e04fd7f84d96122c48240e601 b/test/core/transport/chttp2/hpack_parser_corpus/3be63c163805927e04fd7f84d96122c48240e601
deleted file mode 100644 (file)
index 1e49a89..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8b¤\1fÊ!ð      c)[''(
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/3bf2e349747c0f539181e0d4084a5fe506811a9e b/test/core/transport/chttp2/hpack_parser_corpus/3bf2e349747c0f539181e0d4084a5fe506811a9e
deleted file mode 100644 (file)
index f1e7a8e..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin?ð\8bc[)(-'bin        !!?
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/3c5af4d73e94d0e8ad5666b6acb340f929031e95 b/test/core/transport/chttp2/hpack_parser_corpus/3c5af4d73e94d0e8ad5666b6acb340f929031e95
deleted file mode 100644 (file)
index 6d2446a..0000000
+++ /dev/null
@@ -1 +0,0 @@
\1fc
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/3d2b25346a9671d83bd082d170a45eed739bae6b b/test/core/transport/chttp2/hpack_parser_corpus/3d2b25346a9671d83bd082d170a45eed739bae6b
deleted file mode 100644 (file)
index 98ff11f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8bc[\90)¤(*¤\a;[('¤ð!(-\ e        b\7fni'!!/¤\1f      Ûð!\1f(
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/3de7b860c3fba2bc55707fd6875dce276f2f249b b/test/core/transport/chttp2/hpack_parser_corpus/3de7b860c3fba2bc55707fd6875dce276f2f249b
deleted file mode 100644 (file)
index 7d875fe..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8bc[)(-'bin  !!?¤\1fÛð!\10\að{(-binð      !\      !å\1fé\e;?Gí:[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/3e2004ff9f40e398e0f41138a25a8b66e3d843d9 b/test/core/transport/chttp2/hpack_parser_corpus/3e2004ff9f40e398e0f41138a25a8b66e3d843d9
deleted file mode 100644 (file)
index ddf6c7c..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/3e2004ff9f40e398e0f41138a25a8b66e3d843d9 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/3f8983e457033cc85997c356935ba9c21460e86b b/test/core/transport/chttp2/hpack_parser_corpus/3f8983e457033cc85997c356935ba9c21460e86b
deleted file mode 100644 (file)
index 0350f5a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.:¤c
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/4105669086d83a20f8d991088553ba08202478cd b/test/core/transport/chttp2/hpack_parser_corpus/4105669086d83a20f8d991088553ba08202478cd
deleted file mode 100644 (file)
index c72af1a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8b¤\1fÛð!c[)('-bl      *!!?¤\1fÛâ!\10\aðð{(-bin\    c!'     !       ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/4180619316eef7912d1cf52ffe85897242e1ae88 b/test/core/transport/chttp2/hpack_parser_corpus/4180619316eef7912d1cf52ffe85897242e1ae88
deleted file mode 100644 (file)
index 2bfbdf5..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8bc[)(-'bin  #!?¤\1fÛð!\10\að{(-binð      !\      !å\1fé\e;?Gí:[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/420291d7139d9246de747739fd98102434a742dd b/test/core/transport/chttp2/hpack_parser_corpus/420291d7139d9246de747739fd98102434a742dd
deleted file mode 100644 (file)
index 24f6a24..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/420291d7139d9246de747739fd98102434a742dd and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/4256437fc5897c0cd5d755816e4e68c7be326849 b/test/core/transport/chttp2/hpack_parser_corpus/4256437fc5897c0cd5d755816e4e68c7be326849
deleted file mode 100644 (file)
index 6eebe10..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/4256437fc5897c0cd5d755816e4e68c7be326849 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/42b25a5413c536478a3e63da5adef4250babf2f4 b/test/core/transport/chttp2/hpack_parser_corpus/42b25a5413c536478a3e63da5adef4250babf2f4
deleted file mode 100644 (file)
index 4616caf..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/42b25a5413c536478a3e63da5adef4250babf2f4 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/42bef44ae751a45c671d9da5b1231d2ac747a48d b/test/core/transport/chttp2/hpack_parser_corpus/42bef44ae751a45c671d9da5b1231d2ac747a48d
deleted file mode 100644 (file)
index f9c4871..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/42bef44ae751a45c671d9da5b1231d2ac747a48d and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/438c3c9045c3cf7910aceec34f77b47a70ca4abd b/test/core/transport/chttp2/hpack_parser_corpus/438c3c9045c3cf7910aceec34f77b47a70ca4abd
deleted file mode 100644 (file)
index c000da7..0000000
+++ /dev/null
@@ -1 +0,0 @@
-\10\að[(-bin!     ð(!     !åGý:[(\b!'ð[(¤!
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/43af96b4f65ed0ace7236427f2f8833c4835989e b/test/core/transport/chttp2/hpack_parser_corpus/43af96b4f65ed0ace7236427f2f8833c4835989e
deleted file mode 100644 (file)
index 9fd52af..0000000
+++ /dev/null
@@ -1 +0,0 @@
\1f!\83Û*¤\10\að¤\ f-bin¤\ f¤ððÛðcc'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/44c6119bb91a452d6128ce0ea0d62938800779ea b/test/core/transport/chttp2/hpack_parser_corpus/44c6119bb91a452d6128ce0ea0d62938800779ea
deleted file mode 100644 (file)
index 3894ad5..0000000
+++ /dev/null
@@ -1 +0,0 @@
-;?0c!(\aðK      ð[N!\\19!åG![(!!  !åGýA)(!)í!*åG\80¾ýA)(Ù;\8a
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/46d595331689ae01d77aff387747a98ff3480096 b/test/core/transport/chttp2/hpack_parser_corpus/46d595331689ae01d77aff387747a98ff3480096
deleted file mode 100644 (file)
index acb7629..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/46d595331689ae01d77aff387747a98ff3480096 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/471a307b81dc37459087d41532741c5c9d7ba836 b/test/core/transport/chttp2/hpack_parser_corpus/471a307b81dc37459087d41532741c5c9d7ba836
deleted file mode 100644 (file)
index da07fc4..0000000
+++ /dev/null
@@ -1 +0,0 @@
\ e\7f
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/48900b4a5557530922ce45c15ad0d3b0a337520d b/test/core/transport/chttp2/hpack_parser_corpus/48900b4a5557530922ce45c15ad0d3b0a337520d
deleted file mode 100644 (file)
index 5d9d035..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/48900b4a5557530922ce45c15ad0d3b0a337520d and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/48bcce2c6487b18706ef0c609ca39c456215bac8 b/test/core/transport/chttp2/hpack_parser_corpus/48bcce2c6487b18706ef0c609ca39c456215bac8
deleted file mode 100644 (file)
index 49a5a11..0000000
+++ /dev/null
@@ -1 +0,0 @@
\1f
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/49027bbd3f3f3cafa315843c8fe8280f86985273 b/test/core/transport/chttp2/hpack_parser_corpus/49027bbd3f3f3cafa315843c8fe8280f86985273
deleted file mode 100644 (file)
index 5b390fd..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/49027bbd3f3f3cafa315843c8fe8280f86985273 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/499376c5e291da2f9c25999abf4960fab5a92ec8 b/test/core/transport/chttp2/hpack_parser_corpus/499376c5e291da2f9c25999abf4960fab5a92ec8
deleted file mode 100644 (file)
index 22cebb5..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/499376c5e291da2f9c25999abf4960fab5a92ec8 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/4a3b7ce0cdf217963a0b692769e5d6f4befe73b8 b/test/core/transport/chttp2/hpack_parser_corpus/4a3b7ce0cdf217963a0b692769e5d6f4befe73b8
deleted file mode 100644 (file)
index 6b93c82..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/4a3b7ce0cdf217963a0b692769e5d6f4befe73b8 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/4a3fdb96bc8c80f1992f0f72f963f84856cbade8 b/test/core/transport/chttp2/hpack_parser_corpus/4a3fdb96bc8c80f1992f0f72f963f84856cbade8
deleted file mode 100644 (file)
index 3bf6b6e..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/4a3fdb96bc8c80f1992f0f72f963f84856cbade8 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/4aae80e05793d7adb42a7e6e8a5283b677318777 b/test/core/transport/chttp2/hpack_parser_corpus/4aae80e05793d7adb42a7e6e8a5283b677318777
deleted file mode 100644 (file)
index fc8bdd1..0000000
+++ /dev/null
@@ -1 +0,0 @@
-(B¤\ 1:?ð\1fc
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/4c7a034d3a3b4f29d99caf021a0e9bbb89706c2e b/test/core/transport/chttp2/hpack_parser_corpus/4c7a034d3a3b4f29d99caf021a0e9bbb89706c2e
deleted file mode 100644 (file)
index 778ecf7..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/4c7a034d3a3b4f29d99caf021a0e9bbb89706c2e and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/4ce8a43fb17a075627160812ad26c25210d8a82d b/test/core/transport/chttp2/hpack_parser_corpus/4ce8a43fb17a075627160812ad26c25210d8a82d
deleted file mode 100644 (file)
index 3a3c61a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8bc)(-'*in   !!?¤\1fÛð!!\10\að{(-binð     !\H!\1fåé\e;?Gí:[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/5032a75a98cd14d4dab75c1c5e2cd981abb19dcf b/test/core/transport/chttp2/hpack_parser_corpus/5032a75a98cd14d4dab75c1c5e2cd981abb19dcf
deleted file mode 100644 (file)
index e5a06a1..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/5032a75a98cd14d4dab75c1c5e2cd981abb19dcf and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/50b3f4b6aed97f442496d27f3b4315a18ba76d5f b/test/core/transport/chttp2/hpack_parser_corpus/50b3f4b6aed97f442496d27f3b4315a18ba76d5f
deleted file mode 100644 (file)
index e2e8f9b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-;;?
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/51064b88a98658d48a0da7f1545c2d1293ad9538 b/test/core/transport/chttp2/hpack_parser_corpus/51064b88a98658d48a0da7f1545c2d1293ad9538
deleted file mode 100644 (file)
index 1b08af8..0000000
+++ /dev/null
@@ -1 +0,0 @@
-*¤\10\að¤\ f-bin¤\ f¤Û'(?¤\að;[('¤ð!   \1f(
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/51752f12d59fadaaa0dc72e6370612b84ee1555b b/test/core/transport/chttp2/hpack_parser_corpus/51752f12d59fadaaa0dc72e6370612b84ee1555b
deleted file mode 100644 (file)
index ebcc009..0000000
+++ /dev/null
@@ -1 +0,0 @@
-* ¤®@\b\10\a:ð[(øc (;þ!!\'!cåGý:
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/51eff6fcbfe1a51ceb3f5f2140c01eea89b4313d b/test/core/transport/chttp2/hpack_parser_corpus/51eff6fcbfe1a51ceb3f5f2140c01eea89b4313d
deleted file mode 100644 (file)
index b26118f..0000000
+++ /dev/null
@@ -1 +0,0 @@
\1f¤Ûðð\83cc'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/51f65f681cf3a1218d83ad58642c06deaea86210 b/test/core/transport/chttp2/hpack_parser_corpus/51f65f681cf3a1218d83ad58642c06deaea86210
deleted file mode 100644 (file)
index 103692a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-\10\að[(-bin¤-¤¤ð\a\10bin\8bc[)(-'bin¤\1f?!ð     Û#!\10\að{(\rbinð!  ð(      !!
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/521809903d36db80b1ccd707f354361f2bf05075 b/test/core/transport/chttp2/hpack_parser_corpus/521809903d36db80b1ccd707f354361f2bf05075
deleted file mode 100644 (file)
index 06858ed..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/521809903d36db80b1ccd707f354361f2bf05075 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/5278e3581c069624157fd9176eddf52c0e58df67 b/test/core/transport/chttp2/hpack_parser_corpus/5278e3581c069624157fd9176eddf52c0e58df67
deleted file mode 100644 (file)
index 8f3d4a9..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/5278e3581c069624157fd9176eddf52c0e58df67 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/52fe8f0e1fa270ea16f66c93f2ffab265ce059e8 b/test/core/transport/chttp2/hpack_parser_corpus/52fe8f0e1fa270ea16f66c93f2ffab265ce059e8
deleted file mode 100644 (file)
index fcec5d6..0000000
+++ /dev/null
@@ -1 +0,0 @@
-;?'c\að[(!      ð[N!\   bå3Gý!*(!!      BåGýA)(!)í!d*)åGýI)(Ù;)\8a
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/53de87ae94acdc8e58a369459c12a3240f1294fe b/test/core/transport/chttp2/hpack_parser_corpus/53de87ae94acdc8e58a369459c12a3240f1294fe
deleted file mode 100644 (file)
index aaada4f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-?* ¤®@\b\10ð:\a[\ 6øc        (;þ!!\ð !~      \1fÛåGý!ðcm:'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/54a2b3993c3483745f6314c870a038a8e58f97a7 b/test/core/transport/chttp2/hpack_parser_corpus/54a2b3993c3483745f6314c870a038a8e58f97a7
deleted file mode 100644 (file)
index ac9c813..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/54a2b3993c3483745f6314c870a038a8e58f97a7 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/55d60c2e5040a38be8ca41de63e137e3fef892a4 b/test/core/transport/chttp2/hpack_parser_corpus/55d60c2e5040a38be8ca41de63e137e3fef892a4
deleted file mode 100644 (file)
index c947224..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8bc[(*)? ¤®@\b\10\a:
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/5653c44a5b520bdf2bdc599b7966f1d7c44950b3 b/test/core/transport/chttp2/hpack_parser_corpus/5653c44a5b520bdf2bdc599b7966f1d7c44950b3
deleted file mode 100644 (file)
index 463f1a4..0000000
+++ /dev/null
@@ -1 +0,0 @@
\7f
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/5838b5a683229ebb6e6277e2810863e642b8afc2 b/test/core/transport/chttp2/hpack_parser_corpus/5838b5a683229ebb6e6277e2810863e642b8afc2
deleted file mode 100644 (file)
index 1bfc596..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/5838b5a683229ebb6e6277e2810863e642b8afc2 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/588d225784891ac88e30ac6eb5651d63fac34083 b/test/core/transport/chttp2/hpack_parser_corpus/588d225784891ac88e30ac6eb5651d63fac34083
deleted file mode 100644 (file)
index 48c1dfe..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8b!c[)(-'bin !!?¤\1fÛð!\10\að{(-binð      !\      !å\1fé\e;?Gí:[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/58d51c21a20b6549567a0ab8fee29d162dd3fc5a b/test/core/transport/chttp2/hpack_parser_corpus/58d51c21a20b6549567a0ab8fee29d162dd3fc5a
deleted file mode 100644 (file)
index e7e115f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8bc[)(;-''bin        !!?¤\1fÛð!\10\að{(-binð      !\      !å\1fé\e;:?íå[((!;!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/58f1036d8ff855841ec25b3c33e85a8fec0d94b7 b/test/core/transport/chttp2/hpack_parser_corpus/58f1036d8ff855841ec25b3c33e85a8fec0d94b7
deleted file mode 100644 (file)
index c1c4166..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8bc[)-'bin   1!?¤\1fÛð!;'\10\a*ð{(-binð   !\      !å\1fé\e;?Gí:[((!!Lð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/5a99df42fb7bbafa2d55714ee235b1c46776b2ad b/test/core/transport/chttp2/hpack_parser_corpus/5a99df42fb7bbafa2d55714ee235b1c46776b2ad
deleted file mode 100644 (file)
index 198c062..0000000
+++ /dev/null
@@ -1 +0,0 @@
\1f[ð!ð c'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/5b42793550699b2c015bed677cfcddc052f73513 b/test/core/transport/chttp2/hpack_parser_corpus/5b42793550699b2c015bed677cfcddc052f73513
deleted file mode 100644 (file)
index 144e68b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤p\83Ûðð¤\1f!\83Ûð)ðc
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/5b8ca72ba00231c38b19f582127e6a146eba4282 b/test/core/transport/chttp2/hpack_parser_corpus/5b8ca72ba00231c38b19f582127e6a146eba4282
deleted file mode 100644 (file)
index eb49d1d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-;?'c\að[(!      ð[N!\   !åGý!*(!        !ÔåGýA)(!)í!¼*)åGýI)(Ù;)\8a
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/5baa13dc95da05e7ba02bbe9583ea24517a29a1a b/test/core/transport/chttp2/hpack_parser_corpus/5baa13dc95da05e7ba02bbe9583ea24517a29a1a
deleted file mode 100644 (file)
index 4f5a887..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8b¤ð[c'!)¤\10bi\17
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/5bab61eb53176449e25c2c82f172b82cb13ffb9d b/test/core/transport/chttp2/hpack_parser_corpus/5bab61eb53176449e25c2c82f172b82cb13ffb9d
deleted file mode 100644 (file)
index 0d758c9..0000000
+++ /dev/null
@@ -1 +0,0 @@
-?
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/5c6f6b6f7f3e7b435f060abb73c20d2b773a7f56 b/test/core/transport/chttp2/hpack_parser_corpus/5c6f6b6f7f3e7b435f060abb73c20d2b773a7f56
deleted file mode 100644 (file)
index d8e3155..0000000
+++ /dev/null
@@ -1 +0,0 @@
-;?0c!(\aðK      ð[N!\\19!åG![(!!  !åGýA)(!)í!*åG\80¾A)(Ù;\8a
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/5c9fd9cc7100feaeead1e0e45201945a6e76fd85 b/test/core/transport/chttp2/hpack_parser_corpus/5c9fd9cc7100feaeead1e0e45201945a6e76fd85
deleted file mode 100644 (file)
index d38481c..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/5c9fd9cc7100feaeead1e0e45201945a6e76fd85 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/5ff49c9edc7361797a951585f3e180222c8dd95d b/test/core/transport/chttp2/hpack_parser_corpus/5ff49c9edc7361797a951585f3e180222c8dd95d
deleted file mode 100644 (file)
index f0ce5a2..0000000
+++ /dev/null
@@ -1 +0,0 @@
-?* ¤®@\b\10\a:ð[(øc        (;þ!!\ð !c      \1fåÛGý!ðcm:'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/6129954942e26c2a9ec071b6659675745613cf3c b/test/core/transport/chttp2/hpack_parser_corpus/6129954942e26c2a9ec071b6659675745613cf3c
deleted file mode 100644 (file)
index 1ae539b..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/6129954942e26c2a9ec071b6659675745613cf3c and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/61fa69b6b51b0ed91914fe48779173f8d26a1d54 b/test/core/transport/chttp2/hpack_parser_corpus/61fa69b6b51b0ed91914fe48779173f8d26a1d54
deleted file mode 100644 (file)
index 0759d5b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8bc[)(-'bin  ;!!?¤\1fÛð!\10\að{(-binð     !\      !å\1fé\e;?Gí[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/6362ac61cfb6e964aff78f3cd648475dfd5fd4e9 b/test/core/transport/chttp2/hpack_parser_corpus/6362ac61cfb6e964aff78f3cd648475dfd5fd4e9
deleted file mode 100644 (file)
index 06af54d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-;?'c\að[(!      ð[N!\   bå3Gý!*(!!      BåGýA)(!)í!¼*)åGýI)(Ù;)\8a
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/644deba51c79b6ebd470bd4367452941045d112a b/test/core/transport/chttp2/hpack_parser_corpus/644deba51c79b6ebd470bd4367452941045d112a
deleted file mode 100644 (file)
index 3357333..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/644deba51c79b6ebd470bd4367452941045d112a and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/64beae98e2276749b133e6368c9e0f19a79eba96 b/test/core/transport/chttp2/hpack_parser_corpus/64beae98e2276749b133e6368c9e0f19a79eba96
deleted file mode 100644 (file)
index 9aa7b9d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8bc[)¤(-\ e    b\7fni'!!/¤\1fÛð!
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/64d7add9192301fd878854dc96f9fa9053f03992 b/test/core/transport/chttp2/hpack_parser_corpus/64d7add9192301fd878854dc96f9fa9053f03992
deleted file mode 100644 (file)
index 1203eb1..0000000
+++ /dev/null
@@ -1 +0,0 @@
\1f!\83Ûððcc'_
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/65566df65e8f55428b6672cc351df414fa8f936c b/test/core/transport/chttp2/hpack_parser_corpus/65566df65e8f55428b6672cc351df414fa8f936c
deleted file mode 100644 (file)
index a273e99..0000000
+++ /dev/null
@@ -1 +0,0 @@
-'ð[(!! ð[(!!   !åGý!åGýA)(!)í!¼)Ù:;\87\8a*
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/65bb703af35d5afb824cd68c41d7a1aeb3848d35 b/test/core/transport/chttp2/hpack_parser_corpus/65bb703af35d5afb824cd68c41d7a1aeb3848d35
deleted file mode 100644 (file)
index 8ac4292..0000000
+++ /dev/null
@@ -1 +0,0 @@
-[ð!ð   '(![(!! !åGý!åGýA)(!)í!¼)Ù:;\87\8a*
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/66c537bf59cb3667c037b3517be3d31245c9da8a b/test/core/transport/chttp2/hpack_parser_corpus/66c537bf59cb3667c037b3517be3d31245c9da8a
deleted file mode 100644 (file)
index 07cf3ef..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8bc[)(-'bin)#!?¤\1fÛð!\10\að{(-binð       !\!å\1fé\e;?Gí:[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/66f576baeb0c9435a56eb7375dadc5b5d630ed87 b/test/core/transport/chttp2/hpack_parser_corpus/66f576baeb0c9435a56eb7375dadc5b5d630ed87
deleted file mode 100644 (file)
index c5a8cc6..0000000
+++ /dev/null
@@ -1 +0,0 @@
-?* ¤®P\b\10\a®\80¤\88:ð[\ 6øc    8;þ!!\ð !~(     \1fÛDGý!ðmc:c'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/67b4cec5183659aeae0f5bc71b3adf0542a11828 b/test/core/transport/chttp2/hpack_parser_corpus/67b4cec5183659aeae0f5bc71b3adf0542a11828
deleted file mode 100644 (file)
index 3ad7a92..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/67b4cec5183659aeae0f5bc71b3adf0542a11828 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/68c94721eda2f62481bff9f1d183df70498d0c5b b/test/core/transport/chttp2/hpack_parser_corpus/68c94721eda2f62481bff9f1d183df70498d0c5b
deleted file mode 100644 (file)
index cfe8f60..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-b!n\8b¤-[c'!)¤\10bi\a
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/68ee8169a65d58edb9fc1c752ea81dfec383203c b/test/core/transport/chttp2/hpack_parser_corpus/68ee8169a65d58edb9fc1c752ea81dfec383203c
deleted file mode 100644 (file)
index 2fb6e28..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8b()[c-'bin  !ðÛ¤\1f!\r?\10\að{(-binð      !\      !å\1fé\e;?Gí:[((#!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/6b203d49bbba6ee74def0d35c2266e06ad3c45d9 b/test/core/transport/chttp2/hpack_parser_corpus/6b203d49bbba6ee74def0d35c2266e06ad3c45d9
deleted file mode 100644 (file)
index bb540ad..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/6b203d49bbba6ee74def0d35c2266e06ad3c45d9 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/6d580f28d785c0bf87ac351a31a89289449feadb b/test/core/transport/chttp2/hpack_parser_corpus/6d580f28d785c0bf87ac351a31a89289449feadb
deleted file mode 100644 (file)
index 56c98a4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8bc[)¨-.'bi* !!(?¤\1fÛ!ð!\10\a
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/6f231dec759eb2105e09263d53e171de19a92c74 b/test/core/transport/chttp2/hpack_parser_corpus/6f231dec759eb2105e09263d53e171de19a92c74
deleted file mode 100644 (file)
index 9f2955b..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/6f231dec759eb2105e09263d53e171de19a92c74 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/70ff6621a09e4f641538cb1b27e8b382b2f56a94 b/test/core/transport/chttp2/hpack_parser_corpus/70ff6621a09e4f641538cb1b27e8b382b2f56a94
deleted file mode 100644 (file)
index cc3c4dd..0000000
+++ /dev/null
@@ -1 +0,0 @@
\1f!\83Û*¤\10\að¤\ f-bin¤\ f¦ððÛðcc'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/71981b55f27a1eb6274eda247048fa2c597f5004 b/test/core/transport/chttp2/hpack_parser_corpus/71981b55f27a1eb6274eda247048fa2c597f5004
deleted file mode 100644 (file)
index b57b2aa..0000000
+++ /dev/null
@@ -1 +0,0 @@
-;?'c\að[(!      ð[N!\   !åGý!*(!        !åGýA)(!!í!¼(*)åGýI)(Ù;)\8a
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/71c2b0bebf7f0e916e4ab7eb36d47ccca2b9101c b/test/core/transport/chttp2/hpack_parser_corpus/71c2b0bebf7f0e916e4ab7eb36d47ccca2b9101c
deleted file mode 100644 (file)
index 3a78289..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/71c2b0bebf7f0e916e4ab7eb36d47ccca2b9101c and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/74610e278a5b90aa12ce1beaf222c4306b02ed43 b/test/core/transport/chttp2/hpack_parser_corpus/74610e278a5b90aa12ce1beaf222c4306b02ed43
deleted file mode 100644 (file)
index e87f23e..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8bc[i¤(-\a\ e\7f'bin      !!?¤\1fÛð!
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/748ee9817eba56ec9938601a0e380c74bad4563f b/test/core/transport/chttp2/hpack_parser_corpus/748ee9817eba56ec9938601a0e380c74bad4563f
deleted file mode 100644 (file)
index d0a7c64..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8bc[)('-bin  !!?¤\1fÛð!\10\að{(-bi\n!     !       ðå\1fé\e;?Gí:[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/7727e3eeb2a48c46bf5a678c300ff8a38b8ffe3a b/test/core/transport/chttp2/hpack_parser_corpus/7727e3eeb2a48c46bf5a678c300ff8a38b8ffe3a
deleted file mode 100644 (file)
index 5b7c52d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-?* ¤®P\b\10\a®\80¤\88:ð[\ 6øc    8;þ!!\ð !~(     \1fÛDGý!ðcmc:c'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/78176d80c1d74c4b1b820d386ae483ac4d1d92b7 b/test/core/transport/chttp2/hpack_parser_corpus/78176d80c1d74c4b1b820d386ae483ac4d1d92b7
deleted file mode 100644 (file)
index e9dc85e..0000000
+++ /dev/null
@@ -1 +0,0 @@
-(?¤\1f\9bð!        c
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/789abb571563a6795220046f76b7cf0ade90743c b/test/core/transport/chttp2/hpack_parser_corpus/789abb571563a6795220046f76b7cf0ade90743c
deleted file mode 100644 (file)
index c901c4c..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8bc[)(-.'bin !!?¤\1fÛð!\10\a
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/78f5ff40e5554aa9c31b45f79a7ae9699f93e7fd b/test/core/transport/chttp2/hpack_parser_corpus/78f5ff40e5554aa9c31b45f79a7ae9699f93e7fd
deleted file mode 100644 (file)
index 74d4392..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/78f5ff40e5554aa9c31b45f79a7ae9699f93e7fd and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/7a28fc2e9c72d51d29e87eed63ed405c9779b5e1 b/test/core/transport/chttp2/hpack_parser_corpus/7a28fc2e9c72d51d29e87eed63ed405c9779b5e1
deleted file mode 100644 (file)
index ad5695b..0000000
+++ /dev/null
@@ -1 +0,0 @@
\ f¤Ûðð\83\80cc'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/7a42083be21dce7f96edef1f3b3b2fea0bcaeb3f b/test/core/transport/chttp2/hpack_parser_corpus/7a42083be21dce7f96edef1f3b3b2fea0bcaeb3f
deleted file mode 100644 (file)
index 53ba7aa..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8bc[)(-'bin  «!?¤\1fÛð!;\10\a*ð{(-binð    !\      !å\1fé\e;?Gí:[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/7a51275b11ecb1efec9251390531681c8d6f2481 b/test/core/transport/chttp2/hpack_parser_corpus/7a51275b11ecb1efec9251390531681c8d6f2481
deleted file mode 100644 (file)
index 5529b96..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/7a51275b11ecb1efec9251390531681c8d6f2481 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/7b9682cd7a3984698f6eac034c59c0f91b4fb83d b/test/core/transport/chttp2/hpack_parser_corpus/7b9682cd7a3984698f6eac034c59c0f91b4fb83d
deleted file mode 100644 (file)
index bf413be..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/7b9682cd7a3984698f6eac034c59c0f91b4fb83d and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/7ba7239a29d6183960e3986abc8f19cfb548b905 b/test/core/transport/chttp2/hpack_parser_corpus/7ba7239a29d6183960e3986abc8f19cfb548b905
deleted file mode 100644 (file)
index 8985a07..0000000
+++ /dev/null
@@ -1 +0,0 @@
\1f!\83Ûððcc'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/7d3b3d5f23d0ede9f7e5dbd1115db58c8a54a213 b/test/core/transport/chttp2/hpack_parser_corpus/7d3b3d5f23d0ede9f7e5dbd1115db58c8a54a213
deleted file mode 100644 (file)
index 291a16d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8bc[)¨-'bin  '!!?¤Ûð!\10\að{;?0c!(-b(inð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/7ff3b6239b04479a9caf67f45b2d0c619f712815 b/test/core/transport/chttp2/hpack_parser_corpus/7ff3b6239b04479a9caf67f45b2d0c619f712815
deleted file mode 100644 (file)
index 2b2b727..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/7ff3b6239b04479a9caf67f45b2d0c619f712815 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/8035c81c95dedfc27c3649064f98f49e3e72c21f b/test/core/transport/chttp2/hpack_parser_corpus/8035c81c95dedfc27c3649064f98f49e3e72c21f
deleted file mode 100644 (file)
index bf77deb..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/8035c81c95dedfc27c3649064f98f49e3e72c21f and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/804e1052842ce4d44b9c775ade2b18fcb8ce7bcf b/test/core/transport/chttp2/hpack_parser_corpus/804e1052842ce4d44b9c775ade2b18fcb8ce7bcf
deleted file mode 100644 (file)
index cda608f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\1f-bin\8b¤-[c'!)¦\10bi
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/80514b85933ea9bdd3462595f949c5af24409b87 b/test/core/transport/chttp2/hpack_parser_corpus/80514b85933ea9bdd3462595f949c5af24409b87
deleted file mode 100644 (file)
index 003033b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8bc[)¤'\ f(­¤Ûð'ð(\83cin !!
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/8057c32b8bd28a5ec2105d62f2abe8cf69c9f5fc b/test/core/transport/chttp2/hpack_parser_corpus/8057c32b8bd28a5ec2105d62f2abe8cf69c9f5fc
deleted file mode 100644 (file)
index a384358..0000000
+++ /dev/null
@@ -1 +0,0 @@
-f\13!(!!c'       i[Ñ!ð[(!!       ð[(!!   !åHý![(!!       !åGýåA)(!)í!¼*)åGýA)(Ù!)\8a
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/806a3bd4e078d91adeacedfd3e47ef8ae229244a b/test/core/transport/chttp2/hpack_parser_corpus/806a3bd4e078d91adeacedfd3e47ef8ae229244a
deleted file mode 100644 (file)
index 2760e03..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8bc[):¤\ f(-¤Ûð'ðb\83cin !!
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/8090444f98218e65ff9594789ff22bbea3c0497c b/test/core/transport/chttp2/hpack_parser_corpus/8090444f98218e65ff9594789ff22bbea3c0497c
deleted file mode 100644 (file)
index a9663a0..0000000
+++ /dev/null
@@ -1 +0,0 @@
\1fðcª  Ûð'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/80e516692955d5f224706f268e247858858e16d8 b/test/core/transport/chttp2/hpack_parser_corpus/80e516692955d5f224706f268e247858858e16d8
deleted file mode 100644 (file)
index 6a23452..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/80e516692955d5f224706f268e247858858e16d8 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/810a1372fa97380265f5529c5043ae96f007f5bb b/test/core/transport/chttp2/hpack_parser_corpus/810a1372fa97380265f5529c5043ae96f007f5bb
deleted file mode 100644 (file)
index d5a3aee..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/810a1372fa97380265f5529c5043ae96f007f5bb and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/8127597d3c146b2a89579e44daef9d03a0f941ec b/test/core/transport/chttp2/hpack_parser_corpus/8127597d3c146b2a89579e44daef9d03a0f941ec
deleted file mode 100644 (file)
index 0f7035b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-*@®¤ \b\10\a:ð[(øc (;þ!!\  !cå¤Gý:\7f
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/82ed571f8922caa572d13b4cc9b5c5fabafaade9 b/test/core/transport/chttp2/hpack_parser_corpus/82ed571f8922caa572d13b4cc9b5c5fabafaade9
deleted file mode 100644 (file)
index 42b9598..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8bc[)(-'bin  !!?¤!\1fðÛ\10\að{(öbénð      !       \!å\1fé\e;?Gí:[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/8328e86178800f87a3bf6f80749984f45b0cd0e8 b/test/core/transport/chttp2/hpack_parser_corpus/8328e86178800f87a3bf6f80749984f45b0cd0e8
deleted file mode 100644 (file)
index 8fe5277..0000000
+++ /dev/null
@@ -1 +0,0 @@
-(?*¤!\að¤\ fheme\83¤\a'\a('¤ð!c       
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/84441efd7d8bdb0ce2fac28f218d3d5d4d77f1d4 b/test/core/transport/chttp2/hpack_parser_corpus/84441efd7d8bdb0ce2fac28f218d3d5d4d77f1d4
deleted file mode 100644 (file)
index 20ab849..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/84441efd7d8bdb0ce2fac28f218d3d5d4d77f1d4 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/84cbf70f45a64d5a01d1c96367b6d6160134f1ad b/test/core/transport/chttp2/hpack_parser_corpus/84cbf70f45a64d5a01d1c96367b6d6160134f1ad
deleted file mode 100644 (file)
index 65f4c69..0000000
+++ /dev/null
@@ -1 +0,0 @@
-;?0c!(\aðK      ð[N!\\19!õG![(!!  !åGýA)(!)í!*åG\80¾ýA)(Ù+)\8a
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/85eb0f4502a51e646dab4ae08eabd90613cdf8e1 b/test/core/transport/chttp2/hpack_parser_corpus/85eb0f4502a51e646dab4ae08eabd90613cdf8e1
deleted file mode 100644 (file)
index 4ede523..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/85eb0f4502a51e646dab4ae08eabd90613cdf8e1 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/86080f33e4eae21b37863c253ce61eaa13021a97 b/test/core/transport/chttp2/hpack_parser_corpus/86080f33e4eae21b37863c253ce61eaa13021a97
deleted file mode 100644 (file)
index 8f5c7a8..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/86080f33e4eae21b37863c253ce61eaa13021a97 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/862e3ccf601ee0f7fbd8b23e6811fd50485a118f b/test/core/transport/chttp2/hpack_parser_corpus/862e3ccf601ee0f7fbd8b23e6811fd50485a118f
deleted file mode 100644 (file)
index bae722a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8bc[)(-'bin  !!?O\1fÛð!\10\að{(-b \ni!ð   !å\1fé\e;?Gí[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/86bae059b18af8ae263e5ae0022b67da0cfc0fbe b/test/core/transport/chttp2/hpack_parser_corpus/86bae059b18af8ae263e5ae0022b67da0cfc0fbe
deleted file mode 100644 (file)
index fc8f2ae..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤ÿ
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/870f9cc4bd89c6c04c6a51ceae1efa8634627cd6 b/test/core/transport/chttp2/hpack_parser_corpus/870f9cc4bd89c6c04c6a51ceae1efa8634627cd6
deleted file mode 100644 (file)
index 7d35cc8..0000000
+++ /dev/null
@@ -1 +0,0 @@
-?*®@\b:[\a\10ð\ 6øc  (!!\þ;ð\ 1!~      \1fÛåGý!Ðam:'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/8762a523cdb78d2344d553fa52a229bd63c44e51 b/test/core/transport/chttp2/hpack_parser_corpus/8762a523cdb78d2344d553fa52a229bd63c44e51
deleted file mode 100644 (file)
index e92f115..0000000
+++ /dev/null
@@ -1 +0,0 @@
-\1f¤
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/894211571f9153c3c2ea4102541dac69be8aaa9c b/test/core/transport/chttp2/hpack_parser_corpus/894211571f9153c3c2ea4102541dac69be8aaa9c
deleted file mode 100644 (file)
index ded03ee..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/894211571f9153c3c2ea4102541dac69be8aaa9c and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/894e9b7832c52acb04bfa994ef53c7105d8db206 b/test/core/transport/chttp2/hpack_parser_corpus/894e9b7832c52acb04bfa994ef53c7105d8db206
deleted file mode 100644 (file)
index 218bfa3..0000000
+++ /dev/null
@@ -1 +0,0 @@
-?*®@\b:[\a\10ð\ 6øc  (!!\þ;ð\ 1!~      \1fÛåGý!Ðam'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/8b0e12978b8e2eecf62346e438e47d0993845693 b/test/core/transport/chttp2/hpack_parser_corpus/8b0e12978b8e2eecf62346e438e47d0993845693
deleted file mode 100644 (file)
index 4cb5926..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8bc[)( ?¤-'bin       !!?¤:
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/8b3fa0bd4f289eff6a04a5205e04baaeafbdf637 b/test/core/transport/chttp2/hpack_parser_corpus/8b3fa0bd4f289eff6a04a5205e04baaeafbdf637
deleted file mode 100644 (file)
index 573daa7..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8b()[c-'bin  !!?¤\1fÛð!\10\að{(-binð      !\      !å\1fé\e;?Gí:[((#!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/8d1deedd1e463f8c95129a6f839c380a7c83ab04 b/test/core/transport/chttp2/hpack_parser_corpus/8d1deedd1e463f8c95129a6f839c380a7c83ab04
deleted file mode 100644 (file)
index 11e43ba..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8bc*[)¤\ f(-¤Ûð'ðb\83cin !!
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/8d1e029bd72381e382c87e61b4c5a9741d80d644 b/test/core/transport/chttp2/hpack_parser_corpus/8d1e029bd72381e382c87e61b4c5a9741d80d644
deleted file mode 100644 (file)
index a4a1f3c..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/8d1e029bd72381e382c87e61b4c5a9741d80d644 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/8dd1983889b6632228d4897c365a1e6124d101e1 b/test/core/transport/chttp2/hpack_parser_corpus/8dd1983889b6632228d4897c365a1e6124d101e1
deleted file mode 100644 (file)
index 3a98220..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/8dd1983889b6632228d4897c365a1e6124d101e1 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/8dfc2183691385432f92957cff0b2538e5a0ebfa b/test/core/transport/chttp2/hpack_parser_corpus/8dfc2183691385432f92957cff0b2538e5a0ebfa
deleted file mode 100644 (file)
index c7552c3..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/8dfc2183691385432f92957cff0b2538e5a0ebfa and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/8eb9b86b4f0aa79b8ef84b44e1fb03094e7bb426 b/test/core/transport/chttp2/hpack_parser_corpus/8eb9b86b4f0aa79b8ef84b44e1fb03094e7bb426
deleted file mode 100644 (file)
index 5c87575..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/8eb9b86b4f0aa79b8ef84b44e1fb03094e7bb426 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/8ec540c36da3814e93da765bf2ff0825b59c1bd0 b/test/core/transport/chttp2/hpack_parser_corpus/8ec540c36da3814e93da765bf2ff0825b59c1bd0
deleted file mode 100644 (file)
index 828e12f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-binc[)(-'bin   !!?¤\1fÛð!\10\að{(-binð      !\      !å\9fé\e;?Gí:[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/8f1bec32f4b8e64062f5405a096543e61d771076 b/test/core/transport/chttp2/hpack_parser_corpus/8f1bec32f4b8e64062f5405a096543e61d771076
deleted file mode 100644 (file)
index 24e9fc4..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/8f1bec32f4b8e64062f5405a096543e61d771076 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/8f3e48c49d0794909f6e8e61e5a4312edf484c33 b/test/core/transport/chttp2/hpack_parser_corpus/8f3e48c49d0794909f6e8e61e5a4312edf484c33
deleted file mode 100644 (file)
index 3378b55..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/8f3e48c49d0794909f6e8e61e5a4312edf484c33 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/8fbbf3c0eaa25b64d0a97a8ee08006539e649199 b/test/core/transport/chttp2/hpack_parser_corpus/8fbbf3c0eaa25b64d0a97a8ee08006539e649199
deleted file mode 100644 (file)
index 532ee69..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤c
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/907d0021d42d0fdc867fd02d3609cdce13c8a055 b/test/core/transport/chttp2/hpack_parser_corpus/907d0021d42d0fdc867fd02d3609cdce13c8a055
deleted file mode 100644 (file)
index 4bff0ff..0000000
+++ /dev/null
@@ -1 +0,0 @@
\að[(\80¤-bdin!
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/919511c217a3427c22cad4a71aae31a6cd47b193 b/test/core/transport/chttp2/hpack_parser_corpus/919511c217a3427c22cad4a71aae31a6cd47b193
deleted file mode 100644 (file)
index fcaef32..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/919511c217a3427c22cad4a71aae31a6cd47b193 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/9267c81c3283da8193c198de05e05fa30631a453 b/test/core/transport/chttp2/hpack_parser_corpus/9267c81c3283da8193c198de05e05fa30631a453
deleted file mode 100644 (file)
index 34951fe..0000000
+++ /dev/null
@@ -1 +0,0 @@
-?* ¤®@\b\10\a:ð[\ 6øc        (!!\þ;ð !~      \1fÛåGý!Ðcm:'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/92e80997a4237d76f10b70dae2870b7255c97435 b/test/core/transport/chttp2/hpack_parser_corpus/92e80997a4237d76f10b70dae2870b7255c97435
deleted file mode 100644 (file)
index 0e176e3..0000000
+++ /dev/null
@@ -1 +0,0 @@
-?* ¤®@\b\10\a:ð[(nc        (;þ!;\ð !c      \1fÛåGý!ðcm:'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/935322db76f5d4c74c2dc68fc4631915b8e24323 b/test/core/transport/chttp2/hpack_parser_corpus/935322db76f5d4c74c2dc68fc4631915b8e24323
deleted file mode 100644 (file)
index cbf58cf..0000000
+++ /dev/null
@@ -1 +0,0 @@
\ f¤Ûð¤1\83
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/939f2627ef6263d0176566de267ff3eb910e6a60 b/test/core/transport/chttp2/hpack_parser_corpus/939f2627ef6263d0176566de267ff3eb910e6a60
deleted file mode 100644 (file)
index 0efdf47..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8b)['(=cbin  a!?¤\1fÛð!\10\að{(-bin¤ð\1f¤Û
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/94adea6a0d9a44bee6f5e88adcee57be9e9e3597 b/test/core/transport/chttp2/hpack_parser_corpus/94adea6a0d9a44bee6f5e88adcee57be9e9e3597
deleted file mode 100644 (file)
index 78e29a4..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/94adea6a0d9a44bee6f5e88adcee57be9e9e3597 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/94dcbe0d3352bd9b230096b8dce9c6d8d63f9d51 b/test/core/transport/chttp2/hpack_parser_corpus/94dcbe0d3352bd9b230096b8dce9c6d8d63f9d51
deleted file mode 100644 (file)
index 449c0da..0000000
+++ /dev/null
@@ -1 +0,0 @@
-(?8¤¤¤\1f\1fÛ!×Ûð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/95dad738f60e3e5eb0f1cdafd91ad461f4418e8f b/test/core/transport/chttp2/hpack_parser_corpus/95dad738f60e3e5eb0f1cdafd91ad461f4418e8f
deleted file mode 100644 (file)
index 38402df..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/95dad738f60e3e5eb0f1cdafd91ad461f4418e8f and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/960c0a21c9e5c1a61b93b34da3189b0de1c264df b/test/core/transport/chttp2/hpack_parser_corpus/960c0a21c9e5c1a61b93b34da3189b0de1c264df
deleted file mode 100644 (file)
index 9265e2f..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/960c0a21c9e5c1a61b93b34da3189b0de1c264df and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/96903512b1f1dec08206123f024b62d0e31cd4dc b/test/core/transport/chttp2/hpack_parser_corpus/96903512b1f1dec08206123f024b62d0e31cd4dc
deleted file mode 100644 (file)
index b8c71bd..0000000
+++ /dev/null
@@ -1 +0,0 @@
-\10c\að[(!        ð[(!\   !åGý![(!!       !åGýA)(!)í!¸*)åGýA)(Ù;)\8a
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/96a89c005e8d9992e34cc149b0be096ad0051446 b/test/core/transport/chttp2/hpack_parser_corpus/96a89c005e8d9992e34cc149b0be096ad0051446
deleted file mode 100644 (file)
index 2ac2d76..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/96a89c005e8d9992e34cc149b0be096ad0051446 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/97db8a66dd513eea47a5a25115508f4e59984854 b/test/core/transport/chttp2/hpack_parser_corpus/97db8a66dd513eea47a5a25115508f4e59984854
deleted file mode 100644 (file)
index 941f553..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤(\1e* ¤®@\b\10\a[(?¤\a;:('¤ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/98f2cb84ad89550cf56ee54e11f1448ae7287247 b/test/core/transport/chttp2/hpack_parser_corpus/98f2cb84ad89550cf56ee54e11f1448ae7287247
deleted file mode 100644 (file)
index 252816d..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/98f2cb84ad89550cf56ee54e11f1448ae7287247 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/993497422a59b7f9f0f6db8c867339b5c9e4c978 b/test/core/transport/chttp2/hpack_parser_corpus/993497422a59b7f9f0f6db8c867339b5c9e4c978
deleted file mode 100644 (file)
index d1028f3..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\a¤ð\ f-bin\8bc[)Î\10@\b®?*¤ \a:
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/999821e3750a7f2c9db663d2d100b4404c225040 b/test/core/transport/chttp2/hpack_parser_corpus/999821e3750a7f2c9db663d2d100b4404c225040
deleted file mode 100644 (file)
index eafc765..0000000
+++ /dev/null
@@ -1 +0,0 @@
-\13[(!!  ![ð!å
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/99b2ed83be40cab431d1940e8de2dc3ebfe9352f b/test/core/transport/chttp2/hpack_parser_corpus/99b2ed83be40cab431d1940e8de2dc3ebfe9352f
deleted file mode 100644 (file)
index 168a215..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/99b2ed83be40cab431d1940e8de2dc3ebfe9352f and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/99e888b7372b29256dbefd476855ff73584cc00f b/test/core/transport/chttp2/hpack_parser_corpus/99e888b7372b29256dbefd476855ff73584cc00f
deleted file mode 100644 (file)
index 5173bb4..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/99e888b7372b29256dbefd476855ff73584cc00f and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/9b18087deb3cfafa1b964aa65d8ee980bc61404e b/test/core/transport/chttp2/hpack_parser_corpus/9b18087deb3cfafa1b964aa65d8ee980bc61404e
deleted file mode 100644 (file)
index 838d0d2..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/9b18087deb3cfafa1b964aa65d8ee980bc61404e and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/9b3c745ea3e313909a228a07b49aae110b02ae4a b/test/core/transport/chttp2/hpack_parser_corpus/9b3c745ea3e313909a228a07b49aae110b02ae4a
deleted file mode 100644 (file)
index b7855d7..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤p\83Ûðð¤\1f!\83[ðc
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/9be1ce0ba77758928ff5e9c45139b1624cbe9c2d b/test/core/transport/chttp2/hpack_parser_corpus/9be1ce0ba77758928ff5e9c45139b1624cbe9c2d
deleted file mode 100644 (file)
index f10b76b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8b¤-[c'!)¤\10bi\a
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/9c703141efd69eb8f32a58133c8035fb585e0f4c b/test/core/transport/chttp2/hpack_parser_corpus/9c703141efd69eb8f32a58133c8035fb585e0f4c
deleted file mode 100644 (file)
index e1d551a..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/9c703141efd69eb8f32a58133c8035fb585e0f4c and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/9c7f77981677499f0426a0ffb5cb79d5fe55dcb2 b/test/core/transport/chttp2/hpack_parser_corpus/9c7f77981677499f0426a0ffb5cb79d5fe55dcb2
deleted file mode 100644 (file)
index dec67b6..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8bc[)(-'b)n  #!?¤\1fÛð!\10\að{(-binð      !\      !å\1fé\e;?Gí:[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/9ca59e6cadaa5be9af30dfe5620d1bcd70f442e5 b/test/core/transport/chttp2/hpack_parser_corpus/9ca59e6cadaa5be9af30dfe5620d1bcd70f442e5
deleted file mode 100644 (file)
index 0855a4d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8bc*[)¤\13[((¤-\ fÛð'ðb!\83cin     !!      !![ð!å
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/9d139835d91474e8d8361d65698a31b8b38c4f7b b/test/core/transport/chttp2/hpack_parser_corpus/9d139835d91474e8d8361d65698a31b8b38c4f7b
deleted file mode 100644 (file)
index 4781557..0000000
+++ /dev/null
@@ -1 +0,0 @@
-?¤\1fÛð!ð¤¤\90\að   c'¤\ f-bin\8b¤ò[c'!)¤\10bi\17
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/9e2179564a99e96e179c96f28802a0a2759b581c b/test/core/transport/chttp2/hpack_parser_corpus/9e2179564a99e96e179c96f28802a0a2759b581c
deleted file mode 100644 (file)
index c60f729..0000000
+++ /dev/null
@@ -1 +0,0 @@
-(* ¤®@\b\10\a[(?¤\a;[('¤ð!        \1f(øc    (;þ!!\  !cråGý:
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/9e56bb3b68d2e2617cb2d2f0f3941f7fc832e462 b/test/core/transport/chttp2/hpack_parser_corpus/9e56bb3b68d2e2617cb2d2f0f3941f7fc832e462
deleted file mode 100644 (file)
index ac44166..0000000
+++ /dev/null
@@ -1 +0,0 @@
-c'ð[(!!        ð[(!!   !åGý![(!!       !åGýA)(!)í!¼*)åGýA)(Ù!)\8a
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/9f318b2c2ff9cf4615bd06ba13bdd086b4ad08c6 b/test/core/transport/chttp2/hpack_parser_corpus/9f318b2c2ff9cf4615bd06ba13bdd086b4ad08c6
deleted file mode 100644 (file)
index 40a6ab5..0000000
+++ /dev/null
@@ -1 +0,0 @@
-?* ¤®@\b\18\a:ð[\ 6øc        (!!\þ;ð\ 1!~      \1fÛåGý!Ðim:'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/9f8d90b1480989fc46ea2f1c66cf687638994587 b/test/core/transport/chttp2/hpack_parser_corpus/9f8d90b1480989fc46ea2f1c66cf687638994587
deleted file mode 100644 (file)
index 6c655aa..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/9f8d90b1480989fc46ea2f1c66cf687638994587 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/a09db5715f0bc3879a0e18e4db5a6b5640b254a3 b/test/core/transport/chttp2/hpack_parser_corpus/a09db5715f0bc3879a0e18e4db5a6b5640b254a3
deleted file mode 100644 (file)
index 7fff586..0000000
+++ /dev/null
@@ -1 +0,0 @@
-;?0c!(\aòK      ð[NÔ\   !åG![(!!        !åGýA)(!)í!*å¼G\80ýA)(Ù;)\8a
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/a0c59a090818bca29d76ccf9843f7e2faf330ddf b/test/core/transport/chttp2/hpack_parser_corpus/a0c59a090818bca29d76ccf9843f7e2faf330ddf
deleted file mode 100644 (file)
index d6a316b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-*¤\10\að¤\ f-bin¤\ f¤Ûð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/a1cf10478e5e01a0d951c743a3dd45aa5fc409f2 b/test/core/transport/chttp2/hpack_parser_corpus/a1cf10478e5e01a0d951c743a3dd45aa5fc409f2
deleted file mode 100644 (file)
index 45cce54..0000000
+++ /dev/null
@@ -1 +0,0 @@
\1f!\83ßðð¤\1f!\83Û¤\1fä
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/a22c0f03f8c005a4612a9dcbcd6a643334c35d2f b/test/core/transport/chttp2/hpack_parser_corpus/a22c0f03f8c005a4612a9dcbcd6a643334c35d2f
deleted file mode 100644 (file)
index 6a28aa1..0000000
+++ /dev/null
@@ -1 +0,0 @@
-;?0c!(\aðK      ð[NÔ\   !åG![(!!        !åGýA)(!)í!*å¼G\80ýA)(Ù;)\8a
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/a3154b8ed26b3461f2b091c732da00b63ce8bed3 b/test/core/transport/chttp2/hpack_parser_corpus/a3154b8ed26b3461f2b091c732da00b63ce8bed3
deleted file mode 100644 (file)
index cba4e44..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8b¤-[c'ù)¤\10bi\a
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/a84a1ed1a24e753a27adfd3ba806f06fc44f899f b/test/core/transport/chttp2/hpack_parser_corpus/a84a1ed1a24e753a27adfd3ba806f06fc44f899f
deleted file mode 100644 (file)
index ba1a5db..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/a84a1ed1a24e753a27adfd3ba806f06fc44f899f and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/a871e7ce66afd4f57702cd1299de06cd08995561 b/test/core/transport/chttp2/hpack_parser_corpus/a871e7ce66afd4f57702cd1299de06cd08995561
deleted file mode 100644 (file)
index 59295ac..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/a871e7ce66afd4f57702cd1299de06cd08995561 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/a8dc736ea964586b7dcbf2bc065ec4675d1daba3 b/test/core/transport/chttp2/hpack_parser_corpus/a8dc736ea964586b7dcbf2bc065ec4675d1daba3
deleted file mode 100644 (file)
index 039af40..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8bc[)¤(-\ e\7f'bin       !!?¤\1fÛð!
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/a91a835836c72217824f0b63491d9b623130502a b/test/core/transport/chttp2/hpack_parser_corpus/a91a835836c72217824f0b63491d9b623130502a
deleted file mode 100644 (file)
index a61dd28..0000000
+++ /dev/null
@@ -1 +0,0 @@
-?* ¤®@\b\10\a:ð[(øc        (;þ!!\ð !c      \1fÛåGý!ðcm:'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/ab97c1f6033dc7d96f69b9e1461fd594c16f4ebf b/test/core/transport/chttp2/hpack_parser_corpus/ab97c1f6033dc7d96f69b9e1461fd594c16f4ebf
deleted file mode 100644 (file)
index e359cb7..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/ab97c1f6033dc7d96f69b9e1461fd594c16f4ebf and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/ac8a8c23acd8c290a11dc7828f7f397957fa6400 b/test/core/transport/chttp2/hpack_parser_corpus/ac8a8c23acd8c290a11dc7828f7f397957fa6400
deleted file mode 100644 (file)
index 39985fb..0000000
+++ /dev/null
@@ -1 +0,0 @@
-?* ¦®@\b\10\a:ð[\ 6øc        (!!\þ;ð\ 1!~      \1fGý!Ðim:'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/ac94b2788f5252f9e2e8502c7c75e04bef4c0b76 b/test/core/transport/chttp2/hpack_parser_corpus/ac94b2788f5252f9e2e8502c7c75e04bef4c0b76
deleted file mode 100644 (file)
index 71cc57a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤?
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/ad03b4f58470c43db6593a35be48989486d754f9 b/test/core/transport/chttp2/hpack_parser_corpus/ad03b4f58470c43db6593a35be48989486d754f9
deleted file mode 100644 (file)
index 7691001..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤p\83Ûðð¤\1f!\83Ûððc
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/af417c83e831a96fda1bdde99a1af6509ef2df3d b/test/core/transport/chttp2/hpack_parser_corpus/af417c83e831a96fda1bdde99a1af6509ef2df3d
deleted file mode 100644 (file)
index 3217162..0000000
+++ /dev/null
@@ -1 +0,0 @@
-(?¤\1f¤¤\1fÛÛð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/affd292cd2ce3306b4651cc7ec0ec0524cbbae3d b/test/core/transport/chttp2/hpack_parser_corpus/affd292cd2ce3306b4651cc7ec0ec0524cbbae3d
deleted file mode 100644 (file)
index 4ea1b6b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f£bin\8bäc[ò)'-bi. *)!?¤\1fÛâ\10\að{(-bi\n!     !       ðå\1fé\e;?Gí:[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/b0587e6e319f4b56d877e7ed46bc7da9b1e7249c b/test/core/transport/chttp2/hpack_parser_corpus/b0587e6e319f4b56d877e7ed46bc7da9b1e7249c
deleted file mode 100644 (file)
index 3261071..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤)\a:;!\9cÊ'ÒØ)*;}v)7IÏ!¤);\1e\96-M*±äâ!'d*Cu\18\ e«\91X$0\ e):ó*;:äÝ;;();:]ïæ@
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/b166aa66b5b3ad178bc38aee5768226c8adc082f b/test/core/transport/chttp2/hpack_parser_corpus/b166aa66b5b3ad178bc38aee5768226c8adc082f
deleted file mode 100644 (file)
index 691e650..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤p\83Ûð¤\1f!\83Ûðc
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/b1ade0571262c6e5f1d72f6d25ebb513d2055bc9 b/test/core/transport/chttp2/hpack_parser_corpus/b1ade0571262c6e5f1d72f6d25ebb513d2055bc9
deleted file mode 100644 (file)
index cc073f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8bc[)('-bi.  *!!?¤\1fÛâ!\10\að{(-bi\n!    !       ðå\1fé\e;?Gí:[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/b244c690157ff21d073940ef8c77d1898f37cf8e b/test/core/transport/chttp2/hpack_parser_corpus/b244c690157ff21d073940ef8c77d1898f37cf8e
deleted file mode 100644 (file)
index e93670e..0000000
+++ /dev/null
@@ -1 +0,0 @@
\1f¤Ûðð cc'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/b523091ee4f17d20f51f9b5cf82293465cf61780 b/test/core/transport/chttp2/hpack_parser_corpus/b523091ee4f17d20f51f9b5cf82293465cf61780
deleted file mode 100644 (file)
index 6d66d37..0000000
+++ /dev/null
@@ -1 +0,0 @@
-?* ¤®@\b\10ð:\a[\ 6øc        (;þ!!\ð #~      \1fÛårý!ðcm:'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/b7d4d49ac2c530eb8444a449feb689ee50fd210d b/test/core/transport/chttp2/hpack_parser_corpus/b7d4d49ac2c530eb8444a449feb689ee50fd210d
deleted file mode 100644 (file)
index d2cbccc..0000000
+++ /dev/null
@@ -1 +0,0 @@
-;?'c\að[(!      ð[N!\   #åGý!*(!!       !åGýA)(!)í!¼*)åGýI)(Ù;)\8a
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/b855c161121bfa29c6fb22d3c0236fae4af6984e b/test/core/transport/chttp2/hpack_parser_corpus/b855c161121bfa29c6fb22d3c0236fae4af6984e
deleted file mode 100644 (file)
index 2a4856a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-;?0c!(\aðK      ð[N!\\19;åG![(!!  !åGýA)(!)í!*åG\80¾A)(Ù;\8a
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/bc4263a92952d56168b354f723eaa43a33cd0b35 b/test/core/transport/chttp2/hpack_parser_corpus/bc4263a92952d56168b354f723eaa43a33cd0b35
deleted file mode 100644 (file)
index d62e767..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/bc4263a92952d56168b354f723eaa43a33cd0b35 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/bcaa71abf23b2e5130e0cc464755fe769bf4aaa7 b/test/core/transport/chttp2/hpack_parser_corpus/bcaa71abf23b2e5130e0cc464755fe769bf4aaa7
deleted file mode 100644 (file)
index 81d87fa..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8b\89c[)¤(-\ e\7f'bin      !!?¤\1fÛð!
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/bcf4684ce097faa7e9d99b6e93cc2de24f57aee3 b/test/core/transport/chttp2/hpack_parser_corpus/bcf4684ce097faa7e9d99b6e93cc2de24f57aee3
deleted file mode 100644 (file)
index 3c7fb6e..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/bcf4684ce097faa7e9d99b6e93cc2de24f57aee3 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/bdca6504d2ee7925f62e176355bb481344772075 b/test/core/transport/chttp2/hpack_parser_corpus/bdca6504d2ee7925f62e176355bb481344772075
deleted file mode 100644 (file)
index de4be31..0000000
+++ /dev/null
@@ -1 +0,0 @@
-;?'c\að[(!      ð[N!\   !åGý!*(!!       !åGýA)(!)í!¼*)åGýI)(Ù;)\8a
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/beb208fd8675ba7de2ecb12998d2d628d579ca7c b/test/core/transport/chttp2/hpack_parser_corpus/beb208fd8675ba7de2ecb12998d2d628d579ca7c
deleted file mode 100644 (file)
index 704e797..0000000
+++ /dev/null
@@ -1 +0,0 @@
-?* ¤®@\b\10\a:ð[\ 6øc        8;þ!!\ð !~      \1fÛDGý!ðcm:'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/bf0c98689ab81fc32787023300caf9a4175583dc b/test/core/transport/chttp2/hpack_parser_corpus/bf0c98689ab81fc32787023300caf9a4175583dc
deleted file mode 100644 (file)
index 4f0cbfb..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/bf0c98689ab81fc32787023300caf9a4175583dc and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/bf479e97b39b697e715663de6a1e78dd58d64122 b/test/core/transport/chttp2/hpack_parser_corpus/bf479e97b39b697e715663de6a1e78dd58d64122
deleted file mode 100644 (file)
index fb6b7bd..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8bc*[)¤(¤-\ fÛð'ðb\83cin !!
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/bf826c96be94d1b42eea0666f7239cc5f699a375 b/test/core/transport/chttp2/hpack_parser_corpus/bf826c96be94d1b42eea0666f7239cc5f699a375
deleted file mode 100644 (file)
index cb679b9..0000000
+++ /dev/null
@@ -1 +0,0 @@
-\10\að[(-bin¤¤\10\að¤\ f-bin\8bc[)(-'bin !!?¤\1fÛð!\10\að{(-binð!     ð(      !!
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/c17650d19ae4a48abb36739c83d8979453f5705f b/test/core/transport/chttp2/hpack_parser_corpus/c17650d19ae4a48abb36739c83d8979453f5705f
deleted file mode 100644 (file)
index 482d7db..0000000
+++ /dev/null
@@ -1 +0,0 @@
-;?0c!(\aðK      ð[N!\   !åG![(!!        !åGýA)(!)í!*å¼G\80ýA)(Ù;)\8a
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/c1e5307d88feda2c3b15fc221cba92bcf41622bf b/test/core/transport/chttp2/hpack_parser_corpus/c1e5307d88feda2c3b15fc221cba92bcf41622bf
deleted file mode 100644 (file)
index 6553242..0000000
+++ /dev/null
@@ -1 +0,0 @@
-(?*¤\10\að¤\ f-bin\83¤\a;[('¤ð!c       
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/c249f408c552a0408eab3fe1d1cbeca95cd537c1 b/test/core/transport/chttp2/hpack_parser_corpus/c249f408c552a0408eab3fe1d1cbeca95cd537c1
deleted file mode 100644 (file)
index 52f518b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8bc[)(-b¤¤\10\að¤\ f-bin\8bc[)('-bi.        *!!?¤\1fÛâ
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/c26b460aebc9082c519539069f7e060042989696 b/test/core/transport/chttp2/hpack_parser_corpus/c26b460aebc9082c519539069f7e060042989696
deleted file mode 100644 (file)
index 7c9ca45..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8bc[)(-'bni  !%?¤\1fÛð!\10\að{(-binð      !\!å\1fé\e;?G[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/c2eae71daad0d3561ab4d09b8b85372b8d790bc1 b/test/core/transport/chttp2/hpack_parser_corpus/c2eae71daad0d3561ab4d09b8b85372b8d790bc1
deleted file mode 100644 (file)
index 120b74b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-;?0c!'\aðK      ð[N!\\19!åG![(!!  !åGýA)(!)í!*åG\80¾A)(Ù;\8a
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/c37fda8d02e99132a1de99f959596c784ab8a53c b/test/core/transport/chttp2/hpack_parser_corpus/c37fda8d02e99132a1de99f959596c784ab8a53c
deleted file mode 100644 (file)
index ced68eb..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/c37fda8d02e99132a1de99f959596c784ab8a53c and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/c4836760377a7091fb20f4afa9c712875792b9a7 b/test/core/transport/chttp2/hpack_parser_corpus/c4836760377a7091fb20f4afa9c712875792b9a7
deleted file mode 100644 (file)
index 2d3d63a..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/c4836760377a7091fb20f4afa9c712875792b9a7 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/c48caad597176404f776d532d4baf9faf7655ee2 b/test/core/transport/chttp2/hpack_parser_corpus/c48caad597176404f776d532d4baf9faf7655ee2
deleted file mode 100644 (file)
index 2c7912f..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/c48caad597176404f776d532d4baf9faf7655ee2 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/c4eff0f59986fc5ab09d5bd95f394292f2882659 b/test/core/transport/chttp2/hpack_parser_corpus/c4eff0f59986fc5ab09d5bd95f394292f2882659
deleted file mode 100644 (file)
index 5b704f8..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin)c[)-'bin   1¤¤\10!?¤\1fÛð!\a
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/c5fc2086d167c8c3a7d9ec778db69c5fa14a59fe b/test/core/transport/chttp2/hpack_parser_corpus/c5fc2086d167c8c3a7d9ec778db69c5fa14a59fe
deleted file mode 100644 (file)
index 3e28333..0000000
+++ /dev/null
@@ -1 +0,0 @@
-?* ¤®@\b\18\a:ð_\ 6øc        (!!\þ;ð\ 1!~      !\1fÛåGý!Ð;m:'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/c600877ce547166eb1b9d83afbe128d98767f8a3 b/test/core/transport/chttp2/hpack_parser_corpus/c600877ce547166eb1b9d83afbe128d98767f8a3
deleted file mode 100644 (file)
index 7e26216..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\83c)-bi      (n'!!?¤\1fÛ!ð\10\að{(-binð   !\      !å\1fé\e;?Gí:[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/c6a98fdaf6de78e59e1a149a43f3e42222d650b7 b/test/core/transport/chttp2/hpack_parser_corpus/c6a98fdaf6de78e59e1a149a43f3e42222d650b7
deleted file mode 100644 (file)
index efcad33..0000000
+++ /dev/null
@@ -1 +0,0 @@
-?* ¬®@\b\10ð:\a[\ 6øc        (;þ!\!ð !~      \1fÛ-binåGý!ðcm:'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/c8d22f7fb4f37f2d8cc7953fa2d599d38d899aec b/test/core/transport/chttp2/hpack_parser_corpus/c8d22f7fb4f37f2d8cc7953fa2d599d38d899aec
deleted file mode 100644 (file)
index 104ab47..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/c8d22f7fb4f37f2d8cc7953fa2d599d38d899aec and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/c90951c19b24bac84296e3ec32cdeafe99e99cfb b/test/core/transport/chttp2/hpack_parser_corpus/c90951c19b24bac84296e3ec32cdeafe99e99cfb
deleted file mode 100644 (file)
index d43c094..0000000
+++ /dev/null
@@ -1 +0,0 @@
-?* ¤®@\b\10\a:ð[\ 6øc        (!!\þ;ð\ 1!~      \1fÛåGý!Ðam:'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/c95ff2a172626efb50e94aa6781feba609820076 b/test/core/transport/chttp2/hpack_parser_corpus/c95ff2a172626efb50e94aa6781feba609820076
deleted file mode 100644 (file)
index 0a104c7..0000000
+++ /dev/null
@@ -1 +0,0 @@
-\10\að[(-bin!     ð(!\    !åGý¤\1f!:[(!'ð[(!!       ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/ca6c557afb9c571de62e9b65ca6469a6133760da b/test/core/transport/chttp2/hpack_parser_corpus/ca6c557afb9c571de62e9b65ca6469a6133760da
deleted file mode 100644 (file)
index 4d95be6..0000000
+++ /dev/null
@@ -1 +0,0 @@
-?!cð   \1fß}'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/cb2d0fb23f66c968af2e80d59f71d4c1aed96fbd b/test/core/transport/chttp2/hpack_parser_corpus/cb2d0fb23f66c968af2e80d59f71d4c1aed96fbd
deleted file mode 100644 (file)
index 1cbb336..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8bc[)¤\ f(-¤Ûð'ðb\83cin  !!
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/cc60a642cc2037ad3c459a57381b8f65d8d7aa35 b/test/core/transport/chttp2/hpack_parser_corpus/cc60a642cc2037ad3c459a57381b8f65d8d7aa35
deleted file mode 100644 (file)
index b2d3847..0000000
+++ /dev/null
@@ -1 +0,0 @@
-?* ¤®@\b\10\a:ð[\ 6øã        4;þ!!\ð !~      \1fÛDGýðcm:'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/ccd3b8aa26c52f6d9c607c26ebdf621142aff745 b/test/core/transport/chttp2/hpack_parser_corpus/ccd3b8aa26c52f6d9c607c26ebdf621142aff745
deleted file mode 100644 (file)
index fa972a4..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/ccd3b8aa26c52f6d9c607c26ebdf621142aff745 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/ccdfd1354997eb117bd76b75440a7e4ff20bf564 b/test/core/transport/chttp2/hpack_parser_corpus/ccdfd1354997eb117bd76b75440a7e4ff20bf564
deleted file mode 100644 (file)
index 718a9e5..0000000
+++ /dev/null
@@ -1 +0,0 @@
-+¤¤\10\að¤\ f-bin\v9c[)(-b¤¤\10\að¤
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/cd7a7b8f08c189e95ae3e2ea44b9015000e823f3 b/test/core/transport/chttp2/hpack_parser_corpus/cd7a7b8f08c189e95ae3e2ea44b9015000e823f3
deleted file mode 100644 (file)
index 4d63ccb..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8b#Z)¤(-¤\ eb¤ \10\að¤\ f-bin?ð\8bc[)(-\7fni''bin!!     !/¤!?\1f'ð!
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/ce05678d812a5f8ae8e115938410116ce9169456 b/test/core/transport/chttp2/hpack_parser_corpus/ce05678d812a5f8ae8e115938410116ce9169456
deleted file mode 100644 (file)
index 6caf38a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-;?0c!(\aðK      ð[N!\\19!åG![(!!  !åGýA)(!)í!*åG\80¾ýA)(Ù;)\8a
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/ce6b642b81373f05baa2a6fe6e9d5d1387046285 b/test/core/transport/chttp2/hpack_parser_corpus/ce6b642b81373f05baa2a6fe6e9d5d1387046285
deleted file mode 100644 (file)
index a311265..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/ce6b642b81373f05baa2a6fe6e9d5d1387046285 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/cf84d06e4dddb997a79a41f9b6122bf620bbdb4b b/test/core/transport/chttp2/hpack_parser_corpus/cf84d06e4dddb997a79a41f9b6122bf620bbdb4b
deleted file mode 100644 (file)
index 350c941..0000000
+++ /dev/null
@@ -1 +0,0 @@
-;?'c\að[)!      ð[N!Ü   bå4Gý!*(!!      BåGýA)!)í!¼*)åGýI)(Ù;)\8a
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/cfbcc3e8cd65aa8b654688145ade34b8789468a6 b/test/core/transport/chttp2/hpack_parser_corpus/cfbcc3e8cd65aa8b654688145ade34b8789468a6
deleted file mode 100644 (file)
index 4d7ff3e..0000000
+++ /dev/null
@@ -1 +0,0 @@
-'?0c!(\aðK      ð[N!\\19!åG![(!!  !åG)Aý(!)å!*åG\80A¾)(Ù;;\8a
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/clusterfuzz-testcase-5298216461402112 b/test/core/transport/chttp2/hpack_parser_corpus/clusterfuzz-testcase-5298216461402112
deleted file mode 100644 (file)
index 04d48d6..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/clusterfuzz-testcase-5298216461402112 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/clusterfuzz-testcase-minimized-4857057310146560 b/test/core/transport/chttp2/hpack_parser_corpus/clusterfuzz-testcase-minimized-4857057310146560
deleted file mode 100644 (file)
index 1692480..0000000
+++ /dev/null
@@ -1 +0,0 @@
-D\ 5:path
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/crash-5ac3e1ea7764cfb6383629574262f82dc7b3cada b/test/core/transport/chttp2/hpack_parser_corpus/crash-5ac3e1ea7764cfb6383629574262f82dc7b3cada
deleted file mode 100644 (file)
index 44984f3..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/crash-5ac3e1ea7764cfb6383629574262f82dc7b3cada and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/d000502f32ca5620d7745f39ff6be3b547e26a6d b/test/core/transport/chttp2/hpack_parser_corpus/d000502f32ca5620d7745f39ff6be3b547e26a6d
deleted file mode 100644 (file)
index a422dc4..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/d000502f32ca5620d7745f39ff6be3b547e26a6d and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/d131f83ee73450ff45565d0c638be7d8beeb30d9 b/test/core/transport/chttp2/hpack_parser_corpus/d131f83ee73450ff45565d0c638be7d8beeb30d9
deleted file mode 100644 (file)
index c0404ba..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8b) ¤['(=cbin        a!?ä\1fÛð!\10ð{(-bin¤ð\1f¤
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/d1c7ae01a81a122c2fd7c5d8debcae7566e9ee2f b/test/core/transport/chttp2/hpack_parser_corpus/d1c7ae01a81a122c2fd7c5d8debcae7566e9ee2f
deleted file mode 100644 (file)
index 4547f5a..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/d1c7ae01a81a122c2fd7c5d8debcae7566e9ee2f and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/d2817b89d7aaa7fa880c077b1a67168ec2f4f0f7 b/test/core/transport/chttp2/hpack_parser_corpus/d2817b89d7aaa7fa880c077b1a67168ec2f4f0f7
deleted file mode 100644 (file)
index 272be74..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/d2817b89d7aaa7fa880c077b1a67168ec2f4f0f7 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/d3ccd7039dd34baef465c4b78baa7a30312a8f07 b/test/core/transport/chttp2/hpack_parser_corpus/d3ccd7039dd34baef465c4b78baa7a30312a8f07
deleted file mode 100644 (file)
index e9cb788..0000000
+++ /dev/null
@@ -1 +0,0 @@
-?* ¤®@\b\10\a:ð[(øc        (3þ!!\ð !c      (ÛåGý!ðcm:'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/d4cfaf3b59b22b654d7af80ee6715ce5015bfdc0 b/test/core/transport/chttp2/hpack_parser_corpus/d4cfaf3b59b22b654d7af80ee6715ce5015bfdc0
deleted file mode 100644 (file)
index be8b804..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/d4cfaf3b59b22b654d7af80ee6715ce5015bfdc0 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/d5670827c8e8d4c95ac0f738c0790c19916c0336 b/test/core/transport/chttp2/hpack_parser_corpus/d5670827c8e8d4c95ac0f738c0790c19916c0336
deleted file mode 100644 (file)
index 8c906c5..0000000
+++ /dev/null
@@ -1 +0,0 @@
-*¤\10\að¤\ f-bin¤\ f¤¤¸\10\að\ f¤-Û'(?¤\að;[(
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/d59d7e94863f1ed89cacfbaabf7bc59946036c8f b/test/core/transport/chttp2/hpack_parser_corpus/d59d7e94863f1ed89cacfbaabf7bc59946036c8f
deleted file mode 100644 (file)
index ed929eb..0000000
+++ /dev/null
@@ -1 +0,0 @@
-*¤\10\að¤\ f-bin\83(\1f\80'[ði(bn-!? 
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/d6d8b478e6d13945f7a6f7d27f424ff57ca12f7f b/test/core/transport/chttp2/hpack_parser_corpus/d6d8b478e6d13945f7a6f7d27f424ff57ca12f7f
deleted file mode 100644 (file)
index ace84af..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/d6d8b478e6d13945f7a6f7d27f424ff57ca12f7f and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/d76d0c7f24ae3cc3f530d5306b8dcc15290c7ff2 b/test/core/transport/chttp2/hpack_parser_corpus/d76d0c7f24ae3cc3f530d5306b8dcc15290c7ff2
deleted file mode 100644 (file)
index 81cc0fc..0000000
+++ /dev/null
@@ -1 +0,0 @@
\1fä\97
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/d8b15e9e555ad9900ba4be8cc9f87bef75725b24 b/test/core/transport/chttp2/hpack_parser_corpus/d8b15e9e555ad9900ba4be8cc9f87bef75725b24
deleted file mode 100644 (file)
index 9ed0c80..0000000
+++ /dev/null
@@ -1 +0,0 @@
-?* ¤®@\b\10\a:ð[\ 6øc        (!!\þ;ð\ 1!~      \1fÛåGý!Ðim:'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/d9748abd540810c2449c3dd39a0ebb62754e520f b/test/core/transport/chttp2/hpack_parser_corpus/d9748abd540810c2449c3dd39a0ebb62754e520f
deleted file mode 100644 (file)
index e55083f..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/d9748abd540810c2449c3dd39a0ebb62754e520f and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/da9fc821f0c1e00728b139b36269bc3d21c0a8cc b/test/core/transport/chttp2/hpack_parser_corpus/da9fc821f0c1e00728b139b36269bc3d21c0a8cc
deleted file mode 100644 (file)
index e752baf..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ frbin\8bc[)(-'bin  !!?¤\1fÛð!\10\að{(-binð      !\      !å\1fé\e;?G[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/dcd1bd94ad97b4e67fd7e12ff1bf7c039eb17f66 b/test/core/transport/chttp2/hpack_parser_corpus/dcd1bd94ad97b4e67fd7e12ff1bf7c039eb17f66
deleted file mode 100644 (file)
index cb9bf61..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤Û)\80ðð\8ecc'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/dd3ba9b139e13324fc76cd62af84b00ca8b87205 b/test/core/transport/chttp2/hpack_parser_corpus/dd3ba9b139e13324fc76cd62af84b00ca8b87205
deleted file mode 100644 (file)
index bad7f60..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤p\83Ûðð¤\1f!\83ËTð*
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/de0a9dce0ea4e4bfdcb13f788ae728bf979fed25 b/test/core/transport/chttp2/hpack_parser_corpus/de0a9dce0ea4e4bfdcb13f788ae728bf979fed25
deleted file mode 100644 (file)
index 5a2a027..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8b#Z)¤(\1f-¤¤\10\a        \ ebð¤\ f-bin?ð\8bc[)(-\7fni''bin!;     !/¤!?\1f'ð!
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/deb6f9a930d9b31586ede19fd8fd3caae0e5b1f2 b/test/core/transport/chttp2/hpack_parser_corpus/deb6f9a930d9b31586ede19fd8fd3caae0e5b1f2
deleted file mode 100644 (file)
index 1ceb559..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8b)['(;-cbin !!?¤\1fÛð!\10\að{(-binð      !\      !å\1fé\e;?Gí:[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/dee95e0280b70681eddfb68e3b418126c5661e18 b/test/core/transport/chttp2/hpack_parser_corpus/dee95e0280b70681eddfb68e3b418126c5661e18
deleted file mode 100644 (file)
index 713d178..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/dee95e0280b70681eddfb68e3b418126c5661e18 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/df01203edfa2dfe9e108ddde786ae48235624fef b/test/core/transport/chttp2/hpack_parser_corpus/df01203edfa2dfe9e108ddde786ae48235624fef
deleted file mode 100644 (file)
index a4520fb..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/df01203edfa2dfe9e108ddde786ae48235624fef and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/df0adbe2523508e9afb42a58d98c2657710d6033 b/test/core/transport/chttp2/hpack_parser_corpus/df0adbe2523508e9afb42a58d98c2657710d6033
deleted file mode 100644 (file)
index 10b7a9f..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/df0adbe2523508e9afb42a58d98c2657710d6033 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/e05fcba1b22f658c8bd6f3c330b2b3c9faebf977 b/test/core/transport/chttp2/hpack_parser_corpus/e05fcba1b22f658c8bd6f3c330b2b3c9faebf977
deleted file mode 100644 (file)
index 6e31189..0000000
+++ /dev/null
@@ -1 +0,0 @@
-\10\að[(-`in¤¤\10\að¤\ f-Þin\8bc[)(:'bin !!)?¤\1fÛð!\10\að{(:-binð!   ð(      !!
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/e145caa75d73e3d819a9cb4b6217f1f53112f3f8 b/test/core/transport/chttp2/hpack_parser_corpus/e145caa75d73e3d819a9cb4b6217f1f53112f3f8
deleted file mode 100644 (file)
index df57477..0000000
+++ /dev/null
@@ -1 +0,0 @@
\1f!\83ßð¤\1f!\83Û¤\10\að¤\1f¤\ f-bin\83c[-'bä:nð      !?¤\1fÛð!(!\ð     c
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/e1d86c0094657386197d191855b5645ac1dd5936 b/test/core/transport/chttp2/hpack_parser_corpus/e1d86c0094657386197d191855b5645ac1dd5936
deleted file mode 100644 (file)
index eb157d3..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/e1d86c0094657386197d191855b5645ac1dd5936 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/e25adf8de44f5978d00b7e8c52aee89c5cd1fe93 b/test/core/transport/chttp2/hpack_parser_corpus/e25adf8de44f5978d00b7e8c52aee89c5cd1fe93
deleted file mode 100644 (file)
index bc92a9f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-?¤\1fÛð!ð        c'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/e29f05162e3d96d5549f96aa4a54c868535b2847 b/test/core/transport/chttp2/hpack_parser_corpus/e29f05162e3d96d5549f96aa4a54c868535b2847
deleted file mode 100644 (file)
index d00c6b4..0000000
+++ /dev/null
@@ -1 +0,0 @@
\ f¤Ûðð\83cc'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/e3a970ac8636d29da3ded328b876ed3550cb3209 b/test/core/transport/chttp2/hpack_parser_corpus/e3a970ac8636d29da3ded328b876ed3550cb3209
deleted file mode 100644 (file)
index c989830..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8b-[c*()bin  !!?¤\1fÛð!;\að{(-binð      !\      !*\1fé\e;?Gí:[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/e3cfdc862187b4ec28bd4fb2ced5094bb5b09909 b/test/core/transport/chttp2/hpack_parser_corpus/e3cfdc862187b4ec28bd4fb2ced5094bb5b09909
deleted file mode 100644 (file)
index 9296f0e..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/e3cfdc862187b4ec28bd4fb2ced5094bb5b09909 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/e4ce52007d001806fc9368b62c124dfc56e8471c b/test/core/transport/chttp2/hpack_parser_corpus/e4ce52007d001806fc9368b62c124dfc56e8471c
deleted file mode 100644 (file)
index 34de7ad..0000000
+++ /dev/null
@@ -1 +0,0 @@
-)\a:;!\9cÊ'ÒØ)*;}v-7IÏ!¤)\e\1e\96-M*±äâ!'d*Cu\18\ e«X$0\ e):ó*;:äÝ;;();:]ïæ@
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/e52173f0bc3325629046e85e2dc41acc6ba7d1c3 b/test/core/transport/chttp2/hpack_parser_corpus/e52173f0bc3325629046e85e2dc41acc6ba7d1c3
deleted file mode 100644 (file)
index 84f4753..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\1f-binc([)¤(¤-\ fÛ
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/e6589006e3bda4c57247ad66fcd73ac00ee2cbe2 b/test/core/transport/chttp2/hpack_parser_corpus/e6589006e3bda4c57247ad66fcd73ac00ee2cbe2
deleted file mode 100644 (file)
index 274e09d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-;'c\að[(!       ð[N!\\87!åGý!*(!  !åGýA)(!)í!¼*)åGýI)(Ù;)\8a
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/e67c79d0ed89ab2d5e8d81127df22876e636ac44 b/test/core/transport/chttp2/hpack_parser_corpus/e67c79d0ed89ab2d5e8d81127df22876e636ac44
deleted file mode 100644 (file)
index 600b6cd..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/e67c79d0ed89ab2d5e8d81127df22876e636ac44 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/e6fab7572fb2a1c6e107b6f83cffd103a233d021 b/test/core/transport/chttp2/hpack_parser_corpus/e6fab7572fb2a1c6e107b6f83cffd103a233d021
deleted file mode 100644 (file)
index 720a576..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/e6fab7572fb2a1c6e107b6f83cffd103a233d021 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/e790f5d312957dbfd20abdefe4b1735779ff9689 b/test/core/transport/chttp2/hpack_parser_corpus/e790f5d312957dbfd20abdefe4b1735779ff9689
deleted file mode 100644 (file)
index b818778..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/e790f5d312957dbfd20abdefe4b1735779ff9689 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/e8809017a4cf6c1e80a93f661166ead961f26bb4 b/test/core/transport/chttp2/hpack_parser_corpus/e8809017a4cf6c1e80a93f661166ead961f26bb4
deleted file mode 100644 (file)
index fce39c6..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/e8809017a4cf6c1e80a93f661166ead961f26bb4 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/e9733e973c33b38c2087b7f1deb36688b3b14259 b/test/core/transport/chttp2/hpack_parser_corpus/e9733e973c33b38c2087b7f1deb36688b3b14259
deleted file mode 100644 (file)
index b87a36f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8bc*[)¤\ f(* ¤®@\b\10\a[(?¤\a;[('¤ð(-¤Û!  ð'ð\1fb
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/ea8134769855d574f6673bf0301eb2e24632c6eb b/test/core/transport/chttp2/hpack_parser_corpus/ea8134769855d574f6673bf0301eb2e24632c6eb
deleted file mode 100644 (file)
index 0a16a74..0000000
+++ /dev/null
@@ -1 +0,0 @@
-\10\að[(-bin¤¤\10\að¤-bin\8bc[)(-'bin  !!?¤\1fÛð!\10\að{(-binð!     ð(      !!
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/eb489536e4e5589a93a17cd36669475b8f2a5e1b b/test/core/transport/chttp2/hpack_parser_corpus/eb489536e4e5589a93a17cd36669475b8f2a5e1b
deleted file mode 100644 (file)
index ffa9431..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8b#Z)¤(-¤\ e   b¤\10\að¤\ f-bin?ð\8bc[)(-\7fni''bin!!   !/¤!?\1fÛð!
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/eb48ebd4d01e5623dd16ae61938b3333fab3ce78 b/test/core/transport/chttp2/hpack_parser_corpus/eb48ebd4d01e5623dd16ae61938b3333fab3ce78
deleted file mode 100644 (file)
index b92817b..0000000
+++ /dev/null
@@ -1 +0,0 @@
\1f¤ÛððÜcc'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/eb6ca7624384239c7f7e0d83edb7cc334b7926d7 b/test/core/transport/chttp2/hpack_parser_corpus/eb6ca7624384239c7f7e0d83edb7cc334b7926d7
deleted file mode 100644 (file)
index cb68dfd..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/eb6ca7624384239c7f7e0d83edb7cc334b7926d7 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/ec9457ad41ed745ea9377ffdb16ad09f981daa7f b/test/core/transport/chttp2/hpack_parser_corpus/ec9457ad41ed745ea9377ffdb16ad09f981daa7f
deleted file mode 100644 (file)
index 9b15875..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/ec9457ad41ed745ea9377ffdb16ad09f981daa7f and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/edff5256a2d60d0e51caef25dc1d6f1643dad6d5 b/test/core/transport/chttp2/hpack_parser_corpus/edff5256a2d60d0e51caef25dc1d6f1643dad6d5
deleted file mode 100644 (file)
index 5ef662d..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/edff5256a2d60d0e51caef25dc1d6f1643dad6d5 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/ee4d9c5d22512da42726f47213ff56404d1d81d1 b/test/core/transport/chttp2/hpack_parser_corpus/ee4d9c5d22512da42726f47213ff56404d1d81d1
deleted file mode 100644 (file)
index cd45daf..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/ee4d9c5d22512da42726f47213ff56404d1d81d1 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/eef2f30b5e2ecd98ebefb12d57aba8b4ad52d904 b/test/core/transport/chttp2/hpack_parser_corpus/eef2f30b5e2ecd98ebefb12d57aba8b4ad52d904
deleted file mode 100644 (file)
index 9c27b38..0000000
+++ /dev/null
@@ -1 +0,0 @@
-?ð     \1fÛ!ðcm'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/ef23911de1a27d03d2d4983ca1527e17d6a7092b b/test/core/transport/chttp2/hpack_parser_corpus/ef23911de1a27d03d2d4983ca1527e17d6a7092b
deleted file mode 100644 (file)
index 4535127..0000000
+++ /dev/null
@@ -1 +0,0 @@
-0c'ð[(!        ð[(!\   !åGý![(!!       !åGýA)(!)í!¼*)åGýA)(Ù;)\8a
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/ef5b7fc62a2daecf1e8f928b1fa3ebd028413a41 b/test/core/transport/chttp2/hpack_parser_corpus/ef5b7fc62a2daecf1e8f928b1fa3ebd028413a41
deleted file mode 100644 (file)
index c3c6d73..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/ef5b7fc62a2daecf1e8f928b1fa3ebd028413a41 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/ef718258ca1870198e91a2fbc1eaa90b620673fb b/test/core/transport/chttp2/hpack_parser_corpus/ef718258ca1870198e91a2fbc1eaa90b620673fb
deleted file mode 100644 (file)
index be01d46..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8bc[)²(-'bin¤
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/efb46deb37a78f41dd760f6b7203b20956eb114e b/test/core/transport/chttp2/hpack_parser_corpus/efb46deb37a78f41dd760f6b7203b20956eb114e
deleted file mode 100644 (file)
index 58cc22f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-;?0c!(\aðK      ð\13NÔ\   !åG![(!!        !åGýA)(:)í!*å¼G\80ýA)(Ù;)\8a
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/efdd6824bd2456e3e408e0e84369c4fa3aa14f41 b/test/core/transport/chttp2/hpack_parser_corpus/efdd6824bd2456e3e408e0e84369c4fa3aa14f41
deleted file mode 100644 (file)
index 0926c63..0000000
+++ /dev/null
@@ -1 +0,0 @@
-0c\að[(!        ð[(!\   !åGý![(!!       !åGýA)(!)í!¼*)åGýA)(Ù;)\8a
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/efec040a5de1969df5e37e4bc50a0a8f0de341d8 b/test/core/transport/chttp2/hpack_parser_corpus/efec040a5de1969df5e37e4bc50a0a8f0de341d8
deleted file mode 100644 (file)
index 9e21c0e..0000000
+++ /dev/null
@@ -1 +0,0 @@
-(?¤:\1f\9bð!       c
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/f1e30464c24dc1d7cec7ec1dd2adec8512232b43 b/test/core/transport/chttp2/hpack_parser_corpus/f1e30464c24dc1d7cec7ec1dd2adec8512232b43
deleted file mode 100644 (file)
index a217e4f..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/f1e30464c24dc1d7cec7ec1dd2adec8512232b43 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/f27a617b936814476770a3b31a5afb80d0f3b423 b/test/core/transport/chttp2/hpack_parser_corpus/f27a617b936814476770a3b31a5afb80d0f3b423
deleted file mode 100644 (file)
index ee6ac4e..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/f27a617b936814476770a3b31a5afb80d0f3b423 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/f3f0d99ac2962f8fddb25c65fb4c8c6eb63518a9 b/test/core/transport/chttp2/hpack_parser_corpus/f3f0d99ac2962f8fddb25c65fb4c8c6eb63518a9
deleted file mode 100644 (file)
index 9b0d16f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8bc[)(?* ¤®@\b\10\a:
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/f4628084cf46f139babb886a782b4ab5977d5d2e b/test/core/transport/chttp2/hpack_parser_corpus/f4628084cf46f139babb886a782b4ab5977d5d2e
deleted file mode 100644 (file)
index 8926de3..0000000
+++ /dev/null
@@ -1 +0,0 @@
-(?¤\a;[('¤ð!    \1f(
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/f4753e8881e4b3c71f2728149be7d04cc648f6a6 b/test/core/transport/chttp2/hpack_parser_corpus/f4753e8881e4b3c71f2728149be7d04cc648f6a6
deleted file mode 100644 (file)
index 0c8d290..0000000
+++ /dev/null
@@ -1 +0,0 @@
-?* ¤®@\b\10\aZnð:(c        (;þ!(c\1f!        ;\      ÛäGý!ðcm:'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/f4b48c4f3f310ed767755267210f212dd62bd715 b/test/core/transport/chttp2/hpack_parser_corpus/f4b48c4f3f310ed767755267210f212dd62bd715
deleted file mode 100644 (file)
index 49ea908..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/f4b48c4f3f310ed767755267210f212dd62bd715 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/f4d6ff635ae4fda497221da4bfa3e593df59a44e b/test/core/transport/chttp2/hpack_parser_corpus/f4d6ff635ae4fda497221da4bfa3e593df59a44e
deleted file mode 100644 (file)
index a7c841c..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-b)n\8bc[)(:* ¤®@\b1\a:
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/f52f4d51aaaed0f9c3a20936cf5efd25d0692f67 b/test/core/transport/chttp2/hpack_parser_corpus/f52f4d51aaaed0f9c3a20936cf5efd25d0692f67
deleted file mode 100644 (file)
index 1ab7be3..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤p\83Ûðð¤\1f!\83ÛðTð*
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/f7cf30724ab740918eee6e4a6b6658ae3d7706e8 b/test/core/transport/chttp2/hpack_parser_corpus/f7cf30724ab740918eee6e4a6b6658ae3d7706e8
deleted file mode 100644 (file)
index 669e4a8..0000000
+++ /dev/null
@@ -1 +0,0 @@
\bc
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/f823828ffd2a60efee36f1de52cb0f024ac5b4bb b/test/core/transport/chttp2/hpack_parser_corpus/f823828ffd2a60efee36f1de52cb0f024ac5b4bb
deleted file mode 100644 (file)
index 0fee687..0000000
+++ /dev/null
@@ -1 +0,0 @@
\1fÛð!ð c'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/f8760761bd5ab7b47376bfbc5a44e16b2d5ca800 b/test/core/transport/chttp2/hpack_parser_corpus/f8760761bd5ab7b47376bfbc5a44e16b2d5ca800
deleted file mode 100644 (file)
index 667c246..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8bc[''(-'bin !!?¤\1f¤\bcÛð!\10
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/fb15042c268625089ef6c8aa3d8a6f12d1d02c74 b/test/core/transport/chttp2/hpack_parser_corpus/fb15042c268625089ef6c8aa3d8a6f12d1d02c74
deleted file mode 100644 (file)
index 67f84c5..0000000
+++ /dev/null
@@ -1 +0,0 @@
-\10\að[(! ð(!\    !åGý:[(!'ð[(!!  ð[(!!   !åGý!åGýA)(\13[(  !!å
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/fc3dd4292d6884a770199596f5e9cbc1e869e5fb b/test/core/transport/chttp2/hpack_parser_corpus/fc3dd4292d6884a770199596f5e9cbc1e869e5fb
deleted file mode 100644 (file)
index 99d90a0..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/fc3dd4292d6884a770199596f5e9cbc1e869e5fb and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/fcc06696e641a7743bfd2f3b7ecd88e7b727e00a b/test/core/transport/chttp2/hpack_parser_corpus/fcc06696e641a7743bfd2f3b7ecd88e7b727e00a
deleted file mode 100644 (file)
index f79c824..0000000
+++ /dev/null
@@ -1 +0,0 @@
-;?'c\að[(!      ð[N!\   !åGý!\ 6acceptý.:¤cA)(!)í!¼ª)ågÝI)(Ù;)\8a
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/fd34ec90fe8f9218fd25c3eac151aec998cff6d8 b/test/core/transport/chttp2/hpack_parser_corpus/fd34ec90fe8f9218fd25c3eac151aec998cff6d8
deleted file mode 100644 (file)
index c5005c7..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/fd34ec90fe8f9218fd25c3eac151aec998cff6d8 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/fdf548cde981fab4fb17bd63a124b75eddc5c836 b/test/core/transport/chttp2/hpack_parser_corpus/fdf548cde981fab4fb17bd63a124b75eddc5c836
deleted file mode 100644 (file)
index fcae5ce..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8b\1fÊ!ð       c(?¤)['\1f\9bð!     c'(
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/fe47fb18b064e26479c3c3140082bd01065e897a b/test/core/transport/chttp2/hpack_parser_corpus/fe47fb18b064e26479c3c3140082bd01065e897a
deleted file mode 100644 (file)
index 4ed844a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-(??\81;[(¤('?¤\a
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/ff2097734bd7bb8451aece13c9336c4624735170 b/test/core/transport/chttp2/hpack_parser_corpus/ff2097734bd7bb8451aece13c9336c4624735170
deleted file mode 100644 (file)
index e8e30c8..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/ff2097734bd7bb8451aece13c9336c4624735170 and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/ff2c949863eb4e14d9e835c51591304403d91b6c b/test/core/transport/chttp2/hpack_parser_corpus/ff2c949863eb4e14d9e835c51591304403d91b6c
deleted file mode 100644 (file)
index b9b44ea..0000000
Binary files a/test/core/transport/chttp2/hpack_parser_corpus/ff2c949863eb4e14d9e835c51591304403d91b6c and /dev/null differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/ff7d6ff060e63355701b2e655c802902338497de b/test/core/transport/chttp2/hpack_parser_corpus/ff7d6ff060e63355701b2e655c802902338497de
deleted file mode 100644 (file)
index 58337fb..0000000
+++ /dev/null
@@ -1 +0,0 @@
-¤¤\10\að¤\ f-bin\8bc\97*[)¤\ f(-¤Ûð'ð!b\83cin       ;!!
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-0141fcddc9807ee093313b2256f1306fbbdc6cda b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-0141fcddc9807ee093313b2256f1306fbbdc6cda
new file mode 100644 (file)
index 0000000..60e23b7
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x28\x3f\xa4\x1f\xa4\xa4\x1f\xdb\xa4\xdb\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-0255050a9ccb25f46d6c1bf6a5a8a4c0c7635599 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-0255050a9ccb25f46d6c1bf6a5a8a4c0c7635599
new file mode 100644 (file)
index 0000000..9e77d62
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x13\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1f\xa4\x5b\x29\xa4\x21\x01\x00\x00\x00\xff\xff\x0f\xa4\x00\x00"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-0320a995a8c76c64c8a0e0297f632b76d9bc92d6 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-0320a995a8c76c64c8a0e0297f632b76d9bc92d6
new file mode 100644 (file)
index 0000000..f24e72e
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x1f\x21\x83\xdb\xf0\xa4\x1f\x21\x83\xb6\xdb\xf0\x2a\x63"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-042091aeac4cc255506b96fa11c7354e699fde76 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-042091aeac4cc255506b96fa11c7354e699fde76
new file mode 100644 (file)
index 0000000..9160daa
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x3b\x3f\x30\x63\x21\x28\x07\xf0\x4b\x09\xf0\x5b\x4e\x21\x8b\x63\x5b\x3a\xa4\x10\x07\xf0\xa4\x0f\x2d\x5c\x19\x21\xf5\x47\x21\x29\x3a\x5b\x28\x21\x21\xa4"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-051268ade45dbed0aab896d7d9f4d10ba89d3b09 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-051268ade45dbed0aab896d7d9f4d10ba89d3b09
new file mode 100644 (file)
index 0000000..42d6ce2
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa4\x10\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x63\x5b\x29\x28\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x2d\x27\x62\x69\x6e\x09\x21\x21\x3f\xa4\x1f\xdb\xf0\x21\x10\x07\xf0\x7b\x28\x2d\x62\x69\x6e\xf0\x09\x21\x5c\x09\x21\xe5\x37\xe9\x1b\x3b\x3f\x47\xed\x28\x5b\x28\x21\x21\x5c\xf0\x2a\xa4\x0f\xa4\xdb\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-0696e7bf7837d98de01c915d3c9d80e5d21b30d2 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-0696e7bf7837d98de01c915d3c9d80e5d21b30d2
new file mode 100644 (file)
index 0000000..5b0dbdd
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x10\x07\xf0\x5b\x28\x2d\x62\x69\x6e\x21\x09\xf0\x28\x21\x5c\x09\x3f\x2a\xa0\xa4\xae\x40\x08\x10\x07\x3a\xf0\x5b\x06"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-06995c2f3f01c7ec50547415dc324c64030b7a3e b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-06995c2f3f01c7ec50547415dc324c64030b7a3e
new file mode 100644 (file)
index 0000000..bd91692
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2e\x00\xa4\x63"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-06f7ce769fe07804fc842462d4be8c1aa2ba82c2 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-06f7ce769fe07804fc842462d4be8c1aa2ba82c2
new file mode 100644 (file)
index 0000000..39a023a
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xae\x80\xa4\x88\x28\x63\x63"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-0781b055c85ab8fbd0a3d0080a32e394af8761c4 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-0781b055c85ab8fbd0a3d0080a32e394af8761c4
new file mode 100644 (file)
index 0000000..98417d8
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x1f\x21\x83\xdb\xf0\xf0\xa4\x1f\x21\x83\xdb\xf0\xf0\x63"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-080e1f19e6061c5bcac31add2095f87f6ce46129 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-080e1f19e6061c5bcac31add2095f87f6ce46129
new file mode 100644 (file)
index 0000000..6352505
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3b\x3f\x27\x63\x07\xf0\x5b\x28\x21\x09\xf0\x5b\x4e\x21\x5c\x09\x21\xe5\x47\xfd\x21\x2a\x28\x21\x09\x21\xe5\x47\xfd\x41\x29\x28\x21\x29\xed\x21\xbc\x2a\x29\xe5\x47\xfd\x49\x29\x28\xd9\x3b\x29\x8a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-0828169ba82152a8907f1001e3d98804397d4610 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-0828169ba82152a8907f1001e3d98804397d4610
new file mode 100644 (file)
index 0000000..8d85958
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x1f\xa4\xdb\xf0\x21\xf0\x09\x63\x63\x27"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-08ffc4a4160e9fe6f322c28870a89a41fd9c37d7 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-08ffc4a4160e9fe6f322c28870a89a41fd9c37d7
new file mode 100644 (file)
index 0000000..f690032
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x83\xf5\x63\x1e\x00\x27\x5b\xf0\x69\x28\x62\x6e\x2d\x21\x3f\xa4\x1f\xdb\xf0\x21\x28\x21\x5c\xf0\x09\x63"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-090a7a758898a6e7c9108b7e8a1cb9cda383e707 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-090a7a758898a6e7c9108b7e8a1cb9cda383e707
new file mode 100644 (file)
index 0000000..d268e92
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x63\x5b\x29\x28\x2d\x27\x62\x69\x6e\x09\x21\x21\x3f\xa4\x1f\xdb\xf0\x21\x10\x07\xf0\x7b\x28\x2d\x62\x69\x6e\xf0\x09\x21\x5c\x09\x21\xe5\x1f\xe9\x1b\x3b\x3f\x47\xed\x5b\x28\x28\x21\x21\x5c\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-0940663729501b750a18542e1041cc26385c6148 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-0940663729501b750a18542e1041cc26385c6148
new file mode 100644 (file)
index 0000000..8378d10
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\xe4\x63\x5b\xf2\x29\x28\x27\x2d\x62\x69\x2e\x09\x2a\x29\x21\x3f\xa4\x1f\xdb\xe2\x21\x10\x07\xf0\x7b\x28\x2d\x62\x69\x5c\x6e\x21\x09\x21\x09\xf0\xe5\x1f\xe9\x1b\x3b\x3f\x47\xed\x3a\x5b\x28\x28\x21\x21\x5c\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-0a10bd140c6c5fb109a0816ca061739688a6db9a b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-0a10bd140c6c5fb109a0816ca061739688a6db9a
new file mode 100644 (file)
index 0000000..b3d346d
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa0\xa4\xae\x08\x00\x07\x10\xf4\x5b\x28\x21\x09\x63\xf0\x28\x21\x5c\x09\x21\x63\x47\xfd\x3a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-0a4d3fda02cdcb7adad1daa80d65780c9c8d1464 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-0a4d3fda02cdcb7adad1daa80d65780c9c8d1464
new file mode 100644 (file)
index 0000000..9c03a84
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x28\x8b\x29\x5b\x27\xa4\x0f\xa4\xdb\xf0\xf0\x83\x00\x63\x63\x27\x28\x2d\x63\x62\x69\x6e\x09\x21\x21\x3f\xa4\x1f\xdb\xf0\x21\x10\x07\xf0\x7b\x28\x2d\x62\x69"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-0ad812832efa33e086874fbf3496664d3f1b4dbe b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-0ad812832efa33e086874fbf3496664d3f1b4dbe
new file mode 100644 (file)
index 0000000..b62fee4
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\xc3\x00\x2a\x21\x13\xa0\xae\x08\xa4\x10\x07\xf0\x5b\x28\x63\xa4\x1f\x1f\x2a\x27\x5b\x5b\xf0\x28\x00\x21\x21\x09"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-0c9996d4fef87bacd7a001e99a515b3ba3d5788f b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-0c9996d4fef87bacd7a001e99a515b3ba3d5788f
new file mode 100644 (file)
index 0000000..31f1de8
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2e\x00\xa4\x2a\x63\xa0\xa4\xae\x08\x00\x10\x07\xf0\x5b\x28\x21\x09\x63\xf0\x28\x21\x5c\x09\x21\xa0\xa4\x08\x00\x63\xe5\x47\xfd\x63\x63\x3a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-0d6210208831fe55951af56cdeee3d54a91a5361 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-0d6210208831fe55951af56cdeee3d54a91a5361
new file mode 100644 (file)
index 0000000..d2ce751
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x66\x13\x21\x28\x21\x21\x09\x69\x5b\xd1\x21\xe5"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-0d784965b2262df7ed7a1eb57b92a718cc76bde8 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-0d784965b2262df7ed7a1eb57b92a718cc76bde8
new file mode 100644 (file)
index 0000000..745e284
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x1f\xca\x21\xf0\x09\x63\x27"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-0dc9e41eedf35ccedf4e2b0d230ead7c4d72fdb2 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-0dc9e41eedf35ccedf4e2b0d230ead7c4d72fdb2
new file mode 100644 (file)
index 0000000..ab3168a
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x83\x2a\xa0\xa4\xae\x08\x00\x10\x07\xf0\x5b\x28\x63\xa4\x1f\x1f\x2a\x00\x27\x5b\xf0\x69\x28\xa0\xa4\xae\x08\x00\x10\x07\x62\x21\x09\xa4\xdb\xf0\x63\xf0\x28\x21\x5c\x09\x21\x63\xe5\xf0\x47\xfd\x3a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-0dd470c8939ed535de6b36f7b7bfb68aeace493e b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-0dd470c8939ed535de6b36f7b7bfb68aeace493e
new file mode 100644 (file)
index 0000000..40939de
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x63\x5b\x29\x28\x27\x2d\x62\x68\x09\x2a\x21\x21\x3f\xa4\x1f\xdb\xe2\x21\x10\x07\xf0\x7b\x28\x2d\x62\x69\x5c\x6e\x21\x09\x21\x09\xf0\xe5\x1f\xe9\x1b\x3b\x3f\x47\xed\x3a\x5b\x28\x28\x21\x21\x5c\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-0e61e471fa6d3405daef4276ee00cf5fc189f378 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-0e61e471fa6d3405daef4276ee00cf5fc189f378
new file mode 100644 (file)
index 0000000..a4398f0
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x83\x63\x28\x00\x27\x5b\xf0\x69\x28\x62\x6e\x2d\x21\x3f\xa4\x1f\xdb\xf0\x21\x28\x21\x5c\xf0\x09\x63"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-0e9196f951874edbb5ed098739ea5c8b6c0751c2 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-0e9196f951874edbb5ed098739ea5c8b6c0751c2
new file mode 100644 (file)
index 0000000..990290c
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xf0\x5b\x28\x21\x21\x09\x21\xe5\x47\xfd\x41\x29\x28\x21\x29\xed\x21\xbc\x2a\x29\xd9\x3a\x3b\x87\x8a\x2a\xd5\xc3\xee\x28\xf9\x29\x5d\x28\x28\x3b\x27\x27\x3b\x96\x25\xef\x29\xe6\xd3\x90\xf5\x33\x29\x27\xd3\x29\xca\xd1\x43\x2a\x29\x9c\x95\x00\x29\x28\xf0\x65"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-11442d93a554b9e7f9ab02782bbf9443bf6e1ddc b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-11442d93a554b9e7f9ab02782bbf9443bf6e1ddc
new file mode 100644 (file)
index 0000000..1a628db
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x83\x63\x1f\x00\x27\x5b\xf0\x69\x28\x62\x6e\x2d\x21\x3f\xa4\x1f\xdb\xf0\x21\x28\x21\x5c\xf0\x09\x63"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-11833b795d04eda5a3af56ef7b3c3a26a8ee3444 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-11833b795d04eda5a3af56ef7b3c3a26a8ee3444
new file mode 100644 (file)
index 0000000..85cdb75
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x29\x5b\x27\x28\x2d\x63\x62\x69\x6e\x09\x21\x21\x3f\xa4\x1f\xdb\xf0\x21\x10\x07\xf0\x7b\x28\x2d\x62\x69\x6e\xf0\x09\x21\x5c\x09\x21\xe5\x1f\xe9\x1b\x3b\x3f\x47\xed\x3a\x5b\x28\x28\x21\x21\x5c\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-141272316382b0f3e9ec841c735b84e7aa517c3e b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-141272316382b0f3e9ec841c735b84e7aa517c3e
new file mode 100644 (file)
index 0000000..7856695
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3b\x3f\x30\x63\x21\x28\x07\xf0\x4b\x09\xf0\x5b\x4e\x21\x5c\x19\x21\xf5\x47\x21\x5b\x28\x21\x21\x09\x21\xe5\x47\xfd\x41\x29\x28\x21\x29\xed\x21\x2a\xe5\x47\x80\xbe\xfd\x41\x29\x29\xd9\x2b\xa9\x8a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-15ae43369798e48c396dfe7d53a21878b96e66c8 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-15ae43369798e48c396dfe7d53a21878b96e66c8
new file mode 100644 (file)
index 0000000..c87334f
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\x2a\xa0\xa4\xae\xa0\xa4\xae\x08\x00\x07\x10\x63\x21\x09\x5b\xf4\x28\xf0\x28\x21\x5c\x09\x21\x63\x47\xfd\x3a\x08\x00\x07\x10\x63\x21\x09\x30\x63\x5b\xf4\x27\x28\xf0\xf0\x5b"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-166bf1843c229d34a2880d234dd166c27bdc11fd b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-166bf1843c229d34a2880d234dd166c27bdc11fd
new file mode 100644 (file)
index 0000000..877ddde
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\xed\xa4\x2d\x5b\x63\x27\x21\x29\xa4\x10\x62\x69\x07"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-179e8ac763b4051a953a38b6b3b1f1e1f6cc6c9e b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-179e8ac763b4051a953a38b6b3b1f1e1f6cc6c9e
new file mode 100644 (file)
index 0000000..9c69d77
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x00\x00\x00\x00\x2f\xa4\x1f\xa4\xa4\x1f\xdb\xa4\xdb\x2a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-17faf0ba8a491a835d35977a9007b90ab7d30d2a b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-17faf0ba8a491a835d35977a9007b90ab7d30d2a
new file mode 100644 (file)
index 0000000..965744b
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\x2a\xa0\xa4\xae\xa0\xa4\xae\x08\x00\x07\x10\x63\x21\x09\x5b\xf4\x28\xf0\x28\x21\x5c\x09\x21\x63\x47\xfd\x3a\x08\x00\x07\x10\x63\x21\x09\x5b\xf4\x28\xf0\x28\x21\x5c\x09\x21\x21\x63\x47\xfd\x3a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-188f6cf2470e95b228341de305ef839b27f01a5c b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-188f6cf2470e95b228341de305ef839b27f01a5c
new file mode 100644 (file)
index 0000000..f4d0d8f
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3b\x3f\x30\x63\x07\xf0\x5b\x28\x21\x09\xf0\x5b\x4e\x21\x5c\x09\x21\xe5\x47\xfd\x21\x5b\x28\x21\x21\x09\x21\xe5\x47\xfd\x41\x29\x28\x21\x29\xed\x21\xbc\x2a\x29\xe5\x47\xfd\x41\x29\x28\xd9\x3b\x29\x8a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-1ab3e52adace335d02e2b5130eb4f7c918add7fd b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-1ab3e52adace335d02e2b5130eb4f7c918add7fd
new file mode 100644 (file)
index 0000000..8db9726
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x63\x5b\x27\x29\x28\x2d\x27\x62\x69\x6e\x09\x21\x21\x3f\xa4\x1f\xdb\xf0\x21\x10\x07\xf0\x7b\x28\x2d\x62\x61\x6e\xf0\x09\x21\x5c\x09\x21\x28\xe5\x1f\xe9\x1b\x96\x3b\x3f\x47\xed\x3a\x5b\x28\x28\x21\x21\x5c\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-1b5150514364e2c17f5a4edac1b7af99b936f55a b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-1b5150514364e2c17f5a4edac1b7af99b936f55a
new file mode 100644 (file)
index 0000000..27ee7a1
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\x2a\xa0\xa4\xae\xa0\xa4\xae\x08\x00\x07\x10\x63\x21\x09\x5b\xf4\x28\xf0\x2a\x21\x5c\x09\x21\x63\x47\xfd\x3a\x08\x00\x07\x10\x63\x21\x09\x5b\xf4\x28\xf0\x28\x21\x5c\x09\x21\x63\x47\xfd\x3a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-1e8befb98cbaba059d6771abd1680e19484e7723 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-1e8befb98cbaba059d6771abd1680e19484e7723
new file mode 100644 (file)
index 0000000..e108397
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa0\xa4\xae\x00\x00\x10\x07\xf0\x5b\x63\x3b\xf0\x21\x28\x09\xfe\x28\x21\x5c\x09\x21\x63\xe5\x47\xfd\x3a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-1e9b962969c359bc2ff766704c8ca8e25f5eccfc b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-1e9b962969c359bc2ff766704c8ca8e25f5eccfc
new file mode 100644 (file)
index 0000000..d7e5091
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa0\xa4\xae\x08\x00\x07\x10\x2a\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x63\x83\x7e\x1f\x00\x27\x5b\xf0\x69\x28\x62\x63\x6e"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-1f80af104acf41b912bf4a48fb938267e3718719 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-1f80af104acf41b912bf4a48fb938267e3718719
new file mode 100644 (file)
index 0000000..679cd4b
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3f\x2a\xae\x40\x08\x3a\x5b\x07\x10\xf0\x06\xf8\x63\x09\x28\x21\x21\x5c\xfe\x3b\xf0\x01\x21\x7e\x09\x1f\xdb\xe5\x47\xa4\x0f\xa4\xdb\xf0\xfd\x21\xd0\x61\x6d\xa4"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-1fcc4afd6f48e83d61ea74970df3ca9dcd8ec291 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-1fcc4afd6f48e83d61ea74970df3ca9dcd8ec291
new file mode 100644 (file)
index 0000000..bebf16d
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\x2a\xa0\xa4\xae\xa0\xa4\xae\x08\x00\x07\x10\x63\x21\x09\x5b\xf4\x28\xf0\x28\x21\x5c\x62\x09\x21\x63\xfd\x3a\x08\x00\x07\x10\x63\x21\x09\x5b\xf4\x28\xf0\x28\x63\x21\x09\x5c\x21\x47\xfd\x3a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-213a734ccdb813b18ad9f2dd99b7f9967ee1460b b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-213a734ccdb813b18ad9f2dd99b7f9967ee1460b
new file mode 100644 (file)
index 0000000..5fdfccf
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x99\x5b\x29\x28\x27\x2d\x62\x69\x6e\x09\x21\x21\x3f\xa4\x1f\xdb\xf0\x21\x10\x07\xf0\x7b\x28\x2d\x62\x69\x5c\x6e\x21\x09\x21\x09\xf0\xe5\x1f\xe9\x1b\x3b\x3f\x47\xed\x3a\x5b\x28\x28\x21\x21\x5c\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-2151945f43991c27e123c45dc72b93752a47e65f b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-2151945f43991c27e123c45dc72b93752a47e65f
new file mode 100644 (file)
index 0000000..477e486
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x10\x07\xf0\x5b\x28\x2d\x62\x69\x6e\x21\x09\xf0\x28\x21\x5c\x09\x21\xe5\x47\xfd\x3a\x5b\x28\x21\x27\xf0\x5b\x28\x21\x21\x09\xf0\x5b\x28\x2a\x21\x09\x21\xe5\x21\xfd\x47\xe5\x47\xfd\x41\x29\x28\x13\x5b\x28\x09\x21\x21\xe5"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-21545d998c27a5a1572a89a552937752432b1c14 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-21545d998c27a5a1572a89a552937752432b1c14
new file mode 100644 (file)
index 0000000..3999a3d
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\xe9\x6e\x27\x1f\x83\x27\x63\x29\x5b\xf0\x69\x28\x62\x6e\x2d\x21\x3f\xa4\x1f\xdb\xf0\x21\x09\xf0\x28\x21\x5c\x63"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-23c7443fa1ab713e7c34ec50222b1b8cceaedc65 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-23c7443fa1ab713e7c34ec50222b1b8cceaedc65
new file mode 100644 (file)
index 0000000..0a61adc
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x2d\x5b\x63\x27\x28\x29\x62\x69\x6e\x09\x21\x21\x3f\xa4\x1f\xdb\xf0\x21\x3b\x07\xf0\x7b\x28\x2d\x62\x69\x6e\xf0\x09\x21\x5c\x09\x21\x98\x1f\xe9\x1b\x3b\x3f\x47\xed\x3a\x5b\x28\x28\x21\x21\x5c\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-2445bb2c6779712dc9e14c01fecb7103f8732858 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-2445bb2c6779712dc9e14c01fecb7103f8732858
new file mode 100644 (file)
index 0000000..294d688
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x83\x63\x1f\x00\x27\x5b\xf0\x98\x69\x28\x62\x6e\x2d\x21\x3f\xa4\x1f\xdb\xf0\x21\x28\x21\x5c\xf0\x09\x63"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-244b0a20500e31d3c538418800db816b07f4d210 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-244b0a20500e31d3c538418800db816b07f4d210
new file mode 100644 (file)
index 0000000..6202274
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x63\x5b\x29\x28\x2d\x27\x62\x69\x6e\x09\x31\x21\x3f\xa4\x1f\xdb\xf0\x21\x3b\x10\x07\x2a\xf0\x7b\x28\x2d\x62\x69\x6e\xf0\x09\x21\x5c\x09\x21\xe5\x1f\xe9\x1b\x3b\x3f\x47\xed\x3a\x5b\x28\x28\x21\x21\x5c\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-2461b9fa6b5bc4b6424dec5b9a18d4ec7c309112 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-2461b9fa6b5bc4b6424dec5b9a18d4ec7c309112
new file mode 100644 (file)
index 0000000..fe4ffd8
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3f\x2a\xa0\xa4\xae\x40\x08\x10\x07\x3a\xf0\x5b\x06\xf8\x63\x09\x28\x3b\xfe\x21\x21\x5c\xf0\x09\x21\x7e\x09\x1f\xdb\xe5\x47\xfd\x21\xf0\x63\x6d\x3a\x27"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-24ec2f3e17d3850564788f3fed17a5c586c44658 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-24ec2f3e17d3850564788f3fed17a5c586c44658
new file mode 100644 (file)
index 0000000..4c749e5
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa0\xa4\xae\x08\x00\x07\x10\x63\x00\x00\x21\x09\x00\x5b\x21\x28\xf0\x28\x21\x21\x5c\x09\x73\x63\x47\x00\x2f\xa4\x1f\xa4\xa4\x1f\xfd\x3a\xdb\xa4\xdb\x2a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-2537b8d6b902b8dfc6e17f194cf7d05ddecf74cf b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-2537b8d6b902b8dfc6e17f194cf7d05ddecf74cf
new file mode 100644 (file)
index 0000000..4fa3215
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x1f\x21\x83\xdb\xf0\xd0\xa4\x1f\x21\x83\x3a\x5b\x6f\xf0\xf0\x63"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-253ad01acea4b7038edc3f2a8c4a0c0f5c4dcd05 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-253ad01acea4b7038edc3f2a8c4a0c0f5c4dcd05
new file mode 100644 (file)
index 0000000..96875b9
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x63\x5b\x29\x28\x2d\x27\x62\x69\x6e\x09\x21\x21\x3f\xa4\x1f\xdb\xf0\x21\x10\x07\xf0\x7b\x28\x2d\x62\x69\x6e\xf0\x09\x21\x5c\x09\x21\xe5\x37\xe9\x1b\x3b\x3f\x47\xed\x28\x5b\x28\x21\x21\x5c\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-256d0bbdbed22f5867a6f503bf082011e61ee12b b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-256d0bbdbed22f5867a6f503bf082011e61ee12b
new file mode 100644 (file)
index 0000000..ce28891
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa0\xa4\xae\xa0\xa4\xae\x08\x00\x07\x10\x63\x28\x09\x5b\xf4\x28\xf0\x28\x21\x5c\x09\x21\x63\x47\xfd\x3a\x08\x00\x6b\x10\x63\x21\x09\x5b\xf4\x28\xf0\x28\x21\x5c\x75\x09\x1f\x00\x21\x63\x47\xfd\x3a\xb5\x58"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-26f0e88adbd8f8cdf778131a35b33ecf8711fa49 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-26f0e88adbd8f8cdf778131a35b33ecf8711fa49
new file mode 100644 (file)
index 0000000..29c3e17
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x70\x83\xdb\xf0\xf0\xa4\x1f\x21\x83\xdb\x27\x29\xf0\x63"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-2e5dd8fb9d2a31fad9d681eda697d085b647b57c b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-2e5dd8fb9d2a31fad9d681eda697d085b647b57c
new file mode 100644 (file)
index 0000000..84e7b88
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x1f\x21\x83\xf0\xf1\xa4\x1f\x21\x83\xdb\xf0\xb1\xf0\x63"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-2fdfd2abf30c636ec8c841f1ac26594e25664f0f b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-2fdfd2abf30c636ec8c841f1ac26594e25664f0f
new file mode 100644 (file)
index 0000000..ee1a278
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\x2a\xa0\xa4\xae\xa0\xa4\xae\x08\x00\x07\x10\x63\x21\x09\x5b\xf4\x28\xf0\x28\x21\x5c\x09\x21\x63\x47\xfd\x3a\x48\x00\x07\x10\x63\x21\x09\x5b\xf4\x28\xf0\x28\x21\x5c\x09\x21\x63\x47\xfd"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-311dac5092e36134d3490f98aa4207425e0ee941 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-311dac5092e36134d3490f98aa4207425e0ee941
new file mode 100644 (file)
index 0000000..207712d
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x10\x07\xf0\x5b\x28\x21\x09\xf0\x5b\x28\x21\x5c\x09\x21\xe5\x47\xfd\x3a\x5b\x28\x21\x21\x13\x5b\x28\x09\x21\xe5\x47\xfd\x41\x29\x28\x21\x29\xed\x21\xb8\x2a\x21\x21\x09\x29"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-320fe6224a5b691c0425e34b6b14e8c6fe9f9620 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-320fe6224a5b691c0425e34b6b14e8c6fe9f9620
new file mode 100644 (file)
index 0000000..cb6e53d
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa0\xa4\xae\x40\x08\x10\x07\xf0\x5b\x3a\x06\xf8\x63\x09\x38\x3b\x27\xfe\x21\x21\x5c\xf0\x09\x21\x7e\x09\x1f\xdb\x44\x47\xfd\x21\xf0\x6b\x6d\x27"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-3255f1c7441a7150dc3c33022bfbe8c956c7b7b1 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-3255f1c7441a7150dc3c33022bfbe8c956c7b7b1
new file mode 100644 (file)
index 0000000..7bbb990
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3b\x3f\x27\x63\x07\xf0\x5b\x28\x21\x09\xf0\x5b\x4e\x21\x5c\x09\x21\xe5\x45\xfd\x21\x2a\x28\x21\x21\x09\x21\xe5\x47\xfd\x41\x29\x28\x21\x29\xed\x21\xbc\x2a\x29\xe5\x47\xfd\x49\x29\x28\xd9\x3b\x29\x8a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-33bc9db104eb72891fb096f34cbac191b3f9918d b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-33bc9db104eb72891fb096f34cbac191b3f9918d
new file mode 100644 (file)
index 0000000..36b01e2
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x83\x28\x1f\x00\x27\x5b\xf0\x69\x28\x62\x6e\x2d\x21\x3f\xa4\x1f\xdb\xf0\x21\x28\x21\x5c\xf0\x09\x63"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-342ff1db70a7616b4ef76c03a42802c6702c18cb b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-342ff1db70a7616b4ef76c03a42802c6702c18cb
new file mode 100644 (file)
index 0000000..c7ed9bf
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x29\x07\x3a\x3b\x21\x9c\xca\x27\xd2\xd8\x29\x2a\x3b\x7d\x76\x29\x37\x49\xcf\x21\xa4\x29\x3b\x1e\x96\x2d\x4d\x2a\xb1\xe4\xe2\x21\x27\x64\x2a\x43\x75\x18\x0e\xab\x91\x58\x24\x30\x0e\x29\x3a\xf3\x2a\x3b\x3a\xe4\xdd\x3b\x3b\x28\x29\x3b\x3a\x5d\xef\xe6\x40"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-344c011df992ccfc0ec682c14a1cb2d7959998c7 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-344c011df992ccfc0ec682c14a1cb2d7959998c7
new file mode 100644 (file)
index 0000000..fa294a3
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3b\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x63\x2a\x5b\x29\xa4\x0f\xa4\xa4\x28\x10\x07\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-35775efb9d0d68fa07987b9a84934389b528e436 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-35775efb9d0d68fa07987b9a84934389b528e436
new file mode 100644 (file)
index 0000000..bc838c2
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3f\xa4\x1f\xd3\xf0\x21\xdc\xf0\x09\x63\x27"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-3650168db6fe115fb1e73eed4b76cd224d977d01 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-3650168db6fe115fb1e73eed4b76cd224d977d01
new file mode 100644 (file)
index 0000000..a7dc4d7
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x63\x29\x28\x2d\x27\x62\x69\x6e\x09\x21\x21\x3f\xa4\x1f\xdb\xf0\x21\x10\x07\xf0\x7b\x28\x2d\x62\x69\x6e\xf0\x09\x21\x5c\x09\x21\xe5\x1f\xe9\x1b\x3b\x3f\x47\xed\x3a\x5b\x28\x28\x21\x21\x5c\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-38228bf98cdb50fd3fa830ba5a9d4c7399063dff b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-38228bf98cdb50fd3fa830ba5a9d4c7399063dff
new file mode 100644 (file)
index 0000000..95bff04
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa0\xa4\xae\x40\x08\x10\x07\x3a\xf0\x5b\x28\xf8\x63\x09\x28\x3b\xfe\x21\x21\x5c\x09\x21\x63\xe5\x47\xfd\x3a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-38717bee901151b22a10beb12c6623ccc844d3c2 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-38717bee901151b22a10beb12c6623ccc844d3c2
new file mode 100644 (file)
index 0000000..5cd88d2
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3b\x3f\x2e\x10\x07\xf0\x5b\x28\x2d\x62\x69\x6e\x21\x09\xf0\x28\x21\xa4\x5c\x09\x21\xe5\x47\xfd\x3a\x5b\x28\x21\x27\xf0\x5b\x28\x21\x27\x63\x07\xf0\x21\x09\xf0\x63\x5b"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-3a4bb427a85bdc5bf66ac71db073c99e0dc9f881 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-3a4bb427a85bdc5bf66ac71db073c99e0dc9f881
new file mode 100644 (file)
index 0000000..c723758
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x10\x07\xf0\x5b\x28\x27\x21\x09\xf0\x28\x21\x5c\x09\x21\xe5\x47\xfd\x3a\x28\x21\x27\xf0\x5b\x28\x21\x21\x09\xa4\x1f\x5b\xf0\x21\xf0\x09\x63\xf0\x5b\x28\x21\x21\x1f\x09\x21\xe5\x47\xfd\x21\xe5\x47\xfd\x27\x41\x29\x28\x13\x5b\x28\x09\x27\x21\x21\xe5"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-3ab48621d9b8f075369099a8ec7517bd23fd6e70 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-3ab48621d9b8f075369099a8ec7517bd23fd6e70
new file mode 100644 (file)
index 0000000..d06f4e3
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x63\x5b\x29\x28\x2d\x27\x62\x69\x6e\x09\x41\x21\x21\x3f\xa4\x1f\xdb\xf0\x21\x10\x07\x62\x7b\xf0\x69\x2d\x28\x6e\xf0\x09\x21\x5c\x09\x21\xe5\x1f\xe9\x1b\x3b\x3f\x47\xed\x21\x21\x3a\x5b\x28\x28\x5c\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-3aec8d9311130dfbb6584fe6e619579c21992b5f b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-3aec8d9311130dfbb6584fe6e619579c21992b5f
new file mode 100644 (file)
index 0000000..41b0ee2
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x0f\xa4\xdb\xf0\xa4\x83"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-3b14837f22905dcb04f93aed2aa69bf95924fb9d b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-3b14837f22905dcb04f93aed2aa69bf95924fb9d
new file mode 100644 (file)
index 0000000..a738d84
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x66\x13\x2a\x21\x28\x81\x21\x21\x09\x69\x5b\xd1\x21"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-3be63c163805927e04fd7f84d96122c48240e601 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-3be63c163805927e04fd7f84d96122c48240e601
new file mode 100644 (file)
index 0000000..9e2f46a
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\xa4\x1f\xca\x21\xf0\x09\x63\x29\x5b\x27\x27\x28"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-3bf2e349747c0f539181e0d4084a5fe506811a9e b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-3bf2e349747c0f539181e0d4084a5fe506811a9e
new file mode 100644 (file)
index 0000000..5ef9b7b
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x3f\xf0\x8b\x63\x5b\x29\x28\x2d\x27\x62\x69\x6e\x09\x21\x21\x3f"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-3c5af4d73e94d0e8ad5666b6acb340f929031e95 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-3c5af4d73e94d0e8ad5666b6acb340f929031e95
new file mode 100644 (file)
index 0000000..d30756a
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x1f\x63"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-3d2b25346a9671d83bd082d170a45eed739bae6b b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-3d2b25346a9671d83bd082d170a45eed739bae6b
new file mode 100644 (file)
index 0000000..d9237e7
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x63\x5b\x90\x29\xa4\x28\x2a\xa4\x07\x3b\x5b\x28\x27\xa4\xf0\x21\x28\x2d\x0e\x09\x62\x7f\x6e\x69\x27\x21\x21\x2f\xa4\x1f\x09\xdb\xf0\x21\x1f\x28"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-3de7b860c3fba2bc55707fd6875dce276f2f249b b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-3de7b860c3fba2bc55707fd6875dce276f2f249b
new file mode 100644 (file)
index 0000000..7965bfe
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x63\x5b\x29\x28\x2d\x27\x62\x69\x6e\x09\x21\x21\x3f\xa4\x1f\xdb\xf0\x21\x10\x07\xf0\x7b\x28\x2d\x62\x69\x6e\xf0\x09\x21\x5c\x09\x21\xe5\x1f\xe9\x1b\x3b\x3f\x47\xed\x3a\x5b\x28\x28\x21\x21\x5c\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-3e2004ff9f40e398e0f41138a25a8b66e3d843d9 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-3e2004ff9f40e398e0f41138a25a8b66e3d843d9
new file mode 100644 (file)
index 0000000..4e39628
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x83\x2a\x13\x00\xa0\xae\x08\xa4\x10\x07\xf0\x5b\x28\x63\xa4\x1f\x1f\x2a\x00\x27\x5b\xf0\x5b\x28\x21\x21\x09"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-3f8983e457033cc85997c356935ba9c21460e86b b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-3f8983e457033cc85997c356935ba9c21460e86b
new file mode 100644 (file)
index 0000000..a9f27e6
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2e\x3a\xa4\x63"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-4105669086d83a20f8d991088553ba08202478cd b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-4105669086d83a20f8d991088553ba08202478cd
new file mode 100644 (file)
index 0000000..e2dc7e4
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\xa4\x1f\xdb\xf0\x21\x63\x5b\x29\x28\x27\x2d\x62\x6c\x09\x2a\x21\x21\x3f\xa4\x1f\xdb\xe2\x21\x10\x07\xf0\xf0\x7b\x28\x2d\x62\x69\x6e\x5c\x09\x63\x21\x27\x09\x21\x09\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-4180619316eef7912d1cf52ffe85897242e1ae88 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-4180619316eef7912d1cf52ffe85897242e1ae88
new file mode 100644 (file)
index 0000000..ddd5119
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x63\x5b\x29\x28\x2d\x27\x62\x69\x6e\x09\x23\x21\x3f\xa4\x1f\xdb\xf0\x21\x10\x07\xf0\x7b\x28\x2d\x62\x69\x6e\xf0\x09\x21\x5c\x09\x21\xe5\x1f\xe9\x1b\x3b\x3f\x47\xed\x3a\x5b\x28\x28\x21\x21\x5c\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-420291d7139d9246de747739fd98102434a742dd b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-420291d7139d9246de747739fd98102434a742dd
new file mode 100644 (file)
index 0000000..6c24e52
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\x2a\xa0\xa4\xae\xa0\xa4\xae\x00\x07\x10\x63\x21\x09\x5b\xf4\x28\xf0\x28\x21\x21\x5c\x09\x21\x63\x47\xfd\x29\x08\x00\x07\x10\x63\x21\x09\x5b\xf4\x28\xf0\x28\x21\x5c\x09\x21\x63\x47\xfd\x3a\xa4\xff"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-4256437fc5897c0cd5d755816e4e68c7be326849 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-4256437fc5897c0cd5d755816e4e68c7be326849
new file mode 100644 (file)
index 0000000..6abf566
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x0f\xa4\xdb\xf0\xf0\x83\x00\x63\x63\x27"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-42b25a5413c536478a3e63da5adef4250babf2f4 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-42b25a5413c536478a3e63da5adef4250babf2f4
new file mode 100644 (file)
index 0000000..b529505
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x13\x10\x00\x00\x00\x00\x00\xa4\x2f\xa4\x7e\x1f\xa4\x5b\x28\xa4\x21\x21\x1f\xff\xff\xff\xff\x0f\xa4\x00\x00"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-42bef44ae751a45c671d9da5b1231d2ac747a48d b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-42bef44ae751a45c671d9da5b1231d2ac747a48d
new file mode 100644 (file)
index 0000000..3744d17
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x83\xd3\xf5\x63\x1e\x00\x27\x5b\xf0\x69\x28\x62\x6e\x2d\x21\x3f\xa4\x1f\xdb\xf0\x21\x28\x21\x21\xf0\x09\x63"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-438c3c9045c3cf7910aceec34f77b47a70ca4abd b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-438c3c9045c3cf7910aceec34f77b47a70ca4abd
new file mode 100644 (file)
index 0000000..e60840c
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x10\x07\xf0\x5b\x28\x2d\x62\x69\x6e\x21\x09\xf0\x28\x21\x09\x21\xe5\x47\xfd\x3a\x5b\x28\x08\x21\x27\xf0\x5b\x28\xa4\x21"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-43af96b4f65ed0ace7236427f2f8833c4835989e b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-43af96b4f65ed0ace7236427f2f8833c4835989e
new file mode 100644 (file)
index 0000000..577c54a
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x1f\x21\x83\xdb\x2a\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\xa4\x0f\xa4\xf0\xf0\xdb\xf0\x63\x63\x27"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-44c6119bb91a452d6128ce0ea0d62938800779ea b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-44c6119bb91a452d6128ce0ea0d62938800779ea
new file mode 100644 (file)
index 0000000..372825d
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3b\x3f\x30\x63\x21\x28\x07\xf0\x4b\x09\xf0\x5b\x4e\x21\x5c\x19\x21\xe5\x47\x21\x5b\x28\x21\x21\x09\x21\xe5\x47\xfd\x41\x29\x28\x21\x29\xed\x21\x2a\xe5\x47\x80\xbe\xfd\x41\x29\x28\xd9\x3b\x8a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-46d595331689ae01d77aff387747a98ff3480096 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-46d595331689ae01d77aff387747a98ff3480096
new file mode 100644 (file)
index 0000000..469056b
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x83\x63\x1f\x00\x37\x5b\xf0\x69\x28\x62\x6e\x2d\x3f\x21\xa4\x1f\xdb\xf0\x21\x28\x21\x5c\xf0\x09\x63"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-471a307b81dc37459087d41532741c5c9d7ba836 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-471a307b81dc37459087d41532741c5c9d7ba836
new file mode 100644 (file)
index 0000000..df00f71
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x0e\x7f"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-48900b4a5557530922ce45c15ad0d3b0a337520d b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-48900b4a5557530922ce45c15ad0d3b0a337520d
new file mode 100644 (file)
index 0000000..e4a5c6b
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa0\xa4\xae\x08\x00\x07\x10\x5b\xf4\x28\x21\x09\x63\xf0\x28\x21\x5c\x09\x21\x63\x47\xfd\x3a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-48bcce2c6487b18706ef0c609ca39c456215bac8 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-48bcce2c6487b18706ef0c609ca39c456215bac8
new file mode 100644 (file)
index 0000000..1fb128e
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x1f"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-49027bbd3f3f3cafa315843c8fe8280f86985273 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-49027bbd3f3f3cafa315843c8fe8280f86985273
new file mode 100644 (file)
index 0000000..ea5f89e
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\xa4\x70\x62\x83\xdb\x2a\x69\x6e\x8b\xa4\x2d\x5b\x63\x27\x21\x82\xf0\xf0\xa4\xa4\xae\x08\x00\x1e\x00\x63\x21\x09\x5b\xf4"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-499376c5e291da2f9c25999abf4960fab5a92ec8 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-499376c5e291da2f9c25999abf4960fab5a92ec8
new file mode 100644 (file)
index 0000000..b1a1bf6
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x83\x00\x2a\x21\x13\xa0\xae\x08\xa4\x10\x07\xf0\x5b\x28\x63\xa4\x1f\x1f\x2a\x27\x5b\x5b\xf0\x28\x00\x21\x21\x09"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-4a3b7ce0cdf217963a0b692769e5d6f4befe73b8 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-4a3b7ce0cdf217963a0b692769e5d6f4befe73b8
new file mode 100644 (file)
index 0000000..4e0e43d
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x1f\x21\x83\xdb\xf0\xf0\xa4\x1f\x21\x83\x2a\xf0\xae\xa0\xa4\x08\x00\x07\x10\xf4\x21\x28\x5b\x09\x63\xf0\xf0\x28\x21\x5c\x09\x21\x2a\x63\xa0\xa4\xae\x08"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-4a3fdb96bc8c80f1992f0f72f963f84856cbade8 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-4a3fdb96bc8c80f1992f0f72f963f84856cbade8
new file mode 100644 (file)
index 0000000..98e8067
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x83\x63\x1d\x1f\x00\x27\x5b\xf0\x69\x28\x62\x6e\x2d\x21\x3f\xa4\x1f\xdb\xf0\x21\x28\x21\x5c\xf0\x09\x63"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-4aae80e05793d7adb42a7e6e8a5283b677318777 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-4aae80e05793d7adb42a7e6e8a5283b677318777
new file mode 100644 (file)
index 0000000..e36b6b7
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x28\x42\xa4\x01\x3a\x3f\xf0\x1f\x63"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-4c7a034d3a3b4f29d99caf021a0e9bbb89706c2e b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-4c7a034d3a3b4f29d99caf021a0e9bbb89706c2e
new file mode 100644 (file)
index 0000000..02186fc
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x63\x5b\x28\x21\x21\x09\x21\xe5\x47\xfd\x41\x29\x28\x21\x29\xed\x21\xbc\x2a\x29\xd9\x8a\x3b\x2a\x87\x3a\x2a\xd5\xee\x28\xf9\x29\x5d\x28\x28\x3b\x27\x27\x3b\x96\x25\xeb\x29\xe6\xd3\x90\xf5\x33\x29\x27\xd3\x29\xca\xd1\x43\x2a\x29\x9c\x95\x00\x29\x28\xf0\x65"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-4ce8a43fb17a075627160812ad26c25210d8a82d b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-4ce8a43fb17a075627160812ad26c25210d8a82d
new file mode 100644 (file)
index 0000000..25e14ab
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x63\x29\x28\x2d\x27\x2a\x69\x6e\x09\x21\x21\x3f\xa4\x1f\xdb\xf0\x21\x21\x10\x07\xf0\x7b\x28\x2d\x62\x69\x6e\xf0\x09\x21\x5c\x48\x21\x1f\xe5\xe9\x1b\x3b\x3f\x47\xed\x3a\x5b\x28\x28\x21\x21\x5c\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-5032a75a98cd14d4dab75c1c5e2cd981abb19dcf b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-5032a75a98cd14d4dab75c1c5e2cd981abb19dcf
new file mode 100644 (file)
index 0000000..5691e50
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x83\x28\x5b\x27\x28\x63\x69\xf0\x00\x62\x6e\x2d\x21\x3f\xa4\x1f\xdb\xf0\x21\x28\x21\x5c\x28\x09\x63"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-50b3f4b6aed97f442496d27f3b4315a18ba76d5f b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-50b3f4b6aed97f442496d27f3b4315a18ba76d5f
new file mode 100644 (file)
index 0000000..2ec038d
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3b\x3b\x3f"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-51064b88a98658d48a0da7f1545c2d1293ad9538 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-51064b88a98658d48a0da7f1545c2d1293ad9538
new file mode 100644 (file)
index 0000000..4dda506
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\xa4\x0f\xa4\xdb\x27\x28\x3f\xa4\x07\xf0\x3b\x5b\x28\x27\xa4\xf0\x21\x09\x1f\x28"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-51752f12d59fadaaa0dc72e6370612b84ee1555b b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-51752f12d59fadaaa0dc72e6370612b84ee1555b
new file mode 100644 (file)
index 0000000..c956944
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa0\xa4\xae\x40\x08\x10\x07\x3a\xf0\x5b\x28\xf8\x63\x09\x28\x3b\xfe\x21\x21\x5c\x27\x21\x63\xe5\x47\xfd\x3a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-51eff6fcbfe1a51ceb3f5f2140c01eea89b4313d b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-51eff6fcbfe1a51ceb3f5f2140c01eea89b4313d
new file mode 100644 (file)
index 0000000..c6e5f4b
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x1f\xa4\xdb\xf0\xf0\x83\x63\x63\x27"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-51f65f681cf3a1218d83ad58642c06deaea86210 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-51f65f681cf3a1218d83ad58642c06deaea86210
new file mode 100644 (file)
index 0000000..5da2d77
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x10\x07\xf0\x5b\x28\x2d\x62\x69\x6e\xa4\x2d\xa4\xa4\xf0\x07\x10\x62\x69\x6e\x8b\x63\x5b\x29\x28\x2d\x27\x62\x69\x6e\xa4\x1f\x3f\x21\xf0\x09\xdb\x23\x21\x10\x07\xf0\x7b\x28\x0d\x62\x69\x6e\xf0\x21\x09\xf0\x28\x09\x21\x21"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-521809903d36db80b1ccd707f354361f2bf05075 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-521809903d36db80b1ccd707f354361f2bf05075
new file mode 100644 (file)
index 0000000..0cd8df4
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x13\x00\x00\x00\x00\x2f\xa4\x1f\xa4\x5b\x28\x21\x21\xa4\x1f\xdb\xa4\x09\x21\x5b\xf0\x21\xe5\xdb\x2a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-5278e3581c069624157fd9176eddf52c0e58df67 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-5278e3581c069624157fd9176eddf52c0e58df67
new file mode 100644 (file)
index 0000000..e6833ef
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x0c\xa4\x1f\xa4\x3b\xdb\xe2\xf0\x09\x63\x2e\x00\xa4\x2a\x63\xa0\xa4\xae\x63\x08\x27\x00\x10\x07\x00\x0d\x61\x75\x74\x68\x6f\x72\x69\x7a\x61\x74\x69\x6f\x6e\x00\xf0\x5b\x28\x21\x09\x63\xf0\x28\x21\x5c\x09\x21\xa0\xa4\x08\x00\x63\xe5\x47\xfd\x63\x63\x3a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-52fe8f0e1fa270ea16f66c93f2ffab265ce059e8 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-52fe8f0e1fa270ea16f66c93f2ffab265ce059e8
new file mode 100644 (file)
index 0000000..210e337
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3b\x3f\x27\x63\x07\xf0\x5b\x28\x21\x09\xf0\x5b\x4e\x21\x5c\x09\x62\xe5\x33\x47\xfd\x21\x2a\x28\x21\x21\x09\x42\xe5\x47\xfd\x41\x29\x28\x21\x29\xed\x21\x64\x2a\x29\xe5\x47\xfd\x49\x29\x28\xd9\x3b\x29\x8a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-53de87ae94acdc8e58a369459c12a3240f1294fe b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-53de87ae94acdc8e58a369459c12a3240f1294fe
new file mode 100644 (file)
index 0000000..82650e3
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3f\x2a\xa0\xa4\xae\x40\x08\x10\xf0\x3a\x07\x5b\x06\xf8\x63\x09\x28\x3b\xfe\x21\x21\x5c\xf0\x09\x21\x7e\x09\x1f\xdb\xe5\x47\xfd\x21\xf0\x63\x6d\x3a\x27"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-54a2b3993c3483745f6314c870a038a8e58f97a7 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-54a2b3993c3483745f6314c870a038a8e58f97a7
new file mode 100644 (file)
index 0000000..1fe3376
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x83\x63\x27\x1f\x00\x27\x5b\x29\xf0\x69\x28\x62\x6e\x2d\x21\x3f\xa4\x1f\xdb\xf0\x21\x09\xf0\x28\x21\x5c\x63"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-55d60c2e5040a38be8ca41de63e137e3fef892a4 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-55d60c2e5040a38be8ca41de63e137e3fef892a4
new file mode 100644 (file)
index 0000000..2aeead3
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x63\x5b\x28\x2a\x29\x3f\xa0\xa4\xae\x40\x08\x10\x07\x3a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-5653c44a5b520bdf2bdc599b7966f1d7c44950b3 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-5653c44a5b520bdf2bdc599b7966f1d7c44950b3
new file mode 100644 (file)
index 0000000..ab80f6f
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x7f"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-5838b5a683229ebb6e6277e2810863e642b8afc2 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-5838b5a683229ebb6e6277e2810863e642b8afc2
new file mode 100644 (file)
index 0000000..668209e
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x70\x83\xdb\xf0\xf0\xa4\x1f\x21\x83\x1e\x00\xcb\x54\xf0\x2a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-588d225784891ac88e30ac6eb5651d63fac34083 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-588d225784891ac88e30ac6eb5651d63fac34083
new file mode 100644 (file)
index 0000000..c0f483b
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x21\x63\x5b\x29\x28\x2d\x27\x62\x69\x6e\x09\x21\x21\x3f\xa4\x1f\xdb\xf0\x21\x10\x07\xf0\x7b\x28\x2d\x62\x69\x6e\xf0\x09\x21\x5c\x09\x21\xe5\x1f\xe9\x1b\x3b\x3f\x47\xed\x3a\x5b\x28\x28\x21\x21\x5c\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-58d51c21a20b6549567a0ab8fee29d162dd3fc5a b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-58d51c21a20b6549567a0ab8fee29d162dd3fc5a
new file mode 100644 (file)
index 0000000..0e56658
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x63\x5b\x29\x28\x3b\x2d\x27\x27\x62\x69\x6e\x09\x21\x21\x3f\xa4\x1f\xdb\xf0\x21\x10\x07\xf0\x7b\x28\x2d\x62\x69\x6e\xf0\x09\x21\x5c\x09\x21\xe5\x1f\xe9\x1b\x3b\x3a\x3f\xed\xe5\x5b\x28\x28\x21\x3b\x21\x5c\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-58f1036d8ff855841ec25b3c33e85a8fec0d94b7 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-58f1036d8ff855841ec25b3c33e85a8fec0d94b7
new file mode 100644 (file)
index 0000000..8d638f4
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x63\x5b\x29\x2d\x27\x62\x69\x6e\x09\x31\x21\x3f\xa4\x1f\xdb\xf0\x21\x3b\x27\x10\x07\x2a\xf0\x7b\x28\x2d\x62\x69\x6e\xf0\x09\x21\x5c\x09\x21\xe5\x1f\xe9\x1b\x3b\x3f\x47\xed\x3a\x5b\x28\x28\x21\x21\x4c\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-5a99df42fb7bbafa2d55714ee235b1c46776b2ad b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-5a99df42fb7bbafa2d55714ee235b1c46776b2ad
new file mode 100644 (file)
index 0000000..ff8ba90
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x1f\x5b\xf0\x21\xf0\x09\x63\x27"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-5b42793550699b2c015bed677cfcddc052f73513 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-5b42793550699b2c015bed677cfcddc052f73513
new file mode 100644 (file)
index 0000000..62d7cc2
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x70\x83\xdb\xf0\xf0\xa4\x1f\x21\x83\xdb\xf0\x29\xf0\x63"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-5b8ca72ba00231c38b19f582127e6a146eba4282 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-5b8ca72ba00231c38b19f582127e6a146eba4282
new file mode 100644 (file)
index 0000000..b83768e
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3b\x3f\x27\x63\x07\xf0\x5b\x28\x21\x09\xf0\x5b\x4e\x21\x5c\x09\x21\xe5\x47\xfd\x21\x2a\x28\x21\x09\x21\xd4\xe5\x47\xfd\x41\x29\x28\x21\x29\xed\x21\xbc\x2a\x29\xe5\x47\xfd\x49\x29\x28\xd9\x3b\x29\x8a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-5baa13dc95da05e7ba02bbe9583ea24517a29a1a b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-5baa13dc95da05e7ba02bbe9583ea24517a29a1a
new file mode 100644 (file)
index 0000000..52fbb64
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\xa4\xf0\x5b\x63\x27\x21\x29\xa4\x10\x62\x69\x17"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-5bab61eb53176449e25c2c82f172b82cb13ffb9d b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-5bab61eb53176449e25c2c82f172b82cb13ffb9d
new file mode 100644 (file)
index 0000000..9c2dbb6
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3f"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-5c6f6b6f7f3e7b435f060abb73c20d2b773a7f56 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-5c6f6b6f7f3e7b435f060abb73c20d2b773a7f56
new file mode 100644 (file)
index 0000000..8fb7ee2
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3b\x3f\x30\x63\x21\x28\x07\xf0\x4b\x09\xf0\x5b\x4e\x21\x5c\x19\x21\xe5\x47\x21\x5b\x28\x21\x21\x09\x21\xe5\x47\xfd\x41\x29\x28\x21\x29\xed\x21\x2a\xe5\x47\x80\xbe\x41\x29\x28\xd9\x3b\x8a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-5c9fd9cc7100feaeead1e0e45201945a6e76fd85 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-5c9fd9cc7100feaeead1e0e45201945a6e76fd85
new file mode 100644 (file)
index 0000000..cea5fbd
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa0\xa4\xae\x08\x00\x07\x10\x63\x00\x00\x21\x00\x09\x29\x5b\x28\xf0\x28\x21\x5c\x09\x21\x63\x47\x00\x2f\xa4\x1f\xa4\xa4\x1f\xfd\x3a\xdb\xa4\xdb\x2a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-5ff49c9edc7361797a951585f3e180222c8dd95d b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-5ff49c9edc7361797a951585f3e180222c8dd95d
new file mode 100644 (file)
index 0000000..cc9de44
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3f\x2a\xa0\xa4\xae\x40\x08\x10\x07\x3a\xf0\x5b\x28\xf8\x63\x09\x28\x3b\xfe\x21\x21\x5c\xf0\x09\x21\x63\x09\x1f\xe5\xdb\x47\xfd\x21\xf0\x63\x6d\x3a\x27"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-6129954942e26c2a9ec071b6659675745613cf3c b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-6129954942e26c2a9ec071b6659675745613cf3c
new file mode 100644 (file)
index 0000000..18329c4
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x1f\x21\x83\xdb\xf0\xf0\xa4\x1f\x21\x83\xdb\x2a\xf0\xae\xa0\xa4\x08\x00\x05\x10\xf4\x21\x28\x5b\x09\x63\xf0\xf0\x28\x21\x5c\x09\x21\x2a\x63\xa0\xa4\xae\x08"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-61fa69b6b51b0ed91914fe48779173f8d26a1d54 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-61fa69b6b51b0ed91914fe48779173f8d26a1d54
new file mode 100644 (file)
index 0000000..576c36b
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x63\x5b\x29\x28\x2d\x27\x62\x69\x6e\x09\x3b\x21\x21\x3f\xa4\x1f\xdb\xf0\x21\x10\x07\xf0\x7b\x28\x2d\x62\x69\x6e\xf0\x09\x21\x5c\x09\x21\xe5\x1f\xe9\x1b\x3b\x3f\x47\xed\x5b\x28\x28\x21\x21\x5c\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-6362ac61cfb6e964aff78f3cd648475dfd5fd4e9 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-6362ac61cfb6e964aff78f3cd648475dfd5fd4e9
new file mode 100644 (file)
index 0000000..abc9cec
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3b\x3f\x27\x63\x07\xf0\x5b\x28\x21\x09\xf0\x5b\x4e\x21\x5c\x09\x62\xe5\x33\x47\xfd\x21\x2a\x28\x21\x21\x09\x42\xe5\x47\xfd\x41\x29\x28\x21\x29\xed\x21\xbc\x2a\x29\xe5\x47\xfd\x49\x29\x28\xd9\x3b\x29\x8a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-644deba51c79b6ebd470bd4367452941045d112a b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-644deba51c79b6ebd470bd4367452941045d112a
new file mode 100644 (file)
index 0000000..1c33e28
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x87\x63\x1f\x00\x27\x5b\xf0\x69\x87\x62\x6e\x2d\x21\x3f\xa4\x1f\xdb\xf0\x21\x28\x21\x5c\xf0\x08\x63"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-64beae98e2276749b133e6368c9e0f19a79eba96 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-64beae98e2276749b133e6368c9e0f19a79eba96
new file mode 100644 (file)
index 0000000..abdfb2b
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x63\x5b\x29\xa4\x28\x2d\x0e\x09\x62\x7f\x6e\x69\x27\x21\x21\x2f\xa4\x1f\xdb\xf0\x21"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-64d7add9192301fd878854dc96f9fa9053f03992 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-64d7add9192301fd878854dc96f9fa9053f03992
new file mode 100644 (file)
index 0000000..2ee4fca
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x1f\x21\x83\xdb\xf0\xf0\x63\x63\x27\x5f"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-65566df65e8f55428b6672cc351df414fa8f936c b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-65566df65e8f55428b6672cc351df414fa8f936c
new file mode 100644 (file)
index 0000000..bb04516
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x27\xf0\x5b\x28\x21\x21\x09\xf0\x5b\x28\x21\x21\x09\x21\xe5\x47\xfd\x21\xe5\x47\xfd\x41\x29\x28\x21\x29\xed\x21\xbc\x29\xd9\x3a\x3b\x87\x8a\x2a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-65bb703af35d5afb824cd68c41d7a1aeb3848d35 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-65bb703af35d5afb824cd68c41d7a1aeb3848d35
new file mode 100644 (file)
index 0000000..c2a0c1e
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x5b\xf0\x21\xf0\x09\x27\x28\x21\x5b\x28\x21\x21\x09\x21\xe5\x47\xfd\x21\xe5\x47\xfd\x41\x29\x28\x21\x29\xed\x21\xbc\x29\xd9\x3a\x3b\x87\x8a\x2a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-66c537bf59cb3667c037b3517be3d31245c9da8a b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-66c537bf59cb3667c037b3517be3d31245c9da8a
new file mode 100644 (file)
index 0000000..f9f6b95
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x63\x5b\x29\x28\x2d\x27\x62\x69\x6e\x29\x23\x21\x3f\xa4\x1f\xdb\xf0\x21\x10\x07\xf0\x7b\x28\x2d\x62\x69\x6e\xf0\x09\x21\x5c\x21\xe5\x1f\xe9\x1b\x3b\x3f\x47\xed\x3a\x5b\x28\x28\x21\x21\x5c\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-66f576baeb0c9435a56eb7375dadc5b5d630ed87 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-66f576baeb0c9435a56eb7375dadc5b5d630ed87
new file mode 100644 (file)
index 0000000..a57e244
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3f\x2a\xa0\xa4\xae\x50\x08\x10\x07\xae\x80\xa4\x88\x3a\xf0\x5b\x06\xf8\x63\x09\x38\x3b\xfe\x21\x21\x5c\xf0\x09\x21\x7e\x28\x09\x1f\xdb\x44\x47\xfd\x21\xf0\x6d\x63\x3a\x63\x27"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-67b4cec5183659aeae0f5bc71b3adf0542a11828 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-67b4cec5183659aeae0f5bc71b3adf0542a11828
new file mode 100644 (file)
index 0000000..412e613
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x83\x63\x1f\x62\xf0\x00\x6e\x5b\x28\x27\x2d\x21\x3f\xa4\x1f\xdb\xf0\x21\x28\x21\x5c\xf0\x09\x63"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-68c94721eda2f62481bff9f1d183df70498d0c5b b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-68c94721eda2f62481bff9f1d183df70498d0c5b
new file mode 100644 (file)
index 0000000..36eb314
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x21\x6e\x8b\xa4\x2d\x5b\x63\x27\x21\x29\xa4\x10\x62\x69\x07"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-68ee8169a65d58edb9fc1c752ea81dfec383203c b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-68ee8169a65d58edb9fc1c752ea81dfec383203c
new file mode 100644 (file)
index 0000000..4dab96d
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x28\x29\x5b\x63\x2d\x27\x62\x69\x6e\x09\x21\xf0\xdb\xa4\x1f\x21\x0d\x3f\x10\x07\xf0\x7b\x28\x2d\x62\x69\x6e\xf0\x09\x21\x5c\x09\x21\xe5\x1f\xe9\x1b\x3b\x3f\x47\xed\x3a\x5b\x28\x28\x23\x21\x5c\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-6b203d49bbba6ee74def0d35c2266e06ad3c45d9 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-6b203d49bbba6ee74def0d35c2266e06ad3c45d9
new file mode 100644 (file)
index 0000000..21f5d6c
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa0\xa4\xae\x08\x00\x07\x10\x63\x00\x00\x21\x09\x00\x5b\xf4\x3b\x3f\x30\x63\x21\x28\x07\xf0\x4b\x09\xf0\x5b\x4e\x21\x5c\x19\x21\xe5\x47\x21\x5b\x28\x21\x21\x09\x21\xe5\x47\xfd\x41\x29\x28\x21\x29\xed\x21\x2a\xe5\x47\x80\xbe\xfd\x28"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-6d580f28d785c0bf87ac351a31a89289449feadb b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-6d580f28d785c0bf87ac351a31a89289449feadb
new file mode 100644 (file)
index 0000000..2ae1902
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x63\x5b\x29\xa8\x2d\x2e\x27\x62\x69\x2a\x09\x21\x21\x28\x3f\xa4\x1f\xdb\x21\xf0\x21\x10\x07\x3a\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-6f231dec759eb2105e09263d53e171de19a92c74 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-6f231dec759eb2105e09263d53e171de19a92c74
new file mode 100644 (file)
index 0000000..f288bea
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x1f\x21\x83\xdb\xf0\xf0\xa4\x1f\x21\x83\xdb\x2a\xf0\xae\xa0\xa4\x1f\x00\x08\x00\x07\x10\xf4\x21\x28\x5b\x09\x63\xf0\xf0\x28\x21\x7c\x09\x21\x2a\xa0\xae\x1e\xa4\x63\x00\x08"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-70ff6621a09e4f641538cb1b27e8b382b2f56a94 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-70ff6621a09e4f641538cb1b27e8b382b2f56a94
new file mode 100644 (file)
index 0000000..f7803c1
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x1f\x21\x83\xdb\x2a\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\xa4\x0f\xa6\xf0\xf0\xdb\xf0\x63\x63\x27"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-71981b55f27a1eb6274eda247048fa2c597f5004 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-71981b55f27a1eb6274eda247048fa2c597f5004
new file mode 100644 (file)
index 0000000..3897579
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3b\x3f\x27\x63\x07\xf0\x5b\x28\x21\x09\xf0\x5b\x4e\x21\x5c\x09\x21\xe5\x47\xfd\x21\x2a\x28\x21\x09\x21\xe5\x47\xfd\x41\x29\x28\x21\x21\xed\x21\xbc\x28\x2a\x29\xe5\x47\xfd\x49\x29\x28\xd9\x3b\x29\x8a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-71c2b0bebf7f0e916e4ab7eb36d47ccca2b9101c b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-71c2b0bebf7f0e916e4ab7eb36d47ccca2b9101c
new file mode 100644 (file)
index 0000000..8cada70
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\x2a\xa0\xa4\xae\xa0\xa4\xae\x08\x00\x07\x10\x63\x21\x09\x5b\xf4\x28\xf0\x28\x21\x5c\x09\x21\x63\x47\xfd\x3a\x08\x00\x07\x10\x63\x21\x09\x5b\xf4\x28\xf0\x28\x21\x5c\x09\x21\x63\x47\xfd\x3a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-74610e278a5b90aa12ce1beaf222c4306b02ed43 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-74610e278a5b90aa12ce1beaf222c4306b02ed43
new file mode 100644 (file)
index 0000000..9582656
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x63\x5b\x69\xa4\x28\x2d\x07\x0e\x7f\x27\x62\x69\x6e\x09\x21\x21\x3f\xa4\x1f\xdb\xf0\x21"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-748ee9817eba56ec9938601a0e380c74bad4563f b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-748ee9817eba56ec9938601a0e380c74bad4563f
new file mode 100644 (file)
index 0000000..102fb72
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x63\x5b\x29\x28\x27\x2d\x62\x69\x6e\x09\x21\x21\x3f\xa4\x1f\xdb\xf0\x21\x10\x07\xf0\x7b\x28\x2d\x62\x69\x5c\x6e\x21\x09\x21\x09\xf0\xe5\x1f\xe9\x1b\x3b\x3f\x47\xed\x3a\x5b\x28\x28\x21\x21\x5c\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-7727e3eeb2a48c46bf5a678c300ff8a38b8ffe3a b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-7727e3eeb2a48c46bf5a678c300ff8a38b8ffe3a
new file mode 100644 (file)
index 0000000..8d3bbe9
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3f\x2a\xa0\xa4\xae\x50\x08\x10\x07\xae\x80\xa4\x88\x3a\xf0\x5b\x06\xf8\x63\x09\x38\x3b\xfe\x21\x21\x5c\xf0\x09\x21\x7e\x28\x09\x1f\xdb\x44\x47\xfd\x21\xf0\x63\x6d\x63\x3a\x63\x27"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-78176d80c1d74c4b1b820d386ae483ac4d1d92b7 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-78176d80c1d74c4b1b820d386ae483ac4d1d92b7
new file mode 100644 (file)
index 0000000..a29835d
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x28\x3f\xa4\x1f\x9b\xf0\x21\x09\x63"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-789abb571563a6795220046f76b7cf0ade90743c b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-789abb571563a6795220046f76b7cf0ade90743c
new file mode 100644 (file)
index 0000000..6d6b9eb
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x63\x5b\x29\x28\x2d\x2e\x27\x62\x69\x6e\x09\x21\x21\x3f\xa4\x1f\xdb\xf0\x21\x10\x07\x3a\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-78f5ff40e5554aa9c31b45f79a7ae9699f93e7fd b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-78f5ff40e5554aa9c31b45f79a7ae9699f93e7fd
new file mode 100644 (file)
index 0000000..a779e59
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x83\x63\xa4\x1f\xa4\xdb\xf0\x21\xf0\x09\x63\x1f\x00\x27\x5b\xf0\x69\x28\x62\x6e\x2d\x21\x3f\xa4\x1f\xdb\xf0\x63\x21\x27\x28\x21\x5c\xf0\x09\x63"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-7a28fc2e9c72d51d29e87eed63ed405c9779b5e1 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-7a28fc2e9c72d51d29e87eed63ed405c9779b5e1
new file mode 100644 (file)
index 0000000..339b8c1
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x0f\xa4\xdb\xf0\xf0\x83\x80\x63\x63\x27"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-7a42083be21dce7f96edef1f3b3b2fea0bcaeb3f b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-7a42083be21dce7f96edef1f3b3b2fea0bcaeb3f
new file mode 100644 (file)
index 0000000..d8c49a8
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x63\x5b\x29\x28\x2d\x27\x62\x69\x6e\x09\xab\x21\x3f\xa4\x1f\xdb\xf0\x21\x3b\x10\x07\x2a\xf0\x7b\x28\x2d\x62\x69\x6e\xf0\x09\x21\x5c\x09\x21\xe5\x1f\xe9\x1b\x3b\x3f\x47\xed\x3a\x5b\x28\x28\x21\x21\x5c\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-7a51275b11ecb1efec9251390531681c8d6f2481 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-7a51275b11ecb1efec9251390531681c8d6f2481
new file mode 100644 (file)
index 0000000..bae8f15
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x24\x0f\xa4\xdb\x3b\xf0\x83\x00\x63\x63\x27"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-7b9682cd7a3984698f6eac034c59c0f91b4fb83d b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-7b9682cd7a3984698f6eac034c59c0f91b4fb83d
new file mode 100644 (file)
index 0000000..c7b1444
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x83\x63\xa4\x1f\x1f\x00\x27\x5b\xf0\x69\x28\x62\xa4\xdb\xf0\xf0\x09\x63"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-7ba7239a29d6183960e3986abc8f19cfb548b905 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-7ba7239a29d6183960e3986abc8f19cfb548b905
new file mode 100644 (file)
index 0000000..816d36c
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x1f\x21\x83\xdb\xf0\xf0\x63\x63\x27"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-7d3b3d5f23d0ede9f7e5dbd1115db58c8a54a213 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-7d3b3d5f23d0ede9f7e5dbd1115db58c8a54a213
new file mode 100644 (file)
index 0000000..50b0f76
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x63\x5b\x29\xa8\x2d\x27\x62\x69\x6e\x09\x27\x21\x21\x3f\xa4\xdb\xf0\x21\x10\x07\xf0\x7b\x3b\x3f\x30\x63\x21\x28\x2d\x62\x28\x69\x6e\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-7ff3b6239b04479a9caf67f45b2d0c619f712815 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-7ff3b6239b04479a9caf67f45b2d0c619f712815
new file mode 100644 (file)
index 0000000..811a8da
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\x2a\xa0\xa4\xae\xa0\xa4\xae\x08\x00\x07\x10\x63\x21\x09\x5b\xf4\x28\xf0\x28\x21\x5c\x09\x21\x63\x47\xfd\x3a\x08\x00\x07\x10\x63\x21\x09\x5b\xf4\x28\x47\x21\xf0\x21\x63\x09\x28\x5c\xfd\x3a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-8035c81c95dedfc27c3649064f98f49e3e72c21f b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-8035c81c95dedfc27c3649064f98f49e3e72c21f
new file mode 100644 (file)
index 0000000..2605ec0
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x83\x63\x27\x1f\x00\x27\x5b\xf0\x69\x28\x62\x6e\x2d\x21\x3f\xa4\x0f\xdb\xf0\x21\x28\x21\x5c\xf0\x09\x63"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-804e1052842ce4d44b9c775ade2b18fcb8ce7bcf b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-804e1052842ce4d44b9c775ade2b18fcb8ce7bcf
new file mode 100644 (file)
index 0000000..ebefd36
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x1f\x2d\x62\x69\x6e\x8b\xa4\x2d\x5b\x63\x27\x21\x29\xa6\x10\x62\x69"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-80514b85933ea9bdd3462595f949c5af24409b87 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-80514b85933ea9bdd3462595f949c5af24409b87
new file mode 100644 (file)
index 0000000..004e745
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x63\x5b\x29\xa4\x27\x0f\x28\xad\xa4\xdb\xf0\x27\xf0\x28\x83\x63\x69\x6e\x09\x21\x21"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-8057c32b8bd28a5ec2105d62f2abe8cf69c9f5fc b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-8057c32b8bd28a5ec2105d62f2abe8cf69c9f5fc
new file mode 100644 (file)
index 0000000..4274208
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x66\x13\x21\x28\x21\x21\x63\x27\x09\x69\x5b\xd1\x21\xf0\x5b\x28\x21\x21\x09\xf0\x5b\x28\x21\x21\x09\x21\xe5\x48\xfd\x21\x5b\x28\x21\x21\x09\x21\xe5\x47\xfd\xe5\x41\x29\x28\x21\x29\xed\x21\xbc\x2a\x29\xe5\x47\xfd\x41\x29\x28\xd9\x21\x29\x8a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-806a3bd4e078d91adeacedfd3e47ef8ae229244a b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-806a3bd4e078d91adeacedfd3e47ef8ae229244a
new file mode 100644 (file)
index 0000000..cf4e80b
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x63\x5b\x29\x3a\xa4\x0f\x28\x2d\xa4\xdb\xf0\x27\xf0\x62\x83\x63\x69\x6e\x09\x21\x21"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-8090444f98218e65ff9594789ff22bbea3c0497c b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-8090444f98218e65ff9594789ff22bbea3c0497c
new file mode 100644 (file)
index 0000000..e421338
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xd5\x1f\xf0\x63\xaa\x09\xdb\xf0\x27"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-80e516692955d5f224706f268e247858858e16d8 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-80e516692955d5f224706f268e247858858e16d8
new file mode 100644 (file)
index 0000000..9bc37fc
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x83\x2a\xa0\xa4\xae\x40\x00\x10\x07\xf0\x5b\x63\x3b\x63\x1d\xa4\x1f\x21\x83\xdb\xf0\xf0\xa4\x1f\x1f\x21\x83\xdb\x00\x27\x5b\xf8\x21\x28\x09\xfe\x28\x21\x5c\x09\x21\x63\xe5\x47\x2a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-810a1372fa97380265f5529c5043ae96f007f5bb b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-810a1372fa97380265f5529c5043ae96f007f5bb
new file mode 100644 (file)
index 0000000..835cd35
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x87\x63\x1f\x28\x00\x27\x5b\xf0\x69\x87\x62\x6e\x2d\x21\xc8\x3f\x3f\xa4\x28\x1f\xdb\xa4\xf0\x21\x28\x21\x5c\xf0\x08\x63\x1f\x9b\xf0\x21\x09\x3a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-8127597d3c146b2a89579e44daef9d03a0f941ec b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-8127597d3c146b2a89579e44daef9d03a0f941ec
new file mode 100644 (file)
index 0000000..298cf40
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\x40\xae\xa4\xa0\x08\x10\x07\x3a\xf0\x5b\x28\xf8\x63\x09\x28\x3b\xfe\x21\x21\x5c\x09\x21\x63\xe5\xa4\x47\xfd\x3a\x7f"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-82ed571f8922caa572d13b4cc9b5c5fabafaade9 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-82ed571f8922caa572d13b4cc9b5c5fabafaade9
new file mode 100644 (file)
index 0000000..5a82576
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x63\x5b\x29\x28\x2d\x27\x62\x69\x6e\x09\x21\x21\x3f\xa4\x21\x1f\xf0\xdb\x10\x07\xf0\x7b\x28\xf6\x62\xe9\x6e\xf0\x09\x21\x09\x5c\x21\xe5\x1f\xe9\x1b\x3b\x3f\x47\xed\x3a\x5b\x28\x28\x21\x21\x5c\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-8328e86178800f87a3bf6f80749984f45b0cd0e8 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-8328e86178800f87a3bf6f80749984f45b0cd0e8
new file mode 100644 (file)
index 0000000..5af84d9
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x28\x3f\x2a\xa4\x21\x07\xf0\xa4\x0f\x68\x65\x6d\x65\x83\xa4\x07\x27\x07\x28\x27\xa4\xf0\x21\x63\x09"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-84441efd7d8bdb0ce2fac28f218d3d5d4d77f1d4 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-84441efd7d8bdb0ce2fac28f218d3d5d4d77f1d4
new file mode 100644 (file)
index 0000000..edd5abe
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x1f\x21\x83\xdb\xf0\xf0\xa4\x1f\x21\x83\xdb\x2a\x2a\xae\xa0\xa4\x08\x00\x07\x28\x10\x5f\x21\x28\x5b\x09\x63\xf0\xf0\x28\x21\xf0\x21\x2a\x63\xa0\xa4\xae\x08"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-84cbf70f45a64d5a01d1c96367b6d6160134f1ad b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-84cbf70f45a64d5a01d1c96367b6d6160134f1ad
new file mode 100644 (file)
index 0000000..bdb58ea
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3b\x3f\x30\x63\x21\x28\x07\xf0\x4b\x09\xf0\x5b\x4e\x21\x5c\x19\x21\xf5\x47\x21\x5b\x28\x21\x21\x09\x21\xe5\x47\xfd\x41\x29\x28\x21\x29\xed\x21\x2a\xe5\x47\x80\xbe\xfd\x41\x29\x28\xd9\x2b\x29\x8a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-85eb0f4502a51e646dab4ae08eabd90613cdf8e1 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-85eb0f4502a51e646dab4ae08eabd90613cdf8e1
new file mode 100644 (file)
index 0000000..a4ea312
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x1f\x21\x83\xdb\xf0\xf0\xa4\x1f\x21\x83\xdb\x2a\xf0\xae\xa0\xa4\x08\x00\x07\x10\xf4\x21\x28\x5b\x09\x63\xf0\xf0\x28\x21\x5c\x09\x21\x2a\x63\xa0\xa4\xae\x08"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-86080f33e4eae21b37863c253ce61eaa13021a97 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-86080f33e4eae21b37863c253ce61eaa13021a97
new file mode 100644 (file)
index 0000000..1c2da8a
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\x2a\xa0\xa4\xae\xa0\xa4\xae\x08\x00\x07\x10\x63\x21\x09\x5b\xf4\x28\xf0\x28\x21\x5c\x09\x21\x63\x27\x47\xfd\x3a\x08\x00\x07\x10\x63\x21\x09\x5b\xf4\x28\xf0\x28\x21\x5c\x09\x21\x63\x47\xfd\x3a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-862e3ccf601ee0f7fbd8b23e6811fd50485a118f b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-862e3ccf601ee0f7fbd8b23e6811fd50485a118f
new file mode 100644 (file)
index 0000000..e6e691d
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x63\x5b\x29\x28\x2d\x27\x62\x69\x6e\x09\x21\x21\x3f\x4f\x1f\xdb\xf0\x21\x10\x07\xf0\x7b\x28\x2d\x62\x09\x5c\x6e\x69\x21\xf0\x09\x21\xe5\x1f\xe9\x1b\x3b\x3f\x47\xed\x5b\x28\x28\x21\x21\x5c\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-86bae059b18af8ae263e5ae0022b67da0cfc0fbe b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-86bae059b18af8ae263e5ae0022b67da0cfc0fbe
new file mode 100644 (file)
index 0000000..081ab39
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xff"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-870f9cc4bd89c6c04c6a51ceae1efa8634627cd6 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-870f9cc4bd89c6c04c6a51ceae1efa8634627cd6
new file mode 100644 (file)
index 0000000..e588782
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3f\x2a\xae\x40\x08\x3a\x5b\x07\x10\xf0\x06\xf8\x63\x09\x28\x21\x21\x5c\xfe\x3b\xf0\x01\x21\x7e\x09\x1f\xdb\xe5\x47\xfd\x21\xd0\x61\x6d\x3a\x27"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-8762a523cdb78d2344d553fa52a229bd63c44e51 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-8762a523cdb78d2344d553fa52a229bd63c44e51
new file mode 100644 (file)
index 0000000..728266c
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x1f\xa4"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-894211571f9153c3c2ea4102541dac69be8aaa9c b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-894211571f9153c3c2ea4102541dac69be8aaa9c
new file mode 100644 (file)
index 0000000..9265142
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x00\x00\x00\x00\x2f\xa4\x5d\xa4\xa4\x1f\xdb\xa4\xa8\xdb\x2a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-894e9b7832c52acb04bfa994ef53c7105d8db206 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-894e9b7832c52acb04bfa994ef53c7105d8db206
new file mode 100644 (file)
index 0000000..ca83895
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3f\x2a\xae\x40\x08\x3a\x5b\x07\x10\xf0\x06\xf8\x63\x09\x28\x21\x21\x5c\xfe\x3b\xf0\x01\x21\x7e\x09\x1f\xdb\xe5\x47\xfd\x21\xd0\x61\x6d\x27"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-8b0e12978b8e2eecf62346e438e47d0993845693 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-8b0e12978b8e2eecf62346e438e47d0993845693
new file mode 100644 (file)
index 0000000..04488ac
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x63\x5b\x29\x28\x20\x3f\xa4\x2d\x27\x62\x69\x6e\x09\x21\x21\x3f\xa4\x3a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-8b3fa0bd4f289eff6a04a5205e04baaeafbdf637 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-8b3fa0bd4f289eff6a04a5205e04baaeafbdf637
new file mode 100644 (file)
index 0000000..7027a77
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x28\x29\x5b\x63\x2d\x27\x62\x69\x6e\x09\x21\x21\x3f\xa4\x1f\xdb\xf0\x21\x10\x07\xf0\x7b\x28\x2d\x62\x69\x6e\xf0\x09\x21\x5c\x09\x21\xe5\x1f\xe9\x1b\x3b\x3f\x47\xed\x3a\x5b\x28\x28\x23\x21\x5c\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-8d1deedd1e463f8c95129a6f839c380a7c83ab04 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-8d1deedd1e463f8c95129a6f839c380a7c83ab04
new file mode 100644 (file)
index 0000000..545bf28
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x63\x2a\x5b\x29\xa4\x0f\x28\x2d\xa4\xdb\xf0\x27\xf0\x62\x83\x63\x69\x6e\x09\x21\x21"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-8d1e029bd72381e382c87e61b4c5a9741d80d644 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-8d1e029bd72381e382c87e61b4c5a9741d80d644
new file mode 100644 (file)
index 0000000..66d3383
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x83\x63\xa4\x1f\x62\xf0\x00\x6e\xa6\x28\x27\x2d\x21\x3f\x1f\xdb\xf0\x0e\x21\x28\x7f\x21\x5c\xf0\x09"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-8dd1983889b6632228d4897c365a1e6124d101e1 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-8dd1983889b6632228d4897c365a1e6124d101e1
new file mode 100644 (file)
index 0000000..9f30eb9
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x28\x3f\x2a\xa0\xa4\x8e\x08\x00\x07\x10\xa4\x07\xa4\x21\x28\x27\x5b\xf4\x5b\x3b\xf0\x09\x1f\x28\x28\x16\x09\xe3\x28\x21\x5c\x09\x21\x63\x47\xfd\x3a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-8dfc2183691385432f92957cff0b2538e5a0ebfa b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-8dfc2183691385432f92957cff0b2538e5a0ebfa
new file mode 100644 (file)
index 0000000..81e32dd
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\x2a\xa0\xac\xae\xa0\xa4\xae\x08\x00\x07\x10\x63\x21\x09\x5b\xf4\x28\xf0\x28\x21\x5c\x09\x21\x63\x47\xfd\x3a\x08\x00\x07\x10\x63\x21\x09\x5b\xf4\x28\xf0\x28\x21\x5c\x09\x21\x63\x47\xfd\x1c\x3a\x1e"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-8eb9b86b4f0aa79b8ef84b44e1fb03094e7bb426 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-8eb9b86b4f0aa79b8ef84b44e1fb03094e7bb426
new file mode 100644 (file)
index 0000000..9a8d65e
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa0\xa4\xae\x08\x00\x07\x10\x63\x21\x09\x5b\xf4\x28\xf0\x28\x21\x5c\x09\x21\x63\x47\xfd\x3a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-8ec540c36da3814e93da765bf2ff0825b59c1bd0 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-8ec540c36da3814e93da765bf2ff0825b59c1bd0
new file mode 100644 (file)
index 0000000..d1e3353
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x63\x5b\x29\x28\x2d\x27\x62\x69\x6e\x09\x21\x21\x3f\xa4\x1f\xdb\xf0\x21\x10\x07\xf0\x7b\x28\x2d\x62\x69\x6e\xf0\x09\x21\x5c\x09\x21\xe5\x9f\xe9\x1b\x3b\x3f\x47\xed\x3a\x5b\x28\x28\x21\x21\x5c\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-8f1bec32f4b8e64062f5405a096543e61d771076 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-8f1bec32f4b8e64062f5405a096543e61d771076
new file mode 100644 (file)
index 0000000..c2d0244
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\x2a\xa4\x3a\xae\xa0\xa4\xae\x08\x00\x07\x10\x63\x21\x28\x5c\xf0\x09\x5b\x2a\xf4\x21\x09\x21\x63\x47\xfd\x3a\x08\x00\x07\x10\x63\x21\x09\x5b\xf4\x28\xf0\x28\x21\x5c\x09\x21\x63\x47\xfd\x3a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-8f3e48c49d0794909f6e8e61e5a4312edf484c33 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-8f3e48c49d0794909f6e8e61e5a4312edf484c33
new file mode 100644 (file)
index 0000000..81870c9
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa0\xa4\xae\x08\x00\x07\x10\x63\x00\x00\x21\x00\x09\x29\x5b\x28\xf0\x28\x21\x28\x09\x21\x63\x47\x00\x2f\xa4\x1f\xa4\xa4\x1f\xfd\x3a\xdb\x21\xa4\xdb\x2a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-8fbbf3c0eaa25b64d0a97a8ee08006539e649199 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-8fbbf3c0eaa25b64d0a97a8ee08006539e649199
new file mode 100644 (file)
index 0000000..dfa2f43
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x63"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-907d0021d42d0fdc867fd02d3609cdce13c8a055 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-907d0021d42d0fdc867fd02d3609cdce13c8a055
new file mode 100644 (file)
index 0000000..b39bc72
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xae\x07\xf0\x5b\x28\x80\xa4\x2d\x62\x64\x69\x6e\x21"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-919511c217a3427c22cad4a71aae31a6cd47b193 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-919511c217a3427c22cad4a71aae31a6cd47b193
new file mode 100644 (file)
index 0000000..f0289d1
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x00\x00\x00\x00\x0f\x2d\x62\x69\x6e\x8b\x63\x5b\x29\x28\x2d\x27\x00\x00\x00\x00\xf2\x69\x6e\x09\x21\x21\x3f\xa4\x1f\xdb\xf0\x21\x10\x07\xf0\x7b\x28\x2d\x69\x6e\xf0\x3a\x21\x5c\x09\x21\xe5\x1f\xe9\x1b\x3b\x3f\x47\xed\x5b\x28\x28\x21\x21\x5c\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-9267c81c3283da8193c198de05e05fa30631a453 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-9267c81c3283da8193c198de05e05fa30631a453
new file mode 100644 (file)
index 0000000..feeacb4
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3f\x2a\xa0\xa4\xae\x40\x08\x10\x07\x3a\xf0\x5b\x06\xf8\x63\x09\x28\x21\x21\x5c\xfe\x3b\xf0\x09\x21\x7e\x09\x1f\xdb\xe5\x47\xfd\x21\xd0\x63\x6d\x3a\x27"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-92e80997a4237d76f10b70dae2870b7255c97435 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-92e80997a4237d76f10b70dae2870b7255c97435
new file mode 100644 (file)
index 0000000..2c54971
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3f\x2a\xa0\xa4\xae\x40\x08\x10\x07\x3a\xf0\x5b\x28\x6e\x63\x09\x28\x3b\xfe\x21\x3b\x5c\xf0\x09\x21\x63\x09\x1f\xdb\xe5\x47\xfd\x21\xf0\x63\x6d\x3a\x27"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-935322db76f5d4c74c2dc68fc4631915b8e24323 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-935322db76f5d4c74c2dc68fc4631915b8e24323
new file mode 100644 (file)
index 0000000..c74eb24
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x0f\xa4\xdb\xf0\xa4\x31\x83"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-939f2627ef6263d0176566de267ff3eb910e6a60 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-939f2627ef6263d0176566de267ff3eb910e6a60
new file mode 100644 (file)
index 0000000..0c81db5
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x29\x5b\x27\x28\x3d\x63\x62\x69\x6e\x09\x61\x21\x3f\xa4\x1f\xdb\xf0\x21\x10\x07\xf0\x7b\x28\x2d\x62\x69\x6e\xa4\xf0\x1f\xa4\xdb"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-94adea6a0d9a44bee6f5e88adcee57be9e9e3597 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-94adea6a0d9a44bee6f5e88adcee57be9e9e3597
new file mode 100644 (file)
index 0000000..6828487
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa0\xa4\x8e\x08\x00\x07\x10\xf4\x5b\x28\x16\x09\xe3\x28\x21\x5c\x09\x21\x63\x47\xfd\x3a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-94dcbe0d3352bd9b230096b8dce9c6d8d63f9d51 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-94dcbe0d3352bd9b230096b8dce9c6d8d63f9d51
new file mode 100644 (file)
index 0000000..d358930
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x28\x3f\x38\xa4\xa4\xa4\x1f\x1f\xdb\x21\xd7\xdb\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-95dad738f60e3e5eb0f1cdafd91ad461f4418e8f b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-95dad738f60e3e5eb0f1cdafd91ad461f4418e8f
new file mode 100644 (file)
index 0000000..e2907a7
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa0\xa4\xae\x08\x00\x07\x10\x63\x00\x00\x21\x00\x09\x29\x5b\x28\xf0\x28\x21\x09\x21\x5c\x63\x47\x00\x2f\xa4\x1f\xa4\x3c\x1f\xfd\x3a\xdb\xa4\xdb\x2a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-960c0a21c9e5c1a61b93b34da3189b0de1c264df b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-960c0a21c9e5c1a61b93b34da3189b0de1c264df
new file mode 100644 (file)
index 0000000..d5b8e68
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x83\x63\x1f\x00\x27\x5b\xf0\x69\x28\xe2\x6e\x2d\x21\x3f\x21\x28\xdb\xf0\x21\x1f\x3a\x21\x5c\xf0\x09\x63"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-96903512b1f1dec08206123f024b62d0e31cd4dc b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-96903512b1f1dec08206123f024b62d0e31cd4dc
new file mode 100644 (file)
index 0000000..b8ebe9c
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x10\x63\x07\xf0\x5b\x28\x21\x09\xf0\x5b\x28\x21\x5c\x09\x21\xe5\x47\xfd\x21\x5b\x28\x21\x21\x09\x21\xe5\x47\xfd\x41\x29\x28\x21\x29\xed\x21\xb8\x2a\x29\xe5\x47\xfd\x41\x29\x28\xd9\x3b\x29\x8a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-96a89c005e8d9992e34cc149b0be096ad0051446 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-96a89c005e8d9992e34cc149b0be096ad0051446
new file mode 100644 (file)
index 0000000..1c651a7
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa0\xa4\xae\xa0\xa4\xae\x08\x00\x07\x10\x63\x21\x09\x5b\xf4\x28\xf0\x28\x21\x5c\x09\x21\x63\x47\xfd\x3a\x08\x00\x6b\x10\x63\x21\x09\x5b\xf4\x28\xf0\x28\x21\x5c\x09\x1f\x00\x21\x63\x47\xfd\x3a\xb5\x58"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-97db8a66dd513eea47a5a25115508f4e59984854 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-97db8a66dd513eea47a5a25115508f4e59984854
new file mode 100644 (file)
index 0000000..7f4df6e
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x28\x1e\x2a\xa0\xa4\xae\x40\x08\x10\x3a\xf0\x07\x5b\x28\x3f\xa4\x07\x3b\x3a\x28\x27\xa4\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-98f2cb84ad89550cf56ee54e11f1448ae7287247 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-98f2cb84ad89550cf56ee54e11f1448ae7287247
new file mode 100644 (file)
index 0000000..bd31b28
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x81\x63\xa4\x1f\x1f\x00\x27\x5b\xf0\x69\x28\x62\xa4\xdb\xf0\xf0\x09\x63"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-993497422a59b7f9f0f6db8c867339b5c9e4c978 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-993497422a59b7f9f0f6db8c867339b5c9e4c978
new file mode 100644 (file)
index 0000000..cd2abdd
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xa4\xf0\x0f\x2d\x62\x69\x6e\x8b\x63\x5b\x29\xce\x10\x40\x08\xae\x3f\x2a\xa4\xa0\x07\x3a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-999821e3750a7f2c9db663d2d100b4404c225040 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-999821e3750a7f2c9db663d2d100b4404c225040
new file mode 100644 (file)
index 0000000..1012270
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x13\x5b\x28\x21\x21\x09\x21\x5b\xf0\x21\xe5"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-99b2ed83be40cab431d1940e8de2dc3ebfe9352f b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-99b2ed83be40cab431d1940e8de2dc3ebfe9352f
new file mode 100644 (file)
index 0000000..707d7c9
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x0c\xa4\x1f\xa4\x3b\xdb\xe2\xf0\x09\x63\x2e\x00\xa4\x2a\x63\xa0\xa4\xae\x63\x08\x27\x00\x10\x07\xf0\x5b\x28\x21\x09\x63\xf0\x28\x21\x5c\x09\x21\xa0\xa4\x08\x00\x63\xe5\x47\xfd\x63\x63\x3a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-99e888b7372b29256dbefd476855ff73584cc00f b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-99e888b7372b29256dbefd476855ff73584cc00f
new file mode 100644 (file)
index 0000000..4db28f0
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\x2a\xa0\xa4\xae\xa0\xa4\xae\x08\x00\x07\x10\x63\x21\x09\x5b\xf4\x28\xf0\x28\x21\x5c\x09\x21\x63\x47\x6e\x3a\x08\x00\x07\x10\x63\x21\x09\xf4\x28\xf0\x28\x21\x5c\x09\x21\x63\x47\xfd\x3a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-9b18087deb3cfafa1b964aa65d8ee980bc61404e b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-9b18087deb3cfafa1b964aa65d8ee980bc61404e
new file mode 100644 (file)
index 0000000..dcd6149
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\xa4\xff\x83\x2a\xa0\xa4\xae\x08\x00\x10\x07\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-9b3c745ea3e313909a228a07b49aae110b02ae4a b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-9b3c745ea3e313909a228a07b49aae110b02ae4a
new file mode 100644 (file)
index 0000000..739e186
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x70\x83\xdb\xf0\xf0\xa4\x1f\x21\x83\x5b\xf0\x63"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-9be1ce0ba77758928ff5e9c45139b1624cbe9c2d b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-9be1ce0ba77758928ff5e9c45139b1624cbe9c2d
new file mode 100644 (file)
index 0000000..4477c4e
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\xa4\x2d\x5b\x63\x27\x21\x29\xa4\x10\x62\x69\x07"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-9c703141efd69eb8f32a58133c8035fb585e0f4c b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-9c703141efd69eb8f32a58133c8035fb585e0f4c
new file mode 100644 (file)
index 0000000..c25ba26
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\x2a\xa0\xa4\xae\xa0\xa4\xae\x08\x00\x07\x10\x63\x21\x09\x5b\xf4\x28\xf0\x28\x21\x5c\x09\x21\x63\x47\xfd\x3a\x08\x00\x6b\x10\x63\x21\x09\x5b\xf4\x28\xf0\x28\x21\x5c\x09\x1f\x00\x21\x63\x47\xfd\x3a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-9c7f77981677499f0426a0ffb5cb79d5fe55dcb2 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-9c7f77981677499f0426a0ffb5cb79d5fe55dcb2
new file mode 100644 (file)
index 0000000..c473ee4
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x63\x5b\x29\x28\x2d\x27\x62\x29\x6e\x09\x23\x21\x3f\xa4\x1f\xdb\xf0\x21\x10\x07\xf0\x7b\x28\x2d\x62\x69\x6e\xf0\x09\x21\x5c\x09\x21\xe5\x1f\xe9\x1b\x3b\x3f\x47\xed\x3a\x5b\x28\x28\x21\x21\x5c\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-9ca59e6cadaa5be9af30dfe5620d1bcd70f442e5 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-9ca59e6cadaa5be9af30dfe5620d1bcd70f442e5
new file mode 100644 (file)
index 0000000..97a3691
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x63\x2a\x5b\x29\xa4\x13\x5b\x28\x28\xa4\x2d\x0f\xdb\xf0\x27\xf0\x62\x21\x83\x63\x69\x6e\x09\x21\x21\x09\x21\x21\x5b\xf0\x21\xe5"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-9d139835d91474e8d8361d65698a31b8b38c4f7b b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-9d139835d91474e8d8361d65698a31b8b38c4f7b
new file mode 100644 (file)
index 0000000..782a58b
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3f\xa4\x1f\xdb\xf0\x21\xf0\xa4\xa4\x90\x07\xf0\x09\x63\x27\xa4\x0f\x2d\x62\x69\x6e\x8b\xa4\xf2\x5b\x63\x27\x21\x29\xa4\x10\x62\x69\x17"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-9e2179564a99e96e179c96f28802a0a2759b581c b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-9e2179564a99e96e179c96f28802a0a2759b581c
new file mode 100644 (file)
index 0000000..232c129
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x28\x2a\xa0\xa4\xae\x40\x08\x10\x3a\xf0\x07\x5b\x28\x3f\xa4\x07\x3b\x5b\x28\x27\xa4\xf0\x21\x09\x1f\x28\xf8\x63\x09\x28\x3b\xfe\x21\x21\x5c\x09\x21\x63\x72\xe5\x47\xfd\x3a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-9e56bb3b68d2e2617cb2d2f0f3941f7fc832e462 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-9e56bb3b68d2e2617cb2d2f0f3941f7fc832e462
new file mode 100644 (file)
index 0000000..6b4c14a
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x63\x27\xf0\x5b\x28\x21\x21\x09\xf0\x5b\x28\x21\x21\x09\x21\xe5\x47\xfd\x21\x5b\x28\x21\x21\x09\x21\xe5\x47\xfd\x41\x29\x28\x21\x29\xed\x21\xbc\x2a\x29\xe5\x47\xfd\x41\x29\x28\xd9\x21\x29\x8a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-9f318b2c2ff9cf4615bd06ba13bdd086b4ad08c6 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-9f318b2c2ff9cf4615bd06ba13bdd086b4ad08c6
new file mode 100644 (file)
index 0000000..b9a3965
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3f\x2a\xa0\xa4\xae\x40\x08\x18\x07\x3a\xf0\x5b\x06\xf8\x63\x09\x28\x21\x21\x5c\xfe\x3b\xf0\x01\x21\x7e\x09\x1f\xdb\xe5\x47\xfd\x21\xd0\x69\x6d\x3a\x27"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-9f8d90b1480989fc46ea2f1c66cf687638994587 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-9f8d90b1480989fc46ea2f1c66cf687638994587
new file mode 100644 (file)
index 0000000..80dc0f5
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\x2a\xa4\xae\xa0\xa4\xae\x08\x00\x07\x10\x63\x21\x28\x5c\xf0\x09\x5b\x2a\xf4\x21\x09\x21\x63\x47\xfd\x3a\x08\x00\x07\x10\x63\x21\x09\x5b\xf4\x28\xf0\x28\x21\x5c\x09\x21\x63\x47\xfd\x3a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-a09db5715f0bc3879a0e18e4db5a6b5640b254a3 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-a09db5715f0bc3879a0e18e4db5a6b5640b254a3
new file mode 100644 (file)
index 0000000..c9d98c9
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3b\x3f\x30\x63\x21\x28\x07\xf2\x4b\x09\xf0\x5b\x4e\xd4\x5c\x09\x21\xe5\x47\x21\x5b\x28\x21\x21\x09\x21\xe5\x47\xfd\x41\x29\x28\x21\x29\xed\x21\x2a\xe5\xbc\x47\x80\xfd\x41\x29\x28\xd9\x3b\x29\x8a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-a0c59a090818bca29d76ccf9843f7e2faf330ddf b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-a0c59a090818bca29d76ccf9843f7e2faf330ddf
new file mode 100644 (file)
index 0000000..77ede33
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\xa4\x0f\xa4\xdb\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-a1cf10478e5e01a0d951c743a3dd45aa5fc409f2 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-a1cf10478e5e01a0d951c743a3dd45aa5fc409f2
new file mode 100644 (file)
index 0000000..e55a4b0
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x1f\x21\x83\xdf\xf0\xf0\xa4\x1f\x21\x83\xdb\xa4\x1f\xe4"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-a22c0f03f8c005a4612a9dcbcd6a643334c35d2f b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-a22c0f03f8c005a4612a9dcbcd6a643334c35d2f
new file mode 100644 (file)
index 0000000..14535f9
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3b\x3f\x30\x63\x21\x28\x07\xf0\x4b\x09\xf0\x5b\x4e\xd4\x5c\x09\x21\xe5\x47\x21\x5b\x28\x21\x21\x09\x21\xe5\x47\xfd\x41\x29\x28\x21\x29\xed\x21\x2a\xe5\xbc\x47\x80\xfd\x41\x29\x28\xd9\x3b\x29\x8a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-a3154b8ed26b3461f2b091c732da00b63ce8bed3 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-a3154b8ed26b3461f2b091c732da00b63ce8bed3
new file mode 100644 (file)
index 0000000..59d6e2b
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\xa4\x2d\x5b\x63\x27\xf9\x29\xa4\x10\x62\x69\x07"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-a84a1ed1a24e753a27adfd3ba806f06fc44f899f b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-a84a1ed1a24e753a27adfd3ba806f06fc44f899f
new file mode 100644 (file)
index 0000000..2580e3a
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x83\x63\x1d\xa4\x1f\x21\x83\xdb\xf0\xf0\xa4\x1f\x1f\x21\x83\xdb\x00\x27\x5b\x2a\xf0\xae\xa0\xa4\xf0\x69\x28\x08"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-a871e7ce66afd4f57702cd1299de06cd08995561 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-a871e7ce66afd4f57702cd1299de06cd08995561
new file mode 100644 (file)
index 0000000..8465399
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa0\xa4\xae\x08\x00\x07\x10\xf4\x5b\x28\x21\x09\x63\xf0\x28\x29\x5c\x09\x21\x63\x47\xfd\x3a\xa0\xa4\xae\x08\x00\x63\x63"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-a8dc736ea964586b7dcbf2bc065ec4675d1daba3 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-a8dc736ea964586b7dcbf2bc065ec4675d1daba3
new file mode 100644 (file)
index 0000000..26d15de
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x63\x5b\x29\xa4\x28\x2d\x0e\x7f\x27\x62\x69\x6e\x09\x21\x21\x3f\xa4\x1f\xdb\xf0\x21"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-a91a835836c72217824f0b63491d9b623130502a b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-a91a835836c72217824f0b63491d9b623130502a
new file mode 100644 (file)
index 0000000..e57084d
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3f\x2a\xa0\xa4\xae\x40\x08\x10\x07\x3a\xf0\x5b\x28\xf8\x63\x09\x28\x3b\xfe\x21\x21\x5c\xf0\x09\x21\x63\x09\x1f\xdb\xe5\x47\xfd\x21\xf0\x63\x6d\x3a\x27"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-ab97c1f6033dc7d96f69b9e1461fd594c16f4ebf b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-ab97c1f6033dc7d96f69b9e1461fd594c16f4ebf
new file mode 100644 (file)
index 0000000..8424708
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x00\x00\x00\x00\x2f\xa4\x1f\xa4\xa4\x0f\xa4\xdb\xf0\xe8\x83\x00\x63\x63\x25\x1f\xdb\xa4\xdb\x2a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-ac8a8c23acd8c290a11dc7828f7f397957fa6400 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-ac8a8c23acd8c290a11dc7828f7f397957fa6400
new file mode 100644 (file)
index 0000000..ad123a1
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3f\x2a\xa0\xa6\xae\x40\x08\x10\x07\x3a\xf0\x5b\x06\xf8\x63\x09\x28\x21\x21\x5c\xfe\x3b\xf0\x01\x21\x7e\x09\x1f\x47\xfd\x21\xd0\x69\x6d\x3a\x27"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-ac94b2788f5252f9e2e8502c7c75e04bef4c0b76 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-ac94b2788f5252f9e2e8502c7c75e04bef4c0b76
new file mode 100644 (file)
index 0000000..83887a6
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x3f"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-ad03b4f58470c43db6593a35be48989486d754f9 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-ad03b4f58470c43db6593a35be48989486d754f9
new file mode 100644 (file)
index 0000000..1e0c286
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x70\x83\xdb\xf0\xf0\xa4\x1f\x21\x83\xdb\xf0\xf0\x63"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-af417c83e831a96fda1bdde99a1af6509ef2df3d b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-af417c83e831a96fda1bdde99a1af6509ef2df3d
new file mode 100644 (file)
index 0000000..866c328
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x28\x3f\xa4\x1f\xa4\xa4\x1f\xdb\xdb\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-affd292cd2ce3306b4651cc7ec0ec0524cbbae3d b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-affd292cd2ce3306b4651cc7ec0ec0524cbbae3d
new file mode 100644 (file)
index 0000000..6a25af4
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\xa3\x62\x69\x6e\x8b\xe4\x63\x5b\xf2\x29\x27\x2d\x62\x69\x2e\x09\x2a\x29\x21\x3f\xa4\x1f\xdb\xe2\x10\x07\xf0\x7b\x28\x2d\x62\x69\x5c\x6e\x21\x09\x21\x09\xf0\xe5\x1f\xe9\x1b\x3b\x3f\x47\xed\x3a\x5b\x28\x28\x21\x21\x5c\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-b0587e6e319f4b56d877e7ed46bc7da9b1e7249c b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-b0587e6e319f4b56d877e7ed46bc7da9b1e7249c
new file mode 100644 (file)
index 0000000..57a7d35
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x29\x07\x3a\x3b\x21\x9c\xca\x27\xd2\xd8\x29\x2a\x3b\x7d\x76\x29\x37\x49\xcf\x21\xa4\x29\x3b\x1e\x96\x2d\x4d\x2a\xb1\xe4\xe2\x21\x27\x64\x2a\x43\x75\x18\x0e\xab\x91\x58\x24\x30\x0e\x29\x3a\xf3\x2a\x3b\x3a\xe4\xdd\x3b\x3b\x28\x29\x3b\x3a\x5d\xef\xe6\x40"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-b166aa66b5b3ad178bc38aee5768226c8adc082f b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-b166aa66b5b3ad178bc38aee5768226c8adc082f
new file mode 100644 (file)
index 0000000..4217097
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x70\x83\xdb\xf0\xa4\x1f\x21\x83\xdb\xf0\x63"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-b1ade0571262c6e5f1d72f6d25ebb513d2055bc9 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-b1ade0571262c6e5f1d72f6d25ebb513d2055bc9
new file mode 100644 (file)
index 0000000..746379b
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x63\x5b\x29\x28\x27\x2d\x62\x69\x2e\x09\x2a\x21\x21\x3f\xa4\x1f\xdb\xe2\x21\x10\x07\xf0\x7b\x28\x2d\x62\x69\x5c\x6e\x21\x09\x21\x09\xf0\xe5\x1f\xe9\x1b\x3b\x3f\x47\xed\x3a\x5b\x28\x28\x21\x21\x5c\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-b244c690157ff21d073940ef8c77d1898f37cf8e b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-b244c690157ff21d073940ef8c77d1898f37cf8e
new file mode 100644 (file)
index 0000000..f845f98
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x1f\xa4\xdb\xf0\xf0\x09\x63\x63\x27"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-b523091ee4f17d20f51f9b5cf82293465cf61780 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-b523091ee4f17d20f51f9b5cf82293465cf61780
new file mode 100644 (file)
index 0000000..e74aca4
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3f\x2a\xa0\xa4\xae\x40\x08\x10\xf0\x3a\x07\x5b\x06\xf8\x63\x09\x28\x3b\xfe\x21\x21\x5c\xf0\x09\x23\x7e\x09\x1f\xdb\xe5\x72\xfd\x21\xf0\x63\x6d\x3a\x27"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-b7d4d49ac2c530eb8444a449feb689ee50fd210d b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-b7d4d49ac2c530eb8444a449feb689ee50fd210d
new file mode 100644 (file)
index 0000000..352c689
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3b\x3f\x27\x63\x07\xf0\x5b\x28\x21\x09\xf0\x5b\x4e\x21\x5c\x09\x23\xe5\x47\xfd\x21\x2a\x28\x21\x21\x09\x21\xe5\x47\xfd\x41\x29\x28\x21\x29\xed\x21\xbc\x2a\x29\xe5\x47\xfd\x49\x29\x28\xd9\x3b\x29\x8a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-b855c161121bfa29c6fb22d3c0236fae4af6984e b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-b855c161121bfa29c6fb22d3c0236fae4af6984e
new file mode 100644 (file)
index 0000000..b89b4c2
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3b\x3f\x30\x63\x21\x28\x07\xf0\x4b\x09\xf0\x5b\x4e\x21\x5c\x19\x3b\xe5\x47\x21\x5b\x28\x21\x21\x09\x21\xe5\x47\xfd\x41\x29\x28\x21\x29\xed\x21\x2a\xe5\x47\x80\xbe\x41\x29\x28\xd9\x3b\x8a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-bc4263a92952d56168b354f723eaa43a33cd0b35 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-bc4263a92952d56168b354f723eaa43a33cd0b35
new file mode 100644 (file)
index 0000000..0d5fec0
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x00\x84\x68\x6f\x77\x74\x00\x28\x3f\x01\x9b\xf0\x21\x09\x63"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-bcaa71abf23b2e5130e0cc464755fe769bf4aaa7 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-bcaa71abf23b2e5130e0cc464755fe769bf4aaa7
new file mode 100644 (file)
index 0000000..f0875b6
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x89\x63\x5b\x29\xa4\x28\x2d\x0e\x7f\x27\x62\x69\x6e\x09\x21\x21\x3f\xa4\x1f\xdb\xf0\x21"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-bcf4684ce097faa7e9d99b6e93cc2de24f57aee3 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-bcf4684ce097faa7e9d99b6e93cc2de24f57aee3
new file mode 100644 (file)
index 0000000..45e6c5e
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa0\xa4\xae\x08\x00\x63\x63"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-bdca6504d2ee7925f62e176355bb481344772075 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-bdca6504d2ee7925f62e176355bb481344772075
new file mode 100644 (file)
index 0000000..87872d7
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3b\x3f\x27\x63\x07\xf0\x5b\x28\x21\x09\xf0\x5b\x4e\x21\x5c\x09\x21\xe5\x47\xfd\x21\x2a\x28\x21\x21\x09\x21\xe5\x47\xfd\x41\x29\x28\x21\x29\xed\x21\xbc\x2a\x29\xe5\x47\xfd\x49\x29\x28\xd9\x3b\x29\x8a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-beb208fd8675ba7de2ecb12998d2d628d579ca7c b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-beb208fd8675ba7de2ecb12998d2d628d579ca7c
new file mode 100644 (file)
index 0000000..e6ca884
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3f\x2a\xa0\xa4\xae\x40\x08\x10\x07\x3a\xf0\x5b\x06\xf8\x63\x09\x38\x3b\xfe\x21\x21\x5c\xf0\x09\x21\x7e\x09\x1f\xdb\x44\x47\xfd\x21\xf0\x63\x6d\x3a\x27"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-bf0c98689ab81fc32787023300caf9a4175583dc b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-bf0c98689ab81fc32787023300caf9a4175583dc
new file mode 100644 (file)
index 0000000..9ef7378
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x10\x07\xf0\x5b\x28\x2d\xa4\x1f\xdb\x2a\xa0\xa4\xf0\x21\x62\x69\x6e\xf0\x3f\x2a\xa0\xa4\x09\xae\x40\x08\x10\x07\x2d\x62\x69\x6e\x3a\xf0\x5b\x06\xae\x08\x00\x07\x10\x63\x00\xf8\x63\x21\x00\x21\x09\x00\x5b\x21\x5c\xf4\x09\x09\x28"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-bf479e97b39b697e715663de6a1e78dd58d64122 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-bf479e97b39b697e715663de6a1e78dd58d64122
new file mode 100644 (file)
index 0000000..2282649
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x63\x2a\x5b\x29\xa4\x28\xa4\x2d\x0f\xdb\xf0\x27\xf0\x62\x83\x63\x69\x6e\x09\x21\x21"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-bf826c96be94d1b42eea0666f7239cc5f699a375 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-bf826c96be94d1b42eea0666f7239cc5f699a375
new file mode 100644 (file)
index 0000000..500e955
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x10\x07\xf0\x5b\x28\x2d\x62\x69\x6e\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x63\x5b\x29\x28\x2d\x27\x62\x69\x6e\x09\x21\x21\x3f\xa4\x1f\xdb\xf0\x21\x10\x07\xf0\x7b\x28\x2d\x62\x69\x6e\xf0\x21\x09\xf0\x28\x09\x21\x21"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-c17650d19ae4a48abb36739c83d8979453f5705f b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-c17650d19ae4a48abb36739c83d8979453f5705f
new file mode 100644 (file)
index 0000000..e05253f
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3b\x3f\x30\x63\x21\x28\x07\xf0\x4b\x09\xf0\x5b\x4e\x21\x5c\x09\x21\xe5\x47\x21\x5b\x28\x21\x21\x09\x21\xe5\x47\xfd\x41\x29\x28\x21\x29\xed\x21\x2a\xe5\xbc\x47\x80\xfd\x41\x29\x28\xd9\x3b\x29\x8a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-c1e5307d88feda2c3b15fc221cba92bcf41622bf b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-c1e5307d88feda2c3b15fc221cba92bcf41622bf
new file mode 100644 (file)
index 0000000..fe9202e
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x28\x3f\x2a\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x83\xa4\x07\x3b\x5b\x28\x27\xa4\xf0\x21\x63\x09"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-c249f408c552a0408eab3fe1d1cbeca95cd537c1 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-c249f408c552a0408eab3fe1d1cbeca95cd537c1
new file mode 100644 (file)
index 0000000..2ef5c85
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x63\x5b\x29\x28\x2d\x62\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x63\x5b\x29\x28\x27\x2d\x62\x69\x2e\x09\x2a\x21\x21\x3f\xa4\x1f\xdb\xe2"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-c26b460aebc9082c519539069f7e060042989696 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-c26b460aebc9082c519539069f7e060042989696
new file mode 100644 (file)
index 0000000..b20c7ad
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x63\x5b\x29\x28\x2d\x27\x62\x6e\x69\x09\x21\x25\x3f\xa4\x1f\xdb\xf0\x21\x10\x07\xf0\x7b\x28\x2d\x62\x69\x6e\xf0\x09\x21\x5c\x21\xe5\x1f\xe9\x1b\x3b\x3f\x47\x5b\x28\x28\x21\x21\x5c\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-c2eae71daad0d3561ab4d09b8b85372b8d790bc1 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-c2eae71daad0d3561ab4d09b8b85372b8d790bc1
new file mode 100644 (file)
index 0000000..074a797
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3b\x3f\x30\x63\x21\x27\x07\xf0\x4b\x09\xf0\x5b\x4e\x21\x5c\x19\x21\xe5\x47\x21\x5b\x28\x21\x21\x09\x21\xe5\x47\xfd\x41\x29\x28\x21\x29\xed\x21\x2a\xe5\x47\x80\xbe\x41\x29\x28\xd9\x3b\x8a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-c37fda8d02e99132a1de99f959596c784ab8a53c b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-c37fda8d02e99132a1de99f959596c784ab8a53c
new file mode 100644 (file)
index 0000000..625425e
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\x2a\xa0\xa4\xae\xa0\xa4\xae\x08\x00\x07\x10\x63\x21\x09\x5b\xf4\x28\xf0\x28\x25\x5c\x09\x21\x63\x47\xfd\x3a\x08\x00\x07\x10\x63\x21\x09\x5b\xf4\x28\xf0\x28\x63\x21\x09\x5c\x21\x47\xfd\x3a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-c4836760377a7091fb20f4afa9c712875792b9a7 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-c4836760377a7091fb20f4afa9c712875792b9a7
new file mode 100644 (file)
index 0000000..23aa080
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\x2a\xa0\xa4\xae\xa0\xa4\xae\x08\x00\x07\x63\x21\x09\x5b\xf4\x28\xf0\x28\x21\x5c\x09\x21\x63\x47\xfd\x3a\x08\x00\x07\x10\x63\x21\x5b\xf4\x28\xf0\x28\x21\x5c\x09\x21\x63\x47\xfd\x3a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-c48caad597176404f776d532d4baf9faf7655ee2 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-c48caad597176404f776d532d4baf9faf7655ee2
new file mode 100644 (file)
index 0000000..1b27865
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x10\x07\xf0\x5b\x28\x2d\xa4\x1f\xdb\x2a\xa0\xa4\xf0\x21\x62\x69\x6e\xf0\x3f\x2a\xa0\xa4\x09\xae\x00\x08\x10\x07\x62\x69\x27\x6e\x3a\xf0\x5b\x06\xae\x08\x00\x07\x10\x63\x00\xf8\xa9\x21\x00\x21\x09\x00\x5b\x21\x5c\xf4\x09\x09\x28"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-c4eff0f59986fc5ab09d5bd95f394292f2882659 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-c4eff0f59986fc5ab09d5bd95f394292f2882659
new file mode 100644 (file)
index 0000000..585d9b3
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x29\x63\x5b\x29\x2d\x27\x62\x69\x6e\x09\x31\xa4\xa4\x10\x21\x3f\xa4\x1f\xdb\xf0\x21\x07"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-c5fc2086d167c8c3a7d9ec778db69c5fa14a59fe b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-c5fc2086d167c8c3a7d9ec778db69c5fa14a59fe
new file mode 100644 (file)
index 0000000..73bc091
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3f\x2a\xa0\xa4\xae\x40\x08\x18\x07\x3a\xf0\x5f\x06\xf8\x63\x09\x28\x21\x21\x5c\xfe\x3b\xf0\x01\x21\x7e\x09\x21\x1f\xdb\xe5\x47\xfd\x21\xd0\x3b\x6d\x3a\x27"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-c600877ce547166eb1b9d83afbe128d98767f8a3 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-c600877ce547166eb1b9d83afbe128d98767f8a3
new file mode 100644 (file)
index 0000000..413382c
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x83\x63\x29\x2d\x62\x69\x09\x28\x6e\x27\x21\x21\x3f\xa4\x1f\xdb\x21\xf0\x10\x07\xf0\x7b\x28\x2d\x62\x69\x6e\xf0\x09\x21\x5c\x09\x21\xe5\x1f\xe9\x1b\x3b\x3f\x47\xed\x3a\x5b\x28\x28\x21\x21\x5c\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-c6a98fdaf6de78e59e1a149a43f3e42222d650b7 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-c6a98fdaf6de78e59e1a149a43f3e42222d650b7
new file mode 100644 (file)
index 0000000..bf07f53
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3f\x2a\xa0\xac\xae\x40\x08\x10\xf0\x3a\x07\x5b\x06\xf8\x63\x09\x28\x3b\xfe\x21\x5c\x21\xf0\x09\x21\x7e\x09\x1f\xdb\x2d\x62\x69\x6e\xe5\x47\xfd\x21\xf0\x63\x6d\x3a\x27"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-c8d22f7fb4f37f2d8cc7953fa2d599d38d899aec b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-c8d22f7fb4f37f2d8cc7953fa2d599d38d899aec
new file mode 100644 (file)
index 0000000..261ff44
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x83\x63\x00\x1f\x27\x5b\xf0\x69\x28\x62\x6e\x2d\x21\x3f\xa4\x1f\xdb\xf0\x21\x28\x21\x5c\xf0\x09\x43"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-c90951c19b24bac84296e3ec32cdeafe99e99cfb b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-c90951c19b24bac84296e3ec32cdeafe99e99cfb
new file mode 100644 (file)
index 0000000..9ceac72
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3f\x2a\xa0\xa4\xae\x40\x08\x10\x07\x3a\xf0\x5b\x06\xf8\x63\x09\x28\x21\x21\x5c\xfe\x3b\xf0\x01\x21\x7e\x09\x1f\xdb\xe5\x47\xfd\x21\xd0\x61\x6d\x3a\x27"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-c95ff2a172626efb50e94aa6781feba609820076 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-c95ff2a172626efb50e94aa6781feba609820076
new file mode 100644 (file)
index 0000000..f74cc26
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x10\x07\xf0\x5b\x28\x2d\x62\x69\x6e\x21\x09\xf0\x28\x21\x5c\x09\x21\xe5\x47\xfd\xa4\x1f\x21\x3a\x5b\x28\x21\x27\xf0\x5b\x28\x21\x21\x09\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-ca6c557afb9c571de62e9b65ca6469a6133760da b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-ca6c557afb9c571de62e9b65ca6469a6133760da
new file mode 100644 (file)
index 0000000..d297338
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3f\x21\x63\xf0\x09\x1f\xdf\x7d\x27"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-cb2d0fb23f66c968af2e80d59f71d4c1aed96fbd b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-cb2d0fb23f66c968af2e80d59f71d4c1aed96fbd
new file mode 100644 (file)
index 0000000..113e8a2
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x63\x5b\x29\xa4\x0f\x28\x2d\xa4\xdb\xf0\x27\xf0\x62\x83\x63\x69\x6e\x09\x21\x21"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-cc60a642cc2037ad3c459a57381b8f65d8d7aa35 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-cc60a642cc2037ad3c459a57381b8f65d8d7aa35
new file mode 100644 (file)
index 0000000..329e1f0
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3f\x2a\xa0\xa4\xae\x40\x08\x10\x07\x3a\xf0\x5b\x06\xf8\xe3\x09\x34\x3b\xfe\x21\x21\x5c\xf0\x09\x21\x7e\x09\x1f\xdb\x44\x47\xfd\xf0\x63\x6d\x3a\x27"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-ccd3b8aa26c52f6d9c607c26ebdf621142aff745 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-ccd3b8aa26c52f6d9c607c26ebdf621142aff745
new file mode 100644 (file)
index 0000000..4901bdb
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa0\xa4\xae\x08\x00\x10\x07\xf0\x5b\x28\x21\x09\x63\xf0\x28\x21\x5c\x09\x21\x63\xe5\x47\xfd\x3a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-ccdfd1354997eb117bd76b75440a7e4ff20bf564 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-ccdfd1354997eb117bd76b75440a7e4ff20bf564
new file mode 100644 (file)
index 0000000..6a15108
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2b\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x0b\x39\x63\x5b\x29\x28\x2d\x62\xa4\xa4\x10\x07\xf0\xa4"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-cd7a7b8f08c189e95ae3e2ea44b9015000e823f3 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-cd7a7b8f08c189e95ae3e2ea44b9015000e823f3
new file mode 100644 (file)
index 0000000..9eadc9c
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x23\x5a\x29\xa4\x28\x2d\xa4\x0e\x62\xa4\x09\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x3f\xf0\x8b\x63\x5b\x29\x28\x2d\x7f\x6e\x69\x27\x27\x62\x69\x6e\x21\x21\x09\x21\x2f\xa4\x21\x3f\x1f\x27\xf0\x21"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-ce05678d812a5f8ae8e115938410116ce9169456 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-ce05678d812a5f8ae8e115938410116ce9169456
new file mode 100644 (file)
index 0000000..ddbf97b
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3b\x3f\x30\x63\x21\x28\x07\xf0\x4b\x09\xf0\x5b\x4e\x21\x5c\x19\x21\xe5\x47\x21\x5b\x28\x21\x21\x09\x21\xe5\x47\xfd\x41\x29\x28\x21\x29\xed\x21\x2a\xe5\x47\x80\xbe\xfd\x41\x29\x28\xd9\x3b\x29\x8a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-ce6b642b81373f05baa2a6fe6e9d5d1387046285 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-ce6b642b81373f05baa2a6fe6e9d5d1387046285
new file mode 100644 (file)
index 0000000..92ea41b
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa4\x10\x07\xf4\xa4\x0f\x2d\x62\x69\x6e\x83\x63\xa4\x1f\xdb\xf0\x21\xf0\x09\x1d\xa4\x1f\x21\x83\xdb\xf0\xf0\x63\x27\xa4\x1f\x1f\x21\x83\xdb\x00\x27"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-cf84d06e4dddb997a79a41f9b6122bf620bbdb4b b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-cf84d06e4dddb997a79a41f9b6122bf620bbdb4b
new file mode 100644 (file)
index 0000000..53dc8a3
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3b\x3f\x27\x63\x07\xf0\x5b\x29\x21\x09\xf0\x5b\x4e\x21\xdc\x09\x62\xe5\x34\x47\xfd\x21\x2a\x28\x21\x21\x09\x42\xe5\x47\xfd\x41\x29\x21\x29\xed\x21\xbc\x2a\x29\xe5\x47\xfd\x49\x29\x28\xd9\x3b\x29\x8a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-cfbcc3e8cd65aa8b654688145ade34b8789468a6 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-cfbcc3e8cd65aa8b654688145ade34b8789468a6
new file mode 100644 (file)
index 0000000..b8ffe74
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x27\x3f\x30\x63\x21\x28\x07\xf0\x4b\x09\xf0\x5b\x4e\x21\x5c\x19\x21\xe5\x47\x21\x5b\x28\x21\x21\x09\x21\xe5\x47\x29\x41\xfd\x28\x21\x29\xe5\x21\x2a\xe5\x47\x80\x41\xbe\x29\x28\xd9\x3b\x3b\x8a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-clusterfuzz-testcase-5298216461402112 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-clusterfuzz-testcase-5298216461402112
new file mode 100644 (file)
index 0000000..8604e45
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x72\xac\x90\x2d\x72\xac\x90\x2d\xee\x68\x1a\x2d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaf\xed\x2c\xad\xaf\xed\x2c\xad\xce\xe3\x93\x2f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x6e\x0d\xcc\xad\x6e\x0d\xcc\xad\x38\xe2\x01\xb0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa8\x74\xc2\xac\xa8\x74\xc2\xac\x4f\x79\x08\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf7\xe6\x20\x2d\xf7\xe6\x20\x2d\x55\x9a\x9c\xaf\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe4\x8d\xf4\x2d\xe4\x8d\xf4\x2d\xe7\x6e\xa9\xae\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x56\x2f\x7a\xac\x56\x2f\x7a\xac\xcb\x94\xf9\x2f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xad\xc4\xab\xad\xad\xc4\xab\xad\xe1\x0f\x3e\xb0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x8a\x71\x29\xac\x8a\x71\x29\xac\xe0\x74\x32\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x4d\x7f\x8c\xab\x4d\x7f\x8c\xab\xa3\xf5\x9f\xaf\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1f\x21\x21\xab\x1f\x21\x21\xab\x46\x73\x86\xaf\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xbf\x51\x8d\x2d\xbf\x51\x8d\x2d\x29\x51\x43\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x2d\x49\x85\x2d\x2d\x49\x85\x2d\x05\x38\x79\xb0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x21\x38\x80\xad\x21\x38\x80\xad\xe6\x70\x4b\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xfc\xa1\x5c\xae\xfc\xa1\x5c\xae\xde\x22\x84\xaf\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x68\xda\xcd\x2d\x68\xda\xcd\x2d\x8b\x7a\xe1\xaf\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xcc\x7b\x66\x2e\xcc\x7b\x66\x2e\xe7\x29\x83\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x42\x9e\x2c\x10\x42\x9e\x2c\x78\x28\x9f\xb0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xde\x0b\x22\xae\xde\x0b\x22\xae\x96\x6b\x6f\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xfb\x63\x80\xae\xfb\x63\x80\xae\x98\xbd\x49\xaf\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xee\xa9\x9d\x2d\xee\xa9\x9d\x2d\x26\xc8\x28\xb0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x48\xa3\x2e\x18\x48\xa3\x2e\xea\x27\xae\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xb8\xcc\x57\x2d\xb8\xcc\x57\x2d\xfc\xc4\xcc\xb0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xee\xb2\xb0\xad\xee\xb2\xb0\xad\x82\x1b\x8e\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x5e\xf2\x32\xae\x5e\xf2\x32\xae\x3c\xe3\xd0\xae\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x55\xe1\xff\xad\x55\xe1\xff\xad\x55\x76\x78\xb0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd4\x59\x61\xae\xd4\x59\x61\xae\xa9\x0a\xe8\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x88\x40\xcc\x2e\x88\x40\xcc\x2e\xad\x09\x01\xb1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xb3\xd4\x24\x2f\xb3\xd4\x24\x2f\x0e\x8e\xa6\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe6\xd5\x29\xae\xe6\xd5\x29\xae\x03\x72\x94\xad\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x4d\xb8\x4c\xaf\x4d\xb8\x4c\xaf\x70\x0b\xae\xb0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x5b\xe7\x13\xaf\x5b\xe7\x13\xaf\xa3\x5f\x1b\x31\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x72\xbd\x1c\x2f\x72\xbd\x1c\x2f\xf8\xa7\x24\xb1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x93\xa6\x73\x2f\x93\xa6\x73\x2f\x5d\x24\xcf\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x73\x04\x63\x2e\x73\x04\x63\x2e\xe3\x6c\xc6\x2d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xec\x77\x77\xaf\xec\x77\x77\xaf\x8d\x0e\xfa\xb0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd5\x3a\x2c\xaf\xd5\x3a\x2c\xaf\x70\x9d\x59\x31\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x3d\x79\xd5\x2e\x3d\x79\xd5\x2e\xcd\xcf\x5b\xb1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07\x2d\x88\x2e\x07\x2d\x88\x2e\x68\x3a\x04\x31\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa1\x0b\xd6\x2e\xa1\x0b\xd6\x2e\xe2\xdb\x79\x2f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1b\x93\x6d\x2e\x1b\x93\x6d\x2e\xd8\x10\x3f\xb1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x68\x1c\x23\xae\x68\x1c\x23\xae\x19\xc6\x9a\x31\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x62\xcd\x8a\xaf\x62\xcd\x8a\xaf\xda\x0b\x94\xb1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf7\xc9\x96\xae\xf7\xc9\x96\xae\x14\x6c\x21\x31\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x63\x34\x8a\x2f\x63\x34\x8a\x2f\x58\x29\x59\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd0\x6a\x44\x2f\xd0\x6a\x44\x2f\xee\x19\x91\xb1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x1d\xd8\xad\x40\x1d\xd8\xad\xe3\x57\xd9\x31\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x38\x67\xb1\xaf\x38\x67\xb1\xaf\xd2\xe9\xc9\xb1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\xbb\x32\xaf\xa0\xbb\x32\xaf\xda\xc5\x43\x31\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x51\x42\xd8\x2f\x51\x42\xd8\x2f\x4e\x84\x01\x31\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf1\xff\x0d\x2f\xf1\xff\x0d\x2f\x5a\x4e\xe1\xb1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xdc\xf0\x26\xaf\xdc\xf0\x26\xaf\xd8\x12\x1c\x32\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xbe\x66\x48\xaf\xbe\x66\x48\xaf\xb0\x7c\x0a\xb2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x5e\x84\x01\x2d\x5e\x84\x01\x2d\xf7\x24\x58\x31\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd4\x33\x80\x2d\xd4\x33\x80\x2d\x2a\xf6\x91\x31\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xad\xbe\x2f\x2e\xad\xbe\x2f\x2e\xd2\x17\x39\xb2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x79\xe0\xca\x2f\x79\xe0\xca\x2f\xd6\x7b\x60\x32\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x58\xcc\xa8\x2e\x58\xcc\xa8\x2e\x13\x64\x28\xb2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xed\xdd\x3c\xb0\xed\xdd\x3c\xb0\x05\xda\x02\x31\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xcf\x8d\xaf\x96\xcf\x8d\xaf\x8b\x05\x0a\x32\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x13\x77\x44\x2f\x13\x77\x44\x2f\x57\xe2\x89\xb2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc5\x27\x73\x30\xc5\x27\x73\x30\x02\xc6\x9a\x32\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x22\x6d\xf2\x2f\x22\x6d\xf2\x2f\x33\x53\x4f\xb2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x46\xcf\x53\xb0\x46\xcf\x53\xb0\x66\x10\xe2\xaf\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x95\x01\x8f\xb0\x95\x01\x8f\xb0\x07\xfc\x82\x32\x00\x00\x00\x00\x00\x00\x00\x00\x8f\x7b\xa1\x2e\x8f\x7b\xa1\x2e\x2f\xe9\xdf\xae\x2f\xe9\xdf\xae\xda\x5d\xdc\xb2\x00\x00\x00\x00\x00\x00\x00\x00\x07\x02\x03\x2e\x07\x02\x03\x2e\x92\xb6\xba\x30\x92\xb6\xba\x30\x72\x1e\xd0\x32\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x84\xec\xac\x0a\x84\xec\xac\x38\x85\x63\x30\x38\x85\x63\x30\xe5\x95\x2f\xb2\x00\x00\x00\x00\x00\x00\x00\x00\xde\x8b\x39\xae\xde\x8b\x39\xae\x27\x66\x16\xaf\x27\x66\x16\xaf\x39\xfd\x1c\xb2\x00\x00\x00\x00\x00\x00\x00\x00\xba\x6f\x9e\xae\xba\x6f\x9e\xae\xee\xa1\x8c\xb0\xee\xa1\x8c\xb0\x88\xf2\xd8\x32\x00\x00\x00\x00\x00\x00\x00\x00\x3d\x75\xce\xae\x3d\x75\xce\xae\xb4\x26\x20\xb0\xb4\x26\x20\xb0\xe3\x8d\x0b\xb3\x00\x00\x00\x00\x00\x00\x00\x00\x23\x14\xea\xae\x23\x14\xea\xae\x9e\x7c\x22\xaf\x9e\x7c\x22\xaf\x7a\xa2\xe6\x32\x00\x00\x00\x00\x00\x00\x00\x00\x70\x64\xed\xae\x70\x64\xed\xae\x12\xee\x32\x30\x12\xee\x32\x30\x37\x59\x01\xb2\x00\x00\x00\x00\x00\x00\x00\x00\x2c\xaa\xd6\xae\x2c\xaa\xd6\xae\xf7\xa3\xe4\x30\xf7\xa3\xe4\x30\x1f\xe7\x9d\xb2\x00\x00\x00\x00\x00\x00\x00\x00\xc3\xd9\xa6\xae\xc3\xd9\xa6\xae\x70\xdc\x25\x30\x70\xdc\x25\x30\x48\x14\x24\x33\x00\x00\x00\x00\x00\x00\x00\x00\x84\x68\x41\xae\x84\x68\x41\xae\x54\x06\xe3\xb0\x54\x06\xe3\xb0\xd3\x3b\x36\xb3\x00\x00\x00\x00\x00\x00\x00\x00\x78\x5c\x8c\xac\x78\x5c\x8c\xac\x8e\xf3\x02\xb1\x8e\xf3\x02\xb1\x05\xe1\xf3\x32\x00\x00\x00\x00\x00\x00\x00\x00\xbc\x5c\x35\x2e\xbc\x5c\x35\x2e\x68\x73\x3b\xaf\x68\x73\x3b\xaf\x97\x32\x2b\x30\x00\x00\x00\x00\x00\x00\x00\x00\x26\x2a\xc2\x2e\x26\x2a\xc2\x2e\x13\x6e\x31\x31\x13\x6e\x31\x31\xb5\x3f\x10\xb3\x00\x00\x00\x00\x00\x00\x00\x00\xf0\xc4\x12\x2f\xf0\xc4\x12\x2f\x1b\x17\xc8\x30\x1b\x17\xc8\x30\x33\x47\x69\x33\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x53\x3e\x2f\xa4\x53\x3e\x2f\xbb\x7a\xf1\xaf\xbb\x7a\xf1\xaf\xde\x8f\x5c\xb3\x00\x00\x00\x00\x00\x00\x00\x00\x92\x06\x60\x2f\x92\x06\x60\x2f\xaf\x78\x18\xb1\xaf\x78\x18\xb1\xcc\x16\xcf\x32\x00\x00\x00\x00\x00\x00\x00\x00\xb2\xd3\x74\x2f\xb2\xd3\x74\x2f\x58\x91\xc0\xb0\x58\x91\xc0\xb0\x5f\x94\x90\x32\x00\x00\x00\x00\x00\x00\x00\x00\xe3\xae\x7a\x2f\xe3\xae\x7a\x2f\x43\x29\xaf\x2f\x43\x29\xaf\x2f\xd3\x72\x65\xb3\x00\x00\x00\x00\x00\x00\x00\x00\x62\xc6\x70\x2f\x62\xc6\x70\x2f\xd7\x54\x29\x31\xd7\x54\x29\x31\x04\x66\x94\x33\x00\x00\x00\x00\x00\x00\x00\x00\x9c\xa7\x57\x2f\x9c\xa7\x57\x2f\x7b\x44\x7d\x30\x7b\x44\x7d\x30\xb0\xf8\x6b\xb3\x00\x00\x00\x00\x00\x00\x00\x00\xb2\x46\x31\x2f\xb2\x46\x31\x2f\xf5\xd7\x89\xad\xf5\xd7\x89\xad\x7e\x3b\x63\x32\x00\x00\x00\x00\x00\x00\x00\x00\x66\xe5\x00\x2f\x66\xe5\x00\x2f\xf9\xd0\x3b\xb1\xf9\xd0\x3b\xb1\x13\x79\x24\x33\x00\x00\x00\x00\x00\x00\x00\x00\x3a\xb2\x95\x2e\x3a\xb2\x95\x2e\x15\x41\x07\xb1\x15\x41\x07\xb1\x00\x15\xa2\xb3\x00\x00\x00\x00\x00\x00\x00\x00\xf9\x90\xa1\x2d\xf9\x90\xa1\x2d\xa1\x4a\xd0\x30\xa1\x4a\xd0\x30\xc8\xc8\xb0\x33\x00\x00\x00\x00\x00\x00\x00\x00\xa4\xb8\xed\xad\xa4\xb8\xed\xad\x5f\xfc\x37\x31\x5f\xfc\x37\x31\x69\xbe\x60\xb3\x00\x00\x00\x00\x00\x00\x00\x00\x6d\x8b\x8b\xae\x6d\x8b\x8b\xae\x78\xea\x91\x30\x78\xea\x91\x30\x3a\xec\xd7\xb1\x00\x00\x00\x00\x00\x00\x00\x00\xe2\x48\xbf\xae\xe2\x48\xbf\xae\xdd\x14\x06\xb1\xdd\x14\x06\xb1\x5d\xe5\x8c\x33\x00\x00\x00\x00\x00\x00\x00\x00\xcf\x97\xd0\xae\xcf\x97\xd0\xae\xb4\x8e\x60\xb1\xb4\x8e\x60\xb1\xa0\x7f\xd2\xb3\x00\x00\x00\x00\x00\x00\x00\x00\xb3\xee\xbc\xae\xb3\xee\xbc\xae\xa9\x0d\xc9\x2e\xa9\x0d\xc9\x2e\xcc\xec\xc1\x33\x00\x00\x00\x00\x00\x00\x00\x00\x49\xf4\x85\xae\x49\xf4\x85\xae\x7b\x32\x2e\x31\x7b\x32\x2e\x31\x1d\xff\x29\xb3\x00\x00\x00\x00\x00\x00\x00\x00\x8f\x54\xc7\xad\x8f\x54\xc7\xad\x8a\x64\x29\x31\x8a\x64\x29\x31\x2f\xea\x18\xb3\x00\x00\x00\x00\x00\x00\x00\x00\x2e\x3d\xd3\x2d\x2e\x3d\xd3\x2d\x10\xb4\x2b\xaf\x10\xb4\x2b\xaf\x24\x27\xcf\x33\x00\x00\x00\x00\x00\x00\x00\x00\x82\x6d\x9f\x2e\x82\x6d\x9f\x2e\xf1\x6b\x81\xb1\xf1\x6b\x81\xb1\x00\x98\xf8\xb3\x00\x00\x00\x00\x00\x00\x00\x00\x42\x8b\xfc\x2e\x42\x8b\xfc\x2e\x8d\x0f\x03\xb1\x8d\x0f\x03\xb1\x85\x97\xb9\x33\x00\x00\x00\x00\x00\x00\x00\x00\xd7\x95\x1c\x2f\xd7\x95\x1c\x2f\xd1\x04\xf6\x30\xd1\x04\xf6\x30\x91\x35\x7d\xb2\x00\x00\x00\x00\x00\x00\x00\x00\xa3\x4b\x21\x2f\xa3\x4b\x21\x2f\xbf\x58\x7e\x31\xbf\x58\x7e\x31\x76\xe2\x93\xb3\x00\x00\x00\x00\x00\x00\x00\x00\x98\x30\x04\x2f\x98\x30\x04\x2f\x27\xe8\x1e\x31\x27\xe8\x1e\x31\x69\xbb\x03\x34\x00\x00\x00\x00\x00\x00\x00\x00\x1f\x06\x7d\x2e\x1f\x06\x7d\x2e\xc6\x97\x4d\xb1\xc6\x97\x4d\xb1\x76\xc0\x05\xb4\x00\x00\x00\x00\x00\x00\x00\x00\x87\x41\x41\xae\x87\x41\x41\xae\xbe\xdf\x93\xb1\xbe\xdf\x93\xb1\x38\xe7\x9b\x33\x00\x00\x00\x00\x00\x00\x00\x00\xdd\x44\x49\xaf\xdd\x44\x49\xaf\x3a\x69\x6b\x2f\x3a\x69\x6b\x2f\x91\x42\x8e\x32\x00\x00\x00\x00\x00\x00\x00\x00\xca\xd9\xc2\xaf\xca\xd9\xc2\xaf\x5c\x66\x11\x31\x5c\x66\x11\x31\xcf\xeb\xdb\xb3\x00\x00\x00\x00\x00\x00\x00\x00\xe0\xb2\x16\xb0\xe0\xb2\x16\xb0\x76\xd1\xb2\x31\x76\xd1\xb2\x31\x64\x9c\x1a\x34\x00\x00\x00\x00\x00\x00\x00\x00\x4f\x40\x4e\xb0\x4f\x40\x4e\xb0\xac\x6b\x3b\x30\xac\x6b\x3b\x30\xfa\x37\x05\xb4\x00\x00\x00\x00\x00\x00\x00\x00\xfd\x96\x81\xb0\xfd\x96\x81\xb0\x52\x25\x4f\xb1\x52\x25\x4f\xb1\xb8\x77\x51\x33\x00\x00\x00\x00\x00\x00\x00\x00\x5c\xed\x97\xb0\x5c\xed\x97\xb0\x4d\x6a\xc1\xb1\x4d\x6a\xc1\xb1\x40\xc0\x61\x33\x00\x00\x00\x00\x00\x00\x00\x00\x61\x2a\xa7\xb0\x61\x2a\xa7\xb0\x4f\x1c\x6d\xb0\x4f\x1c\x6d\xb0\xf3\x83\x10\xb4\x00\x00\x00\x00\x00\x00\x00\x00\xbb\x6e\xac\xb0\xbb\x6e\xac\xb0\x49\x48\x95\x31\x49\x48\x95\x31\x24\x76\x2a\x34\x00\x00\x00\x00\x00\x00\x00\x00\x84\x40\xa5\xb0\x84\x40\xa5\xb0\x91\xfd\x03\x32\x91\xfd\x03\x32\xb7\x5e\xee\xb3\x00\x00\x00\x00\x00\x00\x00\x00\x1d\xdc\x8f\xb0\x1d\xdc\x8f\xb0\x42\xb5\x69\xb0\x42\xb5\x69\xb0\x66\xb7\x4a\x32\x00\x00\x00\x00\x00\x00\x00\x00\x5f\x08\x57\xb0\x5f\x08\x57\xb0\x81\x6c\xf1\xb1\x81\x6c\xf1\xb1\x4f\xbf\xc4\x33\x00\x00\x00\x00\x00\x00\x00\x00\x1c\x28\xe3\xaf\x1c\x28\xe3\xaf\x91\x12\xe8\xb1\x91\x12\xe8\xb1\x1e\x24\x27\xb4\x00\x00\x00\x00\x00\x00\x00\x00\xec\x0a\x47\x2e\xec\x0a\x47\x2e\x3a\x43\x0d\x31\x3a\x43\x0d\x31\xae\x63\x27\x34\x00\x00\x00\x00\x00\x00\x00\x00\x8d\x76\x1b\x30\x8d\x76\x1b\x30\x7c\x95\xe3\x31\x7c\x95\xe3\x31\x8f\x84\xba\xb3\x00\x00\x00\x00\x00\x00\x00\x00\xe9\x3f\x98\x30\xe9\x3f\x98\x30\x76\x2a\x1c\x31\x76\x2a\x1c\x31\x00\x32\xd3\xb2\x00\x00\x00\x00\x00\x00\x00\x00\xd3\xa5\xde\x30\xd3\xa5\xde\x30\xa2\x2d\x18\xb1\xa2\x2d\x18\xb1\x20\x6f\x04\x34\x00\x00\x00\x00\x00\x00\x00\x00\x66\x31\x0c\x31\x66\x31\x0c\x31\x96\x73\xa1\xb1\x96\x73\xa1\xb1\xc8\xf4\x31\xb4\x00\x00\x00\x00\x00\x00\x00\x00\x72\xee\x1d\x31\x72\xee\x1d\x31\xe5\x33\xd6\xb1\xe5\x33\xd6\xb1\x6c\xd7\x17\x34\x00\x00\x00\x00\x00\x00\x00\x00\x0b\x72\x1f\x31\x0b\x72\x1f\x31\xc0\xb1\xe5\xb0\xc0\xb1\xe5\xb0\x24\x18\x80\xb3\x00\x00\x00\x00\x00\x00\x00\x00\x3e\xa3\x0b\x31\x3e\xa3\x0b\x31\x97\xad\x85\x31\x97\xad\x85\x31\xe1\x9d\x6c\xb3\x00\x00\x00\x00\x00\x00\x00\x00\xb8\x76\xbb\x30\xb8\x76\xbb\x30\x84\xf1\xeb\x31\x84\xf1\xeb\x31\xdd\x26\x23\x34\x00\x00\x00\x00\x00\x00\x00\x00\x7a\xeb\x8c\x2f\x7a\xeb\x8c\x2f\x0a\xf6\x86\xb1\x0a\xf6\x86\xb1\x89\xe7\x3b\xb4\x00\x00\x00\x00\x00\x00\x00\x00\x8e\xa8\xb7\xb0\x8e\xa8\xb7\xb0\xbc\xdf\x39\xb2\xbc\xdf\x39\xb2\x6e\x09\xf5\x33\x00\x00\x00\x00\x00\x00\x00\x00\x3f\x6b\x6c\xb1\x3f\x6b\x6c\xb1\x0c\x89\xcc\xb1\x0c\x89\xcc\xb1\xd2\xbd\x34\xb2\x00\x00\x00\x00\x00\x00\x00\x00\x1a\x27\x10\xb2\x1a\x27\x10\xb2\x8e\x9b\x6b\x31\x8e\x9b\x6b\x31\x64\xe0\xbc\xb3\x00\x00\x00\x00\x00\x00\x00\x00\x75\x78\x54\xb2\x75\x78\x54\xb2\x0b\x4c\xc4\x31\x0b\x4c\xc4\x31\xf3\xb5\x1f\x34\x00\x00\x00\x00\x00\x00\x00\x00\x22\x63\x94\xb2\x22\x63\x94\xb2\x72\x15\xa2\xb0\x72\x15\xa2\xb0\xce\x9c\x1f\xb4\x00\x00\x00\x00\x00\x00\x00\x00\x29\xac\xc2\xb2\x29\xac\xc2\xb2\x38\x60\xa5\xb1\x38\x60\xa5\xb1\x6c\x52\xba\x33\x00\x00\x00\x00\x00\x00\x00\x00\x1c\xd9\xf1\xb2\x1c\xd9\xf1\xb2\xdd\xbf\x24\xb2\xdd\xbf\x24\xb2\x93\x63\x11\x32\x00\x00\x00\x00\x00\x00\x00\x00\x70\x15\x11\xb3\x70\x15\x11\xb3\xc3\xde\xf7\xb0\xc3\xde\xf7\xb0\xde\xbb\xd0\xb3\x00\x00\x00\x00\x00\x00\x00\x00\x43\x0f\x2a\xb3\x43\x0f\x2a\xb3\xef\xe6\x19\x30\xef\xe6\x19\x30\x20\xa0\x1b\x34\x00\x00\x00\x00\x00\x00\x00\x00\x8b\x8e\x43\xb3\x8b\x8e\x43\xb3\x22\xd0\x66\xb1\x22\xd0\x66\xb1\x5e\x16\x0e\xb4\x00\x00\x00\x00\x00\x00\x00\x00\x7a\xe9\x5c\xb3\x7a\xe9\x5c\xb3\xb9\xf6\x90\xb1\xb9\xf6\x90\xb1\x2f\x2d\x8a\x33\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x29\x75\xb3\x0f\x29\x75\xb3\xa5\x2c\xb1\xb1\xa5\x2c\xb1\xb1\xee\xae\xf2\x32\x00\x00\x00\x00\x00\x00\x00\x00\x0c\xa1\x85\xb3\x0c\xa1\x85\xb3\x76\xa1\x10\xb2\x76\xa1\x10\xb2\x1a\x59\xdd\xb3\x00\x00\x00\x00\x00\x00\x00\x00\x3e\x45\x8f\xb3\x3e\x45\x8f\xb3\x94\xfa\xf9\xb1\x94\xfa\xf9\xb1\x69\xc5\x0c\x34\x00\x00\x00\x00\x00\x00\x00\x00\x48\x7e\x97\xb3\x48\x7e\x97\xb3\x55\x77\x79\xb1\x55\x77\x79\xb1\x34\x43\xe6\xb3\x00\x00\x00\x00\x00\x00\x00\x00\xa5\x80\x9e\xb3\xa5\x80\x9e\xb3\xca\xbe\x15\xb1\xca\xbe\x15\xb1\x70\xf2\x3d\x33\x00\x00\x00\x00\x00\x00\x00\x00\xb2\x79\xa4\xb3\xb2\x79\xa4\xb3\x20\xce\x50\xb2\x20\xce\x50\xb2\x6b\xf2\x07\x33\x00\x00\x00\x00\x00\x00\x00\x00\x40\x63\xa9\xb3\x40\x63\xa9\xb3\xf3\xbb\x80\xb2\xf3\xbb\x80\xb2\xf4\x83\xc5\xb3\x00\x00\x00\x00\x00\x00\x00\x00\x78\x0e\xad\xb3\x78\x0e\xad\xb3\x6b\xbd\x2a\xb2\x6b\xbd\x2a\xb2\xdd\xd9\xf9\x33\x00\x00\x00\x00\x00\x00\x00\x00\xd1\x5e\xaf\xb3\xd1\x5e\xaf\xb3\xef\x1c\x07\xb2\xef\x1c\x07\xb2\x63\xf0\xc8\xb3\x00\x00\x00\x00\x00\x00\x00\x00\x97\x84\xb0\xb3\x97\x84\xb0\xb3\xf5\x90\x1a\xb2\xf5\x90\x1a\xb2\x82\x5e\x16\x33\x00\x00\x00\x00\x00\x00\x00\x00\x36\x01\xb1\xb3\x36\x01\xb1\xb3\xa5\xed\x90\xb2\xa5\xed\x90\xb2\x86\xde\xff\x32\x00\x00\x00\x00\x00\x00\x00\x00\xaf\x67\xb1\xb3\xaf\x67\xb1\xb3\xb5\xb3\xb4\xb2\xb5\xb3\xb4\xb2\x3e\x1c\xaf\xb3\x00\x00\x00\x00\x00\x00\x00\x00\xac\x03\xb2\xb3\xac\x03\xb2\xb3\x24\xa1\xa0\xb2\x24\xa1\xa0\xb2\x7d\x04\xe0\x33\x00\x00\x00\x00\x00\x00\x00\x00\x26\xac\xb2\xb3\x26\xac\xb2\xb3\x38\x64\x97\xb2\x38\x64\x97\xb2\x6d\xe8\xb0\xb3\x00\x00\x00\x00\x00\x00\x00\x00\xf9\xe9\xb2\xb3\xf9\xe9\xb2\xb3\xb5\x1d\x9a\xb2\xb5\x1d\x9a\xb2\xdb\x36\x01\x33\x00\x00\x00\x00\x00\x00\x00\x00\x56\x59\xb2\xb3\x56\x59\xb2\xb3\x12\x81\xb3\xb2\x12\x81\xb3\xb2\x8f\xcd\xda\x32\x00\x00\x00\x00\x00\x00\x00\x00\x65\xfa\xb0\xb3\x65\xfa\xb0\xb3\x65\xbc\xcd\xb2\x65\xbc\xcd\xb2\x83\xef\x99\xb3\x00\x00\x00\x00\x00\x00\x00\x00\x33\x2d\xaf\xb3\x33\x2d\xaf\xb3\xfa\x9c\x10\xb3\xfa\x9c\x10\xb3\xa4\xdd\xc1\x33\x00\x00\x00\x00\x00\x00\x00\x00\xda\x55\xad\xb3\xda\x55\xad\xb3\x14\xa6\x14\xb3\x14\xa6\x14\xb3\x2c\xfd\x95\xb3\x00\x00\x00\x00\x00\x00\x00\x00\x65\x6f\xab\xb3\x65\x6f\xab\xb3\xfc\x9b\xe5\xb2\xfc\x9b\xe5\xb2\x19\x3d\xf5\x32\x00\x00\x00\x00\x00\x00\x00\x00\xdb\xe8\xa8\xb3\xdb\xe8\xa8\xb3\x87\x7e\xed\xb2\x87\x7e\xed\xb2\x23\x2c\x8c\x32\x00\x00\x00\x00\x00\x00\x00\x00\x88\xf1\xa4\xb3\x88\xf1\xa4\xb3\xbd\x05\x1a\xb3\xbd\x05\x1a\xb3\x5d\xef\x70\xb3\x00\x00\x00\x00\x00\x00\x00\x00\xe4\xfe\x9e\xb3\xe4\xfe\x9e\xb3\xfe\x94\x46\xb3\xfe\x94\x46\xb3\x8a\x0a\x9f\x33\x00\x00\x00\x00\x00\x00\x00\x00\xcc\x20\x97\xb3\xcc\x20\x97\xb3\xca\xf5\x46\xb3\xca\xf5\x46\xb3\x75\x12\x87\xb3\x00\x00\x00\x00\x00\x00\x00\x00\x22\xda\x8d\xb3\x22\xda\x8d\xb3\x7a\x3a\x30\xb3\x7a\x3a\x30\xb3\x92\xc8\x09\x33\x00\x00\x00\x00\x00\x00\x00\x00\x64\x98\x83\xb3\x64\x98\x83\xb3\x1a\x43\x33\xb3\x1a\x43\x33\xb3\x19\x09\xd1\x31\x00\x00\x00\x00\x00\x00\x00\x00\x37\x7c\x70\xb3\x37\x7c\x70\xb3\xb4\xd1\x58\xb3\xb4\xd1\x58\xb3\x9b\xe4\x25\xb3\x00\x00\x00\x00\x00\x00\x00\x00\x64\x63\x56\xb3\x64\x63\x56\xb3\x68\x39\x6f\xb3\x68\x39\x6f\xb3\x56\xf8\x6e\x33\x00\x00\x00\x00\x00\x00\x00\x00\x58\xf7\x37\xb3\x58\xf7\x37\xb3\x10\x8b\x6b\xb3\x10\x8b\x6b\xb3\x0c\xd2\x69\xb3\x00\x00\x00\x00\x00\x00\x00\x00\x86\xfd\x15\xb3\x86\xfd\x15\xb3\x74\x9b\x75\xb3\x74\x9b\x75\xb3\xee\x96\x21\x33\x00\x00\x00\x00\x00\x00\x00\x00\x2d\x9f\xe6\xb2\x2d\x9f\xe6\xb2\x0d\xa0\x82\xb3\x0d\xa0\x82\xb3\xc4\xb8\x47\xb2\x00\x00\x00\x00\x00\x00\x00\x00\x65\x32\xa7\xb2\x65\x32\xa7\xb2\x2f\x42\x8b\xb3\x2f\x42\x8b\xb3\xf2\xdb\x8a\xb2\x00\x00\x00\x00\x00\x00\x00\x00\x5e\xc3\x64\xb2\x5e\xc3\x64\xb2\x32\x45\x8e\xb3\x32\x45\x8e\xb3\xab\x92\x1c\x33\x00\x00\x00\x00\x00\x00\x00\x00\xd5\xa5\x0e\xb2\xd5\xa5\x0e\xb2\x2a\x8a\x9c\xb3\x2a\x8a\x9c\xb3\x34\xa0\x3b\xb3\x00\x00\x00\x00\x00\x00\x00\x00\x78\xe0\x82\xb1\x78\xe0\x82\xb1\xb3\xbb\xa3\xb3\xb3\xbb\xa3\xb3\xf5\xfc\x38\x33\x00\x00\x00\x00\x00\x00\x00\x00\x74\x6d\x54\x30\x74\x6d\x54\x30\x33\x98\xa3\xb3\x33\x98\xa3\xb3\x85\xba\x1a\xb3\x00\x00\x00\x00\x00\x00\x00\x00\xd6\x24\xbd\x31\xd6\x24\xbd\x31\xbc\x40\xaa\xb3\xbc\x40\xaa\xb3\x5b\x74\x9a\x32\x00\x00\x00\x00\x00\x00\x00\x00\xf8\xd2\x28\x32\xf8\xd2\x28\x32\xb2\x12\xba\xb3\xb2\x12\xba\xb3\x1a\x8c\xde\x31\x00\x00\x00\x00\x00\x00\x00\x00\xc4\x51\x60\x32\xc4\x51\x60\x32\x79\xbb\xc7\xb3\x79\xbb\xc7\xb3\xf1\x45\x07\xb3\x00\x00\x00\x00\x00\x00\x00\x00\xb2\xd3\x81\x32\xb2\xd3\x81\x32\x04\x77\xc7\xb3\x04\x77\xc7\xb3\xf0\x01\x6e\x33\x00\x00\x00\x00\x00\x00\x00\x00\x4a\xbe\x90\x32\x4a\xbe\x90\x32\x43\x08\xc4\xb3\x43\x08\xc4\xb3\xf2\x93\x9b\xb3\x00\x00\x00\x00\x00\x00\x00\x00\x23\xa7\xa8\x32\x23\xa7\xa8\x32\x41\x7a\xd2\xb3\x41\x7a\xd2\xb3\x0e\x08\x9d\x33\x00\x00\x00\x00\x00\x00\x00\x00\x8e\x92\xd1\x32\x8e\x92\xd1\x32\x3d\xe9\xe8\xb3\x3d\xe9\xe8\xb3\xba\x95\x3a\xb3\x00\x00\x00\x00\x00\x00\x00\x00\x6a\xb3\x04\x33\x6a\xb3\x04\x33\x71\xa2\xec\xb3\x71\xa2\xec\xb3\xcb\xd2\xb0\xb2\x00\x00\x00\x00\x00\x00\x00\x00\x7a\x90\x22\x33\x7a\x90\x22\x33\xc3\xdc\xef\xb3\xc3\xdc\xef\xb3\x7b\xd4\xcb\x33\x00\x00\x00\x00\x00\x00\x00\x00\x32\xf4\x3c\x33\x32\xf4\x3c\x33\xe8\xf8\xf3\xb3\xe8\xf8\xf3\xb3\xc0\x54\x1e\xb4\x00\x00\x00\x00\x00\x00\x00\x00\xc7\xb0\x53\x33\xc7\xb0\x53\x33\xaf\xd8\xf4\xb3\xaf\xd8\xf4\xb3\x4e\xa5\x23\x34\x00\x00\x00\x00\x00\x00\x00\x00\x08\x0f\x6d\x33\x08\x0f\x6d\x33\x39\xe6\xfc\xb3\x39\xe6\xfc\xb3\xe3\x50\xbf\xb3\x00\x00\x00\x00\x00\x00\x00\x00\x94\x7a\x88\x33\x94\x7a\x88\x33\xc0\x1f\x0e\xb4\xc0\x1f\x0e\xb4\xce\x9b\x16\xb3\x00\x00\x00\x00\x00\x00\x00\x00\x67\x53\xa0\x33\x67\x53\xa0\x33\x2a\x5c\x09\xb4\x2a\x5c\x09\xb4\x00\xcd\x39\x34\x00\x00\x00\x00\x00\x00\x00\x00\xcc\xb1\xb8\x33\xcc\xb1\xb8\x33\xc0\xe0\x07\xb4\xc0\xe0\x07\xb4\x9e\xb4\x89\xb4\x00\x00\x00\x00\x00\x00\x00\x00\x19\xaa\xc7\x33\x19\xaa\xc7\x33\xb2\xc4\xef\xb3\xb2\xc4\xef\xb3\x82\xbb\x7c\x34\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x65\xc4\x33\xa4\x65\xc4\x33\x06\x60\xe8\xb3\x06\x60\xe8\xb3\x20\xe6\xfa\xb3\x00\x00\x00\x00\x00\x00\x00\x00\x12\xa8\xad\x33\x12\xa8\xad\x33\xfd\xa0\x08\xb4\xfd\xa0\x08\xb4\x65\xbc\x8d\xb3\x00\x00\x00\x00\x00\x00\x00\x00\x4e\x99\x8c\x33\x4e\x99\x8c\x33\x11\x39\x25\xb4\x11\x39\x25\xb4\x29\xc0\x95\x34\x00\x00\x00\x00\x5b\xe1\x83\xaf\x03\x40\x88\x33\x03\x40\x88\x33\xc9\x1f\x16\xb4\xc9\x1f\x16\xb4\x59\xb0\xe3\xb4\x00\x00\x00\x00\xbd\xbc\x47\xaf\xbe\x04\x7e\x33\xbe\x04\x7e\x33\x13\x96\xe6\xb3\x13\x96\xe6\xb3\xd8\x3d\xc7\x34\x00\x00\x00\x00\x91\xd7\xf8\xae\x9f\xdb\x91\x33\x9f\xdb\x91\x33\xfa\xf1\xec\xb3\xfa\xf1\xec\xb3\x71\xc6\xee\xb3\x00\x00\x00\x00\x26\xb7\x7f\xae\x65\xdf\xb4\x33\x65\xdf\xb4\x33\xeb\x29\x06\xb4\xeb\x29\x06\xb4\xb5\xce\x70\xb4\x00\x00\x00\x00\x87\x7a\x6f\xae\x95\xc6\xd5\x33\x95\xc6\xd5\x33\x94\x00\x15\xb4\x94\x00\x15\xb4\xc4\xc7\x02\x35\x00\x00\x00\x00\x76\xf4\xd0\xae\xcf\xcf\xe6\x33\xcf\xcf\xe6\x33\xe2\x71\x16\xb4\xe2\x71\x16\xb4\x32\x47\x1a\xb5\x00\x00\x00\x00\xec\xcc\x0b\xaf\xfc\xec\xe4\x33\xfc\xec\xe4\x33\x3b\x20\x0b\xb4\x3b\x20\x0b\xb4\xfe\x45\xe1\x34\x00\x00\x00\x00\x30\x7e\xd0\xae\x87\x71\xd7\x33\x87\x71\xd7\x33\x72\xe3\xe2\xb3\x72\xe3\xe2\xb3\x04\xe5\x09\xb3\x00\x00\x00\x00\xe7\x08\x4c\x2d\x7e\x1b\xc9\x33\x7e\x1b\xc9\x33\x4c\xd8\xaf\xb3\x4c\xd8\xaf\xb3\x83\xd2\xe5\xb4\x00\x00\x00\x00\xd2\xf9\x17\x2f\x61\x8b\xbf\x33\x61\x8b\xbf\x33\xc9\x32\xd1\xb3\xc9\x32\xd1\xb3\xe9\x65\x42\x35\x00\x00\x00\x00\x89\x8a\x5d\x2f\xf6\xe0\xb7\x33\xf6\xe0\xb7\x33\xc5\xbb\x13\xb4\xc5\xbb\x13\xb4\x36\x7f\x40\xb5\x00\x00\x00\x00\xd2\x1a\x24\x2f\x7e\x78\xaa\x33\x7e\x78\xaa\x33\x10\x96\x11\xb4\x10\x96\x11\xb4\xe4\x6f\xd6\x34\x00\x00\x00\x00\x4b\xfa\x9f\x2c\x1b\x1b\x92\x33\x1b\x1b\x92\x33\x68\xb2\xd6\xb3\x68\xb2\xd6\xb3\x7d\xef\x18\x34\x00\x00\x00\x00\x90\x9c\x1e\xaf\x4d\xd8\x61\x33\x4d\xd8\x61\x33\xec\xa6\x48\xb3\xec\xa6\x48\xb3\x54\x6e\x39\xb5\x00\x00\x00\x00\xa6\x6a\x5f\xaf\x85\x3a\x1f\x33\x85\x3a\x1f\x33\xff\x26\x6b\xb3\xff\x26\x6b\xb3\x69\xa5\x81\x35\x00\x00\x00\x00\x72\xda\x18\xaf\x19\xe5\xde\x32\x19\xe5\xde\x32\x5b\x94\xad\xb3\x5b\x94\xad\xb3\x74\xe6\x59\xb5\x00\x00\x00\x00\x42\xad\x00\xac\xaf\xb7\xb4\x32\xaf\xb7\xb4\x32\x14\xc7\xed\xb3\x14\xc7\xed\xb3\x5d\x41\x92\x34\x00\x00\x00\x00\x93\x9b\xfa\x2e\xf3\xfb\xae\x32\xf3\xfb\xae\x32\x2e\x0a\xb5\xb3\x2e\x0a\xb5\xb3\x72\xa9\xe5\x34\x00\x00\x00\x00\x21\xa7\x1a\x2f\x67\xe1\xa9\x32\x67\xe1\xa9\x32\x8c\x8a\x64\xb3\x8c\x8a\x64\xb3\x60\x1b\x83\xb5\x00\x00\x00\x00\x6c\xf5\xba\x2e\x36\xcf\x8b\x32\x36\xcf\x8b\x32\x72\xa9\x1f\xb2\x72\xa9\x1f\xb2\x54\x68\x98\x35\x00\x00\x00\x00\xbe\xb7\x88\x2d\x33\x16\x38\x32\x33\x16\x38\x32\xa2\xe0\xce\xb2\xa2\xe0\xce\xb2\x9c\x15\x58\xb5\x00\x00\x00\x00\x91\x39\x4b\x2a\x59\x04\xfc\x31\x59\x04\xfc\x31\x8d\x32\x14\xb3\x8d\x32\x14\xb3\x62\x47\x94\x33\x00\x00\x00\x00\x19\x1a\x49\x2e\x82\x87\x2e\x32\x82\x87\x2e\x32\x2c\x8a\x8f\xb3\x2c\x8a\x8f\xb3\xb7\x10\x48\x35\x00\x00\x00\x00\x42\xea\xc3\x2e\x11\x46\xa2\x32\x11\x46\xa2\x32\xd8\x71\x52\xb3\xd8\x71\x52\xb3\x8c\x9e\xa8\xb5\x00\x00\x00\x00\x97\xb6\x55\x2e\x83\xc9\xef\x32\x83\xc9\xef\x32\x1f\x7a\x48\x32\x1f\x7a\x48\x32\x6b\x35\xa9\x35\x00\x00\x00\x00\x95\x7c\xe9\xae\x0e\xf5\xff\x32\x0e\xf5\xff\x32\xe3\xcb\x17\x33\xe3\xcb\x17\x33\x1d\x52\x3e\xb5\x00\x00\x00\x00\xff\x9f\xb1\xaf\xab\xc9\xb2\x32\xab\xc9\xb2\x32\xed\x7f\xe7\x32\xed\x7f\xe7\x32\x23\x70\x76\xb4\x00\x00\x00\x00\x7d\x93\x09\xb0\x09\x2f\x86\x31\x09\x2f\x86\x31\xc2\x3a\x1c\xb2\xc2\x3a\x1c\xb2\x15\x34\x94\x35\x00\x00\x00\x00\x0c\x06\x19\xb0\x6b\xda\x69\xb2\x6b\xda\x69\xb2\x31\x0f\x01\xb3\x31\x0f\x01\xb3\xbd\x13\xcb\xb5\x00\x00\x00\x00\x6f\x93\x03\xb0\x17\x42\xdd\xb2\x17\x42\xdd\xb2\x88\x7f\xcb\x32\x88\x7f\xcb\x32\x1f\xc8\xae\x35\x00\x00\x00\x00\xcf\xab\xab\xaf\x49\xe4\x09\xb3\x49\xe4\x09\xb3\x5e\xb6\x9a\x33\x5e\xb6\x9a\x33\x89\xb5\x00\xb5\x00\x00\x00\x00\x64\xed\xef\xae\x88\xa3\x1e\xb3\x88\xa3\x1e\xb3\xd9\x5e\xb7\x33\xd9\x5e\xb7\x33\x69\xd6\x2a\xb5\x00\x00\x00\x00\xeb\x42\xfe\x2e\x17\x69\x3e\xb3\x17\x69\x3e\xb3\x9a\x94\x6f\x33\x9a\x94\x6f\x33\xa0\x66\xc5\x35\x00\x00\x00\x00\x2f\x51\xcc\x2f\x74\x19\x67\xb3\x74\x19\x67\xb3\x0f\xfb\xa4\x31\x0f\xfb\xa4\x31\x56\xba\xdf\xb5\x00\x00\x00\x00\x4a\xe0\x2f\x30\x81\xab\x81\xb3\x81\xab\x81\xb3\x33\xbe\x0b\x33\x33\xbe\x0b\x33\xd3\x03\x9d\x35\x00\x00\x00\x00\xde\xbd\x65\x30\xe5\x7a\x7d\xb3\xe5\x7a\x7d\xb3\x1b\xe6\xd1\x33\x1b\xe6\xd1\x33\xc4\x44\xf0\xb3\x00\x00\x00\x00\xaf\x03\x68\x30\xe6\xb1\x54\xb3\xe6\xb1\x54\xb3\x79\x17\x17\x34\x79\x17\x17\x34\x80\x2b\x8c\xb5\x00\x00\x00\x00\x5c\x43\x28\x30\xde\xc9\x22\xb3\xde\xc9\x22\xb3\x8b\xc9\x07\x34\x8b\xc9\x07\x34\xcf\xb0\xe7\x35\x00\x00\x00\x00\x47\x84\x78\x2f\xd2\xca\x0d\xb3\xd2\xca\x0d\xb3\xc0\x31\x76\x33\xc0\x31\x76\x33\x36\xf1\xe0\xb5\x00\x00\x00\x00\x8b\xa1\xff\xae\xa1\x24\x2f\xb3\xa1\x24\x2f\xb3\x0d\x5e\x32\x33\x0d\x5e\x32\x33\x5f\x2d\x76\x35\x00\x00\x00\x00\x9c\xb4\x83\xaf\xd4\x85\x80\xb3\xd4\x85\x80\xb3\x54\xf2\xe9\x33\x54\xf2\xe9\x33\x37\xf5\x9a\x34\x00\x00\x00\x00\x73\x00\x18\xaf\x07\x94\xaf\xb3\x07\x94\xaf\xb3\xa3\x8e\x17\x34\xa3\x8e\x17\x34\x55\xcd\xba\xb5\x00\x00\x00\x00\xd8\xc1\x2c\xab\x2f\x63\xce\xb3\x2f\x63\xce\xb3\x33\x0d\x4b\x34\x33\x0d\x4b\x34\xf2\x46\xfc\x35\x00\x00\x00\x00\x98\xc1\x82\xae\x83\x31\xd2\xb3\x83\x31\xd2\xb3\x49\x3f\x0e\x34\x49\x3f\x0e\x34\x06\x8d\xd2\xb5\x00\x00\x00\x00\xe9\x3f\xc9\xaf\x24\x0b\xc5\xb3\x24\x0b\xc5\xb3\x0c\xcd\xb0\x33\x0c\xcd\xb0\x33\x43\x4f\x1b\x35\x00\x00\x00\x00\x9d\x74\x3b\xb0\xcd\x26\xbf\xb3\xcd\x26\xbf\xb3\x9c\xb8\x59\x33\x9c\xb8\x59\x33\xd2\x3e\x39\x35\x00\x00\x00\x00\xd4\x1c\x2b\xb0\xba\x51\xd2\xb3\xba\x51\xd2\xb3\xc2\x53\xf0\x33\xc2\x53\xf0\x33\xe0\xc2\xe0\xb5\x00\x00\x00\x00\xc5\x15\x46\x2d\x5b\x12\xf7\xb3\x5b\x12\xf7\xb3\x53\x71\x40\x34\x53\x71\x40\x34\x0c\x9c\x01\x36\x00\x00\x00\x00\x2e\xb7\x84\x30\xf8\x0d\x07\xb4\xf8\x0d\x07\xb4\x6e\xeb\x65\x34\x6e\xeb\x65\x34\xe2\x0a\xb2\xb5\x00\x00\x00\x00\xda\xfc\xda\x30\x7e\x77\xf9\xb3\x7e\x77\xf9\xb3\x82\x3c\xe3\x33\x82\x3c\xe3\x33\xff\x8c\x11\x34\x00\x00\x00\x00\x95\xa8\xaf\x30\xcd\xa3\xb9\xb3\xcd\xa3\xb9\xb3\x67\x6d\xfb\x32\x67\x6d\xfb\x32\x35\x9b\x8f\x35\x00\x00\x00\x00\x5a\x5f\x48\xae\x19\xf8\x64\xb3\x19\xf8\x64\xb3\xc6\xa8\xef\x32\xc6\xa8\xef\x32\x8d\x4b\xf0\xb5\x00\x00\x00\x00\x79\xb6\xe8\xb0\xa6\x87\x1d\xb3\xa6\x87\x1d\xb3\xdc\x6a\x04\x34\xdc\x6a\x04\x34\xa1\xfc\xed\x35\x00\x00\x00\x00\x98\x13\x32\xb1\xa0\x30\x33\xb3\xa0\x30\x33\xb3\x01\xcd\x31\x34\x01\xcd\x31\x34\x0e\x19\x85\xb5\x00\x00\x00\x00\x33\xad\x0a\xb1\x03\x94\x65\xb3\x03\x94\x65\xb3\x6a\x78\xdc\x33\x6a\x78\xdc\x33\x9c\x73\x7e\xb4\x00\x00\x00\x00\x5b\x9f\x53\xaf\x5b\x54\x59\xb3\x5b\x54\x59\xb3\x0a\xd1\x3a\x33\x0a\xd1\x3a\x33\x01\x03\xb0\x35\x00\x00\x00\x00\xab\x40\xf6\x30\x5f\x47\xe6\xb2\x5f\x47\xe6\xb2\xf8\xba\x9c\x31\xf8\xba\x9c\x31\xd5\x35\xed\xb5\x00\x00\x00\x00\x21\xa5\x3c\x31\x98\xf6\xac\x30\x98\xf6\xac\x30\x57\x74\xb2\xb2\x57\x74\xb2\xb2\xf7\xb7\xca\x35\x00\x00\x00\x00\xb6\x5f\x21\x31\xa0\x08\x06\x32\xa0\x08\x06\x32\x21\x13\x91\x32\x21\x13\x91\x32\x37\x4f\x33\xb5\x00\x00\x00\x00\x67\x10\xd3\x30\x67\xb6\x9c\xb2\x67\xb6\x9c\xb2\x2f\x79\x7d\x33\x2f\x79\x7d\x33\xe5\x29\x04\xb5\x00\x00\x00\x00\xd1\x2d\x01\x31\x06\xe3\x82\xb3\x06\xe3\x82\xb3\xa3\x51\x8b\x33\xa3\x51\x8b\x33\x83\x7a\xc5\x35\x00\x00\x00\x00\x97\x43\x94\x31\x37\xa1\xba\xb3\x37\xa1\xba\xb3\x0a\x72\x82\xb3\x0a\x72\x82\xb3\x61\x95\xe7\xb5\x00\x00\x00\x00\x2f\x01\x0c\x32\xb4\xe4\x8e\xb3\xb4\xe4\x8e\xb3\xf3\xa6\x11\xb4\xf3\xa6\x11\xb4\x7a\xe0\x9b\x35\x00\x00\x00\x00\x5e\x14\x41\x32\x80\x7b\x3f\x32\x80\x7b\x3f\x32\xd3\xf2\xb4\xb3\xd3\xf2\xb4\xb3\x20\xd5\x53\xb4\x00\x00\x00\x00\xe6\x1d\x7a\x32\xbd\x89\xde\x33\xbd\x89\xde\x33\x86\xb7\x50\xb2\x86\xb7\x50\xb2\xe6\xf7\x40\xb5\x00\x00\x00\x00\x28\x02\x1e\x32\x79\xe5\x87\x34\x79\xe5\x87\x34\x96\x69\xc7\xb1\x96\x69\xc7\xb1\x76\x13\xb0\x35\x00\x00\x00\x00\x30\x20\x38\x31\x28\xf4\xd8\x34\x28\xf4\xd8\x34\x5a\xb3\xae\xb3\x5a\xb3\xae\xb3\x03\x51\xb8\xb5\x00\x00\x00\x00\x9a\xa5\x45\xb0\x87\x7b\x0f\x35\x87\x7b\x0f\x35\x33\xa5\xf8\xb3\x33\xa5\xf8\xb3\xac\x51\x6a\x35\x00\x00\x00\x00\x46\x7a\x57\x30\x17\xf2\x27\x35\x17\xf2\x27\x35\xc9\x4e\x2b\xb4\xc9\x4e\x2b\xb4\xa4\xa2\x5f\xb3\x00\x00\x00\x00\x36\x09\xb0\x31\xcb\x09\x35\x35\xcb\x09\x35\x35\xee\xa9\xb5\xb3\xee\xa9\xb5\xb3\x9a\xbd\x44\xb5\x00\x00\x00\x00\x24\xd0\x16\x32\xac\x22\x3d\x35\xac\x22\x3d\x35\x9e\xd0\x78\xb3\x9e\xd0\x78\xb3\xc5\x06\x9d\x35\x00\x00\x00\x00\x0d\x57\x1e\x32\x4f\xe1\x49\x35\x4f\xe1\x49\x35\x7e\x74\x97\xb3\x7e\x74\x97\xb3\x7d\x3d\x95\xb5\x00\x00\x00\x00\x08\x5c\xcb\x31\x26\xcb\x5f\x35\x26\xcb\x5f\x35\x8e\xa2\x99\xb3\x8e\xa2\x99\xb3\x27\xbb\x27\x35\x00\x00\x00\x00\xce\x26\x08\x30\x0e\xbd\x79\x35\x0e\xbd\x79\x35\x65\x49\x99\xb3\x65\x49\x99\xb3\x04\xa2\x96\x33\x00\x00\x00\x00\xac\x04\x7a\xb1\x19\xbd\x86\x35\x19\xbd\x86\x35\xa7\x93\x9d\xb3\xa7\x93\x9d\xb3\x96\x59\x32\xb5\x00\x00\x00\x00\xe5\x98\x53\xb1\xf7\xd1\x8a\x35\xf7\xd1\x8a\x35\x3d\xd2\x3f\xb2\x3d\xd2\x3f\xb2\x25\xca\x77\x35\x00\x00\x00\x00\x7d\x8c\x1f\x31\xe4\xaf\x8b\x35\xe4\xaf\x8b\x35\x9d\xde\x4d\x33\x9d\xde\x4d\x33\x85\x88\x5b\xb5\x00\x00\x00\x00\xe2\x17\x08\x32\xea\xcd\x8e\x35\xea\xcd\x8e\x35\xd3\xe4\x79\x33\xd3\xe4\x79\x33\xec\x1f\xf1\x34\x00\x00\x00\x00\x34\x3b\x00\x32\xd6\x31\x97\x35\xd6\x31\x97\x35\x58\x41\xa4\x32\x58\x41\xa4\x32\x7c\x61\xdd\x32\x00\x00\x00\x00\x24\xc5\x8d\xb0\x7e\x87\xa2\x35\x7e\x87\xa2\x35\x90\x2d\x65\x33\x90\x2d\x65\x33\x17\xd9\xec\xb4\x00\x00\x00\x00\x87\x3c\x5a\xb2\x84\x8a\xab\x35\x84\x8a\xab\x35\x40\x30\x14\x34\x40\x30\x14\x34\x27\x79\x37\x35\x00\x00\x00\x00\x3f\x23\xa9\xb2\x1f\x1e\xaf\x35\x1f\x1e\xaf\x35\x4f\xed\x51\x34\x4f\xed\x51\x34\x34\x64\x32\xb5\x00\x00\x00\x00\x9f\x5f\x96\xb2\x59\xd4\xae\x35\x59\xd4\xae\x35\x6c\xa9\x63\x34\x6c\xa9\x63\x34\xf8\x8a\xda\x34\x00\x00\x00\x00\x80\x4c\x05\xb2\xe6\xac\xae\x35\xe6\xac\xae\x35\xb7\xba\x65\x34\xb7\xba\x65\x34\x2d\x88\x9c\xb3\x00\x00\x00\x00\x11\x49\x8c\x31\x21\xe7\xb0\x35\x21\xe7\xb0\x35\xb6\xa1\x8a\x34\xb6\xa1\x8a\x34\x58\xea\x85\xb4\x00\x00\x00\x00\x8a\x0b\x53\x32\x11\x4c\xb4\x35\x11\x4c\xb4\x35\x8d\x01\xa8\x34\x8d\x01\xa8\x34\x0d\x1c\x06\x35\x00\x00\x00\x00\x7b\x89\x63\x32\xfc\x12\xb6\x35\xfc\x12\xb6\x35\x40\xe7\xcb\x34\x40\xe7\xcb\x34\x76\xb9\x12\xb5\x00\x00\x00\x00\x64\x7e\x01\x32\xbd\x9d\xb4\x35\xbd\x9d\xb4\x35\xba\xcc\xed\x34\xba\xcc\xed\x34\xb0\x8e\xda\x34\x00\x00\x00\x00\x33\x75\xba\x30\x9b\x22\xb0\x35\x9b\x22\xb0\x35\x5d\xff\xfe\x34\x5d\xff\xfe\x34\x03\x37\x4c\xb4\x00\x00\x00\x00\x70\xfe\x7e\x31\x57\x72\xa9\x35\x57\x72\xa9\x35\x04\x12\x03\x35\x04\x12\x03\x35\xef\x0c\xaf\xb3\x00\x00\x00\x00\xae\x18\x9d\x32\x75\x25\xa1\x35\x75\x25\xa1\x35\x85\x06\x07\x35\x85\x06\x07\x35\xaf\x82\xab\x34\x00\x00\x00\x00\x5d\xa8\x1f\x33\xf2\x29\x98\x35\xf2\x29\x98\x35\x34\xa8\x22\x35\x34\xa8\x22\x35\xd5\x03\xe1\xb4\x00\x00\x00\x00\x36\xd6\x43\x33\x16\x31\x90\x35\x16\x31\x90\x35\x93\x91\x3f\x35\x93\x91\x3f\x35\xe5\xf1\xe0\x34\x00\x00\x00\x00\x94\xea\x19\x33\x1c\x86\x8a\x35\x1c\x86\x8a\x35\xfb\x76\x40\x35\xfb\x76\x40\x35\x75\x52\xb7\xb4\x00\x00\x00\x00\x5d\x59\x89\x32\x00\x68\x86\x35\x00\x68\x86\x35\xee\x3a\x3d\x35\xee\x3a\x3d\x35\x57\xfb\x1e\x34\x00\x00\x00\x00\xd9\xbe\x4e\x31\x8b\x60\x81\x35\x8b\x60\x81\x35\x5f\xf9\x4b\x35\x5f\xf9\x4b\x35\xd5\xfa\x00\x34\x00\x00\x00\x00\x03\xdb\xef\x31\xe4\xcb\x73\x35\xe4\xcb\x73\x35\xa6\x4f\x6b\x35\xa6\x4f\x6b\x35\x5f\xdc\xbb\xb4\x00\x00\x00\x00\x39\x15\xca\x32\x07\xb9\x62\x35\x07\xb9\x62\x35\x00\x11\x84\x35\x00\x11\x84\x35\xe9\xda\xfd\x34\x00\x00\x00\x00\x12\x30\x2e\x33\x97\x7a\x55\x35\x97\x7a\x55\x35\x13\x35\x82\x35\x13\x35\x82\x35\x8a\xae\x06\xb5\x00\x00\x00\x00\xea\x20\x52\x33\x56\x2c\x4e\x35\x56\x2c\x4e\x35\x19\x75\x81\x35\x19\x75\x81\x35\xfa\xf9\xd4\x34\x00\x00\x00\x00\x64\xdc\x43\x33\xb0\x12\x48\x35\xb0\x12\x48\x35\x14\xf5\x8d\x35\x14\xf5\x8d\x35\x23\x65\xde\xb3\x00\x00\x00\x00\x90\x76\x07\x33\x8f\xb1\x3c\x35\x8f\xb1\x3c\x35\x30\xd4\x99\x35\x30\xd4\x99\x35\xba\x55\x8a\xb4\x00\x00\x00\x00\x3d\xe6\x52\x32\x10\x1e\x2b\x35\x10\x1e\x2b\x35\xe2\x1d\xa2\x35\xe2\x1d\xa2\x35\xca\x80\x17\x35\x00\x00\x00\x00\xf5\xb7\x2a\xb0\x44\x73\x18\x35\x44\x73\x18\x35\xf4\xf1\xa6\x35\xf4\xf1\xa6\x35\x85\x50\x4c\xb5\x00\x00\x00\x00\xb5\xb7\x6b\x31\xba\x9f\x08\x35\xba\x9f\x08\x35\xd1\x6b\xa9\x35\xd1\x6b\xa9\x35\xf6\x49\x37\x35\x00\x00\x00\x00\xf9\x10\xb2\x32\x97\x79\xf1\x34\x97\x79\xf1\x34\xad\xa1\xad\x35\xad\xa1\xad\x35\xdc\x41\xa5\xb4\x00\x00\x00\x00\x77\x82\x05\x33\x03\x6e\xc5\x34\x03\x6e\xc5\x34\xcf\x3a\xb1\x35\xcf\x3a\xb1\x35\xd5\xcf\x35\xb4\x00\x00\x00\x00\x13\xcf\x89\x32\x41\x22\x8c\x34\x41\x22\x8c\x34\x2a\xf0\xbc\x35\x2a\xf0\xbc\x35\x92\x42\x33\x35\x00\x00\x00\x00\x52\x27\xa9\xb2\xb1\xd2\x27\x34\xb1\xd2\x27\x34\x7d\x72\xc7\x35\x7d\x72\xc7\x35\x6d\x79\x8d\xb5\x00\x00\x00\x00\xfe\x6b\x56\xb3\x16\xc0\xa2\x33\x16\xc0\xa2\x33\x86\x4c\xca\x35\x86\x4c\xca\x35\xdd\x72\x8d\x35\x00\x00\x00\x00\x30\x77\x60\xb3\x4e\xb2\x09\x31\x4e\xb2\x09\x31\x4c\x31\xc3\x35\x4c\x31\xc3\x35\x69\x94\x27\xb5\x00\x00\x00\x00\x6a\xf9\xf4\xb2\x89\x98\xed\xb3\x89\x98\xed\xb3\x7f\x78\xc4\x35\x7f\x78\xc4\x35\xd8\xb8\xa3\xb3\x00\x00\x00\x00\x1d\x5c\xc1\x30\x21\x59\x97\xb4\x21\x59\x97\xb4\x3e\xa0\xd5\x35\x3e\xa0\xd5\x35\x7e\x16\x66\x35\x00\x00\x00\x00\x45\xaa\xad\x32\xe5\xcc\xfc\xb4\xe5\xcc\xfc\xb4\xf7\x21\xdf\x35\xf7\x21\xdf\x35\x2a\x63\xc3\xb5\x00\x00\x00\x00\xe9\x24\xc4\x32\xf6\x41\x23\xb5\xf6\x41\x23\xb5\x3d\x6f\xda\x35\x3d\x6f\xda\x35\xf6\x31\xd8\x35\x00\x00\x00\x00\x14\x8b\x44\x32\x74\x1a\x33\xb5\x74\x1a\x33\xb5\x61\x0f\xd2\x35\x61\x0f\xd2\x35\x01\xf3\x94\xb5\x00\x00\x00\x00\x91\x95\xf1\xb1\xb2\x7f\x3a\xb5\xb2\x7f\x3a\xb5\xd8\x83\xd8\x35\xd8\x83\xd8\x35\x4b\xca\xfb\xb2\x00\x00\x00\x00\x8f\x38\x93\xb2\xfa\x6f\x4c\xb5\xfa\x6f\x4c\xb5\xb1\xe4\xdd\x35\xb1\xe4\xdd\x35\x95\xa8\xb4\x35\x00\x00\x00\x00\x30\x7f\x1d\xb1\xbd\x5b\x6d\xb5\xbd\x5b\x6d\xb5\xa8\x1e\xe3\x35\xa8\x1e\xe3\x35\x9b\xe2\x16\xb6\x00\x00\x00\x00\xc1\xef\x0e\x33\x99\x00\x87\xb5\x99\x00\x87\xb5\xb0\x29\xeb\x35\xb0\x29\xeb\x35\xfe\x23\x1c\x36\x00\x00\x00\x00\xa5\xec\x78\x33\x36\x29\x8e\xb5\x36\x29\x8e\xb5\x14\xc7\xe8\x35\x14\xc7\xe8\x35\x4c\x76\xbb\xb5\x00\x00\x00\x00\xc5\x0e\x3f\x33\x22\xbe\x8b\xb5\x22\xbe\x8b\xb5\x0d\x5d\xd5\x35\x0d\x5d\xd5\x35\x82\xea\xa8\xb4\x00\x00\x00\x00\xfa\x30\x0d\x32\x37\x4f\x88\xb5\x37\x4f\x88\xb5\x5b\xb4\xe2\x35\x5b\xb4\xe2\x35\xb1\x23\x0f\x36\x00\x00\x00\x00\x6b\xa5\xac\xb1\xaf\x17\x8c\xb5\xaf\x17\x8c\xb5\xca\x1a\xeb\x35\xca\x1a\xeb\x35\x86\x78\x56\xb6\x00\x00\x00\x00\x86\xf9\xb2\x32\xc3\x11\x97\xb5\xc3\x11\x97\xb5\x15\x03\x03\x36\x15\x03\x03\x36\x06\x88\x44\x36\x00\x00\x00\x00\x80\xf8\x32\x33\xc7\x49\xa3\xb5\xc7\x49\xa3\xb5\x09\x1c\x05\x36\x09\x1c\x05\x36\xe9\x1e\xc5\xb5\x00\x00\x00\x00\x30\x8f\xd7\x31\x86\xaf\xad\xb5\x86\xaf\xad\xb5\xab\x61\xef\x35\xab\x61\xef\x35\x9e\x17\x3d\xb5\x00\x00\x00\x00\x57\x94\x8d\xb3\xc1\xd3\xb9\xb5\xc1\xd3\xb9\xb5\x2f\xba\xcc\x35\x2f\xba\xcc\x35\xff\x3b\x56\x36\x00\x00\x00\x00\x88\xc6\x2d\xb4\x3a\x97\xbc\xb5\x3a\x97\xbc\xb5\x56\xcd\xe0\x35\x56\xcd\xe0\x35\xec\x1a\x9c\xb6\x00\x00\x00\x00\x26\x01\xc1\x32\x4d\x56\xd4\xb5\x4d\x56\xd4\xb5\xf1\x02\x06\x36\xf1\x02\x06\x36\x34\x3b\x85\x36\x00\x00\x00\x00\xdc\xec\xc2\x32\xf8\x6a\xd3\xb5\xf8\x6a\xd3\xb5\xb2\x59\x02\x36\xb2\x59\x02\x36\xbb\xa7\xa7\xb5\x00\x00\x00\x00\x1c\x51\x03\x34\x03\x24\xcd\xb5\x03\x24\xcd\xb5\x11\x5a\xee\x35\x11\x5a\xee\x35\xa9\x5d\x0b\xb6\x00\x00\x00\x00\x6a\xc2\x92\x31\xb0\x04\xa9\xb5\xb0\x04\xa9\xb5\x96\x8e\xd6\x35\x96\x8e\xd6\x35\x87\x88\x99\x36\x00\x00\x00\x00\x0e\xad\x6c\xb3\xf1\x49\x9c\xb5\xf1\x49\x9c\xb5\x25\xb9\xd1\x35\x25\xb9\xd1\x35\xc5\x46\xb3\xb6\x00\x00\x00\x00\x4b\x32\x0c\x33\x88\x90\x8b\xb5\x88\x90\x8b\xb5\x48\x57\xd9\x35\x48\x57\xd9\x35\xc1\xff\x80\x36\x00\x00\x00\x00\xd7\x06\x0b\xb3\xbf\xb7\x99\xb5\xbf\xb7\x99\xb5\x9f\xe4\xec\x35\x9f\xe4\xec\x35\x36\x03\xa4\xb4\x00\x00\x00\x00\x26\xe8\x32\x34\x22\x66\x9b\xb5\x22\x66\x9b\xb5\xad\x51\x00\x36\xad\x51\x00\x36\x72\x9b\x7b\xb6\x00\x00\x00\x00\x18\x04\x35\xb4\x96\x7c\x97\xb5\x96\x7c\x97\xb5\xaf\x17\xe5\x35\xaf\x17\xe5\x35\xf4\x46\xd2\x36\x00\x00\x00\x00\x30\xb3\x90\x33\xe9\x1e\x8a\xb5\xe9\x1e\x8a\xb5\xda\x12\xac\x35\xda\x12\xac\x35\x64\x00\xce\xb6\x00\x00\x00\x00\x69\x4f\x7f\xb4\x31\x83\x70\xb5\x31\x83\x70\xb5\x0c\xc9\xa2\x35\x0c\xc9\xa2\x35\x4e\xaa\x63\x36\x00\x00\x00\x00\x41\x71\x45\x34\xfb\x17\x89\xb5\xfb\x17\x89\xb5\x5d\x70\xbc\x35\x5d\x70\xbc\x35\xcf\x61\x9b\x35\x00\x00\x00\x00\x0f\xed\x6e\xb3\xb0\xf0\x8f\xb5\xb0\xf0\x8f\xb5\xe3\x03\xe9\x35\xe3\x03\xe9\x35\x7f\x91\xbd\xb6\x00\x00\x00\x00\x31\x08\xee\x33\xf7\xeb\xb0\xb5\xf7\xeb\xb0\xb5\x28\x4d\xd1\x35\x28\x4d\xd1\x35\x3a\xb6\x03\x37\x00\x00\x00\x00\x68\xe6\x90\xb3\xe8\x0a\xa3\xb5\xe8\x0a\xa3\xb5\x2a\xd3\xa3\x35\x2a\xd3\xa3\x35\x3b\x45\xdf\xb6\x00\x00\x00\x00\xd8\xb0\xbf\xb3\x8a\x40\xa0\xb5\x8a\x40\xa0\xb5\x1b\x4b\x62\x35\x1b\x4b\x62\x35\x15\x7c\x2a\x36\x00\x00\x00\x00\x75\x0b\x2b\x34\x6f\x2b\x78\xb5\x6f\x2b\x78\xb5\xc8\x9f\x71\x35\xc8\x9f\x71\x35\x00\x19\x36\x36\x00\x00\x00\x00\xcf\x2a\x3c\xb4\x2e\xf5\x5c\xb5\x2e\xf5\x5c\xb5\x6f\x9c\x86\x35\x6f\x9c\x86\x35\xd2\x7a\xe2\xb6\x00\x00\x00\x00\x68\x91\x96\x34\xff\xbe\x4e\xb5\xff\xbe\x4e\xb5\xf6\x59\x9e\x35\xf6\x59\x9e\x35\x8d\x71\x03\x37\x00\x00\x00\x00\x57\x06\xd6\xb4\x45\x9a\x44\xb5\x45\x9a\x44\xb5\x30\x81\x6e\x35\x30\x81\x6e\x35\x15\x0e\xb4\xb6\x00\x00\x00\x00\x10\xe4\xbc\x34\x7f\xb0\x42\xb5\x7f\xb0\x42\xb5\xcb\x9f\x27\x35\xcb\x9f\x27\x35\x42\x2f\x9e\x33\x00\x00\x00\x00\x2a\x2d\xc2\xb4\xc2\xfc\xce\xb4\xc2\xfc\xce\xb4\xcf\x18\x6b\x34\xcf\x18\x6b\x34\xc1\xdb\xbe\x36\x00\x00\x00\x00\x32\xc1\xc8\x34\xb4\x9c\x6c\xb4\xb4\x9c\x6c\xb4\x75\xac\x49\x34\x75\xac\x49\x34\xa4\x1e\x1c\xb7\x00\x00\x00\x00\xd5\x79\x8e\xb4\xb2\x8e\x3b\x34\xb2\x8e\x3b\x34\xb2\xf3\xe4\x34\xb2\xf3\xe4\x34\xf1\x18\x1f\x37\x00\x00\x00\x00\xf4\x97\x0f\x34\xb6\xa2\x60\x34\xb6\xa2\x60\x34\x24\x2e\xd5\x34\x24\x2e\xd5\x34\xfd\x5e\xc8\xb6\x00\x00\x00\x00\x49\xf4\x15\xb3\x4c\x31\xba\x34\x4c\x31\xba\x34\x0e\xc2\xe2\x33\x0e\xc2\xe2\x33\x60\xb0\x95\xb3\x00\x00\x00\x00\xe1\x08\x03\xb4\xcd\x60\x68\x34\xcd\x60\x68\x34\x77\x8d\xb6\xb4\x77\x8d\xb6\xb4\xd1\x45\xbe\x36\x00\x00\x00\x00\x53\x05\xc5\x34\x55\x9c\xdc\x33\x55\x9c\xdc\x33\x55\x53\x2a\xb5\x55\x53\x2a\xb5\xae\xa7\x0a\xb7\x00\x00\x00\x00\x94\x2d\xef\xb4\xac\xed\x1c\x34\xac\xed\x1c\x34\x91\xd0\xf8\xb4\x91\xd0\xf8\xb4\xe4\x52\xea\x36\x00\x00\x00\x00\x8c\xc7\x21\x35\x51\x82\x0b\x34\x51\x82\x0b\x34\x23\x45\xbf\xb4\x23\x45\xbf\xb4\xe8\x5d\x03\xb6\x00\x00\x00\x00\xe7\x30\x43\xb5\xce\x98\xcd\x34\xce\x98\xcd\x34\x22\x63\x01\xb5\x22\x63\x01\xb5\xc8\x2d\xa3\xb6\x00\x00\x00\x00\xd3\xef\x4b\x35\x69\x12\x84\x34\x69\x12\x84\x34\x0c\x4b\x65\xb5\x0c\x4b\x65\xb5\x6f\x78\x28\x37\x00\x00\x00\x00\xb8\xea\x44\xb5\x32\x4c\xf9\x34\x32\x4c\xf9\x34\x93\x32\xae\xb5\x93\x32\xae\xb5\x94\xeb\x40\xb7\x00\x00\x00\x00\xef\x59\x24\x35\x83\x8f\xe9\x34\x83\x8f\xe9\x34\x38\xae\xa8\xb5\x38\xae\xa8\xb5\x03\xff\x15\x37\x00\x00\x00\x00\x90\x95\x00\xb5\x9d\x79\x38\x35\x9d\x79\x38\x35\xdc\x20\x8b\xb5\xdc\x20\x8b\xb5\xbd\x4b\x51\xb6\x00\x00\x00\x00\x32\xa2\x8a\x34\xc6\x77\x79\x35\xc6\x77\x79\x35\xe0\x14\x83\xb5\xe0\x14\x83\xb5\x53\x05\x61\xb6\x00\x00\x00\x00\x4e\x2b\x5c\x31\xa8\x97\x9a\x35\xa8\x97\x9a\x35\x5e\xaf\x9d\xb5\x5e\xaf\x9d\xb5\x52\x70\xf5\x36\x00\x00\x00\x00\x53\x60\xdb\xb4\xac\x46\xd5\x35\xac\x46\xd5\x35\x01\x34\xdf\xb5\x01\x34\xdf\xb5\x90\xd5\xf8\xb6\x00\x00\x00\x00\x4e\x66\x2a\x35\xc4\x0d\xa8\x35\xc4\x0d\xa8\x35\x5c\x04\xf8\xb5\x5c\x04\xf8\xb5\xea\x58\x7a\x36\x00\x00\x00\x00\x22\x09\x60\xb5\x69\xa7\xae\x35\x69\xa7\xae\x35\x1d\x2a\xd8\xb5\x1d\x2a\xd8\xb5\xf3\x37\x28\x36\x00\x00\x00\x00\x00\x90\xa1\x35\xef\x69\x31\x35\xef\x69\x31\x35\x37\x3c\xc8\xb5\x37\x3c\xc8\xb5\x17\xc5\x0d\xb7\x00\x00\x00\x00\xcc\x20\xb8\xb5\xe2\xeb\x81\x35\xe2\xeb\x81\x35\x7d\x05\xb3\xb5\x7d\x05\xb3\xb5\x19\xe8\x3e\x37\x00\x00\x00\x00\x59\x4e\xa4\x35\xae\x59\x4c\x35\xae\x59\x4c\x35\x94\x52\xe2\xb5\x94\x52\xe2\xb5\x0c\xd5\x2c\xb7\x00\x00\x00\x00\x69\x81\xa4\xb5\x57\x12\x80\x35\x57\x12\x80\x35\x27\x3b\x02\xb6\x27\x3b\x02\xb6\x94\x81\xbe\x36\x00\x00\x00\x00\xff\x40\x9e\x35\xdb\xe6\x83\x35\xdb\xe6\x83\x35\xc9\x40\x11\xb6\xc9\x40\x11\xb6\x2e\xbe\x36\x35\x00\x00\x00\x00\xbd\x00\x35\xb5\x09\x3e\x31\x35\x09\x3e\x31\x35\x2a\x99\xf3\xb5\x2a\x99\xf3\xb5\x32\x42\xca\xb6\x00\x00\x00\x00\x1d\x4c\x74\x34\x4e\x7c\x85\x35\x4e\x7c\x85\x35\xa2\x85\xc5\xb5\xa2\x85\xc5\xb5\xfa\xd5\x07\x37\x00\x00\x00\x00\xbf\xe1\xc2\x32\x16\x91\x8a\x34\x16\x91\x8a\x34\x49\x65\xb5\xb5\x49\x65\xb5\xb5\x4a\x0c\xcb\xb6\x00\x00\x00\x00\xb6\x43\x32\xb5\x39\x43\xad\x35\x39\x43\xad\x35\x85\x1d\xf4\xb5\x85\x1d\xf4\xb5\x7d\xab\x83\x35\x00\x00\x00\x00\x06\xb1\xb2\x35\x6d\xd1\x3d\x35\x6d\xd1\x3d\x35\xe0\xee\x0d\xb6\xe0\xee\x0d\xb6\xd9\xf4\x95\x36\x00\x00\x00\x00\xd1\xf0\xc5\xb5\x12\xaf\x03\x36\x12\xaf\x03\x36\x24\xfa\x0a\xb6\x24\xfa\x0a\xb6\xa5\x97\x04\xb7\x00\x00\x00\x00\xb5\x55\xe9\x35\xe2\xaf\xb0\x35\xe2\xaf\xb0\x35\x0b\x76\xcb\xb5\x0b\x76\xcb\xb5\xa5\x73\x08\x37\x00\x00\x00\x00\x77\x78\x20\xb6\xed\xe3\x02\x36\xed\xe3\x02\x36\xc3\x5f\xa5\xb5\xc3\x5f\xa5\xb5\x95\x27\xa4\xb6\x00\x00\x00\x00\x6f\xf9\x0a\x36\x1f\x91\xd3\x35\x1f\x91\xd3\x35\xc5\x41\xc0\xb5\xc5\x41\xc0\xb5\x8c\x9d\x30\xb5\x00\x00\x00\x00\xd9\x5e\xd6\xb5\xd3\x75\x9e\x35\xd3\x75\x9e\x35\xac\xb8\xd9\xb5\xac\xb8\xd9\xb5\x4c\xa9\xc7\x36\x00\x00\x00\x00\xf3\x63\xe3\x35\xa8\xa0\xfd\x35\xa8\xa0\xfd\x35\x40\x08\xde\xb5\x40\x08\xde\xb5\x2b\x1d\x14\xb7\x00\x00\x00\x00\x31\xb3\xad\xb5\x37\xb6\x8f\x35\x37\xb6\x8f\x35\x80\xb6\xc5\xb5\x80\xb6\xc5\xb5\x74\xcb\x12\x37\x00\x00\x00\x00\xb3\x3b\x82\x33\x13\xaa\x43\x36\x13\xaa\x43\x36\x03\x41\x9b\xb5\x03\x41\x9b\xb5\x88\x56\xd4\xb6\x00\x00\x00\x00\x62\x96\x12\x35\x6e\x71\xfd\x34\x6e\x71\xfd\x34\xac\x2a\x66\xb5\xac\x2a\x66\xb5\x97\xd3\x34\x36\x00\x00\x00\x00\xea\xbe\x36\xb5\x95\x62\xe1\x35\x95\x62\xe1\x35\xaa\xe8\x50\xb5\xaa\xe8\x50\xb5\x7b\x26\xeb\x34\x00\x00\x00\x00\x6f\xd1\xfb\x35\xd0\xc2\x8f\xb5\xd0\xc2\x8f\xb5\x31\x9f\x9d\xb5\x31\x9f\x9d\xb5\x3c\x04\x99\xb5\x00\x00\x00\x00\x27\x88\x3b\xb6\x3f\x75\xa0\x35\x3f\x75\xa0\x35\x4a\x88\x9d\xb5\x4a\x88\x9d\xb5\xf6\xcf\x7d\xb5\x00\x00\x00\x00\x42\xcd\x0f\x36\x33\x57\xa1\x35\x33\x57\xa1\x35\x8a\xd0\xdb\xb4\x8a\xd0\xdb\xb4\x7e\xc9\x9c\x36\x52\x49\x52\x35\x50\xfc\x68\xb6\xa1\xdc\x79\x36\xa1\xdc\x79\x36\x3c\x07\x25\x31\x3c\x07\x25\x31\x63\x34\x05\xb7\xfe\xb6\x1d\x36\xc8\xc6\x38\x36\x2b\x83\xd5\x36\x2b\x83\xd5\x36\x74\x07\xe9\x33\x74\x07\xe9\x33\x69\xae\x38\x37\xcc\xe3\x2d\x36\xe9\xa9\x2c\xb6\x51\xee\xff\x36\x51\xee\xff\x36\x4d\x4d\x9b\x33\x4d\x4d\x9b\x33\x63\xc4\x5b\xb7\x7e\x31\xca\x35\x13\x65\x1d\x36\x72\x42\x47\x37\x72\x42\x47\x37\x75\x28\xbc\x34\x75\x28\xbc\x34\xe1\xec\x60\x37\x28\x62\x86\x35\xf9\x23\xbc\xb5\xe6\xcd\x2b\x37\xe6\xcd\x2b\x37\x41\x2d\x14\x35\x41\x2d\x14\x35\xac\xb9\x4d\xb7\x92\x59\x90\x35\x12\xc2\xd2\x34\xa9\x2b\x80\x37\xa9\x2b\x80\x37\xc8\xea\x98\x35\xc8\xea\x98\x35\xad\xc1\x34\x37\xf1\xcc\x9a\x35\xdc\xa2\x09\x35\xeb\x9c\x4c\x37\xeb\x9c\x4c\x37\x4c\x4c\xd0\x35\x4c\x4c\xd0\x35\x6e\x85\x27\xb7\x42\xbc\xa5\x35\x0f\x10\x7e\xb5\x31\xd2\x95\x37\x31\xd2\x95\x37\x07\xe7\x05\x36\x07\xe7\x05\x36\xf2\xe0\x29\x37\xd4\x2e\xb1\x35\x73\x77\x20\x36\xab\xc6\x80\x37\xab\xc6\x80\x37\x62\x5d\x1d\x36\x62\x5d\x1d\x36\xa5\xa9\x37\xb7\xa8\x24\xbd\x35\x64\x1f\x49\xb6\x09\x6f\xa7\x37\x09\x6f\xa7\x37\xf3\x85\x36\x36\xf3\x85\x36\x36\x4a\x9e\x51\x37\x3a\x9d\xc9\x35\xe8\x4e\x50\x36\xab\x06\xa3\x37\xab\x06\xa3\x37\xcb\x78\x57\x36\xcb\x78\x57\x36\x62\x74\x72\xb7\x8a\x98\xd6\x35\xed\x7d\x5b\xb6\x94\x2a\xb0\x37\x94\x2a\xb0\x37\x0d\x1d\x88\x36\x0d\x1d\x88\x36\x81\x23\x87\x37\x3b\x25\xe4\x35\x17\x70\x62\x36\x81\x28\xc2\x37\x81\x28\xc2\x37\x0f\x96\x9b\x36\x0f\x96\x9b\x36\x17\xf0\x91\xb7\x4c\x43\xf2\x35\x63\x62\x3d\xb6\x1f\x29\xad\x37\x1f\x29\xad\x37\x8e\xa9\xa0\x36\x8e\xa9\xa0\x36\x22\xaa\x9a\x37\x1c\x7f\x00\x36\x66\x51\x13\x36\x4a\x3a\xdd\x37\x4a\x3a\xdd\x37\x89\x11\xb1\x36\x89\x11\xb1\x36\xbf\x19\x9f\xb7\x00\x2b\x08\x36\x44\xd9\xa0\xb5\xbd\xb6\xb4\x37\xbd\xb6\xb4\x37\x7e\xd0\xca\x36\x7e\xd0\xca\x36\xb2\xf5\x9c\x37\x44\x31\x10\x36\x77\x22\xe5\x34\x45\xf8\xfa\x37\x45\xf8\xfa\x37\x87\x5f\xe2\x36\x87\x5f\xe2\x36\x4a\x6c\x93\xb7\xe8\x91\x18\x36\x3d\x56\x6b\xb4\xec\x95\xc1\x37\xec\x95\xc1\x37\x5a\x33\xf3\x36\x5a\x33\xf3\x36\x3d\xc1\x85\x37\x27\x4f\x21\x36\xd2\x12\xae\xb5\x08\x2c\xfe\x37\x08\x2c\xfe\x37\xba\x03\xfd\x36\xba\x03\xfd\x36\x64\x80\x72\xb7\x01\x69\x2a\x36\x69\xb8\x97\x35\x98\x53\xcd\x37\x98\x53\xcd\x37\xa6\x32\x09\x37\xa6\x32\x09\x37\x2e\xbe\x5f\x37\x60\xdf\x33\x36\xdd\x87\x8d\xb5\xe6\x2e\xf2\x37\xe6\x2e\xf2\x37\xd5\x16\x17\x37\xd5\x16\x17\x37\x90\x81\x59\xb7\x43\xb2\x3d\x36\xb0\x66\xa5\x35\xf5\x05\xe5\x37\xf5\x05\xe5\x37\xbd\x33\x1e\x37\xbd\x33\x1e\x37\x28\x08\x67\x37\xc0\xdd\x47\x36\xe4\xfb\x9c\xb4\x8a\xfe\xdd\x37\x8a\xfe\xdd\x37\x59\xb6\x28\x37\x59\xb6\x28\x37\x41\xcf\x7f\xb7\xd5\x61\x52\x36\xbb\xba\x4f\xb4\x41\x93\xff\x37\x41\x93\xff\x37\x3f\x23\x33\x37\x3f\x23\x33\x37\x39\x0c\x8a\x37\x98\x54\x5d\x36\x15\x8a\x8e\x35\x4a\x13\xc2\x37\x4a\x13\xc2\x37\x5c\x20\x3c\x37\x5c\x20\x3c\x37\xf7\x9f\x8c\xb7\x0a\xb6\x68\x36\x54\xf5\x01\xb6\xe9\xc1\x04\x38\xe9\xc1\x04\x38\xcc\xa9\x41\x37\xcc\xa9\x41\x37\x10\x3f\x83\x37\x14\x9f\x74\x36\x4c\x6d\x54\x36\x63\x31\xa8\x37\x63\x31\xa8\x37\x80\x31\x4e\x37\x80\x31\x4e\x37\x0c\xaa\x57\xb7\xdc\x87\x80\x36\x80\x0c\x3d\xb6\xdc\x69\x03\x38\xdc\x69\x03\x38\x6a\x68\x60\x37\x6a\x68\x60\x37\x4d\x72\x13\x37\xd7\xe8\x86\x36\xf6\x44\x9a\x36\x5a\x59\x9e\x37\x5a\x59\x9e\x37\x76\x4a\x6a\x37\x76\x4a\x6a\x37\x92\xe9\x91\xb6\x7c\x72\x8d\x36\x56\xf3\x85\xb6\xdc\x9a\xe7\x37\xdc\x9a\xe7\x37\xde\xa0\x6a\x37\xde\xa0\x6a\x37\x1f\xc6\x01\x35\xc2\x44\x94\x36\x60\x8a\xaa\x36\x5e\x89\xa1\x37\x5e\x89\xa1\x37\x2e\x32\x71\x37\x2e\x32\x71\x37\xb7\xd7\xfe\x35\xab\x5f\x9b\x36\x8f\x85\xa6\xb6\x22\xe0\xbe\x37\x22\xe0\xbe\x37\x74\xe8\x82\x37\x74\xe8\x82\x37\x8a\x3a\x12\xb6\x18\xb8\xa2\x36\x87\x53\xc1\x36\x60\xae\xb7\x37\x60\xae\xb7\x37\xd2\x91\x8d\x37\xd2\x91\x8d\x37\xca\x0b\x8f\x35\x0a\x4e\xaa\x36\xeb\xc4\xcf\xb6\x95\x7e\x82\x37\x95\x7e\x82\x37\x96\x26\x94\x37\x96\x26\x94\x37\xe8\xa3\x16\x34\x1b\x29\xb2\x36\xb3\xea\x01\x37\x43\xd3\xbf\x37\x43\xd3\xbf\x37\x5c\x99\x93\x37\x5c\x99\x93\x37\xc5\x08\x57\xb5\x4a\x49\xba\x36\xa7\x2a\xf7\xb6\x04\xd1\x1a\x37\x04\xd1\x1a\x37\xf8\x6a\x98\x37\xf8\x6a\x98\x37\x7e\x83\xe3\xb4\x55\xb2\xc2\x36\x1f\x6e\x2d\x37\x3b\x9c\xc6\x37\x3b\x9c\xc6\x37\x65\xb6\xa4\x37\x65\xb6\xa4\x37\x1b\xfd\xa1\x36\x3b\x64\xcb\x36\x6c\xdc\x2b\xb7\x61\x63\xa5\x36\x61\x63\xa5\x36\xa6\x84\xad\x37\xa6\x84\xad\x37\x1c\xfb\x3c\xb7\xac\x60\xd4\x36\x5a\xbb\x3f\x37\x6d\x7b\xaf\x37\x6d\x7b\xaf\x37\x25\x5e\xb6\x37\x25\x5e\xb6\x37\x89\x2f\x99\x37\xa9\xa7\xdd\x36\x3b\x55\x4c\xb7\xc6\x1e\x78\x36\xc6\x1e\x78\x36\x2b\xd9\xbc\x37\x2b\xd9\xbc\x37\xfd\x31\xd0\xb7\x24\x3e\xe7\x36\xd2\x6b\x54\x37\xa9\xb8\x7d\x37\xa9\xb8\x7d\x37\xa4\xab\xc2\x37\xa4\xab\xc2\x37\xc9\xe2\xee\x37\x1c\x24\xf1\x36\xaa\xb3\x40\xb7\xff\x50\x8c\x36\xff\x50\x8c\x36\x14\x4e\xc8\x37\x14\x4e\xc8\x37\x34\x8a\xeb\xb7\x3b\x5d\xfb\x36\x13\xc4\x38\x37\xf4\x85\xc7\x36\xf4\x85\xc7\x36\x8a\xdc\xd1\x37\x8a\xdc\xd1\x37\xea\xe7\xd3\x37\xbf\xf4\x02\x37\x04\x8c\x17\xb7\x60\x49\xdd\x36\x60\x49\xdd\x36\x54\xa3\xdf\x37\x54\xa3\xdf\x37\x0f\x1b\xb3\xb7\x7d\x67\x08\x37\x27\xa2\xe8\x36\x97\x29\x77\xb6\x97\x29\x77\xb6\x74\x21\xea\x37\x74\x21\xea\x37\xdf\xeb\x96\x37\xd8\x06\x0e\x37\x7f\xcc\xa7\xb6\xb7\xbd\x0d\x37\xb7\xbd\x0d\x37\x8f\x41\xf0\x37\x8f\x41\xf0\x37\xcc\x50\x97\xb7\x6c\xd3\x13\x37\x4b\xac\x3f\x35\xca\x25\x40\xb7\xca\x25\x40\xb7\x67\xee\xf2\x37\x67\xee\xf2\x37\x15\x9c\xbd\x37\x3c\xcd\x19\x37\xe9\x8d\x8a\x35\xfc\x76\x12\x37\xfc\x76\x12\x37\x27\x0e\xfc\x37\x27\x0e\xfc\x37\x64\x29\x00\xb8\x28\xf6\x1f\x37\x20\xcf\x83\xb6\x6c\x48\x8c\xb7\x6c\x48\x8c\xb7\x37\xed\x06\x38\x37\xed\x06\x38\xd8\xe5\x26\x38\x30\x4e\x26\x37\xbf\x85\xeb\x36\xc5\xc6\x22\x36\xc5\xc6\x22\x36\xed\xc3\x0b\x38\xed\xc3\x0b\x38\xf6\x8f\x46\xb8\x34\xd8\x2c\x37\x8e\x81\x1a\xb7\x49\x74\xa0\xb7\x49\x74\xa0\xb7\xba\xff\x0d\x38\xba\xff\x0d\x38\xc2\x46\x53\x38\x30\x94\x33\x37\x4f\xcb\x3c\x37\xce\xf3\xb4\xb6\xce\xf3\xb4\xb6\x15\x25\x10\x38\x15\x25\x10\x38\xd3\x85\x45\xb8\xf6\x85\x3a\x37\x22\x42\x47\xb7\x8c\x25\x77\xb7\x8c\x25\x77\xb7\xee\x69\x15\x38\xee\x69\x15\x38\x0e\x71\x1e\x38\x86\xad\x41\x37\xe9\xa5\x4f\x37\x88\x6a\x7a\xb7\x88\x6a\x7a\xb7\xad\x30\x1a\x38\xad\x30\x1a\x38\xb6\x64\xda\xb7\xea\x08\x49\x37\x03\x81\x58\xb7\x95\xfa\x3b\xb7\x95\xfa\x3b\xb7\x51\x08\x1f\x38\x51\x08\x1f\x38\x31\x06\x90\x37\x22\x98\x50\x37\x1e\x2a\x43\x37\x13\xfe\xd4\xb7\x13\xfe\xd4\xb7\xba\x3e\x24\x38\xba\x3e\x24\x38\x41\xe5\x7e\xb7\x16\x62\x58\x37\x0d\x27\x05\xb7\x7b\x4d\x24\xb7\x7b\x4d\x24\xb7\xf0\xc6\x25\x38\xf0\xc6\x25\x38\x48\xb1\xb2\x37\xc2\x66\x60\x37\xcc\x41\xd3\x36\xf1\x4e\x07\xb8\xf1\x4e\x07\xb8\xb1\xe5\x23\x38\xb1\xe5\x23\x38\xf8\x32\x0b\xb8\x26\xa5\x68\x37\x7a\x4c\x21\xb6\x15\xa3\x1e\xb7\x15\xa3\x1e\xb7\x46\xb2\x29\x38\x46\xb2\x29\x38\x90\x11\x40\x38\x3f\x1d\x71\x37\x88\x01\x07\xb6\x56\x99\x04\xb8\x56\x99\x04\xb8\x2b\x8c\x2e\x38\x2b\x8c\x2e\x38\xe3\x90\x5e\xb8\xba\xd3\x79\x37\xd5\xb4\xef\x36\xf9\xc0\x6f\xb7\xf9\xc0\x6f\xb7\xe5\x9d\x35\x38\xe5\x9d\x35\x38\x33\xd7\x53\x38\x4b\x64\x81\x37\xda\x46\x3b\xb7\xae\x4e\x04\xb8\xae\x4e\x04\xb8\x48\xa2\x35\x38\x48\xa2\x35\x38\x78\x84\x1f\xb8\xb3\xfe\x85\x37\x19\x9c\x78\x37\x33\x4c\xbe\xb7\x33\x4c\xbe\xb7\xa1\x8c\x30\x38\xa1\x8c\x30\x38\x13\x6c\x9f\x37\x14\xb9\x8a\x37\x7e\x9e\x87\xb7\xa6\xd1\xd8\xb7\xa6\xd1\xd8\xb7\xb2\x57\x2c\x38\xb2\x57\x2c\x38\xe7\x3b\x07\x36\x01\x95\x8f\x37\x56\x1f\xa5\x37\x04\x3a\xe4\xb7\x04\x3a\xe4\xb7\x45\x9b\x30\x38\x45\x9b\x30\x38\x29\x8b\x80\xb7\x7a\x92\x94\x37\xd1\x14\x9d\xb7\xf1\x74\xad\xb7\xf1\x74\xad\xb7\xd1\x50\x38\x38\xd1\x50\x38\x38\x49\xcc\x63\x37\x68\xb2\x99\x37\x8d\x59\x88\x37\x1d\x67\x10\xb8\x1d\x67\x10\xb8\x10\x28\x35\x38\x10\x28\x35\x38\xb4\xfa\xff\x35\xce\xf4\x9e\x37\xb4\x3b\x4e\xb7\x8c\x0d\xae\xb7\x8c\x0d\xae\xb7\x98\x93\x2e\x38\x98\x93\x2e\x38\x78\x7d\xb2\xb7\x7c\x5b\xa4\x37\x50\x1b\x2d\x37\xb9\xeb\x10\xb8\xb9\xeb\x10\xb8\xfb\x25\x27\x38\xfb\x25\x27\x38\x03\x4c\x13\x38\x74\xe6\xa9\x37\x81\x6b\xa2\xb6\xdc\x8d\x81\xb7\xdc\x8d\x81\xb7\x84\x04\x25\x38\x84\x04\x25\x38\x6f\x68\x1e\xb8\xf9\x96\xaf\x37\xa0\xe2\x27\xb6\x01\x10\x04\xb8\x01\x10\x04\xb8\x79\x56\x23\x38\x79\x56\x23\x38\xf4\xa0\xd8\x37\x0b\x6d\xb5\x37\x27\x84\xe3\x36\x48\x68\xaa\xb7\x48\x68\xaa\xb7\x02\x8c\x22\x38\x02\x8c\x22\x38\x68\xe1\xfe\xb4\x33\x6a\xbb\x37\x65\x1b\x16\xb7\x75\xca\xef\xb7\x75\xca\xef\xb7\xd9\x4b\x22\x38\xd9\x4b\x22\x38\xc4\x13\xf4\xb7\x72\x8e\xc1\x37\xf0\xd5\x64\x37\x1c\x08\xb9\xb7\x1c\x08\xb9\xb7\x02\xf0\x17\x38\x02\xf0\x17\x38\x8e\xd1\x51\x38\xb0\xda\xc7\x37\x0d\xe9\x92\xb7\xdb\xd8\xad\xb7\xdb\xd8\xad\xb7\xae\xac\x07\x38\xae\xac\x07\x38\x5d\x5f\x64\xb8\xf0\x4e\xce\x37\x38\x2c\x83\x37\x0d\x2f\xd8\xb7\x0d\x2f\xd8\xb7\x12\x22\x00\x38\x12\x22\x00\x38\x9c\xfe\x2d\x38\x54\xed\xd4\x37\x6f\x05\x7d\xb7\x14\x07\x61\xb7\x14\x07\x61\xb7\x7e\x08\xff\x37\x7e\x08\xff\x37\xbc\xb3\x84\xb7\xdd\xb5\xdb\x37\x4d\x13\x74\x37\xbf\x17\xf7\xb7\xbf\x17\xf7\xb7\x28\x57\x02\x38\x28\x57\x02\x38\x7f\x45\x39\xb7\xda\xa9\xe2\x37\xbc\x7c\x27\xb7\x48\x11\x44\xb7\x48\x11\x44\xb7\x21\xd5\xec\x37\x21\xd5\xec\x37\x95\x84\xcf\x37\x48\xc9\xe9\x37\x48\x95\xa3\x36\x4d\x90\xfd\xb7\x4d\x90\xfd\xb7\x4d\x1f\xcc\x37\x4d\x1f\xcc\x37\xc9\xaf\x90\xb7\x64\x15\xf1\x37\x2e\x96\x07\xb5\x39\xe8\x23\xb7\x39\xe8\x23\xb7\x2a\x5b\xab\x37\x2a\x5b\xab\x37\x57\x48\x21\xb7\x2e\x8e\xf8\x37\x1d\x28\xc4\xb6\x89\xc5\xb9\xb7\x89\xc5\xb9\xb7\x9a\x30\x9f\x37\x9a\x30\x9f\x37\x4a\x00\x3f\x38\xdf\x1a\x00\x38\xd4\x3f\x55\x37\xfd\x77\x52\xb7\xfd\x77\x52\xb7\xca\xf9\x97\x37\xca\xf9\x97\x37\xaa\x5c\x9e\xb8\x0c\x06\x04\x38\xac\xaa\x89\xb7\xfa\xdd\x47\xb7\xfa\xdd\x47\xb7\x18\xb8\x92\x37\x18\xb8\x92\x37\xc3\x36\xb7\x38\x2d\x09\x08\x38\x28\x43\xa4\x37\x02\x46\x8e\xb7\x02\x46\x8e\xb7\x2b\x03\x66\x37\x2b\x03\x66\x37\xc3\x9e\x9f\xb8\x43\x24\x0c\x38\x5b\xea\xc3\xb7\xe1\x7f\x82\xb5\xe1\x7f\x82\xb5\x87\x22\x2c\x37\x87\x22\x2c\x37\x6f\x31\x3e\x38\x3c\x58\x10\x38\x51\x49\xc1\x37\x29\x6e\xa9\xb7\x29\x6e\xa9\xb7\xa0\xe1\xc1\x36\xa0\xe1\xc1\x36\x3e\x4c\x19\xb7\x16\xa5\x14\x38\xb4\x7a\x9f\xb7\x65\x05\xde\x36\x65\x05\xde\x36\x2d\x90\x86\x36\x2d\x90\x86\x36\xc4\x74\x81\xb7\xc1\x0b\x19\x38\xed\x3b\x81\x37\xcc\x42\x5c\xb7\xcc\x42\x5c\xb7\xeb\x28\x86\x36\xeb\x28\x86\x36\x0d\x2e\x9c\x37\x3b\x8c\x1d\x38\x68\x3b\x37\xb7\x35\xbb\x43\x37\x35\xbb\x43\x37\xc1\x03\x13\x36\xc1\x03\x13\x36\xfa\x58\x29\x36\x3d\x27\x22\x38\x21\xba\x6c\x36\x25\x1f\xeb\xb6\x25\x1f\xeb\xb6\x3f\xa6\xf0\xb5\x3f\xa6\xf0\xb5\x9f\xe8\x2e\xb8\xc6\xdc\x26\x38\xca\x22\x70\x36\x51\x0d\xc7\x36\x51\x0d\xc7\x36\xcd\xc8\xda\xb6\xcd\xc8\xda\xb6\xd8\x0e\xa8\x38\xcb\xad\x2b\x38\x4f\x24\x0c\xb7\x18\xcd\xec\x35\x18\xcd\xec\x35\xc6\x14\x22\xb7\xc6\x14\x22\xb7\xcc\x51\xd2\xb8\x4c\x9a\x30\x38\xf5\x71\x43\x37\x43\xec\x8b\x36\x43\xec\x8b\x36\xcd\x79\x26\xb7\xcd\x79\x26\xb7\x83\x85\xc7\x38\x10\xa3\x35\x38\x8c\xc1\x68\xb7\x8e\x47\xe6\x36\x8e\x47\xe6\x36\x7a\x41\x38\xb7\x7a\x41\x38\xb7\xce\x71\x86\xb8\x1a\xc8\x3a\x38\x76\xae\x77\x37\xbb\xe2\x88\x36\xbb\xe2\x88\x36\xb3\x7e\x66\xb7\xb3\x7e\x66\xb7\x2e\x46\x9c\x37\x82\x0a\x40\x38\x2b\x1a\x5d\xb7\xbd\xc8\x57\x37\xbd\xc8\x57\x37\x2f\x93\x95\xb7\x2f\x93\x95\xb7\x71\xcd\x9c\x37\x4b\x6a\x45\x38\xac\xbc\x23\x37\x74\x90\x0d\x37\x74\x90\x0d\x37\x2c\x84\xb8\xb7\x2c\x84\xb8\xb7\x63\x44\x09\xb8\x2b\xe8\x4a\x38\x87\x98\xe9\xb6\x23\x6e\x82\x37\x23\x6e\x82\x37\xca\x44\xc0\xb7\xca\x44\xc0\xb7\x99\x19\xa8\x37\x22\x84\x50\x38\x4b\x1e\x9e\x36\x01\xec\x3b\x37\x01\xec\x3b\x37\xe1\x33\xc2\xb7\xe1\x33\xc2\xb7\x7b\x19\x84\x37\x30\x3f\x56\x38\xb8\x8b\x77\xb5\xb3\x2f\xbf\x37\xb3\x2f\xbf\x37\x5a\x1a\xce\xb7\x5a\x1a\xce\xb7\xaa\xbb\x73\xb8\x53\x19\x5c\x38\x1e\x73\x05\xb6\xda\x71\x67\x37\xda\x71\x67\x37\x6d\xe1\xe4\xb7\x6d\xe1\xe4\xb7\x0c\x83\xb2\x38\x73\x13\x62\x38\x47\x19\x36\x36\xab\x11\x06\x38\xab\x11\x06\x38\x6e\xf5\x05\xb8\x6e\xf5\x05\xb8\x18\x17\xb4\xb8\x90\x2d\x68\x38\x87\xca\xa3\xb6\x49\x98\x42\x37\x49\x98\x42\x37\xa7\x80\x10\xb8\xa7\x80\x10\xb8\x81\x2f\x78\x38\xba\x68\x6e\x38\xa7\x4d\xe5\x36\xda\xe8\x0d\x38\xda\xe8\x0d\x38\x2e\x3b\x0f\xb8\x2e\x3b\x0f\xb8\x00\x3d\x4b\xb7\xf4\xc4\x74\x38\xd4\x38\xc5\xb6\xba\xb3\x21\x37\xba\xb3\x21\x37\x4f\xb0\x10\xb8\x4f\xb0\x10\xb8\x10\x27\x16\xb8\xf2\x42\x7b\x38\x94\x08\xcb\x36\xcc\xd6\x00\x38\xcc\xd6\x00\x38\xd6\x36\x11\xb8\xd6\x36\x11\xb8\x32\x9b\x86\x38\x5b\xf1\x80\x38\x98\x10\x0e\xb7\x53\xcf\x79\x37\x53\xcf\x79\x37\x76\x39\x20\xb8\x76\x39\x20\xb8\x35\xa9\x86\xb8\xc8\x52\x84\x38\x8b\x94\xe9\x36\x1c\xae\xd3\x37\x1c\xae\xd3\x37\x48\x5c\x2a\xb8\x48\x5c\x2a\xb8\x21\x26\x1d\x38\xc0\xc5\x87\x38\x0f\xb5\xaa\xb6\x3d\xdd\xd4\x37\x3d\xdd\xd4\x37\xc0\xe7\x33\xb8\xc0\xe7\x33\xb8\x61\xcf\x83\x36\x8f\x4a\x8b\x38\x9b\x45\xf1\x36\x92\x4d\x7b\x37\x92\x4d\x7b\x37\x14\x79\x2a\xb8\x14\x79\x2a\xb8\x25\x6c\x25\xb8\x36\xe1\x8e\x38\x97\x6f\xd8\xb6\xa0\x85\x07\x38\xa0\x85\x07\x38\x75\xe7\x21\xb8\x75\xe7\x21\xb8\x6d\x37\x55\x38\x5a\x8a\x92\x38\xa4\x78\xf6\x35\x82\xce\x39\x37\x82\xce\x39\x37\xfc\x1f\x1e\xb8\xfc\x1f\x1e\xb8\x90\xb3\xfc\xb7\xfe\x45\x96\x38\xf9\x7d\x06\xb6\x48\x26\x0c\x38\x48\x26\x0c\x38\xc7\x23\x2c\xb8\xc7\x23\x2c\xb8\xf3\x3d\x84\xb7\x88\x14\x9a\x38\x52\x83\x73\x36\x42\xaf\x82\x37\x42\xaf\x82\x37\x17\xe1\x33\xb8\x17\xe1\x33\xb8\xbe\x48\x8b\x38\xfc\xf5\x9d\x38\x1d\xed\x99\x35\xc1\x87\x0b\x38\xc1\x87\x0b\x38\xa8\xc8\x2f\xb8\xa8\xc8\x2f\xb8\x6a\xcc\xd5\xb8\xed\xea\xa1\x38\xf1\x7d\x85\xb6\x93\xd5\xda\x37\x93\xd5\xda\x37\x65\xfc\x18\xb8\x65\xfc\x18\xb8\x92\x9a\xe9\x38\x5c\xf3\xa5\x38\xce\xd3\x66\x35\xd0\xef\xd4\x37\xd0\xef\xd4\x37\x31\x17\x0a\xb8\x31\x17\x0a\xb8\xda\xb1\xbe\xb8\xb6\x0f\xaa\x38\x00\x43\x10\xb7\x0d\x54\x0c\x38\x0d\x54\x0c\x38\xb4\xce\x09\xb8\xb4\xce\x09\xb8\xcc\xc5\x4e\x38\xfc\x3f\xae\x38\x9b\x0a\x8b\x37\x51\x48\x96\x37\x51\x48\x96\x37\xc2\x43\x09\xb8\xc2\x43\x09\xb8\x06\xda\x10\xb7\xc3\x84\xb2\x38\x52\xce\x92\xb7\xaa\xfa\x04\x38\xaa\xfa\x04\x38\x61\x62\x02\xb8\x61\x62\x02\xb8\x03\x1f\x43\xb7\x0e\xde\xb6\x38\xa1\x16\xb8\x37\xbd\x71\x97\x37\xbd\x71\x97\x37\xcd\x25\xe7\xb7\xcd\x25\xe7\xb7\x57\xde\xc1\x36\x58\x4c\xbb\x38\x60\xab\x05\xb8\xae\xc9\x0f\x38\xae\xc9\x0f\x38\x0e\x05\xbb\xb7\x0e\x05\xbb\xb7\xe1\xb7\xb9\x37\xa4\xcf\xbf\x38\x3e\x7e\x0c\x38\x32\x2e\x84\x37\x32\x2e\x84\x37\x5c\x82\x8d\xb7\x5c\x82\x8d\xb7\x7a\xd5\x82\xb8\x81\x68\xc4\x38\x90\x91\xf7\xb7\x6d\xe4\x98\x37\x6d\xe4\x98\x37\x9d\x18\x55\xb7\x9d\x18\x55\xb7\xc5\xfa\xcb\x38\xf1\x16\xc9\x38\xc6\xb2\x17\x38\x7d\x0f\x21\x37\x7d\x0f\x21\x37\x36\x6f\x66\xb7\x36\x6f\x66\xb7\xc7\x75\xde\xb8\x68\xdb\xcd\x38\xba\xbd\x1c\xb8\x75\x92\x56\x37\x75\x92\x56\x37\x8e\xb0\x41\xb7\x8e\xb0\x41\xb7\xf7\x29\xb0\x38\xe8\xb5\xd2\x38\xf1\x4c\xc1\x37\xc7\xb9\x99\x37\xc7\xb9\x99\x37\x49\x1f\x26\xb6\x49\x1f\x26\xb6\x14\xac\x36\xb8\x5b\x39\xde\x38\x4c\x6e\x94\xb7\x7f\xb5\x92\x36\x7f\xb5\x92\x36\x4b\xab\xa4\x36\x4b\xab\xa4\x36\x3b\x87\xa6\x36\xc2\x65\xf0\x38\x88\xae\x2f\x36\x6b\x73\xe1\x37\x6b\x73\xe1\x37\xf3\x55\x15\x37\xf3\x55\x15\x37\x32\xc9\xeb\x37\x49\x8a\xf7\x38\x11\xb7\xe3\x36\xfe\x9a\x2b\xb7\xfe\x9a\x2b\xb7\x8b\xd7\x2c\x37\x8b\xd7\x2c\x37\x08\x3b\x40\xb8\xef\xa6\xf3\x38\x7e\x63\x74\xb7\xf0\x50\x0b\x38\xf0\x50\x0b\x38\xa2\xbd\x6a\x37\xa2\xbd\x6a\x37\x57\x0a\x2e\x38\xb7\xb7\xf4\x38\xe8\x7a\xf6\x37\xf8\xb6\xbe\xb7\xf8\xb6\xbe\xb7\x9b\x18\x8b\x37\x9b\x18\x8b\x37\xee\xf2\xb3\xb7\xa2\xbc\xfa\x38\x1b\xbd\x3d\xb8\x54\x3e\x2a\x38\x54\x3e\x2a\x38\xea\x52\xc4\x37\xea\x52\xc4\x37\x2e\xf6\x08\xb3\xc6\x70\x00\x39\xa9\x2e\x75\x38\x45\xb1\x28\xb8\x45\xb1\x28\xb8\x49\x25\xe9\x37\x49\x25\xe9\x37\xe7\x79\x20\x37\x3a\x93\x03\x39\xb3\x80\x86\xb8\x09\x4c\x01\x38\x09\x4c\x01\x38\x8f\x3c\xfe\x37\x8f\x3c\xfe\x37\x83\xdb\x2a\xb5\x2a\xc6\x06\x39\x74\x22\xa4\x38\xce\x32\xfe\xb7\xce\x32\xfe\xb7\x12\x71\x09\x38\x12\x71\x09\x38\x09\x0b\xdb\xb7\x97\x09\x0a\x39\x5c\x70\xb3\xb8\xc4\x23\x61\x36\xc4\x23\x61\x36\xe7\xda\x12\x38\xe7\xda\x12\x38\x4f\xbe\x87\x38\xc3\x5d\x0d\x39\x44\xd0\xb6\x38\xfb\xe1\x06\xb7\xfb\xe1\x06\xb7\x76\xa6\x19\x38\x76\xa6\x19\x38\x8b\xff\xd6\xb8\xaf\xc2\x10\x39\xdd\x89\xbb\xb8\x02\x4c\xfc\xb7\x02\x4c\xfc\xb7\x84\xcb\x28\x38\x84\xcb\x28\x38\x0f\x11\x05\x39\x19\x39\x14\x39\x19\x2a\xc1\x38\xf5\xfa\xc2\x37\xf5\xfa\xc2\x37\x9e\xc3\x33\x38\x9e\xc3\x33\x38\x6a\xf9\x0c\xb9\x01\xc1\x17\x39\x64\x73\xb7\xb8\x34\x42\x9d\xb8\x34\x42\x9d\xb8\xa5\x38\x32\x38\xa5\x38\x32\x38\xad\xf2\x05\x39\x06\x5b\x1b\x39\xc7\xd3\xa3\x38\x41\x84\x4f\x38\x41\x84\x4f\x38\xdc\x72\x27\x38\xdc\x72\x27\x38\x2e\xe4\xea\xb8\x28\x07\x1f\x39\x6e\x63\x80\xb8\xc6\xc3\xc9\xb8\xc6\xc3\xc9\xb8\x77\x87\x28\x38\x77\x87\x28\x38\xf1\x4f\xc6\x38\x70\xc6\x22\x39\x3d\xe4\x31\x38\xda\xf2\x83\x38\xda\xf2\x83\x38\xd5\x60\x30\x38\xd5\x60\x30\x38\xb3\xf3\xad\xb8\xdf\x98\x26\x39\x4b\x53\xc4\xb7\x86\x76\xc2\xb8\x86\x76\xc2\xb8\xa8\x63\x2d\x38\xa8\x63\x2d\x38\x75\x26\xb1\x38\xd8\x7e\x2a\x39\x22\x53\x4b\xb7\x69\x37\x22\x38\x69\x37\x22\x38\xbc\x48\x21\x38\xbc\x48\x21\x38\xdd\xd4\xcf\xb8\x5c\x78\x2e\x39\x73\xc0\x2d\x38\xcf\x40\x83\xb8\xcf\x40\x83\xb8\x9e\x10\x10\x38\x9e\x10\x10\x38\xba\x81\xf7\x38\xb8\x85\x32\x39\x04\xc2\x9b\xb8\x35\xf7\xaf\xb6\x35\xf7\xaf\xb6\x30\x57\x05\x38\x30\x57\x05\x38\x37\x29\x0e\xb9\xed\xa6\x36\x39\x1c\x0a\xe3\x38\x10\xcd\x9e\xb7\x10\xcd\x9e\xb7\x9c\xac\xf9\x37\x9c\xac\xf9\x37\xb3\x2d\x19\x39\xfb\xdb\x3a\x39\xe1\x80\x0b\xb9\xa6\xcd\x7b\xb8\xa6\xcd\x7b\xb8\x48\xb2\xe7\x37\x48\xb2\xe7\x37\x69\xe8\x11\xb9\xe3\x24\x3f\x39\xa7\x5e\x26\x39\x82\xa4\x04\x38\x82\xa4\x04\x38\xf1\xfd\xcd\x37\xf1\xfd\xcd\x37\x03\x89\xf1\x38\x51\x83\x43\x39\x63\x89\x34\xb9\x73\xa6\xd5\xb8\x73\xa6\xd5\xb8\xcc\x11\xaa\x37\xcc\x11\xaa\x37\x22\xf4\xad\xb8\x45\xf7\x47\x39\x41\x9b\x39\x39\xcb\x52\x80\x38\xcb\x52\x80\x38\x3c\xd4\x80\x37\x3c\xd4\x80\x37\x8d\xd6\x45\x38\x91\x82\x4c\x39\x6e\x05\x36\xb9\x62\xbd\x06\xb9\x62\xbd\x06\xb9\x3f\xac\x06\x37\x3f\xac\x06\x37\xb2\x28\x8a\xb7\x35\x25\x51\x39\x21\xba\x34\x39\x6c\x49\x95\x38\x6c\x49\x95\x38\x63\x4a\xa9\x36\x63\x4a\xa9\x36\x08\x9f\xa6\xb4\x16\xdc\x55\x39\x79\x61\x1d\xb9\x03\xc2\xf1\xb8\x03\xc2\xf1\xb8\x68\x78\xb6\x36\x68\x78\xb6\x36\x59\xf3\xe0\x36\x34\xa7\x5a\x39\x8d\x4a\x18\x39\x3e\xf4\x0d\x38\x3e\xf4\x0d\x38\x20\x34\x34\x35\x20\x34\x34\x35\xff\x9b\x0b\xb7\xcf\x8a\x5f\x39\xb2\xf6\x09\xb9\xb3\x98\xa5\xb8\xb3\x98\xa5\xb8\x60\x5a\xe5\xb6\x60\x5a\xe5\xb6\xa5\xa2\x19\x37\xe6\x86\x64\x39\x7c\x80\x02\x39\xd2\xc9\xf2\xb6\xd2\xc9\xf2\xb6\x0c\x4e\x74\xb7\x0c\x4e\x74\xb7\x97\x1e\xa0\xb7\x67\x9a\x69\x39\x8b\x11\xef\xb8\x16\x19\x8a\xb7\x16\x19\x8a\xb7\x13\x2d\x8d\xb7\x13\x2d\x8d\xb7\xe4\x29\x3f\x38\x50\xc5\x6e\x39\xff\x53\xe9\x38\xc0\x77\x91\xb8\xc0\x77\x91\xb8\x07\x4b\x8a\xb7\x07\x4b\x8a\xb7\x5a\xcf\xb5\xb8\xce\x08\x74\x39\x09\x57\xda\xb8\x7f\xcd\x0b\x38\x7f\xcd\x0b\x38\x6b\x7e\xa2\xb7\x6b\x7e\xa2\xb7\xe3\x8e\x0f\x39\xe2\x64\x79\x39\xe9\x1b\xdd\x38\xd2\x5e\xeb\xb8\xd2\x5e\xeb\xb8\xad\x42\xdb\xb7\xad\x42\xdb\xb7\xf8\xac\x45\xb9\x52\xda\x7e\x39\x44\xed\xb0\xb8\x5d\xe4\xa4\x38\x5d\xe4\xa4\x38\x69\x5f\x00\xb8\x69\x5f\x00\xb8\x81\x39\x73\x39\x90\x34\x82\x39\xce\x19\xa7\x38\x83\x94\x05\xb9\x83\x94\x05\xb9\x90\x4a\x02\xb8\x90\x4a\x02\xb8\x51\xed\x88\xb9\xdd\x08\x85\x39\x6c\x7b\x85\xb8\xa8\x8e\xa0\x38\xa8\x8e\xa0\x38\x84\x17\x09\xb8\x84\x17\x09\xb8\x8f\xf0\x90\x39\x12\xea\x87\x39\xe4\xd7\x3c\x38\xf5\xcd\xb8\xb8\xf5\xcd\xb8\xb8\xb8\x73\x12\xb8\xb8\x73\x12\xb8\x2a\xc4\x93\xb9\xa3\xd8\x8a\x39\x86\x64\xe3\xb7\xb5\x6e\x3e\x38\xb5\x6e\x3e\x38\x61\x5e\x18\xb8\x61\x5e\x18\xb8\xb4\xb5\x95\x39\x90\xd4\x8d\x39\x43\xf4\x96\x37\xcd\xda\xf2\xb7\xcd\xda\xf2\xb7\xd7\x27\x13\xb8\xd7\x27\x13\xb8\xb9\xec\x9c\xb9\x32\xde\x90\x39\x0d\xd7\xe5\xb6\xdb\xb4\xd3\xb7\xdb\xb4\xd3\xb7\xc7\xcd\x1d\xb8\xc7\xcd\x1d\xb8\x3a\x63\xac\x39\x89\xf5\x93\x39\xa2\x71\x10\x37\x5b\x45\x37\x38\x5b\x45\x37\x38\x1e\xcf\x21\xb8\x1e\xcf\x21\xb8\xa0\x1e\xc2\xb9\x1a\x1b\x97\x39\xc3\x45\x8a\xb7\x82\x42\xb0\xb8\x82\x42\xb0\xb8\x40\xba\x11\xb8\x40\xba\x11\xb8\x13\xff\xda\x39\xe4\x4e\x9a\x39\xc2\xdd\x11\x38\xe4\x49\xde\x38\xe4\x49\xde\x38\x3d\x78\x06\xb8\x3d\x78\x06\xb8\xaa\x19\xf2\xb9\x1c\x91\x9d\x39\x29\x6f\x9f\xb8\x55\xe7\xfe\xb8\x55\xe7\xfe\xb8\xa5\xf6\xf9\xb7\xa5\xf6\xf9\xb7\xaf\x7c\x00\x3a\xc0\xe1\xa0\x39\xf1\xf8\xe1\x38\x30\xa7\x13\x39\x30\xa7\x13\x39\xe3\xb7\xf6\xb7\xe3\xb7\xf6\xb7\x88\x4c\x02\xba\x30\x41\xa4\x39\x44\x9e\x1a\xb9\x05\x84\x01\xb9\x05\x84\x01\xb9\x18\x5c\xe5\xb7\x18\x5c\xe5\xb7\xc5\x57\xfe\x39\x6a\xaf\xa7\x39\x6f\x4f\x4e\x39\x37\xce\xe3\x38\x37\xce\xe3\x38\x59\xb6\x98\xb7\x59\xb6\x98\xb7\x9d\xe0\xf2\xb9\xea\x2c\xab\x39\xb6\x53\x7d\xb9\x05\x59\xa8\xb8\x05\x59\xa8\xb8\xc2\x18\x5a\xb7\xc2\x18\x5a\xb7\xa2\x54\xe8\x39\xb0\xb9\xae\x39\x58\x04\x8e\x39\xf7\x75\x6c\x38\xf7\x75\x6c\x38\xb5\xf2\x44\xb7\xb5\xf2\x44\xb7\x45\xdd\xe1\xb9\x55\x56\xb2\x39\x8b\xe1\x91\xb9\xee\x92\xb2\xb6\xee\x92\xb2\xb6\xae\x6f\xf9\xb6\xae\x6f\xf9\xb6\x98\x40\xe1\x39\xdb\x02\xb6\x39\xd0\xcc\x93\x39\x39\x12\x13\x36\x39\x12\x13\x36\xfa\x0f\x7b\xb5\xfa\x0f\x7b\xb5\xf0\x6f\xe7\xb9\x20\xbf\xb9\x39\xe6\xc1\x93\xb9\x8f\x0c\x69\x38\x8f\x0c\x69\x38\x78\x87\xc2\x36\x78\x87\xc2\x36\x69\x78\xee\x39\x23\x8b\xbd\x39\x8b\xd4\x87\x39\x28\x50\x61\xb8\x28\x50\x61\xb8\xbd\xad\x1b\x37\xbd\xad\x1b\x37\x02\xfb\xed\xb9\xe2\x67\xc1\x39\x6e\x66\x60\xb9\xaa\x6d\xdf\x38\xaa\x6d\xdf\x38\x6e\xb5\x81\x37\x6e\xb5\x81\x37\xf1\xfe\xe3\x39\x5c\x55\xc5\x39\xe4\x3c\x3a\x39\xf2\x7e\xc0\xb8\xf2\x7e\xc0\xb8\x74\xd1\xb1\x37\x74\xd1\xb1\x37\x7f\xed\xd0\xb9\x8f\x53\xc9\x39\xdc\xbf\x05\xb9\x06\x74\xff\x38\x06\x74\xff\x38\x69\xe6\xd7\x37\x69\xe6\xd7\x37\x9a\x20\xb4\x39\x7a\x62\xcd\x39\xad\xc0\x87\x38\x02\x32\x4f\xb8\x02\x32\x4f\xb8\xb7\x90\xec\x37\xb7\x90\xec\x37\x13\x2d\x90\xb9\xd0\x82\xd1\x39\x8e\xb4\xc2\xb5\x1d\x85\xd6\x38\x1d\x85\xd6\x38\x85\x09\x08\x38\x85\x09\x08\x38\x00\x58\x5a\x39\x91\xb4\xd5\x39\x77\x51\x37\xb8\x09\xf6\xa7\xb7\x09\xf6\xa7\xb7\x2c\x02\x23\x38\x2c\x02\x23\x38\xe3\x1a\x2a\xb9\x0b\xf8\xd9\x39\x00\xef\x9c\x38\xd5\x8b\x22\x38\xd5\x8b\x22\x38\x7c\x65\x35\x38\x7c\x65\x35\x38\xdc\x62\x13\x39\x3f\x4d\xde\x39\x2b\xbd\xd5\xb8\xb1\x06\x84\x37\xb1\x06\x84\x37\x48\x74\x18\x38\x48\x74\x18\x38\x55\x8f\xff\xb8\xad\xb4\xe2\x39\x28\x92\x3a\x39\xf5\xc6\x42\x37\xf5\xc6\x42\x37\x87\xdb\x0c\x38\x87\xdb\x0c\x38\x5a\xf1\xd7\x38\x56\x2e\xe7\x39\xc1\xde\x47\xb9\xa8\x2a\x9d\x38\xa8\x2a\x9d\x38\x34\x8d\x0b\x38\x34\x8d\x0b\x38\xed\x30\x92\xb8\x8e\xba\xeb\x39\x75\xcd\x2d\x39\x82\x6c\x60\xb8\x82\x6c\x60\xb8\x0a\xd5\x0e\x38\x0a\xd5\x0e\x38\x71\xfc\x8a\x37\x56\x59\xf0\x39\x55\xfd\x0d\xb9\xd3\xc0\xb2\x38\xd3\xc0\xb2\x38\x45\x82\x06\x38\x45\x82\x06\x38\xb1\x76\x53\x38\x3e\x0b\xf5\x39\x46\xeb\x01\x39\x5a\xe6\x1f\xb8\x5a\xe6\x1f\xb8\x77\x6e\xed\x37\x77\x6e\xed\x37\x5a\x67\xf8\xb8\x44\xd0\xf9\x39\x2e\x5a\xb3\xb8\xb2\x66\x09\x39\xb2\x66\x09\x39\x68\x47\xa5\x37\x68\x47\xa5\x37\xd0\x2c\x3f\x39\xd6\xa8\xfe\x39\x3f\xc6\x8b\x37\xe0\x0e\x10\xb8\xe0\x0e\x10\xb8\x0e\xb5\x6d\x37\x0e\xb5\x6d\x37\xeb\x70\x79\xb9\x78\xca\x01\x3a\xc6\x80\xea\x37\x15\xc2\xc6\x38\x15\xc2\xc6\x38\x43\xf3\x1f\x37\x43\xf3\x1f\x37\xb4\x91\x90\x39\x88\x4a\x04\x3a\x6a\x49\x87\xb8\x9a\xe6\xed\xb7\x9a\xe6\xed\xb7\x66\xc9\x89\x36\x66\xc9\x89\x36\x03\x98\x98\xb9\x9b\xd4\x06\x3a\x20\x04\xff\x38\x89\x5d\x98\x38\x89\x5d\x98\x38\xbc\xc6\x01\xb6\xbc\xc6\x01\xb6\x63\x83\x98\x39\xd9\x68\x09\x3a\x9e\x06\x25\xb9\x24\xfa\xff\x37\x24\xfa\xff\x37\xea\x03\x12\xb7\xea\x03\x12\xb7\x75\xd7\x97\xb9\x42\x07\x0c\x3a\xed\xee\x0e\x39\xf1\xc8\xad\x36\xf1\xc8\xad\x36\x8c\x93\x6a\xb7\x8c\x93\x6a\xb7\xb0\xe2\x9b\x39\x28\xb0\x0e\x3a\xd1\xcc\xed\xb8\x39\x56\xad\x38\x39\x56\xad\x38\x07\xc2\xab\xb7\x07\xc2\xab\xb7\x41\x00\xa7\xb9\x8c\x63\x11\x3a\x13\xd1\xb6\x38\x31\x1b\x6c\xb8\x31\x1b\x6c\xb8\xa4\xff\xe2\xb7\xa4\xff\xe2\xb7\x13\xd7\xb9\x39\x9f\x21\x14\x3a\x80\x9b\x14\xb8\x67\x4f\xbf\x38\x67\x4f\xbf\x38\x34\x19\xf2\xb7\x34\x19\xf2\xb7\xae\xfe\xcf\xb9\x63\xea\x16\x3a\x88\x04\x66\xb7\x51\xcd\xb0\xb8\x51\xcd\xb0\xb8\x46\x86\x08\xb8\x46\x86\x08\xb8\xb9\x91\xe0\x39\x0a\xbe\x19\x3a\xbe\x66\x2e\x38\x12\xcf\xa5\x38\x12\xcf\xa5\x38\xfa\x27\x1b\xb8\xfa\x27\x1b\xb8\xfa\x91\xe4\xb9\x93\x9c\x1c\x3a\xde\xfd\xa2\xb8\x89\x20\x5d\xb8\x89\x20\x5d\xb8\x6b\xed\x1c\xb8\x6b\xed\x1c\xb8\x6c\x7c\xd9\x39\x4d\x86\x1f\x3a\x4a\xc9\xf3\x38\xd1\xc0\x20\x37\xd1\xc0\x20\x37\xc9\x42\x2a\xb8\xc9\x42\x2a\xb8\x71\xda\xc2\xb9\x36\x7b\x22\x3a\x8b\x72\x00\xb9\xbf\x55\x12\x38\xbf\x55\x12\x38\x46\x78\x2c\xb8\x46\x78\x2c\xb8\x67\xa5\xa9\x39\x7e\x7b\x25\x3a\x5f\x53\xfa\x38\x93\xdc\x9f\xb8\x93\xdc\x9f\xb8\x11\x3a\x23\xb8\x11\x3a\x23\xb8\xa2\x70\x96\xb9\x25\x87\x28\x3a\x5a\xb1\xf4\xb8\x32\xc7\xdd\x38\x32\xc7\xdd\x38\x01\xfc\x20\xb8\x01\xfc\x20\xb8\x0c\xd6\x8d\x39\x6d\x9e\x2b\x3a\x8a\xe4\xb1\x38\x90\xeb\x0d\xb9\x90\xeb\x0d\xb9\xd0\xe3\x0b\xb8\xd0\xe3\x0b\xb8\x69\x3a\x90\xb9\x57\xc1\x2e\x3a\x65\xdf\x02\xb8\xf7\x04\x0f\x39\xf7\x04\x0f\x39\x36\xe3\xfb\xb7\x36\xe3\xfb\xb7\xf8\xcd\x97\x39\x28\xf0\x31\x3a\xa5\xe5\x4a\xb7\x09\x75\xf7\xb8\x09\x75\xf7\xb8\xd6\x56\xe3\xb7\xd6\x56\xe3\xb7\x12\xe0\x9a\xb9\xe0\x2a\x35\x3a\xcd\xc5\x6e\x38\x41\xf1\x0f\x39\x41\xf1\x0f\x39\x58\xcb\xc2\xb7\x58\xcb\xc2\xb7\x36\xad\x92\x39\xb4\x71\x38\x3a\x12\xa7\xf6\xb8\x94\x34\xa9\xb8\x94\x34\xa9\xb8\xed\x2c\x7f\xb7\xed\x2c\x7f\xb7\x08\x2e\x7d\xb9\xa2\xc4\x3b\x3a\xa9\xf1\x2d\x39\x4e\x33\x62\x38\x4e\x33\x62\x38\xe6\x57\x0a\xb7\xe6\x57\x0a\xb7\xc2\x6d\x45\x39\xf2\x23\x3f\x3a\x09\x04\x4e\xb9\xb4\x16\x54\xb8\xb4\x16\x54\xb8\x80\x0c\x7c\xb6\x80\x0c\x7c\xb6\xfa\xf8\x0a\xb9\xa3\x8f\x42\x3a\x06\x51\x59\x39\x43\xd0\x64\x37\x43\xd0\x64\x37\x7e\x4b\x94\x33\x7e\x4b\x94\x33\x9b\x38\xb5\x38\xec\x07\x46\x3a\xe2\x2c\x57\xb9\x0d\x35\x48\xb8\x0d\x35\x48\xb8\x0f\x57\xe3\x36\x0f\x57\xe3\x36\x9f\x2b\x76\xb8\xd0\x8c\x49\x3a\x83\xf4\x3c\x39\x5a\xdc\xb3\xb6\x5a\xdc\xb3\xb6\x63\x6c\x74\x37\x63\x6c\x74\x37\x6d\xc8\x4f\x38\x99\x1e\x4d\x3a\x82\xa5\x11\xb9\xe5\x1b\x20\xb8\xe5\x1b\x20\xb8\x63\x58\xb4\x37\x63\x58\xb4\x37\x4b\x37\x48\xb8\x49\xbd\x50\x3a\x02\x74\xc6\x38\x28\xa3\x0d\xb8\x28\xa3\x0d\xb8\xbc\x04\xdc\x37\xbc\x04\xdc\x37\x80\xa5\x23\x38\x12\x69\x54\x3a\xd9\x12\x49\xb8\xe2\x58\x1e\xb7\xe2\x58\x1e\xb7\x8b\x7a\xed\x37\x8b\x7a\xed\x37\xa2\x76\x88\xb7\xf6\x21\x58\x3a\x5d\x41\xe4\x36\xae\x40\x8a\xb8\xae\x40\x8a\xb8\x8d\x3e\x0b\x38\x8d\x3e\x0b\x38\xfc\xbc\xbf\xb7\x36\xe8\x5b\x3a\x1b\x29\xee\x37\x61\x6d\x57\x38\x61\x6d\x57\x38\x1b\x8b\x25\x38\x1b\x8b\x25\x38\x1e\xf9\xa2\x38\xd6\xbb\x5f\x3a\xda\x27\xf7\xb7\xc4\x05\x14\xb9\xc4\x05\x14\xb9\x3d\x5c\x2d\x38\x3d\x5c\x2d\x38\x71\xdc\x12\xb9\x10\x9d\x63\x3a\x5b\xde\x88\x37\xc4\xb4\x2c\x39\xc4\xb4\x2c\x39\xe1\x0c\x2f\x38\xe1\x0c\x2f\x38\xbe\x35\x50\x39\xe8\x8b\x67\x3a\x63\xcb\x38\xb7\x0d\x50\x5c\xb9\x0d\x50\x5c\xb9\x0b\xde\x24\x38\x0b\xde\x24\x38\xd3\xa6\x81\xb9\xa2\x88\x6b\x3a\xb8\x89\x05\x36\x1b\x18\x45\x39\x1b\x18\x45\x39\xac\xa1\x1d\x38\xac\xa1\x1d\x38\x0e\xcd\x95\x39\x42\x93\x6f\x3a\x1a\x0f\x9e\x37\x9d\x2c\x82\xb9\x9d\x2c\x82\xb9\x42\xfd\x18\x38\x42\xfd\x18\x38\x3b\xb5\xa7\xb9\xf5\xab\x73\x3a\x70\x2f\x86\xb7\x07\x01\x1b\x39\x07\x01\x1b\x39\x30\xf6\x0e\x38\x30\xf6\x0e\x38\x40\x35\xbc\x39\xbd\xd2\x77\x3a\xaf\x4b\x5a\xb7\x31\x99\x29\xb9\x31\x99\x29\xb9\x3f\x20\xef\x37\x3f\x20\xef\x37\x0b\x57\xd5\xb9\xf0\x07\x7c\x3a\xce\x96\xd7\x37\xe9\x39\xd8\x37\xe9\x39\xd8\x37\x22\x7b\xaf\x37\x22\x7b\xaf\x37\x14\xab\xf3\x39\xc7\x25\x80\x3a\x31\x3c\x1b\xb8\xb0\x02\x62\xb7\xb0\x02\x62\xb7\x7d\xd6\x79\x37\x7d\xd6\x79\x37\x98\xf6\x0b\xba\xde\x4e\x82\x3a\x30\xdc\x8d\x38\x35\x6f\xf2\xb8\x35\x6f\xf2\xb8\x5d\xa4\x0d\x37\x5d\xa4\x0d\x37\x54\x77\x1f\x3a\x3f\x7f\x84\x3a\x5b\xf8\xa1\xb8\x88\x34\xd6\x38\x88\x34\xd6\x38\xdf\x9d\xd4\x35\xdf\x9d\xd4\x35\xd6\x7b\x31\xba\x12\xb7\x86\x3a\xe4\x50\x63\x38\x50\xdc\x45\xb9\x50\xdc\x45\xb9\x3b\xb3\xf7\xb6\x3b\xb3\xf7\xb6\x16\x84\x40\x3a\x59\xf6\x88\x3a\x45\x99\x0a\xb8\xa2\xd9\xd7\x38\xa2\xd9\xd7\x38\x0a\xe7\x7d\xb7\x0a\xe7\x7d\xb7\x17\xc6\x4c\xba\x2d\x3d\x8b\x3a\xaa\x20\x8d\x37\xd3\x38\x17\xb9\xd3\x38\x17\xb9\x39\xe5\xaf\xb7\x39\xe5\xaf\xb7\xbf\xcb\x56\x3a\x90\x8b\x8d\x3a\x7c\xfc\x1d\x38\x04\xfb\xa8\x38\x04\xfb\xa8\x38\x67\x51\xe5\xb7\x67\x51\xe5\xb7\x19\xf3\x5e\xba\xa4\xe1\x8f\x3a\x2d\x67\xab\xb8\x1f\xae\x9b\xb7\x1f\xae\x9b\xb7\x62\x0a\x0d\xb8\x62\x0a\x0d\xb8\xd1\x5f\x66\x3a\x6c\x3f\x92\x3a\xbb\x3f\xc3\x38\xeb\xad\x63\xb8\xeb\xad\x63\xb8\x0f\x53\x24\xb8\x0f\x53\x24\xb8\x19\xf2\x6e\xba\xff\xa4\x94\x3a\xc6\x1d\x32\xb9\x30\x47\xd3\x38\x30\x47\xd3\x38\x9c\x68\x34\xb8\x9c\x68\x34\xb8\x28\xe9\x77\x3a\x60\x12\x97\x3a\x3e\xc4\x83\x39\xc7\xa8\x2f\xb9\xc7\xa8\x2f\xb9\x35\xa9\x2f\xb8\x35\xa9\x2f\xb8\x7e\xf8\x7d\xba\xb2\x87\x99\x3a\xa3\x56\x9b\xb9\x59\xe7\x15\x39\x59\xe7\x15\x39\x28\x37\x32\xb8\x28\x37\x32\xb8\xa9\x6b\x7f\x3a\xf6\x04\x9c\x3a\xd4\xaf\xb7\x39\xbd\x9f\x3c\xb9\xbd\x9f\x3c\xb9\x6e\x67\x35\xb8\x6e\x67\x35\xb8\x7b\x79\x7c\xba\x4a\x8a\x9e\x3a\x4d\x5e\xe0\xb9\x6d\x56\x54\x39\x6d\x56\x54\x39\x1a\x7d\x20\xb8\x1a\x7d\x20\xb8\xa5\x05\x75\x3a\xac\x17\xa1\x3a\x92\xd2\xf8\x39\x7f\x78\x4f\xb9\x7f\x78\x4f\xb9\xc2\x6b\x11\xb8\xc2\x6b\x11\xb8\xb9\xce\x6a\xba\x41\xad\xa3\x3a\x89\x45\xf4\xb9\xbd\x14\xea\x38\xbd\x14\xea\x38\x51\x4e\xfd\xb7\x51\x4e\xfd\xb7\x99\xa4\x61\x3a\x07\x4b\xa6\x3a\x33\x2c\xfc\x39\x8c\x25\x2d\xb9\x8c\x25\x2d\xb9\xc6\x76\xb8\xb7\xc6\x76\xb8\xb7\xdd\x3f\x5a\xba\x1a\xf1\xa8\x3a\x40\x6d\xef\xb9\x77\x6a\x1f\x39\x77\x6a\x1f\x39\x51\x86\x4b\xb7\x51\x86\x4b\xb7\x32\x85\x50\x3a\x7a\x9f\xab\x3a\x60\x5c\xd8\x39\x4f\xfd\xc7\xb8\x4f\xfd\xc7\xb8\x6f\x30\xd6\xb6\x6f\x30\xd6\xb6\x1e\xb3\x40\xba\x28\x5d\xaf\x3a\xe5\x20\x8a\xb9\x3b\x59\xb0\x38\x3b\x59\xb0\x38\xbf\xff\x24\xb5\xbf\xff\x24\xb5\x26\x7d\x2b\x3a\x22\x2a\xb4\x3a\x73\xbd\x12\x39\xf1\x73\x78\x35\xf1\x73\x78\x35\xc9\x57\x42\x37\xc9\x57\x42\x37\x1e\xff\x13\xba\xd2\x42\xb7\x3a\x6a\x82\x4f\x38\x87\xb3\xad\xb8\x87\xb3\xad\xb8\xe0\x5a\x9e\x37\xe0\x5a\x9e\x37\xb8\x49\xf7\x39\x35\xa7\xb8\x3a\x32\x84\x82\xb9\x1e\x05\xde\x38\x1e\x05\xde\x38\xca\xc5\xbe\x37\xca\xc5\xbe\x37\xa5\x69\xc5\xb9\xb8\xd6\xba\x3a\xbe\x82\xf6\x39\x7f\x39\x0a\xb9\x7f\x39\x0a\xb9\x69\x64\xdc\x37\x69\x64\xdc\x37\x47\x3b\x95\x39\x59\xd1\xbd\x3a\xf0\xa1\x2f\xba\x08\xea\x82\x39\x08\xea\x82\x39\x9e\x4d\xf8\x37\x9e\x4d\xf8\x37\x84\x69\x52\xb9\xfd\xd5\xc0\x3a\x6e\xb1\x59\x3a\x38\x98\x8c\xb9\x38\x98\x8c\xb9\x69\xf6\x0f\x38\x69\xf6\x0f\x38\x10\xab\xfd\x38\xa4\xe4\xc3\x3a\x76\x9b\x6e\xba\x43\xbf\x6a\x39\x43\xbf\x6a\x39\x9c\x0a\x15\x38\x9c\x0a\x15\x38\xa7\xc5\x1f\xb8\x7b\xfd\xc6\x3a\xe4\x51\x84\x3a\x39\xc3\x00\xb9\x39\xc3\x00\xb9\xcf\xb1\xfc\x37\xcf\xb1\xfc\x37\xc1\x6a\x59\xb8\x84\x20\xca\x3a\x37\x7d\x89\xba\xee\xb3\xa4\x38\xee\xb3\xa4\x38\x56\x64\xcf\x37\x56\x64\xcf\x37\x28\x85\x19\x39\xdb\x4d\xcd\x3a\xdd\xc6\x87\x3a\x74\x2c\xd5\x38\x74\x2c\xd5\x38\x13\x17\xaf\x37\x13\x17\xaf\x37\x40\xe2\x79\xb9\x80\x85\xd0\x3a\x62\x77\x86\xba\x5b\xd9\xdd\xb8\x5b\xd9\xdd\xb8\x74\xa2\x97\x37\x74\xa2\x97\x37\x23\xad\xa7\x39\xb8\xc7\xd3\x3a\xd4\xdf\x83\x3a\x3e\x92\x9e\x39\x3e\x92\x9e\x39\xa7\x86\x41\x37\xa7\x86\x41\x37\xe5\x00\xca\xb9\x84\x14\xd7\x3a\x7e\xa9\x6f\xba\x78\x8b\xce\xb9\x78\x8b\xce\xb9\x8a\x21\x21\x35\x8a\x21\x21\x35\x9d\xf5\xe1\x39\x19\x6c\xda\x3a\xc2\x8f\x48\x3a\x4b\x11\x0f\x3a\x4b\x11\x0f\x3a\x75\x77\x34\xb7\x75\x77\x34\xb7\xf1\xa3\xee\xb9\x78\xce\xdd\x3a\xff\x8d\x12\xba\x4e\x08\x12\xba\x4e\x08\x12\xba\x9b\x1c\x90\xb7\x9b\x1c\x90\xb7\x5a\x43\xf2\x39\xfd\x3b\xe1\x3a\x30\xa1\xb3\x39\xb9\xd6\x36\x3a\xb9\xd6\x36\x3a\x57\x62\xba\xb7\x57\x62\xba\xb7\xf8\x8e\xf0\xb9\xa6\xb4\xe4\x3a\xa9\x2c\x0e\xb9\x44\x20\x16\xba\x44\x20\x16\xba\xc4\x9b\xdb\xb7\xc4\x9b\xdb\xb7\xfc\x52\xea\x39\x99\x38\xe8\x3a\xa4\x24\x33\xb9\xc4\x96\x13\x3a\xc4\x96\x13\x3a\x65\x34\x11\xb8\x65\x34\x11\xb8\x48\x2d\xde\xb9\xd5\xc7\xeb\x3a\xcb\x42\xe6\x39\xad\xdc\xd0\xb9\xad\xdc\xd0\xb9\x1c\xd0\x29\xb8\x1c\xd0\x29\xb8\xa4\x99\xcc\x39\x7b\x62\xef\x3a\x0e\x38\x3a\xba\x91\x14\xa5\x39\x91\x14\xa5\x39\x41\xab\x36\xb8\x41\xab\x36\xb8\xb3\xed\xb5\xb9\x8a\x08\xf3\x3a\x30\xe5\x7b\x3a\x42\xb0\x11\xb9\x42\xb0\x11\xb9\x4d\x0c\x37\xb8\x4d\x0c\x37\xb8\xc2\xb3\x97\x39\x08\xba\xf6\x3a\xbc\x24\x97\xba\x12\x7f\x39\xb6\x12\x7f\x39\xb6\xf5\x86\x32\xb8\xf5\x86\x32\xb8\x57\xda\x5c\xb9\xf2\x76\xfa\x3a\x5a\x72\xb1\x3a\x71\x29\x41\x39\x71\x29\x41\x39\x30\x31\x21\xb8\x30\x31\x21\xb8\x5a\xfb\xed\x38\xd7\x3f\xfe\x3a\x0d\x29\xbe\xba\xfd\xe4\x76\xb9\xfd\xe4\x76\xb9\x9d\xa7\x19\xb8\x9d\xa7\x19\xb8\xf0\x02\xc9\xb6\x5a\x0a\x01\x3b\x00\xf5\xc2\x3a\x88\xe0\xbd\x39\x88\xe0\xbd\x39\x70\x5a\x04\xb8\x70\x5a\x04\xb8\xc8\xc5\xe6\xb8\x11\xfb\x02\x3b\x8f\x52\xc0\xba\x54\x6e\xd9\xb9\x54\x6e\xd9\xb9\x95\xbd\xdd\xb7\x95\xbd\xdd\xb7\x88\xde\x74\x39\x0f\xf2\x04\x3b\xe8\xf6\xbb\x3a\xcf\x81\xd5\x39\xcf\x81\xd5\x39\xf0\xf8\x9b\xb7\xf0\xf8\x9b\xb7\x77\x4e\xba\xb9\xdb\xee\x06\x3b\x57\x0a\xa3\xba\x8a\x6f\xad\xb9\x8a\x6f\xad\xb9\x64\xa9\x17\xb7\x64\xa9\x17\xb7\x3e\xed\xf6\x39\x74\xf1\x08\x3b\x7b\xbe\x9a\x3a\x49\xc5\x43\x39\x49\xc5\x43\x39\x6a\xe5\x01\x33\x6a\xe5\x01\x33\x70\xf6\x18\xba\x86\xfa\x0a\x3b\x74\x82\x89\xba\x2f\x1a\xd9\xb8\x2f\x1a\xd9\xb8\xff\xb5\xdc\x36\xff\xb5\xdc\x36\x7e\x89\x36\x3a\x11\x0a\x0d\x3b\xcc\xaf\x76\x3a\x92\xaa\xaf\xb6\x92\xaa\xaf\xb6\xb2\xcc\x6b\x37\xb2\xcc\x6b\x37\x4f\xce\x54\xba\xec\x1f\x0f\x3b\xe9\xf0\x55\xba\x1a\x4c\x31\x39\x1a\x4c\x31\x39\xf8\x1e\xad\x37\xf8\x1e\xad\x37\xd6\x3f\x74\x3a\x16\x3c\x11\x3b\x59\xad\x44\x3a\xda\xa8\x9a\xb9\xda\xa8\x9a\xb9\xd9\x4d\xed\x37\xd9\x4d\xed\x37\xbd\x95\x8a\xba\xc0\x5e\x13\x3b\x58\x7a\x29\xba\x73\x15\xb4\x39\x73\x15\xb4\x39\xc4\x6c\x07\x38\xc4\x6c\x07\x38\x28\x3c\x9c\x3a\xe9\x87\x15\x3b\x93\xbf\x1c\x3a\xc8\xb0\xf7\xb9\xc8\xb0\xf7\xb9\x5b\xad\x15\x38\x5b\xad\x15\x38\xcb\x81\xae\xba\xb2\xb7\x17\x3b\xc8\xdf\xda\xb9\x9f\x51\x13\x3a\x9f\x51\x13\x3a\x89\xad\x17\x38\x89\xad\x17\x38\x80\xc4\xbf\x3a\x1c\xee\x19\x3b\x56\xfb\xb1\x39\x87\x7b\x15\xba\x87\x7b\x15\xba\x0b\xb9\x0a\x38\x0b\xb9\x0a\x38\xb5\x6e\xcf\xba\x37\x2b\x1c\x3b\x27\x9c\x54\xb9\x1e\x2a\xec\x39\x1e\x2a\xec\x39\x3d\x07\xf3\x37\x3d\x07\xf3\x37\xd4\x10\xde\x3a\x04\x6f\x1e\x3b\xf5\x51\xdf\x38\xe2\x5b\xd2\xb9\xe2\x5b\xd2\xb9\x28\x38\xdf\x37\x28\x38\xdf\x37\x84\x72\xeb\xba\xa8\xb9\x20\x3b\x8a\x4f\x3a\xb8\x7c\xc8\x75\x39\x7c\xc8\x75\x39\x29\x09\xb1\x37\x29\x09\xb1\x37\xcf\x80\xf7\x3a\x24\x0b\x23\x3b\x8e\x87\xe6\x37\xb3\xfa\xfc\xb8\xb3\xfa\xfc\xb8\xcc\x3a\x6b\x37\xcc\x3a\x6b\x37\xc3\x9b\x01\xbb\x92\x63\x25\x3b\xd2\x80\x08\xb6\x51\x13\x09\xb9\x51\x13\x09\xb9\x33\x3b\x1a\x36\x33\x3b\x1a\x36\xe1\xa8\x07\x3b\xf3\xc2\x27\x3b\x66\xad\xa5\x38\x81\x25\x5e\x39\x81\x25\x5e\x39\x8e\xfb\x25\xb7\x8e\xfb\x25\xb7\xb6\x87\x0d\xbb\x70\x29\x2a\x3b\x27\x44\x33\xb9\x7d\x1e\xd8\xb9\x7d\x1e\xd8\xb9\x39\x8b\x85\xb7\x39\x8b\x85\xb7\x42\x8d\x12\x3b\x09\x97\x2c\x3b\x84\xc4\x90\x39\x7e\x38\x06\x3a\x7e\x38\x06\x3a\x4c\xc8\xaf\xb7\x4c\xc8\xaf\xb7\xaf\x54\x16\xbb\xce\x0b\x2f\x3b\xa0\x54\x03\xba\x1b\x5d\x25\xba\x1b\x5d\x25\xba\x31\xc6\xfb\xb7\x31\xc6\xfb\xb7\x63\xb7\x18\x3b\xbd\x87\x31\x3b\x2d\x4f\x27\x3a\xb3\x85\x2c\x3a\xb3\x85\x2c\x3a\xf9\x9d\x2e\xb8\xf9\x9d\x2e\xb8\x48\x23\x19\xbb\xf6\x0a\x34\x3b\x95\x87\x5b\xba\xa1\xdd\x27\xba\xa1\xdd\x27\xba\x6c\xe2\x51\xb8\x6c\xe2\x51\xb8\x34\x24\x17\x3b\x76\x95\x36\x3b\xfc\x30\x8f\x3a\x19\xca\xf2\x39\x19\xca\xf2\x39\x8f\x4b\x4e\xb8\x8f\x4b\x4e\xb8\x6e\x1a\x13\xbb\x64\x27\x39\x3b\x04\x32\xab\xba\x60\x51\xc5\xb9\x60\x51\xc5\xb9\x69\xf9\x44\xb8\x69\xf9\x44\xb8\xce\x89\x0d\x3b\xbf\xc0\x3b\x3b\x26\x30\xbe\x3a\x1f\xc0\x2c\x39\x1f\xc0\x2c\x39\x50\xff\x38\xb8\x50\xff\x38\xb8\xcb\x7c\x06\xbb\xb6\x61\x3e\x3b\x41\xc9\xc2\xba\xf0\xaa\xa8\xb8\xf0\xaa\xa8\xb8\x90\x75\x34\xb8\x90\x75\x34\xb8\x0d\x3d\xfc\x3a\x4a\x0a\x41\x3b\x8c\xf5\xc5\x3a\x57\x44\x05\xb8\x57\x44\x05\xb8\x8c\x3f\x23\xb8\x8c\x3f\x23\xb8\xba\x92\xe9\xba\x6d\xba\x43\x3b\x12\x7e\xca\xba\x7a\x01\xdd\x37\x7a\x01\xdd\x37\x36\x0b\xec\xb7\x36\x0b\xec\xb7\xe8\xbc\xd4\x3a\x20\x72\x46\x3b\xa6\xf5\xc4\x3a\xfd\x5e\x59\xb9\xfd\x5e\x59\xb9\xb8\x37\x87\xb7\xb8\x37\x87\xb7\x30\x4c\xbc\xba\xaf\x31\x49\x3b\x85\xb7\xae\xba\xbf\x8d\x83\x39\xbf\x8d\x83\x39\x7b\x17\xbd\xb6\x7b\x17\xbd\xb6\xde\x54\x9f\x3a\x1a\xf9\x4b\x3b\x05\x59\x9e\x3a\x73\xb9\xb0\xb9\x73\xb9\xb0\xb9\xc8\xbd\x16\x37\xc8\xbd\x16\x37\x76\x73\x7c\xba\x60\xc8\x4e\x3b\x6f\x50\x75\xba\x26\x9e\x41\x39\x26\x9e\x41\x39\xd9\x9f\xa9\x37\xd9\x9f\xa9\x37\x5d\x62\x33\x3a\x7f\x9f\x51\x3b\xc9\x53\x16\x3a\xc9\xa0\xea\xb8\xc9\xa0\xea\xb8\xe1\x01\xf7\x37\xe1\x01\xf7\x37\x59\x21\xcb\xb9\xac\x7e\x54\x3b\x70\x2f\x73\xb9\xac\xba\x9a\xb8\xac\xba\x9a\xb8\xe6\xe5\x26\x38\xe6\xe5\x26\x38\x22\x3b\xbd\x38\xe7\x65\x57\x3b\x22\x31\x14\x38\x00\x74\x08\x38\x00\x74\x08\x38\x3b\x94\x4d\x38\x3b\x94\x4d\x38\x76\x88\x49\x39\x45\x55\x5a\x3b\xc4\x51\x23\x39\x23\xa0\x95\xb8\x23\xa0\x95\xb8\xa9\x95\x6a\x38\xa9\x95\x6a\x38\xb7\xc0\xf2\xb9\xc8\x4c\x5d\x3b\x58\xed\xfb\xb9\xa3\x17\x2d\x39\xa3\x17\x2d\x39\x88\x56\x58\x38\x88\x56\x58\x38\x06\xa2\x41\x3a\x92\x4c\x60\x3b\x60\x19\x18\x3a\x79\xb9\x03\xb9\x79\xb9\x03\xb9\xad\x9c\x4d\x38\xad\x9c\x4d\x38\x0e\x42\x84\xba\xa6\x54\x63\x3b\x10\xa1\x68\xba\x03\x67\x4f\x39\x03\x67\x4f\x39\xb9\x19\x4c\x38\xb9\x19\x4c\x38\x00\xd5\xa7\x3a\x18\x65\x66\x3b\xa8\x1c\x5c\x3a\x54\x42\x87\xb9\x54\x42\x87\xb9\xda\x7c\x28\x38\xda\x7c\x28\x38\xd8\x59\xcb\xba\xe9\x7d\x69\x3b\xa6\x68\x2e\xba\x12\x74\x0e\x39\x12\x74\x0e\x39\xd2\x47\x0e\x38\xd2\x47\x0e\x38\xf3\xfa\xec\x3a\x43\x9f\x6c\x3b\xfa\xb9\x39\x3a\xb8\x66\x7d\xb9\xb8\x66\x7d\xb9\xbd\x32\xb3\x37\xbd\x32\xb3\x37\x28\x4e\x05\xbb\x25\xc9\x6f\x3b\xf1\xa9\x2d\xba\xc9\x9d\xa5\x39\xc9\x9d\xa5\x39\x99\xdc\x1a\x37\x99\xdc\x1a\x37\x8b\xbd\x11\x3b\xac\xfb\x72\x3b\x0a\xbe\xcb\x39\x72\x45\xb2\xb9\x72\x45\xb2\xb9\x69\x35\xb8\xb5\x69\x35\xb8\xb5\xd9\x97\x1b\xbb\xd6\x36\x76\x3b\x5c\xcb\x32\xb9\x5b\x66\xbb\x39\x5b\x66\xbb\x39\x43\xdd\x71\xb7\x43\xdd\x71\xb7\xbc\x8d\x22\x3b\xc8\x7a\x79\x3b\xf0\x70\x23\xb5\x2b\xb6\xc9\xb9\x2b\xb6\xc9\xb9\xf9\x41\xe7\xb7\xf9\x41\xe7\xb7\xa9\xc5\x26\xbb\x81\xc7\x7c\x3b\x2e\xed\x8a\x39\xcd\xb4\xb8\x39\xcd\xb4\xb8\x39\xcd\x81\x0c\xb8\xcd\x81\x0c\xb8\xda\xd8\x28\x3b\x8a\x0e\x80\x3b\xc6\x0d\xe0\xb9\xea\x91\x1e\xb9\xea\x91\x1e\xb9\x54\x9f\x1d\xb8\x54\x9f\x1d\xb8\x4b\x06\x29\xbb\xc1\xbd\x81\x3b\x6e\x58\x6d\x39\x7d\x33\x85\x38\x7d\x33\x85\x38\x82\x25\x22\xb8\x82\x25\x22\xb8\x04\xaa\x26\x3b\x7b\x71\x83\x3b\xae\x00\xd8\xb8\x9d\xef\x23\x39\x9d\xef\x23\x39\xfd\x9d\x2d\xb8\xfd\x9d\x2d\xb8\x6d\x59\x21\xbb\xba\x29\x85\x3b\x2d\xc5\x98\x37\x3e\x37\x71\xb9\x3e\x37\x71\xb9\xb9\x40\x2b\xb8\xb9\x40\x2b\xb8\xac\x4f\x19\x3b\x8a\xe6\x86\x3b\x30\xdd\x37\x39\x4a\x70\x9b\x39\x4a\x70\x9b\x39\xc7\x23\x0c\xb8\xc7\x23\x0c\xb8\xe3\x81\x0e\xbb\xea\xa7\x88\x3b\xa4\x49\x80\xb9\xfb\x05\x8a\xb9\xfb\x05\x8a\xb9\x61\xb3\xa5\xb7\x61\xb3\xa5\xb7\xad\xb2\x00\x3b\xe9\x6d\x8a\x3b\xbf\xed\xf8\x38\xa3\xfa\x94\x39\xa3\xfa\x94\x39\x5b\xe8\x5a\xb7\x5b\xe8\x5a\xb7\x65\x31\xe1\xba\x86\x38\x8c\x3b\x9b\xc1\x85\xb8\x1e\x27\x05\xb9\x1e\x27\x05\xb9\xdc\x71\xdb\xb6\xdc\x71\xdb\xb6\xed\xa6\xbe\x3a\xd5\x07\x8e\x3b\x7b\x72\xd0\x38\xe0\x2b\xbe\xb8\xe0\x2b\xbe\xb8\x07\x56\xd7\x34\x07\x56\xd7\x34\x05\xb4\x9a\xba\xd6\xdb\x8f\x3b\x65\xc7\xc8\xb6\xcf\xa1\xde\x39\xcf\xa1\xde\x39\xef\x28\x6c\x37\xef\x28\x6c\x37\xa8\xb0\x6a\x3a\x95\xb4\x91\x3b\x8e\xc6\xff\xb8\x0b\xa6\x1e\xba\x0b\xa6\x1e\xba\xbb\x15\xd2\x37\xbb\x15\xd2\x37\xd9\x76\x1e\xba\x12\x92\x93\x3b\x4d\x17\x24\x39\x49\x82\x50\x3a\x49\x82\x50\x3a\xed\xf2\x02\x38\xed\xf2\x02\x38\x0b\xf6\xa3\x39\x5d\x74\x95\x3b\x18\x7e\x96\xb9\x34\x1b\x58\xba\x34\x1b\x58\xba\xdf\xda\x17\x38\xdf\xda\x17\x38\x79\x17\x8f\xb7\x77\x5b\x97\x3b\x6a\x40\xf9\x39\x38\x8a\x68\x3a\x38\x8a\x68\x3a\xc6\xab\x2a\x38\xc6\xab\x2a\x38\x8e\x19\x95\xb9\x72\x47\x99\x3b\x68\x0c\x17\xba\x5b\xcd\x4e\xba\x5b\xcd\x4e\xba\x77\x62\x2f\x38\x77\x62\x2f\x38\x11\x43\x18\x3a\x4d\x38\x9b\x3b\xb9\x1b\x2d\x3a\x9f\x40\x38\x3a\x9f\x40\x38\x3a\xe7\xd1\x24\x38\xe7\xd1\x24\x38\xc0\xd3\x61\xba\x15\x2e\x9d\x3b\xe5\x93\x44\xba\xd4\x1d\xea\xb9\xd4\x1d\xea\xb9\x06\x3b\x08\x38\x06\x3b\x08\x38\x11\x87\x93\x3a\xca\x28\x9f\x3b\x5f\xf8\x36\x3a\x75\x7b\xcc\x39\x75\x7b\xcc\x39\x3c\xf0\xe2\x37\x3c\xf0\xe2\x37\x03\xdf\xb3\xba\x7c\x28\xa1\x3b\x5f\xa5\xf9\xb9\x42\x15\x86\xb9\x42\x15\x86\xb9\x2b\x18\x9e\x37\x2b\x18\x9e\x37\xf0\xa0\xd1\x3a\x2e\x2d\xa3\x3b\xf3\x56\x70\x39\x9e\xde\x83\x39\x9e\xde\x83\x39\xdb\xb8\x78\x36\xdb\xb8\x78\x36\xb7\xaf\xed\xba\xea\x36\xa5\x3b\xfa\xbd\x13\x39\x27\x93\x36\xb9\x27\x93\x36\xb9\x27\x54\x1c\xb7\x27\x54\x1c\xb7\x8b\x90\x04\x3b\xb1\x45\xa7\x3b\x9b\xcd\x1a\xba\x40\x44\x60\x39\x40\x44\x60\x39\xd2\x89\x85\xb7\xd2\x89\x85\xb7\x92\x3d\x12\xbb\x98\x59\xa9\x3b\x88\xa1\x82\x3a\x5b\x82\xfe\xb8\x5b\x82\xfe\xb8\xb2\xaa\xae\xb7\xb2\xaa\xae\xb7\xbb\x15\x20\x3b\x9d\x72\xab\x3b\x2a\x80\xa7\xba\x7a\x3a\x32\xb8\x7a\x3a\x32\xb8\x7e\x5a\xd9\xb7\x7e\x5a\xd9\xb7\x61\x17\x2e\xbb\xcc\x90\xad\x3b\xf2\x4c\xc1\x3a\x92\x29\x33\x39\x92\x29\x33\x39\xa7\xfa\x13\xb8\xa7\xfa\x13\xb8\xac\xfb\x3b\x3b\x26\xb4\xaf\x3b\xdc\xf7\xcf\xba\xd9\xd1\x20\xb9\xd9\xd1\x20\xb9\x6e\x5e\x1b\xb8\x6e\x5e\x1b\xb8\x82\xd1\x49\xbb\xb9\xdc\xb1\x3b\x7e\x16\xb6\x3a\x5b\xa5\xc6\x39\x5b\xa5\xc6\x39\x2e\xb2\x14\xb8\x2e\xb2\x14\xb8\xd5\x77\x57\x3b\x87\x0a\xb4\x3b\x3a\x17\x6d\xba\xe1\x4c\x3c\xba\xe1\x4c\x3c\xba\x23\xad\x06\xb8\x23\xad\x06\xb8\x35\x77\x64\xbb\x9d\x3d\xb6\x3b\xb9\x24\x96\x39\x03\xf9\x8f\x3a\x03\xf9\x8f\x3a\x2e\x93\xf6\xb7\x2e\x93\xf6\xb7\x01\x01\x71\x3b\xfc\x75\xb8\x3b\x9c\xc2\x4d\x39\x06\x2d\x96\xba\x06\x2d\x96\xba\x12\x5b\xba\xb7\x12\x5b\xba\xb7\xfe\xc3\x7d\xbb\xb4\xb3\xba\x3b\xd6\xba\x29\xba\x6e\xaf\xa9\x3a\x6e\xaf\xa9\x3a\xfb\x31\x48\xb7\xfb\x31\x48\xb7\x1f\x55\x85\x3b\xc5\xf6\xbc\x3b\xe5\x6c\x96\x3a\x8a\x85\xb9\xba\x8a\x85\xb9\xba\xe7\x33\x8a\x34\xe7\x33\x8a\x34\xe8\xc9\x8b\xbb\x3a\x3f\xbf\x3b\x12\x71\xb4\xba\x77\x8d\xab\x3a\x77\x8d\xab\x3a\xfd\x69\x22\x37\xfd\x69\x22\x37\x1a\x5a\x92\x3b\x11\x8d\xc1\x3b\x06\x01\xa8\x3a\xc3\x3d\x71\xba\xc3\x3d\x71\xba\x85\xf5\xbc\x37\x85\xf5\xbc\x37\x6d\xc9\x98\xbb\x61\xe0\xc3\x3b\x2f\xc5\x97\xba\xc0\x4b\x16\x3a\xc0\x4b\x16\x3a\x28\xee\x1a\x38\x28\xee\x1a\x38\xab\x6e\x9e\x3b\x2a\x39\xc6\x3b\x07\xc6\x7e\x3a\x18\x59\x52\xb9\x18\x59\x52\xb9\xa3\x74\x34\x38\xa3\x74\x34\x38\x30\xc6\xa2\xbb\x70\x97\xc8\x3b\x94\xf4\x00\xba\xe2\x53\xbc\xb9\xe2\x53\xbc\xb9\xf3\x41\x30\x38\xf3\x41\x30\x38\x5f\x8b\xa5\x3b\x36\xfb\xca\x3b\x96\xa4\x86\x38\xfe\x64\x33\x3a\xfe\x64\x33\x3a\x53\x34\x33\x38\x53\x34\x33\x38\x40\x8d\xa6\xbb\x8d\x64\xcd\x3b\x72\xb8\x78\x39\xb7\x16\x5f\xba\xb7\x16\x5f\xba\xfd\x6e\x32\x38\xfd\x6e\x32\x38\x1c\x8d\xa5\x3b\x76\xd3\xcf\x3b\xfc\x54\x2e\xba\xd7\xad\x6a\x3a\xd7\xad\x6a\x3a\x96\x62\x35\x38\x96\x62\x35\x38\x60\xb2\xa2\xbb\xfd\x47\xd2\x3b\x66\x61\x90\x3a\x1d\x16\x61\xba\x1d\x16\x61\xba\x8d\x6c\x05\x38\x8d\x6c\x05\x38\x1e\x4c\x9e\x3b\x22\xc2\xd4\x3b\xb8\x8d\xb2\xba\x29\x0d\x27\x3a\x29\x0d\x27\x3a\x8f\x70\x93\x37\x8f\x70\x93\x37\x1b\x4e\x98\xbb\xf4\x41\xd7\x3b\xa4\xd9\xda\x3a\x0e\x05\xc5\xb9\x0e\x05\xc5\xb9\xc3\x0f\xa7\x36\xc3\x0f\xa7\x36\x9f\x57\x90\x3b\x72\xc7\xd9\x3b\xa0\x18\x02\xbb\xa0\x40\x1b\xb9\xa0\x40\x1b\xb9\xd4\xf7\x7a\xb6\xd4\xf7\x7a\xb6\xfa\x21\x86\xbb\xa8\x52\xdc\x3b\x93\x51\xdc\x3a\xf9\xbf\x3f\x3a\xf9\xbf\x3f\x3a\x79\xe3\x7a\xb7\x79\xe3\x7a\xb7\x58\x8e\x72\x3b\x96\xe3\xde\x3b\x46\x58\x84\xba\xac\x15\xa1\xba\xac\x15\xa1\xba\x0d\x28\xe0\xb7\x0d\x28\xe0\xb7\x0b\x61\x52\xbb\x4a\x7a\xe1\x3b\xe1\xce\x08\x3a\xbd\xed\xae\x3a\xbd\xed\xae\x3a\x15\x28\x0b\xb8\x15\x28\x0b\xb8\xd2\xf9\x2a\x3b\xc4\x16\xe4\x3b\xab\x89\xce\x38\xb1\x74\xe8\xba\xb1\x74\xe8\xba\xf4\x58\x18\xb8\xf4\x58\x18\xb8\x25\xfc\xfa\xba\x13\xb9\xe6\x3b\x53\xcc\xa2\xba\x72\xb4\x07\x3b\x72\xb4\x07\x3b\x96\x0f\x24\xb8\x96\x0f\x24\xb8\x88\x4a\x97\x3a\x34\x61\xe9\x3b\x71\xa4\x06\x3b\xcb\x4c\x01\xbb\xcb\x4c\x01\xbb\x61\xf1\x0e\xb8\x61\xf1\x0e\xb8\xc9\xf4\xb3\xb9\x36\x0f\xec\x3b\x2b\x0e\x24\xbb\x03\xa4\xf8\x3a\x03\xa4\xf8\x3a\x39\x5f\xf4\xb7\x39\x5f\xf4\xb7\x56\xa5\x04\xba\x19\xc3\xee\x3b\x88\x7a\x4b\x3b\x05\x78\x0d\xbb\x05\x78\x0d\xbb\x65\xd1\xda\xb7\x65\xd1\xda\xb7\x60\xd8\xb5\x3a\xe6\x7c\xf1\x3b\x7c\xef\x75\xbb\x4f\x8d\x01\x3b\x4f\x8d\x01\x3b\xeb\x34\x57\xb7\xeb\x34\x57\xb7\x6d\xd3\x16\xbb\x9d\x3c\xf4\x3b\x4a\x39\x77\x3b\x5a\x37\xca\xba\x5a\x37\xca\xba\x99\x20\x0e\x37\x99\x20\x0e\x37\xf7\x77\x54\x3b\x73\x82\xf7\x3b\xc7\x14\x50\xbb\x14\x7b\x92\x3a\x14\x7b\x92\x3a\x2b\x5e\x9e\x37\x2b\x5e\x9e\x37\x2d\x29\x8a\xbb\x68\x4e\xfb\x3b\x29\x97\x2a\x3b\xbf\xae\x60\xba\xbf\xae\x60\xba\xe6\x2d\x03\x38\xe6\x2d\x03\x38\x0f\xe3\xab\x3b\x83\x47\xfe\x3b\x48\xd0\xee\xba\x87\x64\x83\x39\x87\x64\x83\x39\x0b\x0c\x3a\x38\x0b\x0c\x3a\x38\x4c\xbf\xcf\xbb\xe2\x36\x00\x3c\xbb\xc1\x19\x3a\x96\x05\x8c\x39\x96\x05\x8c\x39\x7e\xee\x57\x38\x7e\xee\x57\x38\xa5\xb4\xf4\x3b\x70\x7c\x01\x3c\xcc\x65\x74\x3a\x69\xd9\x1f\xba\x69\xd9\x1f\xba\x0e\x8e\x40\x38\x0e\x8e\x40\x38\x9a\x5e\x0c\xbc\x6b\xf4\x02\x3c\x82\x6d\x1c\xbb\x80\x89\x8e\x3a\x80\x89\x8e\x3a\x4b\x76\x31\x38\x4b\x76\x31\x38\x90\x34\x1d\x3c\xbe\x6f\x04\x3c\xc0\x7b\x5e\x3b\xb6\xce\xcf\xba\xb6\xce\xcf\xba\x12\x11\x1c\x38\x12\x11\x1c\x38\xfb\xad\x2c\xbc\x6b\xee\x05\x3c\x0a\xe0\x89\xbb\xb5\x6b\xc4\x3a\xb5\x6b\xc4\x3a\xc1\x6e\xe7\x37\xc1\x6e\xe7\x37\x11\xd2\x3a\x3c\x79\x70\x07\x3c\x15\x41\xa1\x3b\x0c\x36\x8d\xba\x0c\x36\x8d\xba\xa1\x2b\x70\x37\xa1\x2b\x70\x37\x98\xc4\x47\xbc\xea\xf5\x08\x3c\x1d\xbe\xab\xbb\x30\xe5\x3a\x3a\x30\xe5\x3a\x3a\xa6\xcf\xeb\x36\xa6\xcf\xeb\x36\x9a\xc2\x53\x3c\xc1\x7e\x0a\x3c\x49\xb8\xa7\x3b\xa3\xb4\xe1\xb9\xa3\xb4\xe1\xb9\x3e\xa9\xad\xb6\x3e\xa9\xad\xb6\x33\xfb\x5e\xbc\x00\x0b\x0c\x3c\xb8\x27\xa4\xbb\x04\x6b\x28\x38\x04\x6b\x28\x38\xa7\x2c\xb1\xb7\xa7\x2c\xb1\xb7\x6b\x4c\x69\x3c\xb4\x9a\x0d\x3c\x2c\x47\xa2\x3b\x6c\xe3\xf9\x39\x6c\xe3\xf9\x39\xef\x66\x1e\xb8\xef\x66\x1e\xb8\x15\x20\x72\xbc\xdf\x2d\x0f\x3c\xf6\x67\x92\xbb\x92\x3b\x89\xba\x92\x3b\x89\xba\xbe\x8c\x41\xb8\xbe\x8c\x41\xb8\x17\xd8\x78\x3c\x8a\xc4\x10\x3c\xe2\x66\x64\x3b\xe8\x74\xfd\x3a\xe8\x74\xfd\x3a\x08\x3c\x44\xb8\x08\x3c\x44\xb8\x34\xf4\x7c\xbc\xb5\x5e\x12\x3c\x4d\x01\x26\xbb\x3d\xbf\x2f\xbb\x3d\xbf\x2f\xbb\x60\xc7\x3a\xb8\x60\xc7\x3a\xb8\x9d\x07\x7e\x3c\x75\xfc\x13\x3c\x1c\x9d\xf8\x3a\x58\xe6\x4d\x3b\x58\xe6\x4d\x3b\x9e\x85\x37\xb8\x9e\x85\x37\xb8\xa1\x0b\x7c\xbc\xc8\x9d\x15\x3c\x71\xbc\xa1\xba\x0c\x0d\x56\xbb\x0c\x0d\x56\xbb\x43\x96\x14\xb8\x43\x96\x14\xb8\xb2\x82\x77\x3c\xb6\x42\x17\x3c\xf1\x94\x11\x3a\x02\x7a\x50\x3b\x02\x7a\x50\x3b\x98\xdf\xc8\xb7\x98\xdf\xc8\xb7\x09\x26\x71\xbc\x40\xeb\x18\x3c\xc8\x8e\x28\xb9\x40\x3a\x32\xbb\x40\x3a\x32\xbb\xf9\x78\x41\xb7\xf9\x78\x41\xb7\x7a\xb3\x69\x3c\x68\x97\x1a\x3c\x10\x32\x42\x39\xd9\xa5\x18\x3b\xd9\xa5\x18\x3b\xe8\x02\xda\xb5\xe8\x02\xda\xb5\x20\x98\x61\xbc\x31\x47\x1c\x3c\xfe\x30\x01\xba\xd9\x28\xdf\xba\xd9\x28\xdf\xba\x19\x6f\x25\x37\x19\x6f\x25\x37\x26\xf2\x58\x3c\x98\xfa\x1d\x3c\xfe\x87\x93\x3a\x3c\x51\x54\x3a\x3c\x51\x54\x3a\x35\xf1\xbb\x37\x35\xf1\xbb\x37\x1a\x85\x4f\xbc\x9c\xb1\x1f\x3c\xe1\x9e\x03\xbb\x30\x39\x5a\x39\x30\x39\x5a\x39\x6e\xfa\x03\x38\x6e\xfa\x03\x38\x0e\xdb\x44\x3c\x5e\x6c\x21\x3c\x0b\xe6\x49\x3b\xf2\xba\x47\xba\xf2\xba\x47\xba\x73\xb6\x11\x38\x73\xb6\x11\x38\xf3\x96\x38\xbc\xdd\x2a\x23\x3c\x7e\xb6\x8d\xbb\x12\x4e\xbe\x3a\x12\x4e\xbe\x3a\x40\xd0\x19\x38\x40\xd0\x19\x38\x46\xda\x2a\x3c\x3a\xed\x24\x3c\xb0\x8d\xb4\x3b\xe2\xbe\x08\xbb\xe2\xbe\x08\xbb\xe4\x46\x16\x38\xe4\x46\x16\x38\x47\x18\x1c\xbc\x76\xb3\x26\x3c\xa1\x8a\xdb\xbb\xdb\xb8\x13\x3b\xdb\xb8\x13\x3b\xc5\x46\xf3\x37\xc5\x46\xf3\x37\x0c\x07\x0d\x3c\x52\x7d\x28\x3c\x1a\x2d\x02\x3c\x09\xc4\xe9\xba\x09\xc4\xe9\xba\x15\xfc\x89\x37\x15\xfc\x89\x37\xe1\xf3\xfc\xbb\xcd\x4a\x2a\x3c\x5f\x5e\x15\xbc\xe3\xb0\xb3\x3a\xe3\xb0\xb3\x3a\x6e\x37\xa8\x36\x6e\x37\xa8\x36\x52\x1f\xe2\x3b\x39\x1c\x2c\x3c\x71\x0e\x25\x3c\x1d\x2d\x7d\xba\x1d\x2d\x7d\xba\x43\x35\x37\xb6\x43\x35\x37\xb6\xa4\x7b\xc9\xbb\x95\xf1\x2d\x3c\xf1\x0b\x36\xbc\x5c\xb6\xab\x39\x5c\xb6\xab\x39\x23\x74\x56\xb7\x23\x74\x56\xb7\xda\x1b\xb2\x3b\xca\xca\x2f\x3c\x06\x95\x4a\x3c\x82\x07\x1c\x3a\x82\x07\x1c\x3a\xa6\xaf\xc6\xb7\xa6\xaf\xc6\xb7\x5f\x84\x9a\xbb\xd9\xa7\x31\x3c\x16\x44\x5f\xbc\x1c\x28\x93\xba\x1c\x28\x93\xba\x65\xc2\x17\xb8\x65\xc2\x17\xb8\x4f\x2e\x81\x3b\xd3\x88\x33\x3c\x30\x31\x70\x3c\xba\xeb\xd5\x3a\xba\xeb\xd5\x3a\x67\x96\x28\xb8\x67\x96\x28\xb8\xf9\x75\x4a\xbb\xba\x6d\x35\x3c\x74\x71\x81\xbc\x87\x01\x18\xbb\x87\x01\x18\xbb\x9d\xc4\x17\xb8\x9d\xc4\x17\xb8\xd1\x26\x0e\x3b\x9a\x56\x37\x3c\x52\x38\x8c\x3c\x38\x39\x43\x3b\x38\x39\x43\x3b\x59\x3a\xfa\xb7\x59\x3a\xfa\xb7\x1e\x24\xa0\xba\x73\x43\x39\x3c\x0b\x88\x93\xbc\xf0\x24\x46\xbb\xf0\x24\x46\xbb\xe7\x6e\xe2\xb7\xe7\x6e\xe2\xb7\xc9\x35\xa1\x39\x4b\x34\x3b\x3c\xd2\x70\x96\x3c\x98\xa9\x27\x3b\x98\xa9\x27\x3b\xa6\xa3\x9a\xb7\xa6\xa3\x9a\xb7\xf3\x93\x0a\x3a\x20\x29\x3d\x3c\xa3\xbb\x96\xbc\xc4\x61\xf5\xba\xc4\x61\xf5\xba\x95\xa5\xf3\xb6\x95\xa5\xf3\xb6\xeb\xd8\xa5\xba\x02\x22\x3f\x3c\x85\xb0\x91\x3c\xdf\x1c\xa9\x3a\xdf\x1c\xa9\x3a\x39\x55\xf0\x36\x39\x55\xf0\x36\x70\x2e\xfa\x3a\xf1\x1e\x41\x3c\xd2\x4e\x85\xbc\x30\x16\xa7\xb9\x30\x16\xa7\xb9\x44\x8c\xa6\x37\x44\x8c\xa6\x37\x4e\xd7\x22\xbb\xf5\x1f\x43\x3c\x0b\x94\x6b\x3c\x3e\x92\x97\xba\x3e\x92\x97\xba\x70\x4e\x08\x38\x70\x4e\x08\x38\xc0\xa5\x46\x3b\x0f\x25\x45\x3c\xac\xbb\x46\xbc\xa1\x08\x1e\x3b\xa1\x08\x1e\x3b\x1b\x85\x35\x38\x1b\x85\x35\x38\x54\xb0\x69\xbb\x4f\x2e\x47\x3c\xf0\xc9\x1a\x3c\x4d\x94\x5d\xbb\x4d\x94\x5d\xbb\x59\x6d\x4d\x38\x59\x6d\x4d\x38\xda\x8f\x85\x3b\xb6\x3b\x49\x3c\x60\x62\xd9\xbb\x37\x30\x96\x3b\x37\x30\x96\x3b\x38\xc2\x49\x38\x38\xc2\x49\x38\xf2\xdf\x93\xbb\x46\x4d\x4b\x3c\x41\x7f\x88\x3b\x01\x8f\xb8\xbb\x01\x8f\xb8\xbb\x06\xe5\x24\x38\x06\xe5\x24\x38\x41\xf0\x9d\x3b\xff\x62\x4d\x3c\xad\x08\x08\xbb\x65\x2a\xbf\x3b\x65\x2a\xbf\x3b\x95\xaa\xe4\x37\x95\xaa\xe4\x37\xa0\xdb\xa1\xbb\xec\x7c\x4f\x3c\xee\xc1\x53\x39\xba\xd5\xb7\xbb\xba\xd5\xb7\xbb\x5c\x13\x81\x37\x5c\x13\x81\x37\xb1\x4c\x9e\x3b\x0d\x9b\x51\x3c\x0e\x6a\xd1\x3a\xbd\xfa\xa5\x3b\xbd\xfa\xa5\x3b\x41\xf1\x02\xb5\x41\xf1\x02\xb5\xd2\x0f\x93\xbb\x6e\xbd\x53\x3c\x7b\xa2\x4c\xbb\xe3\x5c\x85\xbb\xe3\x5c\x85\xbb\xd4\x6a\x7a\xb7\xd4\x6a\x7a\xb7\x2d\x7a\x81\x3b\x11\xe4\x55\x3c\x7d\x10\x87\x3b\x3a\xe8\x2f\x3b\x3a\xe8\x2f\x3b\x09\xca\xd3\xb7\x09\xca\xd3\xb7\xd5\x76\x57\xbb\x08\x0f\x58\x3c\x78\xdc\x9c\xbb\xf7\x37\xca\xba\xf7\x37\xca\xba\x35\xf7\x1d\xb8\x35\xf7\x1d\xb8\x70\x40\x27\x3b\x52\x3e\x5a\x3c\xe7\x22\xb6\x3b\x24\xe4\xff\x39\x24\xe4\xff\x39\x8b\x15\x45\xb8\x8b\x15\x45\xb8\xe1\x15\xe8\xba\xe6\x71\x5c\x3c\x41\xed\xce\xbb\x81\xdb\xd5\x39\x81\xdb\xd5\x39\xaa\x97\x52\xb8\xaa\x97\x52\xb8\x33\x33\x79\x3a\xc1\xa9\x5e\x3c\x70\x90\xd5\x3b\xf3\x3b\xac\xba\xf3\x3b\xac\xba\xb6\x6e\x4a\xb8\xb6\x6e\x4a\xb8\x5d\x65\x79\xb8\x07\xe6\x60\x3c\x29\x99\xd0\xbb\x20\xfa\x14\x3b\x20\xfa\x14\x3b\xc4\x9c\x28\xb8\xc4\x9c\x28\xb8\xf9\xd6\x79\xba\xb6\x26\x63\x3c\x95\xd8\xb9\x3b\x3b\xfb\x3e\xbb\x3b\xfb\x3e\xbb\x71\xca\xf0\xb7\x71\xca\xf0\xb7\x43\x35\x0a\x3b\xca\x6b\x65\x3c\xab\x4a\x8a\xbb\x07\x34\x0c\x3b\x07\x34\x0c\x3b\xda\x56\x86\xb7\xda\x56\x86\xb7\xf0\x2a\x5e\xbb\x41\xb5\x67\x3c\xc0\x6b\x08\x3b\xbf\xcb\x3a\xba\xbf\xcb\x3a\xba\x18\x56\x83\xb6\x18\x56\x83\xb6\xf2\x5f\x9b\x3b\x31\x03\x6a\x3c\x9c\x18\xa3\x39\x06\x57\x5b\xb9\x06\x57\x5b\xb9\xec\xb7\xc8\x36\xec\xb7\xc8\x36\x45\xb9\xc7\xbb\x98\x55\x6c\x3c\x0d\x32\x38\xbb\x93\x1c\xf4\x39\x93\x1c\xf4\x39\x29\x46\xa9\x37\x29\x46\xa9\x37\x2a\x55\xf2\x3b\x7e\xac\x6e\x3c\x93\xc9\xa7\x3b\x2b\xd7\xb7\xba\x2b\xd7\xb7\xba\xc1\x4b\x22\x38\xc1\x4b\x22\x38\x57\xf9\x0c\xbc\xe2\x07\x71\x3c\x78\x77\xd0\xbb\xfe\xe0\x3c\x3b\xfe\xe0\x3c\x3b\xf4\xb2\x2c\x38\xf4\xb2\x2c\x38\x75\x09\x1f\x3c\xd1\x67\x73\x3c\xc5\x95\xd6\x3b\xb2\xeb\x7a\xbb\xb2\xeb\x7a\xbb\x83\x98\x1f\x38\x83\x98\x1f\x38\x1a\x3b\x2f\xbc\x4a\xcc\x75\x3c\x44\x72\xdb\xbb\xfb\xce\x65\x3b\xfb\xce\x65\x3b\xf9\xc2\x02\x38\xf9\xc2\x02\x38\x0c\x13\x3e\x3c\x54\x35\x78\x3c\xd4\x9f\xf5\x3b\x1d\xa1\x49\xbb\x1d\xa1\x49\xbb\x9b\x96\xa1\x37\x9b\x96\xa1\x37\xc4\x32\x4c\xbc\xf0\xa2\x7a\x3c\x8e\xeb\x05\xbc\xa8\x57\x55\x3b\xa8\x57\x55\x3b\x16\x89\x9b\x35\x16\x89\x9b\x35\xa4\xc6\x59\x3c\x2a\x15\x7d\x3c\xf5\xec\x05\x3c\x62\x0d\x87\xbb\x62\x0d\x87\xbb\x62\x2c\xaa\xb7\x62\x2c\xaa\xb7\xd5\x49\x66\xbc\x05\x8c\x7f\x3c\xdf\x89\xf1\xbb\xaf\x46\x91\x3b\xaf\x46\x91\x3b\xac\x58\x05\xb8\xac\x58\x05\xb8\x5a\xbc\x70\x3c\xc4\x03\x81\x3c\x96\xcd\xcd\x3b\x03\xa1\x82\xbb\x03\xa1\x82\xbb\xdd\xe7\x23\xb8\xdd\xe7\x23\xb8\xa6\xfc\x77\xbc\xd8\x43\x82\x3c\xca\xfe\xa5\xbb\x3c\x74\x6b\x3b\x3c\x74\x6b\x3b\x9d\x5e\x35\xb8\x9d\x5e\x35\xb8\x59\x28\x7b\x3c\x47\x86\x83\x3c\x5b\xfd\x5d\x3b\xa2\x13\x58\xbb\xa2\x13\x58\xbb\x12\x9c\x2e\xb8\x12\x9c\x2e\xb8\x3c\x13\x7a\xbc\x10\xcb\x84\x3c\xf4\xb4\xd5\xba\xdc\x0a\x25\x3b\xdc\x0a\x25\x3b\xaa\x85\x0b\xb8\xaa\x85\x0b\xb8\x33\x0d\x75\x3c\x34\x12\x86\x3c\x2e\xf2\x98\x39\x75\x1c\x93\xba\x75\x1c\x93\xba\x51\x9a\xd0\xb7\x51\x9a\xd0\xb7\xa7\x09\x6d\xbc\xb4\x5b\x87\x3c\xe1\x43\x1c\x3a\xd7\xb7\x0b\xba\xd7\xb7\x0b\xba\xe8\xaa\x89\xb7\xe8\xaa\x89\xb7\x6e\x0a\x63\x3c\x98\xa7\x88\x3c\x09\xa4\xb2\xba\xdd\x13\x0b\x3b\xdd\x13\x0b\x3b\x4b\xc9\x0b\xb7\x4b\xc9\x0b\xb7\x3f\xec\x57\xbc\xdf\xf5\x89\x3c\xb8\xc2\x0b\x3b\xbb\x2a\x45\xbb\xbb\x2a\x45\xbb\x43\xd7\x90\x36\x43\xd7\x90\x36\x32\x28\x4c\x3c\x8e\x46\x8b\x3c\xb9\x8e\x3d\xbb\x21\x42\x59\x3b\x21\x42\x59\x3b\x74\xcc\x93\x37\x74\xcc\x93\x37\x03\xd1\x3f\xbc\xa6\x99\x8c\x3c\x2e\x6a\x6d\x3b\x0e\x55\x67\xbb\x0e\x55\x67\xbb\xc6\xfb\xfd\x37\xc6\xfb\xfd\x37\x7b\xb3\x32\x3c\x27\xef\x8d\x3c\xf9\x76\x73\xbb\xde\xec\x4f\x3b\xde\xec\x4f\x3b\x09\xa6\x1c\x38\x09\xa6\x1c\x38\x29\xde\x24\xbc\x14\x47\x8f\x3c\x5f\x76\x4e\x3b\x92\x7c\xca\xba\x92\x7c\xca\xba\xfa\xbc\x30\x38\xfa\xbc\x30\x38\xe3\x97\x16\x3c\x72\xa1\x90\x3c\x10\x03\xfc\xba\x65\xf8\x35\xba\x65\xf8\x35\xba\xfc\xd2\x31\x38\xfc\xd2\x31\x38\x6e\x91\x08\xbc\x41\xfe\x91\x3c\xe0\xa7\xbc\x39\x3b\x03\x35\x3b\x3b\x03\x35\x3b\x54\x3f\x10\x38\x54\x3f\x10\x38\xa1\x4c\xf7\x3b\x86\x5d\x93\x3c\x6a\xee\xd0\x3a\xeb\x45\xa3\xbb\xeb\x45\xa3\xbb\x93\xcb\x7e\x37\x93\xcb\x7e\x37\x7b\xb3\xe1\xbb\x3e\xbf\x94\x3c\x27\x17\x6b\xbb\x19\xa4\xeb\x3b\x19\xa4\xeb\x3b\xf8\x90\xb2\xb6\xf8\x90\xb2\xb6\x76\xf6\xd1\x3b\x71\x23\x96\x3c\x12\xa0\xa3\x3b\xaa\x8b\x04\xbc\xaa\x8b\x04\xbc\xf5\x8b\xc4\xb7\xf5\x8b\xc4\xb7\xb4\xe1\xc8\xbb\x1d\x8a\x97\x3c\x8a\x93\xae\xbb\x72\xa1\xff\x3b\x72\xa1\xff\x3b\xe2\x78\x1c\xb8\xe2\x78\x1c\xb8\x92\x40\xc6\x3b\x48\xf3\x98\x3c\x9d\x6e\xa5\x3b\x7b\xf0\xea\xbb\x7b\xf0\xea\xbb\x5f\x20\x37\xb8\x5f\x20\x37\xb8\x89\x2b\xc9\xbb\xf3\x5e\x9a\x3c\xaf\x33\x8d\xbb\x17\xc0\xd4\x3b\x17\xc0\xd4\x3b\xd9\x76\x37\xb8\xd9\x76\x37\xb8\xdb\x29\xd0\x3b\x1f\xcd\x9b\x3c\xe1\xc3\x42\x3b\x93\x31\x99\xbb\x93\x31\x99\xbb\xad\xaf\x2b\xb8\xad\xaf\x2b\xb8\xfe\xfc\xd9\xbb\xcd\x3d\x9d\x3c\x60\x4d\xbc\xba\xfa\xd0\x17\x3b\xfa\xd0\x17\x3b\x89\x2f\x0f\xb8\x89\x2f\x0f\xb8\xfd\x86\xe5\x3b\x02\xb1\x9e\x3c\xe5\x2e\x89\x3a\x0a\x0d\x48\xba\x0a\x0d\x48\xba\xcc\x9e\xd4\xb7\xcc\x9e\xd4\xb7\xf3\x76\xf2\xbb\xc0\x26\xa0\x3c\xb0\xda\xed\xba\x93\x31\xa1\x39\x93\x31\xa1\x39\x0d\x6a\x6e\xb7\x0d\x6a\x6e\xb7\x79\x8a\x00\x3c\x07\x9f\xa1\x3c\x2c\xfb\x28\x3b\xde\xa0\x21\x3a\xde\xa0\x21\x3a\x9c\xeb\x2f\xb6\x9c\xeb\x2f\xb6\x86\xbd\x08\xbc\xd9\x19\xa3\x3c\x44\x2a\x53\xbb\x66\x16\xfa\xba\x66\x16\xfa\xba\x02\x35\x25\x37\x02\x35\x25\x37\xe9\x96\x11\x3c\x3c\x97\xa4\x3c\xda\xac\x94\x3b\x64\x69\x20\x3b\x64\x69\x20\x3b\xab\xb0\xaf\x37\xab\xb0\xaf\x37\xaf\xab\x1a\xbc\x2f\x17\xa6\x3c\x64\x6b\xc3\xbb\xac\x84\x06\xbb\xac\x84\x06\xbb\x66\x8f\x09\x38\x66\x8f\x09\x38\xe2\x2a\x23\x3c\xb6\x99\xa7\x3c\xcb\x57\xdb\x3b\x84\xfd\x00\x3b\x84\xfd\x00\x3b\x3c\x09\x2d\x38\x3c\x09\x2d\x38\xa1\x24\x2a\xbc\xce\x1e\xa9\x3c\x43\xc3\xda\xbb\x5e\x0c\x0a\xbb\x5e\x0c\x0a\xbb\x26\x51\x36\x38\x26\x51\x36\x38\x0e\xb2\x2e\x3c\x7f\xa6\xaa\x3c\x0d\xdc\xc7\x3b\x67\x88\x12\x3b\x67\x88\x12\x3b\x3f\x95\x13\x38\x3f\x95\x13\x38\x50\x36\x30\xbc\xc7\x30\xac\x3c\xc8\x9c\xa2\xbb\x96\x88\x2d\xbb\x96\x88\x2d\xbb\x54\x09\xcf\x37\x54\x09\xcf\x37\x1b\x6b\x2e\x3c\xaa\xbd\xad\x3c\x74\xd1\x65\x3b\x41\x45\x84\x3b\x41\x45\x84\x3b\x80\xc1\x5f\x37\x80\xc1\x5f\x37\xf2\x5b\x29\xbc\x28\x4d\xaf\x3c\xe0\x61\x0f\xbb\xf7\x5f\xae\xbb\xf7\x5f\xae\xbb\xba\x1b\xba\xb5\xba\x1b\xba\xb5\x69\x31\x21\x3c\x46\xdf\xb0\x3c\xe9\x57\xa9\x3a\xac\x51\xba\x3b\xac\x51\xba\x3b\xe9\xbe\xa0\xb7\xe9\xbe\xa0\xb7\x59\x39\x16\xbc\x04\x74\xb2\x3c\x52\x62\x36\xba\xf7\xd0\xba\xbb\xf7\xd0\xba\xbb\x14\x0d\x10\xb8\x14\x0d\x10\xb8\xf1\xbb\x08\x3c\x63\x0b\xb4\x3c\xbd\x6a\x82\x39\x26\x14\xbd\x3b\x26\x14\xbd\x3b\xff\x37\x32\xb8\xff\x37\x32\xb8\x7d\xbb\xf1\xbb\x63\xa5\xb5\x3c\x48\x20\x50\x38\xa0\x86\xb2\xbb\xa0\x86\xb2\xbb\x21\xaf\x27\xb8\x21\xaf\x27\xb8\xe3\x38\xcd\x3b\x0b\x42\xb7\x3c\x10\xc6\x62\xb9\x25\xf8\x86\x3b\x25\xf8\x86\x3b\x2f\xd8\xfb\xb7\x2f\xd8\xfb\xb7\x96\x34\xa4\xbb\x5b\xe1\xb8\x3c\x55\xf8\x4d\x38\xfa\x89\xfb\xba\xfa\x89\xfb\xba\xa3\x33\x98\xb7\xa3\x33\x98\xb7\x25\x56\x6e\x3b\x52\x83\xba\x3c\xdc\xdd\x0f\x39\x02\xd2\x27\xb9\x02\xd2\x27\xb9\x97\xaf\x6b\xb6\x97\xaf\x6b\xb6\x64\x5d\x0e\xbb\xf1\x27\xbc\x3c\xd2\x65\x5b\x39\x09\x73\x6a\x3a\x09\x73\x6a\x3a\xea\xd8\x30\x37\xea\xd8\x30\x37\xc8\x05\x2d\x3a\x3d\xcf\xbd\x3c\x5f\x6c\x0a\xba\xc6\xc5\x71\xba\xc6\xc5\x71\xba\xee\xf9\xb3\x37\xee\xf9\xb3\x37\x3e\xbc\x5c\x3a\x37\x79\xbf\x3c\xae\xb6\x8c\xb7\x02\x19\x92\x3a\x02\x19\x92\x3a\x73\xde\x06\x38\x73\xde\x06\x38\x5d\x16\x15\xbb\xe0\x25\xc1\x3c\x94\xc9\xcf\x3a\xe9\xe3\x92\xba\xe9\xe3\x92\xba\x7b\x57\x2e\x38\x7b\x57\x2e\x38\xbe\x18\x6b\x3b\x38\xd5\xc2\x3c\xb1\x19\x6d\xbb\xb3\x11\xe1\x38\xb3\x11\xe1\x38\x19\x01\x59\x38\x19\x01\x59\x38\x98\x5d\x9b\xbb\x44\x87\xc4\x3c\x1e\xe4\xae\x3b\x49\x7e\x8a\x3a\x49\x7e\x8a\x3a\x4c\x8b\x57\x38\x4c\x8b\x57\x38\xa3\xda\xba\x3b\x03\x3c\xc6\x3c\x44\x2a\xcd\xbb\x63\xc4\x04\xbb\x63\xc4\x04\xbb\xba\x88\x3d\x38\xba\x88\x3d\x38\x76\x5f\xd3\xbb\x77\xf3\xc7\x3c\x7c\x3d\xbb\x3b\xb7\xa1\x31\x3b\xb7\xa1\x31\x3b\x89\x42\xf6\x37\x89\x42\xf6\x37\x32\x61\xe4\x3b\xa0\xad\xc9\x3c\x7d\xbb\x80\xbb\xbf\x58\x48\xbb\xbf\x58\x48\xbb\x80\x29\xde\x36\x80\x29\xde\x36\x85\xc9\xed\xbb\x81\x6a\xcb\x3c\xec\x99\x9b\x3a\x9b\x24\x1e\x3b\x9b\x24\x1e\x3b\x78\x86\x8a\xb7\x78\x86\x8a\xb7\xf9\xb3\xef\x3b\x1b\x2a\xcd\x3c\x1d\x4d\x6f\x3a\x74\x30\x76\xba\x74\x30\x76\xba\x70\xf4\x02\xb8\x70\xf4\x02\xb8\x68\x41\xea\xbb\x70\xec\xce\x3c\xe9\xe5\xb3\xba\x0c\xef\x08\xba\x0c\xef\x08\xba\xa1\xcf\x2e\xb8\xa1\xcf\x2e\xb8\x69\xa9\xdd\x3b\x7f\xb1\xd0\x3c\xf8\x02\x08\x3a\xb0\x95\xb3\x3a\xb0\x95\xb3\x3a\xbd\xbf\x39\xb8\xbd\xbf\x39\xb8\x2b\x34\xca\xbb\x4c\x79\xd2\x3c\x89\x37\x20\xb9\xfb\xc9\xb7\xba\xfb\xc9\xb7\xba\x6f\x08\x33\xb8\x6f\x08\x33\xb8\xa9\x33\xb0\x3b\xd8\x43\xd4\x3c\xd7\x69\x23\x39\x72\x81\x61\x3a\x72\x81\x61\x3a\x5f\x3e\x1c\xb8\x5f\x3e\x1c\xb8\x84\x34\x90\xbb\x21\x11\xd6\x3c\x5a\x78\x82\x3a\xf5\xf8\x7e\xb9\xf5\xf8\x7e\xb9\x2b\xef\xb0\xb7\x2b\xef\xb0\xb7\x78\x9a\x55\x3b\x2a\xe1\xd7\x3c\xeb\x9d\x6d\xbb\xbb\x8d\x43\xba\xbb\x8d\x43\xba\xb9\x2a\x18\xb6\xb9\x2a\x18\xb6\x7e\x1b\x02\xbb\xe2\xe6\xd9\x3c\xb2\xd2\xd3\x3b\x4b\x07\xe3\x3a\x4b\x07\xe3\x3a\x11\x25\x30\x37\x11\x25\x30\x37\x74\x5e\x20\x3a\x4c\x22\xdc\x3c\xac\x16\xee\xbb\x64\xb9\x7f\xbb\x64\xb9\x7f\xbb\x89\x7a\xc1\x37\x89\x7a\xc1\x37\x15\xff\x56\x3a\x47\x0a\xde\x3c\x40\x4e\xc6\x3b\xc9\x28\xd6\x3b\xc9\x28\xd6\x3b\xdd\xda\xe3\x37\xdd\xda\xe3\x37\x86\x3d\x15\xbb\xd6\x9e\xdf\x3c\x8a\x97\x86\xbb\x5f\x7d\x04\xbc\x5f\x7d\x04\xbc\xca\xcc\xfd\x37\xca\xcc\xfd\x37\x78\xa3\x74\x3b\xd6\x5b\xe1\x3c\xaf\xaf\x4b\x3b\xdd\x9a\xfa\x3b\xdd\x9a\xfa\x3b\xe0\x75\xf9\x37\xe0\x75\xf9\x37\x81\x9a\xa8\xbb\x48\x41\xe3\x3c\x47\x89\x55\xbb\x0a\x57\xc5\xbb\x0a\x57\xc5\xbb\xb9\x44\xc1\x37\xb9\x44\xc1\x37\x7d\x28\xd4\x3b\xbd\x29\xe5\x3c\x45\x8d\x65\x3b\x86\x9b\x97\x3b\x86\x9b\x97\x3b\xd5\x34\x0f\x37\xd5\x34\x0f\x37\x88\x52\xfb\xbb\x35\x15\xe7\x3c\x41\xb4\x3f\xbb\x8d\x27\x83\xbb\x8d\x27\x83\xbb\xf9\xf2\x2c\xb7\xf9\xf2\x2c\xb7\x6c\x5e\x0e\x3c\xb4\x03\xe9\x3c\xdd\x1d\xbf\x3a\x92\x59\x7a\x3b\x92\x59\x7a\x3b\x9d\xf1\x01\xb8\x9d\xf1\x01\xb8\xc6\x8e\x1b\xbc\x3c\xf5\xea\x3c\x45\x78\x85\xb9\x92\xa4\x43\xbb\x92\xa4\x43\xbb\x22\x7d\x37\xb8\x22\x7d\x37\xb8\xa2\xc1\x24\x3c\xca\xe9\xec\x3c\x30\x53\x94\x37\x68\xf0\x44\x3a\x68\xf0\x44\x3a\x34\x11\x4c\xb8\x34\x11\x4c\xb8\x46\xa2\x29\xbc\x62\xe1\xee\x3c\x87\x3d\x20\xba\xe1\x4f\x18\x3b\xe1\x4f\x18\x3b\xc3\xfc\x36\xb8\xc3\xfc\x36\xb8\xe1\x08\x2a\x3c\x0a\xdc\xf0\x3c\xdf\xc4\xd2\x3a\x12\x0a\x91\xbb\x12\x0a\x91\xbb\xa8\xff\x0c\xb8\xa8\xff\x0c\xb8\x4a\xd0\x25\xbc\xc3\xd9\xf2\x3c\x99\xb7\x3a\xbb\x90\x97\x91\x3b\x90\x97\x91\x3b\x6f\xc7\xa3\xb7\x6f\xc7\xa3\xb7\x15\x21\x1d\x3c\x94\xda\xf4\x3c\x9c\xd8\x7f\x3b\x50\x85\x5d\xbb\x50\x85\x5d\xbb\x87\x0b\xef\xb6\x87\x0b\xef\xb6\xae\x72\x10\xbc\x7a\xde\xf6\x3c\xbb\x95\x8f\xbb\xcd\x83\x35\x3b\xcd\x83\x35\x3b\xd6\x9a\x01\x37\xd6\x9a\x01\x37\xad\xb9\x00\x3c\x84\xe5\xf8\x3c\xaa\x27\x98\x3b\xfa\x65\x12\xbb\xfa\x65\x12\xbb\x44\x97\xa2\x37\x44\x97\xa2\x37\x9a\x39\xde\xbb\xb1\xef\xfa\x3c\x5f\xbd\xa5\xbb\xde\x95\xf0\x3a\xde\x95\xf0\x3a\xe8\xee\x0b\x38\xe8\xee\x0b\x38\x21\x5c\xba\x3b\x02\xfd\xfc\x3c\x2a\x7f\xa1\x3b\x89\x34\xd5\xba\x89\x34\xd5\xba\x12\xe7\x3d\x38\x12\xe7\x3d\x38\x6c\x5c\x99\xbb\x79\x0d\xff\x3c\x32\x60\x5b\xbb\xdd\x24\xc3\x3a\xdd\x24\xc3\x3a\x1f\x30\x52\x38\x1f\x30\x52\x38\x2c\x75\x7d\x3b\x8a\x90\x00\x3d\x0d\x6f\x1f\x3a\x76\x50\xd4\xb9\x76\x50\xd4\xb9\xb7\xa8\x32\x38\xb7\xa8\x32\x38\x43\x6d\x5a\xbb\xec\x9b\x01\x3d\xd7\x15\x01\x3b\x91\xc9\xc2\xba\x91\xc9\xc2\xba\x5b\x7c\xe0\x37\x5b\x7c\xe0\x37\xfc\xfd\x4e\x3b\xde\xa8\x02\x3d\xae\x9f\x80\xbb\x78\x64\x4e\x3b\x78\x64\x4e\x3b\x34\x8c\xcd\x36\x34\x8c\xcd\x36\x35\xf2\x5d\xbb\x60\xb7\x03\x3d\xd2\xa2\xbf\x3b\xbc\x37\x8f\xbb\xbc\x37\x8f\xbb\x53\x1d\x47\xb7\x53\x1d\x47\xb7\x06\x5a\x84\x3b\x7e\xc7\x04\x3d\x3c\x9c\x01\xbc\x81\x1c\xb6\x3b\x81\x1c\xb6\x3b\x39\x02\xe9\xb7\x39\x02\xe9\xb7\xcd\x71\xa7\xbb\x38\xd9\x05\x3d\x19\x6c\x1c\x3c\xc8\x04\xcc\xbb\xc8\x04\xcc\xbb\xb2\xb3\x24\xb8\xb2\xb3\x24\xb8\x9f\xeb\xd7\x3b\x98\xec\x06\x3d\x11\x5f\x23\xbc\x40\x34\xc7\x3b\x40\x34\xc7\x3b\xce\xe2\x4a\xb8\xce\xe2\x4a\xb8\x35\x77\x0a\xbc\x9e\x01\x08\x3d\xfb\xda\x1c\x3c\x29\xb7\xb3\xbb\x29\xb7\xb3\xbb\x24\xc9\x41\xb8\x24\xc9\x41\xb8\xc3\xbe\x2e\x3c\x32\x18\x09\x3d\x27\x33\x18\xbc\x61\x1e\xa6\x3b\x61\x1e\xa6\x3b\x86\xf9\x1d\xb8\x86\xf9\x1d\xb8\xd8\xfa\x57\xbc\x51\x30\x0a\x3d\x9b\x60\x14\x3c\x8c\x24\x60\xbb\x8c\x24\x60\xbb\xf2\x0d\x9a\xb7\xf2\x0d\x9a\xb7\xc9\x8d\x82\x3c\x1b\x4a\x0b\x3d\x80\x21\x08\xbc\x42\xe5\x6e\xb8\x42\xe5\x6e\xb8\x66\x41\xd9\x35\x66\x41\xd9\x35\xd2\x38\x9a\xbc\x90\x65\x0c\x3d\xbb\xd8\xd9\x3b\xd8\x8d\x9b\x3b\xd8\x8d\x9b\x3b\xe6\x0e\xa2\x37\xe6\x0e\xa2\x37\x6c\xef\xb1\x3c\xa4\x82\x0d\x3d\x60\x47\x97\xbb\xfa\x1b\x1c\xbc\xfa\x1b\x1c\xbc\x10\x72\xe7\x37\x10\x72\xe7\x37\xe6\x80\xc8\xbc\x59\xa1\x0e\x3d\x40\x38\x3c\x3b\xfa\x36\x5f\x3c\xfa\x36\x5f\x3c\xeb\xed\xf3\x37\xeb\xed\xf3\x37\xc0\xd2\xdc\x3c\xb2\xc1\x0f\x3d\xc4\x7f\xee\xba\x69\xad\x89\xbc\x69\xad\x89\xbc\x66\x9d\xed\x37\x66\x9d\xed\x37\x39\xe8\xed\xbc\xb1\xe3\x10\x3d\xee\x8e\xa2\x3a\x79\x9d\x9a\x3c\x79\x9d\x9a\x3c\xcc\x82\xd6\x37\xcc\x82\xd6\x37\xdc\x1c\xfb\x3c\x58\x07\x12\x3d\xcb\x8e\x10\xba\x36\xe8\xa7\xbc\x36\xe8\xa7\xbc\xe5\xe6\x9e\x37\xe5\xe6\x9e\x37\x91\x0b\x02\xbd\xa9\x2c\x13\x3d\x10\xad\x6e\xb9\x47\x1d\xb6\x3c\x47\x1d\xb6\x3c\x7b\xa6\x22\x37\x7b\xa6\x22\x37\x18\x5d\x04\x3d\xa2\x53\x14\x3d\xd8\x20\x3f\x3a\x3f\xc6\xbf\xbc\x3f\xc6\xbf\xbc\x85\x22\xab\xb6\x85\x22\xab\xb6\xc9\x87\x04\xbd\x44\x7c\x15\x3d\x13\x87\x57\xba\x89\x05\xc2\x3c\x89\x05\xc2\x3c\x3b\x35\x8c\xb7\x3b\x35\x8c\xb7\x8d\x96\x02\x3d\x93\xa6\x16\x3d\xf1\xc9\x66\x3a\x0a\x6b\xbe\xbc\x0a\x6b\xbe\xbc\x08\xd2\xf2\xb7\x08\xd2\xf2\xb7\x88\x18\xfd\xbc\x90\xd2\x17\x3d\xcd\x89\x85\xba\x98\x45\xb2\x3c\x98\x45\xb2\x3c\x8a\x4a\x14\xb8\x8a\x4a\x14\xb8\x5f\xf2\xf0\x3c\x3a\x00\x19\x3d\x93\x80\x85\x3a\x4f\x11\x9c\xbc\x4f\x11\x9c\xbc\x91\x88\x18\xb8\x91\x88\x18\xb8\xcd\xde\xe0\xbc\x94\x2f\x1a\x3d\xf8\xdf\xc7\xb9\x34\xcb\x74\x3c\x34\xcb\x74\x3c\xc8\x7d\xf5\xb7\xc8\x7d\xf5\xb7\xf8\x3f\xcd\x3c\xa0\x60\x1b\x3d\xd0\x30\x9e\xba\xe1\x7a\x2d\xbc\xe1\x7a\x2d\xbc\x18\x50\xaf\xb7\x18\x50\xaf\xb7\x18\xa0\xb6\xbc\x5f\x93\x1c\x3d\xf8\x00\x6e\x3b\x95\x78\xc3\x3b\x95\x78\xc3\x3b\x20\x54\xbb\xb6\x20\x54\xbb\xb6\x6e\xda\x9d\x3c\xd2\xc7\x1d\x3d\xca\x66\xd0\xbb\xa3\xb0\xad\xba\xa3\xb0\xad\xba\x33\xa3\x10\x37\x33\xa3\x10\x37\x93\xea\x83\xbc\xf8\xfd\x1e\x3d\xf0\xc0\x14\x3c\x8e\xa5\x4a\xbb\x8e\xa5\x4a\xbb\x01\x12\xe0\x37\x01\x12\xe0\x37\x78\x9d\x53\x3c\xd2\x35\x20\x3d\x6e\xda\x42\xbc\xad\x74\xe3\x3b\xad\x74\xe3\x3b\xbe\xbb\x26\x38\xbe\xbb\x26\x38\x16\xaa\x20\xbc\x60\x6f\x21\x3d\x9b\xfd\x79\x3c\x80\x7d\x30\xbc\x80\x7d\x30\xbc\x42\xf6\x2d\x38\x42\xf6\x2d\x38\x70\x6c\xe0\x3b\xa6\xaa\x22\x3d\x00\x20\x97\xbc\xe6\x6c\x5f\x3c\xe6\x6c\x5f\x3c\xe8\xa9\x06\x38\xe8\xa9\x06\x38\x0b\xa6\x85\xbb\xa6\xe7\x23\x3d\x18\x98\xa0\x3c\x96\x93\x48\xbc\x96\x93\x48\xbc\xf6\x9f\x74\x37\xf6\x9f\x74\x37\xa8\x65\xc3\x3a\x62\x26\x25\x3d\x98\xb0\x9a\xbc\x17\xde\xc8\x3b\x17\xde\xc8\x3b\x22\xc8\x1f\xb7\x22\xc8\x1f\xb7\x13\xa3\x74\x3a\xdc\x66\x26\x3d\x78\x7c\x91\x3c\x22\x68\x96\x3a\x22\x68\x96\x3a\xd4\x1a\x04\xb8\xd4\x1a\x04\xb8\x15\xc1\x51\xbb\x0d\xa9\x27\x3d\xaf\x7b\x96\xbc\x36\x9d\xd0\xbb\x36\x9d\xd0\xbb\x22\x5d\x5f\xb8\x22\x5d\x5f\xb8\x0e\xda\xad\x3b\xf6\xec\x28\x3d\xfd\x6b\xa2\x3c\xb7\x0f\x1c\x3c\xb7\x0f\x1c\x3c\x0d\x66\x8b\xb8\x0d\x66\x8b\xb8\xa8\x64\xec\xbb\xa0\x32\x2a\x3d\x4a\x06\xa5\xbc\xb6\xb6\x51\xbc\xb6\xb6\x51\xbc\x6a\xdf\x93\xb8\x6a\xdf\x93\xb8\x52\x70\x11\x3c\x0e\x7a\x2b\x3d\x55\x99\x99\x3c\x14\x5f\x87\x3c\x14\x5f\x87\x3c\xdf\x04\x73\xb8\xdf\x04\x73\xb8\xa7\x96\x27\xbc\x39\xc3\x2c\x3d\xff\x13\x8b\xbc\x2e\xdf\xa2\xbc\x2e\xdf\xa2\xbc\xc3\x98\x1c\xb8\xc3\x98\x1c\xb8\x73\xda\x37\x3c\x22\x0e\x2e\x3d\x65\xab\x66\x3c\xfe\xde\xba\x3c\xfe\xde\xba\x3c\xff\xf1\x9e\xb7\xff\xf1\x9e\xb7\xc7\x04\x42\xbc\xcf\x5a\x2f\x3d\x4d\xef\x24\xbc\xab\x27\xca\xbc\xab\x27\xca\xbc\xca\x46\x0b\xb7\xca\x46\x0b\xb7\x75\x81\x46\x3c\x40\xa9\x30\x3d\xac\x92\xbb\x3b\x00\x46\xd2\x3c\x00\x46\xd2\x3c\x26\xd4\x84\x35\x26\xd4\x84\x35\x5e\x91\x45\xbc\x75\xf9\x31\x3d\x94\xf7\x4f\xbb\x65\x1a\xd2\xbc\x65\x1a\xd2\xbc\xb3\xbf\x0a\x37\xb3\xbf\x0a\x37\x40\xb2\x3f\x3c\x6f\x4b\x33\x3d\x0e\xdf\x38\x3b\x63\x1f\xcc\x3c\x63\x1f\xcc\x3c\x6a\xd7\x85\x37\x6a\xd7\x85\x37\xf0\x45\x35\xbc\x30\x9f\x34\x3d\x25\x28\xfc\xba\x16\x9e\xce\xbc\x16\x9e\xce\xbc\xd7\x73\xcd\x37\xd7\x73\xcd\x37\x84\x7a\x26\x3c\xb7\xf4\x35\x3d\x98\xa9\xbd\x3a\x8f\xe9\xc9\x3c\x8f\xe9\xc9\x3c\xd2\xc9\xfb\x37\xd2\xc9\xfb\x37\xad\x10\x13\xbc\x06\x4c\x37\x3d\x80\x86\xaa\x38\xbc\x2e\xc2\xbc\xbc\x2e\xc2\xbc\xcc\x29\x96\x37\xcc\x29\x96\x37\xde\x89\xf5\x3b\x1c\xa5\x38\x3d\x3d\x4d\x10\xbb\x71\xbb\xaf\x3c\x71\xbb\xaf\x3c\x0b\xab\xe9\xb6\x0b\xab\xe9\xb6\x44\xd9\xba\xbb\xfe\xff\x39\x3d\xf8\xe9\x88\x3b\x79\xd0\x97\xbc\x79\xd0\x97\xbc\xd8\xb9\x09\xb8\xd8\xb9\x09\xb8\x6d\x61\x6f\x3b\xaa\x5c\x3b\x3d\x50\xf3\xb1\xbb\xe3\x4a\x88\x3c\xe3\x4a\x88\x3c\x7b\xe8\x44\xb8\x7b\xe8\x44\xb8\x48\x1e\xbc\xba\x24\xbb\x3c\x3d\xd7\x32\xa1\x3b\xbc\xc5\x82\xbc\xbc\xc5\x82\xbc\x4c\xf4\x52\xb8\x4c\xf4\x52\xb8\xcb\x21\x57\xba\x69\x1b\x3e\x3d\x12\x33\x4c\xbb\x98\xe6\x82\x3c\x98\xe6\x82\x3c\x4f\x0d\x27\xb8\x4f\x0d\x27\xb8\xcf\xb0\x43\x3b\x7e\x7d\x3f\x3d\x26\x5b\xa7\xba\x12\x6e\x53\xbc\x12\x6e\x53\xbc\xb9\x74\xad\xb7\xb9\x74\xad\xb7\x31\xf6\xa2\xbb\x60\xe1\x40\x3d\x9c\x27\xd1\x3b\xe1\xd2\x02\x3c\xe1\xd2\x02\x3c\x82\x3f\x73\x36\x82\x3f\x73\x36\x59\x0c\xdd\x3b\x11\x47\x42\x3d\xb8\x36\x1c\xbc\xc4\x32\x8f\xbb\xc4\x32\x8f\xbb\x29\x97\xbf\x37\x29\x97\xbf\x37\xc1\x7a\x08\xbc\x90\xae\x43\x3d\x56\xe9\x15\x3c\x69\xb8\x82\x3b\x69\xb8\x82\x3b\x83\x36\x19\x38\x83\x36\x19\x38\x4b\x2f\x20\x3c\xe1\x17\x45\x3d\x80\x84\xdd\xbb\x13\x14\x95\xbb\x13\x14\x95\xbb\xbc\x35\x1c\x38\xbc\x35\x1c\x38\x8e\x97\x36\xbc\x04\x83\x46\x3d\x66\x12\x79\x3b\x1f\xc7\xb9\x3b\x1f\xc7\xb9\x3b\xf8\x87\x0c\x38\xf8\x87\x0c\x38\xf9\x59\x4c\x3c\xfb\xef\x47\x3d\x58\xeb\xfd\xba\xfd\x68\xfd\xbb\xfd\x68\xfd\xbb\xac\xaa\xbd\x37\xac\xaa\xbd\x37\xac\x65\x61\xbc\xc4\x5e\x49\x3d\xd4\x79\x8f\x3a\x0b\x48\x27\x3c\x0b\x48\x27\x3c\xd8\x78\x62\x37\xd8\x78\x62\x37\x67\xfa\x74\x3c\x61\xcf\x4a\x3d\x48\x0e\x2d\xb9\x01\x9b\x42\xbc\x01\x9b\x42\xbc\xb2\x46\x91\xb5\xb2\x46\x91\xb5\x1d\x17\x83\xbc\xd1\x41\x4c\x3d\x22\xd9\xf3\xb9\x18\x5f\x50\x3c\x18\x5f\x50\x3c\xc0\x64\x80\xb7\xc0\x64\x80\xb7\x3e\x01\x8a\x3c\x18\xb6\x4d\x3d\xfc\x7f\xa5\x3a\xcf\x7e\x59\xbc\xcf\x7e\x59\xbc\x54\x6b\xfb\xb7\x54\x6b\xfb\xb7\x21\xf1\x8e\xbc\x35\x2c\x4f\x3d\xc8\x92\x80\xba\x4b\x93\x51\x3c\x4b\x93\x51\x3c\x16\xc8\x3d\xb8\x16\xc8\x3d\xb8\x08\xd6\x91\x3c\x29\xa4\x50\x3d\x06\x0c\xbb\xba\xca\x03\x20\xbc\xca\x03\x20\xbc\xac\xaa\x61\xb8\xac\xaa\x61\xb8\x25\xe6\x92\xbc\xf4\x1d\x52\x3d\x71\x64\xc8\x3b\x9a\x5e\xa3\x3b\x9a\x5e\xa3\x3b\xe4\xfa\x4d\xb8\xe4\xfa\x4d\xb8\xbc\x79\x92\x3c\x96\x99\x53\x3d\xa0\x00\x53\xbc\x36\x4b\xe0\x38\x36\x4b\xe0\x38\xc9\xac\x1a\xb8\xc9\xac\x1a\xb8\x22\xe4\x90\xbc\x11\x17\x55\x3d\xda\xaf\xa0\x3c\x73\x72\x66\xbb\x73\x72\x66\xbb\xee\x44\x49\xb7\xee\x44\x49\xb7\x65\x45\x8e\x3c\x66\x96\x56\x3d\x0f\x74\xce\xbc\xea\x8e\xb9\x3b\xea\x8e\xb9\x3b\x95\xd2\x60\x37\x95\xd2\x60\x37\xd7\x8b\x8a\xbc\x95\x17\x58\x3d\xf7\xda\xf6\x3c\x14\x1f\xf7\xbb\x14\x1f\xf7\xbb\x40\x74\x12\x38\x40\x74\x12\x38\xc8\x84\x85\x3c\x9f\x9a\x59\x3d\x98\x37\x0c\xbd\x67\x05\xf3\x3b\x67\x05\xf3\x3b\xda\xa6\x40\x38\xda\xa6\x40\x38\xfe\x14\x7e\xbc\x84\x1f\x5b\x3d\x82\x0d\x18\x3d\x5c\x6a\x8e\xbb\x5c\x6a\x8e\xbb\x6c\xa2\x53\x38\x6c\xa2\x53\x38\x6b\x4d\x6e\x3c\x44\xa6\x5c\x3d\x99\xfb\x1c\xbd\x31\xea\x93\xb9\x31\xea\x93\xb9\x03\x14\x35\x38\x03\x14\x35\x38\xa8\x62\x5c\xbc\xdf\x2e\x5e\x3d\x79\xd3\x1a\x3d\xb9\x1d\xa0\x3b\xb9\x1d\xa0\x3b\xae\xae\xdd\x37\xae\xae\xdd\x37\x1f\x89\x49\x3c\x58\xb9\x5f\x3d\x7b\x3e\x18\xbd\x52\x5f\x01\xbc\x52\x5f\x01\xbc\x71\xb2\x82\x36\x71\xb2\x82\x36\x7f\x44\x37\xbc\xad\x45\x61\x3d\xff\x9f\x1a\x3d\x8e\x2a\x0c\x3c\x8e\x2a\x0c\x3c\xb8\xb1\x94\xb7\xb8\xb1\x94\xb7\xf9\x86\x26\x3c\xe1\xd3\x62\x3d\xc0\x90\x1f\xbd\x0c\x6f\xe2\xbb\x0c\x6f\xe2\xbb\xda\xa9\x07\xb8\xda\xa9\x07\xb8\xf0\xd4\x17\xbc\xf4\x63\x64\x3d\xd1\x01\x1e\x3d\x12\xd7\x99\x3b\x12\xd7\x99\x3b\xbd\xe7\x0f\xb8\xbd\xe7\x0f\xb8\x05\x02\x0b\x3c\xe4\xf5\x65\x3d\x89\x0b\x10\xbd\xb4\x81\x5d\xbb\xb4\x81\x5d\xbb\x04\x0b\xea\xb7\x04\x0b\xea\xb7\xea\x7b\xfe\xbb\xb4\x89\x67\x3d\xc4\x59\xf1\x3c\x0f\xd4\x1f\x3b\x0f\xd4\x1f\x3b\x3e\xcf\x89\xb7\x3e\xcf\x89\xb7\x18\xb1\xe6\x3b\x62\x1f\x69\x3d\x49\x24\xc4\xbc\xba\x87\xfa\xba\xba\x87\xfa\xba\xf6\xba\xf9\xb5\xf6\xba\xf9\xb5\xdf\xd1\xcc\xbb\xef\xb6\x6a\x3d\x17\x94\xa4\x3c\x0b\x8b\x88\x3a\x0b\x8b\x88\x3a\x4b\x71\x25\x37\x4b\x71\x25\x37\x03\xd6\xaf\x3b\x5d\x50\x6c\x3d\xbd\x5b\x93\xbc\xbf\x6a\x98\x3a\xbf\x6a\x98\x3a\xdc\xb7\xa3\x37\xdc\xb7\xa3\x37\x64\xf6\x8f\xbb\xaa\xeb\x6d\x3d\x04\x76\x8b\x3c\x6f\x40\xa6\xbb\x6f\x40\xa6\xbb\x3c\xc4\xef\x37\x3c\xc4\xef\x37\xfc\x5b\x5c\x3b\xd9\x88\x6f\x3d\x5c\xa1\x82\xbc\xbb\xc6\x19\x3c\xbb\xc6\x19\x3c\x71\xf3\x17\x38\x71\xf3\x17\x38\x92\x1d\x18\xbb\xe9\x27\x71\x3d\x53\x4e\x6b\x3c\x4c\xdf\x5f\xbc\x4c\xdf\x5f\xbc\xb1\x32\x13\x38\xb1\x32\x13\x38\x06\xa3\xac\x3a\xd8\xc8\x72\x3d\x97\x50\x38\xbc\xff\xfc\x86\x3c\xff\xfc\x86\x3c\x8b\xbb\xdd\x37\x8b\xbb\xdd\x37\x95\xf7\xc0\xb9\xa7\x6b\x74\x3d\x05\x8a\xeb\x3b\xda\xa3\x8d\xbc\xda\xa3\x8d\xbc\x99\x50\x1d\x37\x99\x50\x1d\x37\x5f\x89\x07\xba\x58\x10\x76\x3d\x93\x36\x53\xbb\xe5\x12\x8d\x3c\xe5\x12\x8d\x3c\x2e\x22\x1f\xb7\x2e\x22\x1f\xb7\x5e\x20\xaf\x3a\xee\xb6\x77\x3d\x1a\xd6\x01\xbb\x44\x2e\x88\xbc\x44\x2e\x88\xbc\x81\xe8\xf0\xb7\x81\xe8\xf0\xb7\x79\x1d\x08\xbb\x62\x5f\x79\x3d\x7e\x0d\x08\x3c\xd9\x11\x73\x3c\xd9\x11\x73\x3c\xe4\x72\x23\xb8\xe4\x72\x23\xb8\x41\x90\x31\x3b\xb8\x09\x7b\x3d\x5e\xde\x58\xbc\x64\x7d\x57\xbc\x64\x7d\x57\xbc\xfa\xbc\x40\xb8\xfa\xbc\x40\xb8\x60\xf6\x4e\xbb\xee\xb5\x7c\x3d\x24\x0c\x8a\x3c\x67\x3c\x2d\x3c\x67\x3c\x2d\x3c\x4c\x6e\x1d\xb8\x4c\x6e\x1d\xb8\x18\x86\x5a\x3b\x07\x64\x7e\x3d\x40\xfd\x97\xbc\xb5\x24\x01\xbc\xb5\x24\x01\xbc\xa8\x74\xb9\xb7\xa8\x74\xb9\xb7\xb4\xda\x4d\xbb\x00\x0a\x80\x3d\xba\x87\x95\x3c\x4e\xae\xae\x3b\x4e\xae\xae\x3b\xac\xb2\x17\xb6\xac\xb2\x17\xb6\x43\x7f\x23\x3b\xee\xe2\x80\x3d\xdf\xae\x82\xbc\xfc\x33\x83\xbb\xfc\x33\x83\xbb\x10\xf0\xb3\x37\x10\xf0\xb3\x37\x60\x40\xaf\xba\xcd\xbc\x81\x3d\x73\xb3\x4c\x3c\xa7\xbd\x82\x3b\xa7\xbd\x82\x3b\xdf\x65\x41\x38\xdf\x65\x41\x38\x8d\x91\xb0\xb9\x9c\x97\x82\x3d\x17\xb8\x1e\xbc\x88\x6c\x88\xbb\x88\x6c\x88\xbb\x8d\xde\x65\x38\x8d\xde\x65\x38\x2c\x3a\x21\x3b\x5c\x73\x83\x3d\xc9\x58\xc8\x3b\x6e\x1b\xc4\x3b\x6e\x1b\xc4\x3b\x19\x30\x4b\x38\x19\x30\x4b\x38\xfd\xf6\xa0\xbb\x0c\x50\x84\x3d\xe5\x9a\xef\xba\x59\xdf\x23\xbc\x59\xdf\x23\xbc\xa2\xa6\xcf\x37\xa2\xa6\xcf\x37\xc6\xc7\xf6\x3b\xac\x2d\x85\x3d\x4d\xb5\x24\xbb\x4b\xcb\x7f\x3c\x4b\xcb\x7f\x3c\x7a\xba\xa9\x36\x7a\xba\xa9\x36\x4a\xdd\x25\xbc\x3e\x0c\x86\x3d\x47\x99\xaa\x3b\x5a\x7b\xac\xbc\x5a\x7b\xac\xbc\x15\x6e\xad\xb6\x15\x6e\xad\xb6\x3a\x6a\x4c\x3c\xbf\xeb\x86\x3d\xc0\xdb\xfe\xbb\xfe\xd3\xd8\x3c\xfe\xd3\xd8\x3c\xbf\x33\x28\xb7\xbf\x33\x28\xb7\xa6\x41\x6c\xbc\x30\xcc\x87\x3d\x5d\xae\x06\x3c\xfb\xac\xfb\xbc\xfb\xac\xfb\xbc\x68\xe4\x8f\xb7\x68\xe4\x8f\xb7\x0f\x59\x81\x3c\x92\xad\x88\x3d\x57\x1c\x00\xbc\x34\xe2\x10\x3d\x34\xe2\x10\x3d\xa8\xa2\xcb\xb7\xa8\xa2\xcb\xb7\x5b\xbf\x86\xbc\xe4\x8f\x89\x3d\xb5\x3a\xf0\x3b\x93\x65\x26\xbd\x93\x65\x26\xbd\x19\x21\x79\xb8\x19\x21\x79\xb8\x36\x43\x85\x3c\x25\x73\x8a\x3d\x4c\xe4\xe4\xbb\xb9\xcc\x3c\x3d\xb9\xcc\x3c\x3d\x72\x42\xc1\xb8\x72\x42\xc1\xb8\xa2\xf3\x77\xbc\x54\x57\x8b\x3d\xd3\x8b\xdc\x3b\xd1\x5b\x54\xbd\xd1\x5b\x54\xbd\xa0\x81\xca\xb7\xa0\x81\xca\xb7\xe1\x6b\x56\x3c\x49\x4e\x8c\x3d\xbd\x13\xe2\xbd\x4e\x4b\x1a\x3e\x4e\x4b\x1a\x3e\x4f\x2d\xea\x39\x4f\x2d\xea\x39\xf1\x23\x24\xbc\x03\x58\x8d\x3d\xb9\x45\xdd\x3d\x03\xe4\xa1\x3d\x03\xe4\xa1\x3d\xdd\xa8\xcf\x3a\xdd\xa8\xcf\x3a\xa4\x39\xbf\x3b\x7d\x44\x8e\x3d\x26\xf1\xd5\xbd\x59\xbb\x79\x3e\x59\xbb\x79\x3e\x73\x4a\x64\x3b\x73\x4a\x64\x3b\x6d\xed\x2c\xba\xb6\x13\x8f\x3d\x4d\x37\xce\x3d\xe8\xf6\x31\x3e\xe8\xf6\x31\x3e\x06\xbf\xc9\x3b\x06\xbf\xc9\x3b\xe7\xba\xb1\xbb\x0f\xf1\x8f\x3d\x3d\x47\xcb\xbd\x99\x08\xa2\x3e\x99\x08\xa2\x3e\x04\x3b\x1d\x3c\x04\x3b\x1d\x3c\x8a\xa3\x49\x3c\x87\xdc\x90\x3d\x83\xcb\xcd\x3d\xfb\x75\x8d\x3e\xfb\x75\x8d\x3e\x69\xff\x61\x3c\x69\xff\x61\x3c\xe8\xd2\xa2\xbc\x02\xc9\x91\x3d\xbc\x2e\xd7\xbd\x8f\xf9\xc2\x3e\x8f\xf9\xc2\x3e\xe3\xc2\x99\x3c\xe3\xc2\x99\x3c\x3c\xd0\xe5\x3c\x7f\xb6\x92\x3d\xfd\x9a\xe3\x3d\xad\x3d\xbe\x3e\xad\x3d\xbe\x3e\x62\xd1\xc8\x3c\x62\xd1\xc8\x3c\xa4\xbf\x16\xbd\xff\xa4\x93\x3d\xa4\x3f\xf7\xbd\x69\xfa\xe2\x3e\x69\xfa\xe2\x3e\xab\x1f\xfe\x3c\xab\x1f\xfe\x3c\x9f\xea\x3c\x3d\x82\x94\x94\x3d\xb7\xbc\x07\x3e\xb5\x02\xea\x3e\xb5\x02\xea\x3e\x82\xd4\x1c\x3d\x82\xd4\x1c\x3d\x09\x65\x65\xbd\x06\x85\x95\x3d\x4a\xfa\x14\xbe\xee\x71\xff\x3e\xee\x71\xff\x3e\xbd\xce\x3d\x3d\xbd\xce\x3d\x3d\xc3\x1e\x88\x3d\x8b\x76\x96\x3d\x96\xe8\x22\x3e\xe1\xb9\x08\x3f\xe1\xb9\x08\x3f\xb8\xf5\x61\x3d\xb8\xf5\x61\x3d\x95\xc7\x9e\xbd\x15\x69\x97\x3d\xe3\x53\x32\xbe\xa0\xe4\x0c\x3f\xa0\xe4\x0c\x3f\xba\xa0\x84\x3d\xba\xa0\x84\x3d\x18\xb4\xb6\x3d\xa2\x5c\x98\x3d\x4e\x6e\x42\x3e\x4c\x4f\x18\x3f\x4c\x4f\x18\x3f\x21\xd3\x99\x3d\x21\xd3\x99\x3d\x60\xe5\xcf\xbd\x34\x51\x99\x3d\xa1\xc3\x53\xbe\x46\x62\x19\x3f\x46\x62\x19\x3f\xdf\x92\xb0\x3d\xdf\x92\xb0\x3d\x1b\x51\xea\x3d\xcb\x46\x9a\x3d\x59\x56\x67\x3e\x0f\xec\x22\x3f\x0f\xec\x22\x3f\x0c\xd5\xc8\x3d\x0c\xd5\xc8\x3d\x79\xf6\x02\xbe\x68\x3d\x9b\x3d\xf4\x49\x7d\xbe\xa8\xc2\x26\x3f\xa8\xc2\x26\x3f\xdf\x99\xe2\x3d\xdf\x99\xe2\x3d\xd9\x56\x11\x3e\x0d\x35\x9c\x3d\x1f\x17\x8a\x3e\x7c\xfb\x26\x3f\x7c\xfb\x26\x3f\xdd\xda\xfd\x3d\xdd\xda\xfd\x3d\xf6\x43\x20\xbe\xb8\x2d\x9d\x3d\x99\x73\x95\xbe\x9c\x65\x33\x3f\x9c\x65\x33\x3f\x17\x4e\x0d\x3e\x17\x4e\x0d\x3e\x3d\xbc\x2f\x3e\x6c\x27\x9e\x3d\xc6\x17\xa1\x3e\x92\x68\x27\x3f\x92\x68\x27\x3f\xfa\x6e\x1c\x3e\xfa\x6e\x1c\x3e\x58\xbd\x3f\xbe\x24\x22\x9f\x3d\xa9\x21\xad\xbe\xfe\xfd\x3c\x3f\xfe\xfd\x3c\x3f\x79\x4f\x2c\x3e\x79\x4f\x2c\x3e\x62\x46\x50\x3e\xe4\x1d\xa0\x3d\xdf\x81\xb9\x3e\x86\x7f\x25\x3f\x86\x7f\x25\x3f\x03\xec\x3c\x3e\x03\xec\x3c\x3e\xe4\x50\x61\xbe\xa6\x1a\xa1\x3d\x2f\x20\xc6\xbe\xa0\xfb\x41\x3f\xa0\xfb\x41\x3f\xbd\x44\x4e\x3e\xbd\x44\x4e\x3e\x26\xd4\x72\x3e\x6a\x18\xa2\x3d\x02\x71\xd2\x3e\x73\x47\x21\x3f\x73\x47\x21\x3f\xa1\x53\x60\x3e\xa1\x53\x60\x3e\x3a\x61\x82\xbe\x39\x17\xa3\x3d\x4b\xf8\xdc\xbe\xbc\x5c\x43\x3f\xbc\x5c\x43\x3f\x55\x14\x73\x3e\x55\x14\x73\x3e\x53\x84\x8b\x3e\x10\x17\xa4\x3d\xc1\x65\xe5\x3e\x2c\x72\x1b\x3f\x2c\x72\x1b\x3f\xdd\x3f\x83\x3e\xdd\x3f\x83\x3e\xd6\xc8\x94\xbe\xf8\x17\xa5\x3d\xcf\x3c\xec\xbe\x35\x91\x3e\x3f\x35\x91\x3e\x3f\x39\x49\x8d\x3e\x39\x49\x8d\x3e\x41\x23\x9e\x3e\xef\x19\xa6\x3d\x87\x07\xf2\x3e\x3f\x96\x15\x3f\x3f\x96\x15\x3f\xcd\xa2\x97\x3e\xcd\xa2\x97\x3e\xd1\x89\xa7\xbe\xe3\x1c\xa7\x3d\xb4\x3f\xf6\xbe\x40\x35\x34\x3f\x40\x35\x34\x3f\xea\x48\xa2\x3e\xea\x48\xa2\x3e\x24\xf5\xb0\x3e\xd3\x20\xa8\x3d\x0f\x75\xf8\x3e\xe0\xbd\x0e\x3f\xe0\xbd\x0e\x3f\x70\x38\xad\x3e\x70\x38\xad\x3e\x13\x63\xba\xbe\xd3\x25\xa9\x3d\xae\xd2\xf8\xbe\x81\x3e\x25\x3f\x81\x3e\x25\x3f\xd1\x6f\xb8\x3e\xd1\x6f\xb8\x3e\x96\xd6\xc3\x3e\xe3\x2b\xaa\x3d\x94\x60\xf7\x3e\xe5\x00\x06\x3f\xe5\x00\x06\x3f\x66\xea\xc3\x3e\x66\xea\xc3\x3e\x23\x57\xcd\xbe\xfb\x32\xab\x3d\x48\xbf\xf3\xbe\x51\xe2\x12\x3f\x51\xe2\x12\x3f\x06\xa4\xcf\x3e\x06\xa4\xcf\x3e\x95\xef\xd6\x3e\x1a\x3b\xac\x3d\x71\x86\xed\x3e\xd5\x3a\xf7\x3e\xd5\x3a\xf7\x3e\xaf\x96\xdb\x3e\xaf\x96\xdb\x3e\x3f\xad\xe0\xbe\x43\x44\xad\x3d\x94\x7f\xe4\xbe\x01\xf0\xf8\x3e\x01\xf0\xf8\x3e\xae\xbe\xe7\x3e\xae\xbe\xe7\x3e\x5a\xa0\xea\x3e\x74\x4e\xae\x3d\x4d\x7d\xd8\x3e\xa5\xbb\xdf\x3e\xa5\xbb\xdf\x3e\x16\x17\xf4\x3e\x16\x17\xf4\x3e\xfe\xd7\xf4\xbe\xb1\x59\xaf\x3d\xe5\x55\xc9\xbe\x41\x96\xc8\x3e\x41\x96\xc8\x3e\xb0\x4c\x00\x3f\xb0\x4c\x00\x3f\x16\x63\xff\x3e\xfa\x65\xb0\x3d\xa3\x9a\xb7\x3e\x86\xae\xbf\x3e\x86\xae\xbf\x3e\xd5\x9e\x06\x3f\xd5\x9e\x06\x3f\xa5\x27\x05\xbf\x4b\x73\xb1\x3d\x6d\xb9\xa3\xbe\x9c\xf1\x9a\x3e\x9c\xf1\x9a\x3e\xaa\xfe\x0c\x3f\xaa\xfe\x0c\x3f\x55\xd3\x0a\x3f\xa6\x81\xb2\x3d\x7b\x9c\x8d\x3e\xc9\xcb\x95\x3e\xc9\xcb\x95\x3e\x27\x68\x13\x3f\x27\x68\x13\x3f\x9d\xb7\x10\xbf\x0c\x91\xb3\x3d\xe5\xf7\x6a\xbe\xcb\xf3\x5d\x3e\xcb\xf3\x5d\x3e\xa3\xd6\x19\x3f\xa3\xd6\x19\x3f\xb7\xd4\x16\x3f\x7c\xa1\xb4\x3d\x50\x2e\x37\x3e\x19\x16\x4a\x3e\x19\x16\x4a\x3e\xf7\x44\x20\x3f\xf7\x44\x20\x3f\xdb\x27\x1d\xbf\xf8\xb2\xb5\x3d\xcd\xfe\x00\xbe\x76\x48\x0d\x3e\x76\x48\x0d\x3e\x03\xaf\x26\x3f\x03\xaf\x26\x3f\x97\xa9\x23\x3f\x80\xc5\xb6\x3d\xf4\x15\x8f\x3d\x82\x58\xac\x3d\x82\x58\xac\x3d\x47\x10\x2d\x3f\x47\x10\x2d\x3f\x3b\x4e\x2a\xbf\x13\xd9\xb7\x3d\xfc\x45\x27\xbc\x6b\x01\x88\x3d\x6b\x01\x88\x3d\x7b\x64\x33\x3f\x7b\x64\x33\x3f\x5a\x05\x31\x3f\xb4\xed\xb8\x3d\x94\x02\x56\xbd\xe0\xab\x06\xbd\xe0\xab\x06\xbd\x5b\xa6\x39\x3f\x5b\xa6\x39\x3f\x89\xbb\x37\xbf\x60\x03\xba\x3d\x41\x8b\xeb\x3d\x86\x9b\x05\xbc\x86\x9b\x05\xbc\xe5\xd0\x3f\x3f\xe5\xd0\x3f\x3f\x84\x5b\x3e\x3f\x16\x1a\xbb\x3d\x3e\x37\x34\xbe\x63\x33\x18\xbe\x63\x33\x18\xbe\x91\xdd\x45\x3f\x91\xdd\x45\x3f\x45\xd1\x44\xbf\xd8\x31\xbc\x3d\x65\x8e\x6f\x3e\xfa\x78\xab\xbd\xfa\x78\xab\xbd\x62\xc6\x4b\x3f\x62\xc6\x4b\x3f\xac\x0a\x4b\x3f\xa5\x4a\xbd\x3d\xea\xb8\x93\xbe\xde\x9b\x83\xbe\xde\x9b\x83\xbe\x10\x84\x51\x3f\x10\x84\x51\x3f\xbb\xf9\x50\xbf\x7d\x64\xbe\x3d\xd2\xd2\xad\x3e\x6d\x0c\x2c\xbe\x6d\x0c\x2c\xbe\x68\x0f\x57\x3f\x68\x0f\x57\x3f\xab\x94\x56\x3f\x62\x7f\xbf\x3d\x3d\x00\xc5\xbe\x0e\xee\xb1\xbe\x0e\xee\xb1\xbe\x5b\x61\x5c\x3f\x5b\x61\x5c\x3f\xce\xd5\x5b\xbf\x56\x9b\xc0\x3d\x8f\x7f\xd7\x3e\x05\x09\x86\xbe\x05\x09\x86\xbe\x04\x72\x61\x3f\x04\x72\x61\x3f\x3d\xba\x60\x3f\x58\xb8\xc1\x3d\xd9\xd9\xe3\xbe\xe0\x70\xd8\xbe\xe0\x70\xd8\xbe\xa4\x39\x66\x3f\xa4\x39\x66\x3f\xd8\x41\x65\xbf\x64\xd6\xc2\x3d\xa1\xb7\xea\x3e\xa4\x94\xb6\xbe\xa4\x94\xb6\xbe\x88\xb1\x6a\x3f\x88\xb1\x6a\x3f\x9a\x6d\x69\x3f\x78\xf5\xc3\x3d\xf6\x0c\xed\xbe\x23\x22\xf8\xbe\x23\x22\xf8\xbe\xcd\xd2\x6e\x3f\xcd\xd2\x6e\x3f\xdd\x3e\x6d\xbf\x9b\x15\xc5\x3d\x6b\xed\xea\x3e\x05\x62\xe6\xbe\x05\x62\xe6\xbe\x23\x96\x72\x3f\x23\x96\x72\x3f\x27\xb6\x70\x3f\xcd\x36\xc6\x3d\x2f\xcd\xe3\xbe\x1f\x10\x09\xbf\x1f\x10\x09\xbf\x61\xf3\x75\x3f\x61\xf3\x75\x3f\x78\xd2\x73\xbf\x0a\x59\xc7\x3d\xe2\x44\xd8\x3e\x51\xc7\x08\xbf\x51\xc7\x08\xbf\xbe\xe2\x78\x3f\xbe\xe2\x78\x3f\x8f\x92\x76\x3f\x51\x7c\xc8\x3d\x44\xf3\xc7\xbe\x7c\x69\x13\xbf\x7c\x69\x13\xbf\xb1\x5b\x7b\x3f\xb1\x5b\x7b\x3f\x16\xf2\x78\xbf\xa6\xa0\xc9\x3d\xee\xcb\xb2\x3e\x6b\x5c\x1c\xbf\x6b\x5c\x1c\xbf\x13\x56\x7d\x3f\x13\x56\x7d\x3f\x7d\xea\x7a\x3f\x09\xc6\xca\x3d\x3b\xb8\x98\xbe\x6c\xc1\x1a\xbf\x6c\xc1\x1a\xbf\x32\xca\x7e\x3f\x32\xca\x7e\x3f\xc0\x70\x7c\xbf\x78\xec\xcb\x3d\x33\x04\x74\x3e\x4d\x7f\x2b\xbf\x4d\x7f\x2b\xbf\xb6\xaf\x7f\x3f\xb6\xaf\x7f\x3f\x66\x77\x7d\x3f\xf2\x13\xcd\x3d\x7a\x93\x2d\xbe\x3f\x68\x22\xbf\x3f\x68\x22\xbf\x9c\xfd\x7f\x3f\x9c\xfd\x7f\x3f\xc4\xef\x7d\xbf\x7a\x3c\xce\x3d\x75\x9e\xb6\x3d\xf7\x68\x2b\xbf\xf7\x68\x2b\xbf\xa3\xac\x7f\x3f\xa3\xac\x7f\x3f\x6b\xcc\x7d\x3f\x0e\x66\xcf\x3d\xc5\xcb\x37\xbc\x66\xdd\x21\xbf\x66\xdd\x21\xbf\x7a\xb6\x7e\x3f\x7a\xb6\x7e\x3f\x53\xff\x7c\xbf\xae\x90\xd0\x3d\x97\x12\x8f\xbd\x0f\x06\x2e\xbf\x0f\x06\x2e\xbf\xf7\x13\x7d\x3f\xf7\x13\x7d\x3f\x3c\x7b\x7b\x3f\x5a\xbc\xd1\x3d\x6e\xa8\x1b\x3e\x54\x58\x27\xbf\x54\x58\x27\xbf\x7c\xbe\x7a\x3f\x7c\xbe\x7a\x3f\xb7\x36\x79\xbf\x13\xe9\xd2\x3d\xc4\xc2\x6e\xbe\x47\xac\x2b\xbf\x47\xac\x2b\xbf\xbb\xb0\x77\x3f\xbb\xb0\x77\x3f\x10\x2d\x76\x3f\xd9\x16\xd4\x3d\x18\xb2\x9e\x3e\xce\x54\x2b\xbf\xce\x54\x2b\xbf\xac\xe5\x73\x3f\xac\xe5\x73\x3f\x77\x5c\x72\xbf\xab\x45\xd5\x3d\x3c\x86\xc1\xbe\x22\x1c\x24\xbf\x22\x1c\x24\xbf\x06\x58\x6f\x3f\x06\x58\x6f\x3f\x6f\xc4\x6d\x3f\x89\x75\xd6\x3d\x07\xdf\xdd\x3e\x43\xf5\x2d\xbf\x43\xf5\x2d\xbf\xf0\x03\x6a\x3f\xf0\x03\x6a\x3f\x15\x64\x68\xbf\x74\xa6\xd7\x3d\x76\xb2\xf0\xbe\xca\x42\x18\xbf\xca\x42\x18\xbf\x63\xe5\x63\x3f\x63\xe5\x63\x3f\x4a\x39\x62\x3f\x6b\xd8\xd8\x3d\x15\x35\xf8\x3e\xd3\xd0\x2b\xbf\xd3\xd0\x2b\xbf\x14\xf9\x5c\x3f\x14\xf9\x5c\x3f\xf1\x41\x5b\xbf\x6e\x0b\xda\x3d\x3c\xa1\xf3\xbe\x41\xf8\x0c\xbf\x41\xf8\x0c\xbf\x4d\x3c\x55\x3f\x4d\x3c\x55\x3f\x16\x7b\x53\x3f\x7a\x3f\xdb\x3d\x7a\x30\xe3\x3e\x4f\x09\x22\xbf\x4f\x09\x22\xbf\x2f\xae\x4c\x3f\x2f\xae\x4c\x3f\x15\xe1\x4a\xbf\x93\x74\xdc\x3d\xcd\x5e\xc7\xbe\x64\xfb\x02\xbf\x64\xfb\x02\xbf\xd0\x4e\x43\x3f\xd0\x4e\x43\x3f\x8b\x71\x41\x3f\xb8\xaa\xdd\x3d\x49\x41\xa1\x3e\x21\x96\x11\xbf\x21\x96\x11\xbf\x4d\x20\x39\x3f\x4d\x20\x39\x3f\xc4\x2c\x37\xbf\xe8\xe1\xde\x3d\xb1\xdd\x64\xbe\x51\x0a\xf1\xbe\x51\x0a\xf1\xbe\xef\x24\x2e\x3f\xef\x24\x2e\x3f\xaa\x15\x2c\x3f\x24\x1a\xe0\x3d\xcd\xb8\xf3\x3d\xcd\xb8\xf9\xbe\xcd\xb8\xf9\xbe\xf7\x61\x22\x3f\xf7\x61\x22\x3f\x38\x32\x20\xbf\x6a\x53\xe1\x3d\x0f\x40\xec\xbb\xa9\x5d\xdb\xbe\xa9\x5d\xdb\xbe\x5f\xdc\x15\x3f\x5f\xdc\x15\x3f\x29\x8b\x13\x3f\xba\x8d\xe2\x3d\xf1\x3a\xd7\xbd\x28\x42\xc6\xbe\x28\x42\xc6\xbe\x9a\x9b\x08\x3f\x9a\x9b\x08\x3f\x94\x2b\x06\xbf\x14\xc9\xe3\x3d\x3e\xc4\x57\x3e\xb0\x12\xc3\xbe\xb0\x12\xc3\xbe\x40\x4d\xf5\x3e\x40\x4d\xf5\x3e\x0d\x3c\xf0\x3e\x7a\x05\xe5\x3d\x1e\x9c\x9b\xbe\x27\x63\x92\xbe\x27\x63\x92\xbe\x6a\x0d\xd8\x3e\x6a\x0d\xd8\x3e\x9a\xd9\xd2\xbe\xe8\x42\xe6\x3d\x11\xf9\xc1\x3e\x2d\xa4\x9f\xbe\x2d\xa4\x9f\xbe\xd9\x8c\xb9\x3e\xd9\x8c\xb9\x3e\xcc\x42\xb4\x3e\x61\x81\xe7\x3d\x17\x23\xdc\xbe\x5c\xc4\x47\xbe\x5c\xc4\x47\xbe\x31\xe4\x99\x3e\x31\xe4\x99\x3e\xe9\x8b\x94\xbe\xe2\xc0\xe8\x3d\x90\x56\xe8\x3e\x95\x86\x60\xbe\x95\x86\x60\xbe\x4a\x5c\x72\x3e\x4a\x5c\x72\x3e\x9e\x94\x67\x3e\x6e\x01\xea\x3d\x76\xb1\xe5\xbe\x57\xb6\xec\xbd\x57\xb6\xec\xbd\xab\x16\x2f\x3e\xab\x16\x2f\x3e\x3f\x33\x24\xbe\x02\x43\xeb\x3d\xb8\x23\xd4\x3e\xbc\xb5\xe2\xbd\xbc\xb5\xe2\xbd\xa4\x78\xd4\x3d\xa4\x78\xd4\x3d\x42\x72\xbe\x3d\xa0\x85\xec\x3d\x21\x04\xb5\xbe\x9e\xd9\x21\xbd\x9e\xd9\x21\xbd\x2f\x74\x10\x3d\x2f\x74\x10\x3d\x38\xe1\xc7\xbc\x46\xc9\xed\x3d\xc3\x85\x8a\x3e\x1a\x7f\x6d\x3a\x1a\x7f\x6d\x3a\xd7\xd9\x0b\xbd\xd7\xd9\x0b\xbd\x46\x7c\x38\xbd\xf2\x0d\xef\x3d\x3b\x46\x2e\xbe\xd5\x4c\x24\x3d\xd5\x4c\x24\x3d\xc8\x4a\xd5\xbd\xc8\x4a\xd5\xbd\x99\x4f\xeb\x3d\xa7\x53\xf0\x3d\x78\x5e\x70\x3d\x86\x5a\xdf\x3d\x86\x5a\xdf\x3d\x37\x91\x32\xbe\x37\x91\x32\xbe\xc8\x27\x3d\xbe\x64\x9a\xf1\x3d\xf9\xd6\x63\x3d\xd3\xda\xfc\x3d\xd3\xda\xfc\x3d\x0f\x56\x7a\xbe\x0f\x56\x7a\xbe\xc5\x12\x82\x3e\x27\xe2\xf2\x3d\x0e\x16\x28\xbe\x84\x20\x55\x3e\x84\x20\x55\x3e\xfd\xc7\xa0\xbe\xfd\xc7\xa0\xbe\x10\x15\xa5\xbe\xf1\x2a\xf4\x3d\x69\x01\x85\x3e\xbb\xc5\x5c\x3e\xbb\xc5\x5c\x3e\x32\xe9\xc3\xbe\x32\xe9\xc3\xbe\xe8\x61\xc7\x3e\xc1\x74\xf5\x3d\xbf\x5d\xac\xbe\x99\x84\x94\x3e\x99\x84\x94\x3e\x4d\x58\xe6\xbe\x4d\x58\xe6\xbe\x26\xc3\xe8\xbe\x97\xbf\xf6\x3d\x4b\x6c\xc7\x3e\x1c\xc2\xa0\x3e\x1c\xc2\xa0\x3e\xa1\xed\x03\xbf\xa1\xed\x03\xbf\x86\x83\x04\x3f\x72\x0b\xf8\x3d\xd8\xc1\xd3\xbe\x96\xbe\xb8\x3e\x96\xbe\xb8\x3e\x33\x1c\x14\xbf\x33\x1c\x14\xbf\xc3\x00\x14\xbf\x53\x58\xf9\x3d\x2c\xb2\xcf\x3e\xf5\xab\xd0\x3e\xf5\xab\xd0\x3e\xe6\x99\x23\xbf\xe6\x99\x23\xbf\x5a\xc6\x22\x3f\x38\xa6\xfa\x3d\xa4\x38\xbb\xbe\xe9\x6b\xd9\x3e\xe9\x6b\xd9\x3e\x5c\x48\x32\xbf\x5c\x48\x32\xbf\xb3\xc4\x30\xbf\x21\xf5\xfb\x3d\xed\x42\x98\x3e\x4d\x20\xfb\x3e\x4d\x20\xfb\x3e\x9b\x08\x40\xbf\x9b\x08\x40\xbf\xb6\xee\x3d\x3f\x0e\x45\xfd\x3d\xcc\x94\x53\xbe\xfd\xcc\xf8\x3e\xfd\xcc\xf8\x3e\xc4\xbc\x4c\xbf\xc4\xbc\x4c\xbf\x5d\x37\x4a\xbf\xfd\x95\xfe\x3d\x55\x1b\xcc\x3d\xad\x9e\x0d\x3f\xad\x9e\x0d\x3f\x35\x47\x58\xbf\x35\x47\x58\xbf\xb7\x8f\x55\x3f\xf0\xe7\xff\x3d\x52\xdf\x88\x3c\x7a\xa0\x0c\x3f\x7a\xa0\x0c\x3f\xe3\x8b\x62\xbf\xe3\x8b\x62\xbf\x52\xe4\x5f\xbf\x73\x9d\x00\x3e\x21\x7a\x09\xbe\x50\x1a\x18\x3f\x50\x1a\x18\x3f\x2d\x6f\x6b\xbf\x2d\x6f\x6b\xbf\x3a\x1a\x69\x3f\x6d\x47\x01\x3e\x35\x5a\x78\x3e\xb8\xb4\x1b\x3f\xb8\xb4\x1b\x3f\xd5\xd7\x72\xbf\xd5\xd7\x72\xbf\xb1\x0e\x71\xbf\xe8\xf1\x01\x3e\x48\x59\xa9\xbe\x00\x64\x1e\x3f\x00\x64\x1e\x3f\x34\xae\x78\xbf\x34\xae\x78\xbf\x68\x98\x77\x3f\xe3\x9c\x02\x3e\x6c\xa9\xc7\x3e\x5f\xd3\x27\x3f\x5f\xd3\x27\x3f\x8a\xdc\x7c\xbf\x8a\xdc\x7c\xbf\x4a\x89\x7c\xbf\x5f\x48\x03\x3e\x74\x1b\xd4\xbe\x67\x6c\x22\x3f\x67\x6c\x22\x3f\x53\x4f\x7f\xbf\x53\x4f\x7f\xbf\x49\xb3\x7f\x3f\x5a\xf4\x03\x3e\x3b\x3c\xcd\x3e\x46\x29\x2e\x3f\x46\x29\x2e\x3f\xfa\xf5\x7f\xbf\xfa\xf5\x7f\xbf\xe5\x76\x80\xbf\xd2\xa0\x04\x3e\xd7\x0a\xb3\xbe\x8f\x4f\x25\x3f\x8f\x4f\x25\x3f\x2d\xc1\x7e\xbf\x2d\xc1\x7e\xbf\xc4\x0c\x80\x3f\xcb\x4d\x05\x3e\x39\x17\x87\x3e\x61\xa6\x2f\x3f\x61\xa6\x2f\x3f\xd1\xa6\x7b\xbf\xd1\xa6\x7b\xbf\xf7\x23\x7d\xbf\x42\xfb\x05\x3e\x42\x1c\x1a\xbe\x65\x0b\x25\x3f\x65\x0b\x25\x3f\x05\x9e\x76\xbf\x05\x9e\x76\xbf\x49\x08\x78\x3f\x38\xa9\x06\x3e\xae\xd9\xad\x3c\x91\x3b\x2d\x3f\x91\x3b\x2d\x3f\xb1\xa4\x6f\xbf\xb1\xa4\x6f\xbf\x77\xce\x70\xbf\xab\x57\x07\x3e\x93\x13\xe2\x3d\xe5\x7d\x21\x3f\xe5\x7d\x21\x3f\xdf\xbb\x66\xbf\xdf\xbb\x66\xbf\x65\x87\x67\x3f\x9c\x06\x08\x3e\xb8\xed\x6b\xbe\x31\xe0\x26\x3f\x31\xe0\x26\x3f\x15\xea\x5b\xbf\x15\xea\x5b\xbf\x2c\x4b\x5c\xbf\x0a\xb6\x08\x3e\xcc\xdb\xa6\x3e\xe5\x70\x1b\x3f\xe5\x70\x1b\x3f\x1b\x39\x4f\xbf\x1b\x39\x4f\xbf\x2e\x35\x4f\x3f\xf4\x65\x09\x3e\x98\xc9\xc5\xbe\xb0\xd4\x1a\x3f\xb0\xd4\x1a\x3f\x29\xb9\x40\xbf\x29\xb9\x40\xbf\xe9\x62\x40\xbf\x5a\x16\x0a\x3e\x34\x22\xcf\x3e\x10\x7b\x14\x3f\x10\x7b\x14\x3f\xf0\x7d\x30\xbf\xf0\x7d\x30\xbf\xed\xf1\x2f\x3f\x3c\xc7\x0a\x3e\x9a\xb3\xc1\xbe\x5f\x9f\x0a\x3f\x5f\x9f\x0a\x3f\x86\xa1\x1e\xbf\x86\xa1\x1e\xbf\xae\x00\x1e\xbf\x9a\x78\x0b\x3e\x47\x30\x9e\x3e\x58\x7e\x08\x3f\x58\x7e\x08\x3f\xf6\x40\x0b\xbf\xf6\x40\x0b\xbf\xed\xad\x0a\x3f\x73\x2a\x0c\x3e\x6b\xec\x4d\xbe\x0c\x72\xf5\x3e\x0c\x72\xf5\x3e\x89\xfe\xec\xbe\x89\xfe\xec\xbe\x7a\x32\xec\xbe\xc7\xdc\x0c\x3e\xa6\x69\x83\x3d\x41\xe9\xed\x3e\x41\xe9\xed\x3e\xe0\x05\xc1\xbe\xe0\x05\xc1\xbe\x36\xc5\xc0\x3e\x94\x8f\x0d\x3e\xf8\xa9\xb0\x3d\xb9\x38\xd2\x3e\xb9\x38\xd2\x3e\x0a\xf1\x92\xbe\x0a\xf1\x92\xbe\xc3\x56\x93\xbe\xdc\x42\x0e\x3e\x83\xd8\x6c\xbe\xac\x45\xc6\x3e\xac\x45\xc6\x3e\xad\x40\x46\xbe\xad\x40\x46\xbe\x37\x5b\x48\x3e\x9c\xf6\x0e\x3e\xfc\xa4\xb4\x3e\xac\x12\xa7\x3e\xac\x12\xa7\x3e\x28\xf9\xc7\xbd\x28\xf9\xc7\xbd\xdc\x55\xce\xbd\xd6\xaa\x0f\x3e\x82\xa7\xde\xbe\x06\xd6\x9f\x3e\x06\xd6\x9f\x3e\x9a\xb1\x90\x37\x9a\xb1\x90\x37\x5b\x6d\x71\x3b\x44\x6b\x10\x3e\xe8\x5e\xee\x3e\x18\x94\x67\x3e\x18\x94\x67\x3e\x36\x92\xc9\x3d\x36\x92\xc9\x3d\x76\x14\xc2\x3d\xe5\x37\x11\x3e\xc3\x75\xe0\xbe\xb4\x2c\x6b\x3e\xb4\x2c\x6b\x3e\xfb\x54\x49\x3e\xfb\x54\x49\x3e\x83\x52\x46\xbe\x22\xf1\x11\x3e\xb0\xe5\xb5\x3e\xe5\xd8\x04\x3e\xe5\xd8\x04\x3e\xca\x4f\x96\x3e\xca\x4f\x96\x3e\xaa\x7d\x95\x3e\xfb\x96\x12\x3e\xe9\xc4\x66\xbe\x82\x5c\x06\x3e\x82\x5c\x06\x3e\xaa\xcf\xc6\x3e\xaa\xcf\xc6\x3e\x84\xe2\xc6\xbe\xf7\x45\x13\x3e\x56\xba\x84\x3d\x3b\xc3\x1d\x3d\x3b\xc3\x1d\x3d\x0e\xa2\xf5\x3e\x0e\xa2\xf5\x3e\xaa\xab\xf6\x3e\x17\xfe\x13\x3e\xdb\xeb\xd7\x3d\x42\xa8\xc6\x3c\x42\xa8\xc6\x3c\xca\x1f\x11\x3f\xca\x1f\x11\x3f\xb5\x14\x12\xbf\xba\xb6\x14\x3e\xf7\x70\x86\xbe\x24\x88\x48\xbd\x24\x88\x48\xbd\x6a\x10\x26\x3f\x6a\x10\x26\x3f\xb1\x59\x27\x3f\xe0\x6f\x15\x3e\x32\xee\xc4\x3e\x90\x08\xb6\xbd\x90\x08\xb6\xbd\xbb\x60\x39\x3f\xbb\x60\x39\x3f\x1e\xd7\x3a\xbf\x88\x29\x16\x3e\x6c\xc4\xe8\xbe\xe5\x5b\x05\xbe\xe5\x5b\x05\xbe\x1c\xd0\x4a\x3f\x1c\xd0\x4a\x3f\x1c\x48\x4c\x3f\xb3\xe3\x16\x3e\xea\x6e\xec\x3e\x2a\xa8\x50\xbe\x2a\xa8\x50\xbe\xf9\x21\x5a\x3f\xf9\x21\x5a\x3f\x63\x70\x5b\xbf\x5e\x9e\x17\x3e\xf7\x3b\xcf\xbe\x67\xb2\x54\xbe\x67\xb2\x54\xbe\xf0\x1c\x67\x3f\xf0\x1c\x67\x3f\x2a\x1b\x68\x3f\x8b\x59\x18\x3e\xb7\xd8\x94\x3e\x3d\xb8\xa0\xbe\x3d\xb8\xa0\xbe\x45\x8d\x71\x3f\x45\x8d\x71\x3f\x2a\x19\x72\xbf\x38\x15\x19\x3e\x04\x02\x0a\xbe\x10\xca\x90\xbe\x10\xca\x90\xbe\xcf\x44\x79\x3f\xcf\x44\x79\x3f\x65\x40\x79\x3f\x68\xd1\x19\x3e\x3e\x36\x2a\xbd\x94\xb6\xd2\xbe\x94\xb6\xd2\xbe\x3f\x1d\x7e\x3f\x3f\x1d\x7e\x3f\x2b\x6c\x7d\xbf\x18\x8e\x1a\x3e\x9f\xb7\x58\x3e\x1e\x6c\xb9\xbe\x1e\x6c\xb9\xbe\xbe\xf7\x7f\x3f\xbe\xf7\x7f\x3f\xa2\x7f\x7e\x3f\x4a\x4b\x1b\x3e\x80\x15\xb2\xbe\xf9\x32\xf9\xbe\xf9\x32\xf9\xbe\x27\xbf\x7e\x3f\x27\xbf\x7e\x3f\x0a\x67\x7c\xbf\xff\x08\x1c\x3e\x24\x20\xdb\x3e\x91\xb4\xe4\xbe\x91\xb4\xe4\xbe\x24\x67\x7a\x3f\x24\x67\x7a\x3f\x14\x1a\x77\x3f\x36\xc7\x1c\x3e\xb4\x11\xe1\xbe\x48\x4f\x0a\xbf\x48\x4f\x0a\xbf\xc9\xed\x72\x3f\xc9\xed\x72\x3f\x17\x9e\x6e\xbf\xf0\x85\x1d\x3e\x4b\x57\xc2\x3e\x23\x58\x07\xbf\x23\x58\x07\xbf\x57\x5a\x68\x3f\x57\x5a\x68\x3f\xbc\x05\x63\x3f\x2b\x45\x1e\x3e\xd7\xfa\x82\xbe\xb9\x6e\x14\xbf\xb9\x6e\x14\xbf\xa0\xbf\x5a\x3f\xa0\xbf\x5a\x3f\x6c\x6f\x54\xbf\xe6\x04\x1f\x3e\x1c\xf1\xb4\x3d\x37\x83\x18\xbf\x37\x83\x18\xbf\x36\x3a\x4a\x3f\x36\x3a\x4a\x3f\x6f\x03\x43\x3f\x22\xc5\x1f\x3e\xbb\x13\xc0\x3d\x8f\x87\x1c\xbf\x8f\x87\x1c\xbf\x96\xf2\x36\x3f\x96\xf2\x36\x3f\x0d\xf3\x2e\xbf\xdb\x85\x20\x3e\x75\xd1\x84\xbe\x55\xf6\x24\xbf\x55\xf6\x24\xbf\x35\x1c\x21\x3f\x35\x1c\x21\x3f\x33\x76\x18\x3f\x12\x47\x21\x3e\x59\xf1\xc2\x3e\x7c\x76\x22\xbf\x7c\x76\x22\xbf\x9e\xf5\x08\x3f\x9e\xf5\x08\x3f\x01\x9a\xff\xbe\xcb\x08\x22\x3e\x38\x70\xdf\xbe\x13\x3a\x2c\xbf\x13\x3a\x2c\xbf\x29\x90\xdd\x3e\x29\x90\xdd\x3e\xd2\x82\xca\x3e\x05\xcb\x22\x3e\x7d\x90\xd4\x3e\xee\x0a\x26\xbf\xee\x0a\x26\xbf\x6a\xce\xa5\x3e\x6a\xce\xa5\x3e\x0a\x51\x92\xbe\xc4\x8d\x23\x3e\x54\x24\xa3\xbe\xf3\x69\x2e\xbf\xf3\x69\x2e\xbf\x3e\xbd\x56\x3e\x3e\xbd\x56\x3e\xae\x8a\x2f\x3e\x08\x51\x24\x3e\xe1\xe6\x26\x3e\x45\x38\x27\xbf\x45\x38\x27\xbf\x05\x27\xbc\x3d\x05\x27\xbc\x3d\x02\xb3\x5d\xbd\xc3\x14\x25\x3e\x1d\x03\xc0\x3c\x34\x6e\x2a\xbf\x34\x6e\x2a\xbf\xab\x92\xe5\xbc\xab\x92\xe5\xbc\x6f\xe3\x83\xbd\xf6\xd8\x25\x3e\x30\x9a\x53\xbe\x07\x01\x27\xbf\x07\x01\x27\xbf\x2e\xd1\x17\xbe\x2e\xd1\x17\xbe\x38\xbd\x3a\x3e\xac\x9d\x26\x3e\xb2\x98\xb4\x3e\xd2\x98\x21\xbf\xd2\x98\x21\xbf\x6a\xbc\x88\xbe\x6a\xbc\x88\xbe\x0b\x94\x98\xbe\xe6\x62\x27\x3e\xb6\xb8\xdd\xbe\x6c\x7c\x21\xbf\x6c\x7c\x21\xbf\xf5\xe7\xc3\xbe\xf5\xe7\xc3\xbe\xbc\xba\xd1\x3e\x9e\x28\x28\x3e\x15\x12\xdc\x3e\x37\xc3\x17\xbf\x37\xc3\x17\xbf\x67\x7e\xfc\xbe\x67\x7e\xfc\xbe\xb7\xff\x03\xbf\xd4\xee\x28\x3e\x20\xd0\xae\xbe\xa7\x82\x15\xbf\xa7\x82\x15\xbf\x59\xca\x18\xbf\x59\xca\x18\xbf\x9a\x4c\x1d\x3f\x88\xb5\x29\x3e\xa8\x02\x3c\x3e\xbc\xb5\x0c\xbf\xbc\xb5\x0c\xbf\x2f\x23\x31\xbf\x2f\x23\x31\xbf\x21\x64\x34\xbf\xb8\x7c\x2a\x3e\xa2\x61\x54\x3c\xbe\x6e\x04\xbf\xbe\x6e\x04\xbf\xd0\xdc\x46\xbf\xd0\xdc\x46\xbf\xf5\xe9\x48\x3f\x68\x44\x2b\x3e\xca\x49\x55\xbe\x32\x72\xfd\xbe\x32\x72\xfd\xbe\xec\x91\x59\xbf\xec\x91\x59\xbf\x80\x85\x5a\xbf\x97\x0c\x2c\x3e\xe5\x8d\xb9\x3e\x8d\xa2\xe2\xbe\x8d\xa2\xe2\xbe\x65\xe6\x68\xbf\x65\xe6\x68\xbf\x90\xe3\x68\x3f\x43\xd5\x2c\x3e\x28\xf7\xe2\xbe\xa5\xee\xd6\xbe\xa5\xee\xd6\xbe\x8a\x89\x74\xbf\x8a\x89\x74\xbf\xc0\xb8\x73\xbf\x6c\x9e\x2d\x3e\x2d\x67\xdd\x3e\x53\x6a\xbc\xbe\x53\x6a\xbc\xbe\xee\x38\x7c\xbf\xee\x38\x7c\xbf\x9c\xc4\x7a\x3f\x12\x68\x2e\x3e\x54\xca\xa8\xbe\x0b\xc1\xa7\xbe\x0b\xc1\xa7\xbe\x26\xc1\x7f\xbf\x26\xc1\x7f\xbf\xd2\xd3\x7d\xbf\x36\x32\x2f\x3e\x91\xe3\x1e\x3e\x58\x56\x92\xbe\x58\x56\x92\xbe\x63\x00\x7f\xbf\x63\x00\x7f\xbf\x7c\xc2\x7c\x3f\xd6\xfc\x2f\x3e\x0d\x9d\x5f\x3d\x37\x8b\x6a\xbe\x37\x8b\x6a\xbe\x22\xe7\x79\xbf\x22\xe7\x79\xbf\x3c\x7c\x77\xbf\xf3\xc7\x30\x3e\x71\xa6\x82\xbe\xaf\xf0\x47\xbe\xaf\xf0\x47\xbe\xec\x78\x70\xbf\xec\x78\x70\xbf\xdc\xfd\x6d\x3f\x8e\x93\x31\x3e\xe2\x6b\xce\x3e\xb1\x19\x03\xbe\xb1\x19\x03\xbe\xe5\xcc\x62\xbf\xe5\xcc\x62\xbf\xcd\x56\x60\xbf\xa5\x5f\x32\x3e\x87\xc5\xed\xbe\x6f\x4b\xc1\xbd\x6f\x4b\xc1\xbd\xdc\x0d\x51\xbf\xdc\x0d\x51\xbf\x50\xaa\x4e\x3f\x38\x2c\x33\x3e\x5e\x5d\xd8\x3e\x45\xb5\xdd\xbc\x45\xb5\xdd\xbc\xce\x7a\x3b\xbf\xce\x7a\x3b\xbf\x44\x32\x39\xbf\x46\xf9\x33\x3e\xc0\x7d\x91\xbe\xf4\xaa\xb8\x3b\xf4\xaa\xb8\x3b\x6c\x66\x22\xbf\x6c\x66\x22\xbf\x6a\x40\x20\x3f\xd0\xc6\x34\x3e\xfd\xc2\xa0\x3d\xf5\x3d\xa9\x3d\xf5\x3d\xa9\x3d\x80\x36\x06\xbf\x80\x36\x06\xbf\x3e\x3f\x04\xbf\xd4\x94\x35\x3e\x97\x8c\x17\x3e\xcc\xb0\xcc\x3d\xcc\xb0\xcc\x3d\x15\xc6\xce\xbe\x15\xc6\xce\xbe\x0b\x5f\xcb\x3e\x54\x63\x36\x3e\xd8\x74\xaf\xbe\xc5\xdd\x41\x3e\xc5\xdd\x41\x3e\xaa\xe8\x8c\xbe\xaa\xe8\x8c\xbe\x46\x4a\x8a\xbe\x4f\x32\x37\x3e\x64\xb6\xeb\x3e\x8d\x92\x4b\x3e\x8d\x92\x4b\x3e\x80\x06\x10\xbe\x80\x06\x10\xbe\xf1\x05\x0d\x3e\xc6\x01\x38\x3e\xd7\x05\xf2\xbe\xdb\x24\x91\x3e\xdb\x24\x91\x3e\x0e\x2a\x2e\xbb\x0e\x2a\x2e\xbb\xb0\xfb\x2d\xbb\xb9\xd1\x38\x3e\x76\x3d\xc0\x3e\x42\xf4\x99\x3e\x42\xf4\x99\x3e\x0d\x67\x0b\x3e\x0d\x67\x0b\x3e\x53\xae\x07\xbe\x24\xa2\x39\x3e\xc1\x25\x42\xbe\x85\x05\xbb\x3e\x85\x05\xbb\x3e\x68\xc8\x8b\x3e\x68\xc8\x8b\x3e\xf8\xc9\x87\x3e\x08\x73\x3a\x3e\xd4\xb1\x32\xbd\x19\x9c\xcb\x3e\x19\x9c\xcb\x3e\xd6\x7a\xcf\x3e\xd6\x7a\xcf\x3e\xd3\x3d\xc9\xbe\x66\x44\x3b\x3e\x5e\x17\x8a\x3e\x3b\xaa\xe1\x3e\x3b\xaa\xe1\x3e\x36\xb3\x07\x3f\x36\xb3\x07\x3f\x7d\x80\x03\x3f\x3e\x16\x3c\x3e\x38\x4c\xdd\xbe\x51\x03\xf5\x3e\x51\x03\xf5\x3e\x46\x19\x25\x3f\x46\x19\x25\x3f\x0e\xf7\x1f\xbf\x90\xe8\x3c\x3e\xb8\x08\xfa\x3e\x1f\xd4\x03\x3f\x1f\xd4\x03\x3f\x4f\x4b\x3f\x3f\x4f\x4b\x3f\x3f\x30\x74\x39\x3f\x59\xbb\x3d\x3e\x35\x68\xd8\xbe\x89\x34\x0a\x3f\x89\x34\x0a\x3f\x01\xb2\x55\x3f\x01\xb2\x55\x3f\xb7\x6c\x4f\xbf\x9c\x8e\x3e\x3e\x1d\xb4\x80\x3e\xdb\x22\x14\x3f\xdb\x22\x14\x3f\xcd\xc5\x67\x3f\xcd\xc5\x67\x3f\xae\x5b\x61\x3f\x56\x62\x3f\x3e\x3b\x16\x86\xbc\x6a\x58\x18\x3f\x6a\x58\x18\x3f\xa5\x12\x75\x3f\xa5\x12\x75\x3f\xbc\xc6\x6e\xbf\x8a\x36\x40\x3e\x8c\xb5\x65\xbe\xa8\xb4\x1d\x3f\xa8\xb4\x1d\x3f\x53\x3b\x7d\x3f\x53\x3b\x7d\x3f\xd6\x44\x77\x3f\x35\x0b\x41\x3e\xf6\xce\xd1\x3e\x77\x1b\x25\x3f\x77\x1b\x25\x3f\xbc\xfd\x7f\x3f\xbc\xfd\x7f\x3f\xc8\x82\x7a\xbf\x58\xe0\x41\x3e\x11\x54\xfb\xbe\xcc\x94\x23\x3f\xcc\x94\x23\x3f\x27\x34\x7d\x3f\x27\x34\x7d\x3f\x33\x4a\x78\x3f\xf2\xb5\x42\x3e\xf5\x43\xe3\x3e\x0e\xb9\x2b\x3f\x0e\xb9\x2b\x3f\x8b\xd8\x74\x3f\x8b\xd8\x74\x3f\x95\x84\x70\xbf\x02\x8c\x43\x3e\xf9\x30\x8f\xbe\x0c\x0c\x28\x3f\x0c\x0c\x28\x3f\x89\x04\x67\x3f\x89\x04\x67\x3f\xe7\x3f\x63\x3f\x89\x62\x44\x3e\x83\x1a\x2b\x3d\x52\xa0\x2b\x3f\x52\xa0\x2b\x3f\x86\xf3\x53\x3f\x86\xf3\x53\x3f\x12\xae\x50\xbf\x86\x39\x45\x3e\x8b\x01\x52\x3e\xf9\x4d\x2a\x3f\xf9\x4d\x2a\x3f\xd9\xff\x3b\x3f\xd9\xff\x3b\x3f\x5b\x25\x39\x3f\xfb\x10\x46\x3e\xd6\x13\xc9\xbe\xc7\xfd\x26\x3f\xc7\xfd\x26\x3f\x16\xa3\x1f\x3f\x16\xa3\x1f\x3f\x53\x1f\x1d\xbf\xe5\xe8\x46\x3e\xc5\xcb\xef\x3e\xe8\x89\x26\x3f\xe8\x89\x26\x3f\x35\xe7\xfe\x3e\x35\xe7\xfe\x3e\x64\x6d\xfa\x3e\x45\xc1\x47\x3e\x85\x04\xd2\xbe\xd7\x00\x21\x3f\xd7\x00\x21\x3f\x59\x45\xb8\x3e\x59\x45\xb8\x3e\x3a\x46\xb4\xbe\x1a\x9a\x48\x3e\xb8\xc7\x6f\x3e\xce\xf2\x1b\x3f\xce\xf2\x1b\x3f\x96\xe1\x59\x3e\x96\xe1\x59\x3e\x92\xcf\x52\x3e\x65\x73\x49\x3e\x86\x93\x26\x3c\x7e\x31\x19\x3f\x7e\x31\x19\x3f\x0f\x1e\x75\x3d\x0f\x1e\x75\x3d\x1c\xa8\x5c\xbd\x23\x4d\x4a\x3e\x28\x7e\x81\xbe\xc3\xb2\x0c\x3f\xc3\xb2\x0c\x3f\xcd\x29\xc3\xbd\xcd\x29\xc3\xbd\x22\x68\xcd\xbd\x54\x27\x4b\x3e\x8a\x00\xd9\x3e\xc3\x60\x0b\x3f\xc3\x60\x0b\x3f\xc6\xde\x7e\xbe\xc6\xde\x7e\xbe\xe3\x87\x81\x3e\xfa\x01\x4c\x3e\x5d\xdf\xf1\xbe\xe8\xf9\xfc\x3e\xe8\xf9\xfc\x3e\x79\x57\xcb\xbe\x79\x57\xcb\xbe\x4d\x1b\xcd\xbe\x14\xdd\x4c\x3e\x56\x0f\xc4\x3e\x9c\x49\xeb\x3e\x9c\x49\xeb\x3e\x6e\x4a\x09\xbf\x6e\x4a\x09\xbf\x51\x24\x0a\x3f\xa2\xb8\x4d\x3e\x3a\xf7\x38\xbe\xb2\xe1\xdd\x3e\xb2\xe1\xdd\x3e\x79\xa6\x29\xbf\x79\xa6\x29\xbf\x5f\xab\x2a\xbf\xa2\x94\x4e\x3e\x89\x2a\x97\xbd\x23\xd8\xbb\x3e\x23\xd8\xbb\x3e\x10\xe2\x45\xbf\x10\xe2\x45\xbf\xd8\x50\x47\x3f\x15\x71\x4f\x3e\x64\xd7\x9a\x3e\xfc\x4f\xb3\x3e\xfc\x4f\xb3\x3e\x0a\x36\x5d\xbf\x0a\x36\x5d\xbf\x93\x4d\x5f\xbf\xf8\x4d\x50\x3e\x70\x72\xde\xbe\x5f\xa4\x8e\x3e\x5f\xa4\x8e\x3e\xf6\xf6\x6e\xbf\xf6\xf6\x6e\xbf\xca\xe7\x71\x3f\x4e\x2b\x51\x3e\x55\x30\xdb\x3e\x8a\xcd\x7b\x3e\x8a\xcd\x7b\x3e\x9d\x9a\x7a\xbf\x9d\x9a\x7a\xbf\x7e\x79\x7e\xbf\x17\x09\x52\x3e\x1c\x3d\x91\xbe\x97\x6a\x42\x3e\x97\x6a\x42\x3e\x82\xbc\x7f\xbf\x82\xbc\x7f\xbf\xc7\x3c\x82\x3f\x50\xe7\x52\x3e\xbc\x3a\x39\x3d\xbf\x92\x0a\x3e\xbf\x92\x0a\x3e\xa1\x22\x7e\xbf\xa1\x22\x7e\xbf\x59\xc3\x81\xbf\xf8\xc5\x53\x3e\x0e\xff\x59\x3e\x9e\xe1\xb7\x3d\x9e\xe1\xb7\x3d\x97\xbe\x75\xbf\x97\xbe\x75\xbf\xb4\x73\x7b\x3f\x12\xa5\x54\x3e\x3f\x10\xd1\xbe\xa2\x18\x01\x3d\xa2\x18\x01\x3d\x93\xb1\x66\xbf\x93\xb1\x66\xbf\xce\x50\x6c\xbf\x9b\x84\x55\x3e\xdb\x1b\xf4\x3e\xc0\x54\xc4\xbc\xc0\x54\xc4\xbc\x12\x4c\x51\xbf\x12\x4c\x51\xbf\x20\x72\x56\x3f\x94\x64\x56\x3e\x63\x0d\xc9\xbe\xec\x46\x88\xbd\xec\x46\x88\xbd\xe7\x0d\x36\xbf\xe7\x0d\x36\xbf\xcd\x6e\x3a\xbf\xfc\x44\x57\x3e\x0e\xae\x37\x3e\xf1\x83\x09\xbe\xf1\x83\x09\xbe\xcb\xa3\x15\xbf\xcb\xa3\x15\xbf\x42\x1b\x19\x3f\xd2\x25\x58\x3e\x7c\x54\xc4\x3d\xa8\xef\x34\xbe\xa8\xef\x34\xbe\x7c\xc9\xe1\xbe\x7c\xc9\xe1\xbe\xf8\xfa\xe6\xbe\x16\x07\x59\x3e\x10\x48\xaf\xbe\xc4\x5d\x65\xbe\xc4\x5d\x65\xbe\x46\x98\x91\xbe\x46\x98\x91\xbe\x0f\x7e\x95\x3e\xc8\xe8\x59\x3e\xa4\x01\xf4\x3e\x3e\xf3\x95\xbe\x3e\xf3\x95\xbe\xa8\x9b\xf3\xbd\xa8\x9b\xf3\xbd\x63\x72\x00\xbe\xe7\xca\x5a\x3e\xbc\xb2\xe7\xbe\x34\x15\x9f\xbe\x34\x15\x9f\xbe\x3d\x52\x4f\x3d\x3d\x52\x4f\x3d\xb4\x7a\x32\xbd\x74\xad\x5b\x3e\x15\x5c\x8e\x3e\x35\xd3\xc6\xbe\x35\xd3\xc6\xbe\x4f\xb9\x60\x3e\x4f\xb9\x60\x3e\x67\x4c\x57\x3e\x6d\x90\x5c\x3e\x4f\x95\x3e\xbc\xe9\x9e\xd0\xbe\xe9\x9e\xd0\xbe\x03\xe8\xc3\x3e\x03\xe8\xc3\x3e\x67\x70\xbd\xbe\xd2\x73\x5d\x3e\x37\x99\x83\xbe\x1f\xca\xe9\xbe\x1f\xca\xe9\xbe\x4b\x05\x09\x3f\x4b\x05\x09\x3f\xb9\xbb\x04\x3f\xa3\x57\x5e\x3e\x66\x11\xdf\x3e\xc4\x38\x01\xbf\xc4\x38\x01\xbf\xa7\x2f\x2c\x3f\xa7\x2f\x2c\x3f\x9f\xd6\x26\xbf\xde\x3b\x5f\x3e\xf9\xf0\xeb\xbe\x18\x7f\x03\xbf\x18\x7f\x03\xbf\xc8\x56\x4a\x3f\xc8\x56\x4a\x3f\x14\x18\x44\x3f\x84\x20\x60\x3e\x15\xd9\xa4\x3e\x1e\xa1\x13\xbf\x1e\xa1\x13\xbf\x97\x7e\x62\x3f\x97\x7e\x62\x3f\xde\xa6\x5b\xbf\x94\x05\x61\x3e\x74\x3f\x8b\xbd\x57\x4a\x13\xbf\x57\x4a\x13\xbf\x70\xd4\x73\x3f\x70\xd4\x73\x3f\x7c\xc4\x6c\x3f\x0f\xeb\x61\x3e\xf8\xd6\x56\xbe\xd5\x24\x1e\xbf\xd5\x24\x1e\xbf\x02\xb8\x7d\x3f\x02\xb8\x7d\x3f\x74\xd3\x76\xbf\xf2\xd0\x62\x3e\xb4\xa6\xd1\x3e\x7b\x41\x21\xbf\x7b\x41\x21\xbf\x0d\xc1\x7f\x3f\x0d\xc1\x7f\x3f\x46\x5e\x79\x3f\x3d\xb7\x63\x3e\xb5\x2e\xe9\xbe\xdd\x22\x25\xbf\xdd\x22\x25\xbf\x1c\xc5\x79\x3f\x1c\xc5\x79\x3f\x78\x1f\x74\xbf\xf1\x9d\x64\x3e\x1f\xe8\xa7\x3e\xe5\xfb\x27\xbf\xe5\xfb\x27\xbf\x57\xda\x6b\x3f\x57\xda\x6b\x3f\x2a\x0a\x67\x3f\x0d\x85\x65\x3e\xfc\x52\x95\xbd\x60\xd9\x2b\xbf\x60\xd9\x2b\xbf\x77\x59\x56\x3f\x77\x59\x56\x3f\xd4\x52\x52\xbf\x8f\x6c\x66\x3e\xbb\x21\x5c\xbe\xc0\x48\x27\xbf\xc0\x48\x27\xbf\xbb\xdb\x39\x3f\xbb\xdb\x39\x3f\x68\x74\x36\x3f\x77\x54\x67\x3e\xbf\x41\xdb\x3e\xe2\xe9\x2d\xbf\xe2\xe9\x2d\xbf\xa1\x37\x17\x3f\xa1\x37\x17\x3f\x3f\x33\x14\xbf\xc6\x3c\x68\x3e\xdd\x13\xf9\xbe\x92\xb0\x25\xbf\x92\xb0\x25\xbf\x77\xf7\xde\x3e\x77\xf7\xde\x3e\xd3\x32\xd9\x3e\x7b\x25\x69\x3e\xe8\x71\xbb\x3e\xf6\xd0\x25\xbf\xf6\xd0\x25\xbf\x0a\xcf\x87\x3e\x0a\xcf\x87\x3e\xeb\xde\x81\xbe\x94\x0e\x6a\x3e\x4c\xfe\xe4\xbd\x2f\xa5\x24\xbf\x2f\xa5\x24\xbf\x71\x0b\xaf\x3d\x71\x0b\xaf\x3d\x1a\x89\x95\x3d\x11\xf8\x6a\x3e\xe6\x90\x37\xbe\xa1\x18\x17\xbf\xa1\x18\x17\xbf\xd4\x94\xc8\xbd\xd4\x94\xc8\xbd\x22\x17\xe4\x3d\xf1\xe1\x6b\x3e\xff\x37\xca\x3e\x62\xa0\x1d\xbf\x62\xa0\x1d\xbf\x7c\xc0\x8e\xbe\x7c\xc0\x8e\xbe\x46\xfa\x95\xbe\x35\xcc\x6c\x3e\xcc\xa0\xe6\xbe\x20\xd7\x08\xbf\x20\xd7\x08\xbf\x1c\xdf\xe6\xbe\x1c\xdf\xe6\xbe\xae\x21\xee\x3e\xdb\xb6\x6d\x3e\xa8\xb5\xa4\x3e\x6f\x70\x0c\xbf\x6f\x70\x0c\xbf\xde\xb3\x1b\xbf\xde\xb3\x1b\xbf\xc9\x24\x1f\xbf\xe4\xa1\x6e\x3e\xa9\xc7\x6e\xbd\xd5\x4a\xf8\xbe\xd5\x4a\xf8\xbe\x75\xba\x3e\xbf\x75\xba\x3e\xbf\x42\xc3\x41\x3f\x4e\x8d\x6f\x3e\x4d\xd2\x6f\xbe\xce\x4f\xe9\xbe\xce\x4f\xe9\xbe\xc0\x37\x5b\xbf\xc0\x37\x5b\xbf\x5a\xa8\x5d\xbf\x18\x79\x70\x3e\xf4\xb8\xdf\x3e\x0e\xcd\xd6\xbe\x0e\xcd\xd6\xbe\x5b\x15\x70\xbf\x5b\x15\x70\xbf\x18\xcd\x71\x3f\x42\x65\x71\x3e\x48\xb6\xee\xbe\x30\x3c\xba\xbe\x30\x3c\xba\xbe\x3d\x7d\x7c\xbf\x3d\x7d\x7c\xbf\x5c\x6f\x7d\xbf\xcc\x51\x72\x3e\x3b\x8f\x9d\x3e\x43\x61\xa6\xbe\x43\x61\xa6\xbe\x73\xe4\x7f\xbf\x73\xe4\x7f\xbf\x98\x0b\x80\x3f\xb3\x3e\x73\x3e\x14\xe8\xc9\xbc\x0b\x22\x8d\xbe\x0b\x22\x8d\xbe\xe3\x10\x7a\xbf\xe3\x10\x7a\xbf\xc8\x9c\x79\xbf\xf8\x2b\x74\x3e\x28\x7a\x88\xbe\xa7\x11\x5e\xbe\xa7\x11\x5e\xbe\xfa\x1b\x6b\xbf\xfa\x1b\x6b\xbf\x52\x29\x6a\x3f\x9b\x19\x75\x3e\xa3\x40\xe3\x3e\x6c\x31\x32\xbe\x6c\x31\x32\xbe\x56\x76\x53\xbf\x56\x76\x53\xbf\x04\x36\x52\xbf\x9b\x07\x76\x3e\x99\x13\xdd\xbe\x1f\xb3\xeb\xbd\x1f\xb3\xeb\xbd\xb0\xe5\x33\xbf\xb0\xe5\x33\xbf\xc4\x87\x32\x3f\xf7\xf5\x76\x3e\x56\xf6\x6f\x3e\x7a\x9b\x5c\xbd\x7a\x9b\x5c\xbd\xb4\x7e\x0d\xbf\xb4\x7e\x0d\xbf\x42\x2c\x0c\xbf\xae\xe4\x77\x3e\x9b\x32\x85\x3d\x1a\x5f\x9a\xbc\x1a\x5f\x9a\xbc\x81\x3a\xc3\xbe\x81\x3a\xc3\xbe\xac\xe5\xc0\x3e\xc0\xd3\x78\x3e\xf6\xea\xac\xbe\xa3\xf2\x8a\x3d\xa3\xf2\x8a\x3d\x96\x6d\x47\xbe\x96\x6d\x47\xbe\x4b\x95\x43\xbe\x2a\xc3\x79\x3e\xb2\xfb\xed\x3e\x35\x36\xb3\x3d\x35\x36\xb3\x3d\x0b\xa4\xb9\xb7\x0b\xa4\xb9\xb7\x36\x8d\x44\xbb\x03\xc1\x7a\x3e\x8a\x0a\xc7\xbe\x61\xc3\x31\x3e\x61\xc3\x31\x3e\x96\x26\x48\x3e\x96\x26\x48\x3e\xaf\xca\x4a\x3e\x49\xcd\x7b\x3e\x78\xfd\x0e\x3e\x16\x25\x52\x3e\x16\x25\x52\x3e\x94\xa7\xc4\x3e\x94\xa7\xc4\x3e\x22\xfa\xc5\xbe\x12\xc2\x7c\x3e\xad\x5f\x34\x3e\x53\xe8\x87\x3e\x53\xe8\x87\x3e\xa0\xf3\x0e\x3f\xa0\xf3\x0e\x3f\x0c\xbd\x0f\x3f\x5d\x9f\x7d\x3e\xc1\xe2\xd6\xbe\xb9\x84\xa3\x3e\xb9\x84\xa3\x3e\xd1\x1b\x36\x3f\xd1\x1b\x36\x3f\x7d\x1f\x37\xbf\x69\x87\x7e\x3e\xf7\x2f\xf6\x3e\xac\x07\xb8\x3e\xac\x07\xb8\x3e\x65\x2e\x56\x3f\x65\x2e\x56\x3f\x93\x7a\x57\x3f\x34\x7a\x7f\x3e\x7d\x3a\xa9\xbe\xd2\x92\xcf\x3e\xd2\x92\xcf\x3e\xb1\xce\x6d\x3f\xb1\xce\x6d\x3f\xae\x63\x6f\xbf\xb2\x36\x80\x3e\x8f\x40\x14\x3d\x21\xb5\xec\x3e\x21\xb5\xec\x3e\xf7\xef\x7b\x3f\xf7\xef\x7b\x3f\x8d\xc2\x7d\x3f\x7d\xb0\x80\x3e\xdf\x36\x89\x3e\xa3\x5c\xf3\x3e\xa3\x5c\xf3\x3e\xbc\xe3\x7f\x3f\xbc\xe3\x7f\x3f\x26\xf0\x80\xbf\x79\x2a\x81\x3e\xaf\xa6\xe2\xbe\xa2\x26\x0a\x3f\xa2\x26\x0a\x3f\x86\x62\x79\x3f\x86\x62\x79\x3f\xda\x73\x7b\x3f\xa7\xa4\x81\x3e\x42\x68\xd0\x3e\xf6\xbe\x0d\x3f\xf6\xbe\x0d\x3f\x93\x91\x68\x3f\x93\x91\x68\x3f\xa8\xa8\x6a\xbf\x06\x1f\x82\x3e\x14\x5f\x34\xbe\x0d\x81\x15\x3f\x0d\x81\x15\x3f\x81\x05\x4e\x3f\x81\x05\x4e\x3f\xa2\x1e\x50\x3f\x95\x99\x82\x3e\x1a\x8b\x12\xbe\xba\xb5\x1f\x3f\xba\xb5\x1f\x3f\xef\xbe\x2a\x3f\xef\xbe\x2a\x3f\xaf\xe2\x2c\xbf\x56\x14\x83\x3e\x35\xbd\xcc\x3e\x72\x64\x1d\x3f\x72\x64\x1d\x3f\x26\x22\x00\x3f\x26\x22\x00\x3f\xec\x61\x02\x3f\x49\x8f\x83\x3e\x10\xbb\xf0\xbe\xba\x74\x2a\x3f\xba\x74\x2a\x3f\x7d\xd5\x9f\x3e\x7d\xd5\x9f\x3e\x45\xb5\xa4\xbe\x6c\x0a\x84\x3e\x77\x8f\xa2\x3e\x81\x1e\x25\x3f\x81\x1e\x25\x3f\x00\xd7\xe0\x3d\x00\xd7\xe0\x3d\x11\x4c\xf6\x3d\xc0\x85\x84\x3e\xf5\x86\x4c\xbc\x55\x6c\x2b\x3f\x55\x6c\x2b\x3f\x60\xd2\xc8\xbd\x60\xd2\xc8\xbd\xd6\x50\xb1\x3d\x46\x01\x85\x3e\xeb\x0b\x99\xbe\x13\xda\x2b\x3f\x13\xda\x2b\x3f\xe6\xd0\x9a\xbe\xe6\xd0\x9a\xbe\x39\x87\x94\xbe\xfd\x7c\x85\x3e\x25\xef\xed\x3e\x4e\x16\x27\x3f\x4e\x16\x27\x3f\x69\x06\xfd\xbe\x69\x06\xfd\xbe\x29\x89\xf6\x3e\xe6\xf8\x85\x3e\xdf\xb1\xcd\xbe\xf3\x45\x2a\x3f\xf3\x45\x2a\x3f\x96\x37\x2a\xbf\x96\x37\x2a\xbf\xba\x03\x27\xbf\xfe\x74\x86\x3e\x79\x38\x0e\x3e\x02\x9a\x23\x3f\x02\x9a\x23\x3f\x28\x86\x4e\xbf\x28\x86\x4e\xbf\x9d\x84\x4b\x3f\x48\xf1\x86\x3e\x8e\x9b\x47\x3e\xf0\xb9\x1e\x3f\xf0\xb9\x1e\x3f\x73\xba\x69\xbf\x73\xba\x69\xbf\x49\x10\x67\xbf\xc0\x6d\x87\x3e\x4b\x27\xde\xbe\x28\x70\x1d\x3f\x28\x70\x1d\x3f\x63\x81\x7a\xbf\x63\x81\x7a\xbf\x3c\x4b\x78\x3f\x68\xea\x87\x3e\x12\x96\xea\x3e\xc7\x57\x10\x3f\xc7\x57\x10\x3f\x51\xfa\x7f\xbf\x51\xfa\x7f\xbf\x54\x4b\x7e\xbf\x3d\x67\x88\x3e\xa7\x7c\x82\xbe\x10\x41\x0e\x3f\x10\x41\x0e\x3f\x16\xc5\x79\xbf\x16\xc5\x79\xbf\x0a\xa8\x78\x3f\x43\xe4\x88\x3e\x04\xff\x97\xbd\xa6\xa4\x02\x3f\xa6\xa4\x02\x3f\x3d\x0a\x68\xbf\x3d\x0a\x68\xbf\xf3\x84\x67\xbf\x79\x61\x89\x3e\xab\x8a\xb9\x3e\x4f\xa2\xef\x3e\x4f\xa2\xef\x3e\x0b\x7d\x4b\xbf\x0b\x7d\x4b\xbf\x25\x93\x4b\x3f\xe1\xde\x89\x3e\xf9\x49\xec\xbe\x95\xee\xe2\x3e\x95\xee\xe2\x3e\xdf\x55\x25\xbf\xdf\x55\x25\xbf\x00\x0b\x26\xbf\x7c\x5c\x8a\x3e\x0a\x29\xa3\x3e\x50\xe4\xbf\x3e\x50\xe4\xbf\x3e\x8d\x8d\xee\xbe\x8d\x8d\xee\xbe\x42\x3b\xf1\x3e\x41\xda\x8a\x3e\x42\x73\xd0\xbb\x16\x66\xb2\x3e\x16\x66\xb2\x3e\xfc\xd2\x86\xbe\xfc\xd2\x86\xbe\x00\xc1\x8a\xbe\x30\x58\x8b\x3e\xfd\x3c\xa0\xbe\x47\xe2\x92\x3e\x47\xe2\x92\x3e\x73\x8b\x42\xbd\x73\x8b\x42\xbd\x9e\x42\x6b\x3d\x51\xd6\x8b\x3e\xf6\x30\xf1\x3e\x2d\x26\x6e\x3e\x2d\x26\x6e\x3e\x6f\x74\x2f\x3e\x6f\x74\x2f\x3e\x01\x5e\x23\x3e\xa2\x54\x8c\x3e\x0e\xfc\xc3\xbe\xd6\x46\x41\x3e\xd6\x46\x41\x3e\xc9\xe9\xc3\x3e\xc9\xe9\xc3\x3e\xb5\x3f\xbd\xbe\x22\xd3\x8c\x3e\x5f\xfa\xbc\x3d\xf0\x56\xfd\x3d\xf0\x56\xfd\x3d\xc8\x77\x13\x3f\xc8\x77\x13\x3f\x40\x0b\x10\x3f\xcf\x51\x8d\x3e\xdc\x4e\x7d\x3e\xda\xa6\x86\x3d\xda\xa6\x86\x3d\xa0\xec\x3d\x3f\xa0\xec\x3d\x3f\x6a\xa6\x3a\xbf\xaa\xd0\x8d\x3e\x83\x47\xe8\xbe\x54\x0a\xd3\x3c\x54\x0a\xd3\x3c\x0c\x28\x5f\x3f\x0c\x28\x5f\x3f\xab\x40\x5c\x3f\xb4\x4f\x8e\x3e\x6d\x3b\xd3\x3e\x98\xf9\x82\xbd\x98\xf9\x82\xbd\xde\x69\x75\x3f\xde\x69\x75\x3f\x24\x09\x73\xbf\xeb\xce\x8e\x3e\xf8\x2e\x12\xbe\x20\xff\xa5\xbd\x20\xff\xa5\xbd\x7e\x77\x7f\x3f\x7e\x77\x7f\x3f\xc2\xa9\x7d\x3f\x50\x4e\x8f\x3e\x9e\xf3\x57\xbe\xbe\xa8\x31\xbe\xbe\xa8\x31\xbe\x99\xae\x7c\x3f\x99\xae\x7c\x3f\xf7\x61\x7b\xbf\xe2\xcd\x8f\x3e\x56\xc5\xe8\x3e\xb5\x6f\x54\xbe\xb5\x6f\x54\xbe\x8f\x11\x6d\x3f\x8f\x11\x6d\x3f\xaa\x19\x6c\x3f\xa2\x4d\x90\x3e\xbc\xd0\xe7\xbe\xc4\x5f\x86\xbe\xc4\x5f\x86\xbe\x30\x4b\x51\x3f\x30\x4b\x51\x3f\xb1\x6d\x50\xbf\x8d\xcd\x90\x3e\x21\x77\x51\x3e\x1d\xf0\xa9\xbe\x1d\xf0\xa9\xbe\x5a\xaa\x2a\x3f\x5a\xaa\x2a\x3f\xe8\xae\x29\x3f\xa6\x4d\x91\x3e\xb4\xdf\x1c\x3e\x25\xc0\xb3\xbe\x25\xc0\xb3\xbe\x6c\x28\xf6\x3e\x6c\x28\xf6\x3e\xde\xa9\xf3\xbe\xec\xcd\x91\x3e\xbb\x7b\xd7\xbe\xe6\x66\xdc\xbe\xe6\x66\xdc\xbe\x99\xda\x89\x3e\x99\xda\x89\x3e\x82\xc6\x86\x3e\x5f\x4e\x92\x3e\x1b\x1b\xe5\x3e\x82\x6e\xe6\xbe\x82\x6e\xe6\xbe\x7b\xc7\x2f\x3d\x7b\xc7\x2f\x3d\x79\x22\x14\xbd\xff\xce\x92\x3e\x32\x95\x5f\xbe\xc7\x91\xff\xbe\xc7\x91\xff\xbe\x12\xe3\x3e\xbe\x12\xe3\x3e\xbe\x6e\xb8\x45\xbe\xcc\x4f\x93\x3e\x58\x03\x09\xbe\x11\x86\x0a\xbf\x11\x86\x0a\xbf\x69\x2c\xd0\xbe\x69\x2c\xd0\xbe\xec\x0b\xd3\x3e\xc4\xd0\x93\x3e\x27\xa0\xce\x3e\xa7\x16\x0f\xbf\xa7\x16\x0f\xbf\x10\x12\x1b\xbf\x10\x12\x1b\xbf\x8b\x03\x1c\xbf\xe8\x51\x94\x3e\x0b\x4c\xdd\xbe\x8d\xfc\x1a\xbf\x8d\xfc\x1a\xbf\x8e\xdf\x45\xbf\x8e\xdf\x45\xbf\xf4\x34\x46\x3f\x38\xd3\x94\x3e\xe7\xbb\x4d\x3e\xa4\x5c\x1d\xbf\xa4\x5c\x1d\xbf\x9a\x17\x66\xbf\x9a\x17\x66\xbf\x0d\xd7\x65\xbf\xb3\x54\x95\x3e\x6d\x5c\x20\x3e\xbf\x71\x22\xbf\xbf\x71\x22\xbf\x0b\xdc\x79\xbf\x0b\xdc\x79\xbf\x6e\x2f\x79\x3f\x5a\xd6\x95\x3e\xb8\xad\xdc\xbe\x91\x83\x2a\xbf\x91\x83\x2a\xbf\x0b\xf7\x7f\xbf\x0b\xf7\x7f\xbf\xdb\x1e\x7f\xbf\x2b\x58\x96\x3e\x3e\x5e\xeb\x3e\x6d\xd7\x25\xbf\x6d\xd7\x25\xbf\x14\xf0\x77\xbf\x14\xf0\x77\xbf\xa1\x2e\x77\x3f\x2a\xda\x96\x3e\xb2\x0f\x64\xbe\x6f\x8b\x2c\xbf\x6f\x8b\x2c\xbf\x0f\x16\x62\xbf\x0f\x16\x62\xbf\xc3\x9a\x61\xbf\x54\x5c\x97\x3e\x96\x6b\x12\xbe\xd1\x65\x2a\xbf\xd1\x65\x2a\xbf\x57\x81\x3f\xbf\x57\x81\x3f\xbf\xe8\x57\x3f\x3f\xa8\xde\x97\x3e\x2a\xe1\xd7\x3e\xd0\xab\x27\xbf\xd0\xab\x27\xbf\x4f\x06\x12\xbf\x4f\x06\x12\xbf\x56\x14\x12\xbf\x25\x61\x98\x3e\x7d\x20\xe4\xbe\x0d\x0c\x27\xbf\x0d\x0c\x27\xbf\x95\x3f\xb8\xbe\x95\x3f\xb8\xbe\x45\x59\xb8\x3e\xcd\xe3\x98\x3e\x3f\x54\x4b\x3e\x06\xdd\x20\xbf\x06\xdd\x20\xbf\x82\x34\x03\xbe\x82\x34\x03\xbe\x39\x5c\x02\xbe\xa0\x66\x99\x3e\xc5\xb0\x2e\x3e\xbc\xf8\x1c\xbf\xbc\xf8\x1c\xbf\xd2\xb9\xe4\x3d\xd2\xb9\xe4\x3d\x62\x14\xea\xbd\x9d\xe9\x99\x3e\x3f\x71\xdf\xbe\x2c\xb2\x15\xbf\x2c\xb2\x15\xbf\xac\x0b\xb1\x3e\xac\x0b\xb1\x3e\x2c\x6b\xb3\x3e\xc4\x6c\x9a\x3e\x01\x6e\xde\x3e\x92\x65\x0d\xbf\x92\x65\x0d\xbf\xad\x7e\x0f\x3f\xad\x7e\x0f\x3f\x4d\x16\x11\xbf\x14\xf0\x9a\x3e\xd8\x64\x27\xbe\x73\x38\x06\xbf\x73\x38\x06\xbf\xc1\x3d\x3e\x3f\xc1\x3d\x3e\x3f\x26\xf9\x3f\x3f\x8c\x73\x9b\x3e\x65\x20\x56\xbe\x2c\x1e\xf4\xbe\x2c\x1e\xf4\xbe\x10\xed\x61\x3f\x10\xed\x61\x3f\xf9\x70\x63\xbf\x2f\xf7\x9b\x3e\x81\x38\xe6\x3e\xc6\x03\xe1\xbe\xc6\x03\xe1\xbe\x60\x53\x78\x3f\x60\x53\x78\x3f\xa5\x44\x79\x3f\xfc\x7a\x9c\x3e\x72\x80\xcf\xbe\xae\x00\xcc\xbe\xae\x00\xcc\xbe\xa7\xf9\x7f\x3f\xa7\xf9\x7f\x3f\x82\x0a\x80\xbf\xf1\xfe\x9c\x3e\x7a\x8c\xd0\x3d\x47\xf5\xa8\xbe\x47\xf5\xa8\xbe\x0c\x47\x78\x3f\x0c\x47\x78\x3f\x78\x73\x77\x3f\x0f\x83\x9d\x3e\x00\x91\x89\x3e\x11\xce\x9d\xbe\x11\xce\x9d\xbe\x4b\x8e\x61\x3f\x4b\x8e\x61\x3f\x2b\xe2\x5f\xbf\x56\x07\x9e\x3e\x57\xdd\xef\xbe\x55\x81\x64\xbe\x55\x81\x64\xbe\x59\x0e\x3d\x3f\x59\x0e\x3d\x3f\x10\xca\x3a\x3f\xc4\x8b\x9e\x3e\x46\x8e\xbb\x3e\xe2\x0b\x41\xbe\xe2\x0b\x41\xbe\x71\xe3\x0c\x3f\x71\xe3\x0c\x3f\x3d\x61\x0a\xbf\x5c\x10\x9f\x3e\xfa\x00\xce\xbc\x97\x94\xfb\xbd\x97\x94\xfb\xbd\xed\xd2\xa7\x3e\xed\xd2\xa7\x3e\xc2\x0f\xa3\x3e\x1b\x95\x9f\x3e\xae\x52\xac\xbe\x01\x31\x78\xbd\x01\x31\x78\xbd\x9f\x98\xac\x3d\x9f\x98\xac\x3d\xf1\xe9\x9c\xbd\x02\x1a\xa0\x3e\x1e\x7a\xf8\x3e\x5f\x20\x50\xbc\x5f\x20\x50\xbc\xf1\x2b\x29\xbe\xf1\x2b\x29\xbe\xc6\xbe\x2e\xbe\x11\x9f\xa0\x3e\x3c\x98\xa5\xbe\x40\x0f\x7d\x3d\x40\x0f\x7d\x3d\x71\x69\xcf\xbe\x71\x69\xcf\xbe\xec\x22\xd1\x3e\x46\x24\xa1\x3e\x63\x65\x34\xbd\x62\x68\xd9\x3d\x62\x68\xd9\x3d\x8e\xc5\x1e\xbf\x8e\xc5\x1e\xbf\x7a\x53\x1f\xbf\xa4\xa9\xa1\x3e\xea\x12\xc0\x3e\x04\xdf\x32\x3e\x04\xdf\x32\x3e\xce\xef\x4b\xbf\xce\xef\x4b\xbf\xfb\x90\x4c\x3f\x28\x2f\xa2\x3e\x55\xbe\xe6\xbe\x5a\xc5\x67\x3e\x5a\xc5\x67\x3e\x71\x38\x6c\xbf\x71\x38\x6c\xbf\x6f\x6a\x6d\xbf\xd2\xb4\xa2\x3e\x72\x80\x62\x3e\x16\xe2\x90\x3e\x16\xe2\x90\x3e\x36\x6e\x7d\xbf\x36\x6e\x7d\xbf\x91\xb3\x7f\x3f\xa4\x3a\xa3\x3e\x56\x4b\x22\x3e\x05\x46\xab\x3e\x05\x46\xab\x3e\x85\x51\x7e\xbf\x85\x51\x7e\xbf\xfc\x0c\x81\xbf\x9b\xc0\xa3\x3e\x82\x2f\xdd\xbe\x00\x38\xc7\x3e\x00\x38\xc7\x3e\xe9\xad\x6e\xbf\xe9\xad\x6e\xbf\x74\x40\x74\x3f\xb9\x46\xa4\x3e\x04\x4e\xd3\x3e\x2f\x62\xda\x3e\x2f\x62\xda\x3e\x6b\x63\x4f\xbf\x6b\x63\x4f\xbf\xea\xcc\x56\xbf\xfc\xcc\xa4\x3e\xc2\x19\xe2\xbd\xe8\xdf\xf7\x3e\xe8\xdf\xf7\x3e\x31\x5e\x22\xbf\x31\x5e\x22\xbf\x9a\x65\x2b\x3f\x66\x53\xa5\x3e\xd3\x78\x8b\xbe\xfd\x14\x03\x3f\xfd\x14\x03\x3f\x2c\xf6\xd4\xbe\x2c\xf6\xd4\xbe\x2b\x3e\xe9\xbe\xf5\xd9\xa5\x3e\x06\xeb\xf2\x3e\x97\xcf\x0c\x3f\x97\xcf\x0c\x3f\x4e\x69\x2d\xbe\x4e\x69\x2d\xbe\x33\x73\x57\x3e\xa9\x60\xa6\x3e\xc7\x57\xb5\xbe\xe9\x48\x17\x3f\xe9\x48\x17\x3f\x32\xda\xb6\x3d\x32\xda\xb6\x3d\x47\xe9\x4d\x3d\x82\xe7\xa6\x3e\x73\x01\x11\xbc\x66\x37\x1a\x3f\x66\x37\x1a\x3f\x29\x71\xaf\x3e\x29\x71\xaf\x3e\x89\x58\x9e\xbe\x7f\x6e\xa7\x3e\x61\x23\xba\x3e\xeb\x02\x23\x3f\xeb\x02\x23\x3f\xa5\xd5\x12\x3f\xa5\xd5\x12\x3f\xce\x89\x0c\x3f\xa0\xf5\xa7\x3e\x94\xdf\xeb\xbe\x66\x46\x25\x3f\x66\x46\x25\x3f\x89\x1e\x44\x3f\x89\x1e\x44\x3f\x3f\xa8\x40\xbf\xe6\x7c\xa8\x3e\x24\xec\x6a\x3e\xb9\x87\x29\x3f\xb9\x87\x29\x3f\x40\x1d\x68\x3f\x40\x1d\x68\x3f\xd7\xbc\x67\x3f\x50\x04\xa9\x3e\x51\xad\x2c\x3e\xba\x1b\x2a\x3f\xba\x1b\x2a\x3f\x64\x38\x7c\x3f\x64\x38\x7c\x3f\xf0\xcb\x7e\xbf\xde\x8b\xa9\x3e\x41\xbd\xe6\xbe\x24\xc5\x29\x3f\x24\xc5\x29\x3f\x44\xe6\x7e\x3f\x44\xe6\x7e\x3f\x67\xf6\x81\x3f\x91\x13\xaa\x3e\xb3\x4d\xd3\x3e\x80\xea\x2a\x3f\x80\xea\x2a\x3f\x75\xcf\x6f\x3f\x75\xcf\x6f\x3f\x45\x7a\x76\xbf\x66\x9b\xaa\x3e\x98\x20\xa2\xbd\x83\x0a\x25\x3f\x83\x0a\x25\x3f\xf4\xdb\x4f\x3f\xf4\xdb\x4f\x3f\xb4\x28\x57\x3f\x5d\x23\xab\x3e\x83\xaf\x9e\xbe\xfd\xd3\x22\x3f\xfd\xd3\x22\x3f\x4d\x29\x21\x3f\x4d\x29\x21\x3f\xb2\x01\x28\xbf\x77\xab\xab\x3e\xee\x55\xf1\x3e\xd0\xaf\x1d\x3f\xd0\xaf\x1d\x3f\x47\xcf\xcd\x3e\x47\xcf\xcd\x3e\x42\x89\xd8\x3e\xb4\x33\xac\x3e\x3d\xf5\x92\xbe\x18\x16\x16\x3f\x18\x16\x16\x3f\x19\x97\x14\x3e\x19\x97\x14\x3e\x44\xc0\x20\xbe\x13\xbc\xac\x3e\x16\xf7\xdd\xbd\x44\x16\x0e\x3f\x44\x16\x0e\x3f\xee\xa5\xfb\xbd\xee\xa5\xfb\xbd\xdc\x5d\xfa\xbd\x94\x44\xad\x3e\x25\xcb\xd9\x3e\x64\xb6\x05\x3f\x64\xb6\x05\x3f\x56\xf4\xc3\xbe\x56\xf4\xc3\xbe\x15\xd2\xc9\x3e\x37\xcd\xad\x3e\x50\x76\xdc\xbe\x28\xb1\xf6\x3e\x28\xb1\xf6\x3e\x2b\x93\x1d\xbf\x2b\x93\x1d\xbf\x47\x70\x23\xbf\xfc\x55\xae\x3e\x14\x19\xf3\x3d\x00\x04\xde\x3e\x00\x04\xde\x3e\xdd\xd8\x4d\xbf\xdd\xd8\x4d\xbf\x67\x1b\x56\x3f\xe1\xde\xae\x3e\x2c\xe5\x8f\x3e\x74\x67\xc8\x3e\x74\x67\xc8\x3e\xe9\x27\x6f\xbf\xe9\x27\x6f\xbf\x29\xf6\x78\xbf\xe7\x67\xaf\x3e\x65\xf6\xf1\xbe\x6b\xce\xab\x3e\x6b\xce\xab\x3e\xa9\xe9\x7e\xbf\xa9\xe9\x7e\xbf\x90\x9a\x84\x3f\x0e\xf1\xaf\x3e\x07\x60\xa0\x3e\x77\xb6\x92\x3e\x77\xb6\x92\x3e\x41\xcc\x7b\xbf\x41\xcc\x7b\xbf\xf5\xbb\x82\xbf\x55\x7a\xb0\x3e\x7f\x53\xa0\x3d\xd5\x9f\x65\x3e\xd5\x9f\x65\x3e\xc8\xe2\x65\xbf\xc8\xe2\x65\xbf\x23\xef\x6d\x3f\xbc\x03\xb1\x3e\xd9\x2a\xd1\xbe\xc5\x02\x2f\x3e\xc5\x02\x2f\x3e\x11\xaa\x3e\xbf\x11\xaa\x3e\xbf\xc0\x5f\x44\xbf\x44\x8d\xb1\x3e\x48\x50\xdb\x3e\xc7\x94\xde\x3d\xc7\x94\xde\x3d\xfa\xf2\x08\xbf\xfa\xf2\x08\xbf\x0b\x06\x0c\x3f\xea\x16\xb2\x3e\x01\xfc\xf8\xbd\x7d\x99\x44\x3d\x7d\x99\x44\x3d\x8a\x64\x91\xbe\x8a\x64\x91\xbe\x3a\xa8\x92\xbe\xaf\xa0\xb2\x3e\xe1\xbf\x8e\xbe\xed\xe0\x4e\xbc\xed\xe0\x4e\xbc\x89\x99\x2e\xbc\x89\x99\x2e\xbc\x8f\x1a\xc8\x3b\x93\x2a\xb3\x3e\x4f\x29\xee\x3e\xe2\x9d\x99\xbd\xe2\x9d\x99\xbd\x91\x43\x87\x3e\x91\x43\x87\x3e\x73\x3d\x8b\x3e\x94\xb4\xb3\x3e\xe0\xfe\x94\xbe\xa4\xf0\x07\xbe\xa4\xf0\x07\xbe\x85\xf6\x04\x3f\x85\xf6\x04\x3f\xd3\xa9\x06\xbf\xb4\x3e\xb4\x3e\x2f\x0f\xe5\xbd\x7d\x3f\x4b\xbe\x7d\x3f\x4b\xbe\xab\x29\x3c\x3f\xab\x29\x3c\x3f\xbe\x89\x3c\x3f\xf3\xc8\xb4\x3e\xba\x9f\xdc\x3e\x1a\xe0\x7d\xbe\x1a\xe0\x7d\xbe\x0a\xd8\x64\x3f\x0a\xd8\x64\x3f\x91\x21\x63\xbf\x4e\x53\xb5\x3e\x6d\x2f\xd4\xbe\x2e\x3f\x9f\xbe\x2e\x3f\x9f\xbe\xa7\xb2\x7b\x3f\xa7\xb2\x7b\x3f\xa2\x89\x77\x3f\xc5\xdd\xb5\x3e\x78\xb1\x93\x3d\xe1\x7e\xb9\xbe\xe1\x7e\xb9\xbe\x0f\xc7\x7e\x3f\x0f\xc7\x7e\x3f\x78\x40\x78\xbf\x5a\x68\xb6\x3e\x45\x9f\xa7\x3e\x77\x73\xd1\xbe\x77\x73\xd1\xbe\xa2\xad\x6d\x3f\xa2\xad\x6d\x3f\xd1\x3e\x65\x3f\x0c\xf3\xb6\x3e\xb6\xe0\xee\xbe\xf1\xfd\xeb\xbe\xf1\xfd\xeb\xbe\x80\x98\x49\x3f\x80\x98\x49\x3f\x5a\xf6\x3f\xbf\xd9\x7d\xb7\x3e\x13\x8f\x6e\x3e\xe3\x60\x00\xbf\xe3\x60\x00\xbf\xf5\x43\x15\x3f\xf5\x43\x15\x3f\xa6\x3b\x0b\x3f\xc2\x08\xb8\x3e\x1d\x21\x40\x3e\xa9\xbe\x09\xbf\xa9\xbe\x09\xbf\xe3\x8c\xa9\x3e\xe3\x8c\xa9\x3e\xd3\x2d\x96\xbe\xc6\x93\xb8\x3e\x3e\xf7\xe9\xbe\x3f\x9b\x13\xbf\x3f\x9b\x13\xbf\x1f\x16\x54\x3d\x1f\x16\x54\x3d\xfa\x0e\x90\x3c\xe6\x1e\xb9\x3e\x38\x64\xb6\x3e\xf7\xdb\x19\xbf\xf7\xdb\x19\xbf\x2a\x16\x6e\xbe\x2a\x16\x6e\xbe\x5d\xf2\x85\x3e\x20\xaa\xb9\x3e\x3a\xea\x0d\x3d\xe1\xb7\x20\xbf\xe1\xb7\x20\xbf\x44\x39\xff\xbe\x44\x39\xff\xbe\x9d\x98\x05\xbf\x76\x35\xba\x3e\x4a\xf8\xcb\xbe\x9e\x1a\x25\xbf\x9e\x1a\x25\xbf\x2a\x61\x39\xbf\x2a\x61\x39\xbf\x19\xe6\x3d\x3f\xe4\xc0\xba\x3e\xf6\xa5\xdf\x3e\xf2\x73\x28\xbf\xf2\x73\x28\xbf\x3d\xf7\x63\xbf\x3d\xf7\x63\xbf\x69\x25\x67\xbf\x6b\x4c\xbb\x3e\xb5\xb9\xed\xbd\x94\x6d\x2a\xbf\x94\x6d\x2a\xbf\x87\xb6\x7b\xbf\x87\xb6\x7b\xbf\x49\xc4\x7d\x3f\x0c\xd8\xbb\x3e\xf2\x50\x9a\xbe\x59\x0b\x2a\xbf\x59\x0b\x2a\xbf\x6f\x7d\x7e\xbf\x6f\x7d\x7e\xbf\xbb\xb0\x7f\xbf\xc5\x63\xbc\x3e\x87\xf6\xf0\x3e\xf7\x35\x2a\xbf\xf7\x35\x2a\xbf\x4d\xe5\x6b\xbf\x4d\xe5\x6b\xbf\x08\x8f\x6c\x3f\x96\xef\xbc\x3e\x03\x4d\x80\xbe\x00\xf3\x25\xbf\x00\xf3\x25\xbf\xce\x54\x45\xbf\xce\x54\x45\xbf\x70\xca\x45\xbf\x80\x7b\xbd\x3e\x43\xdf\x34\xbe\x37\x52\x23\xbf\x37\x52\x23\xbf\x7c\xe9\x0d\xbf\x7c\xe9\x0d\xbf\x20\x7a\x0e\x3f\x93\x07\xbe\x3e\xc2\xdd\xe8\x3e\x73\x71\x1c\xbf\x73\x71\x1c\xbf\xbd\x77\x94\xbe\xbd\x77\x94\xbe\xf8\x43\x96\xbe\xd2\x93\xbe\x3e\x14\x00\xb3\xbe\xe1\xe6\x16\xbf\xe1\xe6\x16\xbf\x62\xdd\x3e\xb8\x62\xdd\x3e\xb8\xba\xa7\xa9\x3b\xf4\x27\xbf\x3e\x0e\xd7\x55\xbd\x32\x00\x0d\xbf\x32\x00\x0d\xbf\xeb\xcb\x94\x3e\xeb\xcb\x94\x3e\x85\x8e\x91\x3e\xfc\xc3\xbf\x3e\x10\xba\xd2\x3e\x78\xf7\x04\xbf\x78\xf7\x04\xbf\x58\x8a\x0e\x3f\x58\x8a\x0e\x3f\x54\xea\x0c\xbf\xb1\x52\xc0\x3e\x1f\x36\xd7\xbe\x07\x48\xf3\xbe\x07\x48\xf3\xbe\x95\x6d\x46\x3f\x95\x6d\x46\x3f\x58\x3a\x45\x3f\x16\xd4\xc0\x3e\x71\x41\x8b\x3d\xd8\x4e\xd9\xbe\xd8\x4e\xd9\xbe\x41\x13\x6d\x3f\x41\x13\x6d\x3f\x56\xbe\x6c\xbf\x76\x5b\xc1\x3e\x1e\xb6\xb0\x3e\x5a\xfd\xc5\xbe\x5a\xfd\xc5\xbe\x86\xf3\x7e\x3f\x86\xf3\x7e\x3f\xd2\xce\x7f\x3f\xd1\xe8\xc1\x3e\x91\x99\xed\xbe\x41\xe7\xa1\xbe\x41\xe7\xa1\xbe\x0b\x52\x7a\x3f\x0b\x52\x7a\x3f\xa1\x6f\x7c\xbf\x4a\x76\xc2\x3e\xea\xc3\x3d\x3e\x3d\xf4\x8c\xbe\x3d\xf4\x8c\xbe\x01\x6d\x5f\x3f\x01\x6d\x5f\x3f\x97\x8f\x62\x3f\xde\x03\xc3\x3e\x2d\xdb\x80\x3e\x81\xba\x55\xbe\x81\xba\x55\xbe\x02\x80\x30\x3f\x02\x80\x30\x3f\xeb\x21\x34\xbf\x90\x91\xc3\x3e\xb7\x47\xf0\xbe\xaf\x15\x17\xbe\xaf\x15\x17\xbe\xf7\x33\xe3\x3e\xf7\x33\xe3\x3e\x24\x14\xea\x3e\x5f\x1f\xc4\x3e\x1d\x4f\x8e\x3e\xc6\x53\xb4\xbd\xc6\x53\xb4\xbd\xbc\x23\x21\x3e\xbc\x23\x21\x3e\x77\x55\x2b\xbe\x48\xad\xc4\x3e\xee\x74\x1f\x3e\x5c\x39\xbe\xbc\x5c\x39\xbe\xbc\xf3\x80\x13\xbe\xf3\x80\x13\xbe\x80\xf5\x0e\xbe\x4d\x3b\xc5\x3e\x5e\x2b\xe6\xbe\x45\x2c\x0a\x3d\x45\x2c\x0a\x3d\x1a\xbd\xdd\xbe\x1a\xbd\xdd\xbe\xce\xb8\xde\x3e\x6e\xc9\xc5\x3e\x96\xa9\xae\x3e\xa2\x68\xe7\x3d\xa2\x68\xe7\x3d\x62\xe1\x2e\xbf\x62\xe1\x2e\xbf\xc8\xdb\x30\xbf\xaa\x57\xc6\x3e\x9e\x26\x9b\x3d\xb6\x31\x1f\x3e\xb6\x31\x1f\x3e\x41\xef\x5e\xbf\x41\xef\x5e\xbf\x68\xed\x61\x3f\x02\xe6\xc6\x3e\x25\x67\xdc\xbe\x55\xb5\x68\x3e\x55\xb5\x68\x3e\x88\x76\x7a\xbf\x88\x76\x7a\xbf\x21\xc8\x7d\xbf\x75\x74\xc7\x3e\x51\x4c\xcf\x3e\xb3\xc2\x91\x3e\xb3\xc2\x91\x3e\xae\xc0\x7e\xbf\xae\xc0\x7e\xbf\x4c\xd3\x80\x3f\x04\x03\xc8\x3e\xcb\x3e\x9b\xbc\x03\xe9\xae\x3e\x03\xe9\xae\x3e\x0c\x3c\x6b\xbf\x0c\x3c\x6b\xbf\x4b\x12\x6d\xbf\xae\x91\xc8\x3e\xe9\xb5\xc4\xbe\x98\x97\xc8\x3e\x98\x97\xc8\x3e\xf5\x91\x41\xbf\xf5\x91\x41\xbf\x2b\xf1\x41\x3f\x75\x20\xc9\x3e\x03\x95\xe2\x3e\xdf\x1b\xe0\x3e\xdf\x1b\xe0\x3e\x47\x88\x05\xbf\x47\x88\x05\xbf\x02\x56\x04\xbf\x57\xaf\xc9\x3e\x37\x86\xcf\xbd\x18\x56\xff\x3e\x18\x56\xff\x3e\x67\xbb\x72\xbe\x67\xbb\x72\xbe\x70\x71\x68\x3e\x52\x3e\xca\x3e\x6e\x8a\xa9\xbe\x45\x90\x05\x3f\x45\x90\x05\x3f\x92\x06\x91\x3d\x92\x06\x91\x3d\xd7\x44\xad\x3d\x68\xcd\xca\x3e\x81\xe8\xea\x3e\x01\x63\x11\x3f\x01\x63\x11\x3f\x5f\xca\xbe\x3e\x5f\xca\xbe\x3e\x4c\xb2\xc6\xbe\x96\x5c\xcb\x3e\x98\x3e\x26\xbe\xb6\xa7\x18\x3f\xb6\xa7\x18\x3f\xec\xa9\x23\x3f\xec\xa9\x23\x3f\x9b\x84\x27\x3f\xdc\xeb\xcb\x3e\x47\x24\x92\xbe\x95\x22\x20\x3f\x95\x22\x20\x3f\x0a\x42\x58\x3f\x0a\x42\x58\x3f\x74\x9d\x5b\xbf\x3e\x7b\xcc\x3e\xb3\x46\xf0\x3e\x51\xf2\x23\x3f\x51\xf2\x23\x3f\xec\xf1\x77\x3f\xec\xf1\x77\x3f\x86\x99\x7a\x3f\xb8\x0a\xcd\x3e\x9b\xfc\x5e\xbe\x4b\xa3\x27\x3f\x4b\xa3\x27\x3f\x6f\x79\x7f\x3f\x6f\x79\x7f\x3f\xb9\xb6\x80\xbf\x51\x9a\xcd\x3e\x9e\xe2\x70\xbe\x6d\x41\x2b\x3f\x6d\x41\x2b\x3f\x2e\xee\x6d\x3f\x2e\xee\x6d\x3f\x1f\x5b\x6f\x3f\x06\x2a\xce\x3e\x85\xce\xee\x3e\xf5\x0c\x2a\x3f\xf5\x0c\x2a\x3f\xbb\xdd\x44\x3f\xbb\xdd\x44\x3f\xfd\x0a\x46\xbf\xcf\xb9\xce\x3e\xae\x18\x84\xbe\xf0\xec\x28\x3f\xf0\xec\x28\x3f\x44\x30\x08\x3f\x44\x30\x08\x3f\x55\x6b\x09\x3f\xaa\x49\xcf\x3e\x25\x51\x48\xbe\xbc\x5e\x27\x3f\xbc\x5e\x27\x3f\xb3\x39\x77\x3e\xb3\x39\x77\x3e\xc0\x64\x7d\xbe\xa2\xd9\xcf\x3e\x21\xf3\xee\x3e\x4f\x13\x23\x3f\x4f\x13\x23\x3f\x84\x75\x97\xbd\x84\x75\x97\xbd\x2b\x41\x87\xbd\xb7\x69\xd0\x3e\xef\x27\x98\xbe\x87\xb5\x1a\x3f\x87\xb5\x1a\x3f\xca\xe7\xc3\xbe\xca\xe7\xc3\xbe\xc9\xb9\xbe\x3e\xe2\xf9\xd0\x3e\x00\xf2\x1c\xbe\x1e\x3b\x17\x3f\x1e\x3b\x17\x3f\x6f\x42\x27\xbf\x6f\x42\x27\xbf\xb2\x18\x24\xbf\x26\x8a\xd1\x3e\xe8\x3a\xe9\x3e\x55\x05\x0c\x3f\x55\x05\x0c\x3f\xcb\xbe\x5b\xbf\xcb\xbe\x5b\xbf\xa2\x0d\x58\x3f\x80\x1a\xd2\x3e\xb7\xcd\xa3\xbe\xf8\x93\x02\x3f\xf8\x93\x02\x3f\x13\xef\x79\xbf\x13\xef\x79\xbf\xb9\xcc\x75\xbf\xf1\xaa\xd2\x3e\x82\x9f\xfe\xbd\xff\xe6\xed\x3e\xff\xe6\xed\x3e\x0e\x92\x7e\xbf\x0e\x92\x7e\xbf\xdc\x22\x7a\x3f\x7b\x3b\xd3\x3e\x5f\x5a\xe6\x3e\xcd\x68\xd8\x3e\xcd\x68\xd8\x3e\x81\xfe\x68\xbf\x81\xfe\x68\xbf\x4c\x7c\x64\xbf\x1d\xcc\xd3\x3e\x29\xb7\xae\xbe\x8d\x04\xb9\x3e\x8d\x04\xb9\x3e\x78\x40\x3b\xbf\x78\x40\x3b\xbf\xd6\x01\x37\x3f\xd6\x5c\xd4\x3e\xbb\xe6\xc7\xbd\x26\x3b\x9e\x3e\x26\x3b\x9e\x3e\x3d\xdd\xf3\xbe\x3d\xdd\xf3\xbe\x2a\xd2\xec\xbe\xa4\xed\xd4\x3e\x98\xcd\xe0\x3e\x39\x26\x83\x3e\x39\x26\x83\x3e\x10\xe5\x2e\xbe\x10\xe5\x2e\xbe\xf4\xe3\x25\x3e\x8a\x7e\xd5\x3e\x57\x22\xb2\xbe\xb7\x4b\x38\x3e\xb7\x4b\x38\x3e\x78\x00\x1d\x3e\x78\x00\x1d\x3e\x3c\xbc\x1e\x3e\x86\x0f\xd6\x3e\x0b\x4f\xb2\xbd\xd6\x7d\x09\x3e\xd6\x7d\x09\x3e\x3b\x8b\xec\x3e\x3b\x8b\xec\x3e\xe7\xf1\xe8\xbe\x99\xa0\xd6\x3e\x68\xcf\xdf\x3e\xae\x9f\x6d\x3d\xae\x9f\x6d\x3d\x3b\xf1\x38\x3f\x3b\xf1\x38\x3f\x7b\xc4\x34\x3f\xc2\x31\xd7\x3e\x8a\x09\xb6\xbe\x9f\x83\xd5\xbb\x9f\x83\xd5\xbb\x99\x15\x68\x3f\x99\x15\x68\x3f\x5d\xc4\x61\xbf\x02\xc3\xd7\x3e\x90\xec\xa0\xbd\xa7\x59\x88\xbd\xa7\x59\x88\xbd\x82\x86\x7e\x3f\x82\x86\x7e\x3f\xbb\xb3\x76\x3f\x59\x54\xd8\x3e\x19\x35\xdf\x3e\x3f\x03\x07\xbe\x3f\x03\x07\xbe\x17\xaf\x79\x3f\x17\xaf\x79\x3f\x12\x55\x71\xbf\xc4\xe5\xd8\x3e\x49\xc3\xb8\xbe\x44\x97\x4c\xbe\x44\x97\x4c\xbe\xd0\xe3\x59\x3f\xd0\xe3\x59\x3f\x7c\x2c\x52\x3f\x45\x77\xd9\x3e\xe9\x5d\x97\xbd\xda\x65\x86\xbe\xda\x65\x86\xbe\x11\x67\x22\x3f\x11\x67\x22\x3f\x45\x72\x1c\xbf\xda\x08\xda\x3e\x29\xd8\xde\x3e\x18\x93\x9e\xbe\x18\x93\x9e\xbe\xde\x32\xb2\x3e\xde\x32\xb2\x3e\x6c\x88\xab\x3e\x84\x9a\xda\x3e\x0b\x63\xb8\xbe\xa9\x8c\xc0\xbe\xa9\x8c\xc0\xbe\xd3\x13\xbc\x3c\xd3\x13\xbc\x3c\xf7\x9e\xb3\xbc\x43\x2c\xdb\x3e\xe5\xd9\x9c\xbd\x8f\x72\xde\xbe\x8f\x72\xde\xbe\x7f\x5d\x9c\xbe\x7f\x5d\x9c\xbe\x34\xca\x96\xbe\x17\xbe\xdb\x3e\x12\xe8\xdc\x3e\x2f\x71\xee\xbe\x2f\x71\xee\xbe\xde\xcc\x19\xbf\xde\xcc\x19\xbf\xc3\x62\x14\x3f\x00\x50\xdc\x3e\x64\x9a\xae\xbe\xcd\x92\x04\xbf\xcd\x92\x04\xbf\xf5\x85\x54\xbf\xf5\x85\x54\xbf\xb5\x32\x4d\xbf\xfe\xe1\xdc\x3e\xea\x61\xd0\xbd\x78\x18\x11\xbf\x78\x18\x11\xbf\xc8\xb1\x77\xbf\xc8\xb1\x77\xbf\xfa\x51\x6f\x3f\x0e\x74\xdd\x3e\x26\x4d\xe0\x3e\x4d\x5c\x15\xbf\x4d\x5c\x15\xbf\x03\x3a\x7f\xbf\x03\x3a\x7f\xbf\x0e\xb2\x76\xbf\x30\x06\xde\x3e\x7d\x69\xa2\xbe\x86\x49\x1e\xbf\x86\x49\x1e\xbf\x94\x17\x6a\xbf\x94\x17\x6a\xbf\x01\x4a\x62\x3f\x67\x98\xde\x3e\xca\x19\x0d\xbe\x98\xda\x24\xbf\x98\xda\x24\xbf\x1b\x7c\x3a\xbf\x1b\x7c\x3a\xbf\xce\x4e\x34\xbf\xb3\x2a\xdf\x3e\x35\xfd\xe8\x3e\xa9\x4e\x27\xbf\xa9\x4e\x27\xbf\x4c\x40\xeb\xbe\x4c\x40\xeb\xbe\x4d\xfd\xe3\x3e\x11\xbd\xdf\x3e\x93\x91\x9a\xbe\x1d\x6d\x29\xbf\x1d\x6d\x29\xbf\x2b\xe3\x0c\xbe\x2b\xe3\x0c\xbe\x95\x01\x0c\xbe\x81\x4f\xe0\x3e\x8d\x26\x2b\xbe\xf6\xc9\x2b\xbf\xf6\xc9\x2b\xbf\x5f\x89\x4d\x3e\x5f\x89\x4d\x3e\x0a\x45\x3e\xbe\x03\xe2\xe0\x3e\x95\x7a\xed\x3e\x80\x2d\x29\xbf\x80\x2d\x29\xbf\xf8\x43\x04\x3f\xf8\x43\x04\x3f\x09\x8a\xf8\x3e\x98\x74\xe1\x3e\x80\xd5\x8b\xbe\xcc\x1c\x25\xbf\xcc\x1c\x25\xbf\xf4\x0b\x46\x3f\xf4\x0b\x46\x3f\x35\x71\x3a\xbf\x3f\x07\xe2\x3e\x26\x5a\x55\xbe\x45\x37\x25\xbf\x45\x37\x25\xbf\x7d\xfc\x70\x3f\x7d\xfc\x70\x3f\x7e\x32\x63\x3f\xfa\x99\xe2\x3e\x93\x95\xf0\x3e\x3d\xa6\x1a\xbf\x3d\xa6\x1a\xbf\x8e\xea\x7f\x3f\x8e\xea\x7f\x3f\xe5\x24\x72\xbf\xc5\x2c\xe3\x3e\xd3\x53\x6a\xbe\x4d\x44\x13\xbf\x4d\x44\x13\xbf\x25\xe9\x70\x3f\x25\xe9\x70\x3f\x43\xc8\x65\x3f\xa1\xbf\xe3\x3e\xeb\xb1\x85\xbe\x11\x39\x0e\xbf\x11\x39\x0e\xbf\xe1\x8c\x45\x3f\xe1\x8c\x45\x3f\xcd\x8d\x3f\xbf\x8e\x52\xe4\x3e\x82\xf1\xf3\x3e\x60\x47\x00\xbf\x60\x47\x00\xbf\x8d\xc6\x02\x3f\x8d\xc6\x02\x3f\x41\xaa\x03\x3f\x8c\xe5\xe4\x3e\x16\x2d\x3e\xbe\x71\x21\xe6\xbe\x71\x21\xe6\xbe\xee\x69\x41\x3e\xee\x69\x41\x3e\xc6\xc2\x62\xbe\x9b\x78\xe5\x3e\x8e\xf2\x99\xbe\xea\x34\xd4\xbe\xea\x34\xd4\xbe\x97\xff\x1f\xbe\x97\xff\x1f\xbe\x2a\x47\xc8\xbd\xbc\x0b\xe6\x3e\xee\xd3\xec\x3e\x16\xaf\xb7\xbe\x16\xaf\xb7\xbe\x2e\x7e\xf7\xbe\x2e\x7e\xf7\xbe\x34\x70\xd0\x3e\xeb\x9e\xe6\x3e\xff\xe9\x02\xbe\x5f\xf3\x8c\xbe\x5f\xf3\x8c\xbe\xf5\xcb\x40\xbf\xf5\xcb\x40\xbf\x8a\x91\x2b\xbf\x2a\x32\xe7\x3e\xa3\xd3\xae\xbe\xfb\x1f\x79\xbe\xfb\x1f\x79\xbe\x68\xbb\x6e\xbf\x68\xbb\x6e\xbf\x28\xce\x5a\x3f\x79\xc5\xe7\x3e\xa8\x08\xe0\x3e\xaa\xe2\x32\xbe\xaa\xe2\x32\xbe\x90\xd6\x7f\xbf\x90\xd6\x7f\xbf\xd3\xb9\x6f\xbf\xd9\x58\xe8\x3e\x3d\x38\x65\xbd\x35\xef\xb0\xbd\x35\xef\xb0\xbd\xe1\xd4\x71\xbf\xe1\xd4\x71\xbf\x7f\x26\x67\x3f\x48\xec\xe8\x3e\x28\x97\xc6\xbe\xbf\x46\x2b\xbd\xbf\x46\x2b\xbd\xbc\x35\x46\xbf\xbc\x35\x46\xbf\x88\x92\x41\xbf\xc4\x7f\xe9\x3e\xe1\xf8\xd0\x3e\x7b\x38\xcf\x3c\x7b\x38\xcf\x3c\x81\x23\x02\xbf\x81\x23\x02\xbf\x91\x50\x03\x3f\x50\x13\xea\x3e\x35\x18\x94\x3c\x2c\xca\xd9\x3d\x2c\xca\xd9\x3d\x2c\x76\x37\xbe\x2c\x76\x37\xbe\xf2\x85\x50\xbe\xea\xa6\xea\x3e\xee\xb1\xd7\xbe\x97\xa6\x2b\x3e\x97\xa6\x2b\x3e\x4c\x1b\x31\x3e\x4c\x1b\x31\x3e\xf3\xd9\x06\xbe\x92\x3a\xeb\x3e\x13\x80\xb6\x3e\x6b\x95\x61\x3e\x6b\x95\x61\x3e\xd4\x1d\x01\x3f\xd4\x1d\x01\x3f\xa6\x9a\xe5\x3e\x49\xce\xeb\x3e\x9a\xe2\xce\x3d\xfb\x48\x98\x3e\xfb\x48\x98\x3e\xfb\x03\x46\x3f\xfb\x03\x46\x3f\xfe\x37\x34\xbf\x0c\x62\xec\x3e\x7d\x69\xe0\xbe\xb2\x25\xb4\x3e\xb2\x25\xb4\x3e\xac\x37\x72\x3f\xac\x37\x72\x3f\x67\x2f\x5d\x3f\xdd\xf5\xec\x3e\x69\x48\x8f\x3e\x0d\xec\xcd\x3e\x0d\xec\xcd\x3e\x02\x00\x80\x3f\x02\x00\x80\x3f\x71\x5b\x68\xbf\xba\x89\xed\x3e\xaa\xf7\x43\x3e\x47\x5c\xec\x3e\x47\x5c\xec\x3e\x96\x70\x6d\x3f\x96\x70\x6d\x3f\x56\x90\x54\x3f\xa4\x1d\xee\x3e\x44\xda\xe1\xbe\x5f\x54\x00\x3f\x5f\x54\x00\x3f\x9c\xb1\x3c\x3f\x9c\xb1\x3c\x3f\x5f\xe8\x24\xbf\x9b\xb1\xee\x3e\x52\xab\x3f\x3e\xd3\xb0\x0c\x3f\xd3\xb0\x0c\x3f\xfb\x8e\xe7\x3e\xfb\x8e\xe7\x3e\x20\x7f\xc0\x3e\x9e\x45\xef\x3e\xac\x9f\x8f\x3e\x44\x27\x15\x3f\x44\x27\x15\x3f\x89\x06\xdf\x3d\x89\x06\xdf\x3d\x98\x04\x81\xbd\xad\xd9\xef\x3e\x16\x09\xdb\xbe\x98\x5d\x1b\x3f\x98\x5d\x1b\x3f\xf4\x23\x7f\xbe\xf4\x23\x7f\xbe\x2f\x59\x81\xbe\xc6\x6d\xf0\x3e\x1b\x2d\xae\x3d\x58\x5d\x24\x3f\x58\x5d\x24\x3f\x3c\x62\x13\xbf\x3c\x62\x13\xbf\x38\xa4\x07\x3f\xec\x01\xf1\x3e\x24\x64\xb6\x3e\x20\xc5\x26\x3f\x20\xc5\x26\x3f\x57\x07\x54\xbf\x57\x07\x54\xbf\xe7\xd9\x3b\xbf\x1c\x96\xf1\x3e\xee\xeb\xc6\xbe\x13\x88\x29\x3f\x13\x88\x29\x3f\xe2\x2f\x79\xbf\xe2\x2f\x79\xbf\xab\xfd\x56\x3f\x58\x2a\xf2\x3e\xed\xb0\xef\xbc\xa1\x91\x2a\x3f\xa1\x91\x2a\x3f\x60\xd1\x7d\xbf\x60\xd1\x7d\xbf\x05\x0c\x56\xbf\x9d\xbe\xf2\x3e\x2a\x56\xd6\x3e\x84\x6f\x29\x3f\x84\x6f\x29\x3f\x36\x1a\x61\xbf\x36\x1a\x61\xbf\xcf\x93\x39\x3f\xec\x52\xf3\x3e\xba\x87\xa7\xbe\x7a\x5a\x28\x3f\x7a\x5a\x28\x3f\x25\xa2\x26\xbf\x25\xa2\x26\xbf\xaa\x8a\x05\xbf\x45\xe7\xf3\x3e\x78\x2e\x14\xbe\x69\x1f\x21\x3f\x69\x1f\x21\x3f\xb2\xfa\xab\xbe\xb2\xfa\xab\xbe\x28\x7f\x81\x3e\xa7\x7b\xf4\x3e\x11\xec\xe6\x3e\x31\xe5\x1b\x3f\x31\xe5\x1b\x3f\x82\x99\xc7\x3c\x82\x99\xc7\x3c\x8a\x38\x3f\x3d\x12\x10\xf5\x3e\xfd\x35\x6f\xbe\xf5\xa1\x15\x3f\xf5\xa1\x15\x3f\x99\xa0\xc3\x3e\x99\xa0\xc3\x3e\x02\x5b\xad\xbe\x86\xa4\xf5\x3e\x0f\xc8\x81\xbe\x5a\xbd\x0a\x3f\x5a\xbd\x0a\x3f\x09\x74\x30\x3f\x09\x74\x30\x3f\x4a\xb6\x15\x3f\x02\x39\xf6\x3e\x49\xcd\xe0\x3e\x5d\x3a\xfe\x3e\x5d\x3a\xfe\x3e\x74\x78\x67\x3f\x74\x78\x67\x3f\xe8\xbc\x40\xbf\x86\xcd\xf6\x3e\x8c\xcd\xdb\xbd\x44\x9c\xe8\x3e\x44\x9c\xe8\x3e\x9d\x45\x7f\x3f\x9d\x45\x7f\x3f\x2f\xed\x51\x3f\x12\x62\xf7\x3e\x07\x92\xb2\xbe\x6f\xe0\xcc\x3e\x6f\xe0\xcc\x3e\xba\x71\x74\x3f\xba\x71\x74\x3f\x07\xb3\x46\xbf\xa5\xf6\xf7\x3e\xef\x56\xc8\x3e\x25\xef\xad\x3e\x25\xef\xad\x3e\xff\x41\x48\x3f\xff\x41\x48\x3f\xa2\x21\x20\x3f\x40\x8b\xf8\x3e\x23\x46\xf2\x3c\xd1\x41\x90\x3e\xd1\x41\x90\x3e\x2b\x8d\x00\x3f\x2b\x8d\x00\x3f\xca\xe7\xc5\xbe\xe0\x1f\xf9\x3e\xc4\x9a\xd4\xbe\x19\x09\x60\x3e\x19\x09\x60\x3e\x31\x10\x1c\x3e\x31\x10\x1c\x3e\x70\x96\xb8\x3d\x87\xb4\xf9\x3e\x61\x73\x9c\x3e\x18\x71\x18\x3e\x18\x71\x18\x3e\x77\x4e\x60\xbe\x77\x4e\x60\xbe\xc7\x86\x65\x3e\x33\x49\xfa\x3e\x09\x0d\x2e\x3e\x64\xce\xa2\x3d\x64\xce\xa2\x3d\x06\x8f\x0f\xbf\x06\x8f\x0f\xbf\x46\x5d\x03\xbf\xe5\xdd\xfa\x3e\xf7\xbf\xdf\xbe\x90\x61\xaa\x3c\x90\x61\xaa\x3c\xd0\x36\x53\xbf\xd0\x36\x53\xbf\xcf\x57\x3c\x3f\x9c\x72\xfb\x3e\x96\x7d\x2b\x3e\x84\x93\x70\xbd\x84\x93\x70\xbd\x52\x7c\x79\xbf\x52\x7c\x79\xbf\xa4\xbf\x5b\xbf\x57\x07\xfc\x3e\xca\x57\x9f\x3e\xb1\x12\x04\xbe\xb1\x12\x04\xbe\x10\xd4\x7c\xbf\x10\xd4\x7c\xbf\x78\x4e\x5c\x3f\x17\x9c\xfc\x3e\x1e\x15\xd1\xbe\x96\x50\x3e\xbe\x96\x50\x3e\xbe\xe5\x8c\x5c\xbf\xe5\x8c\x5c\xbf\x19\x04\x3d\xbf\xdb\x30\xfd\x3e\x33\xaf\x91\xba\x34\x24\x84\xbe\x34\x24\x84\xbe\x93\x00\x1d\xbf\x93\x00\x1d\xbf\x55\x86\x01\x3f\xa2\xc5\xfd\x3e\x9e\x93\xd4\x3e\x2c\xf1\xa3\xbe\x2c\xf1\xa3\xbe\x6c\x0f\x8e\xbe\x6c\x0f\x8e\xbe\x75\x28\x47\xbe\x6d\x5a\xfe\x3e\x2e\xdb\xa3\xbe\x00\x6e\xc3\xbe\x00\x6e\xc3\xbe\x1a\xfe\xc9\x3d\x1a\xfe\xc9\x3d\x54\xae\x1b\xbe\x39\xef\xfe\x3e\x43\x33\x32\xbe\xc8\xf7\xdb\xbe\xc8\xf7\xdb\xbe\xdd\x44\xec\x3e\xdd\x44\xec\x3e\x5e\x1d\xf7\x3e\x07\x84\xff\x3e\x85\x40\xec\x3e\x38\x99\xf8\xbe\x38\x99\xf8\xbe\x87\x43\x42\x3f\x87\x43\x42\x3f\x9a\x3c\x3f\xbf\x6c\x0c\x00\x3f\xcb\x6c\x3b\xbe\x65\xfb\x08\xbf\x65\xfb\x08\xbf\x5e\x89\x72\x3f\x5e\x89\x72\x3f\x86\x4b\x67\x3f\xd5\x56\x00\x3f\xed\xfe\xa6\xbe\x6f\xfd\x0e\xbf\x6f\xfd\x0e\xbf\x22\xc8\x7f\x3f\x22\xc8\x7f\x3f\x29\x13\x6d\xbf\x3f\xa1\x00\x3f\x9d\x4c\xe1\x3e\x1b\x48\x1c\xbf\x1b\x48\x1c\xbf\x4c\xdf\x67\x3f\x4c\xdf\x67\x3f\xcd\x11\x4f\x3f\xa9\xeb\x00\x3f\x5c\x91\x45\xbc\x19\x11\x22\xbf\x19\x11\x22\xbf\x4a\x17\x2e\x3f\x4a\x17\x2e\x3f\x1d\x47\x11\xbf\x13\x36\x01\x3f\xf8\x4d\xde\xbe\xa6\x2b\x22\xbf\xa6\x2b\x22\xbf\x33\x67\xb5\x3e\x33\x67\xb5\x3e\xc1\xe2\x72\x3e\x7c\x80\x01\x3f\x41\x98\xb0\x3e\x2b\x71\x2b\xbf\x2b\x71\x2b\xbf\x00\x05\xc6\xbc\x00\x05\xc6\xbc\xcb\x7a\x07\x3e\xe5\xca\x01\x3f\x8d\x42\x30\x3e\xe2\x8e\x2d\xbf\xe2\x8e\x2d\xbf\x5f\xaf\xcc\xbe\x5f\xaf\xcc\xbe\x3f\x1d\xf8\xbe\x4d\x15\x02\x3f\x8c\xc4\xf1\xbe\xd2\xf4\x24\xbf\xd2\xf4\x24\xbf\x65\x7d\x37\xbf\x65\x7d\x37\xbf\x75\x04\x44\x3f\xb4\x5f\x02\x3f\x25\x97\x37\x3e\xf2\x27\x28\xbf\xf2\x27\x28\xbf\xab\x77\x6d\xbf\xab\x77\x6d\xbf\x08\xbc\x6e\xbf\x1b\xaa\x02\x3f\x6d\xca\xab\x3e\x66\x92\x28\xbf\x66\x92\x28\xbf\x71\x08\x80\xbf\x71\x08\x80\xbf\xfb\xad\x75\x3f\x80\xf4\x02\x3f\x3f\x24\xd7\xbe\xe3\xd0\x17\xbf\xe3\xd0\x17\xbf\x1c\x4a\x6c\xbf\x1c\x4a\x6c\xbf\x1c\xc4\x57\xbf\xe2\x3e\x03\x3f\xa5\x14\xfe\xbc\xfa\x95\x14\xbf\xfa\x95\x14\xbf\x13\xe2\x34\xbf\x13\xe2\x34\xbf\xba\x74\x19\x3f\x6a\x89\x03\x3f\xa9\x7a\xe2\x3e\x96\x1f\x11\xbf\x96\x1f\x11\xbf\x74\x0a\xc4\xbe\x74\x0a\xc4\xbe\xba\xf6\x87\xbe\x16\xd4\x03\x3f\x47\x8f\x93\xbe\xf6\xc0\xf8\xbe\xf6\xc0\xf8\xbe\xc0\xab\x13\xba\xc0\xab\x13\xba\xb4\x13\xe1\xbd\xa0\x22\x04\x3f\x66\x2b\x71\xbe\xec\x45\xe4\xbe\xec\x45\xe4\xbe\x60\xcc\xc3\x3e\x60\xcc\xc3\x3e\x6c\xd8\xf1\x3e\x08\x75\x04\x3f\x1c\x6e\xe9\x3e\xf0\x38\xd6\xbe\xf0\x38\xd6\xbe\xeb\x1c\x35\x3f\xeb\x1c\x35\x3f\x7f\xde\x44\xbf\x7b\xc0\x04\x3f\x3e\x9e\xab\xbd\x11\x08\xa8\xbe\x11\x08\xa8\xbe\x40\xa4\x6c\x3f\x40\xa4\x6c\x3f\x55\xb1\x74\x3f\xfa\x04\x05\x3f\x5a\xab\xce\xbe\xf1\x59\x88\xbe\xf1\x59\x88\xbe\x84\xc4\x7f\x3f\x84\xc4\x7f\x3f\x25\x71\x80\xbf\x94\x4c\x05\x3f\x84\x90\xbc\x3e\x99\x0c\x6b\xbe\x99\x0c\x6b\xbe\xc5\x52\x6b\x3f\xc5\x52\x6b\x3f\x93\xd7\x66\x3f\x4b\x97\x05\x3f\x6c\xec\x1f\x3e\x7e\xd0\x06\xbe\x7e\xd0\x06\xbe\xe8\x44\x32\x3f\xe8\x44\x32\x3f\xb5\x70\x29\xbf\x02\xe2\x05\x3f\xf1\xea\xfb\xbe\x1e\x57\x7e\xbd\x1e\x57\x7e\xbd\x8c\x9a\xba\x3e\x8c\x9a\xba\x3e\x85\xd2\xa1\x3e\xba\x2c\x06\x3f\x87\x78\x46\x3e\x3e\x4b\xac\xbc\x3e\x4b\xac\xbc\x9a\x3d\xce\xbc\x9a\x3d\xce\xbc\xa5\xf8\xaf\x3d\x72\x77\x06\x3f\x22\x93\xb9\x3e\xd2\x58\xa8\x3d\xd2\x58\xa8\x3d\x09\xcc\xd2\xbe\x09\xcc\xd2\xbe\x0e\x48\xf7\xbe\x2c\xc2\x06\x3f\xa2\x96\xea\xbe\xd4\x38\x1d\x3e\xd4\x38\x1d\x3e\x4c\xf2\x3b\xbf\x4c\xf2\x3b\xbf\x35\xd0\x4f\x3f\xe4\x0c\x07\x3f\x17\xbb\x0d\xbd\xf3\xbe\x3f\x3e\xf3\xbe\x3f\x3e\x34\xe9\x70\xbf\x34\xe9\x70\xbf\xc5\x39\x82\xbf\x9b\x57\x07\x3f\x48\x77\xf6\x3e\x3a\x2d\x90\x3e\x3a\x2d\x90\x3e\xb2\xb1\x7f\xbf\xb2\xb1\x7f\xbf\xfa\x19\x88\x3f\x53\xa2\x07\x3f\xc5\xcf\x9c\xbe\xe3\x1a\xb8\x3e\xe3\x1a\xb8\x3e\x49\xb9\x65\xbf\x49\xb9\x65\xbf\x8c\x49\x70\xbf\x0c\xed\x07\x3f\x59\xc5\x83\xbe\xdb\x2b\xc3\x3e\xdb\x2b\xc3\x3e\xf9\xee\x26\xbf\xf9\xee\x26\xbf\x63\x3f\x29\x3f\xc3\x37\x08\x3f\x25\x7f\xf1\x3e\x9a\x61\xe5\x3e\x9a\x61\xe5\x3e\x13\x6b\x9a\xbe\x13\x6b\x9a\xbe\xe6\xc6\x8c\xbe\x7a\x82\x08\x3f\x40\xd6\x83\xbd\x91\x8c\x06\x3f\x91\x8c\x06\x3f\x1b\x02\xc9\x3d\x1b\x02\xc9\x3d\x42\x53\x20\xbe\x30\xcd\x08\x3f\x14\xfd\xd3\xbe\xaf\x64\x0a\x3f\xaf\x64\x0a\x3f\x17\x22\xf7\x3e\x17\x22\xf7\x3e\x21\xdf\x0f\x3f\xe8\x17\x09\x3f\xc7\x32\xa7\x3e\xc6\x4f\x12\x3f\xc6\x4f\x12\x3f\x20\x18\x4a\x3f\x20\x18\x4a\x3f\x7c\xd3\x5f\xbf\x9e\x62\x09\x3f\xdb\xc5\x4b\x3e\x91\xd7\x21\x3f\x91\xd7\x21\x3f\x3a\xcd\x77\x3f\x3a\xcd\x77\x3f\x3d\x70\x85\x3f\x54\xad\x09\x3f\x7d\xa6\xe4\xbe\x16\xa9\x24\x3f\x16\xa9\x24\x3f\xcf\x0a\x7d\x3f\xcf\x0a\x7d\x3f\x96\x19\x85\xbf\x09\xf8\x09\x3f\xf3\xea\xa7\x3d\x30\x2a\x24\x3f\x30\x2a\x24\x3f\x67\xbc\x58\x3f\x67\xbc\x58\x3f\x3f\x43\x5e\x3f\xbc\x42\x0a\x3f\x75\xd6\xc9\x3e\xe8\x6e\x2c\x3f\xe8\x6e\x2c\x3f\xc5\xa2\x10\x3f\xc5\xa2\x10\x3f\xd9\xa1\x0e\xbf\x6e\x8d\x0a\x3f\xc2\xdc\xa8\xbe\x9a\x42\x2c\x3f\x9a\x42\x2c\x3f\x98\xe4\x41\x3e\x98\xe4\x41\x3e\x7d\x72\x22\x3e\x1c\xd8\x0a\x3f\xb5\x5c\x3e\xbe\x77\x28\x25\x3f\x77\x28\x25\x3f\x3d\x9b\x5f\xbe\x3d\x9b\x5f\xbe\xd1\x0e\x86\x3e\xca\x22\x0b\x3f\x6f\xe4\xe2\x3e\x21\x1d\x26\x3f\x21\x1d\x26\x3f\xfd\x1e\x17\xbf\xfd\x1e\x17\xbf\xba\xcc\x22\xbf\x78\x6d\x0b\x3f\x23\x7a\xb5\xbd\x59\x22\x22\x3f\x59\x22\x22\x3f\x1a\x31\x5d\xbf\x1a\x31\x5d\xbf\x9f\x42\x67\x3f\x25\xb8\x0b\x3f\x9f\x26\xc5\xbe\xa7\xc4\x12\x3f\xa7\xc4\x12\x3f\x53\x34\x7e\xbf\x53\x34\x7e\xbf\x86\xb6\x82\xbf\xd2\x02\x0c\x3f\x0c\xa2\xa3\x3e\xc9\x21\x0f\x3f\xc9\x21\x0f\x3f\x1b\x63\x74\xbf\x1b\x63\x74\xbf\x4c\x7b\x78\x3f\x7a\x4d\x0c\x3f\xc1\x19\x47\x3e\x85\x8c\x07\x3f\x85\x8c\x07\x3f\x94\x2b\x41\xbf\x94\x2b\x41\xbf\xe6\x90\x42\xbf\x1e\x98\x0c\x3f\x28\x21\xe1\xbe\xa4\x59\xe1\x3e\xa4\x59\xe1\x3e\xcf\x12\xda\xbe\xcf\x12\xda\xbe\xa6\xf0\xd8\x3e\xc0\xe2\x0c\x3f\xb2\x34\x8d\x3d\x18\x62\xd0\x3e\x18\x62\xd0\x3e\x80\x46\xc5\xbc\x80\x46\xc5\xbc\xbb\x5a\x89\xbc\x63\x2d\x0d\x3f\x6e\xaf\xcf\x3e\x21\xcf\xbc\x3e\x21\xcf\xbc\x3e\xa2\xe0\xc3\x3e\xa2\xe0\xc3\x3e\xed\x80\xc9\xbe\x02\x78\x0d\x3f\x73\xdc\xa2\xbe\x43\x9e\x87\x3e\x43\x9e\x87\x3e\xa2\x67\x39\x3f\xa2\x67\x39\x3f\xd7\x0f\x3d\x3f\x9f\xc2\x0d\x3f\x79\x3a\x61\xbe\xee\xd5\x53\x3e\xee\xd5\x53\x3e\x60\x12\x71\x3f\x60\x12\x71\x3f\xff\x89\x75\xbf\x38\x0d\x0e\x3f\x82\xd3\xeb\x3e\x28\xbf\x2c\x3e\x28\xbf\x2c\x3e\x53\x22\x7f\x3f\x53\x22\x7f\x3f\x98\x19\x82\x3f\xce\x57\x0e\x3f\xe4\x96\x70\xbd\x9c\x7b\x72\x3d\x9c\x7b\x72\x3d\xa3\xea\x60\x3f\xa3\xea\x60\x3f\x28\x09\x66\xbf\x62\xa2\x0e\x3f\xbb\xe0\xdc\xbe\x74\x22\x2d\xbc\x74\x22\x2d\xbc\x52\x71\x1b\x3f\x52\x71\x1b\x3f\x7a\xbc\x1f\x3f\xf3\xec\x0e\x3f\x54\x0d\xa4\x3e\x87\xf3\x55\xbd\x87\xf3\x55\xbd\xdf\x9c\x6a\x3e\xdf\x9c\x6a\x3e\x5d\x5a\x74\xbe\x81\x37\x0f\x3f\x04\x11\x77\x3e\x0b\x0e\x21\xbe\x0b\x0e\x21\xbe\xb9\x6f\x42\xbe\xb9\x6f\x42\xbe\x31\x91\x43\xbe\x0b\x82\x0f\x3f\xbb\x36\xed\xbe\xcc\xe7\x67\xbe\xcc\xe7\x67\xbe\x33\x83\x13\xbf\x33\x83\x13\xbf\xce\xd3\x16\x3f\x92\xcc\x0f\x3f\x11\x5e\x00\x3d\x7b\x0b\x87\xbe\x7b\x0b\x87\xbe\x21\x88\x5c\xbf\x21\x88\x5c\xbf\xa6\x66\x62\xbf\x14\x17\x10\x3f\xde\x3b\xe2\x3e\x7f\xab\xb6\xbe\x7f\xab\xb6\xbe\x09\x93\x7e\xbf\x09\x93\x7e\xbf\x4c\xdc\x82\x3f\x94\x61\x10\x3f\x55\x97\x91\xbe\xd8\x65\xd9\xbe\xd8\x65\xd9\xbe\x1b\x5f\x73\xbf\x1b\x5f\x73\xbf\xf0\xf8\x79\xbf\x0f\xac\x10\x3f\xac\x24\x8e\xbe\x49\x7e\xe4\xbe\x49\x7e\xe4\xbe\x5c\xb1\x3c\xbf\x5c\xb1\x3c\xbf\xe7\xce\x40\x3f\x87\xf6\x10\x3f\xb2\xab\xe1\x3e\xb0\xae\x03\xbf\xb0\xae\x03\xbf\x2b\x3b\xc8\xbe\x2b\x3b\xc8\xbe\x4c\x6f\xc8\xbe\xfa\x40\x11\x3f\xb2\xab\xe7\x3c\xc2\x47\x13\xbf\xc2\x47\x13\xbf\xa1\x8b\xd3\x3c\xa1\x8b\xd3\x3c\x0b\x2c\x32\xbd\x6a\x8b\x11\x3f\x29\xc0\xe9\xbe\xa3\xc3\x15\xbf\xa3\xc3\x15\xbf\x78\xa8\xe0\x3e\x78\xa8\xe0\x3e\x97\xb2\xf1\x3e\xd4\xd5\x11\x3f\x0f\x75\x68\x3e\xef\x06\x1e\xbf\xef\x06\x1e\xbf\x75\xe2\x45\x3f\x75\xe2\x45\x3f\xa7\x86\x50\xbf\x3a\x20\x12\x3f\x5f\xd6\xa9\x3e\x19\x2d\x29\xbf\x19\x2d\x29\xbf\xd3\x9b\x77\x3f\xd3\x9b\x77\x3f\xba\xd0\x80\x3f\x9c\x6a\x12\x3f\xdc\xfc\xd2\xbe\xc7\xee\x27\xbf\xc7\xee\x27\xbf\x9c\x3c\x7c\x3f\x9c\x3c\x7c\x3f\x61\x58\x81\xbf\xf8\xb4\x12\x3f\x78\x8d\xd9\xbd\x14\x63\x28\xbf\x14\x63\x28\xbf\xf8\xb0\x52\x3f\xf8\xb0\x52\x3f\xc9\x33\x53\x3f\x4e\xff\x12\x3f\x8e\x77\xf2\x3e\x27\x07\x2d\xbf\x27\x07\x2d\xbf\xed\x5e\x02\x3f\xed\x5e\x02\x3f\xb9\xbe\xf7\xbe\xa2\x49\x13\x3f\xc1\x61\x1c\xbe\xe9\x66\x26\xbf\xe9\x66\x26\xbf\xfd\x0e\xcf\x3d\xfd\x0e\xcf\x3d\x4d\x6d\x51\x3d\xf0\x93\x13\x3f\xa6\x84\xc9\xbe\x4b\xc3\x1f\xbf\x4b\xc3\x1f\xbf\xc9\x1f\xa7\xbe\xc9\x1f\xa7\xbe\xeb\x57\xc8\x3e\x39\xde\x13\x3f\xe6\x24\xbc\x3e\xaa\x5a\x1e\xbf\xaa\x5a\x1e\xbf\x79\xa7\x31\xbf\x79\xa7\x31\xbf\x49\x69\x42\xbf\x7a\x28\x14\x3f\xc9\x7f\x4a\x3e\x82\x9e\x13\xbf\x82\x9e\x13\xbf\xed\xc5\x6e\xbf\xed\xc5\x6e\xbf\xe8\xcd\x7b\x3f\xb7\x72\x14\x3f\xb2\x99\xf3\xbe\x52\x24\x04\xbf\x52\x24\x04\xbf\x7f\x54\x7f\xbf\x7f\x54\x7f\xbf\xaa\xce\x82\xbf\xee\xbc\x14\x3f\x4f\xb5\x63\x3d\x87\x43\xfa\xbe\x87\x43\xfa\xbe\x9d\x00\x60\xbf\x9d\x00\x60\xbf\xd9\x28\x5e\x3f\x1f\x07\x15\x3f\xd6\x7e\xe4\x3e\xfa\x84\xe1\xbe\xfa\x84\xe1\xbe\xb7\x71\x16\xbf\xb7\x71\x16\xbf\x31\x01\x0d\xbf\x49\x51\x15\x3f\xa4\xe7\x93\xbe\x23\xb7\xb5\xbe\x23\xb7\xb5\xbe\xef\x4e\x41\xbe\xef\x4e\x41\xbe\xdd\x95\x05\x3e\x6d\x9b\x15\x3f\xd4\xed\x96\xbe\x50\x07\x9c\xbe\x50\x07\x9c\xbe\xfd\x89\x7c\x3e\xfd\x89\x7c\x3e\xe5\x68\xa1\x3e\x8b\xe5\x15\x3f\x0c\x07\xe1\x3e\x90\x5b\x7d\xbe\x90\x5b\x7d\xbe\x80\xc6\x22\x3f\x80\xc6\x22\x3f\x0f\x57\x34\xbf\xa2\x2f\x16\x3f\x75\x0b\x8a\x3d\x25\x82\x1c\xbe\x25\x82\x1c\xbe\xbc\x82\x67\x3f\xbc\x82\x67\x3f\x87\x43\x77\x3f\xb3\x79\x16\x3f\xe9\xc9\xf0\xbe\x1e\x4e\xb8\xbd\x1e\x4e\xb8\xbd\x90\x03\x80\x3f\x90\x03\x80\x3f\xb5\x86\x86\xbf\xbd\xc3\x16\x3f\x37\x5b\x2f\x3e\x6a\xa5\xf1\xbc\x6a\xa5\xf1\xbc\x1d\x66\x67\x3f\x1d\x66\x67\x3f\x23\x38\x71\x3f\xc0\x0d\x17\x3f\x26\xfd\xc1\x3e\x94\xdc\x8f\x3d\x94\xdc\x8f\x3d\x27\x1f\x22\x3f\x27\x1f\x22\x3f\x4f\x18\x28\xbf\xbc\x57\x17\x3f\x37\xfa\xb5\xbe\xca\xac\x0f\x3e\xca\xac\x0f\x3e\xcd\x7d\x75\x3e\xcd\x7d\x75\x3e\xe8\x39\x79\x3e\xb0\xa1\x17\x3f\xed\xcd\x4f\xbe\xa7\x8c\x43\x3e\xa7\x8c\x43\x3e\xeb\xc2\x4d\xbe\xeb\xc2\x4d\xbe\x77\xaf\x64\x3e\x9d\xeb\x17\x3f\xa9\x94\xe6\x3e\xaf\x1f\x90\x3e\xaf\x1f\x90\x3e\xd0\x66\x1a\xbf\xd0\x66\x1a\xbf\xf6\x2c\x28\xbf\x82\x35\x18\x3f\xbe\x66\x3f\xbc\xfb\x8b\xb5\x3e\xfb\x8b\xb5\x3e\x4e\x5a\x63\xbf\x4e\x5a\x63\xbf\x75\x4c\x79\x3f\x60\x7f\x18\x3f\xcf\x84\xe3\xbe\xe6\x86\xc9\x3e\xe6\x86\xc9\x3e\x2d\xda\x7f\xbf\x2d\xda\x7f\xbf\xe4\x04\x8e\xbf\x34\xc9\x18\x3f\x35\xa5\x61\x3e\x98\x01\xed\x3e\x98\x01\xed\x3e\x9d\x10\x6a\xbf\x9d\x10\x6a\xbf\xf2\x2e\x84\x3f\x02\x13\x19\x3f\x22\xef\xae\x3e\x28\x50\x07\x3f\x28\x50\x07\x3f\xaf\x05\x26\xbf\xaf\x05\x26\xbf\xc1\xdb\x40\xbf\xc7\x5c\x19\x3f\xf3\x0f\xc2\xbe\xca\xde\x0b\x3f\xca\xde\x0b\x3f\x30\xef\x81\xbe\x30\xef\x81\xbe\x7c\x5d\xa5\x3e\x84\xa6\x19\x3f\xd1\x7b\x2b\xbe\xfe\xc8\x17\x3f\xfe\xc8\x17\x3f\x71\xaa\x44\x3e\x71\xaa\x44\x3e\x1e\xee\x32\x3e\x39\xf0\x19\x3f\xbd\x12\xea\x3e\xbc\x4d\x25\x3f\xbc\x4d\x25\x3f\x4b\xab\x19\x3f\x4b\xab\x19\x3f\x19\xef\x23\xbf\xe4\x39\x1a\x3f\xb6\x2a\x26\xbd\x86\xd7\x22\x3f\x86\xd7\x22\x3f\xa3\x93\x63\x3f\xa3\x93\x63\x3f\x8f\xb6\x7a\x3f\x85\x83\x1a\x3f\x97\xe0\xe2\xbe\xd2\x28\x27\x3f\xd2\x28\x27\x3f\x4a\xe4\x7f\x3f\x4a\xe4\x7f\x3f\xdc\xa3\x8f\xbf\x1e\xcd\x1a\x3f\x2c\x8b\x7a\x3e\x19\xa7\x2f\x3f\x19\xa7\x2f\x3f\xa5\xac\x68\x3f\xa5\xac\x68\x3f\xf6\x14\x85\x3f\xaf\x16\x1b\x3f\xfc\x10\xac\x3e\xaf\x89\x27\x3f\xaf\x89\x27\x3f\xdc\x5d\x22\x3f\xdc\x5d\x22\x3f\x4a\xe2\x3f\xbf\x36\x60\x1b\x3f\xb6\x69\xce\xbe\x24\xa4\x23\x3f\x24\xa4\x23\x3f\x9d\x0e\x6c\x3e\x9d\x0e\x6c\x3e\x53\xfe\x9f\x3e\xb2\xa9\x1b\x3f\x30\xfa\x1b\xbe\x91\x22\x25\x3f\x91\x22\x25\x3f\xcf\xff\x61\xbe\xcf\xff\x61\xbe\x28\xf3\x38\x3e\x26\xf3\x1b\x3f\x8a\xec\xf2\x3e\xd3\xcc\x17\x3f\xd3\xcc\x17\x3f\xdf\xa8\x20\xbf\xdf\xa8\x20\xbf\x2a\xca\x20\xbf\x8f\x3c\x1c\x3f\x67\x39\x82\xbd\xf0\xf1\x0d\x3f\xf0\xf1\x0d\x3f\x3d\x16\x68\xbf\x3d\x16\x68\xbf\x49\x57\x70\x3f\xee\x85\x1c\x3f\x78\xc3\xe2\xbe\xea\xde\x07\x3f\xea\xde\x07\x3f\x84\xf1\x7f\xbf\x84\xf1\x7f\xbf\x77\x95\x86\xbf\x44\xcf\x1c\x3f\xc1\x85\x83\x3e\x7a\xf9\xe8\x3e\x7a\xf9\xe8\x3e\x6f\x11\x63\xbf\x6f\x11\x63\xbf\xa5\x5a\x72\x3f\x8e\x18\x1d\x3f\x06\x4c\xa8\x3e\x8d\x94\xcf\x3e\x8d\x94\xcf\x3e\xd8\x2c\x17\xbf\xd8\x2c\x17\xbf\xff\xa1\x26\xbf\xcd\x61\x1d\x3f\xf2\xab\xc9\xbe\x1d\x08\xb8\x3e\x1d\x08\xb8\x3e\xe3\x29\x2f\xbe\xe3\x29\x2f\xbe\x09\xef\x6a\x3e\x02\xab\x1d\x3f\xff\x15\x27\xbe\x8c\xf0\x84\x3e\x8c\xf0\x84\x3e\x0a\xc1\x91\x3e\x0a\xc1\x91\x3e\xe2\x3a\x69\x3e\x2c\xf4\x1d\x3f\x4f\x50\xec\x3e\x41\xa0\x50\x3e\x41\xa0\x50\x3e\x9b\x81\x2e\x3f\x9b\x81\x2e\x3f\x60\x09\x20\xbf\x4b\x3d\x1e\x3f\xce\x69\xea\xbc\xac\x86\x18\x3e\xac\x86\x18\x3e\x66\xb8\x6f\x3f\x66\xb8\x6f\x3f\x91\xa7\x61\x3f\x5f\x86\x1e\x3f\xbc\x57\xe5\xbe\xd0\xf6\x13\x3d\xd0\xf6\x13\x3d\xfc\x9e\x7e\x3f\xfc\x9e\x7e\x3f\x31\x39\x72\xbf\x66\xcf\x1e\x3f\xff\xe5\x57\x3e\x53\x8a\xe7\xbc\x53\x8a\xe7\xbc\x2a\xd2\x57\x3f\x2a\xd2\x57\x3f\x24\x29\x4f\x3f\x62\x18\x1f\x3f\xc9\xcd\xb7\x3e\x57\x26\xa4\xbd\x57\x26\xa4\xbd\x6b\x49\x03\x3f\x6b\x49\x03\x3f\x15\x93\x00\xbf\x51\x61\x1f\x3f\x60\x9d\xb2\xbe\xf2\xdb\x3f\xbe\xf2\xdb\x3f\xbe\x31\x0e\x96\x3d\x31\x0e\x96\x3d\x44\xe4\xbb\x3d\x34\xaa\x1f\x3f\xec\x47\x64\xbe\x45\x75\x84\xbe\x45\x75\x84\xbe\x0e\xdf\xc3\xbe\x0e\xdf\xc3\xbe\x40\x51\xab\x3e\x0c\xf3\x1f\x3f\xde\x5c\xdd\x3e\x53\x22\x9c\xbe\x53\x22\x9c\xbe\xad\xe1\x41\xbf\xad\xe1\x41\xbf\x47\x8d\x2f\xbf\xd7\x3b\x20\x3f\xc3\x8e\x80\x3d\x11\x03\xc6\xbe\x11\x03\xc6\xbe\x71\x68\x78\xbf\x71\x68\x78\xbf\xcb\xd3\x62\x3f\x96\x84\x20\x3f\x69\x06\xed\xbe\x8d\x59\xe8\xbe\x8d\x59\xe8\xbe\x5d\x95\x79\xbf\x5d\x95\x79\xbf\xd0\x2e\x64\xbf\x46\xcd\x20\x3f\x4d\x1e\xe9\x3d\x00\x01\xff\xbe\x00\x01\xff\xbe\x03\xe6\x44\xbf\x03\xe6\x44\xbf\xa7\xee\x32\x3f\xea\x15\x21\x3f\xd9\x56\xdb\x3e\x60\xc3\x0a\xbf\x60\xc3\x0a\xbf\x1d\x04\xcb\xbe\x1d\x04\xcb\xbe\x6c\xcd\xb2\xbe\x82\x5e\x21\x3f\x79\x1b\x93\xbe\xe9\x1f\x17\xbf\xe9\x1f\x17\xbf\xae\x97\x80\x3d\xae\x97\x80\x3d\xa9\x28\xa8\xbd\x0a\xa7\x21\x3f\x93\x2b\xa1\xbe\xc0\x80\x21\xbf\xc0\x80\x21\xbf\xc7\x55\x02\x3f\xc7\x55\x02\x3f\x1c\xcf\xff\x3e\x86\xef\x21\x3f\x63\xbc\xd1\x3e\xb9\xf7\x22\xbf\xb9\xf7\x22\xbf\x38\x48\x58\x3f\x38\x48\x58\x3f\xbd\x26\x4f\xbf\xf3\x37\x22\x3f\x20\x03\x1b\x3e\x90\x1c\x27\xbf\x90\x1c\x27\xbf\xbe\xed\x7e\x3f\xbe\xed\x7e\x3f\x2e\x7d\x70\x3f\x52\x80\x22\x3f\x95\xba\xe8\xbe\xd8\xc3\x2e\xbf\xd8\xc3\x2e\xbf\xbc\x8d\x6d\x3f\xbc\x8d\x6d\x3f\x9d\xcf\x5b\xbf\xa3\xc8\x22\x3f\x8c\x75\x23\x3c\xa0\xe8\x28\xbf\xa0\xe8\x28\xbf\xab\xbc\x27\x3f\xab\xbc\x27\x3f\x08\x3a\x15\x3f\xe4\x10\x23\x3f\x44\x92\xe4\x3e\x5d\x32\x23\xbf\x5d\x32\x23\xbf\x2d\xc7\x72\x3e\x2d\xc7\x72\x3e\x08\x2b\x31\xbe\x17\x59\x23\x3f\x21\xff\x21\xbe\xdc\xda\x24\xbf\xdc\xda\x24\xbf\xeb\xed\x6f\xbe\xeb\xed\x6f\xbe\xa2\xdd\x8e\xbe\x3b\xa1\x23\x3f\x13\x47\xcd\xbe\xa5\xe4\x19\xbf\xa5\xe4\x19\xbf\xb4\x7a\x27\xbf\xb4\x7a\x27\xbf\x83\xbe\x2b\x3f\x50\xe9\x23\x3f\x2e\xa1\x99\x3e\x8d\xfb\x0c\xbf\x8d\xfb\x0c\xbf\xfc\xb5\x6d\xbf\xfc\xb5\x6d\xbf\x59\xcd\x69\xbf\x54\x31\x24\x3f\x7e\x28\x9c\x3e\xb2\x94\x06\xbf\xb2\x94\x06\xbf\x7e\xc0\x7e\xbf\x7e\xc0\x7e\xbf\xe1\x61\x73\x3f\x4a\x79\x24\x3f\x98\x87\xd4\xbe\xb4\x46\xec\xbe\xb4\x46\xec\xbe\x53\x85\x56\xbf\x53\x85\x56\xbf\xdb\x23\x46\xbf\x2e\xc1\x24\x3f\x74\xf7\x22\xbe\x5e\x4d\xcb\xbe\x5e\x4d\xcb\xbe\x3e\xa8\xfb\xbe\x3e\xa8\xfb\xbe\x82\x5c\xd8\x3e\x03\x09\x25\x3f\x22\xe5\xf1\x3e\x58\x36\xb1\xbe\x58\x36\xb1\xbe\x63\x6e\x08\xbd\x63\x6e\x08\xbd\xec\x8d\xc5\x3c\xc8\x50\x25\x3f\x37\x67\xf0\xbb\xdd\x43\x86\xbe\xdd\x43\x86\xbe\x38\xc3\xdd\x3e\x38\xc3\xdd\x3e\xf5\xe4\xed\xbe\x7c\x98\x25\x3f\xb5\x53\xed\xbe\x9d\x71\x44\xbe\x9d\x71\x44\xbe\x3b\x34\x4d\x3f\x3b\x34\x4d\x3f\xa3\x67\x4c\x3f\x1e\xe0\x25\x3f\x95\x6b\x24\x3e\xef\x75\xfe\xbd\xef\x75\xfe\xbd\xeb\xc6\x7c\x3f\xeb\xc6\x7c\x3f\x00\xfa\x72\xbf\xb0\x27\x26\x3f\xe1\x7b\xce\x3e\x30\x45\xf6\xbc\x30\x45\xf6\xbc\xaf\x7d\x72\x3f\xaf\x7d\x72\x3f\x7c\xd0\x61\x3f\x31\x6f\x26\x3f\x03\x57\x90\xbe\x14\x2a\x23\x3d\x14\x2a\x23\x3d\x27\x75\x30\x3f\x27\x75\x30\x3f\xda\xe5\x1c\xbf\x9e\xb6\x26\x3f\xe9\x24\xa1\xbe\xfb\x5b\xe4\x3d\xfb\x5b\xe4\x3d\x88\x4d\x8b\x3e\x88\x4d\x8b\x3e\x6c\x97\x50\x3e\xfa\xfd\x26\x3f\x70\xff\xbe\x3e\x27\xb5\x53\x3e\x27\xb5\x53\x3e\x4c\xa9\x55\xbe\x4c\xa9\x55\xbe\xef\x90\x80\x3e\x43\x45\x27\x3f\xfd\x04\x56\x3e\xe7\xe0\x89\x3e\xe7\xe0\x89\x3e\xfc\x45\x24\xbf\xfc\x45\x24\xbf\x17\xa5\x25\xbf\x7c\x8c\x27\x3f\x8d\xc8\xe1\xbe\x5b\x36\xaa\x3e\x5b\x36\xaa\x3e\x2b\x12\x6d\xbf\x2b\x12\x6d\xbf\xff\xc8\x64\x3f\xa1\xd3\x27\x3f\x3c\x63\xa4\xbd\x6f\xc3\xd5\x3e\x6f\xc3\xd5\x3e\xbe\xa3\x7e\xbf\xbe\xa3\x7e\xbf\xdb\x63\x6f\xbf\xb2\x1a\x28\x3f\x1b\xb7\xf2\x3e\xe1\x42\xee\x3e\xe1\x42\xee\x3e\xb3\x9b\x54\xbf\xb3\x9b\x54\xbf\x09\x15\x43\x3f\x11\x62\x28\x3f\x4f\xd1\x87\xbd\x3d\x52\x03\x3f\x3d\x52\x03\x3f\x6f\x25\xf1\xbe\x6f\x25\xf1\xbe\x15\x94\xd3\xbe\xbd\xa9\x28\x3f\x1a\xfe\xe8\xbe\xbc\x4e\x13\x3f\xbc\x4e\x13\x3f\x1f\x4f\x1c\x38\x1f\x4f\x1c\x38\x47\x02\x09\xbd\x74\xf4\x28\x3f\x39\xc4\x4f\x3e\xcc\x40\x1a\x3f\xcc\x40\x1a\x3f\x6e\x86\xf1\x3e\x6e\x86\xf1\x3e\x77\xd3\xf4\x3e\x34\x42\x29\x3f\x74\x4f\xc9\x3e\xfb\xa5\x20\x3f\xfb\xa5\x20\x3f\x1a\x0e\x55\x3f\x1a\x0e\x55\x3f\xc1\x09\x52\xbf\xa3\x89\x29\x3f\xc6\x53\xa0\xbe\x61\x23\x29\x3f\x61\x23\x29\x3f\x28\xd0\x7e\x3f\x28\xd0\x7e\x3f\xbd\x11\x7b\x3f\xbf\xca\x29\x3f\xd0\x45\x9d\xbe\x31\x40\x2a\x3f\x31\x40\x2a\x3f\xfc\xdb\x6b\x3f\xfc\xdb\x6b\x3f\xfc\x08\x6b\xbf\xba\x0e\x2a\x3f\xff\x75\xcd\x3e\x89\x01\x29\x3f\x89\x01\x29\x3f\xd1\x75\x20\x3f\xd1\x75\x20\x3f\xd0\x0d\x24\x3f\x92\x55\x2a\x3f\x16\x07\x4a\x3e\xc6\xed\x28\x3f\xc6\xed\x28\x3f\x77\xd1\x39\x3e\x77\xd1\x39\x3e\x1f\xf8\x53\xbe\x5a\x9c\x2a\x3f\x2d\x47\xeb\xbe\x70\xd8\x24\x3f\x70\xd8\x24\x3f\x89\xcc\x9d\xbe\x89\xcc\x9d\xbe\x3f\x7b\x92\xbe\x0f\xe3\x2a\x3f\x18\x7f\x8f\xbd\x2d\xdf\x1b\x3f\x2d\xdf\x1b\x3f\x85\x65\x39\xbf\x85\x65\x39\xbf\xeb\x00\x39\x3f\xb3\x29\x2b\x3f\x62\x09\xf5\x3e\xed\x51\x12\x3f\xed\x51\x12\x3f\x7f\x2b\x77\xbf\x7f\x2b\x77\xbf\xf4\xdf\x7e\xbf\x45\x70\x2b\x3f\x31\x7c\x6b\xbd\x2d\xfe\x09\x3f\x2d\xfe\x09\x3f\xf9\x02\x79\xbf\xf9\x02\x79\xbf\xd4\x51\x84\x3f\xc4\xb6\x2b\x3f\x97\x42\xed\xbe\xcd\xd8\xf5\x3e\xcd\xd8\xf5\x3e\xa5\x31\x3e\xbf\xa5\x31\x3e\xbf\x00\x71\x52\xbf\x32\xfd\x2b\x3f\xb7\xc0\x35\x3e\xa4\x46\xd1\x3e\xa4\x46\xd1\x3e\x50\x9c\xa9\xbe\x50\x9c\xa9\xbe\xdb\xf2\xd0\x3e\x8c\x43\x2c\x3f\xdb\xa1\xd5\x3e\xb5\xb8\xb9\x3e\xb5\xb8\xb9\x3e\xb3\x20\x26\x3e\xb3\x20\x26\x3e\x93\x8c\xdc\x3d\xd5\x89\x2c\x3f\xe8\xad\x90\xbe\xdc\x96\x93\x3e\xdc\x96\x93\x3e\x8d\xd7\x1d\x3f\x8d\xd7\x1d\x3f\x5a\xd2\x18\xbf\x0a\xd0\x2c\x3f\xa1\x29\xb0\xbe\x41\x40\x45\x3e\x41\x40\x45\x3e\x02\x64\x6b\x3f\x02\x64\x6b\x3f\xb4\xba\x6f\x3f\x2e\x16\x2d\x3f\xbf\x37\xba\x3e\xb5\x3a\x0d\x3e\xb5\x3a\x0d\x3e\x26\xd4\x7e\x3f\x26\xd4\x7e\x3f\x39\x29\x85\xbf\x3e\x5c\x2d\x3f\x9f\x5b\x82\x3e\x3f\xda\x71\x3d\x3f\xda\x71\x3d\xea\x15\x53\x3f\xea\x15\x53\x3f\xc7\x04\x62\x3f\x3d\xa2\x2d\x3f\x2c\xcf\xd6\xbe\xce\x47\x49\xbd\xce\x47\x49\xbd\x8c\x8b\xe5\x3e\x8c\x8b\xe5\x3e\xbb\x5e\x01\xbf\x28\xe8\x2d\x3f\x71\x79\x21\xbe\x16\xcf\xdc\xbd\x16\xcf\xdc\xbd\x96\xe3\x24\xbd\x96\xe3\x24\xbd\x2b\xed\xa4\x3b\x02\x2e\x2e\x3f\x49\x06\xe8\x3e\x0a\x5a\x36\xbe\x0a\x5a\x36\xbe\xd3\xf7\x04\xbf\xd3\xf7\x04\xbf\xa6\xdb\xfa\x3e\xc7\x73\x2e\x3f\x2c\x48\x68\x3d\x10\xf1\x90\xbe\x10\xf1\x90\xbe\x08\x6a\x5e\xbf\x08\x6a\x5e\xbf\xa1\x89\x5a\xbf\x78\xb9\x2e\x3f\x52\xe9\xed\xbe\x52\x27\xae\xbe\x52\x27\xae\xbe\x5d\xfc\x7f\xbf\x5d\xfc\x7f\xbf\xfd\x85\x7e\x3f\x15\xff\x2e\x3f\x96\x8f\x30\x3d\x3b\xd8\xc9\xbe\x3b\xd8\xc9\xbe\x8c\xf8\x60\xbf\x8c\xf8\x60\xbf\x13\x7c\x60\xbf\x9e\x44\x2f\x3f\x75\xe2\xe9\x3e\xb7\xec\xf5\xbe\xb7\xec\xf5\xbe\xe6\xf1\x08\xbf\xe6\xf1\x08\xbf\xfc\x50\x08\x3f\x13\x8a\x2f\x3f\x6d\x75\x0e\xbe\x55\x77\x06\xbf\x55\x77\x06\xbf\xf7\x4c\x60\xbd\xf7\x4c\x60\xbd\xe9\x2d\x4b\xbd\x75\xcf\x2f\x3f\x9e\x7a\xdd\xbe\xa7\xe9\x0e\xbf\xa7\xe9\x0e\xbf\xd6\x47\xe1\x3e\xd6\x47\xe1\x3e\x21\x39\xe5\xbe\xc4\x14\x30\x3f\x87\x46\x6f\x3e\x24\xf2\x1d\xbf\x24\xf2\x1d\xbf\xa2\xae\x52\x3f\xa2\xae\x52\x3f\x9f\xcb\x54\x3f\x02\x5a\x30\x3f\x34\x57\xc5\x3e\xe5\x7f\x23\xbf\xe5\x7f\x23\xbf\xce\xdd\x7e\x3f\xce\xdd\x7e\x3f\x43\x24\x80\xbf\x27\x9f\x30\x3f\x04\x92\xa2\xbe\x2a\x79\x25\xbf\x2a\x79\x25\xbf\x35\x9f\x69\x3f\x35\x9f\x69\x3f\x5a\x50\x69\x3f\x34\xe4\x30\x3f\x74\x00\xa2\xbe\x1d\x88\x2c\xbf\x1d\x88\x2c\xbf\xa5\x27\x18\x3f\xa5\x27\x18\x3f\x11\x15\x15\xbf\x2f\x29\x31\x3f\x09\xbc\xc1\x3e\xc3\x5f\x2a\xbf\xc3\x5f\x2a\xbf\x39\x16\xfa\x3d\x39\x16\xfa\x3d\xce\xf6\xc4\x3d\x17\x6e\x31\x3f\x88\x25\x76\x3e\xf6\xf4\x24\xbf\xf6\xf4\x24\xbf\x2e\xcd\xc3\xbe\x2e\xcd\xc3\xbe\xee\xcb\xd8\x3e\xea\xb2\x31\x3f\x41\x1a\xd7\xbe\x66\xa5\x24\xbf\x66\xa5\x24\xbf\xf0\xca\x49\xbf\xf0\xca\x49\xbf\x02\xb4\x57\xbf\xa6\xf7\x31\x3f\x0b\x7b\x27\xbe\x30\xba\x1a\xbf\x30\xba\x1a\xbf\xbb\x37\x7d\xbf\xbb\x37\x7d\xbf\x4f\xa1\x86\x3f\x4e\x3c\x32\x3f\x42\x75\xe5\x3e\x6f\xe1\x0c\xbf\x6f\xe1\x0c\xbf\x15\x80\x6e\xbf\x15\x80\x6e\xbf\xa7\x96\x7e\xbf\xdf\x80\x32\x3f\x56\x7b\xb0\x3d\x68\x7b\x06\xbf\x68\x7b\x06\xbf\xba\x35\x21\xbf\xba\x35\x21\xbf\x5f\xa7\x2e\x3f\x5c\xc5\x32\x3f\x62\xdc\xed\xbe\x4b\x52\xed\xbe\x4b\x52\xed\xbe\x00\x98\x25\xbe\x00\x98\x25\xbe\x20\x3d\x45\xbe\xc3\x09\x33\x3f\xea\x4e\x06\xbc\x09\xc8\xc2\xbe\x09\xc8\xc2\xbe\x0a\x07\xb3\x3e\x0a\x07\xb3\x3e\xad\x42\xb3\xbe\x14\x4e\x33\x3f\x91\x30\xf1\x3e\xfe\xed\xaa\xbe\xfe\xed\xaa\xbe\x0d\xed\x44\x3f\x0d\xed\x44\x3f\xd8\x7e\x4e\x3f\x4e\x92\x33\x3f\x05\x71\x96\xbd\x32\x39\x84\xbe\x32\x39\x84\xbe\x45\x38\x7c\x3f\x45\x38\x7c\x3f\x93\x80\x87\xbf\x72\xd6\x33\x3f\x60\x7d\xec\xbe\x73\x57\x23\xbe\x73\x57\x23\xbe\x15\x74\x70\x3f\x15\x74\x70\x3f\xbf\x20\x85\x3f\x82\x1a\x34\x3f\x2b\x9a\x1c\x3e\x16\x62\xc8\xbd\x16\x62\xc8\xbd\xc1\x7e\x24\x3f\xc1\x7e\x24\x3f\xfc\x5c\x41\xbf\x79\x5e\x34\x3f\xcf\x94\xdf\x3e\x1d\xa2\x60\xbc\x1d\xa2\x60\xbc\x8f\xa9\x31\x3e\x8f\xa9\x31\x3e\x03\xe0\x8e\x3e\x5a\xa2\x34\x3f\x1e\xe2\x64\xbe\x00\x23\xb1\x3d\x00\x23\xb1\x3d\xb3\x79\xaf\xbe\xb3\x79\xaf\xbe\xd1\x79\x86\x3e\x24\xe6\x34\x3f\xd3\x52\xcd\xbe\x06\x70\x16\x3e\x06\x70\x16\x3e\xc0\x72\x44\xbf\xc0\x72\x44\xbf\x22\xbc\x39\xbf\xd9\x29\x35\x3f\x42\x0e\x92\x3e\x63\x9e\x6d\x3e\x63\x9e\x6d\x3e\xc0\x46\x7c\xbf\xc0\x46\x7c\xbf\x44\x87\x7c\x3f\x76\x6d\x35\x3f\x18\x81\xb6\x3e\x47\x29\xa7\x3e\x47\x29\xa7\x3e\x23\xe4\x6f\xbf\x23\xe4\x6f\xbf\x1a\x45\x7a\xbf\xfa\xb0\x35\x3f\xcb\x08\xac\xbe\x54\xec\xbe\x3e\x54\xec\xbe\x3e\x3e\x5f\x22\xbf\x3e\x5f\x22\xbf\xd4\xba\x34\x3f\x68\xf4\x35\x3f\xa5\x17\x9d\xbe\xd0\x3b\xe2\x3e\xd0\x3b\xe2\x3e\xe9\x31\x22\xbe\xe9\x31\x22\xbe\x2e\xbd\x80\xbe\xbd\x37\x36\x3f\x59\xcf\xbf\x3e\x3b\x43\x05\x3f\x3b\x43\x05\x3f\xbc\x06\xb9\x3e\xbc\x06\xb9\x3e\xab\xe6\x82\xbe\xfb\x7a\x36\x3f\x81\x7f\x84\x3e\x3c\x94\x0c\x3f\x3c\x94\x0c\x3f\xca\x6f\x48\x3f\xca\x6f\x48\x3f\x61\x06\x2c\x3f\x22\xbe\x36\x3f\xc6\x49\xd0\xbe\x2b\xb7\x17\x3f\x2b\xb7\x17\x3f\xc4\x7b\x7d\x3f\xc4\x7b\x7d\x3f\xc6\xdb\x61\xbf\x31\x01\x37\x3f\x86\x87\x59\xbe\xe3\x74\x24\x3f\xe3\x74\x24\x3f\x49\xd0\x6c\x3f\x49\xd0\x6c\x3f\x22\x0e\x55\x3f\x28\x44\x37\x3f\x1e\x2c\xe0\x3e\x38\x21\x25\x3f\x38\x21\x25\x3f\xee\xbd\x1a\x3f\xee\xbd\x1a\x3f\x70\x07\x0b\xbf\x06\x87\x37\x3f\xc7\x8a\x24\x3e\x65\xd8\x28\x3f\x65\xd8\x28\x3f\x29\xd7\xed\x3d\x29\xd7\xed\x3d\xec\x15\xd4\x3d\xcc\xc9\x37\x3f\xe1\x53\xed\xbe\xc7\x3a\x2d\x3f\xc7\x3a\x2d\x3f\x13\x5e\xcf\xbe\x13\x5e\xcf\xbe\xc9\xc5\xb6\x3e\x78\x0c\x38\x3f\xae\x8b\xce\xbd\x2a\xc0\x26\x3f\x2a\xc0\x26\x3f\xd2\x63\x50\xbf\xd2\x63\x50\xbf\x4b\xcc\x34\xbf\x0b\x4f\x38\x3f\xa4\x18\xf3\x3e\x75\xee\x21\x3f\x75\xee\x21\x3f\xd2\x09\x7f\xbf\xd2\x09\x7f\xbf\xad\x91\x58\x3f\x86\x91\x38\x3f\x1c\x8f\x2b\x3d\x61\x1c\x1d\x3f\x61\x1c\x1d\x3f\xf9\x53\x66\xbf\xf9\x53\x66\xbf\x7d\xe9\x3c\xbf\xe8\xd3\x38\x3f\x91\xb2\xf1\xbe\x4c\x1d\x10\x3f\x4c\x1d\x10\x3f\x12\xe7\x0c\xbf\x12\xe7\x0c\xbf\xfe\x46\xd3\x3e\x30\x16\x39\x3f\x7f\x3c\xdd\x3b\xc7\x3f\x04\x3f\xc7\x3f\x04\x3f\x8f\xdd\x3a\xbd\x8f\xdd\x3a\xbd\xb0\xcf\x24\x3d\x60\x58\x39\x3f\x53\xac\xee\x3e\x16\x56\xef\x3e\x16\x56\xef\x3e\x36\x06\xf2\x3e\x36\x06\xf2\x3e\x46\x12\xfe\xbe\x74\x9a\x39\x3f\xa2\xc3\x44\xbd\x8f\x16\xc9\x3e\x8f\x16\xc9\x3e\xf2\x9b\x5b\x3f\xf2\x9b\x5b\x3f\x02\x11\x54\x3f\x70\xdc\x39\x3f\x79\x6b\xec\xbe\x83\xbf\xa4\x3e\x83\xbf\xa4\x3e\x8b\xf9\x7f\x3f\x8b\xf9\x7f\x3f\x67\xb0\x70\xbf\x50\x1e\x3a\x3f\x59\xdd\xb2\x3d\x1f\xce\x81\x3e\x1f\xce\x81\x3e\xbf\x80\x5b\x3f\xbf\x80\x5b\x3f\x16\xb3\x4a\x3f\x18\x60\x3a\x3f\x55\x4e\xea\x3e\x29\x71\x2d\x3e\x29\x71\x2d\x3e\xc6\xa1\xf0\x3e\xc6\xa1\xf0\x3e\x45\x87\xd3\xbe\xc4\xa1\x3a\x3f\xd7\xac\x02\xbe\xa9\x94\xa7\x3d\xa9\x94\xa7\x3d\xcf\xf2\x56\xbd\xcf\xf2\x56\xbd\x2d\x0b\xcd\xbd\x56\xe3\x3a\x3f\xdb\x08\xe6\xbe\xb3\x5a\x8e\xb8\xb3\x5a\x8e\xb8\xc0\x7c\x0f\xbf\xc0\x7c\x0f\xbf\x11\xdf\x1b\x3f\xcd\x24\x3b\x3f\xf5\xcb\x2a\x3e\x82\xbf\xa9\xbd\x82\xbf\xa9\xbd\x74\x65\x68\xbf\x74\x65\x68\xbf\x3e\x97\x77\xbf\x28\x66\x3b\x3f\x44\x16\xde\x3e\xa9\xb4\x2b\xbe\xa9\xb4\x2b\xbe\xc2\x57\x7e\xbf\xc2\x57\x7e\xbf\x6b\x3d\x88\x3f\x6a\xa7\x3b\x3f\x9c\xa4\x4a\xbe\x1b\x4e\x80\xbe\x1b\x4e\x80\xbe\xe4\xb4\x4a\xbf\xe4\xb4\x4a\xbf\xc2\x6d\x5c\xbf\x90\xe8\x3b\x3f\xcb\xe5\xd5\xbe\x95\x6e\xa7\xbe\x95\x6e\xa7\xbe\x14\x57\xb8\xbe\x14\x57\xb8\xbe\xe6\xb0\xcf\x3e\x9c\x29\x3c\x3f\x6d\xd7\x63\x3e\x94\xbd\xca\xbe\x94\xbd\xca\xbe\xa7\x5f\x35\x3e\xa7\x5f\x35\x3e\xc9\x4e\x33\x3e\x8a\x6a\x3c\x3f\x5f\x94\xcf\x3e\xe9\x40\xed\xbe\xe9\x40\xed\xbe\x4a\xcf\x29\x3f\x4a\xcf\x29\x3f\xae\x37\x36\xbf\x5e\xab\x3c\x3f\xfe\x01\x7c\xbe\xd8\x93\x05\xbf\xd8\x93\x05\xbf\xff\xbd\x74\x3f\xff\xbd\x74\x3f\xda\x97\x85\x3f\x15\xec\x3c\x3f\x30\x72\xc9\xbe\xc1\x43\x11\xbf\xc1\x43\x11\xbf\xa1\xf0\x77\x3f\xa1\xf0\x77\x3f\x27\xe5\x88\xbf\xb0\x2c\x3d\x3f\x6b\xec\x88\x3e\xfc\x55\x1c\xbf\xfc\x55\x1c\xbf\xe4\x2a\x32\x3f\xe4\x2a\x32\x3f\x36\xaf\x47\x3f\x2f\x6d\x3d\x3f\x38\xce\xc3\x3e\xae\x2d\x24\xbf\xae\x2d\x24\xbf\x38\xe5\x5e\x3e\x38\xe5\x5e\x3e\x79\x1d\x86\xbe\x91\xad\x3d\x3f\xd0\xf4\x92\xbe\xec\x7a\x27\xbf\xec\x7a\x27\xbf\x35\xb8\xa6\xbe\x35\xb8\xa6\xbe\x70\x75\xa8\xbe\xd7\xed\x3d\x3f\x8f\xc8\xbe\xbe\x35\x7b\x2a\xbf\x35\x7b\x2a\xbf\x89\xdf\x45\xbf\x89\xdf\x45\xbf\x89\xf7\x50\x3f\x00\x2e\x3e\x3f\xd9\x63\x9d\x3e\x1c\xfb\x2a\xbf\x1c\xfb\x2a\xbf\x3e\xa6\x7d\xbf\x3e\xa6\x7d\xbf\x92\x2a\x87\xbf\x0c\x6e\x3e\x3f\x82\xd6\xb7\x3e\x05\x86\x25\xbf\x05\x86\x25\xbf\xbb\xd3\x69\xbf\xbb\xd3\x69\xbf\x2f\xba\x7a\x3f\xfa\xad\x3e\x3f\x09\xb8\xa5\xbe\x1d\x33\x1f\xbf\x1d\x33\x1f\xbf\x89\x0b\x10\xbf\x89\x0b\x10\xbf\xcd\x9c\x1c\xbf\xcc\xed\x3e\x3f\x66\x72\xaf\xbe\x4b\xf5\x17\xbf\x4b\xf5\x17\xbf\x38\x4b\x2f\xbd\x38\x4b\x2f\xbd\x07\xe4\x81\x3d\x7f\x2d\x3f\x3f\x36\x7f\xa9\x3e\xc8\xb0\x0a\xbf\xc8\xb0\x0a\xbf\x42\x30\xfb\x3e\x42\x30\xfb\x3e\x5c\xcf\x00\x3f\x14\x6d\x3f\x3f\xcd\x99\xa9\x3e\x15\x00\xf9\xbe\x15\x00\xf9\xbe\xf1\x72\x60\x3f\xf1\x72\x60\x3f\x22\xab\x6b\xbf\x8c\xac\x3f\x3f\xc8\x5f\xab\xbe\xf3\xc4\xdc\xbe\xf3\xc4\xdc\xbe\xcb\x92\x7f\x3f\xcb\x92\x7f\x3f\x70\x49\x88\x3f\xe4\xeb\x3f\x3f\x60\xfb\xa6\xbe\x65\xd7\xb5\xbe\x65\xd7\xb5\xbe\x9c\x43\x51\x3f\x9c\x43\x51\x3f\xa9\x21\x64\xbf\x1f\x2b\x40\x3f\x3a\x6b\xae\x3e\x59\xf0\x8d\xbe\x59\xf0\x8d\xbe\x70\x96\xc6\x3e\x70\x96\xc6\x3e\x47\xd9\xe5\x3e\x3c\x6a\x40\x3f\xf2\xb6\xa4\x3e\x2f\xd4\x4e\xbe\x2f\xd4\x4e\xbe\xc2\x47\x24\xbe\xc2\x47\x24\xbe\xa5\xf2\x06\x3e\x39\xa9\x40\x3f\x4a\x4d\xb1\xbe\xe5\x4c\xe9\xbd\xe5\x4c\xe9\xbd\xe2\x0c\x29\xbf\xe2\x0c\x29\xbf\xab\x49\x2d\xbf\x17\xe8\x40\x3f\x3a\x9e\xa2\xbe\x03\xf3\xeb\xbc\x03\xf3\xeb\xbc\xc1\x62\x75\xbf\xc1\x62\x75\xbf\xa2\x90\x82\x3f\xd6\x26\x41\x3f\xdb\x0b\xb3\x3e\x10\xac\x69\x3d\x10\xac\x69\x3d\x48\x6d\x76\xbf\x48\x6d\x76\xbf\x00\xe4\x86\xbf\x76\x65\x41\x3f\xbc\x26\xa1\x3e\x7d\x53\x18\x3e\x7d\x53\x18\x3e\x60\x91\x2b\xbf\x60\x91\x2b\xbf\xb2\xcf\x43\x3f\xf6\xa3\x41\x3f\x58\x24\xb3\xbe\x8c\x9b\x67\x3e\x8c\x9b\x67\x3e\x6c\x8c\x2e\xbe\x6c\x8c\x2e\xbe\x90\xf2\x75\xbe\x56\xe2\x41\x3f\xdf\xa5\xa0\xbe\x93\xbd\x9c\x3e\x93\xbd\x9c\x3e\x96\xea\xc3\x3e\x96\xea\xc3\x3e\x5e\x79\xb7\xbe\x96\x20\x42\x3f\x25\x73\xb0\x3e\x8c\x90\xc6\x3e\x8c\x90\xc6\x3e\xe3\x50\x51\x3f\xe3\x50\x51\x3f\x6e\x13\x58\x3f\xb6\x5e\x42\x3f\x54\x1d\xa4\x3e\x5d\x89\xe4\x3e\x5d\x89\xe4\x3e\x6c\xa7\x7f\x3f\x6c\xa7\x7f\x3f\x34\x4b\x88\xbf\xb5\x9c\x42\x3f\x6b\xc0\xae\xbe\xec\xc9\x02\x3f\xec\xc9\x02\x3f\x7c\x40\x5e\x3f\x7c\x40\x5e\x3f\x36\xb2\x73\x3f\x93\xda\x42\x3f\xc8\x80\xa9\xbe\x81\x72\x12\x3f\x81\x72\x12\x3f\x9f\x7e\xee\x3e\x9f\x7e\xee\x3e\x53\xdf\x0a\xbf\x50\x18\x43\x3f\x34\xe7\xaf\x3e\x20\xb5\x18\x3f\x20\xb5\x18\x3f\xd0\x71\xaa\xbd\xd0\x71\xaa\xbd\xff\x63\x07\xbd\xee\x55\x43\x3f\x1c\x35\xab\x3e\xec\xc4\x21\x3f\xec\xc4\x21\x3f\xd7\x53\x1b\xbf\xd7\x53\x1b\xbf\x95\xbe\x17\x3f\x68\x93\x43\x3f\xb1\xb8\xad\xbe\x47\xc5\x2b\x3f\x47\xc5\x2b\x3f\x4a\x84\x70\xbf\x4a\x84\x70\xbf\x67\x2a\x76\xbf\xc1\xd0\x43\x3f\x1b\xd8\xab\xbe\xfb\x03\x29\x3f\xfb\x03\x29\x3f\x8b\xc0\x79\xbf\x8b\xc0\x79\xbf\x8e\x62\x83\x3f\xf8\x0d\x44\x3f\x79\xca\xa5\x3e\xe3\x81\x27\x3f\xe3\x81\x27\x3f\x4d\xd2\x33\xbf\x4d\xd2\x33\xbf\x73\x4f\x45\xbf\x0e\x4b\x44\x3f\xba\xd7\xb0\x3e\xfa\x78\x29\x3f\xfa\x78\x29\x3f\x04\xa2\x52\xbe\x04\xa2\x52\xbe\x84\x6a\x8e\x3e\x01\x88\x44\x3f\x78\xe6\x9c\xbe\xbc\x14\x1f\x3f\xbc\x14\x1f\x3f\x95\xda\xb6\x3e\x95\xda\xb6\x3e\x96\xf2\x96\x3e\xd2\xc4\x44\x3f\xf2\xf5\xb8\xbe\x71\x1b\x14\x3f\x71\x1b\x14\x3f\x76\x75\x4e\x3f\x76\x75\x4e\x3f\x60\xb1\x44\xbf\x80\x01\x45\x3f\x27\x1f\x95\x3e\xcd\xfb\x0c\x3f\xcd\xfb\x0c\x3f\x6c\x7b\x7f\x3f\x6c\x7b\x7f\x3f\x54\xc0\x7e\x3f\x0b\x3e\x45\x3f\x25\x95\xc1\x3e\xad\x1f\xf7\x3e\xad\x1f\xf7\x3e\x58\x81\x5e\x3f\x58\x81\x5e\x3f\x60\xf3\x67\xbf\x72\x7a\x45\x3f\x7a\x61\x8d\xbe\x4f\xb8\xd2\x3e\x4f\xb8\xd2\x3e\xb3\xaa\xeb\x3e\xb3\xaa\xeb\x3e\xb8\x20\x08\x3f\xb5\xb6\x45\x3f\xc7\x71\xca\xbe\x60\xf1\xb5\x3e\x60\xf1\xb5\x3e\xcd\x2e\xc8\xbd\xcd\x2e\xc8\xbd\x63\x75\xd3\x3b\xd4\xf2\x45\x3f\x30\x11\x86\x3e\xe2\xbb\x88\x3e\xe2\xbb\x88\x3e\x64\xf7\x1f\xbf\x64\xf7\x1f\xbf\x21\xbc\x08\xbf\xd0\x2e\x46\x3f\x16\x56\xd1\x3e\xb9\xf6\x35\x3e\xb9\xf6\x35\x3e\x64\x27\x73\xbf\x64\x27\x73\xbf\x48\x1d\x61\x3f\xa8\x6a\x46\x3f\x15\x85\x7a\xbe\xf3\x56\xd7\x3d\xf3\x56\xd7\x3d\xc2\x4b\x77\xbf\xc2\x4b\x77\xbf\x9a\xde\x6d\xbf\x5c\xa6\x46\x3f\x0f\x0c\xd5\xbe\xa1\xf2\x1b\x3c\xa1\xf2\x1b\x3c\xb5\xbc\x2a\xbf\xb5\xbc\x2a\xbf\xe2\x04\x2b\x3f\xeb\xe1\x46\x3f\xac\xf1\x5d\x3e\xf3\x34\xaf\xbd\xf3\x34\xaf\xbd\x55\xeb\x18\xbe\x55\xeb\x18\xbe\xc3\x11\x3d\xbe\x54\x1d\x47\x3f\x4b\x6f\xd9\x3e\x3f\x09\x27\xbe\x3f\x09\x27\xbe\x09\xee\xd5\x3e\x09\xee\xd5\x3e\xdf\x95\xb6\xbe\x98\x58\x47\x3f\x15\xad\x38\xbe\xef\x13\x81\xbe\xef\x13\x81\xbe\xe2\x26\x59\x3f\xe2\x26\x59\x3f\xc7\x54\x45\x3f\xb7\x93\x47\x3f\x20\xc6\xe0\xbe\x35\x11\xab\xbe\x35\x11\xab\xbe\x2b\xe1\x7f\x3f\x2b\xe1\x7f\x3f\x08\x8b\x6a\xbf\xaf\xce\x47\x3f\x28\xe2\x12\x3e\x64\xcb\xcd\xbe\x64\xcb\xcd\xbe\x5e\x15\x52\x3f\x5e\x15\x52\x3f\xf6\x47\x3e\x3f\x81\x09\x48\x3f\x10\x34\xe8\x3e\x63\x01\xf4\xbe\x63\x01\xf4\xbe\x2f\x41\xbd\x3e\x2f\x41\xbd\x3e\x39\xe6\x9f\xbe\x2d\x44\x48\x3f\x27\x08\xda\xbd\xe5\xf1\x08\xbf\xe5\xf1\x08\xbf\x97\x8d\x51\xbe\x97\x8d\x51\xbe\x46\xb1\x69\xbe\xb3\x7e\x48\x3f\xe2\xab\xed\xbe\xa7\x44\x13\xbf\xa7\x44\x13\xbf\xec\x1f\x36\xbf\xec\x1f\x36\xbf\x9a\x68\x31\x3f\x12\xb9\x48\x3f\x47\x41\x88\x3d\xbf\x0c\x1f\xbf\xbf\x0c\x1f\xbf\x70\x38\x7b\xbf\x70\x38\x7b\xbf\x34\x6b\x6c\xbf\x48\xf3\x48\x3f\x0e\x92\xf1\x3e\xb1\x77\x26\xbf\xb1\x77\x26\xbf\x1b\x55\x6c\xbf\x1b\x55\x6c\xbf\xbb\x56\x57\x3f\x15\x2e\x49\x3f\xa8\x51\xc8\xbc\xec\x64\x28\xbf\xec\x64\x28\xbf\x92\x21\x0e\xbf\x92\x21\x0e\xbf\x1f\x23\xf2\xbe\x77\x69\x49\x3f\xa7\x07\xf3\xbe\x86\x0e\x2b\xbf\x86\x0e\x2b\xbf\x4e\x57\xa1\x37\x4e\x57\xa1\x37\x30\x8f\x70\xbd\x46\xa6\x49\x3f\x53\xc5\xa7\xbc\xf6\x3b\x29\xbf\xf6\x3b\x29\xbf\x48\x4f\x0e\x3f\x48\x4f\x0e\x3f\x4f\xba\x13\x3f\x84\xe4\x49\x3f\x0a\x67\xf1\x3e\x45\xa8\x21\xbf\x45\xa8\x21\xbf\x33\xa7\x6c\x3f\x33\xa7\x6c\x3f\x08\xcf\x68\xbf\x08\x1e\x4a\x3f\x89\x8d\x8f\x3d\xee\x18\x1b\xbf\xee\x18\x1b\xbf\x75\xe1\x7a\x3f\x75\xe1\x7a\x3f\x71\x86\x71\x3f\xd5\x52\x4a\x3f\x99\xf7\xed\xbe\x14\xd4\x10\xbf\x14\xd4\x10\xbf\x39\xe2\x33\x3f\x39\xe2\x33\x3f\x29\xfa\x29\xbf\xe5\x89\x4a\x3f\x35\x25\xf7\xbd\x26\xc2\x00\xbf\x26\xc2\x00\xbf\x34\x2c\x3e\x3e\x34\x2c\x3e\x3e\x93\xd4\x22\x3e\x38\xc3\x4a\x3f\x92\xc0\xe7\x3e\x46\x94\xe3\xbe\x46\x94\xe3\xbe\x41\x5d\xca\xbe\x41\x5d\xca\xbe\x5e\x41\xd0\x3e\x65\xfc\x4a\x3f\x7b\x98\x2d\x3e\xb6\x58\xc1\xbe\xb6\x58\xc1\xbe\x09\x71\x57\xbf\x09\x71\x57\xbf\xea\x32\x58\xbf\x6b\x35\x4b\x3f\x55\xff\xdb\xbe\x04\xee\x94\xbe\x04\xee\x94\xbe\x15\xe1\x7f\xbf\x15\xe1\x7f\xbf\xb0\x84\x80\x3f\x4a\x6e\x4b\x3f\xeb\xd1\x62\xbe\x7e\x39\x56\xbe\x7e\x39\x56\xbe\x58\x4d\x50\xbf\x58\x4d\x50\xbf\x66\x71\x53\xbf\x02\xa7\x4b\x3f\x58\x4d\xcc\x3e\x89\x7f\x02\xbe\x89\x7f\x02\xbe\x19\xa0\xb1\xbe\x19\xa0\xb1\xbe\xc5\x02\xbb\x3e\x92\xdf\x4b\x3f\x6b\x93\x8d\x3e\xeb\x10\x01\xbd\xeb\x10\x01\xbd\x78\x10\x76\x3e\x78\x10\x76\x3e\x7d\x29\x65\x3e\xf8\x17\x4c\x3f\x4f\x7f\xbb\xbe\xe7\xb7\x79\x3d\xe7\xb7\x79\x3d\x3a\xb0\x3e\x3f\x3a\xb0\x3e\x3f\x5a\x0d\x3d\xbf\x38\x50\x4c\x3f\x91\x66\xa6\xbe\xc6\x4c\x16\x3e\xc6\x4c\x16\x3e\xea\xbe\x7d\x3f\xea\xbe\x7d\x3f\x7c\x7a\x7f\x3f\x50\x88\x4c\x3f\x8e\x77\xa6\x3e\xdb\xf4\x6f\x3e\xdb\xf4\x6f\x3e\xfb\x77\x64\x3f\xfb\x77\x64\x3f\x68\x97\x68\xbf\x40\xc0\x4c\x3f\x87\x34\xbb\x3e\x2c\x44\xa3\x3e\x2c\x44\xa3\x3e\x88\xb2\xf6\x3e\x88\xb2\xf6\x3e\x38\xd0\xff\x3e\x06\xf8\x4c\x3f\x42\x66\x8a\xbe\xc9\x10\xcb\x3e\xc9\x10\xcb\x3e\x31\xb2\xc8\xbd\x31\xb2\xc8\xbd\x3b\xd5\xad\x3d\xa5\x2f\x4d\x3f\x70\x68\xcf\xbe\x22\x11\xee\x3e\x22\x11\xee\x3e\x4a\xde\x24\xbf\x4a\xde\x24\xbf\x2b\x14\x23\xbf\x1c\x67\x4d\x3f\x54\xa7\x55\x3e\xe0\x63\x06\x3f\xe0\x63\x06\x3f\x58\xc7\x76\xbf\x58\xc7\x76\xbf\xe6\x88\x75\x3f\x6a\x9e\x4d\x3f\xcd\x5d\xe1\x3e\x5d\xec\x13\x3f\x5d\xec\x13\x3f\xbe\xbd\x71\xbf\xbe\xbd\x71\xbf\x21\x55\x6f\xbf\x90\xd5\x4d\x3f\x90\x10\x14\xbe\xca\x25\x1e\x3f\xca\x25\x1e\x3f\xe2\x3a\x17\xbf\xe2\x3a\x17\xbf\x8d\x6c\x12\x3f\x8c\x0c\x4e\x3f\xaa\xe9\xec\xbe\xd3\x61\x25\x3f\xd3\x61\x25\x3f\x45\xe1\xdf\xbc\x45\xe1\xdf\xbc\x54\x3a\x4f\xb9\x60\x43\x4e\x3f\xb5\xa8\x97\x3d\x43\xb4\x29\x3f\x43\xb4\x29\x3f\x97\xe9\x0b\x3f\x97\xe9\x0b\x3f\x63\x06\x13\xbf\x08\x7a\x4e\x3f\xa3\x3d\xf2\x3e\x8c\x38\x2a\x3f\x8c\x38\x2a\x3f\x79\x25\x6d\x3f\x79\x25\x6d\x3f\x4a\x88\x71\x3f\x88\xb0\x4e\x3f\x7b\xa9\xf9\x3a\xd0\x43\x28\x3f\xd0\x43\x28\x3f\x06\xc7\x79\x3f\x06\xc7\x79\x3f\xf5\x07\x79\xbf\xdd\xe6\x4e\x3f\x8b\x7c\xf1\xbe\xf8\x58\x23\x3f\xf8\x58\x23\x3f\xdd\xfe\x2c\x3f\xdd\xfe\x2c\x3f\xc7\x77\x26\x3f\x09\x1d\x4f\x3f\x0b\x8b\xa1\xbd\x5b\xf6\x19\x3f\x5b\xf6\x19\x3f\x51\x43\x08\x3e\x51\x43\x08\x3e\x23\x29\xbb\xbd\x0c\x53\x4f\x3f\xcb\x5c\xe8\x3e\xf3\x08\x0e\x3f\xf3\x08\x0e\x3f\xe3\x81\xea\xbe\xe3\x81\xea\xbe\x02\x9b\x00\xbf\xe5\x88\x4f\x3f\x9b\x0c\x22\x3e\x67\x9d\x00\x3f\x67\x9d\x00\x3f\x07\x75\x62\xbf\x07\x75\x62\xbf\x41\x93\x6a\x3f\x92\xbe\x4f\x3f\x6d\x92\xd7\xbe\x50\xaa\xdf\x3e\x50\xaa\xdf\x3e\x95\xea\x7d\xbf\x95\xea\x7d\xbf\x41\x1a\x80\xbf\x12\xf4\x4f\x3f\x0a\x33\x74\xbe\x9a\x82\xb8\x3e\x9a\x82\xb8\x3e\xe5\x5f\x3d\xbf\xe5\x5f\x3d\xbf\xe6\xd5\x39\x3f\x69\x29\x50\x3f\xa8\x1f\xc1\x3e\x2a\x3f\x8f\x3e\x2a\x3f\x8f\x3e\x4e\xd6\x5f\xbe\x4e\xd6\x5f\xbe\xd2\xaf\x44\xbe\x96\x5e\x50\x3f\x7c\x9e\x9f\x3e\x73\x29\x46\x3e\x73\x29\x46\x3e\x52\xed\xc3\x3e\x52\xed\xc3\x3e\x73\x6e\xd0\xbe\x98\x93\x50\x3f\x73\x24\xa4\xbe\x27\xc4\xd3\x3d\x27\xc4\xd3\x3d\xd2\x47\x58\x3f\xd2\x47\x58\x3f\xf7\xeb\x5a\x3f\x70\xc8\x50\x3f\x92\x08\xbf\xbe\xd6\xea\x3f\x3c\xd6\xea\x3f\x3c\x40\x9a\x7f\x3f\x40\x9a\x7f\x3f\xcc\xac\x7d\xbf\x1a\xfd\x50\x3f\x00\xb2\x7e\x3e\x99\xa2\xa9\xbd\x99\xa2\xa9\xbd\xb6\x3b\x49\x3f\xb6\x3b\x49\x3f\xb3\x2e\x44\x3f\x98\x31\x51\x3f\x50\x00\xd8\x3e\xcc\x63\x33\xbe\xcc\x63\x33\xbe\xf0\x96\x91\x3e\xf0\x96\x91\x3e\x22\x2d\x87\xbe\xea\x65\x51\x3f\x5e\xae\x27\xbe\x31\x67\x85\xbe\x31\x67\x85\xbe\xff\x51\xa5\xbe\xff\x51\xa5\xbe\x89\x55\xaa\xbe\x12\x9a\x51\x3f\xc2\x9d\xe9\xbe\x22\x53\xaf\xbe\x22\x53\xaf\xbe\x2d\xc3\x4f\xbf\x2d\xc3\x4f\xbf\x5e\x6a\x4e\x3f\x0c\xce\x51\x3f\x45\x4f\x8f\x3d\x8e\x51\xd8\xbe\x8e\x51\xd8\xbe\x4e\x04\x80\xbf\x4e\x04\x80\xbf\x21\xfe\x7b\xbf\xda\x01\x52\x3f\xc9\xea\xf1\x3e\x86\xc3\xfb\xbe\x86\xc3\xfb\xbe\xea\x4a\x51\xbf\xea\x4a\x51\xbf\xbf\x39\x4d\x3f\x7c\x35\x52\x3f\xd3\x9a\xf0\x3c\x74\x7e\x0b\xbf\x74\x7e\x0b\xbf\x51\x46\xa9\xbe\x51\x46\xa9\xbe\x24\xfb\xa5\xbe\xf0\x68\x52\x3f\x77\xfb\xef\xbe\x3c\xcd\x17\xbf\x3c\xcd\x17\xbf\xaf\x67\x8f\x3e\xaf\x67\x8f\x3e\x32\x78\x8c\xbe\x38\x9c\x52\x3f\x47\xcf\x03\xbe\xb7\xa5\x22\xbf\xb7\xa5\x22\xbf\x3f\x68\x49\x3f\x3f\x68\x49\x3f\x23\x4f\x46\x3f\x53\xcf\x52\x3f\x4c\xc2\xe2\x3e\x4b\x06\x28\xbf\x4b\x06\x28\xbf\xd0\xc6\x7f\x3f\xd0\xc6\x7f\x3f\x7a\xdf\x7d\xbf\x40\x02\x53\x3f\x5c\x92\x62\x3e\xe2\x65\x29\xbf\xe2\x65\x29\xbf\xdb\x19\x56\x3f\xdb\x19\x56\x3f\x40\xf0\x57\x3f\xff\x34\x53\x3f\xb5\xdf\xc7\xbe\xcc\x0c\x2a\xbf\xcc\x0c\x2a\xbf\x53\x7b\xb7\x3e\x53\x7b\xb7\x3e\x75\x0c\xc4\xbe\x91\x67\x53\x3f\x03\xb2\x9c\xbe\xab\xed\x26\xbf\xab\xed\x26\xbf\x68\xbc\x82\xbe\x68\xbc\x82\xbe\x24\x8e\x61\xbe\xf6\x99\x53\x3f\x99\x62\xa0\x3e\xdb\xa7\x1d\xbf\xdb\xa7\x1d\xbf\x45\xe4\x45\xbf\x45\xe4\x45\xbf\x77\xa5\x3d\x3f\x2c\xcc\x53\x3f\xbc\x57\xc3\x3e\xdf\x07\x13\xbf\xdf\x07\x13\xbf\xdf\x82\x7f\xbf\xdf\x82\x7f\xbf\xec\x63\x7b\xbf\x33\xfe\x53\x3f\xb3\xfb\x61\xbe\x6a\xf4\x07\xbf\x6a\xf4\x07\xbf\x95\x13\x58\xbf\x95\x13\x58\xbf\x4d\xe9\x59\x3f\x0c\x30\x54\x3f\xfb\xf7\xdf\xbe\x17\x7c\xed\xbe\x17\x7c\xed\xbe\xf8\x81\xbc\xbe\xf8\x81\xbc\xbe\xc6\xbd\xcb\xbe\xb5\x61\x54\x3f\xc0\x83\xed\x3d\x15\x33\xc4\xbe\x15\x33\xc4\xbe\x33\xe8\x7e\x3e\x33\xe8\x7e\x3e\xb5\xda\x4f\xbe\x30\x93\x54\x3f\xeb\xad\xee\x3e\x78\xf5\x9e\xbe\x78\xf5\x9e\xbe\xb3\x78\x45\x3f\xb3\x78\x45\x3f\x84\xe0\x37\x3f\x7e\xc4\x54\x3f\x99\x72\x20\x39\xbb\xc0\x68\xbe\xbb\xc0\x68\xbe\x62\x88\x7f\x3f\x62\x88\x7f\x3f\xd9\xa1\x72\xbf\x9a\xf5\x54\x3f\x73\xf2\xef\xbe\x1e\x33\x03\xbe\x1e\x33\x03\xbe\xcb\x55\x57\x3f\xcb\x55\x57\x3f\x5c\xac\x4d\x3f\x88\x26\x55\x3f\x1e\xf7\xf1\xbd\x00\x78\x10\xbd\x00\x78\x10\xbd\x03\x2f\xb8\x3e\x03\x2f\xb8\x3e\x64\xf9\xaf\xbe\x44\x57\x55\x3f\xeb\x87\xe2\x3e\x56\x3d\x64\x3d\x56\x3d\x64\x3d\x8d\xae\x85\xbe\x8d\xae\x85\xbe\x93\x56\x7f\xbe\xd2\x87\x55\x3f\xad\xb7\x68\x3e\x07\x7f\x1c\x3e\x07\x7f\x1c\x3e\xf4\x0c\x48\xbf\xf4\x0c\x48\xbf\xa5\xef\x3d\x3f\x2e\xb8\x55\x3f\xd3\x53\xc3\xbe\x4f\x98\x77\x3e\x4f\x98\x77\x3e\xb1\xbc\x7f\xbf\xb1\xbc\x7f\xbf\xb8\xb2\x70\xbf\x5c\xe8\x55\x3f\xd0\x93\xa6\xbe\x13\xfd\xa6\x3e\x13\xfd\xa6\x3e\x18\xef\x53\xbf\x18\xef\x53\xbf\x81\x1a\x44\x3f\x58\x18\x56\x3f\xf8\x2c\x95\x3e\xe4\x14\xd3\x3e\xe4\x14\xd3\x3e\xbb\xbf\xaa\xbe\xbb\xbf\xaa\xbe\x91\xb9\x92\xbe\x22\x48\x56\x3f\x74\xaa\xcf\x3e\xe0\x1b\xf6\x3e\xe0\x1b\xf6\x3e\xc7\x6a\x95\x3e\xc7\x6a\x95\x3e\x31\xf9\x9f\xbe\xbd\x77\x56\x3f\xe6\x4a\x3a\xbe\xee\xaf\x08\x3f\xee\xaf\x08\x3f\x49\xa9\x4d\x3f\x49\xa9\x4d\x3f\xab\x7e\x4c\x3f\x27\xa7\x56\x3f\x19\xeb\xe8\xbe\x12\x25\x17\x3f\x12\x25\x17\x3f\x36\xf3\x7f\x3f\x36\xf3\x7f\x3f\x7d\x92\x7b\xbf\x5f\xd6\x56\x3f\x2a\x8f\x63\x3d\x35\x7d\x22\x3f\x35\x7d\x22\x3f\x10\x84\x4d\x3f\x10\x84\x4d\x3f\x8b\x27\x4a\x3f\x66\x05\x57\x3f\xa5\xe2\xf0\x3e\x41\x26\x27\x3f\x41\x26\x27\x3f\x4d\xd1\x93\x3e\x4d\xd1\x93\x3e\xe2\xa4\x94\xbe\x3a\x34\x57\x3f\x53\xcc\xa0\x3d\x18\x31\x29\x3f\x18\x31\x29\x3f\x97\x31\xae\xbe\x97\x31\xae\xbe\x00\x68\xa6\xbe\xdb\x62\x57\x3f\x22\xbe\xe6\xbe\x93\x6d\x2a\x3f\x93\x6d\x2a\x3f\xd6\xbc\x55\xbf\xd6\xbc\x55\xbf\x6c\x8e\x51\x3f\x4b\x91\x57\x3f\xe5\xe4\x53\xbe\x8f\xce\x26\x3f\x8f\xce\x26\x3f\x7d\x88\x7f\xbf\x7d\x88\x7f\xbf\x87\x54\x7f\xbf\x8a\xbf\x57\x3f\x66\x68\xc8\x3e\xdc\x77\x1d\x3f\xdc\x77\x1d\x3f\x7f\x8e\x43\xbf\x7f\x8e\x43\xbf\xd1\x1e\x4a\x3f\x95\xed\x57\x3f\xc0\x0a\xa5\x3e\x9e\xeb\x12\x3f\x9e\xeb\x12\x3f\x18\xc9\x65\xbe\x18\xc9\x65\xbe\x2e\x9b\x8c\xbe\x6d\x1b\x58\x3f\x63\x58\x99\xbe\x57\xf0\x06\x3f\x57\xf0\x06\x3f\x81\x92\xcf\x3e\x81\x92\xcf\x3e\x79\x92\xb0\xbe\x12\x49\x58\x3f\x94\x79\xd2\xbe\x10\x96\xea\x3e\x10\x96\xea\x3e\xbd\x93\x5f\x3f\xbd\x93\x5f\x3f\x18\x6c\x52\x3f\x83\x76\x58\x3f\x04\x1f\x3a\x3e\xcb\xc0\xc0\x3e\xcb\xc0\xc0\x3e\xac\xa2\x7d\x3f\xac\xa2\x7d\x3f\xb3\xcd\x76\xbf\xc1\xa3\x58\x3f\xd5\xf5\xea\x3e\x32\x96\x99\x3e\x32\x96\x99\x3e\x85\x84\x35\x3f\x85\x84\x35\x3f\xcb\x77\x36\x3f\xcc\xd0\x58\x3f\xd6\xb5\x24\xbd\xb5\xdf\x5c\x3e\xb5\xdf\x5c\x3e\xe7\xf4\x0f\x3e\xe7\xf4\x0f\x3e\x0d\x25\x2e\xbe\xa2\xfd\x58\x3f\x24\x7f\xee\xbe\xdd\x88\xe7\x3d\xdd\x88\xe7\x3d\xd8\x85\xf8\xbe\xd8\x85\xf8\xbe\x8e\x19\xe2\xbe\x42\x2a\x59\x3f\xb6\x4e\xe2\xbd\x05\x2b\x86\x3c\x05\x2b\x86\x3c\x86\x3d\x6a\xbf\x86\x3d\x6a\xbf\xd5\xcd\x5e\x3f\xb0\x56\x59\x3f\x27\x6d\xdd\x3e\x7a\x20\x93\xbd\x7a\x20\x93\xbd\x9c\x12\x79\xbf\x9c\x12\x79\xbf\xbd\x57\x70\xbf\xe8\x82\x59\x3f\x3c\x56\x7e\x3e\xa5\x68\x30\xbe\xa5\x68\x30\xbe\xd4\x6d\x22\xbf\xd4\x6d\x22\xbf\x25\x49\x1e\x3f\xed\xae\x59\x3f\x38\x9b\xb4\xbe\x3c\x33\x89\xbe\x3c\x33\x89\xbe\xff\xe1\x15\xbd\xff\xe1\x15\xbd\x51\xd9\x27\xbd\xbc\xda\x59\x3f\xd5\xe7\xb9\xbe\x4c\x8b\xb1\xbe\x4c\x8b\xb1\xbe\x67\xaf\x13\x3f\x67\xaf\x13\x3f\x5a\xd9\x0d\xbf\x56\x06\x5a\x3f\x6a\xc5\x6e\x3e\xf4\x2e\xdb\xbe\xf4\x2e\xdb\xbe\x5d\x4c\x74\x3f\x5d\x4c\x74\x3f\x3a\x8b\x6b\x3f\xb9\x31\x5a\x3f\x70\x05\xe4\x3e\xb4\x9f\x00\xbf\xb4\x9f\x00\xbf\x06\x85\x70\x3f\x06\x85\x70\x3f\xc0\xa0\x67\xbf\xe7\x5c\x5a\x3f\x51\xf0\xbc\xbd\x4a\x04\x0e\xbf\x4a\x04\x0e\xbf\xea\x92\x09\x3f\xea\x92\x09\x3f\x03\x8e\x03\x3f\xde\x87\x5a\x3f\x2c\xe3\xf3\xbe\x12\x84\x1a\xbf\x12\x84\x1a\xbf\x72\x85\xb2\xbd\x72\x85\xb2\xbd\x17\x18\xba\x3d\x9f\xb2\x5a\x3f\xb4\x2f\x77\xbd\x87\xfc\x24\xbf\x87\xfc\x24\xbf\x6c\x1e\x2d\xbf\x6c\x1e\x2d\xbf\x49\x4f\x28\xbf\x2a\xdd\x5a\x3f\x8e\xa9\xe5\x3e\xe0\x69\x28\xbf\xe0\x69\x28\xbf\xfd\x3a\x7c\xbf\xfd\x3a\x7c\xbf\x7a\x7d\x72\x3f\x7e\x07\x5b\x3f\x06\xc0\x5c\x3e\xe6\x87\x29\xbf\xe6\x87\x29\xbf\x9b\x81\x62\xbf\x9b\x81\x62\xbf\xa7\xae\x55\xbf\x9b\x31\x5b\x3f\x98\x95\xbe\xbe\x8c\xe4\x29\xbf\x8c\xe4\x29\xbf\xcb\x9c\xd4\xbe\xcb\x9c\xd4\xbe\x1f\xa3\xb9\x3e\x81\x5b\x5b\x3f\x9a\xff\xb2\xbe\xb0\x31\x23\xbf\xb0\x31\x23\xbf\x8a\xd6\x69\x3e\x8a\xd6\x69\x3e\xb1\xa7\x8b\x3e\x30\x85\x5b\x3f\x68\x0f\x83\x3e\x2f\x3e\x18\xbf\x2f\x3e\x18\xbf\x72\xe7\x46\x3f\x72\xe7\x46\x3f\x24\x39\x4d\xbf\xa6\xae\x5b\x3f\x0d\x58\xe0\x3e\xf2\xc0\x0d\xbf\xf2\xc0\x0d\xbf\xfd\xf7\x7f\x3f\xfd\xf7\x7f\x3f\xee\xba\x7e\x3f\xe5\xd7\x5b\x3f\x92\xef\xd6\xbd\xf0\x22\xfd\xbe\xf0\x22\xfd\xbe\x30\x63\x4d\x3f\x30\x63\x4d\x3f\xba\x77\x43\xbf\xeb\x00\x5c\x3f\x2d\x43\xf1\xbe\xc3\xcf\xd3\xbe\xc3\xcf\xd3\xbe\x41\x58\x88\x3e\x41\x58\x88\x3e\x28\x36\x4b\x3e\xba\x29\x5c\x3f\x6f\xbe\x86\xbd\xed\xcb\xab\xbe\xed\xcb\xab\xbe\x5c\xed\xc3\xbe\x5c\xed\xc3\xbe\xc0\xd3\xed\x3e\x4e\x52\x5c\x3f\xa5\x40\xe5\x3e\xf4\x6b\x82\xbe\xf4\x6b\x82\xbe\x17\xc6\x5e\xbf\x17\xc6\x5e\xbf\x7e\xc2\x71\xbf\xaa\x7a\x5c\x3f\x4e\xae\x6a\x3e\x7d\x1b\x1f\xbe\x7d\x1b\x1f\xbe\x9f\x29\x7d\xbf\x9f\x29\x7d\xbf\xe1\x85\x84\x3f\xcc\xa2\x5c\x3f\x79\x4a\xbb\xbe\xf4\xb5\x53\xbd\xf4\xb5\x53\xbd\x08\xe3\x2f\xbf\x08\xe3\x2f\xbf\xa8\x1a\x32\xbf\xb6\xca\x5c\x3f\xb4\xeb\xb8\xbe\x28\xa1\x27\x3d\x28\xa1\x27\x3d\xbb\x45\xbc\xbd\xbb\x45\xbc\xbd\x07\x0f\x88\x3d\x66\xf2\x5c\x3f\xa2\xc7\x6a\x3e\xca\xf0\x08\x3e\xca\xf0\x08\x3e\x54\x07\x0b\x3f\x54\x07\x0b\x3f\x1b\xd8\x16\x3f\xdd\x19\x5d\x3f\x63\x18\xe5\x3e\x78\x9c\x71\x3e\x78\x9c\x71\x3e\x7f\x33\x72\x3f\x7f\x33\x72\x3f\xf1\x71\x7f\xbf\x18\x41\x5d\x3f\x47\xd3\x71\xbd\x5c\x04\xa8\x3e\x5c\x04\xa8\x3e\x8f\x83\x71\x3f\x8f\x83\x71\x3f\x47\xba\x7d\x3f\x18\x68\x5d\x3f\xf6\xfb\xf1\xbe\x33\xf0\xce\x3e\x33\xf0\xce\x3e\x01\xf2\x08\x3f\x01\xf2\x08\x3f\x8c\x6d\x13\xbf\xde\x8e\x5d\x3f\x58\x80\xf5\xbd\x1e\x49\xf6\x3e\x1e\x49\xf6\x3e\x40\xf9\xd5\xbd\x40\xf9\xd5\xbd\xeb\x39\x90\xbd\x69\xb5\x5d\x3f\xc2\xa4\xda\x3e\xd0\x2b\x0c\x3f\xd0\x2b\x0c\x3f\x1a\x07\x33\xbf\x1a\x07\x33\xbf\x80\xe5\x2c\x3f\xb9\xdb\x5d\x3f\x7b\xac\x91\x3e\x97\x75\x17\x3f\x97\x75\x17\x3f\x9a\xec\x7d\xbf\x9a\xec\x7d\xbf\x82\x7a\x7c\xbf\xce\x01\x5e\x3f\x83\x2b\xa2\xbe\x6f\xc1\x21\x3f\x6f\xc1\x21\x3f\x6c\xb1\x5a\xbf\x6c\xb1\x5a\xbf\x1f\x35\x60\x3f\xa6\x27\x5e\x3f\xeb\x4d\xd1\xbe\x9c\xca\x29\x3f\x9c\xca\x29\x3f\x64\xa2\xb0\xbe\x64\xa2\xb0\xbe\x26\x5e\xca\xbe\x44\x4d\x5e\x3f\xfa\xc3\x20\x3e\x68\x67\x2a\x3f\x68\x67\x2a\x3f\x43\x57\xa1\x3e\x43\x57\xa1\x3e\x3c\xc6\x7d\xbe\xa4\x72\x5e\x3f\x62\x4d\xf1\x3e\x74\xac\x27\x3f\x74\xac\x27\x3f\xaa\x95\x56\x3f\xaa\x95\x56\x3f\xea\xfa\x46\x3f\xc6\x97\x5e\x3f\xe1\x53\xe7\x3c\xb9\x9d\x24\x3f\xb9\x9d\x24\x3f\x5f\xb4\x7e\x3f\x5f\xb4\x7e\x3f\x58\x54\x77\xbf\xac\xbc\x5e\x3f\x5a\x1e\xeb\xbe\x94\xdc\x1b\x3f\x94\xdc\x1b\x3f\x2c\x21\x37\x3f\x2c\x21\x37\x3f\xbb\x1c\x3c\x3f\x56\xe1\x5e\x3f\x44\x60\x56\xbe\xe0\x2d\x0d\x3f\xe0\x2d\x0d\x3f\x8e\x9f\xf7\x3d\x8e\x9f\xf7\x3d\x5c\x51\x3f\xbe\xc2\x05\x5f\x3f\x41\x3e\xbd\x3e\x83\x10\xfc\x3e\x83\x10\xfc\x3e\x07\x0a\x07\xbf\x07\x0a\x07\xbf\x40\xc5\xde\xbe\xf0\x29\x5f\x3f\x7b\x15\xb8\x3e\x3d\x5e\xda\x3e\x3d\x5e\xda\x3e\xb7\x93\x71\xbf\xb7\x93\x71\xbf\x19\x03\x5b\x3f\xe1\x4d\x5f\x3f\x2d\x9c\x5e\xbe\x0d\x7d\xae\x3e\x0d\x7d\xae\x3e\x29\x4d\x71\xbf\x29\x4d\x71\xbf\x85\x8b\x63\xbf\x94\x71\x5f\x3f\xd7\x5d\xe7\xbe\x1d\x41\x7b\x3e\x1d\x41\x7b\x3e\xae\xfe\x05\xbf\xae\xfe\x05\xbf\x0a\xf2\x05\x3f\x07\x95\x5f\x3f\x56\x8b\xf1\x3c\x7f\xcb\x1b\x3e\x7f\xcb\x1b\x3e\x14\xe1\x03\x3e\x14\xe1\x03\x3e\x15\x0a\x96\x3d\x3c\xb8\x5f\x3f\x21\x12\xed\x3e\xbb\xb4\x6a\x3d\xbb\xb4\x6a\x3d\x88\x65\x39\x3f\x88\x65\x39\x3f\x68\xb6\x20\xbf\x31\xdb\x5f\x3f\x34\xa5\x2a\x3e\x2b\x1a\x39\xbd\x2b\x1a\x39\xbd\xa9\x33\x7f\x3f\xa9\x33\x7f\x3f\x25\xe1\x62\x3f\xe7\xfd\x5f\x3f\x86\x58\xc7\xbe\x9f\x1e\x19\xbe\x9f\x1e\x19\xbe\x6f\xe7\x52\x3f\x6f\xe7\x52\x3f\x9c\xb1\x3a\xbf\x5e\x20\x60\x3f\x03\x79\xad\xbe\xd7\x72\x7b\xbe\xd7\x72\x7b\xbe\x49\x01\x90\x3e\x49\x01\x90\x3e\x29\x20\x69\x3e\x94\x42\x60\x3f\x25\x9f\x7d\x3e\x49\xd4\xa9\xbe\x49\xd4\xa9\xbe\xa3\xca\xc6\xbe\xa3\xca\xc6\xbe\xbf\xf1\xc6\x3e\x8b\x64\x60\x3f\xdc\x56\xe5\x3e\xd1\x55\xd4\xbe\xd1\x55\xd4\xbe\x34\x35\x62\xbf\x34\x35\x62\xbf\x70\x97\x55\xbf\x40\x86\x60\x3f\x0f\xa2\x72\xbd\xa7\x14\xfd\xbe\xa7\x14\xfd\xbe\x06\x0d\x7b\xbf\x06\x0d\x7b\xbf\x0a\x66\x66\x3f\xe1\xa8\x60\x3f\x28\x23\xf0\xbe\x9e\xca\x0e\xbf\x9e\xca\x0e\xbf\x74\x5c\x22\xbf\x74\x5c\x22\xbf\xf4\x64\x0c\xbf\x6d\xcc\x60\x3f\xc4\x27\x17\xbe\xa6\xe6\x19\xbf\xa6\xe6\x19\xbf\x06\x5e\x1b\x38\x06\x5e\x1b\x38\xaa\xb8\x86\xbd\x20\xef\x60\x3f\xe0\xc6\xcd\x3e\x8d\xc6\x22\xbf\x8d\xc6\x22\xbf\x90\x84\x22\x3f\x90\x84\x22\x3f\x8e\x33\x2a\x3f\xfc\x10\x61\x3f\x7d\x13\xa8\x3e\xac\xe8\x29\xbf\xac\xe8\x29\xbf\x63\x2f\x7b\x3f\x63\x2f\x7b\x3f\x24\x4c\x79\xbf\x97\x30\x61\x3f\x47\x2d\x83\xbe\x7f\x9d\x2b\xbf\x7f\x9d\x2b\xbf\x1b\x59\x61\x3f\x1b\x59\x61\x3f\xec\xc1\x58\x3f\xf4\x4d\x61\x3f\xcb\xb7\xe2\xbe\x51\x12\x27\xbf\x51\x12\x27\xbf\x0f\xf9\xc0\x3e\x0f\xf9\xc0\x3e\x3a\xaa\xab\xbe\x9c\x6c\x61\x3f\xf8\xa2\x5d\x3d\xf4\xa8\x20\xbf\xf4\xa8\x20\xbf\x75\x59\x99\xbe\x75\x59\x99\xbe\x50\xf1\xa9\xbe\x91\x8c\x61\x3f\xd6\xec\xf0\x3e\xcb\x66\x18\xbf\xcb\x66\x18\xbf\x65\xc8\x56\xbf\x65\xc8\x56\xbf\x45\x1a\x5a\x3f\x43\xac\x61\x3f\xed\xc5\x24\x3e\x0b\xd1\x09\xbf\x0b\xd1\x09\xbf\x98\x34\x7e\xbf\x98\x34\x7e\xbf\xa5\x58\x7c\xbf\xb3\xcb\x61\x3f\xbd\xad\xcd\xbe\xbf\x68\xee\xbe\xbf\x68\xee\xbe\xcd\x78\x30\xbf\xcd\x78\x30\xbf\x4e\x42\x2b\x3f\xe0\xea\x61\x3f\x3c\x61\xaf\xbe\xd5\x14\xc9\xbe\xd5\x14\xc9\xbe\xf5\x19\x89\xbd\xf5\x19\x89\xbd\x88\x2f\x36\xbd\xcb\x09\x62\x3f\xe4\xd4\x7a\x3e\xcb\xbb\x9d\xbe\xcb\xbb\x9d\xbe\xfa\x46\x16\x3f\xfa\x46\x16\x3f\xe6\xfb\x19\xbf\x72\x28\x62\x3f\xb6\x15\xe8\x3e\x80\x0f\x55\xbe\x80\x0f\x55\xbe\xad\x1f\x78\x3f\xad\x1f\x78\x3f\x16\x77\x78\x3f\xd7\x46\x62\x3f\xa1\xaf\x0b\xbd\x74\xa5\xdf\xbd\x74\xa5\xdf\xbd\xd6\xb2\x66\x3f\xd6\xb2\x66\x3f\x77\x22\x64\xbf\xf8\x64\x62\x3f\x69\xf4\xed\xbe\x22\x09\x3f\xbc\x22\x09\x3f\xbc\xb2\x8b\xd3\x3e\xb2\x8b\xd3\x3e\x67\x96\xcc\x3e\xd5\x82\x62\x3f\x0e\x1e\x3e\xbe\xf7\x32\xc0\x3d\xf7\x32\xc0\x3d\x04\x4e\x89\xbe\x04\x4e\x89\xbe\x5b\x45\x8d\x3e\x6f\xa0\x62\x3f\x08\x7d\xbd\x3e\xb9\xfd\x4a\x3e\xb9\xfd\x4a\x3e\x0d\x1e\x53\xbf\x0d\x1e\x53\xbf\xe8\x5f\x52\xbf\xc6\xbd\x62\x3f\x80\x04\xbc\x3e\xcb\x7c\x94\x3e\xcb\x7c\x94\x3e\x52\xba\x7e\xbf\x52\xba\x7e\xbf\x39\x5d\x7c\x3f\xd8\xda\x62\x3f\x5f\x3a\x44\xbe\x06\x73\xc0\x3e\x06\x73\xc0\x3e\x1a\xb1\x32\xbf\x1a\xb1\x32\xbf\x5e\xd8\x31\xbf\xa7\xf7\x62\x3f\xba\xb8\xed\xbe\x0b\xf3\xeb\x3e\x0b\xf3\xeb\x3e\xc9\x99\x93\xbd\xc9\x99\x93\xbd\x32\x71\xb2\x3d\x31\x14\x63\x3f\xdf\x13\x01\xbd\x4e\x45\x08\x3f\x4e\x45\x08\x3f\x0b\xa5\x16\x3f\x0b\xa5\x16\x3f\x51\x69\x0d\x3f\x78\x30\x63\x3f\x7c\x75\xe5\x3e\x1e\x56\x15\x3f\x1e\x56\x15\x3f\xd7\xab\x78\x3f\xd7\xab\x78\x3f\x2d\x20\x6d\xbf\x79\x4c\x63\x3f\x61\x54\x81\x3e\x25\xd4\x1f\x3f\x25\xd4\x1f\x3f\xf9\xf8\x64\x3f\xf9\xf8\x64\x3f\x59\xa3\x5c\x3f\x35\x68\x63\x3f\xd9\xfe\xa5\xbe\x24\x2b\x28\x3f\x24\x2b\x28\x3f\xd1\x12\xc9\x3e\xd1\x12\xc9\x3e\x5f\x70\xc8\xbe\xac\x83\x63\x3f\xb4\x0c\xd5\xbe\xa7\x30\x2b\x3f\xa7\x30\x2b\x3f\x85\xbb\x97\xbe\x85\xbb\x97\xbe\x21\x10\x86\xbe\xdc\x9e\x63\x3f\x72\x98\xfb\x3d\x72\xb1\x28\x3f\x72\xb1\x28\x3f\x0e\x45\x58\xbf\x0e\x45\x58\xbf\xa3\x81\x49\x3f\xc8\xb9\x63\x3f\xc7\xb6\xf2\x3e\x6c\x65\x23\x3f\x6c\x65\x23\x3f\xa2\x75\x7d\xbf\xa2\x75\x7d\xbf\x5f\x64\x6e\xbf\x6f\xd4\x63\x3f\x0c\xeb\xe7\x3d\xc5\x5b\x1b\x3f\xc5\x5b\x1b\x3f\x71\x4f\x29\xbf\x71\x4f\x29\xbf\x33\xdb\x1e\x3f\xd0\xee\x63\x3f\xcd\xd7\xd2\xbe\xc1\x1b\x0e\x3f\xc1\x1b\x0e\x3f\x75\x9f\x76\xbc\x75\x9f\x76\xbc\x0c\x9c\xf3\xb9\xec\x08\x64\x3f\x00\x06\xa7\xbe\xdb\x39\xf8\x3e\xdb\x39\xf8\x3e\x5a\x93\x23\x3f\x5a\x93\x23\x3f\x23\x40\x21\xbf\xc0\x22\x64\x3f\x2e\xb0\x7d\x3e\x80\xa9\xd1\x3e\x80\xa9\xd1\x3e\xa6\x51\x7c\x3f\xa6\x51\x7c\x3f\xb9\xcf\x75\x3f\x4d\x3c\x64\x3f\xc9\xdd\xe7\x3e\x3f\x14\xa8\x3e\x3f\x14\xa8\x3e\x12\x53\x5b\x3f\x12\x53\x5b\x3f\xff\x62\x52\xbf\x93\x55\x64\x3f\x9d\xe6\x91\xbc\xcd\x92\x6c\x3e\xcd\x92\x6c\x3e\x3b\x69\xa0\x3e\x3b\x69\xa0\x3e\x43\xd6\x8c\x3e\x94\x6e\x64\x3f\xfc\x6d\xe9\xbe\x08\x2d\xff\x3d\x08\x2d\xff\x3d\x1a\xd9\xc3\xbe\x1a\xd9\xc3\xbe\xe9\xcb\xd4\x3e\x4e\x87\x64\x3f\x60\xff\x64\xbe\xba\x36\xbe\x3c\xba\x36\xbe\x3c\x92\xa8\x64\xbf\x92\xa8\x64\xbf\xa5\xf7\x68\xbf\xc0\x9f\x64\x3f\x38\xf8\xac\x3e\x33\x4c\x9b\xbd\x33\x4c\x9b\xbd\xd1\x33\x78\xbf\xd1\x33\x78\xbf\xd1\x19\x76\x3f\xeb\xb7\x64\x3f\xfc\x2a\xd0\x3e\xc9\xe0\x39\xbe\xc9\xe0\x39\xbe\x27\xac\x12\xbf\x27\xac\x12\xbf\xde\x58\x0a\xbf\xcd\xcf\x64\x3f\x0a\x2f\x04\xbe\x3b\x3e\x92\xbe\x3b\x3e\x92\xbe\x5a\x4a\xd5\x3d\x5a\x4a\xd5\x3d\xbb\xba\x17\xbe\x67\xe7\x64\x3f\xd3\xfe\xf1\xbe\xe9\x66\xbf\xbe\xe9\x66\xbf\xbe\xb9\x18\x3b\x3f\xb9\x18\x3b\x3f\x7c\x4e\x44\x3f\xba\xfe\x64\x3f\x23\x88\xf8\xbd\xd0\xf1\xe6\xbe\xd0\xf1\xe6\xbe\x80\xd9\x7f\x3f\x80\xd9\x7f\x3f\x29\x71\x81\xbf\xc4\x15\x65\x3f\xe9\x31\xcf\x3e\xf4\x9a\x06\xbf\xf4\x9a\x06\xbf\xb5\xd7\x46\x3f\xb5\xd7\x46\x3f\x96\xa1\x42\x3f\x87\x2c\x65\x3f\xd6\x40\xb0\x3e\x88\x67\x16\xbf\x88\x67\x16\xbf\xf2\x30\x2f\x3e\xf2\x30\x2f\x3e\x2f\xa9\x0a\xbe\x00\x43\x65\x3f\xba\xfe\x66\xbe\x44\x94\x20\xbf\x44\x94\x20\xbf\xa9\x03\x05\xbf\xa9\x03\x05\xbf\xc7\xdd\x0e\xbf\x30\x59\x65\x3f\x3d\x58\xee\xbe\x5f\x04\x27\xbf\x5f\x04\x27\xbf\x23\x28\x74\xbf\x23\x28\x74\xbf\x97\xf9\x7a\x3f\x17\x6f\x65\x3f\xcb\x63\xa5\xbc\x0d\xc9\x2a\xbf\x0d\xc9\x2a\xbf\x9f\x50\x6a\xbf\x9f\x50\x6a\xbf\x33\x82\x6c\xbf\xb5\x84\x65\x3f\x91\x2c\xe4\x3e\x52\xc2\x29\xbf\x52\xc2\x29\xbf\x31\x10\xd8\xbe\x31\x10\xd8\xbe\xc8\xe2\xd4\x3e\x09\x9a\x65\x3f\xf1\xf0\x88\x3e\x57\x13\x23\xbf\x57\x13\x23\xbf\x29\x46\x90\x3e\x29\x46\x90\x3e\x83\x7e\x96\x3e\x14\xaf\x65\x3f\xa0\x43\x97\xbe\xa9\x1a\x19\xbf\xa9\x1a\x19\xbf\x86\x75\x58\x3f\x86\x75\x58\x3f\x18\xe5\x5a\xbf\xd4\xc3\x65\x3f\x4f\x14\xdf\xbe\x40\x82\x0c\xbf\x40\x82\x0c\xbf\x4d\xb3\x7c\x3f\x4d\xb3\x7c\x3f\x25\x80\x7d\x3f\x4c\xd8\x65\x3f\x4a\xf3\x6c\x3d\xf8\x27\xf6\xbe\xf8\x27\xf6\xbe\x1d\x65\x22\x3f\x1d\x65\x22\x3f\x14\x48\x22\xbf\x78\xec\x65\x3f\x2d\x53\xee\x3e\x02\x2c\xcb\xbe\x02\x2c\xcb\xbe\x38\x65\x18\xbd\x38\x65\x18\xbd\xb2\x65\x09\xbd\x58\x00\x66\x3f\x6f\xa1\x4f\x3e\x6d\x92\x9d\xbe\x6d\x92\x9d\xbe\xb9\xd7\x30\xbf\xb9\xd7\x30\xbf\x36\xf7\x2c\x3f\xef\x13\x66\x3f\x49\x9f\xb2\xbe\x81\xdc\x59\xbe\x81\xdc\x59\xbe\x8a\x30\x7f\xbf\x8a\x30\x7f\xbf\x3d\x3a\x78\xbf\x3a\x27\x66\x3f\x18\x30\xcf\xbe\xaa\x45\xdf\xbd\xaa\x45\xdf\xbd\xe5\xb4\x4c\xbf\xe5\xb4\x4c\xbf\x71\x22\x45\x3f\x3b\x3a\x66\x3f\x3e\xb1\xfe\x3d\xaf\x77\x0d\xba\xaf\x77\x0d\xba\xe6\x53\x4a\xbe\xe6\x53\x4a\xbe\xd1\x5b\x3a\xbe\xf1\x4c\x66\x3f\x6f\x28\xf3\x3e\xb4\x74\xda\x3d\xb4\x74\xda\x3d\xcd\x4a\x01\x3f\xcd\x4a\x01\x3f\x01\x8a\xfc\xbe\x5b\x5f\x66\x3f\x57\x18\x11\x3e\xa8\xdd\x55\x3e\xa8\xdd\x55\x3e\x01\x9a\x73\x3f\x01\x9a\x73\x3f\x9d\x60\x69\x3f\x78\x71\x66\x3f\xe5\x06\xc6\xbe\xca\xe6\x9c\x3e\xca\xe6\x9c\x3e\xda\x03\x6a\x3f\xda\x03\x6a\x3f\xe7\x68\x5c\xbf\x4a\x83\x66\x3f\xc1\xf3\xbb\xbe\x87\xad\xcb\x3e\x87\xad\xcb\x3e\xa8\x31\xd2\x3e\xa8\x31\xd2\x3e\xcb\x99\xbc\x3e\xce\x94\x66\x3f\xea\x09\x30\x3e\x4f\x7e\xf5\x3e\x4f\x7e\xf5\x3e\x0c\x42\x9b\xbe\x0c\x42\x9b\xbe\xae\x7b\xa0\x3e\x07\xa6\x66\x3f\x05\x8f\xf1\x3e\x03\x5f\x0c\x3f\x03\x5f\x0c\x3f\x56\xc5\x5c\xbf\x56\xc5\x5c\xbf\x76\x99\x55\xbf\xf3\xb6\x66\x3f\x44\x9c\xca\x3d\x72\xcb\x19\x3f\x72\xcb\x19\x3f\xe6\xc0\x7a\xbf\xe6\xc0\x7a\xbf\xdf\x06\x6d\x3f\x92\xc7\x66\x3f\x24\x42\xd3\xbe\x5f\x75\x23\x3f\x5f\x75\x23\x3f\xd0\xcf\x17\xbf\xd0\xcf\x17\xbf\xc2\x11\x0a\xbf\xe3\xd7\x66\x3f\x1e\xe0\xad\xbe\x16\x56\x29\x3f\x16\x56\x29\x3f\x5c\x87\xcb\x3d\x5c\x87\xcb\x3d\x49\x8b\x02\xbe\xe8\xe7\x66\x3f\xbf\x03\x56\x3e\xa1\xb3\x2a\x3f\xa1\xb3\x2a\x3f\x1a\xb3\x3d\x3f\x1a\xb3\x3d\x3f\x33\x03\x3b\x3f\xa1\xf7\x66\x3f\x96\x0e\xef\x3e\xf8\x95\x27\x3f\xf8\x95\x27\x3f\x30\xf5\x7f\x3f\x30\xf5\x7f\x3f\xb3\xd7\x74\xbf\x0b\x07\x67\x3f\x97\xbb\x87\x3d\xf0\x66\x1f\x3f\xf0\x66\x1f\x3f\x71\x9c\x3d\x3f\x71\x9c\x3d\x3f\xc2\x97\x2f\x3f\x26\x16\x67\x3f\xab\x6f\xdb\xbe\x67\x47\x13\x3f\x67\x47\x13\x3f\x33\xe2\xc5\x3d\x33\xe2\xc5\x3d\x15\xb1\x6e\xbd\xf3\x24\x67\x3f\xa3\xf3\xa2\xbe\x0e\x57\x04\x3f\x0e\x57\x04\x3f\x13\x2b\x19\xbf\x13\x2b\x19\xbf\xac\x5d\x19\xbf\x71\x33\x67\x3f\x8f\x7a\x6e\x3e\x0a\x1b\xe2\x3e\x0a\x1b\xe2\x3e\x9b\x5d\x7b\xbf\x9b\x5d\x7b\xbf\x95\x03\x71\x3f\xa1\x41\x67\x3f\xf6\x3b\xeb\x3e\xd9\x4e\xb4\x3e\xd9\x4e\xb4\x3e\x17\x4b\x5a\xbf\x17\x4b\x5a\xbf\x65\xed\x49\xbf\x82\x4f\x67\x3f\x11\xc4\x45\x3d\x75\x59\x83\x3e\x75\x59\x83\x3e\xcf\xc6\x8d\xbe\xcf\xc6\x8d\xbe\x35\xd3\x62\x3e\x14\x5d\x67\x3f\x02\x80\xde\xbe\x72\xb4\x1e\x3e\x72\xb4\x1e\x3e\x74\xa2\xe3\x3e\x74\xa2\xe3\x3e\xc2\x26\xec\x3e\x58\x6a\x67\x3f\x3a\xac\x9e\xbe\xc3\xce\x41\x3d\xc3\xce\x41\x3d\x82\xd5\x6e\x3f\x82\xd5\x6e\x3f\xc2\x3a\x66\xbf\x4b\x77\x67\x3f\xa9\x62\x7a\x3e\x2b\xab\x82\xbd\x2b\xab\x82\xbd\x42\x30\x6e\x3f\x42\x30\x6e\x3f\xf4\x98\x5c\x3f\xef\x83\x67\x3f\x61\xe4\xe9\x3e\x63\x69\x2e\xbe\x63\x69\x2e\xbe\x2d\xcb\xdf\x3e\x2d\xcb\xdf\x3e\x89\xbb\xbc\xbe\x44\x90\x67\x3f\x7c\xe7\x2b\x3d\xab\x3a\x8a\xbe\xab\x3a\x8a\xbe\xec\x4b\x93\xbe\xec\x4b\x93\xbe\x0b\xfa\xa2\xbe\x48\x9c\x67\x3f\x3d\x19\xde\xbe\x0b\xfd\xbb\xbe\x0b\xfd\xbb\xbe\x05\x5e\x5c\xbf\x05\x5e\x5c\xbf\xea\x82\x55\x3f\xfc\xa7\x67\x3f\x63\x6d\x9f\xbe\xa4\x2d\xe9\xbe\xa4\x2d\xe9\xbe\x14\x47\x7a\xbf\x14\x47\x7a\xbf\xcc\x64\x67\xbf\x5e\xb3\x67\x3f\xf7\x0d\x78\x3e\xc8\xfd\x06\xbf\xc8\xfd\x06\xbf\x63\x1d\x13\xbf\x63\x1d\x13\xbf\x8a\x1b\xfb\x3e\x70\xbe\x67\x3f\xec\x82\xea\x3e\x0a\xd7\x15\xbf\x0a\xd7\x15\xbf\x91\x22\x0a\x3e\x91\x22\x0a\x3e\x70\x1b\x3e\x3e\x30\xc9\x67\x3f\xcb\x35\x4c\x3d\x29\x8b\x21\xbf\x29\x8b\x21\xbf\xc0\xe3\x45\x3f\xc0\xe3\x45\x3f\xfa\x3a\x43\xbf\xa1\xd3\x67\x3f\x35\x63\xda\xbe\xcc\x96\x28\xbf\xcc\x96\x28\xbf\x1e\x84\x7f\x3f\x1e\x84\x7f\x3f\x83\x1d\x6e\x3f\xc0\xdd\x67\x3f\x63\x1a\xa6\xbe\x98\x2c\x2a\xbf\x98\x2c\x2a\xbf\xb3\x40\x30\x3f\xb3\x40\x30\x3f\x7f\x6b\x18\xbf\x8e\xe7\x67\x3f\xa4\x55\x67\x3e\x4e\x28\x28\xbf\x4e\x28\x28\xbf\xf0\x4e\x12\x3c\xf0\x4e\x12\x3c\xc5\x97\x86\xbd\x09\xf1\x67\x3f\x31\xd3\xee\x3e\x17\x22\x22\xbf\x17\x22\x22\xbf\x31\x11\x2d\xbf\x31\x11\x2d\xbf\x4e\x48\x33\x3f\x32\xfa\x67\x3f\x42\x8e\x90\x3d\xac\x25\x16\xbf\xac\x25\x16\xbf\x70\x48\x7f\xbf\x70\x48\x7f\xbf\xfc\x55\x77\xbf\x0a\x03\x68\x3f\x50\x26\xd6\xbe\x7c\x33\x06\xbf\x7c\x33\x06\xbf\x36\xaa\x47\xbf\x36\xaa\x47\xbf\x66\x42\x37\x3f\x8e\x0b\x68\x3f\x47\x86\xaf\xbe\xf7\xa2\xe7\xbe\xf7\xa2\xe7\xbe\xbe\xad\x0f\xbe\xbe\xad\x0f\xbe\x33\x35\xa1\xbd\xc1\x13\x68\x3f\xbc\x91\x4c\x3e\xe5\xbb\xbb\xbe\xe5\xbb\xbb\xbe\x8f\x6d\x13\x3f\x8f\x6d\x13\x3f\x13\x17\x1b\xbf\xa0\x1b\x68\x3f\x51\x70\xf1\x3e\x17\x51\x89\xbe\x17\x51\x89\xbe\xec\xca\x7a\x3f\xec\xca\x7a\x3f\x4e\x11\x78\x3f\x2c\x23\x68\x3f\x5d\x1d\xd3\x3d\x11\xa8\x26\xbe\x11\xa8\x26\xbe\x6d\xb8\x59\x3f\x6d\xb8\x59\x3f\x24\xda\x4f\xbf\x65\x2a\x68\x3f\x2d\x1c\xcc\xbe\xb8\x11\x5e\xbd\xb8\x11\x5e\xbd\x6d\xd9\x83\x3e\x6d\xd9\x83\x3e\x3c\x98\x5c\x3e\x4a\x31\x68\x3f\xfa\x80\xbb\xbe\xa6\x14\x64\x3d\xa6\x14\x64\x3d\xd5\xf4\xf3\xbe\xd5\xf4\xf3\xbe\x9c\xf0\xff\x3e\xdc\x37\x68\x3f\xc8\x7c\x1f\x3e\x11\x2b\x29\x3e\x11\x2b\x29\x3e\x8a\x43\x73\xbf\x8a\x43\x73\xbf\x58\xf9\x71\xbf\x1b\x3e\x68\x3f\xec\xd9\xf1\x3e\xc9\x98\x8a\x3e\xc9\x98\x8a\x3e\xf6\x3c\x67\xbf\xf6\x3c\x67\xbf\x88\x27\x60\x3f\x05\x44\x68\x3f\xc1\xd9\x1d\x3e\x14\x76\xbc\x3e\x14\x76\xbc\x3e\x36\x36\xb8\xbe\x36\x36\xb8\xbe\xe4\x14\xa7\xbe\x9b\x49\x68\x3f\x75\xb9\xbc\xbe\xdc\x89\xe8\x3e\xdc\x89\xe8\x3e\x33\xcb\xc3\x3e\x33\xcb\xc3\x3e\x5f\xa7\xce\xbe\xdc\x4e\x68\x3f\xa3\x5d\xcc\xbe\xdb\x5c\x07\x3f\xdb\x5c\x07\x3f\xc1\x0d\x6a\x3f\xc1\x0d\x6a\x3f\xba\x12\x6a\x3f\xc8\x53\x68\x3f\xf8\x3a\xcb\x3d\x06\x1d\x17\x3f\x06\x1d\x17\x3f\x78\xe8\x70\x3f\x78\xe8\x70\x3f\x25\xd5\x6c\xbf\x5f\x58\x68\x3f\x70\x2f\xf0\x3e\x68\x57\x22\x3f\x68\x57\x22\x3f\x6d\x9d\xe4\x3e\x6d\x9d\xe4\x3e\x82\x1b\xdc\x3e\xa1\x5c\x68\x3f\x39\x9d\x5a\x3e\x5d\x85\x28\x3f\x5d\x85\x28\x3f\x87\xa8\x97\xbe\x87\xa8\x97\xbe\xe4\xb6\x98\x3e\x8e\x60\x68\x3f\xb1\x76\xa6\xbe\x04\x29\x2a\x3f\x04\x29\x2a\x3f\x5d\xf2\x5f\xbf\x5d\xf2\x5f\xbf\x60\x62\x5b\xbf\x28\x64\x68\x3f\x7c\xbe\xdb\xbe\x63\xcd\x27\x3f\x63\xcd\x27\x3f\x39\x6e\x77\xbf\x39\x6e\x77\xbf\xfd\xd8\x6f\x3f\x69\x67\x68\x3f\x9e\x5a\xe6\x3c\xe8\x7f\x20\x3f\xe8\x7f\x20\x3f\x42\xd8\x04\xbf\x42\xd8\x04\xbf\xe5\x22\xfd\xbe\x52\x6a\x68\x3f\xaf\x9b\xe6\x3e\x40\xdb\x13\x3f\x40\xdb\x13\x3f\xd9\x6c\x60\x3e\xd9\x6c\x60\x3e\x54\xee\x63\xbe\xe6\x6c\x68\x3f\x93\x51\x90\x3e\x00\x59\x03\x3f\x00\x59\x03\x3f\xfe\xc1\x55\x3f\xfe\xc1\x55\x3f\x60\xc8\x4f\x3f\x26\x6f\x68\x3f\x4d\x81\x85\xbe\x00\xf9\xde\x3e\x00\xf9\xde\x3e\x66\x89\x7b\x3f\x66\x89\x7b\x3f\xa6\xed\x70\xbf\x0e\x71\x68\x3f\xe4\xae\xea\xbe\x0a\xc2\xb0\x3e\x0a\xc2\xb0\x3e\x92\xe6\x13\x3f\x92\xe6\x13\x3f\xf7\x94\x09\x3f\xa1\x72\x68\x3f\xc3\x09\x6e\xbd\xe2\xe8\x7a\x3e\xe2\xe8\x7a\x3e\x59\x78\x1c\xbe\x59\x78\x1c\xbe\xed\x1b\x30\x3e\xdb\x73\x68\x3f\xc6\x29\xd7\x3e\x2a\x76\x0b\x3e\x2a\x76\x0b\x3e\xaf\x31\x4c\xbf\xaf\x31\x4c\xbf\x60\x24\x49\xbf\xbe\x74\x68\x3f\x88\x19\xb4\x3e\x88\x69\xc1\x3c\x88\x69\xc1\x3c\xc9\xf3\x7d\xbf\xc9\xf3\x7d\xbf\x0a\x85\x74\x3f\x49\x75\x68\x3f\xc8\x2a\x3a\xbe\x4e\xb3\xb2\xbd\x4e\xb3\xb2\xbd\x36\xe2\x1f\xbf\x36\xe2\x1f\xbf\x7b\x35\x15\xbf\x7c\x75\x68\x3f\xf9\x94\xf2\xbe\xf3\x2b\x49\xbe\xf3\x2b\x49\xbe\x22\x6e\xc8\x3d\x22\x6e\xc8\x3d\xc6\x63\xf7\xbd\x58\x75\x68\x3f\xfe\x81\x18\xbe\xb2\x40\x9b\xbe\xb2\x40\x9b\xbe\xe2\xf3\x43\x3f\xe2\xf3\x43\x3f\xcc\x84\x41\x3f\xdd\x74\x68\x3f\x6b\x2e\xbb\x3e\x99\xe9\xcc\xbe\x99\xe9\xcc\xbe\x13\x5a\x7f\x3f\x13\x5a\x7f\x3f\xb6\xdc\x75\xbf\x09\x74\x68\x3f\xc6\xcf\xd0\x3e\x52\xb1\xf6\xbe\x52\xb1\xf6\xbe\xd0\xfb\x28\x3f\xd0\xfb\x28\x3f\x6c\xb8\x1d\x3f\xdd\x72\x68\x3f\xb1\x1d\xa0\xbd\x4a\x50\x0d\xbf\x4a\x50\x0d\xbf\x23\x2c\x62\xbd\x23\x2c\x62\xbd\x6b\xd7\xa9\x3d\x58\x71\x68\x3f\x7d\x5b\xeb\xbe\xc8\x3e\x1c\xbf\xc8\x3e\x1c\xbf\x53\x46\x3d\xbf\x53\x46\x3d\xbf\x2d\x46\x3d\xbf\x7b\x6f\x68\x3f\x3c\xd1\x80\xbe\x12\xbe\x25\xbf\x12\xbe\x25\xbf\x49\xd8\x7f\xbf\x49\xd8\x7f\xbf\x0c\x24\x7a\x3f\x44\x6d\x68\x3f\x9d\x2e\x8e\x3e\x1d\xb8\x29\xbf\x1d\xb8\x29\xbf\x72\x50\x2f\xbf\x72\x50\x2f\xbf\x8f\xd8\x27\xbf\xb4\x6a\x68\x3f\x25\x4b\xe9\x3e\xfd\xa6\x29\xbf\xfd\xa6\x29\xbf\x35\x26\xc8\x3c\x35\x26\xc8\x3c\x63\x4d\x40\xbd\xca\x67\x68\x3f\xf9\x85\x3e\x3d\xfe\x26\x25\xbf\xfe\x26\x25\xbf\x76\x50\x38\x3f\x76\x50\x38\x3f\x3c\x22\x3b\x3f\x85\x64\x68\x3f\x70\x6f\xd8\xbe\xc6\x28\x1b\xbf\xc6\x28\x1b\xbf\xac\xe6\x7f\x3f\xac\xe6\x7f\x3f\xd5\x2d\x80\xbf\xe8\x60\x68\x3f\x72\x67\xb3\xbe\x07\x02\x0c\xbf\x07\x02\x0c\xbf\x8a\x42\x33\x3f\x8a\x42\x33\x3f\x5a\x58\x32\x3f\xf1\x5c\x68\x3f\x18\x6e\x2c\x3e\x4b\xbb\xf2\xbe\x4b\xbb\xf2\xbe\x9e\x94\xc2\xbb\x9e\x94\xc2\xbb\x24\xd6\x4b\x3c\xa0\x58\x68\x3f\xdd\xb0\xf2\x3e\xdc\x76\xc7\xbe\xdc\x76\xc7\xbe\x58\x90\x35\xbf\x58\x90\x35\xbf\x8b\x73\x37\xbf\xf3\x53\x68\x3f\x11\xee\x31\x3e\xf8\x35\x95\xbe\xf8\x35\x95\xbe\xe4\xed\x7f\xbf\xe4\xed\x7f\xbf\xa2\xa0\x80\x3f\x90\x50\x68\x3f\x7a\xb3\xb0\xbe\x1a\xd8\x3b\xbe\x1a\xd8\x3b\xbe\x10\xe9\x34\xbf\x10\xe9\x34\xbf\xc7\x29\x35\xbf\x77\x4e\x68\x3f\xaa\x6e\xd9\xbe\x4b\x77\x90\xbd\x4b\x77\x90\xbd\x5b\xa7\xbb\xb7\x5b\xa7\xbb\xb7\x7b\x3d\x2f\xb9\xc5\x48\x68\x3f\x5b\xf2\xee\x3c\xda\xf0\x34\x3d\xda\xf0\x34\x3d\xbb\x09\x35\x3f\xbb\x09\x35\x3f\x43\x5b\x33\x3f\x7c\x3f\x68\x3f\x55\xb8\xe5\x3e\xea\x7c\x20\x3e\xea\x7c\x20\x3e\xce\xef\x7f\x3f\xce\xef\x7f\x3f\x73\x1e\x7b\xbf\x23\x37\x68\x3f\xf4\x9d\x9a\x3e\x7f\xa9\x87\x3e\x7f\xa9\x87\x3e\xfa\x5c\x34\x3f\xfa\x5c\x34\x3f\x4d\x15\x2e\x3f\xba\x2f\x68\x3f\x66\xd3\x66\xbe\x36\xa0\xbb\x3e\x36\xa0\xbb\x3e\x1d\x1d\xc7\xbb\x1d\x1d\xc7\xbb\x9f\xbd\x87\x3c\x5c\x28\x68\x3f\xd3\x94\xef\xbe\xd3\x69\xea\x3e\xd3\x69\xea\x3e\xf5\xb6\x36\xbf\xf5\xb6\x36\xbf\x65\xad\x30\xbf\x07\x21\x68\x3f\x53\x5d\x01\xbe\x2c\xd0\x08\x3f\x2c\xd0\x08\x3f\x49\xf5\x7f\xbf\x49\xf5\x7f\xbf\x2a\xf5\x70\x3f\x55\x19\x68\x3f\x97\x0e\xc1\x3e\x25\x02\x18\x3f\x25\x02\x18\x3f\x85\x94\x31\xbf\x85\x94\x31\xbf\x5c\x94\x20\xbf\x44\x11\x68\x3f\xac\x6b\xd0\x3e\xee\x0e\x23\x3f\xee\x0e\x23\x3f\x0c\x9b\xc9\x3c\x0c\x9b\xc9\x3c\xc1\x9e\x66\xbd\xd6\x08\x68\x3f\x8f\x89\x95\xbd\x31\x72\x29\x3f\x31\x72\x29\x3f\x19\x96\x3a\x3f\x19\x96\x3a\x3f\xd5\x53\x32\x3f\x0a\x00\x68\x3f\x9b\x75\xea\xbe\xd2\x7b\x2a\x3f\xd2\x7b\x2a\x3f\x13\xd4\x7f\x3f\x13\xd4\x7f\x3f\x0a\x2a\x69\xbf\xe0\xf6\x67\x3f\x3d\x9b\x8d\xbe\x8c\x47\x26\x3f\x8c\x47\x26\x3f\x42\x66\x2c\x3f\x42\x66\x2c\x3f\xa8\xa7\x12\x3f\x58\xed\x67\x3f\xaa\x50\x80\x3e\x58\x2f\x1d\x3f\x58\x2f\x1d\x3f\xb8\x10\x63\xbd\xb8\x10\x63\xbd\x61\xa1\xe7\x3d\x72\xe3\x67\x3f\xf3\xcb\xee\x3e\x9b\x7e\x0f\x3f\x9b\x7e\x0f\x3f\x20\x68\x40\xbf\x20\x68\x40\xbf\x2b\x01\x3c\xbf\x2f\xd9\x67\x3f\x17\xda\xd1\x3d\xa0\x67\xfa\x3e\xa0\x67\xfa\x3e\xfe\x41\x7f\xbf\xfe\x41\x7f\xbf\x9c\x18\x6a\x3f\x8d\xce\x67\x3f\xda\x81\xc4\xbe\xb3\xb1\xcd\x3e\xb3\xb1\xcd\x3e\x52\xac\x24\xbf\x52\xac\x24\xbf\xd6\xb2\x09\xbf\x8c\xc3\x67\x3f\x0d\xdf\xcc\xbe\x0f\xce\x9b\x3e\x0f\xce\x9b\x3e\x55\x3a\xc9\x3d\x55\x3a\xc9\x3d\xf1\xfe\x34\xbe\x2c\xb8\x67\x3f\x40\xd1\x9f\x3d\xc9\xc1\x4a\x3e\xc9\xc1\x4a\x3e\x1b\xeb\x47\x3f\x1b\xeb\x47\x3f\xac\x62\x4d\x3f\x6e\xac\x67\x3f\xaf\x08\xec\x3e\xb8\x02\xa9\x3d\xb8\x02\xa9\x3d\x10\xf2\x7d\x3f\x10\xf2\x7d\x3f\x49\xaa\x74\xbf\x51\xa0\x67\x3f\x56\xd4\x8c\x3e\xf6\x3c\x14\xbd\xf6\x3c\x14\xbd\x45\x3a\x1a\x3f\x45\x3a\x1a\x3f\x95\xf6\x07\x3f\xd6\x93\x67\x3f\xd6\x6e\x7a\xbe\x61\x98\x19\xbe\x61\x98\x19\xbe\xf2\x82\x1c\xbe\xf2\x82\x1c\xbe\x31\x03\x6a\x3e\xfc\x86\x67\x3f\xc3\x8a\xef\xbe\x39\x0f\x84\xbe\x39\x0f\x84\xbe\x7a\xda\x50\xbf\x7a\xda\x50\xbf\x66\x89\x5e\xbf\xc2\x79\x67\x3f\xa0\xf3\xf0\xbd\x67\xcb\xb9\xbe\x67\xcb\xb9\xbe\x3b\x8d\x7b\xbf\x3b\x8d\x7b\xbf\x01\x7c\x7f\x3f\x29\x6c\x67\x3f\x82\xf7\xc0\x3e\xd1\xd5\xea\xbe\xd1\xd5\xea\xbe\xec\xd4\x0c\xbf\xec\xd4\x0c\xbf\x59\x70\x06\xbf\x30\x5e\x67\x3f\xe9\x3d\xd1\x3e\x24\x0b\x09\xbf\x24\x0b\x09\xbf\x29\x3f\x60\x3e\x29\x3f\x60\x3e\x27\x56\x8b\xbe\xd8\x4f\x67\x3f\xe7\x82\x55\xbd\x9b\xe0\x17\xbf\x9b\xe0\x17\xbf\xcd\xcd\x5a\x3f\xcd\xcd\x5a\x3f\xe0\xae\x69\x3f\x22\x41\x67\x3f\xec\x80\xe7\xbe\xe3\x24\x23\xbf\xe3\x24\x23\xbf\x52\x75\x77\x3f\x52\x75\x77\x3f\x71\xa2\x80\xbf\x0a\x32\x67\x3f\x38\xaf\x9b\xbe\x2a\x04\x2a\xbf\x2a\x04\x2a\xbf\xe6\x1b\xf8\x3e\xe6\x1b\xf8\x3e\x3c\x61\xfa\x3e\x94\x22\x67\x3f\xd7\x83\x5a\x3e\x3a\xdc\x2a\xbf\x3a\xdc\x2a\xbf\x07\xa1\x97\xbe\x07\xa1\x97\xbe\x7e\xd8\xa4\x3e\xbc\x12\x67\x3f\xe1\xec\xf0\x3e\x5c\x6f\x25\xbf\x5c\x6f\x25\xbf\x68\x0d\x65\xbf\x68\x0d\x65\xbf\x78\xea\x6e\xbf\x86\x02\x67\x3f\x4c\x44\x27\x3e\x84\x67\x1b\xbf\x84\x67\x1b\xbf\x1d\xde\x70\xbf\x1d\xde\x70\xbf\x45\x08\x79\x3f\xee\xf1\x66\x3f\x32\xc3\xaf\xbe\x82\x65\x0d\xbf\x82\x65\x0d\xbf\xb4\x3c\xcf\xbe\xb4\x3c\xcf\xbe\xfe\x12\xd7\xbe\xf7\xe0\x66\x3f\x8b\x45\xdf\xbe\x06\x4e\xf5\xbe\x06\x4e\xf5\xbe\xf0\xe7\xc3\x3e\xf0\xe7\xc3\x3e\x29\x7c\xc3\xbe\xa0\xcf\x66\x3f\xe2\xfd\x5c\xbb\x70\xc9\xc6\xbe\x70\xc9\xc6\xbe\xdd\xd2\x6e\x3f\xdd\xd2\x6e\x3f\xbc\x3a\x70\x3f\xe8\xbd\x66\x3f\x88\x90\xdb\x3e\x25\xd3\x91\xbe\x25\xd3\x91\xbe\x7b\x35\x67\x3f\x7b\x35\x67\x3f\x40\xae\x68\xbf\xd0\xab\x66\x3f\xdc\x89\xb3\x3e\xb1\x4c\x32\xbe\xb1\x4c\x32\xbe\xc1\xf3\x9e\x3e\xc1\xf3\x9e\x3e\xa1\xe6\xa1\x3e\x56\x99\x66\x3f\x7a\xb4\x15\xbe\x57\x11\x71\xbd\x57\x11\x71\xbd\xf7\x07\xf4\xbe\xf7\x07\xf4\xbe\x2b\x61\xef\x3e\x7c\x86\x66\x3f\xd2\x1a\xf0\xbe\xc6\x6c\x74\x3d\xc6\x6c\x74\x3d\xd4\x59\x77\xbf\xd4\x59\x77\xbf\x01\x9e\x73\xbf\x41\x73\x66\x3f\xc0\x0d\x6e\xbe\x7e\x7e\x35\x3e\x7e\x7e\x35\x3e\xea\xc4\x59\xbf\xea\xc4\x59\xbf\x70\x1b\x55\x3f\xa6\x5f\x66\x3f\xd7\x91\x8d\x3e\x89\xbc\x93\x3e\x89\xbc\x93\x3e\x73\xb9\x4d\xbe\x73\xb9\x4d\xbe\x86\x0f\x3d\xbe\xa9\x4b\x66\x3f\x38\x20\xec\x3e\x3c\xd6\xc7\x3e\x3c\xd6\xc7\x3e\x14\x62\x13\x3f\x14\x62\x13\x3f\xe4\x49\x15\xbf\x4b\x37\x66\x3f\x38\xc9\xcc\x3d\xe7\xc1\xf5\x3e\xe7\xc1\xf5\x3e\x42\x78\x7d\x3f\x42\x78\x7d\x3f\x69\xbd\x7b\x3f\x8b\x22\x66\x3f\xfa\x23\xc4\xbe\x70\x31\x0e\x3f\x70\x31\x0e\x3f\x12\xa2\x47\x3f\x12\xa2\x47\x3f\x67\x09\x42\xbf\x6a\x0d\x66\x3f\x2c\x0a\xd2\xbe\xb1\xc3\x1c\x3f\xb1\xc3\x1c\x3f\x7a\x3a\x9c\x3d\x7a\x3a\x9c\x3d\x55\x67\x39\x3d\xe6\xf7\x65\x3f\x1c\x58\x34\x3d\xd4\x08\x26\x3f\xd4\x08\x26\x3f\x4c\x10\x2d\xbf\x4c\x10\x2d\xbf\x1a\x2a\x34\x3f\x02\xe2\x65\x3f\xc5\xaa\xe4\x3e\x61\x35\x2a\x3f\x61\x35\x2a\x3f\x77\xf6\x7f\xbf\x77\xf6\x7f\xbf\x55\x57\x81\xbf\xbb\xcb\x65\x3f\xda\xc7\xa6\x3e\xb5\x3b\x29\x3f\xb5\x3b\x29\x3f\x70\x33\x30\xbf\x70\x33\x30\xbf\xe1\xc4\x2c\x3f\x14\xb5\x65\x3f\x55\x09\x38\xbe\x93\xbd\x22\x3f\x93\xbd\x22\x3f\x36\x46\x7d\x3d\x36\x46\x7d\x3d\x90\x8e\xbf\x3d\x0a\x9e\x65\x3f\xd4\xb2\xf0\xbe\x3b\x9e\x16\x3f\x3b\x9e\x16\x3f\x8a\xe5\x45\x3f\x8a\xe5\x45\x3f\x78\x92\x4e\xbf\x9e\x86\x65\x3f\xfe\xdd\x5a\xbe\xed\x75\x05\x3f\xed\x75\x05\x3f\x41\x9f\x7d\x3f\x41\x9f\x7d\x3f\x92\x44\x81\x3f\xcd\x6e\x65\x3f\xb2\xe3\x93\x3e\x3b\x97\xe0\x3e\x3b\x97\xe0\x3e\x52\x08\x13\x3f\x52\x08\x13\x3f\xac\x30\x12\xbf\x9b\x56\x65\x3f\x36\x42\xeb\x3e\xed\x5a\xaf\x3e\xed\x5a\xaf\x3e\x87\x9c\x57\xbe\x87\x9c\x57\xbe\xc9\xb6\x6d\xbe\x08\x3e\x65\x3f\xe3\xf2\xc0\x3d\x51\x69\x6f\x3e\x51\x69\x6f\x3e\x97\x58\x5c\xbf\x97\x58\x5c\xbf\x71\xb3\x63\x3f\x12\x25\x65\x3f\x67\x81\xc2\xbe\x2e\xe9\xef\x3d\x2e\xe9\xef\x3d\x95\x22\x75\xbf\x95\x22\x75\xbf\x4d\x8d\x7b\xbf\xbb\x0b\x65\x3f\x24\xf2\xd3\xbe\x4a\x04\x15\xbb\x4a\x04\x15\xbb\x7d\xe7\xdf\xbe\x7d\xe7\xdf\xbe\x9b\x54\xe7\x3e\x00\xf2\x64\x3f\xb3\xe2\xee\x3c\xe8\x1c\xf9\xbd\xe8\x1c\xf9\xbd\xe5\x3b\xbb\x3e\xe5\x3b\xbb\x3e\xf9\x2b\xbb\x3e\xe0\xd7\x64\x3f\x55\x90\xe2\x3e\x09\x8a\x74\xbe\x09\x8a\x74\xbe\x47\xcc\x6e\x3f\x47\xcc\x6e\x3f\x40\xe6\x72\xbf\x5f\xbd\x64\x3f\x70\x63\xaf\x3e\x15\x44\xb2\xbe\x15\x44\xb2\xbe\xd7\x57\x65\x3f\xd7\x57\x65\x3f\x4f\xed\x6c\x3f\x7a\xa2\x64\x3f\x18\xb3\x1c\xbe\x2e\x60\xe3\xbe\x2e\x60\xe3\xbe\x76\xef\x8d\x3e\x76\xef\x8d\x3e\xd9\xdd\x9e\xbe\x32\x87\x64\x3f\xb9\xc0\xef\xbe\x3a\x87\x06\xbf\x3a\x87\x06\xbf\xbf\xb3\x05\xbf\xbf\xb3\x05\xbf\x8a\x82\x00\xbf\x87\x6b\x64\x3f\x60\x34\x7f\xbe\x3a\x90\x17\xbf\x3a\x90\x17\xbf\x15\x66\x7b\xbf\x15\x66\x7b\xbf\xa9\xdd\x7c\x3f\x78\x4f\x64\x3f\x8d\x6d\x82\x3e\x0a\xa9\x23\xbf\x0a\xa9\x23\xbf\x29\x11\x4d\xbf\x29\x11\x4d\xbf\x38\xff\x54\xbf\x05\x33\x64\x3f\x87\x03\xf0\x3e\x90\x99\x29\xbf\x90\x99\x29\xbf\x7e\x03\xc5\xbd\x7e\x03\xc5\xbd\xb5\x26\x0a\x3e\x30\x16\x64\x3f\xb5\xaa\x15\x3e\x39\xd2\x29\xbf\x39\xd2\x29\xbf\xed\x07\x2c\x3f\xed\x07\x2c\x3f\x79\x46\x26\x3f\xf6\xf8\x63\x3f\x8d\x2a\xae\xbe\xbb\x0d\x25\xbf\xbb\x0d\x25\xbf\x7d\xef\x7f\x3f\x7d\xef\x7f\x3f\x8c\xf7\x80\xbf\x59\xdb\x63\x3f\xe6\x34\xe2\xbe\xef\x58\x1b\xbf\xef\x58\x1b\xbf\xd4\xbb\x2b\x3f\xd4\xbb\x2b\x3f\x56\x2c\x34\x3f\x58\xbd\x63\x3f\xd0\x6f\x30\xbd\xb1\xd8\x0b\xbf\xb1\xd8\x0b\xbf\xad\x22\xcc\xbd\xad\x22\xcc\xbd\xba\x29\x79\x3d\xf2\x9e\x63\x3f\x5d\xdf\xd0\x3e\xf6\xa5\xed\xbe\xf6\xa5\xed\xbe\x14\x0e\x4e\xbf\x14\x0e\x4e\xbf\x4a\x9f\x47\xbf\x29\x80\x63\x3f\xd4\xe0\xc9\x3e\x65\x37\xbc\xbe\x65\x37\xbc\xbe\x4e\xa6\x7a\xbf\x4e\xa6\x7a\xbf\x33\x15\x7a\x3f\xfb\x60\x63\x3f\x03\x18\x83\xbd\x09\x1b\x86\xbe\x09\x1b\x86\xbe\x6b\x7a\x01\xbf\x6b\x7a\x01\xbf\x8c\x38\x06\xbf\x68\x41\x63\x3f\x05\x43\xe5\xbe\xec\xb3\x15\xbe\xec\xb3\x15\xbe\x4b\x2f\x9b\x3e\x4b\x2f\x9b\x3e\xbc\x53\x8b\xbe\x72\x21\x63\x3f\xd3\x65\xa9\xbe\x37\xe7\xba\xbc\x37\xe7\xba\xbc\x71\x54\x69\x3f\x71\x54\x69\x3f\x25\xcc\x60\x3f\x17\x01\x63\x3f\xed\x05\x24\x3e\xc3\xa9\xcf\x3d\xc3\xa9\xcf\x3d\xb4\x04\x6a\x3f\xb4\x04\x6a\x3f\xd6\x9f\x63\xbf\x58\xe0\x62\x3f\x28\xe1\xf0\x3e\x6d\x6e\x60\x3e\x6d\x6e\x60\x3e\x24\x8d\x9d\x3e\x24\x8d\x9d\x3e\xd3\x1a\x9a\x3e\x32\xbf\x62\x3f\x4b\x3c\x81\x3e\x39\xb9\xa8\x3e\x39\xb9\xa8\x3e\x9c\x31\x01\xbf\x9c\x31\x01\xbf\x2a\x22\xfa\x3e\xa9\x9d\x62\x3f\xf7\x3b\x79\xbe\xcf\x55\xdd\x3e\xcf\x55\xdd\x3e\xc6\xf3\x7a\xbf\xc6\xf3\x7a\xbf\x4c\x62\x72\xbf\xbb\x7b\x62\x3f\xb1\x48\xf1\xbe\xc7\x2b\x05\x3f\xc7\x2b\x05\x3f\x04\xb4\x4c\xbf\x04\xb4\x4c\xbf\x1a\x97\x43\x3f\x68\x59\x62\x3f\x3b\x0c\x32\xbe\xca\x70\x16\x3f\xca\x70\x16\x3f\x6a\x74\xa8\xbd\x6a\x74\xa8\xbd\xf8\x16\x7e\xbd\xaf\x36\x62\x3f\x56\x9b\xa3\x3e\x53\x91\x22\x3f\x53\x91\x22\x3f\xc4\xdd\x30\x3f\xc4\xdd\x30\x3f\x6a\x91\x2f\xbf\x92\x13\x62\x3f\xa1\xad\xe8\x3e\x55\xb0\x29\x3f\x55\xb0\x29\x3f\x28\xd4\x7f\x3f\x28\xd4\x7f\x3f\x22\xc8\x78\x3f\x0e\xf0\x61\x3f\x63\xf8\xb5\x3d\x67\x3f\x2b\x3f\x67\x3f\x2b\x3f\x2b\x50\x22\x3f\x2b\x50\x22\x3f\xb1\xc9\x18\xbf\x27\xcc\x61\x3f\x04\x1c\xc1\xbe\xb9\x47\x26\x3f\xb9\x47\x26\x3f\x53\x84\x23\xbe\x53\x84\x23\xbe\xad\xfe\x43\xbe\xdb\xa7\x61\x3f\x9e\xed\xda\xbe\x65\x33\x1b\x3f\x65\x33\x1b\x3f\x89\x83\x58\xbf\x89\x83\x58\xbf\xad\x57\x5c\x3f\x29\x83\x61\x3f\xfd\xc5\xad\xba\x7a\x5e\x0b\x3f\x7a\x5e\x0b\x3f\x26\x88\x75\xbf\x26\x88\x75\xbf\xcc\xc0\x73\xbf\x10\x5e\x61\x3f\xb9\xe2\xd7\x3e\xff\x37\xee\x3e\xff\x37\xee\x3e\x10\xdc\xd7\xbe\x10\xdc\xd7\xbe\x9c\x9c\xc9\x3e\x92\x38\x61\x3f\x4a\x48\xc3\x3e\x97\xda\xbc\x3e\x97\xda\xbc\x3e\xb2\x43\xce\x3e\xb2\x43\xce\x3e\xf9\x3f\xe3\x3e\xae\x12\x61\x3f\x5d\x96\x99\xbd\xeb\x99\x83\x3e\xeb\x99\x83\x3e\x03\x1f\x74\x3f\x03\x1f\x74\x3f\xc7\x4a\x7e\xbf\x64\xec\x60\x3f\x55\xf7\xe6\xbe\xf1\x1a\x0c\x3e\xf1\x1a\x0c\x3e\x39\xb3\x5a\x3f\x39\xb3\x5a\x3f\x33\x33\x60\x3f\xb6\xc5\x60\x3f\xfa\x86\xa9\xbe\x09\x62\x77\x3c\x09\x62\x77\x3c\xc8\x3d\x2f\x3e\xc8\x3d\x2f\x3e\x4a\x68\x27\xbe\xa1\x9e\x60\x3f\xbf\x70\x16\x3e\x97\xbb\xdd\xbd\x97\xbb\xdd\xbd\xe3\x37\x21\xbf\xe3\x37\x21\xbf\xde\xe7\x29\xbf\x26\x77\x60\x3f\x4a\xa0\xed\x3e\x88\xaf\x6c\xbe\x88\xaf\x6c\xbe\xbd\xda\x7f\xbf\xbd\xda\x7f\xbf\x7c\x8c\x85\x3f\x45\x4f\x60\x3f\xd1\x07\x90\x3e\xaa\xe7\xb0\xbe\xaa\xe7\xb0\xbe\x9c\xcb\x2e\xbf\x9c\xcb\x2e\xbf\xe3\x4d\x37\xbf\xfd\x26\x60\x3f\xb6\xcf\x57\xbe\x66\xce\xe3\xbe\x66\xce\xe3\xbe\x82\xd2\xd4\x3d\x82\xd2\xd4\x3d\x94\xc8\xc2\xbd\x4f\xfe\x5f\x3f\xf4\x17\xf3\xbe\x49\x48\x07\xbf\x49\x48\x07\xbf\x99\xc7\x51\x3f\x99\xc7\x51\x3f\xa3\x0f\x56\x3f\x3c\xd5\x5f\x3f\xdc\xe4\x63\xbe\x62\xb5\x18\xbf\x62\xb5\x18\xbf\xe4\x34\x78\x3f\xe4\x34\x78\x3f\xa2\x49\x80\xbf\xc2\xab\x5f\x3f\x2a\xd3\x89\x3e\x73\xf2\x24\xbf\x73\xf2\x24\xbf\x11\xfb\xe5\x3e\x11\xfb\xe5\x3e\x79\xa0\xf7\x3e\xe2\x81\x5f\x3f\xb1\x8b\xf1\x3e\x73\x8e\x2a\xbf\x73\x8e\x2a\xbf\x0e\xea\xc3\xbe\x0e\xea\xc3\xbe\xd8\x10\xb8\x3e\x9a\x57\x5f\x3f\x9b\x8c\x27\x3e\x85\xd4\x29\xbf\x85\xd4\x29\xbf\xd9\x0d\x73\xbf\xd9\x0d\x73\xbf\x36\x23\x72\xbf\xec\x2c\x5f\x3f\x86\x58\xa4\xbe\x5d\xc7\x23\xbf\x5d\xc7\x23\xbf\xa4\x4d\x5b\xbf\xa4\x4d\x5b\xbf\x08\xb6\x5f\x3f\xd6\x01\x5f\x3f\x91\x70\xe9\xbe\x2f\x6b\x18\xbf\x2f\x6b\x18\xbf\x92\x63\x2b\xbe\x92\x63\x2b\xbe\xe8\x00\x4c\xbe\x5c\xd6\x5e\x3f\xff\x5e\xd8\xbd\xf6\x11\x07\xbf\xf6\x11\x07\xbf\xad\x9e\x23\x3f\xad\x9e\x23\x3f\x26\xa9\x1a\xbf\x7b\xaa\x5e\x3f\xd2\xfe\xb5\x3e\xb7\x5b\xe0\xbe\xb7\x5b\xe0\xbe\x2c\xf1\x7f\x3f\x2c\xf1\x7f\x3f\x1f\x5e\x79\x3f\x36\x7e\x5e\x3f\x6b\x4a\xe1\x3e\x6c\x36\xab\xbe\x6c\x36\xab\xbe\xd5\x3f\x29\x3f\xd5\x3f\x29\x3f\xad\x4d\x27\xbf\x86\x51\x5e\x3f\x63\x16\x5f\x3d\x93\x1d\x63\xbe\x93\x1d\x63\xbe\x85\x76\x10\xbe\x85\x76\x10\xbe\xbc\x75\x03\xbe\x6e\x24\x5e\x3f\x5e\x29\xc6\xbe\xe7\x10\xce\xbd\xe7\x10\xce\xbd\x74\x43\x58\xbf\x74\x43\x58\xbf\xea\xfc\x50\x3f\xf0\xf6\x5d\x3f\xba\xa2\xd6\xbe\x3d\x4d\xe4\x3c\x3d\x4d\xe4\x3c\xd7\x79\x74\xbf\xd7\x79\x74\xbf\x81\xb1\x6b\xbf\x0c\xc9\x5d\x3f\x4e\x7f\x1b\xbc\xf7\x51\x1f\x3e\xf7\x51\x1f\x3e\xa4\x14\xc9\xbe\xa4\x14\xc9\xbe\x4a\xf6\xba\x3e\xc2\x9a\x5d\x3f\xcd\xe7\xd4\x3e\x54\xd9\x8c\x3e\x54\xd9\x8c\x3e\x45\xd4\xe4\x3e\x45\xd4\xe4\x3e\xe7\x82\xe9\x3e\x11\x6c\x5d\x3f\x13\x2b\xcc\x3e\x75\x79\xc4\x3e\x75\x79\xc4\x3e\x8d\xac\x78\x3f\x8d\xac\x78\x3f\xb1\xe6\x74\xbf\xf8\x3c\x5d\x3f\x2d\xa1\x26\xbd\xd1\xe0\xf5\x3e\xd1\xe0\xf5\x3e\x7d\x00\x4f\x3f\x7d\x00\x4f\x3f\x3a\x92\x46\x3f\x77\x0d\x5d\x3f\xf5\x51\xde\xbe\x52\xa5\x0f\x3f\x52\xa5\x0f\x3f\x75\x02\x94\x3d\x75\x02\x94\x3d\xda\x32\x1b\xbd\x90\xdd\x5c\x3f\x1a\x69\xbf\xbe\x45\xe2\x1e\x3f\x45\xe2\x1e\x3f\x95\x49\x37\xbf\x95\x49\x37\xbf\x29\x67\x3b\xbf\x40\xad\x5c\x3f\xe1\x05\xa9\x3d\xc6\xf9\x27\x3f\xc6\xf9\x27\x3f\xb0\xc9\x7e\xbf\xb0\xc9\x7e\xbf\xb6\x99\x7b\x3f\x8a\x7c\x5c\x3f\x14\xa2\xe6\x3e\xe4\x01\x2b\x3f\xe4\x01\x2b\x3f\x71\xb8\x10\xbf\x71\xb8\x10\xbf\xc4\x0b\x08\xbf\x6d\x4b\x5c\x3f\xb8\x11\xb0\x3e\x94\xf2\x27\x3f\x94\xf2\x27\x3f\x5d\x71\x89\x3e\x5d\x71\x89\x3e\xef\x61\x9b\xbe\xe8\x19\x5c\x3f\x03\x6d\xee\xbd\x7b\xef\x1e\x3f\x7b\xef\x1e\x3f\x1a\x1e\x69\x3f\x1a\x1e\x69\x3f\x21\x56\x6d\x3f\xfb\xe7\x5b\x3f\x45\x91\xea\xbe\xcb\xe2\x0f\x3f\xcb\xe2\x0f\x3f\x21\xa6\x66\x3f\x21\xa6\x66\x3f\xd4\x84\x64\xbf\xa8\xb5\x5b\x3f\x30\x33\xa5\xbe\xc1\xb4\xf6\x3e\xc1\xb4\xf6\x3e\x26\x1a\x7b\x3e\x26\x1a\x7b\x3e\xe3\x03\x63\x3e\xee\x82\x5b\x3f\x52\x9c\x18\x3e\x60\xf7\xc4\x3e\x60\xf7\xc4\x3e\x94\x42\x16\xbf\x94\x42\x16\xbf\xc6\xef\x1b\x3f\xcc\x4f\x5b\x3f\x82\xfa\xec\x3e\x65\xad\x8b\x3e\x65\xad\x8b\x3e\xe3\x51\x7f\xbf\xe3\x51\x7f\xbf\x3f\xe2\x80\xbf\x44\x1c\x5b\x3f\x99\x86\x9a\x3e\x78\x52\x1a\x3e\x78\x52\x1a\x3e\xa7\x77\x30\xbf\xa7\x77\x30\xbf\x74\xbb\x2f\x3f\x52\xe8\x5a\x3f\x2a\x48\x31\xbe\x6d\xcf\xc0\x3c\x6d\xcf\xc0\x3c\x51\xba\xee\x3d\x51\xba\xee\x3d\xf3\x72\xfd\x3d\xf9\xb3\x5a\x3f\x27\x57\xf1\xbe\x2c\x9c\xd6\xbd\x2c\x9c\xd6\xbd\xe8\xc2\x56\x3f\xe8\xc2\x56\x3f\xfa\xdc\x57\xbf\x38\x7f\x5a\x3f\xae\x7f\x8f\xbe\xe2\x3d\x6b\xbe\xe2\x3d\x6b\xbe\xe4\x44\x74\x3f\xe4\x44\x74\x3f\x26\x8c\x74\x3f\x10\x4a\x5a\x3f\x8e\x0e\x49\x3e\x62\xae\xb1\xbe\x62\xae\xb1\xbe\x4a\x0e\xc1\x3e\x4a\x0e\xc1\x3e\x70\x4d\xc2\xbe\x80\x14\x5a\x3f\xc3\xf4\xf1\x3e\xcc\xc2\xe6\xbe\xcc\xc2\xe6\xbe\x65\x01\xf3\xbe\x65\x01\xf3\xbe\xde\xe0\xef\xbe\x89\xde\x59\x3f\x66\x78\x87\x3e\xbe\x3a\x09\xbf\xbe\x3a\x09\xbf\x9b\x36\x7b\xbf\x9b\x36\x7b\xbf\x9a\xcc\x79\x3f\x52\xaa\x59\x3f\xc6\x09\x5e\xbe\x2c\x5d\x1a\xbf\x2c\x5d\x1a\xbf\xb5\xce\x45\xbf\xb5\xce\x45\xbf\x5d\x72\x46\xbf\xdc\x77\x59\x3f\x13\xeb\xf1\xbe\x3b\xf0\x25\xbf\x3b\xf0\x25\xbf\xe4\x65\x96\x39\xe4\x65\x96\x39\xa3\x50\x54\x3c\xd6\x3e\x59\x3f\xb3\x4b\x7e\xbe\xa3\x12\x2b\xbf\xa3\x12\x2b\xbf\x5e\xf8\x45\x3f\x5e\xf8\x45\x3f\xe8\x6f\x41\x3f\x3e\xff\x58\x3f\xc0\x68\x69\x3e\x81\x77\x29\xbf\x81\x77\x29\xbf\x0f\xef\x7a\x3f\x0f\xef\x7a\x3f\xe2\x3e\x78\xbf\x2d\xc4\x58\x3f\x6a\xa7\xf2\x3e\x20\x7e\x21\xbf\x20\x7e\x21\xbf\x40\xaa\xef\x3e\x40\xaa\xef\x3e\xdb\x74\xf2\x3e\xa0\x8d\x58\x3f\xac\x57\x72\x3e\xf4\xf0\x13\xbf\xf4\xf0\x13\xbf\xd2\xc8\xc6\xbe\xd2\xc8\xc6\xbe\x3c\x03\xbc\x3e\xca\x55\x58\x3f\x41\xce\x72\xbe\x99\xaa\x00\xbf\x99\xaa\x00\xbf\x15\x98\x75\xbf\x15\x98\x75\xbf\x1b\xb1\x6e\xbf\xa8\x1c\x58\x3f\xb4\xf2\xf1\xbe\x3d\xf0\xcf\xbe\x3d\xf0\xcf\xbe\x0a\xd0\x52\xbf\x0a\xd0\x52\xbf\x9a\xf4\x4d\x3f\x1c\xe3\x57\x3f\xb4\x8d\x6d\xbe\xe5\xa7\x96\xbe\xe5\xa7\x96\xbe\x04\x54\xa2\xbd\x04\x54\xa2\xbd\x7b\xa8\xa2\xbd\x25\xa9\x57\x3f\x34\xbd\x79\x3e\x46\xac\x30\xbe\x46\xac\x30\xbe\xfa\x65\x39\x3f\xfa\x65\x39\x3f\x83\xcc\x33\xbf\xc2\x6e\x57\x3f\x61\x3c\xf2\x3e\xac\x6a\x38\xbd\xac\x6a\x38\xbd\x0b\xda\x7d\x3f\x0b\xda\x7d\x3f\x35\xc8\x74\x3f\xf3\x33\x57\x3f\x97\x3b\x6a\x3e\xc0\x77\xaf\x3d\xc0\x77\xaf\x3d\x6f\xec\x05\x3f\x6f\xec\x05\x3f\x22\xff\xfa\xbe\xba\xf8\x56\x3f\x1f\x7f\x7c\xbe\xdb\xf9\x5b\x3e\xdb\xf9\x5b\x3e\x42\x50\xab\xbe\x42\x50\xab\xbe\xb2\x51\xb2\xbe\x15\xbd\x56\x3f\x43\xee\xf2\xbe\x7d\x4d\xab\x3e\x7d\x4d\xab\x3e\xe6\x9a\x71\xbf\xe6\x9a\x71\xbf\x82\x09\x6e\x3f\x05\x81\x56\x3f\x76\x6c\x68\xbe\x89\x60\xe1\x3e\x89\x60\xe1\x3e\x06\x7a\x59\xbf\x06\x7a\x59\xbf\xac\x64\x50\xbf\x8a\x44\x56\x3f\xa8\x2c\x7b\x3e\x8a\x81\x07\x3f\x8a\x81\x07\x3f\x04\x37\xf7\xbd\x04\x37\xf7\xbd\x82\xb6\xa9\x3d\xa4\x07\x56\x3f\x24\x93\xf2\x3e\x8c\x6f\x19\x3f\x8c\x6f\x19\x3f\x87\xe5\x32\x3f\x87\xe5\x32\x3f\xfc\x86\x37\x3f\x52\xca\x55\x3f\xb3\x50\x6b\x3e\xa3\x86\x25\x3f\xa3\x86\x25\x3f\x52\xc5\x7e\x3f\x52\xc5\x7e\x3f\xc5\x78\x7b\xbf\x96\x8c\x55\x3f\xe3\xca\x75\xbe\xad\xe9\x2a\x3f\xad\xe9\x2a\x3f\x2e\x7e\x0b\x3f\x2e\x7e\x0b\x3f\x38\x20\x02\x3f\x70\x4e\x55\x3f\x30\x5a\xf1\xbe\x04\x7b\x29\x3f\x04\x7b\x29\x3f\x4a\x61\xa1\xbe\x4a\x61\xa1\xbe\xfe\xa0\xb5\x3e\xde\x0f\x55\x3f\x2e\xff\x74\xbe\x6d\xb6\x21\x3f\x6d\xb6\x21\x3f\xf4\x3a\x70\xbf\xf4\x3a\x70\xbf\x46\xda\x75\xbf\xe0\xd0\x54\x3f\xbd\x84\x6c\x3e\x31\xd4\x13\x3f\x31\xd4\x13\x3f\x9a\xb5\x5a\xbf\x9a\xb5\x5a\xbf\xc8\x79\x59\x3f\x78\x91\x54\x3f\xea\xc4\xf1\x3e\xea\x02\x00\x3f\xea\x02\x00\x3f\x03\x0c\x00\xbe\x03\x0c\x00\xbe\x18\xde\xc6\xbd\xa6\x51\x54\x3f\x5d\xe4\x7f\x3e\x68\xe6\xcd\x3e\x68\xe6\xcd\x3e\x52\xff\x32\x3f\x52\xff\x32\x3f\xf6\x2e\x3d\xbf\x69\x11\x54\x3f\x85\x4b\x5e\xbe\x82\x99\x93\x3e\x82\x99\x93\x3e\x65\x87\x7e\x3f\x65\x87\x7e\x3f\x60\x17\x84\x3f\xc2\xd0\x53\x3f\x99\xd9\xf2\xbe\x30\xf2\x27\x3e\x30\xf2\x27\x3e\xb4\xf9\x08\x3f\xb4\xf9\x08\x3f\xac\x97\x0e\xbf\xb0\x8f\x53\x3f\x57\xf9\x86\xbe\xcc\x9b\x08\x3d\xcc\x9b\x08\x3d\x51\x8c\xa9\xbe\x51\x8c\xa9\xbe\x35\x21\xab\xbe\x34\x4e\x53\x3f\x6c\x19\x50\x3e\xc5\xcf\xcb\xbd\xc5\xcf\xcb\xbd\xc0\x29\x72\xbf\xc0\x29\x72\xbf\x3d\x09\x79\x3f\x4c\x0c\x53\x3f\x48\xd5\xf0\x3e\xff\x25\x6a\xbe\xff\x25\x6a\xbe\xe1\x02\x57\xbf\xe1\x02\x57\xbf\xc9\x53\x60\xbf\xf8\xc9\x52\x3f\x37\x5f\x90\x3e\xfc\x6a\xb2\xbe\xfc\x6a\xb2\xbe\x2d\xcc\xbc\xbd\x2d\xcc\xbc\xbd\x1c\x6c\xf0\x3d\x3c\x87\x52\x3f\x5c\xdc\x3b\xbe\xb9\x87\xe8\xbe\xb9\x87\xe8\xbe\x8b\x03\x3a\x3f\x8b\x03\x3a\x3f\x5c\x3c\x3a\x3f\x15\x44\x52\x3f\x79\x82\xef\xbe\x2a\xc8\x0a\xbf\x2a\xc8\x0a\xbf\x97\x39\x7d\x3f\x97\x39\x7d\x3f\x2a\x10\x82\xbf\x84\x00\x52\x3f\x07\x3b\x99\xbe\x68\x01\x1c\xbf\x68\x01\x1c\xbf\xd5\x40\xfc\x3e\xd5\x40\xfc\x3e\x35\x0f\x08\x3f\x87\xbc\x51\x3f\xa4\x0f\x1f\x3e\x7c\xfe\x26\xbf\x7c\xfe\x26\xbf\x06\xfa\xc3\xbe\x06\xfa\xc3\xbe\x6f\x52\xb4\x3e\x21\x78\x51\x3f\xa4\x8b\xed\x3e\x15\x2c\x2b\xbf\x15\x2c\x2b\xbf\x2b\xc8\x76\xbf\x2b\xc8\x76\xbf\x83\x30\x75\xbf\x52\x33\x51\x3f\x57\x35\xa5\x3e\xcf\x6a\x28\xbf\xcf\x6a\x28\xbf\xeb\x63\x4d\xbf\xeb\x63\x4d\xbf\x2c\x82\x53\x3f\x17\xee\x50\x3f\x61\x17\x03\xbe\x1e\xf1\x1e\xbf\x1e\xf1\x1e\xbf\x6b\x86\xac\xbc\x6b\x86\xac\xbc\x41\x8f\x8b\xbd\x72\xa8\x50\x3f\x69\x55\xe8\xbe\xde\x40\x0f\xbf\xde\x40\x0f\xbf\xeb\xe2\x46\x3f\xeb\xe2\x46\x3f\xf3\x83\x39\xbf\x63\x62\x50\x3f\x7e\x99\xb2\xbe\x1e\x81\xf3\xbe\x1e\x81\xf3\xbe\x93\x3d\x79\x3f\x93\x3d\x79\x3f\xd0\x59\x70\x3f\xeb\x1b\x50\x3f\xb8\x9d\xc0\x3d\x01\x53\xbe\xbe\x01\x53\xbe\xbe\xe4\x8a\xd4\x3e\xe4\x8a\xd4\x3e\x21\xfd\xd3\xbe\x08\xd5\x4f\x3f\x0c\x0c\xe4\x3e\xe0\x46\x81\xbe\xe0\x46\x81\xbe\x8b\xb9\xee\xbe\x8b\xb9\xee\xbe\xab\x96\xde\xbe\xbc\x8d\x4f\x3f\x12\xbb\xbd\x3e\xff\x7b\xfc\xbd\xff\x7b\xfc\xbd\x37\x3c\x7c\xbf\x37\x3c\x7c\xbf\xbe\xec\x70\x3f\x04\x46\x4f\x3f\x7a\xab\x5c\xbd\x08\x83\x29\x3c\x08\x83\x29\x3c\x8c\x90\x3c\xbf\x8c\x90\x3c\xbf\xee\x07\x35\xbf\xe3\xfd\x4e\x3f\x20\xbe\xdc\xbe\x1d\x3a\x13\x3e\x1d\x3a\x13\x3e\x4f\xd0\xb2\x3d\x4f\xd0\xb2\x3d\x96\xc1\xad\xbd\x58\xb5\x4e\x3f\x26\xa4\xca\xbe\x42\x53\x8b\x3e\x42\x53\x8b\x3e\x7a\xe3\x57\x3f\x7a\xe3\x57\x3f\x72\x07\x50\x3f\x64\x6c\x4e\x3f\x70\x6f\x6d\x3c\x84\x8a\xc7\x3e\x84\x8a\xc7\x3e\x45\x74\x70\x3f\x45\x74\x70\x3f\x94\x72\x66\xbf\x06\x23\x4e\x3f\xee\xba\xd0\x3e\x21\x83\xfb\x3e\x21\x83\xfb\x3e\xbb\xe8\x98\x3e\xbb\xe8\x98\x3e\xb0\xae\x8b\x3e\x3c\xd9\x4d\x3f\x53\x9f\xd6\x3e\xd1\x75\x12\x3f\xd1\x75\x12\x3f\x9c\xad\x13\xbf\x9c\xad\x13\xbf\xf6\xda\x13\x3f\x0a\x8f\x4d\x3f\x83\xa0\x07\x3d\x9e\x35\x21\x3f\x9e\x35\x21\x3f\xa9\xc4\x7f\xbf\xa9\xc4\x7f\xbf\x74\x88\x79\xbf\x6f\x44\x4d\x3f\x15\x73\xc3\xbe\x95\x7e\x29\x3f\x95\x7e\x29\x3f\xe2\x69\x22\xbf\xe2\x69\x22\xbf\x05\xfe\x17\x3f\x6a\xf9\x4c\x3f\x41\x0f\xe0\xbe\xb4\xcb\x2a\x3f\xb4\xcb\x2a\x3f\x63\xb0\x6c\x3e\x63\xb0\x6c\x3e\x73\x69\x8c\x3e\xfa\xad\x4c\x3f\x3f\x5d\xb1\xbd\xbd\xfe\x24\x3f\xbd\xfe\x24\x3f\x7a\x27\x6a\x3f\x7a\x27\x6a\x3f\xdf\xc7\x71\xbf\x21\x62\x4c\x3f\x3d\x5b\xb2\x3e\x3e\x44\x18\x3f\x3e\x44\x18\x3f\xc1\xe5\x5f\x3f\xc1\xe5\x5f\x3f\x79\x55\x61\x3f\xde\x15\x4c\x3f\x5a\xa4\xe9\x3e\x18\x41\x05\x3f\x18\x41\x05\x3f\x28\x68\x10\x3e\x28\x68\x10\x3e\x70\xf6\xfc\xbd\x32\xc9\x4b\x3f\xa9\xfa\x0e\x3e\xb5\x98\xd9\x3e\xb5\x98\xd9\x3e\xcc\x7d\x34\xbf\xcc\x7d\x34\xbf\xc1\x77\x3b\xbf\x1c\x7c\x4b\x3f\x18\x47\x9d\xbe\x02\x93\x9f\x3e\x02\x93\x9f\x3e\x79\xa7\x7d\xbf\x79\xa7\x7d\xbf\xb9\x66\x81\x3f\x9e\x2e\x4b\x3f\x81\x70\xf0\xbe\x23\xe8\x3d\x3e\x23\xe8\x3d\x3e\xc0\x93\xf9\xbe\xc0\x93\xf9\xbe\x39\x42\xfb\xbe\xb6\xe0\x4a\x3f\x4c\xbc\x46\xbe\x0d\x90\x50\x3d\x0d\x90\x50\x3d\xd6\x6b\xcf\x3e\xd6\x6b\xcf\x3e\xa1\xcc\xd5\xbe\x64\x92\x4a\x3f\xa1\xd4\x84\x3e\x2a\xb0\xb0\xbd\x2a\xb0\xb0\xbd\x77\x74\x79\x3f\x77\x74\x79\x3f\x5c\xba\x7e\x3f\xa9\x43\x4a\x3f\xfc\x8c\xf2\x3e\x33\xc4\x60\xbe\x33\xc4\x60\xbe\x9a\xa0\x43\x3f\x9a\xa0\x43\x3f\xe1\x9f\x48\xbf\x84\xf4\x49\x3f\x3c\xb7\x7f\x3e\xb1\xde\xaf\xbe\xb1\xde\xaf\xbe\xc8\xb0\x70\xbd\xc8\xb0\x70\xbd\x79\xae\x4d\xbd\xf8\xa4\x49\x3f\x87\x76\x50\xbe\x79\xe0\xe7\xbe\x79\xe0\xe7\xbe\x5e\xc1\x55\xbf\x5e\xc1\x55\xbf\x7c\xdb\x58\x3f\x02\x55\x49\x3f\xa3\xd8\xef\xbe\xb0\x3e\x0b\xbf\xb0\x3e\x0b\xbf\x75\xb4\x70\xbf\x75\xb4\x70\xbf\xdb\xea\x79\xbf\xa2\x04\x49\x3f\x2d\x49\x9c\xbe\x2e\xd0\x1c\xbf\x2e\xd0\x1c\xbf\xac\xab\x93\xbe\xac\xab\x93\xbe\x44\x69\xac\x3e\xda\xb3\x48\x3f\x4c\xc3\x0e\x3e\xf8\x84\x27\xbf\xf8\x84\x27\xbf\xd1\xa8\x18\x3f\xd1\xa8\x18\x3f\x51\x93\x0f\x3f\xa9\x62\x48\x3f\xd1\xec\xe8\x3e\xc4\x18\x2b\xbf\xc4\x18\x2b\xbf\xfd\xf5\x7f\x3f\xfd\xf5\x7f\x3f\x66\xfe\x7f\xbf\x0f\x11\x48\x3f\xb7\x3a\xb6\x3e\x48\x72\x27\xbf\x48\x72\x27\xbf\x90\x4b\x18\x3f\x90\x4b\x18\x3f\x79\x7c\x21\x3f\x0c\xbf\x47\x3f\x94\x07\x8a\xbd\xe5\xd6\x1c\xbf\xe5\xd6\x1c\xbf\xed\x7e\x95\xbe\xed\x7e\x95\xbe\x85\x52\x7d\x3e\xa0\x6c\x47\x3f\x84\xaf\xdc\xbe\x62\x9c\x0b\xbf\x62\x9c\x0b\xbf\x38\x42\x71\xbf\x38\x42\x71\xbf\x09\x9a\x6c\xbf\xcb\x19\x47\x3f\x36\xfe\xcc\xbe\x8d\x5a\xe8\xbe\x8d\x5a\xe8\xbe\x69\xe4\x53\xbf\x69\xe4\x53\xbf\xc8\xcd\x59\x3f\x8d\xc6\x46\x3f\x3b\x9a\xfa\xbb\x2e\x77\xaf\xbe\x2e\x77\xaf\xbe\xe8\x37\x22\xbd\xe8\x37\x22\xbd\xfc\x76\xb1\xbd\xe7\x72\x46\x3f\xf5\x3d\xc8\x3e\xf4\x48\x5e\xbe\xf4\x48\x5e\xbe\xb8\x06\x48\x3f\xb8\x06\x48\x3f\x08\xac\x3e\xbf\xd8\x1e\x46\x3f\x4f\x93\xdf\x3e\x8c\x5a\xa8\xbd\x8c\x5a\xa8\xbd\xc7\x20\x77\x3f\xc7\x20\x77\x3f\x19\xaa\x76\x3f\x62\xca\x45\x3f\x17\x8b\xb3\x3d\xc2\x81\x65\x3d\xc2\x81\x65\x3d\x7c\x7c\xb8\x3e\x7c\x7c\xb8\x3e\xee\xbf\xc8\xbe\x82\x75\x45\x3f\x0f\x33\xad\xbe\x1f\x25\x45\x3e\x1f\x25\x45\x3e\x81\x56\x0a\xbf\x81\x56\x0a\xbf\x9b\x48\xfd\xbe\x39\x20\x45\x3f\xc7\xd9\xeb\xbe\x8f\x76\xa4\x3e\x8f\x76\xa4\x3e\xff\xaa\x7f\xbf\xff\xaa\x7f\xbf\x8b\xcc\x75\x3f\x89\xca\x44\x3f\x37\xdc\x2f\xbe\xb2\x10\xdf\x3e\xb2\x10\xdf\x3e\xe8\x0b\x23\xbf\xe8\x0b\x23\xbf\x86\x1c\x1e\xbf\x72\x74\x44\x3f\x4c\xe3\x8b\x3e\xe2\xeb\x07\x3f\xe2\xeb\x07\x3f\x27\x2c\x7f\x3e\x27\x2c\x7f\x3e\x75\x96\x7b\xbe\xf0\x1d\x44\x3f\x9b\x86\xf2\x3e\x1a\x5d\x1a\x3f\x1a\x5d\x1a\x3f\xe6\x2a\x6e\x3f\xe6\x2a\x6e\x3f\xaa\x28\x68\x3f\x06\xc7\x43\x3f\x02\x69\x80\x3e\x30\x51\x26\x3f\x30\x51\x26\x3f\x38\x11\x58\x3f\x38\x11\x58\x3f\xda\xac\x4f\xbf\xb4\x6f\x43\x3f\x99\xa5\x48\xbe\xbf\x3a\x2b\x3f\xbf\x3a\x2b\x3f\x19\x44\x77\x3d\x19\x44\x77\x3d\xb7\xd4\x16\x3d\xfa\x17\x43\x3f\xb1\x68\xf0\xbe\xb3\x70\x28\x3f\xb3\x70\x28\x3f\x52\xef\x45\xbf\x52\xef\x45\xbf\xb3\x28\x45\x3f\xda\xbf\x42\x3f\x2c\x66\xa5\xbe\x49\x18\x1e\x3f\x49\x18\x1e\x3f\x75\x5b\x77\xbf\x75\x5b\x77\xbf\x57\x5a\x6f\xbf\x52\x67\x42\x3f\xb3\xcf\xdf\x3d\x9d\xd4\x0c\x3f\x9d\xd4\x0c\x3f\x1a\x34\xb7\xbe\x1a\x34\xb7\xbe\xc9\xb1\xa2\x3e\x62\x0e\x42\x3f\xbf\xc4\xe2\x3e\x27\x1f\xeb\x3e\x27\x1f\xeb\x3e\x56\x48\x0c\x3f\x56\x48\x0c\x3f\xc0\xa3\x11\x3f\x09\xb5\x41\x3f\x57\x57\xc5\x3e\x81\x8f\xb2\x3e\x81\x8f\xb2\x3e\x3a\x8f\x7f\x3f\x3a\x8f\x7f\x3f\x70\x40\x7c\xbf\x49\x5b\x41\x3f\xf4\x3d\x3f\xbc\xb1\x42\x63\x3e\xb1\x42\x63\x3e\x33\xf4\x1d\x3f\x33\xf4\x1d\x3f\x27\x66\x14\x3f\x22\x01\x41\x3f\xba\x31\xcb\xbe\x49\x57\xad\x3d\x49\x57\xad\x3d\x1d\x2b\x8f\xbe\x1d\x2b\x8f\xbe\xc1\x8c\xa2\x3e\x93\xa6\x40\x3f\xda\x50\xde\xbe\x1d\x05\x66\xbd\x1d\x05\x66\xbd\x73\x82\x71\xbf\x73\x82\x71\xbf\x6e\xa0\x76\xbf\x9c\x4b\x40\x3f\x45\xb4\xbb\xbd\x0b\xd5\x46\xbe\x0b\xd5\x46\xbe\xa4\x5a\x51\xbf\xa4\x5a\x51\xbf\xde\x55\x51\x3f\x3f\xf0\x3f\x3f\xc3\x00\xaa\x3e\xff\xa6\xa5\xbe\xff\xa6\xa5\xbe\x54\x30\xc5\xbb\x54\x30\xc5\xbb\xfe\x4d\xbf\x3b\x7b\x94\x3f\x3f\x72\x97\xee\x3e\xde\xef\xe0\xbe\xde\xef\xe0\xbe\x2b\xc5\x4f\x3f\x2b\xc5\x4f\x3f\x25\xe6\x53\xbf\x50\x38\x3f\x3f\x4d\x53\x45\x3e\x67\x25\x09\xbf\x67\x25\x09\xbf\x1b\x6c\x72\x3f\x1b\x6c\x72\x3f\x56\xac\x76\x3f\xbe\xdb\x3e\x3f\x39\x65\x7f\xbe\x7d\x8d\x1b\xbf\x7d\x8d\x1b\xbf\x8d\xa1\x91\x3e\x8d\xa1\x91\x3e\x96\xad\x97\xbe\xc5\x7e\x3e\x3f\xe1\x95\xf2\xbe\x70\x0a\x27\xbf\x70\x0a\x27\xbf\x3f\x4f\x1e\xbf\x3f\x4f\x1e\xbf\x73\xad\x1e\xbf\x64\x21\x3e\x3f\x78\x69\x92\xbe\x00\x1d\x2b\xbf\x00\x1d\x2b\xbf\xc6\xbc\x7f\xbf\xc6\xbc\x7f\xbf\x95\x40\x82\x3f\x9e\xc3\x3d\x3f\x18\xdf\x18\x3e\xba\x85\x27\xbf\xba\x85\x27\xbf\x0c\xd0\x08\xbf\x0c\xd0\x08\xbf\x1e\xad\x0f\xbf\x70\x65\x3d\x3f\xdb\xc5\xe8\x3e\xe2\x53\x1c\xbf\xe2\x53\x1c\xbf\x3a\x15\xc4\x3e\x3a\x15\xc4\x3e\x96\xb9\xbb\xbe\xdc\x06\x3d\x3f\x40\xb9\xbb\x3e\x40\x0c\x0a\xbf\x40\x0c\x0a\xbf\xcc\xc3\x79\x3f\xcc\xc3\x79\x3f\xbb\xd6\x7b\x3f\xe2\xa7\x3c\x3f\xd0\x4b\x14\xbd\x65\x61\xe3\xbe\x65\x61\xe3\xbe\xec\x54\x3d\x3f\xec\x54\x3d\x3f\xbc\xf6\x44\xbf\x80\x48\x3c\x3f\xdc\xa9\xd0\xbe\xdd\x33\xa8\xbe\xdd\x33\xa8\xbe\x58\xdb\x00\xbe\x58\xdb\x00\xbe\x36\xec\xbb\xbd\xba\xe8\x3b\x3f\x86\x1e\xdc\xbe\x88\xdc\x49\xbe\x88\xdc\x49\xbe\x02\x6c\x62\xbf\x02\x6c\x62\xbf\xf1\x7c\x5d\x3f\x8e\x88\x3b\x3f\x99\x36\xa8\xbd\x6d\x7d\x67\xbd\x6d\x7d\x67\xbd\xfa\x82\x63\xbf\xfa\x82\x63\xbf\xc7\x83\x64\xbf\xff\x27\x3b\x3f\x4a\xa9\xab\x3e\x80\xb4\xaf\x3d\x80\xb4\xaf\x3d\xbe\x82\x08\xbe\xbe\x82\x08\xbe\x57\xcb\x1e\x3e\x06\xc7\x3a\x3f\xf9\x98\xee\x3e\x4e\xd3\x64\x3e\x4e\xd3\x64\x3e\x8f\x9e\x3c\x3f\x8f\x9e\x3c\x3f\xd1\xfe\x35\x3f\xa5\x65\x3a\x3f\xf7\xf8\x4b\x3e\x00\x49\xb4\x3e\x00\x49\xb4\x3e\x21\xcd\x79\x3f\x21\xcd\x79\x3f\x84\xad\x75\xbf\xe0\x03\x3a\x3f\xca\x78\x74\xbe\xdb\x9f\xee\x3e\xdb\x9f\xee\x3e\x95\x00\xc1\x3e\x95\x00\xc1\x3e\x4e\x82\xc1\x3e\xb6\xa1\x39\x3f\x33\x49\xf1\xbe\xf9\xef\x0e\x3f\xf9\xef\x0e\x3f\xd6\xe8\x0b\xbf\xd6\xe8\x0b\xbf\x45\xd7\x07\x3f\x29\x3f\x39\x3f\x2b\xf3\x9b\xbe\x66\x9e\x1f\x3f\x66\x9e\x1f\x3f\xae\xf4\x7f\xbf\xae\xf4\x7f\xbf\x54\xa2\x7a\xbf\x37\xdc\x38\x3f\x33\x82\xf4\x3d\x9d\xd4\x28\x3f\x9d\xd4\x28\x3f\x0c\x44\x17\xbf\x0c\x44\x17\xbf\x79\xca\x13\x3f\xdf\x78\x38\x3f\x00\x2d\xe3\x3e\xf7\xa2\x2a\x3f\xf7\xa2\x2a\x3f\xfc\x4f\xa8\x3e\xfc\x4f\xa8\x3e\xe7\xc1\xa7\x3e\x21\x15\x38\x3f\x46\xa4\xc8\x3e\xf9\xce\x24\x3f\xf9\xce\x24\x3f\x8b\xe1\x76\x3f\x8b\xe1\x76\x3f\x5d\x28\x73\xbf\xfe\xb0\x37\x3f\xde\x08\x2f\x3c\xd1\x27\x17\x3f\xd1\x27\x17\x3f\x8d\xca\x43\x3f\x8d\xca\x43\x3f\xb8\xe0\x3e\x3f\x76\x4c\x37\x3f\x6e\x71\xc2\xbe\x46\x2a\x02\x3f\x46\x2a\x02\x3f\x67\x60\xc9\xbd\x67\x60\xc9\xbd\x6d\xca\xe3\x3d\x8a\xe7\x36\x3f\xc6\x1c\xe7\xbe\x05\x3e\xce\x3e\x05\x3e\xce\x3e\xa8\x56\x60\xbf\xa8\x56\x60\xbf\x7a\x6b\x60\xbf\x3b\x82\x36\x3f\x2b\x6b\x12\xbe\x8b\x27\x8f\x3e\x8b\x27\x8f\x3e\x4b\x6a\x64\xbf\x4b\x6a\x64\xbf\xa2\xca\x61\x3f\x87\x1c\x36\x3f\x8e\x2f\x91\x3e\x3e\x08\x13\x3e\x3e\x08\x13\x3e\xf7\x1a\x06\xbe\xf7\x1a\x06\xbe\x4f\xfe\xf1\xbd\x70\xb6\x35\x3f\xf7\xd7\xf1\x3e\x4b\xbe\x93\xb9\x4b\xbe\x93\xb9\x01\xab\x3e\x3f\x01\xab\x3e\x3f\x2f\xae\x40\xbf\xf4\x4f\x35\x3f\xd2\x4b\x89\x3e\x91\x6a\x14\xbe\x91\x6a\x14\xbe\x80\x63\x78\x3f\x80\x63\x78\x3f\x35\xa5\x78\x3f\x16\xe9\x34\x3f\x83\xd7\x22\xbe\x63\x98\x90\xbe\x63\x98\x90\xbe\x6d\xb1\xb1\x3e\x6d\xb1\xb1\x3e\xe5\x3b\xb0\xbe\xd3\x81\x34\x3f\x39\x81\xe8\xbe\xe2\xcb\xcf\xbe\xe2\xcb\xcf\xbe\x9d\x9c\x14\xbf\x9d\x9c\x14\xbf\x67\x72\x15\xbf\x2c\x1a\x34\x3f\x33\xc4\xbe\xbe\xd4\xa8\x02\xbf\xd4\xa8\x02\xbf\x76\xd1\x7f\xbf\x76\xd1\x7f\xbf\xdb\x3c\x80\x3f\x22\xb2\x33\x3f\x9e\xfb\x8c\x3c\xcb\x7c\x17\xbf\xcb\x7c\x17\xbf\x0d\x49\x0a\xbf\x0d\x49\x0a\xbf\x06\xc3\x0a\xbf\xb5\x49\x33\x3f\x9c\xc5\xc9\x3e\xd7\x39\x25\xbf\xd7\x39\x25\xbf\x75\x1e\xca\x3e\x75\x1e\xca\x3e\xc5\x0a\xca\xbe\xe4\xe0\x32\x3f\xe3\xf3\xe3\x3e\x35\x03\x2b\xbf\x35\x03\x2b\xbf\x2e\x83\x7b\x3f\x2e\x83\x7b\x3f\xf9\x32\x7c\x3f\xb2\x77\x32\x3f\x1c\x92\x02\x3e\xa7\x9b\x28\xbf\xa7\x9b\x28\xbf\x7c\x04\x34\x3f\x7c\x04\x34\x3f\x28\x0b\x35\xbf\x1c\x0e\x32\x3f\xdc\x7d\x96\xbe\xa5\x42\x1e\xbf\xa5\x42\x1e\xbf\x62\xe6\x4a\xbe\x62\xe6\x4a\xbe\x75\xd0\x49\xbe\x24\xa4\x31\x3f\xc0\x39\xf2\xbe\x6a\x76\x0c\xbf\x6a\x76\x0c\xbf\x1d\xb7\x6c\xbf\x1d\xb7\x6c\xbf\x7a\x03\x6e\x3f\x61\x3c\x31\x3f\xaf\x60\x87\xbe\x48\xe1\xe7\xbe\x48\xe1\xe7\xbe\x91\xe3\x54\xbf\x91\xe3\x54\xbf\xb9\x52\x57\xbf\xd2\xd6\x30\x3f\x36\x1d\x24\x3e\x5c\x7e\xab\xbe\x5c\x7e\xab\xbe\x71\x55\x95\x37\x71\x55\x95\x37\x56\xac\x05\x3c\x16\x68\x30\x3f\x14\xd4\xe7\x3e\xf4\xa5\x4d\xbe\xf4\xa5\x4d\xbe\x6b\xf8\x54\x3f\x6b\xf8\x54\x3f\xe5\x74\x54\x3f\x2d\xf0\x2f\x3f\x9b\xf9\xc0\x3e\x45\x26\x6b\xbd\x45\x26\x6b\xbd\xf3\x5e\x6c\x3f\xf3\x5e\x6c\x3f\xbb\x61\x6d\xbf\x2c\x80\x2f\x3f\xa5\x05\x98\xbb\xd9\x31\xb6\x3d\xd9\x31\xb6\x3d\xb3\x27\x44\x3e\xb3\x27\x44\x3e\xfd\xb0\x49\x3e\x12\x18\x2f\x3f\x99\x93\xc4\xbe\x16\x19\x6d\x3e\x16\x19\x6d\x3e\xad\x1e\x36\xbf\xad\x1e\x36\xbf\xa1\x83\x35\x3f\x7e\xad\x2e\x3f\x91\x28\xe7\xbe\x76\x0b\xba\x3e\x76\x0b\xba\x3e\x5e\x88\x7a\xbf\x5e\x88\x7a\xbf\xb8\x07\x7b\xbf\x70\x40\x2e\x3f\x8a\x15\x1c\xbe\x14\x7e\xf4\x3e\x14\x7e\xf4\x3e\x86\x58\xbd\xbe\x86\x58\xbd\xbe\x04\xaf\xbf\x3e\xfa\xd2\x2d\x3f\x55\x88\x89\x3e\xcf\x58\x11\x3f\xcf\x58\x11\x3f\xb2\x27\x12\x3f\xb2\x27\x12\x3f\x10\xf5\x10\x3f\x1c\x65\x2d\x3f\xf6\x90\xf2\x3e\x99\x7e\x21\x3f\x99\x7e\x21\x3f\xa7\xe3\x7f\x3f\xa7\xe3\x7f\x3f\x74\x3f\x7f\xbf\xda\xf6\x2c\x3f\x1c\xa0\x97\x3e\x68\x02\x2a\x3f\x68\x02\x2a\x3f\x48\x90\x07\x3f\x48\x90\x07\x3f\x57\x10\x08\x3f\x30\x88\x2c\x3f\xad\xfb\xf4\xbd\xa2\x4b\x2a\x3f\xa2\x4b\x2a\x3f\xc8\xe8\xd5\xbe\xc8\xe8\xd5\xbe\x6c\xd5\xd1\x3e\x22\x19\x2c\x3f\x15\xc9\xdf\xbe\xaa\x2f\x22\x3f\xaa\x2f\x22\x3f\xf9\x29\x7d\xbf\xf9\x29\x7d\xbf\x88\xf5\x79\xbf\xae\xa9\x2b\x3f\x13\x27\xd0\xbe\x52\xde\x11\x3f\x52\xde\x11\x3f\xd0\xc4\x2a\xbf\xd0\xc4\x2a\xbf\x87\xc7\x27\x3f\xd4\x39\x2b\x3f\x7c\x7e\x4c\xbd\x92\xf4\xf4\x3e\x92\xf4\xf4\x3e\x87\x4d\x84\x3e\x87\x4d\x84\x3e\x5b\x98\x86\x3e\x96\xc9\x2a\x3f\xca\xe8\xb1\x3e\x45\xa7\xba\x3e\x45\xa7\xba\x3e\xcd\x3e\x73\x3f\xcd\x3e\x73\x3f\x26\x09\x72\xbf\xf2\x58\x2a\x3f\x2c\x62\xee\x3e\xae\x22\x6e\x3e\xae\x22\x6e\x3e\x6d\xc1\x47\x3f\x6d\xc1\x47\x3f\x19\x67\x45\x3f\xe8\xe7\x29\x3f\x8b\xcc\x5b\x3e\x2c\x54\xb5\x3d\x2c\x54\xb5\x3d\xae\x62\xc9\xbd\xae\x62\xc9\xbd\x45\x25\xd5\x3d\x7a\x76\x29\x3f\xf7\x7d\x54\xbe\x57\xff\x78\xbd\x57\xff\x78\xbd\x90\x41\x63\xbf\x90\x41\x63\xbf\x14\xa8\x62\xbf\xa7\x04\x29\x3f\x34\x1e\xee\xbe\x1d\xf5\x53\xbe\x1d\xf5\x53\xbe\x9f\x6d\x5e\xbf\x9f\x6d\x5e\xbf\x54\x44\x5c\x3f\x6f\x92\x28\x3f\x1d\x24\xb4\xbe\xb0\x02\xaf\xbe\xb0\x02\xaf\xbe\x3a\x0a\x6c\xbd\x3a\x0a\x6c\xbd\x59\xca\x49\xbd\xd4\x1f\x28\x3f\x08\xef\x12\x3d\xd2\x89\xeb\xbe\xd2\x89\xeb\xbe\x3e\x7d\x4e\x3f\x3e\x7d\x4e\x3f\x5b\x44\x4f\xbf\xd4\xac\x27\x3f\x63\x85\xca\x3e\x8a\x61\x0e\xbf\x8a\x61\x0e\xbf\x9e\x00\x6f\x3f\x9e\x00\x6f\x3f\xbe\x12\x6e\x3f\x70\x39\x27\x3f\x44\x7f\xe4\x3e\x1b\x0c\x20\xbf\x1b\x0c\x20\xbf\x5b\x7a\x52\x3e\x5b\x7a\x52\x3e\x80\xb9\x49\xbe\xaa\xc5\x26\x3f\xfd\x3c\x13\x3e\x77\xbb\x29\xbf\x77\xbb\x29\xbf\xe6\x2d\x36\xbf\xe6\x2d\x36\xbf\x7a\xf1\x38\xbf\x81\x51\x26\x3f\xa2\xf1\x89\xbe\xed\x95\x2a\xbf\xed\x95\x2a\xbf\xde\xcb\x79\xbf\xde\xcb\x79\xbf\xb3\x6f\x7c\x3f\xf5\xdc\x25\x3f\xa0\x56\xf2\xbe\x67\xe2\x22\xbf\x67\xe2\x22\xbf\xdb\x44\xaf\xbe\xdb\x44\xaf\xbe\xef\xab\xb2\xbe\x04\x68\x25\x3f\xe9\xaf\x9d\xbe\xc4\x3a\x13\xbf\xc4\x3a\x13\xbf\x02\x63\x1b\x3f\x02\x63\x1b\x3f\xaa\x67\x1b\xbf\xb0\xf2\x24\x3f\x7b\xd4\xd1\x3d\x7e\x84\xf8\xbe\x7e\x84\xf8\xbe\xc6\x2c\x7f\x3f\xc6\x2c\x7f\x3f\x5c\x81\x80\x3f\xfa\x7c\x24\x3f\xbb\x7b\xdb\x3e\xce\x26\xbe\xbe\xce\x26\xbe\xbe\x89\x7d\xee\x3e\x89\x7d\xee\x3e\x57\x80\xf3\xbe\xe2\x06\x24\x3f\xd6\xae\xd7\x3e\xc3\x2d\x73\xbe\xc3\x2d\x73\xbe\x4f\x13\xfe\xbe\x4f\x13\xfe\xbe\xf7\xb0\xfb\xbe\x69\x90\x23\x3f\x4f\xe6\xb5\x3d\x06\x19\xba\xbd\x06\x19\xba\xbd\x1f\xaf\x7f\xbf\x1f\xaf\x7f\xbf\x02\x94\x80\x3f\x8e\x19\x23\x3f\x9b\x4d\xa1\xbe\x83\x2d\x74\x3d\x83\x2d\x74\x3d\xb2\x33\x13\xbf\xb2\x33\x13\xbf\xbf\xb1\x16\xbf\x50\xa2\x22\x3f\x7d\x09\xf1\xbe\x23\xfa\x53\x3e\x23\xfa\x53\x3e\xe4\xf9\xc3\x3e\xe4\xf9\xc3\x3e\xdf\xdb\xbd\xbe\xb1\x2a\x22\x3f\xae\xe8\x87\xbe\x9f\xfe\xaf\x3e\x9f\xfe\xaf\x3e\xfc\x17\x7c\x3f\xfc\x17\x7c\x3f\x95\xe1\x7b\x3f\xb1\xb2\x21\x3f\x78\xff\x11\x3e\x3b\x54\xed\x3e\x3b\x54\xed\x3e\xb4\x81\x2b\x3f\xb4\x81\x2b\x3f\x5c\x92\x2e\xbf\x50\x3a\x21\x3f\x24\x12\xe4\x3e\x0b\x7c\x0f\x3f\x0b\x7c\x0f\x3f\x2f\x0f\x8a\xbe\x2f\x0f\x8a\xbe\xf3\x0a\x81\xbe\x8c\xc1\x20\x3f\x21\xc2\xcd\x3e\x35\xc8\x20\x3f\x35\xc8\x20\x3f\x3b\x3e\x75\xbf\x3b\x3e\x75\xbf\x0d\xe1\x71\x3f\x69\x48\x20\x3f\xbe\x4b\x52\x3d\xeb\xca\x29\x3f\xeb\xca\x29\x3f\x9c\x3c\x40\xbf\x9c\x3c\x40\xbf\x03\x82\x3f\xbf\xe5\xce\x1f\x3f\x52\x63\xac\xbe\xa3\x1e\x2a\x3f\xa3\x1e\x2a\x3f\x6b\x7b\x23\x3e\x6b\x7b\x23\x3e\x1e\x29\x1d\xbe\x01\x55\x1f\x3f\x93\xf2\xf0\xbe\xf7\xbb\x21\x3f\xf7\xbb\x21\x3f\x56\xdd\x6b\x3f\x56\xdd\x6b\x3f\xc1\x87\x69\x3f\xbc\xda\x1e\x3f\x15\x4e\x77\xbe\x83\x3d\x11\x3f\x83\x3d\x11\x3f\x4d\x73\x51\x3f\x4d\x73\x51\x3f\x8c\x0d\x50\xbf\x18\x60\x1e\x3f\xc0\xc4\x2c\x3e\xfd\x31\xf2\x3e\xfd\x31\xf2\x3e\x54\x4b\x61\xbd\x54\x4b\x61\xbd\xb8\xbb\x59\xbd\x12\xe5\x1d\x3f\xdb\xe1\xe5\x3e\x42\xfe\xb4\x3e\x42\xfe\xb4\x3e\x50\x8c\x60\xbf\x50\x8c\x60\xbf\x6b\x74\x5e\x3f\xaf\x69\x1d\x3f\x55\x63\xc9\x3e\xcc\xd7\x5c\x3e\xcc\xd7\x5c\x3e\xf5\x43\x5f\xbf\xf5\x43\x5f\xbf\x8e\xd3\x5c\xbf\xec\xed\x1c\x3f\xf7\xe0\x12\x3d\xec\x34\x88\x3d\xec\x34\x88\x3d\x04\xc5\x2f\xbd\x04\xc5\x2f\xbd\x5f\xec\x1b\x3d\xca\x71\x1c\x3f\x9f\x25\xb2\xbe\x44\x17\xaf\xbd\x44\x17\xaf\xbd\x16\xca\x53\x3f\x16\xca\x53\x3f\x92\x06\x53\x3f\x47\xf5\x1b\x3f\x15\x3e\xef\xbe\x52\xd5\x6e\xbe\x52\xd5\x6e\xbe\x38\xf7\x69\x3f\x38\xf7\x69\x3f\x59\xb5\x67\xbf\x66\x78\x1b\x3f\xfb\xfb\x72\xbe\x78\x5b\xbd\xbe\x78\x5b\xbd\xbe\x9c\xc9\x08\x3e\x9c\xc9\x08\x3e\x82\x51\xff\x3d\x28\xfb\x1a\x3f\xe1\x52\x33\x3e\xfc\x50\xf9\xbe\xfc\x50\xf9\xbe\xc1\x0e\x46\xbf\xc1\x0e\x46\xbf\x31\x13\x47\x3f\x8a\x7d\x1a\x3f\xf2\x39\xe8\x3e\x19\x16\x14\xbf\x19\x16\x14\xbf\xd0\xf8\x71\xbf\xd0\xf8\x71\xbf\x7c\xb0\x71\xbf\x8c\xff\x19\x3f\x7b\x38\xc7\x3e\x27\xaa\x23\xbf\x27\xaa\x23\xbf\xc4\x12\x5e\xbe\xc4\x12\x5e\xbe\xf4\xc4\x5c\x3e\x32\x81\x19\x3f\xca\xb5\x1d\x3d\x70\x9c\x2a\xbf\x70\x9c\x2a\xbf\x54\xda\x37\x3f\x54\xda\x37\x3f\x7c\xf2\x36\x3f\x7a\x02\x19\x3f\x96\xe6\xaf\xbe\xc0\xcf\x28\xbf\xc0\xcf\x28\xbf\xf7\xc2\x77\x3f\xf7\xc2\x77\x3f\xd4\xe0\x75\xbf\x64\x83\x18\x3f\xc0\x31\xf0\xbe\x5a\x14\x1e\xbf\x5a\x14\x1e\xbf\xd6\xc2\x95\x3e\xd6\xc2\x95\x3e\xa5\xbd\x93\x3e\xf1\x03\x18\x3f\x31\x42\x79\xbe\x25\xdb\x0a\xbf\x25\xdb\x0a\xbf\x65\xbc\x29\xbf\x65\xbc\x29\xbf\x4b\x68\x28\x3f\x20\x84\x17\x3f\x91\xad\x22\x3e\x2c\x75\xe0\xbe\x2c\x75\xe0\xbe\xa7\xc9\x7b\xbf\xa7\xc9\x7b\xbf\x1c\x22\x79\xbf\xf4\x03\x17\x3f\x83\x2b\xe5\x3e\x50\x15\x9f\xbe\x50\x15\x9f\xbe\xd7\x59\xb8\xbe\xd7\x59\xb8\xbe\xce\x59\xb6\x3e\x69\x83\x16\x3f\x77\xac\xce\x3e\x30\xfb\x2a\xbe\x30\xfb\x2a\xbe\x26\x36\x1c\x3f\x26\x36\x1c\x3f\x0f\xc5\x19\x3f\x82\x02\x16\x3f\x6d\x58\x6d\x3d\x87\x6b\x6c\xbc\x87\x6b\x6c\xbc\xc7\x68\x7e\x3f\xc7\x68\x7e\x3f\xdb\x4f\x7a\xbf\x3e\x81\x15\x3f\x5f\x62\xa6\xbe\x24\xee\x0e\x3e\x24\xee\x0e\x3e\x4c\xa8\xd6\x3e\x4c\xa8\xd6\x3e\x92\xda\xd2\x3e\x9f\xff\x14\x3f\x43\xa3\xf1\xbe\x79\x80\x92\x3e\x79\x80\x92\x3e\x6d\x91\x0f\xbf\x6d\x91\x0f\xbf\x04\x5e\x0d\x3f\xa3\x7d\x14\x3f\x3e\xfe\x8a\xbe\x0a\xce\xd5\x3e\x0a\xce\xd5\x3e\x02\xd2\x7f\xbf\x02\xd2\x7f\xbf\x46\x71\x7b\xbf\x4a\xfb\x13\x3f\x55\x96\x05\x3e\x55\xcb\x06\x3f\x55\xcb\x06\x3f\xb0\xc1\xf0\xbe\xb0\xc1\xf0\xbe\xa4\x80\xea\x3e\x97\x78\x13\x3f\x2d\x41\xdd\x3e\xee\x61\x1b\x3f\xee\x61\x1b\x3f\x04\xe1\x03\x3f\x04\xe1\x03\x3f\xdd\x51\x04\x3f\x89\xf5\x12\x3f\xe2\x1d\xd8\x3e\x6a\xbc\x27\x3f\x6a\xbc\x27\x3f\xad\x15\x80\x3f\xad\x15\x80\x3f\x92\x09\x7f\xbf\x20\x72\x12\x3f\xe8\xcc\xd2\x3d\x59\x0e\x2b\x3f\x59\x0e\x2b\x3f\xfb\x74\x03\x3f\xfb\x74\x03\x3f\x5e\x2b\x02\x3f\x5a\xee\x11\x3f\x67\xe7\x96\xbe\x10\x15\x25\x3f\x10\x15\x25\x3f\x4b\x62\xf2\xbe\x4b\x62\xf2\xbe\x78\xb2\xf4\x3e\x3b\x6a\x11\x3f\x69\xd5\xf1\xbe\x00\x2a\x16\x3f\x00\x2a\x16\x3f\x39\xbc\x7f\xbf\x39\xbc\x7f\xbf\x2b\x51\x80\xbf\xc1\xe5\x10\x3f\x11\xc2\x9e\xbe\x36\xf2\xfd\x3e\x36\xf2\xfd\x3e\x75\xc4\x0c\xbf\x75\xc4\x0c\xbf\x6c\x70\x0c\x3f\xec\x60\x10\x3f\xc2\x2b\x9d\x3d\xed\xc1\xc1\x3e\xed\xc1\xc1\x3e\xe6\x6b\xdf\x3e\xe6\x6b\xdf\x3e\x37\xf2\xe3\x3e\xbe\xdb\x0f\x3f\xab\x2e\xd2\x3e\xce\x3f\x76\x3e\xce\x3f\x76\x3e\xa1\xee\x7e\x3f\xa1\xee\x7e\x3f\x1c\xf7\x80\xbf\x35\x56\x0f\x3f\x17\x93\xe2\x3e\xb5\x89\xb6\x3d\xb5\x89\xb6\x3d\x4a\x77\x14\x3f\x4a\x77\x14\x3f\xc8\xca\x15\x3f\x53\xd0\x0e\x3f\x84\x4c\x24\x3e\xb7\x78\x89\xbd\xb7\x78\x89\xbd\xdb\x5a\xcf\xbe\xdb\x5a\xcf\xbe\x38\x13\xd2\x3e\x17\x4a\x0e\x3f\x44\x4d\x73\xbe\x1d\x52\x61\xbe\x1d\x52\x61\xbe\x27\x19\x7e\xbf\x27\x19\x7e\xbf\x6a\x52\x80\xbf\x81\xc3\x0d\x3f\xac\x22\xf0\xbe\xfe\x01\xb9\xbe\xfe\x01\xb9\xbe\x6b\xa0\x1a\xbf\x6b\xa0\x1a\xbf\xce\x29\x1c\x3f\x93\x3c\x0d\x3f\xe6\x65\xb7\xbe\xe9\x01\xf7\xbe\xe9\x01\xf7\xbe\x39\x7b\xc2\x3e\x39\x7b\xc2\x3e\x3a\xa9\xc2\x3e\x4d\xb5\x0c\x3f\x88\x2a\xae\x3b\x81\xbb\x13\xbf\x81\xbb\x13\xbf\xd0\x56\x7d\x3f\xd0\x56\x7d\x3f\x9b\x18\x7e\xbf\xae\x2d\x0c\x3f\x8b\x2b\xbb\x3e\xa3\xc9\x23\xbf\xa3\xc9\x23\xbf\xd0\x44\x1f\x3f\xd0\x44\x1f\x3f\xbd\xde\x1f\x3f\xb4\xa5\x0b\x3f\xd0\x2a\xef\x3e\xc7\xc8\x2a\xbf\xc7\xc8\x2a\xbf\x26\xd4\xb8\xbe\x26\xd4\xb8\xbe\xae\xb1\xb7\x3e\x64\x1d\x0b\x3f\x77\x28\x6c\x3e\x7b\x76\x28\xbf\x7b\x76\x28\xbf\xd7\xb2\x7c\xbf\xd7\xb2\x7c\xbf\xd6\x07\x7c\xbf\xbb\x94\x0a\x3f\x1f\x79\x28\xbe\x45\xbe\x1c\xbf\x45\xbe\x1c\xbf\x11\x6c\x22\xbf\x11\x6c\x22\xbf\x36\x51\x22\x3f\xbc\x0b\x0a\x3f\xa0\x0d\xe3\xbe\xe9\x31\x08\xbf\xe9\x31\x08\xbf\x20\x6c\xb2\x3e\x20\x6c\xb2\x3e\xfb\x0c\xb0\x3e\x66\x82\x09\x3f\xda\xd2\xd2\xbe\x00\x04\xd8\xbe\x00\x04\xd8\xbe\x38\x41\x7c\x3f\x38\x41\x7c\x3f\xbb\x36\x7a\xbf\xb8\xf8\x08\x3f\xc0\x20\xac\xbd\x61\x6a\x93\xbe\x61\x6a\x93\xbe\x9e\x2d\x24\x3f\x9e\x2d\x24\x3f\x4e\xcd\x22\x3f\xb4\x6e\x08\x3f\x2c\x2f\x99\x3e\x5c\xbe\x0d\xbe\x5c\xbe\x0d\xbe\x83\x58\xaf\xbe\x83\x58\xaf\xbe\x7a\x99\xae\x3e\x58\xe4\x07\x3f\x98\xe1\xf1\x3e\x77\x8f\x99\x3c\x77\x8f\x99\x3c\x3a\x1f\x7c\xbf\x3a\x1f\x7c\xbf\x6f\x91\x7a\xbf\xa5\x59\x07\x3f\xfd\x99\xa1\x3e\xf9\xf6\x33\x3e\xf9\xf6\x33\x3e\xe3\x91\x24\xbf\xe3\x91\x24\xbf\xb8\x7d\x23\x3f\x9d\xce\x06\x3f\x59\x8d\x8a\xbd\xa5\x78\xa5\x3e\xa5\x78\xa5\x3e\x24\x9d\xaf\x3e\x24\x9d\xaf\x3e\xa7\xc2\xae\x3e\x3e\x43\x06\x3f\x1d\x00\xcc\xbe\xb2\xbc\xe7\x3e\xb2\xbc\xe7\x3e\xaa\x4c\x7c\x3f\xaa\x4c\x7c\x3f\xf5\xf0\x7a\xbf\x8a\xb7\x05\x3f\x97\x12\xe7\xbe\xe7\x4b\x0e\x3f\xe7\x4b\x0e\x3f\xc6\x97\x23\x3f\xc6\x97\x23\x3f\x21\xaf\x22\x3f\x82\x2b\x05\x3f\x5b\xe6\x44\xbe\x92\x8f\x20\x3f\x92\x8f\x20\x3f\x6d\x32\xb3\xbe\x6d\x32\xb3\xbe\xb0\x2f\xb3\x3e\x24\x9f\x04\x3f\xf8\x23\x52\x3e\x5b\xfa\x29\x3f\x5b\xfa\x29\x3f\x2f\xb4\x7c\xbf\x2f\xb4\x7c\xbf\xd1\xc7\x7c\xbf\x70\x12\x04\x3f\xba\x8a\xe9\x3e\x2f\xdc\x29\x3f\x2f\xdc\x29\x3f\xe7\x33\x21\xbf\xe7\x33\x21\xbf\xe1\x55\x22\x3f\x69\x85\x03\x3f\xbd\x80\xc8\x3e\xe2\x02\x20\x3f\xe2\x02\x20\x3f\x6c\xf7\xb9\x3e\x6c\xf7\xb9\x3e\x40\x1f\xb7\x3e\x0d\xf8\x02\x3f\x5e\xb2\x68\x3d\xd9\xda\x0c\x3f\xd9\xda\x0c\x3f\x48\x4c\x7d\x3f\x48\x4c\x7d\x3f\x51\x9c\x7d\xbf\x5d\x6a\x02\x3f\xa9\x99\xa4\xbe\x67\xf0\xe2\x3e\x67\xf0\xe2\x3e\xff\x67\x1d\x3f\xff\x67\x1d\x3f\xf2\x1c\x20\x3f\x5a\xdc\x01\x3f\xe5\x06\xf2\xbe\xc7\x97\x9f\x3e\xc7\x97\x9f\x3e\xc2\xea\xc3\xbe\xc2\xea\xc3\xbe\x5e\x57\xbe\x3e\x02\x4e\x01\x3f\x28\x06\x99\xbe\xba\xd2\x26\x3e\xba\xd2\x26\x3e\x6f\x0e\x7e\xbf\x6f\x0e\x7e\xbf\x25\x5f\x7e\xbf\x58\xbf\x00\x3f\xff\x94\xa0\x3d\x17\xda\x8a\x3b\x17\xda\x8a\x3b\x69\x31\x18\xbf\x69\x31\x18\xbf\x40\xca\x1b\x3f\x59\x30\x00\x3f\x39\x27\xcf\x3e\x73\x10\x1f\xbe\x73\x10\x1f\xbe\x7d\x05\xd1\x3e\x7d\x05\xd1\x3e\xe3\xaf\xca\x3e\x10\x42\xff\x3e\xd8\x8c\xe6\x3e\x99\xf8\x9c\xbe\x99\xf8\x9c\xbe\x1c\xeb\x7e\x3f\x1c\xeb\x7e\x3f\xa4\x06\x80\xbf\xcc\x22\xfe\x3e\x84\xfe\x41\x3e\x11\x17\xe1\xbe\x11\x17\xe1\xbe\xd7\x70\x11\x3f\xd7\x70\x11\x3f\x2e\x87\x16\x3f\xe7\x02\xfd\x3e\x78\x01\x4d\xbe\x59\xef\x0b\xbf\x59\xef\x0b\xbf\x53\x39\xe1\xbe\x53\x39\xe1\xbe\x1a\xe8\xd7\x3e\x59\xe2\xfb\x3e\x57\xc5\xe9\xbe\x4c\x58\x1f\xbf\x4c\x58\x1f\xbf\xbe\xa6\x7f\xbf\xbe\xa6\x7f\xbf\x46\x21\x7f\xbf\x22\xc1\xfa\x3e\x46\xe5\xcb\xbe\x35\xaa\x29\xbf\x35\xaa\x29\xbf\x1a\xff\x08\xbf\x1a\xff\x08\xbf\x2d\xe9\x0b\x3f\x4d\x9f\xf9\x3e\x97\xf8\x8e\xbd\x31\x31\x2a\xbf\x31\x31\x2a\xbf\x24\x56\xf4\x3e\x24\x56\xf4\x3e\x1b\x53\xef\x3e\xd8\x7c\xf8\x3e\x15\xec\x9b\x3e\x4b\xb8\x20\xbf\x4b\xb8\x20\xbf\x2a\xff\x7f\x3f\x2a\xff\x7f\x3f\x19\x4b\x80\xbf\xc4\x59\xf7\x3e\x8a\xa8\xf2\x3e\x13\xa2\x0d\xbf\x13\xa2\x0d\xbf\xef\x6e\xfd\x3e\xef\x6e\xfd\x3e\x31\x97\x01\x3f\x0e\x36\xf6\x3e\x6b\x23\xa4\x3e\x99\x6a\xe4\xbe\x99\x6a\xe4\xbe\x84\x01\x05\xbf\x84\x01\x05\xbf\x74\x7f\x02\x3f\xb9\x11\xf5\x3e\x67\x58\x41\xbd\xf9\x43\xa0\xbe\xf9\x43\xa0\xbe\x00\xb7\x7f\xbf\x00\xb7\x7f\xbf\xa2\x23\x7f\xbf\xc2\xec\xf3\x3e\xaf\x04\xc4\xbe\x10\x79\x25\xbe\x10\x79\x25\xbe\xc8\x2f\xe5\xbe\xc8\x2f\xe5\xbe\x9e\x43\xe7\x3e\x2c\xc7\xf2\x3e\x7f\xdf\xec\xbe\xbe\x59\x61\xba\xbe\x59\x61\xba\x33\xf0\x10\x3f\x33\xf0\x10\x3f\xdb\x44\x0f\x3f\xf7\xa0\xf1\x3e\xc2\x6f\x6b\xbe\x0f\x0d\x24\x3e\x0f\x0d\x24\x3e\x47\x99\x7e\x3f\x47\x99\x7e\x3f\x06\xec\x7c\xbf\x26\x7a\xf0\x3e\x4c\x35\x20\x3e\x3f\xd3\x9f\x3e\x3f\xd3\x9f\x3e\xcc\x3e\xc9\x3e\xcc\x3e\xc9\x3e\x00\xb8\xc6\x3e\xb8\x52\xef\x3e\xe8\xcf\xdf\x3e\x87\x3b\xe4\x3e\x87\x3b\xe4\x3e\xb7\xbb\x1d\xbf\xb7\xbb\x1d\xbf\x9d\x11\x1e\x3f\xb0\x2a\xee\x3e\xd9\x1f\xda\x3e\xf5\x96\x0d\x3f\xf5\x96\x0d\x3f\x71\x6e\x7c\xbf\x71\x6e\x7c\xbf\x81\xe1\x7b\xbf\x0d\x02\xed\x3e\xad\xfd\x05\x3e\xd4\x9f\x20\x3f\xd4\x9f\x20\x3f\xd5\x84\xa9\xbe\xd5\x84\xa9\xbe\xd0\x45\xa9\x3e\xcf\xd8\xeb\x3e\xb8\x63\x80\xbe\x35\x0d\x2a\x3f\x35\x0d\x2a\x3f\x99\x3a\x2b\x3f\x99\x3a\x2b\x3f\xe2\x34\x29\x3f\xf6\xae\xea\x3e\x94\x38\xee\xbe\x61\x72\x29\x3f\x61\x72\x29\x3f\x47\xe9\x78\x3f\x47\xe9\x78\x3f\x36\xb3\x74\xbf\x85\x84\xe9\x3e\x25\xd4\xbe\xbe\xb4\xbd\x1e\x3f\xb4\xbd\x1e\x3f\x18\xb5\x85\x3e\x18\xb5\x85\x3e\xb3\xda\x7b\x3e\x7a\x59\xe8\x3e\x2c\x84\x05\xbd\x1b\x87\x0a\x3f\x1b\x87\x0a\x3f\x2e\x3d\x39\xbf\x2e\x3d\x39\xbf\x6c\xc7\x39\x3f\xd7\x2d\xe7\x3e\x15\x1e\xa9\x3e\x0a\xe6\xdb\x3e\x0a\xe6\xdb\x3e\x03\xa9\x73\xbf\x03\xa9\x73\xbf\x51\xa1\x70\xbf\x9b\x01\xe6\x3e\x00\x69\xf2\x3e\xcf\x31\x95\x3e\xcf\x31\x95\x3e\x10\xda\x3a\xbe\x10\xda\x3a\xbe\x14\xc9\x2d\x3e\xc9\xd4\xe4\x3e\x81\xfb\x9b\x3e\xda\x18\x0b\x3e\xda\x18\x0b\x3e\xc9\x70\x47\x3f\xc9\x70\x47\x3f\xda\x4f\x47\x3f\x61\xa7\xe3\x3e\xf0\x1c\x84\xbd\xa6\xdc\xe4\xbc\xa6\xdc\xe4\xbc\x70\x24\x6c\x3f\x70\x24\x6c\x3f\x0e\x92\x68\xbf\x64\x79\xe2\x3e\x64\xe6\xc7\xbe\xca\xa8\x42\xbe\xca\xa8\x42\xbe\x49\x85\xc2\x3d\x49\x85\xc2\x3d\xff\x81\xa7\x3d\xd2\x4a\xe1\x3e\x9f\x3d\xeb\xbe\x3c\x7d\xae\xbe\x3c\x7d\xae\xbe\xc3\x3d\x55\xbf\xc3\x3d\x55\xbf\x4e\xef\x54\x3f\x8c\x21\xe0\x3e\xc5\x10\x6b\xbe\xaf\x44\xf1\xbe\xaf\x44\xf1\xbe\x59\xdc\x61\xbf\x59\xdc\x61\xbf\x09\xe6\x5d\xbf\x91\xfd\xde\x3e\x3d\x7c\x19\x3e\x33\xb4\x12\xbf\x33\xb4\x12\xbf\xc8\xe8\xda\x39\xc8\xe8\xda\x39\x15\x24\x9b\xbc\xa7\xc3\xdd\x3e\x4b\xbb\xdd\x3e\x5f\xc9\x23\xbf\x5f\xc9\x23\xbf\xaa\xf0\x61\x3f\xaa\xf0\x61\x3f\x71\xeb\x64\x3f\xcd\x73\xdc\x3e\x9e\x05\xde\x3e\x6c\xe7\x2a\xbf\x6c\xe7\x2a\xbf\x05\x89\x54\x3f\x05\x89\x54\x3f\xe1\x63\x55\xbf\x97\x38\xdb\x3e\x1a\xc6\x1b\x3e\x58\x94\x27\xbf\x58\x94\x27\xbf\xde\x01\xd1\xbd\xde\x01\xd1\xbd\xbf\x2e\xd2\xbd\x05\x12\xda\x3e\x7a\xa2\x68\xbe\x39\x07\x1a\xbf\x39\x07\x1a\xbf\x9f\x06\x6d\xbf\x9f\x06\x6d\xbf\x91\xf6\x6c\x3f\x12\xe5\xd8\x3e\xa5\xa3\xeb\xbe\x2b\x0e\x03\xbf\x2b\x0e\x03\xbf\xf5\x19\x44\xbf\xf5\x19\x44\xbf\xbb\x23\x43\xbf\xbf\xb1\xd7\x3e\x6f\xd2\xc9\xbe\x15\xce\xc7\xbe\x15\xce\xc7\xbe\x4b\xb2\x55\x3e\x4b\xb2\x55\x3e\xc8\x15\x5d\xbe\xcf\x7d\xd6\x3e\xfe\x2f\x9b\xbd\x53\x6e\x7a\xbe\x53\x6e\x7a\xbe\x10\x20\x76\x3f\x10\x20\x76\x3f\xb5\xfc\x77\x3f\x42\x49\xd5\x3e\xbd\xcf\x94\x3e\x85\xae\xab\xbd\x85\xae\xab\xbd\x5c\x6b\x30\x3f\x5c\x6b\x30\x3f\x53\x25\x31\xbf\x1b\x14\xd4\x3e\x76\x0e\xf2\x3e\x82\x58\xa8\x3d\x82\x58\xa8\x3d\x51\x86\xa3\xbe\x51\x86\xa3\xbe\xb8\xa0\xa4\xbe\x5a\xde\xd2\x3e\xf2\xf3\xb2\x3e\x1e\x15\x79\x3e\x1e\x15\x79\x3e\x0f\xb6\x7c\xbf\x0f\xb6\x7c\xbf\x97\x6a\x7d\x3f\x00\xa8\xd1\x3e\xf4\xd1\x69\x3b\xd2\xa3\xc7\x3e\xd2\xa3\xc7\x3e\xd9\x25\x19\xbf\xd9\x25\x19\xbf\x91\x3a\x19\xbf\x0c\x71\xd0\x3e\xeb\x9f\xb0\xbe\xec\x3a\x03\x3f\xec\x3a\x03\x3f\xae\x85\xdd\x3e\xae\x85\xdd\x3e\xca\x9e\xdc\xbe\x81\x39\xcf\x3e\x69\x42\xf2\xbe\xa6\x67\x1a\x3f\xa6\x67\x1a\x3f\x77\xf0\x7f\x3f\x77\xf0\x7f\x3f\xf0\x83\x7d\x3f\x5d\x01\xce\x3e\x6f\x97\x98\xbe\x0b\xf0\x27\x3f\x0b\xf0\x27\x3f\x3e\xfa\xfb\x3e\x3e\xfa\xfb\x3e\x96\xf4\xf3\xbe\xa4\xc8\xcc\x3e\xc0\x84\x82\x3d\x53\xe7\x2a\x3f\x53\xe7\x2a\x3f\x30\xb5\x0b\xbf\x30\xb5\x0b\xbf\x86\x9e\x0e\xbf\x55\x8f\xcb\x3e\x79\x3d\xc5\x3e\x72\x3c\x23\x3f\x72\x3c\x23\x3f\x5f\xe7\x7e\xbf\x5f\xe7\x7e\xbf\x2b\xbe\x7e\x3f\x70\x55\xca\x3e\xf5\x38\xed\x3e\x07\x5f\x11\x3f\x07\x5f\x11\x3f\xdd\xf2\xbd\xbe\xdd\xf2\xbd\xbe\xa9\x3c\xba\xbe\xf6\x1a\xc9\x3e\x77\xf7\x7d\x3e\x38\x8c\xec\x3e\x38\x8c\xec\x3e\x90\xa2\x27\x3f\x90\xa2\x27\x3f\xca\xd6\x27\xbf\xe7\xdf\xc7\x3e\x6e\xf5\xfc\xbd\x19\x67\xa7\x3e\x19\x67\xa7\x3e\xa0\xe3\x78\x3f\xa0\xe3\x78\x3f\x48\xfe\x75\x3f\x45\xa4\xc6\x3e\xac\x09\xd6\xbe\xb7\xf2\x2e\x3e\xb7\xf2\x2e\x3e\xce\x1d\x72\x3e\xce\x1d\x72\x3e\x62\x4c\x62\xbe\x11\x68\xc5\x3e\x6e\x93\xe5\xbe\xff\x39\x7d\x3b\xff\x39\x7d\x3b\x4d\x7d\x41\xbf\x4d\x7d\x41\xbf\xe5\x61\x43\xbf\x4c\x2b\xc4\x3e\x8f\x3f\x49\xbe\x7a\x21\x27\xbe\x7a\x21\x27\xbe\x9a\x6f\x6d\xbf\x9a\x6f\x6d\xbf\x01\x3e\x6c\x3f\xf8\xed\xc2\x3e\x18\xb4\x35\x3e\x19\xe2\xa3\xbe\x19\xe2\xa3\xbe\x29\x41\xba\xbd\x29\x41\xba\xbd\x4e\x5c\xa3\xbd\x16\xb0\xc1\x3e\xfb\x32\xe1\x3e\x78\xc9\xe9\xbe\x78\xc9\xe9\xbe\x61\x3e\x58\x3f\x61\x3e\x58\x3f\x55\xe3\x5a\xbf\xa4\x71\xc0\x3e\x48\x24\xdb\x3e\x0e\x73\x10\xbf\x0e\x73\x10\xbf\xf3\x32\x5c\x3f\xf3\x32\x5c\x3f\xf5\xab\x5d\x3f\xa2\x32\xbf\x3e\x20\xe6\x19\x3e\x51\xda\x22\xbf\x51\xda\x22\xbf\xe5\x99\x80\xbd\xe5\x99\x80\xbd\x24\x88\x7e\x3d\x10\xf3\xbd\x3e\x13\x4d\x63\xbe\xe5\xd0\x2a\xbf\xe5\xd0\x2a\xbf\xed\xe2\x6a\xbf\xed\xe2\x6a\xbf\xd0\x93\x6b\xbf\xec\xb2\xbc\x3e\x8a\xab\xe9\xbe\x8f\xdf\x27\xbf\x8f\xdf\x27\xbf\x54\xe2\x44\xbf\x54\xe2\x44\xbf\x1a\x37\x45\x3f\x43\x72\xbb\x3e\x1c\xa1\xd0\xbe\xc6\x21\x1a\xbf\xc6\x21\x1a\xbf\x58\x24\x63\x3e\x58\x24\x63\x3e\x56\x1b\x69\x3e\x13\x31\xba\x3e\x02\xf8\xd9\xbd\xad\x6e\x02\xbf\xad\x6e\x02\xbf\x62\x56\x78\x3f\x62\x56\x78\x3f\x33\xc3\x7b\xbf\x56\xef\xb8\x3e\x04\x7f\x85\x3e\x0c\xa8\xc4\xbe\x0c\xa8\xc4\xbe\xca\x45\x27\x3f\xca\x45\x27\x3f\xf0\x9e\x2a\x3f\x0a\xad\xb7\x3e\x5c\x20\xee\x3e\x1c\x3f\x6f\xbe\x1c\x3f\x6f\xbe\xcd\xa6\xc3\xbe\xcd\xa6\xc3\xbe\xfa\x00\xc2\x3e\x38\x6a\xb6\x3e\xd1\xfa\xc4\x3e\x41\x87\x8b\xbd\x41\x87\x8b\xbd\x8b\x62\x7f\xbf\x8b\x62\x7f\xbf\xb1\xad\x80\xbf\xdc\x26\xb5\x3e\xef\x16\x8d\x3d\x33\xe2\xd0\x3d\x33\xe2\xd0\x3d\xe5\x68\x03\xbf\xe5\x68\x03\xbf\xed\xe0\x05\x3f\xfa\xe2\xb3\x3e\x91\xd9\x94\xbe\xec\x1a\x88\x3e\xec\x1a\x88\x3e\x7b\xc1\x09\x3f\x7b\xc1\x09\x3f\x92\x36\x09\x3f\x91\x9e\xb2\x3e\xc0\x11\xf1\xbe\x74\x37\xd3\x3e\x74\x37\xd3\x3e\x11\xc2\x7e\x3f\x11\xc2\x7e\x3f\xbe\x12\x80\xbf\xa1\x59\xb1\x3e\xa8\x7f\xba\xbe\xe7\x51\x08\x3f\xe7\x51\x08\x3f\xfe\x9d\xb3\x3e\xfe\x9d\xb3\x3e\x3e\xd6\xb5\x3e\x2c\x14\xb0\x3e\xec\xc2\x0c\xbd\x51\x19\x1e\x3f\x51\x19\x1e\x3f\xcb\xb5\x2e\xbf\xcb\xb5\x2e\xbf\x14\xb6\x2f\x3f\x32\xce\xae\x3e\x55\xfa\xa1\x3e\x6c\x84\x29\x3f\x6c\x84\x29\x3f\x43\x6f\x75\xbf\x43\x6f\x75\xbf\x59\x12\x78\xbf\xb5\x87\xad\x3e\x89\x7b\xf1\x3e\x05\xd9\x29\x3f\x05\xd9\x29\x3f\x21\x43\x2e\xbe\x21\x43\x2e\xbe\x61\x59\x37\x3e\xb4\x40\xac\x3e\x8c\xb2\xaf\x3e\x29\x03\x1f\x3f\x29\x03\x1f\x3f\x56\xb9\x4e\x3f\x56\xb9\x4e\x3f\x68\x0e\x4e\x3f\x30\xf9\xaa\x3e\x3f\x1a\xda\x3b\x6b\xbd\x09\x3f\x6b\xbd\x09\x3f\xed\xe0\x62\x3f\xed\xe0\x62\x3f\xc6\x32\x63\xbf\x2b\xb1\xa9\x3e\x7d\x21\xab\xbe\x37\xc6\xd6\x3e\x37\xc6\xd6\x3e\x03\x0a\xb9\xbc\x03\x0a\xb9\xbc\xe1\xce\xb9\xbc\xa4\x68\xa8\x3e\xd3\xc8\xf1\xbe\x8c\xd1\x8b\x3e\x8c\xd1\x8b\x3e\x2d\xfb\x67\xbf\x2d\xfb\x67\xbf\x24\xb3\x68\x3f\x9d\x1f\xa7\x3e\xd0\x9f\xa7\xbe\xf1\x5a\xde\x3d\xf1\x5a\xde\x3d\x10\x14\x47\xbf\x10\x14\x47\xbf\x93\xc8\x47\xbf\x15\xd6\xa5\x3e\x25\x12\x88\x3c\x13\x14\x82\xbd\x13\x14\x82\xbd\x6b\xe5\x61\x3e\x6b\xe5\x61\x3e\x62\x3a\x61\xbe\x0f\x8c\xa4\x3e\x70\x4c\xb3\x3e\x56\x02\x6d\xbe\x56\x02\x6d\xbe\x4e\xde\x78\x3f\x4e\xde\x78\x3f\xe1\x11\x79\x3f\x8b\x41\xa3\x3e\x38\x73\xf1\x3e\x35\xac\xc4\xbe\x35\xac\xc4\xbe\x32\x51\x22\x3f\x32\x51\x22\x3f\x95\xce\x22\xbf\x8a\xf6\xa1\x3e\x46\x2e\xa0\x3e\xaf\xe5\x02\xbf\xaf\xe5\x02\xbf\x3b\x05\xd5\xbe\x3b\x05\xd5\xbe\x87\x82\xd2\xbe\x0d\xab\xa0\x3e\x90\x7a\x09\xbd\xbe\xb4\x1a\xbf\xbe\xb4\x1a\xbf\xfe\xcb\x7f\xbf\xfe\xcb\x7f\xbf\x35\xc3\x7d\x3f\x14\x5f\x9f\x3e\x18\x39\xb8\xbe\xd9\x3e\x28\xbf\xd9\x3e\x28\xbf\xab\x83\xea\xbe\xab\x83\xea\xbe\xcb\xce\xe7\xbe\x9f\x12\x9e\x3e\x52\x49\xf1\xbe\x06\x87\x2a\xbf\x06\x87\x2a\xbf\x79\x91\x19\x3f\x79\x91\x19\x3f\x8b\xa7\x18\xbf\xb0\xc5\x9c\x3e\xdd\xe4\x9b\xbe\x7d\x64\x21\xbf\x7d\x64\x21\xbf\x8f\x48\x7b\x3f\x8f\x48\x7b\x3f\xfd\xf8\x78\x3f\x45\x78\x9b\x3e\xd4\xb0\x38\x3d\x0f\x65\x0d\xbf\x0f\x65\x0d\xbf\x9e\x30\x82\x3e\x9e\x30\x82\x3e\x59\x29\x81\xbe\x64\x2a\x9a\x3e\x51\xd8\xbb\x3e\x8f\x8c\xdf\xbe\x8f\x8c\xdf\xbe\xcb\xe6\x42\xbf\xcb\xe6\x42\xbf\xf7\xd2\x3f\xbf\x0c\xdc\x98\x3e\x58\xc4\xf0\x3e\x7e\x20\x95\xbe\x7e\x20\x95\xbe\xab\x41\x6a\xbf\xab\x41\x6a\xbf\xae\x1c\x66\x3f\x3c\x8d\x97\x3e\x47\xe5\x98\x3e\x54\x0c\x01\xbe\x54\x0c\x01\xbe\xa6\x28\xfb\xbc\xa6\x28\xfb\xbc\xfa\xe1\xe4\xbc\xf2\x3d\x96\x3e\x73\xc1\x4a\xbd\x7a\x8a\x44\x3d\x7a\x8a\x44\x3d\xba\x9c\x63\x3f\xba\x9c\x63\x3f\x82\xce\x5f\xbf\x35\xee\x94\x3e\x7a\x39\xbc\xbe\x74\x07\x60\x3e\x74\x07\x60\x3e\x82\x4d\x4c\x3f\x82\x4d\x4c\x3f\xda\xd7\x47\x3f\x03\x9e\x93\x3e\x81\xfb\xf0\xbe\x97\x03\xc0\x3e\x97\x03\xc0\x3e\x6c\x90\x4e\xbe\x6c\x90\x4e\xbe\x83\xf8\x52\x3e\x5d\x4d\x92\x3e\x85\x5e\x99\xbe\xdd\x74\x01\x3f\xdd\x74\x01\x3f\x4d\xc8\x78\xbf\x4d\xc8\x78\xbf\xb9\xe0\x76\xbf\x42\xfc\x90\x3e\x1c\x00\x49\x3d\x13\x0e\x1a\x3f\x13\x0e\x1a\x3f\x1a\x0a\x22\xbf\x1a\x0a\x22\xbf\x44\x60\x20\x3f\xb6\xaa\x8f\x3e\x7f\x45\xbc\x3e\xc1\x22\x28\x3f\xc1\x22\x28\x3f\x63\xa6\xdb\x3e\x63\xa6\xdb\x3e\x52\x9c\xdb\x3e\xb8\x58\x8e\x3e\x3b\x2a\xf1\x3e\xbf\xad\x2a\x3f\xbf\xad\x2a\x3f\x2c\x05\x80\x3f\x2c\x05\x80\x3f\x3c\xa3\x7f\xbf\x49\x06\x8d\x3e\x75\x51\x9a\x3e\x35\x88\x21\x3f\x35\x88\x21\x3f\x11\x3d\xda\x3e\x11\x3d\xda\x3e\xb6\xca\xd9\x3e\x68\xb3\x8b\x3e\xd8\x41\x32\xbd\xf7\x3f\x0d\x3f\xf7\x3f\x0d\x3f\xaa\xcb\x22\xbf\xaa\xcb\x22\xbf\xe0\x47\x24\x3f\x18\x60\x8a\x3e\x09\x29\xb9\xbe\x1c\x66\xde\x3e\x1c\x66\xde\x3e\xa8\xe7\x77\xbf\xa8\xe7\x77\xbf\xaa\xbd\x7a\xbf\x59\x0c\x89\x3e\x04\x43\xf1\xbe\x9d\xef\x92\x3e\x9d\xef\x92\x3e\xb7\x08\x41\xbe\xb7\x08\x41\xbe\x52\x5b\x45\x3e\x2c\xb8\x87\x3e\xbf\x86\x9e\xbe\x8d\xde\xf4\x3d\x8d\xde\xf4\x3d\xce\xe7\x4e\x3f\xce\xe7\x4e\x3f\xbd\x18\x52\x3f\x93\x63\x86\x3e\xa3\x6e\x03\x3d\x7a\x02\x67\xbd\x7a\x02\x67\xbd\x99\xdc\x5f\x3f\x99\xdc\x5f\x3f\x76\xe7\x64\xbf\x8d\x0e\x85\x3e\x81\x3e\xb5\x3e\xc0\xf8\x69\xbe\xc0\xf8\x69\xbe\x18\x39\x8a\xbd\x18\x39\x8a\xbd\x85\x81\x78\xbd\x1a\xb9\x83\x3e\x9c\xb7\xf1\x3e\xd9\x16\xc5\xbe\xd9\x16\xc5\xbe\xba\x9d\x6e\xbf\xba\x9d\x6e\xbf\xd5\x60\x71\x3f\x3c\x63\x82\x3e\x17\xe6\xa3\x3e\x30\xbd\x03\xbf\x30\xbd\x03\xbf\xf5\x43\x38\xbf\xf5\x43\x38\xbf\xf3\x38\x3b\xbf\xf4\x0c\x81\x3e\x9a\xc5\x77\xbc\xb9\xc5\x1b\xbf\xb9\xc5\x1b\xbf\x28\xf4\xa6\x3e\x28\xf4\xa6\x3e\x92\x88\xa8\xbe\x87\x6c\x7f\x3e\x8a\x43\xae\xbe\xd2\xf4\x28\xbf\xd2\xf4\x28\xbf\xbe\xad\x7e\x3f\xbe\xad\x7e\x3f\x32\xf3\x80\x3f\x59\xbe\x7c\x3e\xfb\x2f\xf2\xbe\x59\x41\x2a\xbf\x59\x41\x2a\xbf\x33\x6b\x02\x3f\x33\x6b\x02\x3f\x87\xff\x03\xbf\x58\x0f\x7a\x3e\xc1\x65\xac\xbe\x1e\x95\x1f\xbf\x1e\x95\x1f\xbf\x08\x78\x11\xbf\x08\x78\x11\xbf\xe8\x93\x12\xbf\x84\x5f\x77\x3e\x46\x80\xfa\xbb\xd5\xa7\x09\xbf\xd5\xa7\x09\xbf\xdd\x50\x7c\xbf\xdd\x50\x7c\xbf\x0c\x4f\x7d\x3f\xe7\xae\x74\x3e\x5b\x46\xa6\x3e\x2a\xf2\xd3\xbe\x2a\xf2\xd3\xbe\xb4\xa8\x82\xbe\xb4\xa8\x82\xbe\xb4\xd1\x80\xbe\x80\xfd\x71\x3e\x06\x59\xf2\x3e\x1d\xa0\x85\xbe\x1d\xa0\x85\xbe\xc3\xf2\x45\x3f\xc3\xf2\x45\x3f\xce\xd1\x46\xbf\x53\x4b\x6f\x3e\x42\x10\xb5\x3e\x89\xe1\xb6\xbd\x89\xe1\xb6\xbd\x0b\x33\x66\x3f\x0b\x33\x66\x3f\xdf\x88\x64\x3f\x60\x98\x6c\x3e\xd3\xcb\x10\x3d\x6d\x39\xb6\x3d\x6d\x39\xb6\x3d\xd4\xd1\xd2\xbc\xd4\xd1\xd2\xbc\xed\x3f\x1f\x3d\xa6\xe4\x69\x3e\xb8\x5a\x9a\xbe\x61\x9c\x85\x3e\x61\x9c\x85\x3e\x07\xb8\x6b\xbf\x07\xb8\x6b\xbf\x1d\x8e\x6d\xbf\x28\x30\x67\x3e\xeb\xe1\xf0\xbe\xa2\x47\xd4\x3e\xa2\x47\xd4\x3e\xe9\xc8\x3c\xbf\xe9\xc8\x3c\xbf\x38\xae\x3b\x3f\xe7\x7a\x64\x3e\x5d\x05\xc0\xbe\xff\xdb\x09\x3f\xff\xdb\x09\x3f\x55\x3e\x9f\x3e\x55\x3e\x9f\x3e\x8b\x31\xa3\x3e\xe5\xc4\x61\x3e\xcd\xc5\x8e\xbd\x68\xbc\x1f\x3f\x68\xbc\x1f\x3f\x64\x9b\x7e\x3f\x64\x9b\x7e\x3f\xa0\xda\x7e\xbf\x27\x0e\x5f\x3e\xe5\xa6\x8c\x3e\x3c\x3e\x2a\x3f\x3c\x3e\x2a\x3f\x4f\x41\x02\x3f\x4f\x41\x02\x3f\xe2\x83\x00\x3f\xae\x56\x5c\x3e\xdd\x74\xee\x3e\xd1\x86\x28\x3f\xd1\x86\x28\x3f\x27\x71\x13\xbf\x27\x71\x13\xbf\x83\xb1\x15\x3f\x79\x9e\x59\x3e\x12\xb5\xca\x3e\x45\xbf\x1a\x3f\x45\xbf\x1a\x3f\xf7\x74\x7b\xbf\xf7\x74\x7b\xbf\xde\xd8\x7c\xbf\x89\xe5\x56\x3e\xcb\x80\xdc\x3d\x61\xc7\x01\x3f\x61\xc7\x01\x3f\xc2\x2d\x6b\xbe\xc2\x2d\x6b\xbe\xb7\xd3\x6a\x3e\xe3\x2b\x54\x3e\x14\xf6\x75\xbe\xd7\xd2\xbe\x3e\xd7\xd2\xbe\x3e\xbf\x68\x4b\x3f\xbf\x68\x4b\x3f\x11\x24\x4d\x3f\x88\x71\x51\x3e\xfb\x33\xe9\xbe\x04\xcc\x58\x3e\x04\xcc\x58\x3e\x1e\x0f\x61\x3f\x1e\x0f\x61\x3f\xb6\xdf\x63\xbf\x78\xb6\x4e\x3e\x38\x3f\xd6\xbe\x20\xdf\x0f\x3d\x20\xdf\x0f\x3d\xae\x52\x9e\xbd\xae\x52\x9e\xbd\xd3\x3e\x8e\xbd\xb3\xfa\x4b\x3e\x27\xbe\x1a\xbe\xc3\xa0\x13\xbe\xc3\xa0\x13\xbe\x9b\x32\x71\xbf\x9b\x32\x71\xbf\xa3\xb0\x71\x3f\x42\x3e\x49\x3e\x8e\x3f\x4d\x3e\x1f\x6e\xa0\xbe\x1f\x6e\xa0\xbe\x5a\x6b\x30\xbf\x5a\x6b\x30\xbf\xd8\x74\x32\xbf\x22\x81\x46\x3e\x4e\xa9\xe1\x3e\x7d\x9d\xeb\xbe\x7d\x9d\xeb\xbe\x4f\x08\xc4\x3e\x4f\x08\xc4\x3e\x3d\xae\xc2\xbe\x56\xc3\x43\x3e\xfa\x49\xe0\x3e\xb0\xc9\x12\xbf\xb0\xc9\x12\xbf\xaa\xf3\x7f\x3f\xaa\xf3\x7f\x3f\xc6\x07\x81\x3f\xdc\x04\x41\x3e\x26\xcc\x49\x3e\x39\x16\x25\xbf\x39\x16\x25\xbf\xc5\x21\xda\x3e\xc5\x21\xda\x3e\xe7\x26\xe0\xbe\xb8\x45\x3e\x3e\x26\x95\x1b\xbe\x9e\x3c\x2b\xbf\x9e\x3c\x2b\xbf\x47\xe8\x27\xbf\x47\xe8\x27\xbf\xac\xe3\x26\xbf\xeb\x85\x3b\x3e\xe6\xf0\xd5\xbe\x30\xc4\x24\xbf\x30\xc4\x24\xbf\x8e\x8d\x74\xbf\x8e\x8d\x74\xbf\x65\xc0\x75\x3f\x80\xc5\x38\x3e\x76\x87\xe9\xbe\x7e\x35\x12\xbf\x7e\x35\x12\xbf\x09\xaa\xe7\xbd\x09\xaa\xe7\xbd\xf3\x0f\xf1\xbd\x79\x04\x36\x3e\xba\xe8\x7c\xbe\x6a\xb8\xe9\xbe\x6a\xb8\xe9\xbe\x3a\x71\x5d\x3f\x3a\x71\x5d\x3f\xa9\x91\x5d\xbf\xc5\x42\x33\x3e\x51\x61\xc8\x3d\xf2\xd3\x9d\xbe\xf2\xd3\x9d\xbe\xe1\xa0\x4e\x3f\xe1\xa0\x4e\x3f\xda\x16\x4f\x3f\x65\x80\x30\x3e\xfc\xd7\xc6\x3e\xbc\x51\x0c\xbe\xbc\x51\x0c\xbe\x8c\x60\x60\xbe\x8c\x60\x60\xbe\x5b\x88\x62\x3e\x6f\xbd\x2d\x3e\x88\x92\xef\x3e\x59\x2f\x37\x3d\x59\x2f\x37\x3d\x1b\x86\x7b\xbf\x1b\x86\x7b\xbf\x8e\xe9\x7c\xbf\xe4\xf9\x2a\x3e\xbf\x97\x97\x3e\x33\x82\x64\x3e\x33\x82\x64\x3e\x6a\x96\x10\xbf\x6a\x96\x10\xbf\x47\xb1\x11\x3f\xc2\x35\x28\x3e\xac\x48\x14\xbd\x33\x22\xc5\x3e\x33\x22\xc5\x3e\xbe\x77\x08\x3f\xbe\x77\x08\x3f\xc5\x0e\x08\x3f\x09\x71\x25\x3e\xc2\x2e\xb2\xbe\x38\xa6\x04\x3f\x38\xa6\x04\x3f\xf9\x21\x7d\x3f\xf9\x21\x7d\x3f\x00\x1b\x7d\xbf\xb8\xab\x22\x3e\x64\x51\xf2\xbe\xa3\xdf\x1c\x3f\xa3\xdf\x1c\x3f\x29\x99\x80\x3e\x29\x99\x80\x3e\x7b\x0a\x81\x3e\xcc\xe5\x1f\x3e\x56\xb8\xb0\xbe\x77\x7b\x29\x3f\x77\x7b\x29\x3f\x5f\x3c\x4a\xbf\x5f\x3c\x4a\xbf\x02\x2d\x4a\x3f\x51\x1f\x1d\x3e\x30\x41\xfa\xbc\xb3\x6e\x29\x3f\xb3\x6e\x29\x3f\xc7\x2a\x60\xbf\xc7\x2a\x60\xbf\x08\x30\x61\xbf\x46\x58\x1a\x3e\x12\xca\x98\x3e\x49\xab\x1c\x3f\x49\xab\x1c\x3f\x67\x5d\xca\x3d\x67\x5d\xca\x3d\x94\xdb\xb8\xbd\xae\x90\x17\x3e\x15\xa4\xef\x3e\x72\x0f\x04\x3f\x72\x0f\x04\x3f\xb1\x20\x74\x3f\xb1\x20\x74\x3f\x39\x90\x72\x3f\x8a\xc8\x14\x3e\xe7\x4a\xc7\x3e\x18\xde\xc2\x3e\x18\xde\xc2\x3e\x0d\xba\x26\x3f\x0d\xba\x26\x3f\xcb\x14\x28\xbf\xe0\xff\x11\x3e\x87\x45\xd3\x3d\x1b\xce\x5d\x3e\x1b\xce\x5d\x3e\x98\x77\xe2\xbe\x98\x77\xe2\xbe\x32\xa6\xda\xbe\xb0\x36\x0f\x3e\xd5\xf8\x71\xbe\x91\x54\x14\x3d\x91\x54\x14\x3d\x39\x77\x7f\xbf\x39\x77\x7f\xbf\x36\x9c\x7c\x3f\xfa\x6c\x0c\x3e\xfd\x5c\xe7\xbe\xb4\x89\x16\xbe\xb4\x89\x16\xbe\xdd\x6e\xad\xbe\xdd\x6e\xad\xbe\x51\xba\xaf\xbe\xc0\xa2\x09\x3e\xc6\x70\xdb\xbe\xc2\x82\xa3\xbe\xc2\x82\xa3\xbe\x75\xbb\x3b\x3f\x75\xbb\x3b\x3f\xda\xda\x37\xbf\x05\xd8\x06\x3e\x64\x10\x36\xbe\xd4\x81\xef\xbe\xd4\x81\xef\xbe\x73\x35\x69\x3f\x73\x35\x69\x3f\x4d\xf8\x66\x3f\xcb\x0c\x04\x3e\x92\x1c\x29\x3e\x3b\xab\x14\xbf\x3b\xab\x14\xbf\xbe\xe2\xc7\xbc\xbe\xe2\xc7\xbc\xc0\x99\x7d\x3c\x13\x41\x01\x3e\x0b\xcf\xd7\x3e\x89\x3c\x26\xbf\x89\x3c\x26\xbf\x8a\x2d\x6e\xbf\x8a\x2d\x6e\xbf\x4a\x3d\x69\xbf\xbc\xe9\xfc\x3d\xa4\xba\xe9\x3e\xe9\x12\x2b\xbf\xe9\x12\x2b\xbf\xc9\x7c\x32\xbf\xc9\x7c\x32\xbf\xac\x7f\x2f\x3f\x62\x50\xf7\x3d\x23\x1e\x81\x3e\x39\xc8\x22\xbf\x39\xc8\x22\xbf\x12\x2f\xc8\x3e\x12\x2f\xc8\x3e\x7c\x98\xc5\x3e\x19\xb6\xf1\x3d\xd0\x84\xa9\xbd\xea\xff\x0d\xbf\xea\xff\x0d\xbf\x32\xf4\x7f\x3f\x32\xf4\x7f\x3f\xac\x5c\x7c\xbf\xea\x1a\xec\x3d\xf2\x4e\xc0\xbe\xf7\x93\xdc\xbe\xf7\x93\xdc\xbe\xcd\x8a\xc2\x3e\xcd\x8a\xc2\x3e\x5a\x25\xbe\x3e\xd5\x7e\xe6\x3d\x0a\xc6\xf1\xbe\xd0\x22\x8c\xbe\xd0\x22\x8c\xbe\xa8\x3c\x35\xbf\xa8\x3c\x35\xbf\xa7\x9c\x34\x3f\xbe\xfa\xe0\x3d\xc3\x16\xa5\xbe\x98\x3d\xc3\xbd\x98\x3d\xc3\xbd\x57\x84\x6c\xbf\x57\x84\x6c\xbf\xfc\xbd\x6a\xbf\xa7\x8e\xdb\x3d\x65\xa3\xd2\xbb\x63\xb0\xb9\x3d\x63\xb0\xb9\x3d\x53\x0a\x87\xb9\x53\x0a\x87\xb9\x57\x24\x69\xbb\x9e\xc7\xd5\x3d\xfe\x42\xa0\x3e\xac\x23\x8a\x3e\xac\x23\x8a\x3e\xde\x7b\x6c\x3f\xde\x7b\x6c\x3f\xa4\x60\x6c\x3f\xa6\xa5\xcf\x3d\x24\xac\xf0\x3e\x6b\x37\xdb\x3e\x6b\x37\xdb\x3e\x92\xc1\x34\x3f\x92\xc1\x34\x3f\x6c\xf9\x33\xbf\x0a\xdc\xc9\x3d\x88\xe4\xc4\x3e\x92\xa6\x0d\x3f\x92\xa6\x0d\x3f\x79\x60\xc5\xbe\x79\x60\xc5\xbe\x98\x0f\xc8\xbe\xcd\x6a\xc4\x3d\x43\x55\xd0\x3d\x81\xa9\x22\x3f\x81\xa9\x22\x3f\x72\xee\x7f\xbf\x72\xee\x7f\xbf\x65\xbd\x80\x3f\x6f\xe0\xbe\x3d\x9f\xec\x6f\xbe\x2e\x00\x2b\x3f\x2e\x00\x2b\x3f\x33\x71\xbf\xbe\x33\x71\xbf\xbe\xe2\xcc\xc0\xbe\xf2\x3c\xb9\x3d\x53\x1b\xe6\xbe\x72\xfb\x25\x3f\x72\xfb\x25\x3f\x1e\x6b\x37\x3f\x1e\x6b\x37\x3f\xb0\x4d\x38\xbf\x7a\x98\xb3\x3d\xcd\xf3\xdd\xbe\x31\xf6\x13\x3f\x31\xf6\x13\x3f\xeb\xa0\x6a\x3f\xeb\xa0\x6a\x3f\x74\x08\x6c\x3f\x08\xf3\xad\x3d\x52\x30\x49\xbe\x5f\xa5\xec\x3e\x5f\xa5\xec\x3e\x59\xe4\xc6\xbc\x59\xe4\xc6\xbc\xc6\x5e\xbe\x3c\xa6\x4c\xa8\x3d\x52\x64\x10\x3e\x52\xac\x9e\x3e\x52\xac\x9e\x3e\xe1\x7f\x6f\xbf\xe1\x7f\x6f\xbf\xb3\x5f\x70\xbf\x55\xa5\xa2\x3d\x0c\xca\xcf\x3e\x34\x2d\x08\x3e\x34\x2d\x08\x3e\xba\x0c\x2e\xbf\xba\x0c\x2e\xbf\xf1\x9d\x2e\x3f\x21\xfd\x9c\x3d\xd0\xb3\xed\x3e\x0c\x1f\x60\xbd\x0c\x1f\x60\xbd\xf0\xd2\xd9\x3e\xf0\xd2\xd9\x3e\xce\xd9\xda\x3e\x0c\x54\x97\x3d\x13\x2e\x93\x3e\x05\x09\x74\xbe\x05\x09\x74\xbe\x7d\xc4\x7f\x3f\x7d\xc4\x7f\x3f\x54\x49\x80\xbf\x17\xaa\x91\x3d\x75\xe2\x12\xbd\x34\x63\xce\xbe\x34\x63\xce\xbe\x87\xde\xa4\x3e\x87\xde\xa4\x3e\x5c\x08\xa5\x3e\x43\xff\x8b\x3d\x84\x4b\xae\xbe\x25\x33\x09\xbf\x25\x33\x09\xbf\xd8\x40\x42\xbf\xd8\x40\x42\xbf\x0d\x96\x42\x3f\x9c\x53\x86\x3d\xe8\xfd\xf1\xbe\x71\x4e\x20\xbf\x71\x4e\x20\xbf\x0c\x3c\x63\xbf\x0c\x3c\x63\xbf\x38\xed\x62\xbf\x21\xa7\x80\x3d\xac\xc3\xbb\xbe\x7e\xa9\x2a\xbf\x7e\xa9\x2a\xbf\x2d\xc4\xc9\x3d\x2d\xc4\xc9\x3d\xd4\x0d\xd2\xbd\xaf\xf3\x75\x3d\x45\x96\x9b\xbd\x91\x6d\x27\xbf\x91\x6d\x27\xbf\x86\xed\x75\x3f\x86\xed\x75\x3f\x38\x9c\x76\x3f\x7c\x97\x6a\x3d\x1a\x2c\x81\x3e\x9e\xcb\x16\xbf\x9e\xcb\x16\xbf\xc6\x08\x1d\x3f\xc6\x08\x1d\x3f\xdf\x7a\x1c\xbf\xc2\x39\x5f\x3d\xfc\x8a\xe8\x3e\x74\x1a\xf4\xbe\x74\x1a\xf4\xbe\x33\xb5\x01\xbf\x33\xb5\x01\xbf\xc5\x08\x03\xbf\x82\xda\x53\x3d\x0d\x8e\xdb\x3e\xed\xe8\xa6\xbe\xed\xe8\xa6\xbe\xc5\xd1\x7c\xbf\xc5\xd1\x7c\xbf\xa9\x7b\x7d\x3f\xca\x79\x48\x3d\x7f\x01\x41\x3e\x44\x59\x18\xbe\x44\x59\x18\xbe\x5a\x9e\x62\xbe\x5a\x9e\x62\xbe\x51\xb5\x5f\xbe\x9d\x17\x3d\x3d\xbe\xcb\x14\xbe\x40\xdb\x25\x3d\x40\xdb\x25\x3d\xe9\x32\x53\x3f\xe9\x32\x53\x3f\xc4\x6a\x54\xbf\x22\xb4\x31\x3d\x71\x1d\xd0\xbe\x1c\x0a\x68\x3e\x1c\x0a\x68\x3e\xd2\xc6\x53\x3f\xd2\xc6\x53\x3f\xe4\x03\x54\x3f\x58\x4f\x26\x3d\x7c\x4d\xee\xbe\x28\xfa\xc9\x3e\x28\xfa\xc9\x3e\x68\x33\x60\xbe\x68\x33\x60\xbe\x64\xca\x64\x3e\x37\xe9\x1a\x3d\x60\x3c\x96\xbe\x48\xd5\x07\x3f\x48\xd5\x07\x3f\x39\xe1\x7c\xbf\x39\xe1\x7c\xbf\x9b\x66\x7e\xbf\xbe\x81\x0f\x3d\xce\xec\xbd\x3c\x47\xb4\x1f\x3f\x47\xb4\x1f\x3f\x4e\x94\x00\xbf\x4e\x94\x00\xbf\xc7\x32\x01\x3f\xec\x18\x04\x3d\x59\x35\xa8\x3e\xd8\x98\x2a\x3f\xd8\x98\x2a\x3f\xb7\x53\x1f\x3f\xb7\x53\x1f\x3f\xec\xe7\x1f\x3f\x82\x5d\xf1\x3c\xb7\x81\xf1\x3e\x27\x95\x27\x3f\x27\x95\x27\x3f\xfc\x87\x74\x3f\xfc\x87\x74\x3f\xbe\xa3\x75\xbf\x2b\x87\xda\x3c\xee\xb5\xc3\x3e\xd8\xdc\x16\x3f\xd8\xdc\x16\x3f\x93\x53\x90\x3d\x93\x53\x90\x3d\x78\x40\x96\x3d\xd4\xae\xc3\x3c\xa1\x52\xd7\x3d\x31\x8c\xf3\x3e\x31\x8c\xf3\x3e\xa4\x95\x67\xbf\xa4\x95\x67\xbf\xf8\xd6\x67\x3f\x18\xd4\xac\x3c\x8d\xd6\x64\xbe\xa0\x63\xa5\x3e\xa0\x63\xa5\x3e\xe6\x6a\x39\xbf\xe6\x6a\x39\xbf\xc5\x8e\x3a\xbf\xf7\xf6\x95\x3c\x17\x6a\xe2\xbe\xcf\x30\x13\x3e\xcf\x30\x13\x3e\x7e\xdb\xc3\x3e\x7e\xdb\xc3\x3e\x8e\xeb\xc1\xbe\xa7\x2f\x7e\x3c\x74\xac\xe3\xbe\x49\x96\x42\xbd\x49\x96\x42\xbd\x5f\xfa\x7f\x3f\x5f\xfa\x7f\x3f\x1d\x28\x80\x3f\x5a\x6d\x50\x3c\x76\xd0\x6b\xbe\x99\xa9\x70\xbe\x99\xa9\x70\xbe\x99\xdb\xab\x3e\x99\xdb\xab\x3e\x32\xfa\xae\xbe\x3f\xa7\x22\x3c\x59\x30\xc5\x3d\xd7\x88\xce\xbe\xd7\x88\xce\xbe\xcb\x75\x42\xbf\xcb\x75\x42\xbf\x00\x12\x41\xbf\xb0\xba\xe9\x3b\x9e\x65\xc0\x3e\x45\xdd\x09\xbf\x45\xdd\x09\xbf\x58\x12\x61\xbf\x58\x12\x61\xbf\x6b\x20\x61\x3f\xa2\x1f\x8e\x3b\x7f\xf8\xf1\x3e\x5c\x0f\x21\xbf\x5c\x0f\x21\xbf\x39\x2e\x07\x3e\x39\x2e\x07\x3e\xd8\x32\x02\x3e\x4e\xf5\xc9\x3a\xcc\x3e\xae\x3e\x44\xe3\x2a\xbf\x44\xe3\x2a\xbf\x8f\x2e\x79\x3f\x8f\x2e\x79\x3f\x7f\x27\x78\xbf\xae\xad\xa4\xba\x36\xd6\x32\x3d\x5e\x7d\x26\xbf\x5e\x7d\x26\xbf\xc4\x6d\x0f\x3f\xc4\x6d\x0f\x3f\xfa\xa0\x0f\x3f\x9b\xda\x84\xbb\x85\x35\x8c\xbe\x7b\x37\x14\xbf\x7b\x37\x14\xbf\xd7\x6a\x13\xbf\xd7\x6a\x13\xbf\x09\x31\x12\x3f\xf4\x8f\xe0\xbb\x45\x16\xeb\xbe\xe4\x19\xeb\xbe\xe4\x19\xeb\xbe\xfd\xe2\x77\xbf\xfd\xe2\x77\xbf\x2f\xc3\x76\xbf\xbb\x25\x1e\xbc\x86\xd2\xd8\xbe\xfc\x0a\x9a\xbe\xfc\x0a\x9a\xbe\xb4\x3e\xde\xbd\xb4\x3e\xde\xbd\x87\x00\xdf\x3d\x31\x06\x4c\xbc\x55\xf8\x3c\xbe\xe9\xf5\xef\xbd\xe9\xf5\xef\xbd\xa2\x53\x64\x3f\xa2\x53\x64\x3f\x28\x0a\x63\x3f\x5b\xe9\x79\xbc\xb5\x34\x12\x3e\x73\xdb\x9c\x3d\x73\xdb\x9c\x3d\xe5\x89\x3c\x3f\xe5\x89\x3c\x3f\x7a\x51\x3b\xbf\x89\xe7\x93\xbc\xf3\x7e\xcd\x3e\x59\x36\x87\x3e\x59\x36\x87\x3e\x85\xc4\xbf\xbe\x85\xc4\xbf\xbe\x1b\xbe\xbf\xbe\xaa\xdb\xaa\xbc\xbe\xa8\xef\x3e\x00\xe2\xdb\x3e\x00\xe2\xdb\x3e\x8f\xd8\x7f\xbf\x8f\xd8\x7f\xbf\x50\xcd\x7e\x3f\xde\xd0\xc1\xbc\xe3\xa4\x9f\x3e\x8b\x06\x0f\x3f\x8b\x06\x0f\x3f\x5c\x4b\xa6\xbe\x5c\x4b\xa6\xbe\x9a\xc7\xa4\xbe\x25\xc7\xd8\xbc\xda\x40\xeb\x3b\x58\x06\x24\x3f\x58\x06\x24\x3f\x4e\xe0\x45\x3f\x4e\xe0\x45\x3f\x5e\x85\x45\xbf\x57\xbe\xef\xbc\xba\xd9\x99\xbe\x8d\x23\x2b\x3f\x8d\x23\x2b\x3f\x9c\x16\x5d\x3f\x9c\x16\x5d\x3f\xa2\x27\x5c\x3f\x3a\x5b\x03\xbd\xb4\x64\xee\xbe\x88\xb8\x23\x3f\x88\xb8\x23\x3f\xe2\x90\x30\xbe\xe2\x90\x30\xbe\xfb\xd6\x32\x3e\xb6\xd7\x0e\xbd\x03\x17\xd2\xbe\xc2\x5a\x0e\x3f\xc2\x5a\x0e\x3f\xc0\xca\x7b\xbf\xc0\xca\x7b\xbf\x04\xa4\x7b\xbf\xa0\x54\x1a\xbd\x32\xe6\x24\xbe\xe6\xa8\xd9\x3e\xe6\xa8\xd9\x3e\x6c\x4e\x02\xbf\x6c\x4e\x02\xbf\xcc\xb0\x01\x3f\xe7\xd1\x25\xbd\xfe\xb9\x27\x3e\x91\xef\x83\x3e\x91\xef\x83\x3e\xaf\xcc\x21\x3f\xaf\xcc\x21\x3f\xa6\x41\x22\x3f\x8e\x4f\x31\xbd\x9c\xaa\xd2\x3e\xa4\x55\x8b\x3d\xa4\x55\x8b\x3d\xa3\xfa\x71\x3f\xa3\xfa\x71\x3f\x15\xc6\x71\xbf\x6a\xcd\x3c\xbd\x45\x5e\xee\x3e\x97\xad\x02\xbe\x97\xad\x02\xbe\x08\x41\x96\x3c\x08\x41\x96\x3c\x42\xfc\x80\x3c\x7a\x4b\x48\xbd\xb5\x2a\x9a\x3e\xe4\xfc\x9f\xbe\xe4\xfc\x9f\xbe\x2b\xd3\x6e\xbf\x2b\xd3\x6e\xbf\xfd\x20\x6f\x3f\xcb\xc9\x53\xbd\x64\x1a\x7f\xbb\xd4\xed\xf0\xbe\xd4\xed\xf0\xbe\xc5\x60\x28\xbf\xc5\x60\x28\xbf\xaa\xca\x27\xbf\x5b\x48\x5f\xbd\x9d\x30\x9d\xbe\xef\x93\x16\xbf\xef\x93\x16\xbf\x34\x86\xf7\x3e\x34\x86\xf7\x3e\xe5\x41\xf9\xbe\x06\xc7\x6a\xbd\xbb\xe3\xee\xbe\x12\xb6\x27\xbf\x12\xb6\x27\xbf\x4a\xea\x7c\x3f\x4a\xea\x7c\x3f\x6f\xf8\x7c\x3f\xce\x45\x76\xbd\x9c\x52\xd1\xbe\x17\x58\x2a\xbf\x17\x58\x2a\xbf\x07\x7a\x41\x3e\x07\x7a\x41\x3e\x20\x3e\x3e\xbe\x51\xe2\x80\xbd\x13\x3b\x25\xbe\xa2\x36\x1e\xbf\xa2\x36\x1e\xbf\xec\x24\x5c\xbf\xec\x24\x5c\xbf\x98\xe4\x5c\xbf\xc3\xa1\x86\xbd\xc9\xe9\x24\x3e\xfc\x51\x04\xbf\xfc\x51\x04\xbf\x91\x97\x45\xbf\x91\x97\x45\xbf\x13\x9f\x45\x3f\x34\x61\x8c\xbd\xf5\x26\xd1\x3e\x8f\xbd\xbd\xbe\x8f\xbd\xbd\xbe\x82\xf5\xac\x3e\x82\xf5\xac\x3e\xe4\x3e\xae\x3e\xa3\x20\x92\xbd\x10\x10\xef\x3e\x36\x70\x44\xbe\x36\x70\x44\xbe\x13\xfc\x7f\x3f\x13\xfc\x7f\x3f\x66\x67\x80\xbf\x09\xe0\x97\xbd\xca\xb3\x9e\x3e\xdd\xf7\x78\x3b\xdd\xf7\x78\x3b\xb7\x0c\xac\x3e\xb7\x0c\xac\x3e\xe0\xd9\xac\x3e\x66\x9f\x9d\xbd\xaa\x57\x29\x3c\x5d\x1c\x4c\x3e\x5d\x1c\x4c\x3e\x86\x25\x46\xbf\x86\x25\x46\xbf\xa6\x96\x46\x3f\xae\x5e\xa3\xbd\x51\x57\x96\xbe\x3d\x49\xc1\x3e\x3d\x49\xc1\x3e\x06\xfe\x5a\xbf\x06\xfe\x5a\xbf\x53\x24\x5c\xbf\xe1\x1d\xa9\xbd\xca\xeb\xec\xbe\x80\xcf\x05\x3f\x80\xcf\x05\x3f\xbc\xf3\x4d\x3e\xbc\xf3\x4d\x3e\x9a\x8f\x4a\xbe\xf8\xdc\xae\xbd\x16\xff\xd6\xbe\x4b\x3c\x1f\x3f\x4b\x3c\x1f\x3f\x22\x69\x7d\x3f\x22\x69\x7d\x3f\x8a\xeb\x7d\x3f\xf3\x9b\xb4\xbd\xb6\x5c\x3d\xbe\x5a\xa4\x2a\x3f\x5a\xa4\x2a\x3f\x28\x13\xeb\x3e\x28\x13\xeb\x3e\xb5\x2f\xee\xbe\xc9\x5a\xba\xbd\x89\x58\x09\x3e\x91\xfa\x26\x3f\x91\xfa\x26\x3f\xff\x49\x2f\xbf\xff\x49\x2f\xbf\x41\x2e\x2e\xbf\x7a\x19\xc0\xbd\x98\xa1\xc8\x3e\x69\x84\x14\x3f\x69\x84\x14\x3f\x80\x03\x6a\xbf\x80\x03\x6a\xbf\x1c\x74\x6a\x3f\x00\xd8\xc5\xbd\x7c\x4b\xf1\x3e\x2f\xb8\xe9\x3e\x2f\xb8\xe9\x3e\xb3\x1c\xa3\x3d\xb3\x1c\xa3\x3d\x4d\x11\x97\x3d\x58\x96\xcb\xbd\x2e\x57\xac\x3e\x42\x91\x95\x3e\x42\x91\x95\x3e\x3c\x9f\x77\x3f\x3c\x9f\x77\x3f\x63\xbc\x76\xbf\x74\x54\xd1\xbd\x7a\x80\x4b\x3d\x07\x14\xd0\x3d\x07\x14\xd0\x3d\x1c\xdc\x0e\x3f\x1c\xdc\x0e\x3f\xd7\x8e\x0f\x3f\x52\x12\xd7\xbd\x38\xf7\x84\xbe\x85\xf8\xc8\xbd\x85\xf8\xc8\xbd\x61\xbe\x19\xbf\x61\xbe\x19\xbf\xf6\x59\x18\x3f\xf6\xcf\xdc\xbd\x9f\x34\xe7\xbe\xcd\x1b\x94\xbe\xcd\x1b\x94\xbe\xe5\xd5\x73\xbf\xe5\xd5\x73\xbf\xea\x44\x73\xbf\x5f\x8d\xe2\xbd\x36\x0b\xe1\xbe\x9b\xce\xe8\xbe\x9b\xce\xe8\xbe\x09\x2f\xbc\xbc\x09\x2f\xbc\xbc\x6f\xbb\xd0\x3c\x7a\x4a\xe8\xbd\xe9\x87\x6b\xbe\x6e\x59\x14\xbf\x6e\x59\x14\xbf\x32\x0c\x70\x3f\x32\x0c\x70\x3f\x97\x2d\x6f\x3f\x48\x07\xee\xbd\x8b\x37\xa9\x3d\xcc\xfd\x26\xbf\xcc\xfd\x26\xbf\x0f\x59\x22\x3f\x0f\x59\x22\x3f\x36\x2b\x22\xbf\xc0\xc3\xf3\xbd\xb4\x38\xb7\x3e\x22\x9a\x2a\xbf\x22\x9a\x2a\xbf\xcc\x6b\x06\xbf\xcc\x6b\x06\xbf\x03\x2b\x06\xbf\xe3\x7f\xf9\xbd\x47\x1d\xf2\x3e\x13\xd1\x1e\xbf\x13\xd1\x1e\xbf\x96\x97\x79\xbf\x96\x97\x79\xbf\xb9\x82\x79\x3f\xaa\x3b\xff\xbd\x34\xfe\xc0\x3e\xc4\xab\x04\xbf\xc4\xab\x04\xbf\x1b\x57\xda\xbd\x1b\x57\xda\xbd\x27\xce\xda\xbd\x8a\x7b\x02\xbe\xe7\xfb\xe6\x3d\x00\xfc\xbc\xbe\x00\xfc\xbc\xbe\x54\xfc\x67\x3f\x54\xfc\x67\x3f\x9d\xf4\x67\xbf\x0d\x59\x05\xbe\x37\x21\x4e\xbe\x84\xe3\x3e\xbe\x84\xe3\x3e\xbe\x86\xf3\x30\x3f\x86\xf3\x30\x3f\xab\xcb\x30\x3f\x5d\x36\x08\xbe\xd9\xf6\xd9\xbe\x86\x63\x5b\x3c\x86\x63\x5b\x3c\x51\x55\xec\xbe\x51\x55\xec\xbe\x12\xf9\xec\x3e\x74\x13\x0b\xbe\xaf\x29\xec\xbe\xfe\x4b\x59\x3e\xfe\x4b\x59\x3e\x12\xe4\x7c\xbf\x12\xe4\x7c\xbf\x52\x06\x7d\xbf\x53\xf0\x0d\xbe\x47\xcc\x95\xbe\xc1\xa0\xc8\x3e\xc1\xa0\xc8\x3e\x97\x5e\x2f\xbe\x97\x5e\x2f\xbe\x54\x6b\x2e\x3e\xf5\xcc\x10\xbe\x25\x61\xa3\x3b\xc1\x2e\x09\x3f\xc1\x2e\x09\x3f\x77\xfa\x60\x3f\x77\xfa\x60\x3f\xe3\x15\x61\x3f\x5a\xa9\x13\xbe\x25\xbd\x99\x3e\xcf\x82\x21\x3f\xcf\x82\x21\x3f\x8a\x5f\x3b\x3f\x8a\x5f\x3b\x3f\x93\xf9\x3a\xbf\x7d\x85\x16\xbe\x0a\x2c\xed\x3e\x2f\x09\x2b\x3f\x2f\x09\x2b\x3f\xeb\xca\xd3\xbe\xeb\xca\xd3\xbe\x52\x5b\xd4\xbe\x5c\x61\x19\xbe\x99\x40\xd8\x3e\xff\xda\x24\x3f\xff\xda\x24\x3f\xb9\xab\x7e\xbf\xb9\xab\x7e\xbf\xbf\x36\x7e\x3f\xf6\x3c\x1c\xbe\xef\x26\x49\x3e\x26\x7c\x0f\x3f\x26\x7c\x0f\x3f\xbf\x1d\x5d\xbe\xbf\x1d\x5d\xbe\xde\x46\x5a\xbe\x4b\x18\x1f\xbe\x0c\x23\xec\xbd\xef\xb8\xd9\x3e\xef\xb8\xd9\x3e\xf7\xd2\x5b\x3f\xf7\xd2\x5b\x3f\xe4\xf0\x5b\xbf\x53\xf3\x21\xbe\x3e\xac\xc0\xbe\xdc\x44\x80\x3e\xdc\x44\x80\x3e\xb2\xcd\x41\x3f\xb2\xcd\x41\x3f\x12\x56\x41\x3f\x0f\xce\x24\xbe\x0d\x34\xf2\xbe\xaf\x95\x56\x3d\xaf\x95\x56\x3d\x09\x13\xc4\xbe\x09\x13\xc4\xbe\x47\xb0\xc4\x3e\x7b\xa8\x27\xbe\xe1\x5d\xba\xbe\x49\x67\x1a\xbe\x49\x67\x1a\xbe\x6c\x54\x7f\xbf\x6c\x54\x7f\xbf\xb2\x18\x7f\xbf\x97\x82\x2a\xbe\x5e\xf3\xc5\xbd\x18\x28\xae\xbe\x18\x28\xae\xbe\x79\xce\x76\xbe\x79\xce\x76\xbe\xf6\x04\x75\x3e\x60\x5c\x2d\xbe\x1a\x86\x59\x3e\xec\xf2\xfe\xbe\xec\xf2\xfe\xbe\x2d\xd2\x58\x3f\x2d\xd2\x58\x3f\xcd\x29\x59\x3f\xd6\x35\x30\xbe\x29\xbf\xdb\x3e\x3a\x00\x1c\xbf\x3a\x00\x1c\xbf\x5a\xc0\x44\x3f\x5a\xc0\x44\x3f\x8e\xe6\x44\xbf\xec\x0e\x33\xbe\xc1\xb1\xeb\x3e\x61\xf8\x29\xbf\x61\xf8\x29\xbf\xc0\x06\xbd\xbe\xc0\x06\xbd\xbe\x31\x59\xbd\xbe\xa0\xe7\x35\xbe\x85\xed\x95\x3e\x54\x07\x28\xbf\x54\x07\x28\xbf\xc8\x5e\x7f\xbf\xc8\x5e\x7f\xbf\xf8\xbd\x7f\x3f\x00\xc0\x38\xbe\xad\xca\xe3\xb9\x03\x53\x16\xbf\x03\x53\x16\xbf\x51\x11\x7e\xbe\x51\x11\x7e\xbe\xb8\xe8\x7e\xbe\x09\x98\x3b\xbe\x49\x32\x96\xbe\x57\xed\xec\xbe\x57\xed\xec\xbe\x40\x2d\x58\x3f\x40\x2d\x58\x3f\x2f\x43\x58\xbf\xa9\x6f\x3e\xbe\x89\xb5\xeb\xbe\xa8\xcf\x96\xbe\xa8\xcf\x96\xbe\xed\xac\x44\x3f\xed\xac\x44\x3f\x12\xce\x44\x3f\xdf\x46\x41\xbe\xad\x1e\xdc\xbe\x71\x96\xc9\xbd\x71\x96\xc9\xbd\x08\xad\xbe\xbe\x08\xad\xbe\xbe\x9d\xb7\xbe\x3e\xa8\x1d\x44\xbe\xf3\xfa\x5c\xbe\x58\x78\xdb\x3d\x58\x78\xdb\x3d\xd8\x29\x7f\xbf\xd8\x29\x7f\xbf\xe0\x35\x7f\xbf\x05\xf4\x46\xbe\xb8\xd7\xb8\x3d\xb5\x02\x9b\x3e\xb5\x02\x9b\x3e\x2b\xdd\x72\xbe\x2b\xdd\x72\xbe\x58\x04\x73\x3e\xf8\xc9\x49\xbe\x63\x14\xb7\x3e\xb8\x88\xf0\x3e\xb8\x88\xf0\x3e\xfc\x38\x5a\x3f\xfc\x38\x5a\x3f\x7f\xf3\x59\x3f\x80\x9f\x4c\xbe\x06\xf8\xf1\x3e\xf1\xa4\x17\x3f\xf1\xa4\x17\x3f\x02\x94\x41\x3f\x02\x94\x41\x3f\xa7\x29\x41\xbf\x95\x74\x4f\xbe\xc7\x40\xc6\x3e\x4c\x9b\x28\x3f\x4c\x9b\x28\x3f\x1a\x9f\xc9\xbe\x1a\x9f\xc9\xbe\x59\xbc\xc9\xbe\x36\x49\x52\xbe\xdb\xff\x0c\x3e\xf5\x7e\x29\x3f\xf5\x7e\x29\x3f\x17\xbd\x7e\xbf\x17\xbd\x7e\xbf\x6b\x5f\x7e\x3f\x5c\x1d\x55\xbe\x5a\xf2\x2d\xbe\xe2\x2b\x1a\x3f\xe2\x2b\x1a\x3f\xcc\x26\x54\xbe\xcc\x26\x54\xbe\x39\x2e\x53\xbe\x08\xf1\x57\xbe\xca\x8c\xcf\xbe\x8c\x1c\xf8\x3e\x8c\x1c\xf8\x3e\x60\xe8\x5e\x3f\x60\xe8\x5e\x3f\x8c\xb8\x5e\xbf\x34\xc4\x5a\xbe\x20\x9e\xf0\xbe\xc0\x04\xa4\x3e\xc0\x04\xa4\x3e\xa3\x12\x3b\x3f\xa3\x12\x3b\x3f\x79\xd2\x3a\x3f\xdf\x96\x5d\xbe\x7c\x6d\xac\xbe\x14\x29\x00\x3e\x14\x29\x00\x3e\x05\xac\xdd\xbe\x05\xac\xdd\xbe\xd5\x79\xdd\x3e\x08\x69\x60\xbe\x33\x11\x80\xbd\xe7\x7a\xa8\xbd\xe7\x7a\xa8\xbd\xef\x70\x7d\xbf\xef\x70\x7d\xbf\x74\x27\x7d\xbf\xae\x3a\x63\xbe\xce\x6c\x73\x3e\x52\x5c\x90\xbe\x52\x5c\x90\xbe\x31\x4f\x21\xbe\x31\x4f\x21\xbe\x59\xe2\x20\x3e\xca\x0b\x66\xbe\x3f\x85\xe0\x3e\xe5\xc0\xe8\xbe\xe5\xc0\xe8\xbe\x37\x82\x65\x3f\x37\x82\x65\x3f\x61\x6e\x65\x3f\x5d\xdc\x68\xbe\x42\x72\xe9\x3e\x75\x56\x15\xbf\x75\x56\x15\xbf\x48\x92\x30\x3f\x48\x92\x30\x3f\xe5\x87\x30\xbf\x62\xac\x6b\xbe\xbb\x19\x91\x3e\x4d\xd4\x27\xbf\x4d\xd4\x27\xbf\xbd\x02\xfa\xbe\xbd\x02\xfa\xbe\x3f\xdd\xf9\xbe\xdc\x7b\x6e\xbe\x5e\xc0\xe2\xbb\x75\x03\x2a\xbf\x75\x03\x2a\xbf\x36\x6d\x7a\xbf\x36\x6d\x7a\xbf\x76\x4f\x7a\x3f\xc2\x4a\x71\xbe\xd8\x95\x96\xbe\x8e\xa1\x1b\xbf\x8e\xa1\x1b\xbf\x6c\x15\xb4\xbd\x6c\x15\xb4\xbd\xb5\x1f\xb3\xbd\x14\x19\x74\xbe\xb3\x0c\xeb\xbe\x4e\x17\xfc\xbe\x4e\x17\xfc\xbe\x8e\x33\x6d\x3f\x8e\x33\x6d\x3f\x7c\x54\x6d\xbf\xce\xe6\x76\xbe\x3c\x4f\xde\xbe\x44\x35\xa8\xbe\x44\x35\xa8\xbe\x80\x90\x21\x3f\x80\x90\x21\x3f\x25\x95\x21\x3f\xec\xb3\x79\xbe\x35\x86\x6b\xbe\xcd\x88\x07\xbe\xcd\x88\x07\xbe\xa5\xad\x0e\xbf\xa5\xad\x0e\xbf\xf9\xee\x0e\x3f\xaf\x74\x7c\xbe\xb5\x18\x8d\x3d\x06\xa4\x9d\x3d\x06\xa4\x9d\x3d\x51\xc9\x74\xbf\x51\xc9\x74\xbf\x6a\x28\x75\xbf\x15\x29\x7f\xbe\x0c\x9f\xad\x3e\x91\xcf\x8e\x3e\x91\xcf\x8e\x3e\x50\x1a\x19\x3a\x50\x1a\x19\x3a\x9d\x9f\xd9\xb9\xf7\x01\x81\xbe\x5b\x98\xf0\x3e\x9b\x3f\xe8\x3e\x9b\x3f\xe8\x3e\x4f\xd2\x74\x3f\x4f\xd2\x74\x3f\x5d\x39\x75\x3f\x9d\x82\x82\xbe\xaa\xda\xd0\x3e\x0b\x69\x15\x3f\x0b\x69\x15\x3f\x18\xb8\x0d\x3f\x18\xb8\x0d\x3f\xea\x0c\x0e\xbf\xcf\xf0\x83\xbe\x38\x6e\x37\x3e\xc2\xf2\x27\x3f\xc2\xf2\x27\x3f\xdf\xe0\x22\xbf\xdf\xe0\x22\xbf\x9d\x14\x23\xbf\x8c\x4c\x85\xbe\xb8\xfd\xfa\xbd\xde\xdb\x29\x3f\xde\xdb\x29\x3f\x44\xaf\x6b\xbf\x44\xaf\x6b\xbf\x46\x21\x6c\x3f\x6b\xac\x86\xbe\x2f\x95\xbf\xbe\x6c\xe8\x1a\x3f\x6c\xe8\x1a\x3f\x81\xb0\xda\x3d\x81\xb0\xda\x3d\xa5\x6f\xd9\x3d\x6c\x10\x88\xbe\xc3\x4d\xf2\xbe\xa8\x13\xf9\x3e\xa8\x13\xf9\x3e\x59\x81\x7b\x3f\x59\x81\x7b\x3f\xbd\x9c\x7b\xbf\x1f\x74\x89\xbe\x4f\x89\xc2\xbe\xa9\x77\xa3\x3e\xa9\x77\xa3\x3e\x29\x29\xe9\x3e\x29\x29\xe9\x3e\x0d\x4a\xe9\x3e\x85\xd7\x8a\xbe\x4c\xed\x07\xbe\xa2\xe0\xf5\x3d\xa2\xe0\xf5\x3d\xd2\x2e\x39\xbf\xd2\x2e\x39\xbf\x9d\x1f\x39\x3f\x9a\x3a\x8c\xbe\x90\x0e\x2c\x3e\xa7\x16\xbb\xbd\xa7\x16\xbb\xbd\x8d\x13\x5e\xbf\x8d\x13\x5e\xbf\xdb\xd8\x5d\xbf\x60\x9d\x8d\xbe\x68\x17\xcd\x3e\x95\x6e\x96\xbe\x95\x6e\x96\xbe\xd9\x4e\x6d\x3e\xd9\x4e\x6d\x3e\x50\x01\x6e\xbe\xd0\xff\x8e\xbe\x73\x69\xf1\x3e\xa3\x16\xef\xbe\xa3\x16\xef\xbe\xba\xd5\x7f\x3f\xba\xd5\x7f\x3f\x9e\x9f\x7f\x3f\xee\x61\x90\xbe\x93\x8f\xb4\x3e\x73\xe3\x17\xbf\x73\xe3\x17\xbf\x21\xed\xa9\x3e\x21\xed\xa9\x3e\xfb\x33\xa9\xbe\xb5\xc3\x91\xbe\x1b\x94\xbc\x3d\xbb\xf3\x28\xbf\xbb\xf3\x28\xbf\xcf\x2a\x50\xbf\xcf\x2a\x50\xbf\x8f\x2f\x50\xbf\x27\x25\x93\xbe\xc1\x19\x52\xbe\x24\xf8\x28\xbf\x24\xf8\x28\xbf\xff\xc0\x49\xbf\xff\xc0\x49\xbf\x09\x72\x49\x3f\x3f\x86\x94\xbe\xe2\x16\xd7\xbe\xfb\xe4\x17\xbf\xfb\xe4\x17\xbf\x95\x98\xbe\x3e\x95\x98\xbe\x3e\xe4\x19\xbf\x3e\xfe\xe6\x95\xbe\x9a\x15\xef\xbe\xa9\xd2\xee\xbe\xa9\xd2\xee\xbe\x4f\xe7\x7e\x3f\x4f\xe7\x7e\x3f\x9e\xf0\x7e\xbf\x62\x47\x97\xbe\xb9\xac\xa7\xbe\x43\x8e\x95\xbe\x43\x8e\x95\xbe\x24\x76\x3a\x3e\x24\x76\x3a\x3e\x93\x21\x3a\x3e\x6b\xa7\x98\xbe\xe6\xdc\x6c\xbd\xa7\xf5\xb3\xbd\xa7\xf5\xb3\xbd\x01\xf3\x64\xbf\x01\xf3\x64\xbf\x60\x1b\x65\x3f\x16\x07\x9a\xbe\x7d\x48\x70\x3e\xb6\x88\x00\x3e\xb6\x88\x00\x3e\xcb\x6a\x2d\xbf\xcb\x6a\x2d\xbf\x40\xa6\x2d\xbf\x62\x66\x9b\xbe\xb7\x1a\xde\x3e\x29\x12\xa7\x3e\x29\x12\xa7\x3e\x30\x10\x05\x3f\x30\x10\x05\x3f\xd4\xf8\x04\xbf\x4c\xc5\x9c\xbe\xb8\x03\xec\x3e\x45\xe1\xfc\x3e\x45\xe1\xfc\x3e\xad\xbb\x76\x3f\xad\xbb\x76\x3f\xa5\xf9\x76\x3f\xd6\x23\x9e\xbe\xc7\xad\x9c\x3e\x0b\x6b\x1c\x3f\x0b\x6b\x1c\x3f\x2f\x2e\x29\x3c\x2f\x2e\x29\x3c\xfb\x62\x3c\xbc\xf8\x81\x9f\xbe\x96\x7b\xf9\x3c\xe0\x5a\x2a\x3f\xe0\x5a\x2a\x3f\xef\x4c\x75\xbf\xef\x4c\x75\xbf\xaf\x56\x75\xbf\xb6\xdf\xa0\xbe\xd7\x81\x83\xbe\xc7\xc6\x26\x3f\xc7\xc6\x26\x3f\x84\xe0\x08\xbf\x84\xe0\x08\xbf\x4a\x2e\x09\x3f\x0c\x3d\xa2\xbe\x21\xcd\xe2\xbe\xd0\x01\x12\x3f\xd0\x01\x12\x3f\x8f\xb0\x2a\x3f\x8f\xb0\x2a\x3f\xd7\x7f\x2a\x3f\xfe\x99\xa3\xbe\xa8\x10\xe9\xbe\xbb\x4a\xdc\x3e\xbb\x4a\xdc\x3e\x4c\xd1\x65\x3f\x4c\xd1\x65\x3f\xc2\xe1\x65\xbf\x87\xf6\xa4\xbe\x0a\x04\x94\xbe\xbc\x6e\x7b\x3e\xbc\x6e\x7b\x3e\x05\x37\x38\xbe\x05\x37\x38\xbe\x10\xe3\x37\xbe\xa8\x52\xa6\xbe\x53\x9e\x25\xbc\x0a\x2a\x10\x3d\x0a\x2a\x10\x3d\x46\xd4\x7e\xbf\x46\xd4\x7e\xbf\xd5\xdd\x7e\x3f\x59\xae\xa7\xbe\x8d\x8e\x8b\x3e\x92\x4d\x37\xbe\x92\x4d\x37\xbe\x3f\xd7\xb6\xbe\x3f\xd7\xb6\xbe\x38\xa2\xb6\xbe\x98\x09\xa9\xbe\x7b\xd1\xe5\x3e\x83\xe4\xbf\xbe\x83\xe4\xbf\xbe\x02\xc3\x4d\x3f\x02\xc3\x4d\x3f\xfe\x17\x4e\xbf\x6a\x64\xaa\xbe\x19\xa4\xe6\x3e\x46\x1c\x08\xbf\x46\x1c\x08\xbf\x1c\xd5\x49\x3f\x1c\xd5\x49\x3f\xd7\xec\x49\x3f\xcd\xbe\xab\xbe\x28\xf8\x8d\x3e\x9f\x17\x22\xbf\x9f\x17\x22\xbf\x11\xd3\xc3\xbe\x11\xd3\xc3\xbe\x6f\xcc\xc4\x3e\xbf\x18\xad\xbe\x73\x0c\x4f\xbb\xf2\x22\x2b\xbf\xf2\x22\x2b\xbf\xa9\x1c\x7e\xbf\xa9\x1c\x7e\xbf\x5d\xad\x7e\xbf\x40\x72\xae\xbe\x19\x78\x90\xbe\x6f\x40\x22\xbf\x6f\x40\x22\xbf\xa9\xb7\x14\xbe\xa9\xb7\x14\xbe\xdd\xd6\x13\x3e\x4a\xcb\xaf\xbe\xe7\x72\xe7\xbe\x84\x53\x08\xbf\x84\x53\x08\xbf\x35\x72\x6a\x3f\x35\x72\x6a\x3f\x7d\x5d\x6b\x3f\xdc\x23\xb1\xbe\xd1\x32\xe5\xbe\x92\x13\xc0\xbe\x92\x13\xc0\xbe\xb3\x2d\x21\x3f\xb3\x2d\x21\x3f\x2c\x9d\x21\xbf\xf8\x7b\xb2\xbe\xf3\xd1\x8a\xbe\xfe\x5a\x36\xbe\xfe\x5a\x36\xbe\xb1\x78\x15\xbf\xb1\x78\x15\xbf\x32\x1e\x16\xbf\x9c\xd3\xb3\xbe\x3f\x1b\x19\x3c\xe4\xa1\x1b\x3d\xe4\xa1\x1b\x3d\xff\xd1\x6f\xbf\xff\xd1\x6f\xbf\x31\xa4\x70\x3f\xc5\x2a\xb5\xbe\x1d\x71\x92\x3e\xce\x23\x80\x3e\xce\x23\x80\x3e\x28\x8b\xbd\x3d\x28\x8b\xbd\x3d\x36\xc6\xbd\x3d\x74\x81\xb6\xbe\xb2\xf7\xe7\x3e\x8b\x58\xdf\x3e\x8b\x58\xdf\x3e\x40\x36\x7c\x3f\x40\x36\x7c\x3f\xa0\xd2\x7c\xbf\xa5\xd7\xb7\xbe\xd4\xe2\xe4\x3e\xb2\x74\x13\x3f\xb2\x74\x13\x3f\x2b\xc0\xd7\x3e\x2b\xc0\xd7\x3e\x4d\x48\xd8\x3e\x59\x2d\xb9\xbe\x37\x96\x8a\x3e\x38\x94\x27\x3f\x38\x94\x27\x3f\x55\x14\x44\xbf\x55\x14\x44\xbf\xf1\x49\x44\x3f\x8c\x82\xba\xbe\x12\x19\x0b\xbc\xc4\xda\x29\x3f\xc4\xda\x29\x3f\xdb\x9c\x51\xbf\xdb\x9c\x51\xbf\xe7\xb4\x51\xbf\x3e\xd7\xbb\xbe\xd3\x81\x91\xbe\x09\xfe\x19\x3f\x09\xfe\x19\x3f\x8a\x50\xaf\x3e\x8a\x50\xaf\x3e\x46\x7b\xaf\xbe\x6e\x2b\xbd\xbe\xd0\x6d\xe7\xbe\xcd\x46\xf3\x3e\xcd\x46\xf3\x3e\x9a\xe0\x7e\x3f\x9a\xe0\x7e\x3f\x98\xad\x7e\x3f\x1a\x7f\xbe\xbe\xb3\xb7\xe5\xbe\x8e\x6c\x98\x3e\x8e\x6c\x98\x3e\x0d\xa9\x2d\x3e\x0d\xa9\x2d\x3e\x02\x2c\x2c\xbe\x42\xd2\xbf\xbe\xba\x47\x8d\xbe\x91\x71\xb4\x3d\x91\x71\xb4\x3d\x83\xaf\x68\xbf\x83\xaf\x68\xbf\x56\x9d\x68\xbf\xe4\x24\xc1\xbe\x0a\x45\x24\x3a\xc8\x4f\x06\xbe\xc8\x4f\x06\xbe\x84\x6c\x22\xbf\x84\x6c\x22\xbf\xba\xd7\x21\x3f\xfc\x76\xc2\xbe\x44\xb5\x8d\x3e\xbf\x47\xac\xbe\xbf\x47\xac\xbe\x35\xf2\x15\x3f\x35\xf2\x15\x3f\xaf\x52\x16\x3f\x8c\xc8\xc3\xbe\x2a\xc0\xe5\x3e\x57\x70\x01\xbf\x57\x70\x01\xbf\x06\xbd\x6e\x3f\x06\xbd\x6e\x3f\x11\x64\x6e\xbf\x8f\x19\xc5\xbe\x49\x9a\xe7\x3e\x7e\xc4\x1e\xbf\x7e\xc4\x1e\xbf\xf2\xe5\xe7\xbd\xf2\xe5\xe7\xbd\x7b\xad\xec\xbd\x08\x6a\xc6\xbe\x18\xcc\x92\x3e\x61\xe8\x2a\xbf\x61\xe8\x2a\xbf\xad\x7f\x7d\xbf\xad\x7f\x7d\xbf\x50\x8a\x7d\x3f\xf4\xb9\xc7\xbe\x16\x33\x67\x3c\x34\x7f\x24\xbf\x34\x7f\x24\xbf\xa8\x72\xc5\xbe\xa8\x72\xc5\xbe\x27\x7d\xc4\xbe\x54\x09\xc9\xbe\xef\xe2\x86\xbe\x8f\x2e\x0c\xbf\x8f\x2e\x0c\xbf\x10\xff\x4b\x3f\x10\xff\x4b\x3f\x58\x47\x4c\xbf\x21\x58\xca\xbe\xd0\xb5\xe2\xbe\x62\x20\xc9\xbe\x62\x20\xc9\xbe\x8b\xe8\x48\x3f\x8b\xe8\x48\x3f\xf7\xb4\x48\x3f\x5a\xa6\xcb\xbe\x8a\x45\xea\xbe\x38\xb2\x47\xbe\x38\xb2\x47\xbe\xc2\x80\xcf\xbe\xc2\x80\xcf\xbe\x3f\xf2\xcf\x3e\x02\xf4\xcc\xbe\xd3\xf6\x9a\xbe\x62\x1e\xc7\x3c\x62\x1e\xc7\x3c\x08\x99\x7c\xbf\x08\x99\x7c\xbf\xc0\x80\x7c\xbf\x17\x41\xce\xbe\x8e\x1b\x13\xbd\xf4\xf7\x76\x3e\xf4\xf7\x76\x3e\x3b\x52\xac\xbd\x3b\x52\xac\xbd\xbf\xa4\xab\x3d\x96\x8d\xcf\xbe\xfb\xc7\x79\x3e\x68\x0f\xdd\x3e\x68\x0f\xdd\x3e\x17\xfd\x71\x3f\x17\xfd\x71\x3f\x2e\xd6\x71\x3f\x7d\xd9\xd0\xbe\xa1\x00\xde\x3e\x82\x33\x13\x3f\x82\x33\x13\x3f\x83\xd8\x0c\x3f\x83\xd8\x0c\x3f\xe2\xcc\x0c\xbf\xcc\x24\xd2\xbe\x47\x51\xed\x3e\x8a\xab\x27\x3f\x8a\xab\x27\x3f\x66\xbe\x2c\xbf\x66\xbe\x2c\xbf\x89\x95\x2c\xbf\x82\x6f\xd3\xbe\xd3\x78\xa5\x3e\x9f\xa2\x29\x3f\x9f\xa2\x29\x3f\xce\x7e\x61\xbf\xce\x7e\x61\xbf\xd1\x8c\x61\x3f\x9c\xb9\xd4\xbe\x5d\xe9\x83\x3d\xbd\xd3\x18\x3f\xbd\xd3\x18\x3f\xd0\xf3\x79\x3e\xd0\xf3\x79\x3e\xe1\xc9\x78\x3e\x1a\x03\xd6\xbe\xd5\xec\x5e\xbe\xbc\x26\xee\x3e\xbc\x26\xee\x3e\x09\xe6\x7f\x3f\x09\xe6\x7f\x3f\x14\xe8\x7f\xbf\xfa\x4b\xd7\xbe\x54\x14\xd7\xbe\x67\x11\x90\x3e\x67\x11\x90\x3e\xaa\xa8\x77\x3e\xaa\xa8\x77\x3e\xab\x3e\x79\x3e\x3b\x94\xd8\xbe\xeb\x28\xf0\xbe\x17\x82\x87\x3d\x17\x82\x87\x3d\x63\xd4\x61\xbf\x63\xd4\x61\xbf\x9a\xa7\x61\x3f\xdb\xdb\xd9\xbe\x87\xc3\xb1\xbe\x24\x5a\x20\xbe\x24\x5a\x20\xbe\xb3\x0f\x2b\xbf\xb3\x0f\x2b\xbf\x75\x6a\x2b\xbf\xda\x22\xdb\xbe\x8c\x7f\xcb\xbd\xa8\x64\xb9\xbe\xa8\x64\xb9\xbe\x19\x60\x0f\x3f\x19\x60\x0f\x3f\x5a\xf3\x0e\xbf\x35\x69\xdc\xbe\xb5\xaf\x3c\x3e\xc1\xf9\x06\xbf\xc1\xf9\x06\xbf\x7a\xfc\x6f\x3f\x7a\xfc\x6f\x3f\x68\xf9\x6f\x3f\xec\xae\xdd\xbe\x07\x51\xcd\x3e\xad\x27\x22\xbf\xad\x27\x22\xbf\x95\x9e\xe3\xbd\x95\x9e\xe3\xbd\x82\x80\xe0\x3d\xfc\xf3\xde\xbe\x95\xfe\xf1\x3e\x94\x22\x2b\xbf\x94\x22\x2b\xbf\xeb\xb3\x7d\xbf\xeb\xb3\x7d\xbf\xfc\x3a\x7d\xbf\x66\x38\xe0\xbe\x89\x5c\xbf\x3e\xcf\xdc\x20\xbf\xcf\xdc\x20\xbf\xf4\x8b\xb8\xbe\xf4\x8b\xb8\xbe\x03\x4d\xb8\x3e\x26\x7c\xe1\xbe\xf3\xbf\x0f\x3e\xa7\x70\x04\xbf\xa7\x70\x04\xbf\xf0\x20\x52\x3f\xf0\x20\x52\x3f\x99\xb6\x51\x3f\x3f\xbf\xe2\xbe\xdf\xb7\x12\xbe\x6b\x11\xb2\xbe\x6b\x11\xb2\xbe\x7d\xa8\x3f\x3f\x7d\xa8\x3f\x3f\x14\x28\x3f\xbf\xaa\x01\xe4\xbe\x82\x22\xc0\xbe\x30\x0c\x0e\xbe\x30\x0c\x0e\xbe\x55\xff\xef\xbe\x55\xff\xef\xbe\xd1\xf4\xef\xbe\x68\x43\xe5\xbe\x31\x0c\xf2\xbe\x76\xad\xb0\x3d\x76\xad\xb0\x3d\x64\x17\x78\xbf\x64\x17\x78\xbf\x58\xa2\x77\x3f\x78\x84\xe6\xbe\xcd\x65\xcd\xbe\x37\x73\x9a\x3e\x37\x73\x9a\x3e\x51\x60\x7f\x3c\x51\x60\x7f\x3c\xde\x79\x8a\x3c\xd9\xc4\xe7\xbe\xb0\xee\x3e\xbe\xda\x3f\xf7\x3e\xda\x3f\xf7\x3e\x43\x02\x7a\x3f\x43\x02\x7a\x3f\x11\x0a\x7a\xbf\x89\x04\xe9\xbe\xe5\x62\xc1\x3d\xb6\xf8\x1b\x3f\xb6\xf8\x1b\x3f\x68\x64\xe0\x3e\x68\x64\xe0\x3e\xa7\x1b\xe0\x3e\x88\x43\xea\xbe\xf3\xd9\xae\x3e\xa0\x87\x2a\x3f\xa0\x87\x2a\x3f\x9e\x01\x46\xbf\x9e\x01\x46\xbf\x5a\x58\x46\x3f\xd2\x81\xeb\xbe\x3b\x33\xef\x3e\x2d\x96\x25\x3f\x2d\x96\x25\x3f\xf6\x9f\x4b\xbf\xf6\x9f\x4b\xbf\x42\xff\x4b\xbf\x67\xbf\xec\xbe\xa5\xcc\xda\x3e\x38\xa6\x0d\x3f\x38\xa6\x0d\x3f\xe4\x61\xd0\x3e\xe4\x61\xd0\x3e\xb0\xa4\xd0\xbe\x46\xfc\xed\xbe\x7e\x3a\x72\x3e\x99\xd3\xca\x3e\x99\xd3\xca\x3e\x51\x6b\x7b\x3f\x51\x6b\x7b\x3f\x0b\x05\x7c\x3f\x6e\x38\xef\xbe\xcc\x11\x1a\xbd\xe0\xd9\x45\x3e\xe0\xd9\x45\x3e\x84\xa7\x2e\x3d\x84\xa7\x2e\x3d\x3b\x10\x32\xbd\xdc\x73\xf0\xbe\x24\xbc\x98\xbe\x09\xe3\x03\xbd\x09\xe3\x03\xbd\xc2\x6e\x76\xbf\xc2\x6e\x76\xbf\xd7\xeb\x76\xbf\x91\xae\xf1\xbe\x2b\x69\xe8\xbe\xca\x18\x82\xbe\xca\x18\x82\xbe\x31\x15\xf6\xbe\x31\x15\xf6\xbe\xdd\xe6\xf6\x3e\x88\xe8\xf2\xbe\x1e\x7a\xe6\xbe\x66\xbe\xe4\xbe\x66\xbe\xe4\xbe\xff\xae\x3e\x3f\xff\xae\x3e\x3f\x39\xd5\x3e\x3f\xc4\x21\xf4\xbe\xc4\xcc\x93\xbe\x7a\x79\x16\xbf\x7a\x79\x16\xbf\x59\x4a\x51\x3f\x59\x4a\x51\x3f\x18\x78\x51\xbf\x40\x5a\xf5\xbe\x52\x80\xd8\xbc\x83\x1f\x29\xbf\x83\x1f\x29\xbf\xee\xef\xc0\xbe\xee\xef\xc0\xbe\x89\x19\xc1\xbe\xfc\x91\xf6\xbe\xfb\xb9\x7a\x3e\x9c\x1a\x28\xbf\x9c\x1a\x28\xbf\x35\xb7\x7c\xbf\x35\xb7\x7c\xbf\x18\x98\x7c\x3f\xf7\xc8\xf7\xbe\xf4\x7a\xdc\x3e\x97\x7a\x13\xbf\x97\x7a\x13\xbf\x84\x5d\x84\xbd\x84\x5d\x84\xbd\xb1\x24\x82\xbd\x2e\xff\xf8\xbe\x0f\xd3\xee\x3e\x9c\x33\xdb\xbe\x9c\x33\xdb\xbe\x4c\x7a\x75\x3f\x4c\x7a\x75\x3f\xc8\x39\x75\xbf\xa2\x34\xfa\xbe\x37\x46\xae\x3e\xb9\x6c\x6b\xbe\xb9\x6c\x6b\xbe\xc8\x29\xfb\x3e\xc8\x29\xfb\x3e\x14\x09\xfa\x3e\x52\x69\xfb\xbe\x34\xa3\xc5\x3d\xef\x84\x94\xbb\xef\x84\x94\xbb\x11\x02\x3e\xbf\x11\x02\x3e\xbf\x28\xdb\x3d\x3f\x3a\x9d\xfc\xbe\xaf\xda\x38\xbe\x00\xe5\x62\x3e\x00\xe5\x62\x3e\x65\x68\x51\xbf\x65\x68\x51\xbf\x4b\x9e\x50\xbf\x5b\xd0\xfd\xbe\x38\x3e\xca\xbe\x9d\xf4\xd7\x3e\x9d\xf4\xd7\x3e\x06\x1b\xc4\x3e\x06\x1b\xc4\x3e\xf0\x78\xc4\xbe\xb1\x02\xff\xbe\x79\x4f\xf2\xbe\x69\x8a\x12\x3f\x69\x8a\x12\x3f\xfe\x61\x7c\x3f\xfe\x61\x7c\x3f\x78\xb0\x7b\x3f\x1f\x1a\x00\xbf\x1c\xff\xc6\xbe\xa1\xd1\x27\x3f\xa1\xd1\x27\x3f\x32\xc6\x40\x3d\x32\xc6\x40\x3d\x4a\x38\x3a\xbd\x7f\xb2\x00\xbf\x36\xca\x2e\xbe\x41\x40\x29\x3f\x41\x40\x29\x3f\xfd\x27\x77\xbf\xfd\x27\x77\xbf\x94\xba\x76\xbf\x78\x4a\x01\xbf\xd3\x30\xd8\x3d\x52\x9c\x16\x3f\x52\x9c\x16\x3f\x72\x4a\xee\xbe\x72\x4a\xee\xbe\x6b\x66\xed\x3e\x09\xe2\x01\xbf\xa1\xe3\xb0\x3e\x0a\x1c\xe4\x3e\x0a\x1c\xe4\x3e\xc4\xa8\x43\x3f\xc4\xa8\x43\x3f\x06\x92\x43\x3f\x31\x79\x02\xbf\x1e\x3b\xef\x3e\x30\x8b\x7f\x3e\x30\x8b\x7f\x3e\x1f\x59\x4b\x3f\x1f\x59\x4b\x3f\xd8\x26\x4b\xbf\xf2\x0f\x03\xbf\xee\x01\xdc\x3e\x8e\x9d\xc1\x3c\x8e\x9d\xc1\x3c\x25\xb2\xd8\xbe\x25\xb2\xd8\xbe\x6e\xbf\xd8\xbe\x4b\xa6\x03\xbf\xd9\xee\x7b\x3e\x96\x3c\x52\xbe\x96\x3c\x52\xbe\x11\xa3\x79\xbf\x11\xa3\x79\xbf\x72\xbc\x79\x3f\x39\x3c\x04\xbf\xf6\x60\xac\xbc\x87\xda\xd1\xbe\x87\xda\xd1\xbe\x9c\x96\xf3\x3b\x9c\x96\xf3\x3b\x7c\x87\xe1\x3b\xba\xd1\x04\xbf\x4b\xbb\x8f\xbe\x25\xc2\x10\xbf\x25\xc2\x10\xbf\x6e\x64\x7a\x3f\x6e\x64\x7a\x3f\xb5\x8d\x7a\xbf\xcf\x66\x05\xbf\x4c\xf6\xe3\xbe\x89\x3b\x27\xbf\x89\x3b\x27\xbf\x2c\x39\xd0\x3e\x2c\x39\xd0\x3e\xfa\xdc\xd0\x3e\x78\xfb\x05\xbf\x09\x29\xeb\xbe\x59\x98\x29\xbf\x59\x98\x29\xbf\x6a\x6c\x4e\xbf\x6a\x6c\x4e\xbf\x41\x7d\x4e\x3f\xb4\x8f\x06\xbf\x11\x1a\xa3\xbe\x48\x80\x17\xbf\x48\x80\x17\xbf\xd4\xe9\x3e\xbf\xd4\xe9\x3e\xbf\xff\x4b\x3f\xbf\x83\x23\x07\xbf\x3e\xf1\x90\xbd\x3b\x27\xe6\xbe\x3b\x27\xe6\xbe\x4b\xd2\xfc\x3e\x4b\xd2\xfc\x3e\x8d\xa5\xfc\xbe\xe4\xb6\x07\xbf\xef\x6c\x4d\x3e\x34\x5c\x81\xbe\x34\x5c\x81\xbe\x2d\xbf\x73\x3f\x2d\xbf\x73\x3f\xf2\xfe\x73\x3f\xd7\x49\x08\xbf\xf5\x1b\xcf\x3e\x54\x68\xcc\xbc\x54\x68\xcc\xbc\x50\xfc\xc7\xbd\x50\xfc\xc7\xbd\xba\x3c\xc7\x3d\x58\xdc\x08\xbf\x30\x1e\xf2\x3e\xac\xee\x52\x3e\xac\xee\x52\x3e\xde\x34\x7e\xbf\xde\x34\x7e\xbf\xad\x57\x7e\xbf\x6a\x6e\x09\xbf\x0e\x3e\xc4\x3e\xa7\xf6\xd2\x3e\xa7\xf6\xd2\x3e\x13\x05\xa0\xbe\x13\x05\xa0\xbe\xd6\x20\xa0\x3e\x09\x00\x0a\xbf\x9f\xfa\x29\x3e\x24\x68\x11\x3f\x24\x68\x11\x3f\x63\x60\x5d\x3f\x63\x60\x5d\x3f\xda\x74\x5d\x3f\x37\x91\x0a\xbf\xa4\xc1\xd9\xbd\x55\x98\x27\x3f\x55\x98\x27\x3f\x79\xd2\x2a\x3f\x79\xd2\x2a\x3f\x00\xd9\x2a\xbf\xf2\x21\x0b\xbf\xee\xac\xaf\xbe\x88\x48\x29\x3f\x88\x48\x29\x3f\xbc\xac\x17\xbf\xbc\xac\x17\xbf\xeb\xab\x17\xbf\x3a\xb2\x0b\xbf\x78\x91\xee\xbe\xab\x35\x16\x3f\xab\x35\x16\x3f\xb5\xa4\x68\xbf\xb5\xa4\x68\xbf\xd0\x8c\x68\x3f\x0e\x42\x0c\xbf\xd8\x74\xde\xbe\x0f\x52\xe1\x3e\x0f\x52\xe1\x3e\xb4\xc0\x65\x3e\xb4\xc0\x65\x3e\xd7\x6f\x65\x3e\x6c\xd1\x0c\xbf\x45\xe4\x84\xbe\xc5\xd3\x74\x3e\xc5\xd3\x74\x3e\x5b\xf9\x7f\x3f\x5b\xf9\x7f\x3f\xfe\xaa\x7f\xbf\x56\x60\x0d\xbf\x90\xf5\x51\x3a\xf0\x11\x0a\x3c\xf0\x11\x0a\x3c\x5b\xcd\x35\x3e\x5b\xcd\x35\x3e\xd6\x22\x36\x3e\xcc\xee\x0d\xbf\xdf\x77\x85\x3e\x62\xdb\x64\xbe\x62\xdb\x64\xbe\x10\xe3\x6d\xbf\x10\xe3\x6d\xbf\xe2\x58\x6d\x3f\xc9\x7c\x0e\xbf\xed\x94\xde\x3e\xeb\x1d\xdb\xbe\xeb\x1d\xdb\xbe\x8f\x59\x0c\xbf\x8f\x59\x0c\xbf\x21\x3f\x0c\xbf\x4e\x0a\x0f\xbf\x97\xa5\xee\x3e\x09\x5c\x14\xbf\x09\x5c\x14\xbf\xfd\x29\x36\x3f\xfd\x29\x36\x3f\xd5\x9a\x35\xbf\x5c\x97\x0f\xbf\x5f\x94\xb0\x3e\xa2\xc1\x28\xbf\xa2\xc1\x28\xbf\x14\x80\x54\x3f\x14\x80\x54\x3f\xd2\x2d\x54\x3f\xf2\x23\x10\xbf\x44\x7f\xe3\x3d\xfd\x27\x28\xbf\xfd\x27\x28\xbf\xd3\xb9\xc4\xbe\xd3\xb9\xc4\xbe\x8c\xf9\xc3\x3e\xa4\xad\x10\xbf\xab\x8e\x22\xbe\x7b\x93\x12\xbf\x7b\x93\x12\xbf\xe7\x2c\x7b\xbf\xe7\x2c\x7b\xbf\x7e\xcb\x7a\xbf\x70\x34\x11\xbf\x24\xdc\xc0\xbe\xde\x4e\xd5\xbe\xde\x4e\xd5\xbe\xaf\xb4\x0d\x39\xaf\xb4\x0d\x39\x9e\xb4\x0c\x3a\x55\xc1\x11\xbf\x9b\xb0\xf1\xbe\xa4\x62\x55\xbe\xa4\x62\x55\xbe\x45\x26\x7b\x3f\x45\x26\x7b\x3f\x2b\xe5\x7a\x3f\x51\x54\x12\xbf\x85\x1a\xd4\xbe\xed\xa4\xd6\x3c\xed\xa4\xd6\x3c\x74\x26\xc3\x3e\x74\x26\xc3\x3e\xe1\x40\xc3\xbe\xd8\xe1\x12\xbf\xad\xc4\x63\xbe\x6a\xf4\x83\x3e\x6a\xf4\x83\x3e\x8f\x4a\x55\xbf\x8f\x4a\x55\xbf\xa1\x3c\x55\xbf\xec\x69\x13\xbf\x7d\x53\x28\x3d\xaf\xf9\xe9\x3e\xaf\xf9\xe9\x3e\xf3\xe7\x33\xbf\xf3\xe7\x33\xbf\x4e\xe5\x33\x3f\x41\xf2\x13\xbf\x63\x0f\x95\x3e\xed\x47\x19\x3f\xed\x47\x19\x3f\xd2\x21\x10\x3f\xd2\x21\x10\x3f\xcb\x35\x10\x3f\xd9\x7a\x14\xbf\xc7\xff\xe4\x3e\xfa\x39\x2a\x3f\xfa\x39\x2a\x3f\xc9\x31\x6b\x3f\xc9\x31\x6b\x3f\x38\x19\x6b\xbf\xf6\x02\x15\xbf\x28\x4d\xeb\x3e\xeb\xa0\x25\x3f\xeb\xa0\x25\x3f\xa8\x16\x5a\xbe\xa8\x16\x5a\xbe\xa9\xbe\x5a\xbe\x96\x8a\x15\xbf\x3d\x21\xa6\x3e\x2f\x03\x0c\x3f\x2f\x03\x0c\x3f\x1b\x04\x80\xbf\x1b\x04\x80\xbf\x73\xe5\x7f\x3f\xba\x11\x16\xbf\x1a\x51\xaf\x3d\xa3\x27\xc1\x3e\xa3\x27\xc1\x3e\xad\xe9\x28\xbe\xad\xe9\x28\xbe\x66\xf2\x27\xbe\x62\x98\x16\xbf\x60\xc5\x38\xbe\x92\x39\x23\x3e\x92\x39\x23\x3e\x46\x3c\x70\x3f\x46\x3c\x70\x3f\xe9\x2b\x70\xbf\x89\x1e\x17\xbf\x84\x03\xc7\xbe\xe3\xbd\xa1\xbd\xe3\xbd\xa1\xbd\x28\x51\x04\x3f\x28\x51\x04\x3f\xf2\x0b\x04\x3f\x32\xa4\x17\xbf\xd2\x2e\xf2\xbe\x85\x6c\x9d\xbe\x85\x6c\x9d\xbe\x36\xe7\x3e\xbf\x36\xe7\x3e\xbf\xfa\xec\x3e\x3f\x5a\x29\x18\xbf\x7c\x58\xd0\xbe\x7b\x5b\xfe\xbe\x7b\x5b\xfe\xbe\x26\x56\x4b\xbf\x26\x56\x4b\xbf\xb8\x22\x4b\xbf\x04\xae\x18\xbf\x10\xe3\x58\xbe\x97\x5f\x1f\xbf\x97\x5f\x1f\xbf\x4a\x57\xe7\x3e\x4a\x57\xe7\x3e\x4a\x4a\xe7\xbe\x2b\x32\x19\xbf\x47\xa0\x4d\x3d\xc3\x1c\x2b\xbf\xc3\x1c\x2b\xbf\x09\xf1\x75\x3f\x09\xf1\x75\x3f\x45\xdf\x75\x3f\xd1\xb5\x19\xbf\x14\x9b\x97\x3e\x7d\xd3\x20\xbf\x7d\xd3\x20\xbf\x90\xe9\xca\xbd\x90\xe9\xca\xbd\xff\x45\xc9\x3d\xf3\x38\x1a\xbf\x0d\x93\xe5\x3e\x51\xc7\x01\xbf\x51\xc7\x01\xbf\x33\x10\x7f\xbf\x33\x10\x7f\xbf\xbb\x0b\x7f\xbf\x92\xbb\x1a\xbf\x22\x30\xeb\x3e\xa2\xd9\xa3\xbe\xa2\xd9\xa3\xbe\xdf\x3c\x87\xbe\xdf\x3c\x87\xbe\x1d\xe6\x87\x3e\xac\x3d\x1b\xbf\x33\xe2\xa6\x3e\x12\x50\xbb\xbd\x12\x50\xbb\xbd\x04\x5f\x66\x3f\x04\x5f\x66\x3f\x44\x3e\x66\x3f\x42\xbf\x1b\xbf\x81\x1f\xb9\x3d\x0d\xc3\x18\x3e\x0d\xc3\x18\x3e\x2c\xfd\x16\x3f\x2c\xfd\x16\x3f\x5e\x3c\x17\xbf\x52\x40\x1c\xbf\x5d\x6f\x31\xbe\x61\xc6\xbd\x3e\x61\xc6\xbd\x3e\x99\xf3\x2f\xbf\x99\xf3\x2f\xbf\x1f\xab\x2f\xbf\xdd\xc0\x1c\xbf\x95\xe0\xc3\xbe\xd6\x46\x0b\x3f\xd6\x46\x0b\x3f\x18\x28\x56\xbf\x18\x28\x56\xbf\xac\x2f\x56\x3f\xe0\x40\x1d\xbf\x7e\xd6\xf1\xbe\x58\x88\x25\x3f\x58\x88\x25\x3f\x1b\xe9\xc6\x3e\x1b\xe9\xc6\x3e\xb7\x53\xc6\x3e\x5a\xc0\x1d\xbf\x3e\x71\xd4\xbe\x01\x2c\x2a\x3f\x01\x2c\x2a\x3f\xbd\x91\x79\x3f\xbd\x91\x79\x3f\x2e\x6c\x79\xbf\x4c\x3f\x1e\xbf\x81\x0d\x6a\xbe\xc1\x86\x18\x3f\xc1\x86\x18\x3f\xd6\xf4\x2f\xbd\xd6\xf4\x2f\xbd\xc8\x6a\x2e\xbd\xb5\xbd\x1e\xbf\x99\xf7\xe9\x3c\x50\xb2\xe5\x3e\x50\xb2\xe5\x3e\x7b\x87\x7d\xbf\x7b\x87\x7d\xbf\x10\x56\x7d\x3f\x94\x3b\x1f\xbf\x59\xa1\x8d\x3e\x96\x25\x78\x3e\x96\x25\x78\x3e\x8a\x48\x9c\xbe\x8a\x48\x9c\xbe\xf3\x03\x9c\xbe\xe8\xb8\x1f\xbf\x92\xbd\xe0\x3e\x5f\xd1\x80\x3b\x5f\xd1\x80\x3b\xf5\x60\x62\x3f\xf5\x60\x62\x3f\x18\x39\x62\xbf\xb1\x35\x20\xbf\x7f\x6e\xee\x3e\xed\xd6\x70\xbe\xed\xd6\x70\xbe\x3c\xff\x1c\x3f\x3c\xff\x1c\x3f\x2f\xd5\x1c\x3f\xec\xb1\x20\xbf\x84\xad\xb2\x3e\x1e\x0a\xe3\xbe\x1e\x0a\xe3\xbe\xa8\x28\x2c\xbf\xa8\x28\x2c\xbf\xec\x02\x2c\x3f\x9b\x2d\x21\xbf\x63\x19\x00\x3e\x21\xd7\x17\xbf\x21\xd7\x17\xbf\x6b\x5e\x58\xbf\x6b\x5e\x58\xbf\x96\x5d\x58\xbf\xbd\xa8\x21\xbf\x26\x45\x0c\xbe\xd1\x0b\x2a\xbf\xd1\x0b\x2a\xbf\xad\xe5\xc3\x3e\xad\xe5\xc3\x3e\x8c\x7d\xc3\xbe\x50\x23\x22\xbf\x25\xb9\xb6\xbe\x90\xa9\x25\xbf\x90\xa9\x25\xbf\x89\xda\x79\x3f\x89\xda\x79\x3f\xed\x01\x7a\x3f\x55\x9d\x22\xbf\x8d\x5a\xef\xbe\x7a\x36\x0b\xbf\x7a\x36\x0b\xbf\xd7\xe2\x4e\xbd\xd7\xe2\x4e\xbd\x3a\x88\x49\x3d\xc9\x16\x23\xbf\x9b\xe4\xde\xbe\xeb\x54\xbc\xbe\xeb\x54\xbc\xbe\xb9\x50\x7e\xbf\xb9\x50\x7e\xbf\xd5\x70\x7e\xbf\xad\x8f\x23\xbf\x20\x8b\x8a\xbe\x21\xf7\x11\xbe\x21\xf7\x11\xbe\xe4\x9c\x91\xbe\xe4\x9c\x91\xbe\xc7\xa1\x92\x3e\x00\x08\x24\xbf\xb8\x23\xc2\xbc\xe0\xfd\xd0\x3d\xe0\xfd\xd0\x3d\x9c\xf3\x65\x3f\x9c\xf3\x65\x3f\x68\xe6\x65\x3f\xc2\x7f\x24\xbf\xb8\xb5\x6b\x3e\xde\x95\xaa\x3e\xde\x95\xaa\x3e\x25\x92\x15\x3f\x25\x92\x15\x3f\xc3\x33\x16\xbf\xf1\xf6\x24\xbf\xfc\x05\xd4\x3e\x2b\x0d\x05\x3f\x2b\x0d\x05\x3f\x07\x27\x34\xbf\x07\x27\x34\xbf\x49\xf3\x33\xbf\x8e\x6d\x25\xbf\xff\xfb\xf1\x3e\xe6\xee\x22\x3f\xe6\xee\x22\x3f\x85\x2b\x51\xbf\x85\x2b\x51\xbf\xf5\xc6\x51\x3f\x96\xe3\x25\xbf\xd8\xe0\xc6\x3e\x48\xda\x2a\x3f\x48\xda\x2a\x3f\x37\x21\xde\x3e\x37\x21\xde\x3e\x4f\x9b\xdd\x3e\x0a\x59\x26\xbf\xa2\xc8\x3f\x3e\x18\xad\x1b\x3f\x18\xad\x1b\x3f\x0e\xa4\x75\x3f\x0e\xa4\x75\x3f\xb5\x0a\x76\xbf\xe8\xcd\x26\xbf\x37\x5a\x8f\xbd\xe2\xca\xee\x3e\xe2\xca\xee\x3e\x81\xe6\xf5\xbd\x81\xe6\xf5\xbd\xc3\x01\xf4\xbd\x32\x42\x27\xbf\xdc\xb1\x9c\xbe\x6d\xc2\x85\x3e\x6d\xc2\x85\x3e\xca\xae\x7f\xbf\xca\xae\x7f\xbf\x5f\xdd\x7f\x3f\xe4\xb5\x27\xbf\x22\x81\xe6\xbe\xfe\x32\xa7\x3c\xfe\x32\xa7\x3c\x92\x0d\x50\xbe\x92\x0d\x50\xbe\xbe\xba\x50\xbe\xfe\x28\x28\xbf\xaa\x51\xeb\xbe\xf8\xc7\x64\xbe\xf8\xc7\x64\xbe\xe2\xe5\x6e\x3f\xe2\xe5\x6e\x3f\xf6\x0a\x6f\xbf\x82\x9b\x28\xbf\xa3\xe3\xa9\xbe\x13\xbb\xdf\xbe\x13\xbb\xdf\xbe\xf9\xa1\x00\x3f\xf9\xa1\x00\x3f\x71\xb7\x00\x3f\x6c\x0d\x29\xbf\x2b\x92\xd7\xbd\x3e\x4a\x17\xbf\x3e\x4a\x17\xbf\x0c\xc1\x45\xbf\x0c\xc1\x45\xbf\x53\x0c\x46\x3f\xbe\x7e\x29\xbf\x66\x18\x1c\x3e\x95\x06\x2a\xbf\x95\x06\x2a\xbf\x24\x92\x3f\xbf\x24\x92\x3f\xbf\x74\x9e\x3f\xbf\x75\xef\x29\xbf\xf4\xb6\xba\x3e\x6d\x71\x25\xbf\x6d\x71\x25\xbf\x86\x24\x09\x3f\x86\x24\x09\x3f\x6b\x8f\x09\xbf\x92\x5f\x2a\xbf\xaa\xf6\xef\x3e\x59\x1b\x0a\xbf\x59\x1b\x0a\xbf\xe8\xdf\x6a\x3f\xe8\xdf\x6a\x3f\xef\x06\x6b\x3f\x14\xcf\x2a\xbf\xc7\x2e\xde\x3e\x03\x71\xb7\xbe\x03\x71\xb7\xbe\x77\x80\x7e\xbe\x77\x80\x7e\xbe\xe5\xa2\x7f\x3e\xfa\x3d\x2b\xbf\x12\xd0\x8a\x3e\x10\x8a\x02\xbe\x10\x8a\x02\xbe\xc1\xc2\x7e\xbf\xc1\xc2\x7e\xbf\xe2\x0c\x7f\xbf\x45\xac\x2b\xbf\x9c\xbd\xe9\x3c\xef\x1d\xf8\x3d\xef\x1d\xf8\x3d\x0e\xc1\x75\xbd\x0e\xc1\x75\xbd\x75\x04\x76\x3d\xf1\x19\x2c\xbf\x21\x91\x63\xbe\x4a\xd9\xb4\x3e\x4a\xd9\xb4\x3e\xf4\xff\x79\x3f\xf4\xff\x79\x3f\x9b\x43\x7a\x3f\x00\x87\x2c\xbf\x15\xa7\xd0\xbe\x83\x56\x09\x3f\x83\x56\x09\x3f\x35\x60\xb8\x3e\x35\x60\xb8\x3e\x62\xce\xb8\xbe\x70\xf3\x2c\xbf\x94\x49\xf2\xbe\xc4\x32\x25\x3f\xc4\x32\x25\x3f\x31\xdc\x5d\xbf\x31\xdc\x5d\xbf\x08\xdd\x5d\xbf\x41\x5f\x2d\xbf\x3b\x06\xcd\xbe\xf4\x12\x2a\x3f\xf4\x12\x2a\x3f\xf6\xb6\x1f\xbf\xf6\xb6\x1f\xbf\xbe\xe0\x1f\x3f\x73\xca\x2d\xbf\x87\xdf\x57\xbe\xb7\x38\x17\x3f\xb7\x38\x17\x3f\x40\xaa\x2d\x3f\x40\xaa\x2d\x3f\x27\x63\x2d\x3f\x06\x35\x2e\xbf\x50\x25\x24\x3d\x09\x6b\xde\x3e\x09\x6b\xde\x3e\xf3\xf8\x53\x3f\xf3\xf8\x53\x3f\x83\xf9\x53\xbf\xf6\x9e\x2e\xbf\x5f\xe5\x8e\x3e\xdf\x51\x5e\x3e\xdf\x51\x5e\x3e\xa8\x8d\xdc\xbe\xa8\x8d\xdc\xbe\x60\xf7\xdb\xbe\x45\x08\x2f\xbf\x85\xaf\xdf\x3e\x92\xfc\xfc\xbc\x92\xfc\xfc\xbc\x8c\xbd\x74\xbf\x8c\xbd\x74\xbf\xe1\xba\x74\x3f\xf1\x70\x2f\xbf\x35\x93\xef\x3e\x85\xaf\x8c\xbe\x85\xaf\x8c\xbe\x82\xb3\x16\x3e\x82\xb3\x16\x3e\x63\x67\x16\x3e\xfb\xd8\x2f\xbf\xe2\x22\xba\x3e\xf9\xda\xf5\xbe\xf9\xda\xf5\xbe\x0d\xcb\x7f\x3f\x0d\xcb\x7f\x3f\xa2\xef\x7f\xbf\x61\x40\x30\xbf\xac\xfa\x1d\x3e\xe0\x34\x1e\xbf\xe0\x34\x1e\xbf\x57\x17\x16\x3e\x57\x17\x16\x3e\x28\x85\x15\x3e\x24\xa7\x30\xbf\x9f\x63\xcb\xbd\xa1\x25\x2b\xbf\xa1\x25\x2b\xbf\x03\xdc\x74\xbf\x03\xdc\x74\xbf\x89\x32\x75\x3f\x41\x0d\x31\xbf\x82\xf0\xa5\xbe\x3d\xd9\x1f\xbf\x3d\xd9\x1f\xbf\x5a\x7d\xd9\xbe\x5a\x7d\xd9\xbe\x02\x28\xd9\xbe\xb9\x72\x31\xbf\x17\x46\xe9\xbe\x37\xb3\xfb\xbe\x37\xb3\xfb\xbe\xd6\x7a\x55\x3f\xd6\x7a\x55\x3f\xc7\xf2\x55\xbf\x8b\xd7\x31\xbf\x2e\xad\xe9\xbe\x96\xda\x93\xbe\x96\xda\x93\xbe\x86\x2b\x2a\x3f\x86\x2b\x2a\x3f\x7f\x18\x2a\x3f\xb8\x3b\x32\xbf\xa2\x36\xa7\xbe\xe7\xdd\x36\xbd\xe7\xdd\x36\xbd\x97\xd5\x24\xbf\x97\xd5\x24\xbf\xd8\x62\x25\x3f\x3c\x9f\x32\xbf\x26\x38\xd4\xbd\x8f\x01\x53\x3e\x8f\x01\x53\x3e\x89\x2d\x59\xbf\x89\x2d\x59\xbf\xde\x27\x59\xbf\x1a\x02\x33\xbf\x85\x41\x18\x3e\x34\xe3\xda\x3e\x34\xe3\xda\x3e\x02\xdb\xce\x3e\x02\xdb\xce\x3e\x98\x07\xd0\xbe\x4e\x64\x33\xbf\x1b\x8a\xb7\x3e\x26\x82\x16\x3f\x26\x82\x16\x3f\x20\x81\x76\x3f\x20\x81\x76\x3f\x2a\x79\x76\x3f\xd9\xc5\x33\xbf\x2c\xbc\xee\x3e\x27\x02\x2a\x3f\x27\x02\x2a\x3f\x94\x4e\x0a\xbe\x94\x4e\x0a\xbe\xcf\x35\x0c\x3e\xbb\x26\x34\xbf\xba\x35\xe2\x3e\xea\x14\x25\x3f\xea\x14\x25\x3f\x4b\x2b\x80\xbf\x4b\x2b\x80\xbf\x74\x22\x80\xbf\xf3\x86\x34\xbf\xef\xad\x95\x3e\x30\x5f\x08\x3f\x30\x5f\x08\x3f\x5c\xa7\x10\xbe\x5c\xa7\x10\xbe\xe1\xb0\x0f\x3e\x80\xe6\x34\xbf\xb2\x71\x77\x3d\x1f\xe9\xaf\x3e\x1f\xe9\xaf\x3e\x44\x76\x76\x3f\x44\x76\x76\x3f\x9e\x59\x76\x3f\x61\x45\x35\xbf\xbe\xe1\x40\xbe\xbb\x37\xd6\x3d\xbb\x37\xd6\x3d\xb5\xe1\xce\x3e\xb5\xe1\xce\x3e\x1a\xcc\xce\xbe\x97\xa3\x35\xbf\x05\x91\xc4\xbe\x73\x58\x19\xbe\x73\x58\x19\xbe\xbd\x45\x5a\xbf\xbd\x45\x5a\xbf\x8c\x17\x5a\xbf\x20\x01\x36\xbf\x8a\x63\xf1\xbe\xe3\xe4\xc3\xbe\xe3\xe4\xc3\xbe\x3b\x69\x22\xbf\x3b\x69\x22\xbf\x50\x62\x22\x3f\xfc\x5d\x36\xbf\x3c\x7d\xda\xbe\x68\x5e\x0f\xbf\x68\x5e\x0f\xbf\x65\x85\x2e\x3f\x65\x85\x2e\x3f\x0a\x4d\x2e\x3f\x2c\xba\x36\xbf\x76\x75\x86\xbe\x65\xf1\x27\xbf\x65\xf1\x27\xbf\x25\x09\x51\x3f\x25\x09\x51\x3f\xa1\xec\x50\xbf\xac\x15\x37\xbf\xc1\x0a\xcf\xbc\x49\x06\x28\xbf\x49\x06\x28\xbf\xd8\xc3\xed\xbe\xd8\xc3\xed\xbe\x82\x79\xed\xbe\x7d\x70\x37\xbf\x08\x26\x60\x3e\x99\x88\x0f\xbf\x99\x88\x0f\xbf\x3f\x64\x70\xbf\x3f\x64\x70\xbf\x81\x4c\x70\x3f\x9f\xca\x37\xbf\x32\xc9\xcd\x3e\x27\xfb\xc3\xbe\x27\xfb\xc3\xbe\x0f\x57\x5e\x3e\x0f\x57\x5e\x3e\x32\x76\x5e\x3e\x10\x24\x38\xbf\xfb\x3f\xf2\x3e\x30\x16\x18\xbe\x30\x16\x18\xbe\xb0\xda\x7e\x3f\xb0\xda\x7e\x3f\x4b\xe8\x7e\xbf\xd1\x7c\x38\xbf\x30\x83\xd3\x3e\x69\xc0\xdc\x3d\x69\xc0\xdc\x3d\x36\x53\x2d\x3d\x36\x53\x2d\x3d\xfc\xa6\x29\x3d\xe2\xd4\x38\xbf\x62\x86\x74\x3e\x29\x68\xb2\x3e\x29\x68\xb2\x3e\xba\x11\x7c\xbf\xba\x11\x7c\xbf\x96\x46\x7c\x3f\x40\x2c\x39\xbf\xf3\xeb\xb0\xba\x5d\xb3\x09\x3f\x5d\xb3\x09\x3f\x72\x92\x97\xbe\x72\x92\x97\xbe\x05\xda\x96\xbe\xed\x82\x39\xbf\x68\xb4\x76\xbe\x1c\xe0\x25\x3f\x1c\xe0\x25\x3f\x73\xce\x68\x3f\x73\xce\x68\x3f\x0d\x17\x69\xbf\xe6\xd8\x39\xbf\xc6\xf5\xd3\xbe\x1f\x7f\x29\x3f\x1f\x7f\x29\x3f\x24\x03\x07\x3f\x24\x03\x07\x3f\xc8\x9d\x06\x3f\x2b\x2e\x3a\xbf\xba\x41\xf2\xbe\xd5\xf5\x13\x3f\xd5\xf5\x13\x3f\x52\xd4\x46\xbf\x52\xd4\x46\xbf\x7b\x2e\x47\x3f\xbd\x82\x3a\xbf\x3b\x15\xce\xbe\xfd\xcc\xd0\x3e\xfd\xcc\xd0\x3e\x46\xee\x38\xbf\x46\xee\x38\xbf\x4d\x9a\x38\xbf\x9c\xd6\x3a\xbf\x8f\x09\x63\xbe\xb0\xfd\x34\x3e\xb0\xfd\x34\x3e\x58\xc7\x18\x3f\x58\xc7\x18\x3f\xf2\x38\x19\xbf\xc5\x29\x3b\xbf\x70\xd2\x9f\x3c\xdf\xae\xa5\xbd\xdf\xae\xa5\xbd\xd9\xd2\x5e\x3f\xd9\xd2\x5e\x3f\xec\xa7\x5e\x3f\x38\x7c\x3b\xbf\xce\xa9\x82\x3e\x9c\x42\xa7\xbe\x9c\x42\xa7\xbe\x26\xea\xc3\xbe\x26\xea\xc3\xbe\x5d\xc9\xc4\x3e\xf4\xcd\x3b\xbf\xf5\xa7\xd7\x3e\xc9\x13\x06\xbf\xc9\x13\x06\xbf\x12\xdc\x76\xbf\x12\xdc\x76\xbf\xd0\xda\x76\xbf\xfa\x1e\x3c\xbf\x5b\xf9\xf1\x3e\x28\x72\x24\xbf\x28\x72\x24\xbf\x11\x0b\x18\x3e\x11\x0b\x18\x3e\x99\x00\x19\xbe\x48\x6f\x3c\xbf\x3d\xa4\xca\x3e\x14\x1d\x2a\xbf\x14\x1d\x2a\xbf\xa4\x0b\x80\x3f\xa4\x0b\x80\x3f\x49\x13\x80\x3f\xe2\xbe\x3c\xbf\xac\xf9\x58\x3e\x0d\x28\x16\xbf\x0d\x28\x16\xbf\xf6\x12\xbb\x3d\xf6\x12\xbb\x3d\x27\x75\xbb\xbd\xc1\x0d\x3d\xbf\x31\x60\xee\xbc\xdd\x07\xd7\xbe\xdd\x07\xd7\xbe\xa3\x7c\x7a\xbf\xa3\x7c\x7a\xbf\x26\x79\x7a\xbf\xe7\x5b\x3d\xbf\x40\x29\x86\xbe\x98\x4c\x42\xbe\x98\x4c\x42\xbe\x50\x6e\xa5\xbe\x50\x6e\xa5\xbe\x77\xdd\xa5\x3e\x54\xa9\x3d\xbf\xbb\x34\xd9\xbe\x4f\x3d\x8e\x3d\x4f\x3d\x8e\x3d\x65\xeb\x66\x3f\x65\xeb\x66\x3f\xd9\xc2\x66\x3f\x0a\xf6\x3d\xbf\x25\xd1\xf1\xbe\x05\xfe\xa2\x3e\x05\xfe\xa2\x3e\x74\xc3\x08\x3f\x74\xc3\x08\x3f\xe3\xf3\x08\xbf\x03\x42\x3e\xbf\x10\x8c\xc9\xbe\x0d\xe0\x04\x3f\x0d\xe0\x04\x3f\xd8\x07\x47\xbf\xd8\x07\x47\xbf\x60\xbc\x46\xbf\x42\x8d\x3e\xbf\x02\xb1\x56\xbe\x11\x0e\x24\x3f\x11\x0e\x24\x3f\x97\xc1\x36\xbf\x97\xc1\x36\xbf\xd2\xce\x36\x3f\xc4\xd7\x3e\xbf\x58\x72\xf7\x3c\x16\x38\x2a\x3f\x16\x38\x2a\x3f\xff\x04\x1d\x3f\xff\x04\x1d\x3f\xe0\xa0\x1c\x3f\x8b\x21\x3f\xbf\xe9\x0b\x86\x3e\x6f\x5b\x16\x3f\x6f\x5b\x16\x3f\xf5\x8b\x5a\x3f\xf5\x8b\x5a\x3f\x38\x6d\x5a\xbf\x96\x6a\x3f\xbf\x7c\xd4\xd8\x3e\x11\xe1\xd6\x3e\x11\xe1\xd6\x3e\xa3\xe7\xd6\xbe\xa3\xe7\xd6\xbe\x58\x1b\xd6\xbe\xe4\xb2\x3f\xbf\x7d\xe9\xf1\x3e\xaf\xf7\x3f\x3e\xaf\xf7\x3f\x3e\x5e\xb6\x72\xbf\x5e\xb6\x72\xbf\xcf\x67\x72\x3f\x75\xfa\x3f\xbf\x3c\xcc\xca\x3e\x6c\x1a\x97\xbd\x6c\x1a\x97\xbd\x7f\x7c\x54\x3e\x7f\x7c\x54\x3e\x45\x6d\x53\x3e\x48\x41\x40\xbf\xfc\x0a\x5c\x3e\x36\xd4\xa5\xbe\x36\xd4\xa5\xbe\x15\x89\x7e\x3f\x15\x89\x7e\x3f\x40\x0f\x7e\xbf\x5c\x87\x40\xbf\x5c\xfb\xbb\xbc\xb6\x32\x06\xbf\xb6\x32\x06\xbf\x46\xbb\x45\x3c\x46\xbb\x45\x3c\x59\x7d\x45\x3c\xb2\xcc\x40\xbf\x04\x4f\x82\xbe\xe2\xc5\x24\xbf\xe2\xc5\x24\xbf\x7a\xee\x7d\xbf\x7a\xee\x7d\xbf\xb4\x68\x7d\x3f\x49\x11\x41\xbf\x5b\x73\xd6\xbe\x13\xd9\x29\xbf\x13\xd9\x29\xbf\x95\x7f\x69\xbe\x95\x7f\x69\xbe\x64\x68\x68\xbe\x20\x55\x41\xbf\x2c\x27\xf2\xbe\xf8\x8f\x14\xbf\xf8\x8f\x14\xbf\x35\x68\x71\x3f\x35\x68\x71\x3f\xf6\x00\x71\xbf\x36\x98\x41\xbf\xe6\x4e\xce\xbe\x30\x4f\xd0\xbe\x30\x4f\xd0\xbe\x6c\x57\xdc\x3e\x6c\x57\xdc\x3e\x4e\x8e\xdb\x3e\x8c\xda\x41\xbf\xce\xf1\x68\xbe\x44\xea\x2d\xbe\x44\xea\x2d\xbe\xad\x06\x5a\xbf\xad\x06\x5a\xbf\xad\xcd\x59\x3f\x20\x1c\x42\xbf\x52\xc6\xee\x3b\x4a\x50\xc0\x3d\x4a\x50\xc0\x3d\x13\x46\x1c\xbf\x13\x46\x1c\xbf\x76\xec\x1b\xbf\xf3\x5c\x42\xbf\x65\xbb\x75\x3e\xcf\xb8\xaf\x3e\xcf\xb8\xaf\x3e\xe5\x51\x39\x3f\xe5\x51\x39\x3f\x15\x34\x39\xbf\x04\x9d\x42\xbf\xf7\xe7\xd1\x3e\x39\xf9\x09\x3f\x39\xf9\x09\x3f\x3d\xe5\x42\x3f\x3d\xe5\x42\x3f\x4f\xaa\x42\x3f\x54\xdc\x42\xbf\xa0\x4f\xf2\x3e\x7e\x79\x26\x3f\x7e\x79\x26\x3f\xb7\x22\x11\xbf\xb7\x22\x11\xbf\x1e\x03\x11\x3f\xdf\x1a\x43\xbf\xc1\xcf\xd3\x3e\xd8\xd0\x28\x3f\xd8\xd0\x28\x3f\xb0\xb1\x60\xbf\xb0\xb1\x60\xbf\x26\x99\x60\xbf\xa7\x58\x43\xbf\x2d\xf5\x7c\x3e\x57\x8f\x10\x3f\x57\x8f\x10\x3f\xd1\xf9\xc6\x3e\xd1\xf9\xc6\x3e\xab\x97\xc6\xbe\xab\x95\x43\xbf\xaa\x35\x88\x3c\xa5\xe9\xc2\x3e\xa5\xe9\xc2\x3e\xef\xca\x74\x3f\xef\xca\x74\x3f\x16\xdc\x74\x3f\xea\xd1\x43\xbf\x85\x17\x5f\xbe\x6e\x95\x0b\x3e\x6e\x95\x0b\x3e\x5c\xd6\x49\xbe\x5c\xd6\x49\xbe\x63\xa7\x48\x3e\xd7\x0b\x44\xbf\xb1\xc6\xca\xbe\x5b\x03\x05\xbe\x5b\x03\x05\xbe\x56\xca\x7e\xbf\x56\xca\x7e\xbf\xd9\x07\x7f\xbf\x72\x43\x44\xbf\x58\xc6\xf1\xbe\xa7\x55\xc0\xbe\xa7\x55\xc0\xbe\x68\x9c\x0b\x3a\x68\x9c\x0b\x3a\xb4\xad\x9a\x3a\x7e\x7c\x44\xbf\x9f\xb9\xda\xbe\x46\xdc\x0f\xbf\x46\xdc\x0f\xbf\xde\xbf\x7e\x3f\xde\xbf\x7e\x3f\x9a\x12\x7f\x3f\xfc\xb6\x44\xbf\x01\xae\x8b\xbe\x58\xab\x28\xbf\x58\xab\x28\xbf\xf7\xdd\x45\x3e\xf7\xdd\x45\x3e\x4d\x1d\x48\xbe\xe8\xf0\x44\xbf\x2d\xda\x47\xbd\xba\x8f\x26\xbf\xba\x8f\x26\xbf\x5d\x27\x75\xbf\x5d\x27\x75\xbf\x29\x66\x75\xbf\x43\x2a\x45\xbf\x9f\xf5\x3f\x3e\xb0\xd2\x09\xbf\xb0\xd2\x09\xbf\xef\xfb\xc0\xbe\xef\xfb\xc0\xbe\x4b\x1f\xc2\x3e\xd5\x61\x45\xbf\x78\x65\xc0\x3e\xd5\xf3\xad\xbe\xd5\xf3\xad\xbe\xf8\xd5\x62\x3f\xf8\xd5\x62\x3f\x1a\xe5\x62\x3f\xa0\x97\x45\xbf\xfe\xd1\xef\x3e\x94\xff\xb0\xbd\x94\xff\xb0\xbd\x88\x52\x0b\x3f\x88\x52\x0b\x3f\x8d\xc1\x0b\xbf\xa2\xcc\x45\xbf\x1e\x5b\xe2\x3e\x85\x61\x39\x3e\x85\x61\x39\x3e\xab\xe1\x48\xbf\xab\xe1\x48\xbf\xf9\xc6\x48\xbf\xdb\x00\x46\xbf\x69\x90\x9b\x3e\x6c\xd0\xd6\x3e\x6c\xd0\xd6\x3e\x36\xa0\x30\xbf\x36\xa0\x30\xbf\x5d\xe3\x30\x3f\x4c\x34\x46\xbf\xb9\xfe\xb5\x3d\x29\x30\x17\x3f\x29\x30\x17\x3f\x24\x8c\x28\x3f\x24\x8c\x28\x3f\xd2\x5b\x28\x3f\xf2\x66\x46\xbf\x1f\xeb\x17\xbe\x96\x8e\x2a\x3f\x96\x8e\x2a\x3f\x76\x60\x4f\x3f\x76\x60\x4f\x3f\x3c\x8d\x4f\xbf\xd0\x98\x46\xbf\x85\x2c\xb2\xbe\xe3\x4f\x22\x3f\xe3\x4f\x22\x3f\xfd\x34\x03\xbf\xfd\x34\x03\xbf\x23\xf7\x02\xbf\xe2\xc9\x46\xbf\xa8\x7f\xeb\xbe\x2c\x6b\xff\x3e\x2c\x6b\xff\x3e\xb3\xdc\x66\xbf\xb3\xdc\x66\xbf\xe1\x0c\x67\x3f\x2a\xfa\x46\xbf\xdc\xa9\xe9\xbe\xcf\x9a\x90\x3e\xcf\x9a\x90\x3e\xcb\x9e\xb4\x3e\xcb\x9e\xb4\x3e\x3b\xfd\xb3\x3e\xa5\x29\x47\xbf\xb9\x4b\xad\xbe\x98\xef\xa1\x3c\x98\xef\xa1\x3c\xb4\xac\x76\x3f\xb4\xac\x76\x3f\x76\xec\x76\xbf\x55\x58\x47\xbf\xed\x4d\x0b\xbe\xcc\x45\x7c\xbe\xcc\x45\x7c\xbe\x5f\x4d\x3d\xbe\x5f\x4d\x3d\xbe\x93\xb9\x3b\xbe\x39\x86\x47\xbf\x78\x1a\xcd\x3d\xcf\xe2\xf1\xbe\xcf\xe2\xf1\xbe\x74\xb3\x7e\xbf\x74\xb3\x7e\xbf\xbd\x09\x7f\x3f\x50\xb3\x47\xbf\x79\x52\x9f\x3e\x30\x0c\x1f\xbf\x30\x0c\x1f\xbf\x09\x7a\x6a\x3c\x09\x7a\x6a\x3c\x99\x7b\x4f\x3c\x99\xdf\x47\xbf\xac\xa8\xe3\x3e\xfe\x12\x2b\xbf\xfe\x12\x2b\xbf\xcd\x1c\x7f\x3f\xcd\x1c\x7f\x3f\xfd\x96\x7f\xbf\x14\x0b\x48\xbf\x5d\x70\xef\x3e\xb4\xf8\x1a\xbf\xb4\xf8\x1a\xbf\x0c\x81\x1d\x3e\x0c\x81\x1d\x3e\x82\x04\x1f\x3e\xc2\x35\x48\xbf\xc0\xe4\xbf\x3e\x75\xa3\xe2\xbe\x75\xa3\xe2\xbe\x2d\x56\x78\xbf\x2d\x56\x78\xbf\xf9\xfd\x78\x3f\x9f\x5f\x48\xbf\x15\xe0\x41\x3e\xfb\xb2\x53\xbe\xfb\xb2\x53\xbe\xf4\x39\xa1\xbe\xf4\x39\xa1\xbe\x05\xce\xa1\xbe\xae\x88\x48\xbf\x08\xf8\x2e\xbd\xfd\x2e\x82\x3d\xfd\x2e\x82\x3d\xc4\xfd\x6a\x3f\xc4\xfd\x6a\x3f\x1b\xcc\x6b\xbf\xed\xb0\x48\xbf\xe6\x31\x87\xbe\x57\xab\xa5\x3e\x57\xab\xa5\x3e\xbf\xf7\xed\x3e\xbf\xf7\xed\x3e\x15\x5d\xee\x3e\x5d\xd8\x48\xbf\x55\x2d\xd7\xbe\x2b\xb4\x07\x3f\x2b\xb4\x07\x3f\x32\xcd\x57\xbf\x32\xcd\x57\xbf\x9a\xb0\x58\x3f\xfc\xfe\x48\xbf\x80\x44\xf2\xbe\x42\x0d\x26\x3f\x42\x0d\x26\x3f\x01\x94\x19\xbf\x01\x94\x19\xbf\xbc\xb8\x19\xbf\xc8\x24\x49\xbf\x2e\xf9\xd1\xbe\xde\xc1\x28\x3f\xde\xc1\x28\x3f\x49\x8f\x3f\x3f\x49\x8f\x3f\x3f\x73\x7a\x40\xbf\xc4\x49\x49\xbf\xcd\xb5\x7c\xbe\x5e\x4b\x0f\x3f\x5e\x4b\x0f\x3f\xc2\xb2\x37\x3f\xc2\xb2\x37\x3f\x58\xd7\x37\x3f\xec\x6d\x49\xbf\x26\x85\xbf\xbc\x86\xaf\xbb\x3e\x86\xaf\xbb\x3e\xbd\x23\x23\xbf\xbd\x23\x23\xbf\x1e\x0a\x24\x3f\x44\x91\x49\xbf\xe6\x74\x52\x3e\x14\xf9\xe4\x3d\x14\xf9\xe4\x3d\x68\xde\x50\xbf\x68\xde\x50\xbf\x4b\x0b\x51\xbf\xc8\xb3\x49\xbf\x22\xbb\xc4\x3e\x38\xdd\x25\xbe\x38\xdd\x25\xbe\xf6\x7f\x03\x3f\xf6\x7f\x03\x3f\x52\x45\x04\xbf\x7a\xd5\x49\xbf\xf1\x66\xf0\x3e\xdb\x49\xd1\xbe\xdb\x49\xd1\xbe\xf6\xc8\x64\x3f\xf6\xc8\x64\x3f\x99\xf8\x64\x3f\x58\xf6\x49\xbf\x78\xca\xe1\x3e\x30\x3f\x16\xbf\x30\x3f\x16\xbf\x34\x39\xc3\xbe\x34\x39\xc3\xbe\xe6\x35\xc4\x3e\x62\x16\x4a\xbf\x75\x97\x9c\x3e\xb6\x85\x2a\xbf\xb6\x85\x2a\xbf\xac\x45\x73\xbf\xac\x45\x73\xbf\x96\x67\x73\xbf\x99\x35\x4a\xbf\x51\x9d\xc6\x3d\xb0\xf8\x21\xbf\xb0\xf8\x21\xbf\x10\x73\x79\x3e\x10\x73\x79\x3e\x91\x12\x7a\xbe\xfa\x53\x4a\xbf\xfc\x4f\x0a\xbe\x39\xed\xfb\xbe\x39\xed\xfb\xbe\x5b\x4e\x7c\x3f\x5b\x4e\x7c\x3f\xa8\x52\x7c\x3f\x84\x71\x4a\xbf\x70\x3c\xab\xbe\xb5\x13\x89\xbe\xb5\x13\x89\xbe\x62\x4e\xd4\xbd\x62\x4e\xd4\xbd\xba\xaa\xd3\x3d\x3a\x8e\x4a\xbf\x89\x1f\xe8\xbe\xd9\xc1\x17\x3b\xd9\xc1\x17\x3b\x62\x05\x80\xbf\x62\x05\x80\xbf\xfa\xe8\x7f\xbf\x19\xaa\x4a\xbf\x05\x56\xed\xbe\x72\x5c\x8b\x3e\x72\x5c\x8b\x3e\x44\xb2\x11\xbd\x44\xb2\x11\xbd\xc7\xe8\x13\x3d\x23\xc5\x4a\xbf\x3d\xc6\xb9\xbe\x61\xdd\xfd\x3e\x61\xdd\xfd\x3e\x77\xc6\x7e\x3f\x77\xc6\x7e\x3f\x12\x7d\x7e\x3f\x57\xdf\x4a\xbf\xba\xce\x33\xbe\x72\x86\x22\x3f\x72\x86\x22\x3f\xce\x42\x2f\x3e\xce\x42\x2f\x3e\xbe\x9e\x2f\xbe\xb3\xf8\x4a\xbf\x27\x79\x5a\x3d\xbd\x4d\x2a\x3f\xbd\x4d\x2a\x3f\x64\xdb\x78\xbf\x64\xdb\x78\xbf\x0b\x72\x78\xbf\x38\x11\x4b\xbf\xfa\xeb\x89\x3e\xfa\xda\x14\x3f\xfa\xda\x14\x3f\x36\xd3\x99\xbe\x36\xd3\x99\xbe\x9e\xe3\x99\x3e\xe4\x28\x4b\xbf\x7f\xb0\xd7\x3e\xdf\x93\xcb\x3e\xdf\x93\xcb\x3e\xfd\xaa\x6e\x3f\xfd\xaa\x6e\x3f\x56\x39\x6e\x3f\xb9\x3f\x4b\xbf\x58\x45\xf2\x3e\xab\x91\x14\x3e\xab\x91\x14\x3e\xeb\xcd\xd7\x3e\xeb\xcd\xd7\x3e\x22\xc0\xd7\xbe\xb5\x55\x4b\xbf\xcd\x85\xd3\x3e\x33\xe5\x07\xbe\x33\xe5\x07\xbe\x80\xab\x60\xbf\x80\xab\x60\xbf\x84\x52\x60\xbf\xd8\x6a\x4b\xbf\x17\xdd\x82\x3e\x7c\x8f\xc6\xbe\x7c\x8f\xc6\xbe\xec\x72\x08\xbf\xec\x72\x08\xbf\x67\x52\x08\x3f\x22\x7f\x4b\xbf\xb0\x85\x1b\x3d\xee\x71\x13\xbf\xee\x71\x13\xbf\x14\x6d\x4f\x3f\x14\x6d\x4f\x3f\x74\x40\x4f\x3f\x94\x92\x4b\xbf\x4d\xea\x40\xbe\x2d\x0f\x2a\xbf\x2d\x0f\x2a\xbf\x4b\x42\x22\x3f\x4b\x42\x22\x3f\x11\x05\x22\xbf\x2a\xa5\x4b\xbf\x3d\x9c\xbd\xbe\x87\x1d\x23\xbf\x87\x1d\x23\xbf\xf6\x82\x3b\xbf\xf6\x82\x3b\xbf\x43\x7b\x3b\xbf\xe6\xb6\x4b\xbf\x93\x40\xee\xbe\x49\x7b\xff\xbe\x49\x7b\xff\xbe\x8c\x09\x39\xbf\x8c\x09\x39\xbf\x70\xc2\x38\x3f\xc8\xc7\x4b\xbf\x5c\x1f\xe7\xbe\x92\x10\x8c\xbe\x92\x10\x8c\xbe\xf5\x6a\x25\x3f\xf5\x6a\x25\x3f\x17\x74\x25\x3f\xcf\xd7\x4b\xbf\x11\x09\xaa\xbe\x02\xcf\xb3\xb8\x02\xcf\xb3\xb8\xfa\x93\x4c\x3f\xfa\x93\x4c\x3f\xb6\x5a\x4c\xbf\xfc\xe6\x4b\xbf\x9c\xbd\x0a\xbe\xc5\x1b\x8c\x3e\xc5\x1b\x8c\x3e\x5c\x93\x0d\xbf\x5c\x93\x0d\xbf\x77\xa4\x0d\xbf\x4e\xf5\x4b\xbf\xee\x64\xbd\x3d\x2f\xc8\xff\x3e\x2f\xc8\xff\x3e\xc2\xd9\x5c\xbf\xc2\xd9\x5c\xbf\x59\xae\x5c\x3f\xc4\x02\x4c\xbf\x48\xfa\x98\x3e\x3a\x48\x23\x3f\x3a\x48\x23\x3f\xf1\xed\xe8\x3e\xf1\xed\xe8\x3e\x34\x22\xe9\x3e\x5d\x0f\x4c\xbf\x08\x10\xdf\x3e\xba\xed\x29\x3f\xba\xed\x29\x3f\x6a\xee\x69\x3f\x6a\xee\x69\x3f\x8b\xbb\x69\xbf\x1a\x1b\x4c\xbf\x83\x7b\xf1\x3e\xc7\x94\x12\x3f\xc7\x94\x12\x3f\x63\x3f\xb5\xbe\x63\x3f\xb5\xbe\x2b\x78\xb5\xbe\xfc\x25\x4c\xbf\x8c\x1f\xcc\x3e\xc8\x94\xc2\x3e\xc8\x94\xc2\x3e\xec\xdf\x73\xbf\xec\xdf\x73\xbf\xe6\x9c\x73\x3f\xff\x2f\x4c\xbf\x88\x80\x6f\x3e\xd9\xc6\xf5\x3d\xd9\xc6\xf5\x3d\xb6\x0b\x81\x3e\xb6\x0b\x81\x3e\x81\x2b\x81\x3e\x25\x39\x4c\xbf\xec\xfb\x7c\x3c\xd0\x6b\x25\xbe\xd0\x6b\x25\xbe\x21\xb5\x7a\x3f\x21\xb5\x7a\x3f\xff\x79\x7a\xbf\x6e\x41\x4c\xbf\x7e\x4e\x53\xbe\x0e\x49\xd4\xbe\x0e\x49\xd4\xbe\x94\xdc\x19\xbe\x94\xdc\x19\xbe\x6c\xf0\x19\xbe\xd9\x48\x4c\xbf\x6b\xe5\xc2\xbe\x40\x14\x18\xbf\x40\x14\x18\xbf\x2e\x8e\x7e\xbf\x2e\x8e\x7e\xbf\xd2\x7d\x7e\x3f\x67\x4f\x4c\xbf\xd2\x78\xef\xbe\x0a\xe9\x2a\xbf\x0a\xe9\x2a\xbf\x0e\xb7\x4a\x3d\x0e\xb7\x4a\x3d\x39\xfa\x4b\x3d\x18\x55\x4c\xbf\xf0\x52\xe5\xbe\x47\x30\x1f\xbf\x47\x30\x1f\xbf\x06\xb3\x7f\x3f\x06\xb3\x7f\x3f\x66\xd6\x7f\xbf\xe9\x59\x4c\xbf\xf5\xef\xa6\xbe\x66\xe0\xed\xbe\x66\xe0\xed\xbe\xbc\x54\x49\x3d\xbc\x54\x49\x3d\x41\x9e\x45\x3d\xdb\x5d\x4c\xbf\x34\x3b\x05\xbe\xd1\x24\x65\xbe\xd1\x24\x65\xbe\xce\x76\x7e\xbf\xce\x76\x7e\xbf\x5b\xb8\x7e\x3f\xee\x60\x4c\xbf\xb6\xfa\xc2\x3d\x23\xa2\x6b\x3d\x23\xa2\x6b\x3d\x3c\xc7\x13\xbe\x3c\xc7\x13\xbe\x1c\x59\x12\xbe\x23\x63\x4c\xbf\x6e\xf4\x98\x3e\x6d\x4b\xa8\x3e\x6d\x4b\xa8\x3e\xdd\x15\x7b\x3f\xdd\x15\x7b\x3f\x0c\x5d\x7b\xbf\x78\x64\x4c\xbf\x79\x78\xde\x3e\x63\x70\x0a\x3f\x63\x70\x0a\x3f\x0f\x95\x70\x3e\x0f\x95\x70\x3e\xb8\x0e\x6f\x3e\xee\x64\x4c\xbf\x08\xaf\xf1\x3e\x1c\xbe\x27\x3f\x1c\xbe\x27\x3f\xe7\xbd\x75\xbf\xe7\xbd\x75\xbf\xd2\x00\x76\x3f\x84\x64\x4c\xbf\x9e\x65\xce\x3e\xa9\xad\x26\x3f\xa9\xad\x26\x3f\x30\x25\xa4\xbe\x30\x25\xa4\xbe\x94\x6c\xa3\xbe\x3b\x63\x4c\xbf\x76\x65\x79\x3e\x34\x5a\x07\x3f\x34\x5a\x07\x3f\x59\xac\x6e\x3f\x59\xac\x6e\x3f\xdc\xe2\x6e\xbf\x10\x61\x4c\xbf\x01\x12\xf1\x3c\x42\xc2\x9e\x3e\x42\xc2\x9e\x3e\x61\x51\xcd\x3e\x61\x51\xcd\x3e\xdd\x91\xcc\x3e\x06\x5e\x4c\xbf\xd6\xae\x43\xbe\x09\x44\x0e\x3d\x09\x44\x0e\x3d\x45\x2f\x66\xbf\x45\x2f\x66\xbf\x2d\x45\x66\x3f\x1a\x5a\x4c\xbf\x10\xc1\xbc\xbe\xa3\x1c\x7d\xbe\xa3\x1c\x7d\xbe\x56\x87\xf3\xbe\x56\x87\xf3\xbe\x5f\xc5\xf2\xbe\x50\x55\x4c\xbf\x6c\x6e\xed\xbe\x95\xde\xf7\xbe\x95\xde\xf7\xbe\x3b\x83\x5c\x3f\x3b\x83\x5c\x3f\xa0\x67\x5c\xbf\xa3\x4f\x4c\xbf\x67\x23\xe9\xbe\x8b\xef\x21\xbf\x8b\xef\x21\xbf\x8c\x3d\x0b\x3f\x8c\x3d\x0b\x3f\xfc\xf6\x0a\x3f\x15\x49\x4c\xbf\x4f\xfa\xb0\xbe\x61\x3f\x2a\xbf\x61\x3f\x2a\xbf\xc6\xc5\x51\xbf\xc6\xc5\x51\xbf\x3b\x86\x51\x3f\xa6\x41\x4c\xbf\xc2\x20\x23\xbe\x07\x43\x13\xbf\x07\x43\x13\xbf\x92\x15\x1b\xbf\x92\x15\x1b\xbf\x70\x02\x1b\xbf\x55\x39\x4c\xbf\xb0\xc4\x7e\x3d\xb9\x40\xc2\xbe\xb9\x40\xc2\xbe\x9e\x15\x46\x3f\x9e\x15\x46\x3f\x0b\xdb\x45\xbf\x23\x30\x4c\xbf\x4d\x1d\x8a\x3e\xbd\x22\xe8\xbd\xbd\x22\xe8\xbd\xc9\x72\x29\x3f\xc9\x72\x29\x3f\xd8\x87\x29\x3f\x0f\x26\x4c\xbf\x2f\xcb\xd5\x3e\x71\x15\x32\x3e\x71\x15\x32\x3e\xfa\xb4\x39\xbf\xfa\xb4\x39\xbf\xee\xa1\x39\x3f\x19\x1b\x4c\xbf\x9c\x48\xf2\x3e\x27\xc1\xdb\x3e\x27\xc1\xdb\x3e\xb8\x78\x36\xbf\xb8\x78\x36\xbf\x92\x93\x36\xbf\x41\x0f\x4c\xbf\x8e\x70\xd9\x3e\x2b\xe5\x1a\x3f\x2b\xe5\x1a\x3f\x37\xf8\x2c\x3f\x37\xf8\x2c\x3f\xc7\x12\x2d\xbf\x87\x02\x4c\xbf\x1d\xdc\x90\x3e\x2b\x25\x2b\x3f\x2b\x25\x2b\x3f\xcb\x2a\x42\x3f\xcb\x2a\x42\x3f\x84\x3a\x42\x3f\xeb\xf4\x4b\xbf\x72\x52\xa2\x3d\xda\x84\x1b\x3f\xda\x84\x1b\x3f\xc9\x18\x20\xbf\xc9\x18\x20\xbf\x2d\x5a\x20\x3f\x6c\xe6\x4b\xbf\xef\xfc\x10\xbe\x7c\xb1\xdd\x3e\x7c\xb1\xdd\x3e\xe5\x82\x4c\xbf\xe5\x82\x4c\xbf\x02\x95\x4c\xbf\x0b\xd7\x4b\xbf\xef\xa3\xa9\xbe\x4a\x9e\x35\x3e\x4a\x9e\x35\x3e\x1e\x2c\x13\x3f\x1e\x2c\x13\x3f\xef\x95\x13\xbf\xc7\xc6\x4b\xbf\x6d\xb7\xe5\xbe\x6c\xcd\xe4\xbd\x6c\xcd\xe4\xbd\x36\x94\x55\x3f\x36\x94\x55\x3f\xcb\xb5\x55\x3f\xa1\xb5\x4b\xbf\x55\xbf\xef\xbe\xe4\x99\xc2\xbe\xe4\x99\xc2\xbe\xb7\x49\x06\xbf\xb7\x49\x06\xbf\x44\xdd\x06\x3f\x98\xa3\x4b\xbf\x41\xb1\xc5\xbe\x04\xc3\x13\xbf\x04\xc3\x13\xbf\x93\x84\x5d\xbf\x93\x84\x5d\xbf\x20\xaa\x5d\xbf\xaa\x90\x4b\xbf\x9f\xa2\x61\xbe\x23\x6d\x2a\xbf\x23\x6d\x2a\xbf\x86\x49\xf3\x3e\x86\x49\xf3\x3e\x24\x93\xf4\xbe\xda\x7c\x4b\xbf\x85\x1f\xe7\xbb\x54\xf0\x20\xbf\x54\xf0\x20\xbf\x13\x69\x64\x3f\x13\x69\x64\x3f\x9d\x80\x64\x3f\x28\x68\x4b\xbf\xf2\x8a\x54\x3e\xf4\x02\xf2\xbe\xf4\x02\xf2\xbe\x51\xe5\xda\xbe\x51\xe5\xda\xbe\x1b\xef\xdb\x3e\x92\x52\x4b\xbf\xa1\x24\xc1\x3e\xff\x70\x68\xbe\xff\x70\x68\xbe\xbb\x3e\x6a\xbf\xbb\x3e\x6a\xbf\x2c\x4d\x6a\xbf\x18\x3c\x4b\xbf\x88\x60\xee\x3e\x31\xee\x7d\x3d\x31\xee\x7d\x3d\x01\x89\xc3\x3e\x01\x89\xc3\x3e\x19\x05\xc4\xbe\xbc\x24\x4b\xbf\xf4\x5f\xe8\x3e\x6c\xcc\xad\x3e\x6c\xcc\xad\x3e\x0c\x0c\x6f\x3f\x0c\x0c\x6f\x3f\x76\x24\x6f\x3f\x7b\x0c\x4b\xbf\xe3\x8f\xb0\x3e\x3e\x6f\x0d\x3f\x3e\x6f\x0d\x3f\xcc\x1c\xad\xbe\xcc\x1c\xad\xbe\x8c\x08\xad\x3e\x58\xf3\x4a\xbf\xb1\x07\x26\x3e\x9f\x05\x29\x3f\x9f\x05\x29\x3f\xd4\xf6\x72\xbf\xd4\xf6\x72\xbf\xb6\x18\x73\xbf\x51\xd9\x4a\xbf\x33\x7e\x61\xbd\xfe\x4f\x24\x3f\xfe\x4f\x24\x3f\x5f\xa1\x97\x3e\x5f\xa1\x97\x3e\x5f\x30\x97\xbe\x67\xbe\x4a\xbf\x89\x49\x85\xbe\x89\x1e\x00\x3f\x89\x1e\x00\x3f\xba\x2d\x76\x3f\xba\x2d\x76\x3f\x58\x3f\x76\x3f\x99\xa2\x4a\xbf\xda\xee\xd1\xbe\x6c\x99\x86\x3e\x6c\x99\x86\x3e\x1e\x51\x83\xbe\x1e\x51\x83\xbe\x9d\xb1\x82\x3e\xe8\x85\x4a\xbf\x0c\xea\xf1\xbe\x54\xaf\xd0\xbc\x54\xaf\xd0\xbc\x1c\xc6\x78\xbf\x1c\xc6\x78\xbf\x89\xb7\x78\xbf\x52\x68\x4a\xbf\x58\x91\xde\xbe\x7f\x50\x9e\xbe\x7f\x50\x9e\xbe\x41\xca\x60\x3e\x41\xca\x60\x3e\x54\x5b\x5f\xbe\xda\x49\x4a\xbf\xc8\x20\x9c\xbe\x12\x94\x08\xbf\x12\x94\x08\xbf\xfb\xc1\x7a\x3f\xfb\xc1\x7a\x3f\x7e\xa6\x7a\x3f\x7d\x2a\x4a\xbf\x63\x0e\xe3\xbd\x0b\xa2\x27\xbf\x0b\xa2\x27\xbf\x64\xbd\x3d\xbe\x64\xbd\x3d\xbe\x00\x52\x3c\x3e\x3d\x0a\x4a\xbf\x3c\xe8\xd9\x3d\x57\x3b\x26\xbf\x57\x3b\x26\xbf\xad\x32\x7c\xbf\xad\x32\x7c\xbf\x98\x2b\x7c\xbf\x18\xe9\x49\xbf\xd1\x25\x9a\x3e\xdb\x8f\x04\xbf\xdb\x8f\x04\xbf\x81\x48\x1d\x3e\x81\x48\x1d\x3e\xe3\x38\x1c\xbe\x10\xc7\x49\xbf\xcc\x58\xdd\x3e\x82\x2c\x92\xbe\x82\x2c\x92\xbe\x3a\x43\x7d\x3f\x3a\x43\x7d\x3f\x8b\x5c\x7d\x3f\x26\xa4\x49\xbf\x75\x14\xf2\x3e\x96\xad\x2c\x3b\x96\xad\x2c\x3b\x01\x01\xff\xbd\x01\x01\xff\xbd\x0e\x17\xfe\x3d\x57\x80\x49\xbf\x41\x23\xd4\x3e\x47\xbb\x94\x3e\x47\xbb\x94\x3e\xb7\x1a\x7e\xbf\xb7\x1a\x7e\xbf\xba\x48\x7e\xbf\xa4\x5b\x49\xbf\x8a\xe9\x89\x3e\x2a\x94\x05\x3f\x2a\x94\x05\x3f\xe0\x8b\xc9\x3d\xe0\x8b\xc9\x3d\xfb\x9c\xc9\xbd\x0e\x36\x49\xbf\xa8\xfc\x8b\x3d\x09\xad\x26\x3f\x09\xad\x26\x3f\xf1\xc1\x7e\x3f\xf1\xc1\x7e\x3f\x61\xfb\x7e\x3f\x95\x0f\x49\xbf\x54\x3b\x16\xbe\x16\x17\x27\x3f\x16\x17\x27\x3f\xea\xa3\x9a\xbd\xea\xa3\x9a\xbd\xa9\xf9\x9a\x3d\x38\xe8\x48\xbf\xd0\x88\xa9\xbe\xff\xa5\x06\x3f\xff\xa5\x06\x3f\x33\x31\x7f\xbf\x33\x31\x7f\xbf\x32\x78\x7f\xbf\xf8\xbf\x48\xbf\x0c\xb9\xe4\xbe\x5f\x4d\x97\x3e\x5f\x4d\x97\x3e\xcf\x06\x64\x3d\xcf\x06\x64\x3d\x03\x74\x64\xbd\xd5\x96\x48\xbf\x3d\x86\xf0\xbe\x62\x9d\xd5\x3b\x62\x9d\xd5\x3b\x89\x6f\x7f\x3f\x89\x6f\x7f\x3f\xe3\xc0\x7f\x3f\xce\x6c\x48\xbf\x78\xa0\xca\xbe\x96\x6b\x91\xbe\x96\x6b\x91\xbe\x10\xa9\x1e\xbd\x10\xa9\x1e\xbd\x53\x4d\x1f\x3d\xe4\x41\x48\xbf\xc8\xf4\x75\xbe\x20\xc0\x04\xbf\x20\xc0\x04\xbf\x32\x96\x7f\xbf\x32\x96\x7f\xbf\xfe\xdf\x7f\xbf\x18\x16\x48\xbf\x87\xa9\x10\xbd\xb3\x7e\x26\xbf\xb3\x7e\x26\xbf\x4f\x75\xcb\x3c\x4f\x75\xcb\x3c\x24\x6a\xce\xbc\x68\xe9\x47\xbf\xe9\xde\x34\x3e\xdc\x28\x27\xbf\xdc\x28\x27\xbf\x8c\xb6\x7f\x3f\x8c\xb6\x7f\x3f\x67\xec\x7f\x3f\xd4\xbb\x47\xbf\xc7\x4f\xb4\x3e\x67\x84\x06\xbf\x67\x84\x06\xbf\xf0\x34\x69\xbc\xf0\x34\x69\xbc\x43\xe8\x70\x3c\x5f\x8d\x47\xbf\xd9\x32\xe9\x3e\x3a\xfd\x95\xbe\x3a\xfd\x95\xbe\xfe\xca\x7f\xbf\xfe\xca\x7f\xbf\x6e\xfa\x7f\xbf\x08\x5e\x47\xbf\x1e\x65\xee\x3e\x14\xff\xd7\xba\x14\xff\xd7\xba\x5e\x38\xe2\x3b\x5e\x38\xe2\x3b\x06\x7d\xee\xbb\xce\x2d\x47\xbf\xec\xf8\xc2\x3e\x8a\x98\x94\x3e\x8a\x98\x94\x3e\x7b\xc7\x7f\x3f\x7b\xc7\x7f\x3f\xc4\x07\x80\x3f\xb2\xfc\x46\xbf\xe3\xd1\x5f\x3e\x91\x2a\x06\x3f\x91\x2a\x06\x3f\xa5\xa8\x22\xbb\xa5\xa8\x22\xbb\x76\x20\x37\x3b\x4c\xca\x46\xbf\x4a\x12\x46\x3c\x58\x1a\x27\x3f\x58\x1a\x27\x3f\x30\xb2\x7f\xbf\x30\xb2\x7f\xbf\xfb\x11\x80\xbf\x9d\x96\x46\xbf\x61\x5b\x49\xbe\x09\x69\x26\x3f\x09\x69\x26\x3f\x57\x39\x2f\x3a\x57\x39\x2f\x3a\x63\x06\xa6\xba\xaa\x5f\x46\xbf\x44\x13\xbb\xbe\x55\x22\x04\x3f\x55\x22\x04\x3f\x71\xa2\x7f\x3f\x71\xa2\x7f\x3f\x37\x19\x80\x3f\x75\x25\x46\xbf\x3b\x9f\xeb\xbe\x85\x34\x8e\x3e\x85\x34\x8e\x3e\x75\x44\xca\xba\x75\x44\xca\xba\x38\xf0\x31\x3b\x6c\xef\x45\xbf\x04\x9b\xec\xbe\x23\x08\x8c\xbc\x23\x08\x8c\xbc\x84\xab\x7f\xbf\x84\xab\x7f\xbf\x17\x1d\x80\xbf\x8f\xbd\x45\xbf\x3a\xf8\xbd\xbe\xcb\x13\x9e\xbe\xcb\x13\x9e\xbe\x0d\x05\xb4\x3b\x0d\x05\xb4\x3b\x05\x2a\xea\xbb\x5f\x88\x45\xbf\x24\x68\x52\xbe\x67\xb3\x09\xbf\x67\xb3\x09\xbf\x1b\xcd\x7f\x3f\x1b\xcd\x7f\x3f\xc4\x1d\x80\x3f\xdb\x4f\x45\xbf\xf9\x22\x97\x3a\x15\x5e\x28\xbf\x15\x5e\x28\xbf\xec\x15\x52\xbc\xec\x15\x52\xbc\x82\xcf\x6e\x3c\x74\x16\x45\xbf\x9a\x5d\x54\x3e\xbd\xb2\x24\xbf\xbd\xb2\x24\xbf\x63\xf8\x7f\xbf\x63\xf8\x7f\xbf\xf6\x19\x80\xbf\x28\xdc\x44\xbf\x9b\x77\xbe\x3e\xe9\xb2\xfe\xbe\xe9\xb2\xfe\xbe\xe4\x54\xc1\x3c\xe4\x54\xc1\x3c\x70\x90\xcd\xbc\xf9\xa0\x44\xbf\x18\xb0\xec\x3e\x8c\x81\x7f\xbe\x8c\x81\x7f\xbe\x34\x0d\x80\x3f\x34\x0d\x80\x3f\x53\x10\x80\x3f\xe6\x64\x44\xbf\x1a\xbf\xeb\x3e\x2f\x34\x4c\x3d\x2f\x34\x4c\x3d\x82\xab\x1a\xbd\x82\xab\x1a\xbd\xcb\xb7\x1e\x3d\xef\x27\x44\xbf\x4a\xf7\xbb\x3e\xd0\xb2\xad\x3e\xd0\xb2\xad\x3e\xd0\x0f\x80\xbf\xd0\x0f\x80\xbf\x7a\xfb\x7f\xbf\x14\xea\x43\xbf\xa5\xe5\x4d\x3e\x02\x1c\x0f\x3f\x02\x1c\x0f\x3f\xcf\x44\x62\x3d\xcf\x44\x62\x3d\x72\x52\x63\xbd\x56\xab\x43\xbf\xc5\x9b\x97\xbb\x3f\xe1\x29\x3f\x3f\xe1\x29\x3f\x16\xf1\x7f\x3f\x16\xf1\x7f\x3f\xb3\xb6\x7f\x3f\xb3\x6b\x43\xbf\xed\x3d\x56\xbe\x37\x8c\x21\x3f\x37\x8c\x21\x3f\x0e\x7c\x9b\xbd\x0e\x7c\x9b\xbd\x64\x2c\x9a\x3d\x2e\x2b\x43\xbf\x76\xa6\xbe\xbe\x64\x7f\xef\x3e\x64\x7f\xef\x3e\x32\x79\x7f\xbf\x32\x79\x7f\xbf\x65\x40\x7f\xbf\xc4\xe9\x42\xbf\x9a\x94\xec\xbe\xf9\x42\x54\x3e\xf9\x42\x54\x3e\xb7\xdd\xcb\x3d\xb7\xdd\xcb\x3d\xb3\xfa\xc8\xbd\x78\xa7\x42\xbf\xb5\xfe\xeb\xbe\x08\xa5\xc5\xbd\x08\xa5\xc5\xbd\x12\xad\x7e\x3f\x12\xad\x7e\x3f\x8b\x8d\x7e\x3f\x48\x64\x42\xbf\x16\x23\xbd\xbe\x35\xcc\xc2\xbe\x35\xcc\xc2\xbe\xc3\xcb\x00\xbe\xc3\xcb\x00\xbe\xe4\x31\xfe\x3d\x35\x20\x42\xbf\x14\x99\x52\xbe\x61\xd4\x15\xbf\x61\xd4\x15\xbf\x8b\x91\x7d\xbf\x8b\x91\x7d\xbf\xc0\x99\x7d\xbf\x3f\xdb\x41\xbf\x7d\x4e\xf5\xba\xec\xfa\x2a\xbf\xec\xfa\x2a\xbf\x70\x21\x1e\x3e\x70\x21\x1e\x3e\x81\xdc\x1c\xbe\x66\x95\x41\xbf\x4f\xf8\x4e\x3e\xd6\x55\x1c\xbf\xd6\x55\x1c\xbf\x6c\x30\x7c\x3f\x6c\x30\x7c\x3f\xf3\x5c\x7c\x3f\xaa\x4e\x41\xbf\x46\xb2\xbb\x3e\xbe\xbe\xd9\xbe\xbe\xbe\xd9\xbe\xce\x00\x3e\xbe\xce\x00\x3e\xbe\xbe\x9e\x3d\x3e\x0c\x07\x41\xbf\x60\x5e\xeb\x3e\x00\xeb\x19\xbe\x00\xeb\x19\xbe\xbc\x88\x7a\xbf\xbc\x88\x7a\xbf\x4d\xc3\x7a\xbf\x8e\xbe\x40\xbf\x51\x5a\xed\x3e\x8c\x52\x20\x3e\x8c\x52\x20\x3e\x1a\xaa\x60\x3e\x1a\xaa\x60\x3e\x71\x38\x61\xbe\x2c\x75\x40\xbf\x47\x63\xc1\x3e\xa0\x81\xdc\x3e\xa0\x81\xdc\x3e\x3a\x84\x78\x3f\x3a\x84\x78\x3f\x06\xb4\x78\x3f\xe7\x2a\x40\xbf\x58\x2e\x60\x3e\xe3\x2c\x1d\x3f\xe3\x2c\x1d\x3f\x3e\x24\x83\xbe\x3e\x24\x83\xbe\xe9\xc2\x83\x3e\xc0\xdf\x3f\xbf\x44\xf0\x93\x3c\x2d\xd8\x2a\x3f\x2d\xd8\x2a\x3f\xb6\xfe\x75\xbf\xb6\xfe\x75\xbf\x4f\x19\x76\xbf\xb7\x93\x3f\xbf\x16\x91\x3e\xbe\x6b\x44\x14\x3f\x6b\x44\x14\x3f\x94\x65\x97\x3e\x94\x65\x97\x3e\xb1\x2a\x98\xbe\xcd\x46\x3f\xbf\xaa\x67\xb5\xbe\x50\x49\xbc\x3e\x50\x49\xbc\x3e\x33\xd4\x72\x3f\x33\xd4\x72\x3f\x3c\xdf\x72\x3f\x03\xf9\x3e\xbf\x66\xa7\xe8\xbe\x58\x53\x9f\x3d\x58\x53\x9f\x3d\x33\xf9\xac\xbe\x33\xf9\xac\xbe\x99\xb2\xad\x3e\x57\xaa\x3e\xbf\x3c\x51\xef\xbe\x8c\x7f\x6a\xbe\x8c\x7f\x6a\xbe\x8c\xe9\x6e\xbf\x8c\xe9\x6e\xbf\x41\xec\x6e\xbf\xca\x5a\x3e\xbf\xdd\x40\xc8\xbe\xcf\x63\xf9\xbe\xcf\x63\xf9\xbe\xeb\xbd\xc3\x3e\xeb\xbd\xc3\x3e\xc0\x3f\xc4\xbe\x5c\x0a\x3e\xbf\x93\x15\x76\xbe\x20\x1c\x24\xbf\x20\x1c\x24\xbf\x15\x26\x6a\x3f\x15\x26\x6a\x3f\x39\x22\x6a\x3f\x0e\xb9\x3d\xbf\x49\xe2\x33\xbd\xa2\x58\x28\xbf\xa2\x58\x28\xbf\xa9\x93\xdb\xbe\xa9\x93\xdb\xbe\x80\xbf\xdb\x3e\xdf\x66\x3d\xbf\x9b\x83\x24\x3e\xaf\x66\x08\xbf\xaf\x66\x08\xbf\xf4\x6a\x64\xbf\xf4\x6a\x64\xbf\xc5\x63\x64\xbf\xd0\x13\x3d\xbf\xfa\x50\xab\x3e\x33\x1b\x96\xbe\x33\x1b\x96\xbe\xd6\x48\xf4\x3e\xd6\x48\xf4\x3e\x4a\x19\xf4\xbe\xe1\xbf\x3c\xbf\x9f\xdf\xe3\x3e\x99\x0f\x23\x3c\x99\x0f\x23\x3c\x6b\x96\x5d\x3f\x6b\x96\x5d\x3f\xd0\x96\x5d\x3f\x14\x6b\x3c\xbf\xb8\x51\xf1\x3e\x0f\x59\x9f\x3e\x0f\x59\x9f\x3e\x74\xc7\x06\xbf\x74\xc7\x06\xbf\x66\x91\x06\x3f\x66\x15\x3c\xbf\x8f\x3a\xd1\x3e\xa1\x9e\x0b\x3f\xa1\x9e\x0b\x3f\x3b\x92\x55\xbf\x3b\x92\x55\xbf\x1b\xa4\x55\xbf\xd9\xbe\x3b\xbf\x05\xc5\x89\x3e\x16\x53\x29\x3f\x16\x53\x29\x3f\xf1\x87\x13\x3f\xf1\x87\x13\x3f\x5e\x51\x13\xbf\x6c\x67\x3b\xbf\x41\xf3\xa1\x3d\x5c\x3e\x22\x3f\x5c\x3e\x22\x3f\xe8\x58\x4c\x3f\xe8\x58\x4c\x3f\xf3\x77\x4c\x3f\x22\x0f\x3b\xbf\x9a\x98\x00\xbe\xaf\xa0\xef\x3e\xaf\xa0\xef\x3e\x85\x46\x20\xbf\x85\x46\x20\xbf\x89\x2d\x20\x3f\xf8\xb5\x3a\xbf\xbb\xf3\x9c\xbe\x44\xcc\x4c\x3e\x44\xcc\x4c\x3e\x7d\xe9\x41\xbf\x7d\xe9\x41\xbf\xb5\x05\x42\xbf\xf2\x5b\x3a\xbf\x06\x33\xdc\xbe\x58\x50\xe5\xbd\x58\x50\xe5\xbd\x10\xf0\x2c\x3f\x10\xf0\x2c\x3f\x14\x03\x2d\xbf\x0c\x01\x3a\xbf\xa2\x52\xf2\xbe\xb4\x9f\xcc\xbe\xb4\x9f\xcc\xbe\xb1\x36\x36\x3f\xb1\x36\x36\x3f\x52\x44\x36\x3f\x49\xa5\x39\xbf\x21\x51\xdb\xbe\xdf\x91\x19\xbf\xdf\x91\x19\xbf\xe3\x6b\x39\xbf\xe3\x6b\x39\xbf\x8c\xa7\x39\x3f\xa9\x48\x39\xbf\xfd\x93\x9b\xbe\x7e\x1d\x2b\xbf\x7e\x1d\x2b\xbf\xa4\x27\x29\xbf\xa4\x27\x29\xbf\x72\x27\x29\xbf\x2c\xeb\x38\xbf\x1f\x25\xfc\xbd\x70\xff\x16\xbf\x70\xff\x16\xbf\x0d\x8f\x45\x3f\x0d\x8f\x45\x3f\x68\xe8\x45\xbf\xd2\x8c\x38\xbf\x6b\x62\xa4\x3d\xd6\x18\xc3\xbe\xd6\x18\xc3\xbe\x34\xa7\x1a\x3f\x34\xa7\x1a\x3f\xfa\x9c\x1a\x3f\x9c\x2d\x38\xbf\x7c\x89\x89\x3e\x07\xec\xb3\xbd\x07\xec\xb3\xbd\x9e\x23\x51\xbf\x9e\x23\x51\xbf\xfe\x8e\x51\x3f\x89\xcd\x37\xbf\x2f\x85\xd0\x3e\x8c\x72\x66\x3e\x8c\x72\x66\x3e\x01\xac\x0a\xbf\x01\xac\x0a\xbf\xba\x93\x0a\xbf\x9a\x6c\x37\xbf\xfe\x0d\xf1\x3e\x88\x00\xfa\x3e\x88\x00\xfa\x3e\xf3\xf6\x5b\x3f\xf3\xf6\x5b\x3f\xeb\x63\x5c\xbf\xd0\x0a\x37\xbf\x4f\x47\xe5\x3e\xaf\xa9\x24\x3f\xaf\xa9\x24\x3f\xe2\x61\xf2\x3e\xe2\x61\xf2\x3e\xba\x07\xf2\x3e\x2a\xa8\x36\xbf\x73\x78\xaf\x3e\xf5\xaf\x27\x3f\xf5\xaf\x27\x3f\x99\xd9\x65\xbf\x99\xd9\x65\xbf\x84\x2f\x66\x3f\xaa\x44\x36\xbf\xb3\x2c\x33\x3e\x7f\x4d\x05\x3f\x7f\x4d\x05\x3f\x15\x59\xcc\xbe\x15\x59\xcc\xbe\xb0\xe1\xcb\xbe\x51\xe0\x35\xbf\x72\x8e\xc9\xbc\x0b\x2f\x8a\x3e\x0b\x2f\x8a\x3e\x02\x8e\x6e\x3f\x02\x8e\x6e\x3f\x6b\xba\x6e\xbf\x1c\x7b\x35\xbf\x8e\xcc\x60\xbe\x38\x54\x2a\xbd\x38\x54\x2a\xbd\xf2\x3a\xa3\x3e\xf2\x3a\xa3\x3e\x5b\xce\xa2\x3e\x0c\x15\x35\xbf\x62\xa6\xbf\xbe\x3a\x21\xb0\xbe\x3a\x21\xb0\xbe\xba\xc3\x75\xbf\xba\xc3\x75\xbf\xc4\xcd\x75\x3f\x23\xae\x34\xbf\x22\x00\xec\xbe\x63\xc3\x11\xbf\x63\xc3\x11\xbf\x1d\x75\x6e\xbe\x1d\x75\x6e\xbe\xa8\xed\x6d\xbe\x62\x46\x34\xbf\x75\x81\xed\xbe\x3f\xb1\x2a\xbf\x3f\xb1\x2a\xbf\xc6\x27\x7b\x3f\xc6\x27\x7b\x3f\x45\x31\x7b\xbf\xc8\xdd\x33\xbf\xb0\x01\xc4\xbe\x04\x21\x1d\xbf\x04\x21\x1d\xbf\xe3\x8d\x11\x3e\xe3\x8d\x11\x3e\xab\x36\x11\x3e\x54\x74\x33\xbf\xe9\x3d\x6e\xbe\x6e\x0d\xd8\xbe\x6e\x0d\xd8\xbe\xef\x7c\x7e\xbf\xef\x7c\x7e\xbf\x97\xa6\x7e\x3f\x0a\x0a\x33\xbf\x25\x9f\x26\xbd\xa6\xac\x09\xbe\xa6\xac\x09\xbe\x9c\xdf\x42\xbd\x9c\xdf\x42\xbd\x04\xb7\x40\xbd\xe7\x9e\x32\xbf\x2f\x2c\x22\x3e\x9e\x1d\x3c\x3e\x9e\x1d\x3c\x3e\x73\x9b\x7f\x3f\x73\x9b\x7f\x3f\x3d\xe8\x7f\xbf\xee\x32\x32\xbf\x1f\x2f\xa8\x3e\x6f\x7e\xeb\x3e\x6f\x7e\xeb\x3e\xa4\x34\x4d\xbd\xa4\x34\x4d\xbd\x18\x36\x51\xbd\x1d\xc6\x31\xbf\xc6\x17\xe1\x3e\x80\xbf\x21\x3f\x80\xbf\x21\x3f\x6d\x5c\x7e\xbf\x6d\x5c\x7e\xbf\x20\xb1\x7e\x3f\x76\x58\x31\xbf\x74\xa4\xf1\x3e\xc4\xe3\x28\x3f\xc4\xe3\x28\x3f\x2e\xe9\x19\x3e\x2e\xe9\x19\x3e\x45\x42\x1b\x3e\xf9\xe9\x30\xbf\x92\x02\xd7\x3e\x2b\x73\x09\x3f\x2b\x73\x09\x3f\xdd\x89\x7a\x3f\xdd\x89\x7a\x3f\x0e\xc6\x7a\xbf\xa6\x7a\x30\xbf\x3c\x11\x96\x3e\xfd\x07\x95\x3e\xfd\x07\x95\x3e\x51\x2a\x81\xbe\x51\x2a\x81\xbe\x67\xcd\x81\xbe\x7c\x0a\x30\xbf\x20\xe5\xe9\x3d\x1b\x46\xb2\xbc\x1b\x46\xb2\xbc\xb8\xe2\x73\xbf\xb8\xe2\x73\xbf\xa2\xf7\x73\x3f\x7f\x99\x2f\xbf\x8d\xb9\xad\xbd\x44\xea\xa8\xbe\x46\xea\xa8\xbe\xba\xaa\xb5\x3e\xba\xaa\xb5\x3e\xb4\x08\xb6\x3e\xad\x27\x2f\xbf\x1e\x8d\x89\xbe\x10\xf8\x0f\xbf\x10\xf8\x0f\xbf\xdd\x2b\x6a\x3f\xdd\x2b\x6a\x3f\x40\x1d\x6a\xbf\x07\xb5\x2e\xbf\xc4\x3f\xcf\xbe\x07\x51\x2a\xbf\x07\x51\x2a\xbf\x5c\xab\xe9\xbe\x5c\xab\xe9\xbe\x68\x96\xe9\xbe\x8c\x41\x2e\xbf\x99\x44\xf0\xbe\x70\x52\x1d\xbf\x70\x52\x1d\xbf\x3d\x35\x5d\xbf\x3d\x35\x5d\xbf\x80\x14\x5d\x3f\x40\xcd\x2d\xbf\xd4\xdf\xe6\xbe\xec\xc6\xd7\xbe\xec\xc6\xd7\xbe\x29\x1f\x0e\x3f\x29\x1f\x0e\x3f\x27\xd0\x0d\x3f\x20\x58\x2d\xbf\x31\xd5\xb4\xbe\x8d\x8e\x05\xbe\x8d\x8e\x05\xbe\x17\xdd\x4c\x3f\x17\xdd\x4c\x3f\x41\xc7\x4c\xbf\x2f\xe2\x2c\xbf\x87\x19\x46\xbe\xee\xb4\x43\x3e\xee\xb4\x43\x3e\x0f\x29\x26\xbf\x0f\x29\x26\xbf\x4b\x9d\x25\xbf\x6b\x6b\x2c\xbf\xe5\x7c\x88\x38\x72\xd5\xef\x3e\x72\xd5\xef\x3e\x77\x1a\x39\xbf\x77\x1a\x39\xbf\x0e\x34\x39\x3f\xd6\xf3\x2b\xbf\xc8\x08\x46\x3e\x81\xff\x22\x3f\x81\xff\x22\x3f\x34\x5a\x3c\x3f\x34\x5a\x3c\x3f\x9b\xb3\x3b\x3f\x71\x7b\x2b\xbf\x96\x9b\xb4\x3e\x5c\x08\x28\x3f\x5c\x08\x28\x3f\xc0\x0e\x22\x3f\xc0\x0e\x22\x3f\x3d\x6f\x22\xbf\x3c\x02\x2b\xbf\xb3\xa0\xe6\x3e\x36\xbc\x05\x3f\x36\xbc\x05\x3f\x9f\x1b\x50\xbf\x9f\x1b\x50\xbf\x9a\x8f\x4f\xbf\x36\x88\x2a\xbf\xfe\x73\xf0\x3e\x1b\x12\x88\x3e\x1b\x12\x88\x3e\xf1\x07\x08\xbf\xf1\x07\x08\xbf\x20\x9f\x08\x3f\x62\x0d\x2a\xbf\x2c\x7b\xd0\x3e\x3b\x66\x5b\xbd\x3b\x66\x5b\xbd\x07\xf3\x60\x3f\x07\xf3\x60\x3f\x9e\xaf\x60\x3f\xbd\x91\x29\xbf\x95\x5f\x8c\x3e\xe8\x9a\xb8\xbe\xe7\x9a\xb8\xbe\x27\xc9\xd6\x3e\x27\xc9\xd6\x3e\xf4\xf9\xd7\xbe\x4b\x15\x29\xbf\x3e\x1a\xc0\x3d\x97\x2f\x15\xbf\x97\x2f\x15\xbf\x72\x82\x6e\xbf\x72\x82\x6e\xbf\x16\x94\x6e\xbf\x0b\x98\x28\xbf\xa4\x1f\xd2\xbd\x46\xdd\x2a\xbf\x46\xdd\x2a\xbf\x93\xf2\x98\xbe\x93\xf2\x98\xbe\xa6\xb3\x99\x3e\xfe\x19\x28\xbf\x68\xed\x8f\xbe\x4e\x1d\x18\xbf\x4e\x1d\x18\xbf\x7f\x6f\x78\x3f\x7f\x6f\x78\x3f\xc6\xbc\x78\x3f\x24\x9b\x27\xbf\x74\x76\xd2\xbe\x08\x8a\xc2\xbe\x08\x8a\xc2\xbe\x06\x46\x2e\x3e\x06\x46\x2e\x3e\xad\x88\x2e\xbe\x7e\x1b\x27\xbf\x19\xc8\xf0\xbe\xe7\x10\x9a\xbd\xe7\x10\x9a\xbd\xd1\x49\x7e\xbf\xd1\x49\x7e\xbf\x24\xab\x7e\xbf\x0d\x9b\x26\xbf\x6c\xc9\xe5\xbe\x79\xa3\x7d\x3e\x79\xa3\x7d\x3e\xd9\xfe\x10\xbd\xd9\xfe\x10\xbd\xbb\xcb\x0d\x3d\xd0\x19\x26\xbf\xa5\x77\xb3\xbe\xf9\x06\x03\x3f\xf9\x06\x03\x3f\xce\x94\x7f\x3f\xce\x94\x7f\x3f\x28\xee\x7f\x3f\xc9\x97\x25\xbf\xb2\x0a\x45\xbe\x83\x64\x27\x3f\x83\x64\x27\x3f\xb4\xca\xd3\xbd\xb4\xca\xd3\xbd\xf5\xb8\xd6\x3d\xf7\x14\x25\xbf\x84\x78\xd5\xba\xc1\xb6\x23\x3f\xc1\xb6\x23\x3f\xf3\xe8\x7b\xbf\xf3\xe8\x7b\xbf\x97\x2d\x7c\xbf\x5b\x91\x24\xbf\x91\xd4\x41\x3e\x6d\x88\xf1\x3e\x6b\x88\xf1\x3e\xed\x4b\x79\x3e\xed\x4b\x79\x3e\x78\x09\x7b\xbe\xf7\x0c\x24\xbf\xed\x1b\xb2\x3e\x80\x11\x43\x3e\x7e\x11\x43\x3e\x07\x04\x73\x3f\x07\x04\x73\x3f\x1d\x2c\x73\x3f\xcc\x87\x23\xbf\xc9\x03\xe5\x3e\x4e\x1d\x0c\xbe\x4f\x1d\x0c\xbe\x1f\x6b\xc3\xbe\x1f\x6b\xc3\xbe\xf8\x34\xc4\x3e\xd8\x01\x23\xbf\x92\x18\xf1\x3e\x87\xe3\xdc\xbe\x87\xe3\xdc\xbe\x07\xc0\x64\xbf\x07\xc0\x64\xbf\xe6\xc5\x64\xbf\x1d\x7b\x22\xbf\xe6\x6b\xd4\x3e\x3a\x3e\x1f\xbf\x3a\x3e\x1f\xbf\x47\xcd\x03\x3f\x47\xcd\x03\x3f\x0a\x07\x04\xbf\x9b\xf3\x21\xbf\xdd\xf1\x93\x3e\xf4\x8b\x29\xbf\xf4\x8b\x29\xbf\x75\x08\x51\x3f\x75\x08\x51\x3f\x5b\xf4\x50\x3f\x52\x6b\x21\xbf\x94\x7b\xea\x3d\x4c\xc0\x0a\xbf\x4d\xc0\x0a\xbf\x3f\xa9\x23\xbf\x3f\xa9\x23\xbf\x8f\xa5\x23\x3f\x46\xe2\x20\xbf\xb2\xe2\xa1\xbd\xf2\x6f\x94\xbe\xf2\x6f\x94\xbe\xc4\xed\x37\xbf\xc4\xed\x37\xbf\xfc\xd8\x37\xbf\x75\x58\x20\xbf\x6b\xaf\x84\xbe\x6b\x10\x07\x3d\x6b\x10\x07\x3d\xea\x3b\x40\x3f\xea\x3b\x40\x3f\x83\x09\x40\xbf\xe0\xcd\x1f\xbf\x54\x9a\xca\xbe\xe5\x3c\xb2\x3e\xe5\x3c\xb2\x3e\x75\xc5\x19\x3f\x75\xc5\x19\x3f\xd3\xc4\x19\x3f\x86\x42\x1f\xbf\xdf\x99\xee\xbe\xc9\x17\x14\x3f\xc9\x17\x14\x3f\x7b\x7e\x58\xbf\x7b\x7e\x58\xbf\x8c\x42\x58\x3f\x6a\xb6\x1e\xbf\x64\xc5\xea\xbe\x58\xde\x2a\x3f\x58\xde\x2a\x3f\x25\x55\xee\xbe\x25\x55\xee\xbe\x26\x75\xee\xbe\x8c\x29\x1e\xbf\xf7\xdc\xbf\xbe\xa3\xc2\x17\x3f\xa3\xc2\x17\x3f\x9e\x91\x6b\x3f\x9e\x91\x6b\x3f\x34\x69\x6b\xbf\xec\x9b\x1d\xbf\x41\x3a\x6a\xbe\x29\xb3\xbe\x3e\x29\xb3\xbe\x3e\x51\xc1\xa1\x3e\x51\xc1\xa1\x3e\xaf\xd8\xa1\x3e\x8c\x0d\x1d\xbf\x6b\x07\x38\xbd\xbb\xc7\x76\x3d\xbf\xc7\x76\x3d\xbb\xbc\x78\xbf\xbb\xbc\x78\xbf\xc8\xac\x78\x3f\x6b\x7e\x1c\xbf\x40\xad\x15\x3e\xb5\xbd\x88\xbe\xb5\xbd\x88\xbe\xe1\xf7\x1e\xbe\xe1\xf7\x1e\xbe\x09\xe9\x1e\xbe\x8b\xee\x1b\xbf\x6c\x3b\xa0\x3e\x7b\x57\x07\xbf\x7a\x57\x07\xbf\x45\x56\x7f\x3f\x45\x56\x7f\x3f\xe4\x58\x7f\xbf\xec\x5d\x1b\xbf\x58\x1f\xdb\x3e\x52\xdf\x28\xbf\x52\xdf\x28\xbf\x50\xcc\x51\xbc\x50\xcc\x51\xbc\x50\x25\x54\xbc\x8f\xcc\x1a\xbf\x31\xe2\xf1\x3e\x44\x90\x20\xbf\x44\x90\x20\xbf\x05\xc0\x7e\xbf\x05\xc0\x7e\xbf\xe5\xd8\x7e\x3f\x75\x3a\x1a\xbf\x8d\xdf\xe0\x3e\xcf\xbb\xe0\xbe\xcf\xbb\xe0\xbe\x77\xee\x3b\x3e\x77\xee\x3b\x3e\x68\x0a\x3c\x3e\x9e\xa7\x19\xbf\xf5\xfd\xaa\x3e\x2b\xa9\x10\xbe\x2d\xa9\x10\xbe\x7e\x90\x76\x3f\x7e\x90\x76\x3f\x0f\xc2\x76\xbf\x0c\x14\x19\xbf\x99\x53\x32\x3e\xa6\x7c\x44\x3e\xa6\x7c\x44\x3e\x21\x00\xb4\xbe\x21\x00\xb4\xbe\x18\x13\xb4\xbe\xbd\x7f\x18\xbf\xff\x34\x65\xbc\xdb\x6e\xf4\x3e\xdb\x6e\xf4\x3e\x65\xaa\x66\xbf\x65\xaa\x66\xbf\xfe\xe4\x66\x3f\xb4\xea\x17\xbf\x79\x77\x4c\xbe\x2d\xcb\x24\x3f\x2d\xcb\x24\x3f\x47\xea\x02\x3f\x47\xea\x02\x3f\xf5\xfa\x02\x3f\xf2\x54\x17\xbf\x9c\x92\xb4\xbe\xd2\x17\x26\x3f\xd1\x17\x26\x3f\x14\x37\x4f\x3f\x14\x37\x4f\x3f\x71\x5d\x4f\xbf\x76\xbe\x16\xbf\xfc\x7f\xe5\xbe\x7a\x57\xfb\x3e\x79\x57\xfb\x3e\x2e\x59\x28\xbf\x2e\x59\x28\xbf\xc8\x5f\x28\xbf\x43\x27\x16\xbf\x83\x2a\xf1\xbe\x1c\x55\x56\x3e\x1c\x55\x56\x3e\x18\x8e\x30\xbf\x18\x8e\x30\xbf\x2a\x97\x30\x3f\x58\x8f\x15\xbf\x5e\xc8\xd5\xbe\x9f\x4f\x00\xbe\x9f\x4f\x00\xbe\xb5\xdf\x48\x3f\xb5\xdf\x48\x3f\x8c\xc3\x48\x3f\xb4\xf6\x14\xbf\x46\xe0\x97\xbe\x15\x6b\xdb\xbe\x15\x6b\xdb\xbe\xaf\x43\x0b\x3f\xaf\x43\x0b\x3f\x1c\x4b\x0b\xbf\x5c\x5d\x14\xbf\xa7\x0e\x03\xbe\xb8\xa4\x1f\xbf\xb8\xa4\x1f\xbf\xce\xf7\x62\xbf\xce\xf7\x62\xbf\xe8\xc3\x62\xbf\x4f\xc3\x13\xbf\x6f\x4f\x7a\x3d\xa6\x25\x29\xbf\xa6\x25\x29\xbf\xc7\xba\xc0\xbe\xc7\xba\xc0\xbe\x4f\xfb\xc0\x3e\x8c\x28\x13\xbf\x04\xf9\x75\x3e\xb7\xb3\x07\xbf\xb6\xb3\x07\xbf\xaf\x3b\x75\x3f\xaf\x3b\x75\x3f\x76\x1d\x75\x3f\x16\x8d\x12\xbf\x64\xe0\xc2\x3e\xcf\x65\x87\xbe\xcd\x65\x87\xbe\x22\x40\x45\x3e\x22\x40\x45\x3e\xa1\xfd\x45\xbe\xcc\xf1\x11\xbf\xb1\x81\xeb\x3e\x11\xfb\x8c\x3d\x11\xfb\x8c\x3d\x17\x9d\x7e\xbf\x17\x9d\x7e\xbf\x4c\xba\x7e\xbf\xae\x56\x11\xbf\x9b\x7a\xee\x3e\x80\x08\xc5\x3e\x80\x08\xc5\x3e\x58\x46\x1f\x3a\x58\x46\x1f\x3a\xd6\xee\xa5\xb9\xd6\xb4\x10\xbf\xd9\x66\xcb\x3e\xe2\x43\x1a\x3f\xe2\x43\x1a\x3f\xc4\x82\x7e\x3f\xc4\x82\x7e\x3f\x00\xc6\x7e\x3f\x42\x0c\x10\xbf\xe8\xfc\x87\x3e\x5d\x86\x2a\x3f\x5d\x86\x2a\x3f\x0e\x28\x49\xbe\x0e\x28\x49\xbe\x3e\x97\x49\x3e\x00\x6b\x0f\xbf\x59\x17\xbc\x3d\x40\x01\x0f\x3f\x40\x01\x0f\x3f\x43\x96\x74\xbf\x43\x96\x74\xbf\xa1\xc6\x74\xbf\x10\xd1\x0e\xbf\x72\x4f\xc5\xbd\x03\x54\x9d\x3e\x03\x54\x9d\x3e\xc7\x91\xc6\x3e\xc7\x91\xc6\x3e\xac\xe4\xc6\xbe\x75\x33\x0e\xbf\xf8\xc8\x89\xbe\xf4\x54\xc0\xbc\xf4\x54\xc0\xbc\x10\xb2\x60\x3f\x10\xb2\x60\x3f\x2c\xb0\x60\x3f\x30\x92\x0d\xbf\xf9\x63\xcc\xbe\xbb\x69\xb2\xbe\xbd\x69\xb2\xbe\x64\x20\x11\xbf\x64\x20\x11\xbf\x0d\x23\x11\x3f\x39\xf0\x0c\xbf\xff\xb0\xee\xbe\xc2\x63\x15\xbf\xc2\x63\x15\xbf\x1c\x0c\x43\xbf\x1c\x0c\x43\xbf\x81\xec\x42\xbf\x91\x4d\x0c\xbf\xee\x60\xeb\xbe\x22\xe6\x2a\xbf\x22\xe6\x2a\xbf\xd1\x9b\x39\x3f\xd1\x9b\x39\x3f\x37\x5c\x39\xbf\x39\xaa\x0b\xbf\x22\x14\xc3\xbe\xac\x0b\x14\xbf\xac\x0b\x14\xbf\x56\x69\x1c\x3f\x56\x69\x1c\x3f\x95\x59\x1c\x3f\x31\x06\x0b\xbf\x15\x72\x78\xbe\x29\x50\xad\xbe\x29\x50\xad\xbe\x35\x8a\x5a\xbf\x35\x8a\x5a\xbf\x91\x14\x5a\x3f\x7b\x61\x0a\xbf\x1b\xf3\x87\xbd\xb1\x6d\x28\xbc\xb1\x6d\x28\xbc\x03\x65\xdc\xbe\x03\x65\xdc\xbe\x8e\x92\xdc\xbe\x18\xbc\x09\xbf\x15\xea\xf5\x3d\x61\x4b\xa4\x3e\x61\x4b\xa4\x3e\xe2\x0d\x72\x3f\xe2\x0d\x72\x3f\x9a\x75\x71\xbf\x07\x16\x09\xbf\xf1\x45\x93\x3e\xbc\x81\x11\x3f\xbc\x81\x11\x3f\xd9\xfc\x68\x3e\xd9\xfc\x68\x3e\x65\x13\x6a\x3e\x48\x6f\x08\xbf\x1f\x10\xd2\x3e\x30\xc9\x2a\x3f\x30\xc9\x2a\x3f\x41\xa1\x7e\xbf\x41\xa1\x7e\xbf\x77\xfd\x7d\x3f\xdf\xc7\x07\xbf\xa3\x27\xf0\x3e\x29\x3f\x17\x3f\x29\x3f\x17\x3f\xf2\xdf\x32\xbc\xf2\xdf\x32\xbc\xcf\xd3\x51\xbc\xca\x1f\x07\xbf\x17\xf9\xe8\x3e\xf8\xcf\xb7\x3e\xfa\xcf\xb7\x3e\x89\x27\x7f\x3f\x89\x27\x7f\x3f\x38\x9a\x7e\xbf\x0c\x77\x06\xbf\x43\xbc\xbd\x3e\x95\xa4\x04\x3d\x95\xa4\x04\x3d\x94\x2b\x56\xbe\x94\x2b\x56\xbe\xc3\x73\x53\xbe\xa2\xcd\x05\xbf\x4c\x71\x6a\x3e\x92\x2f\x9b\xbe\x92\x2f\x9b\xbe\xec\x11\x73\xbf\xec\x11\x73\xbf\x92\xc1\x72\x3f\x91\x23\x05\xbf\x10\x8d\x55\x3d\x42\x07\x0f\xbf\x42\x07\x0f\xbf\x8e\xb1\xd7\x3e\x8e\xb1\xd7\x3e\x54\x46\xd6\x3e\xd7\x78\x04\xbf\x24\xbb\x07\xbe\x93\x9d\x2a\xbf\x92\x9d\x2a\xbf\xa5\x92\x5a\x3f\xa5\x92\x5a\x3f\x89\x88\x5a\xbf\x76\xcd\x03\xbf\x12\xeb\x97\xbe\x13\xec\x18\xbf\x13\xec\x18\xbf\x4e\x2c\x1d\xbf\x4e\x2c\x1d\xbf\xc7\xb2\x1c\xbf\x6f\x21\x03\xbf\x9e\x9a\xd4\xbe\xf8\x0f\xbd\xbe\xf8\x0f\xbd\xbe\x6f\xa2\x36\xbf\x6f\xa2\x36\xbf\x88\xb2\x36\x3f\xc3\x74\x02\xbf\x5a\xb1\xf0\xbe\x91\x4d\x2e\xbd\x99\x4d\x2e\xbd\xf8\xdd\x46\x3f\xf8\xdd\x46\x3f\xfd\xba\x46\x3f\x74\xc7\x01\xbf\xea\xf9\xe7\xbe\x17\x72\x97\x3e\x17\x72\x97\x3e\xc4\xc0\x08\x3f\xc4\xc0\x08\x3f\x18\xb3\x08\xbf\x80\x19\x01\xbf\x67\xe1\xbb\xbe\x5e\x27\x0e\x3f\x5d\x27\x0e\x3f\x4b\x8e\x66\xbf\x4b\x8e\x66\xbf\x4e\x9c\x66\xbf\xea\x6a\x00\xbf\x5a\x70\x66\xbe\x5e\x8b\x2a\x3f\x5e\x8b\x2a\x3f\x5b\xc6\xa5\xbe\x5b\xc6\xa5\xbe\x27\x4c\xa5\x3e\x5d\x77\xff\xbe\x70\xf5\x48\xbd\xf4\x2c\x19\x3f\xf4\x2c\x19\x3f\x03\x1c\x7a\x3f\x03\x1c\x7a\x3f\xef\x22\x7a\x3f\xa0\x17\xfe\xbe\xf9\x65\x09\x3e\xb8\x33\xbd\x3e\xb8\x33\xbd\x3e\x9f\x8e\xbc\x3d\x9f\x8e\xbc\x3d\xc9\x27\xba\xbd\xa7\xb6\xfc\xbe\x1f\x07\x98\x3e\xb5\xe8\x27\x3d\xb5\xe8\x27\x3d\x16\xc6\x7f\xbf\x16\xc6\x7f\xbf\x67\xba\x7f\xbf\x74\x54\xfb\xbe\x3e\x4f\xd4\x3e\x6f\x08\x99\xbe\x6f\x08\x99\xbe\x66\xea\x17\x3e\x66\xea\x17\x3e\x1f\xc3\x18\xbe\x00\xf1\xf9\xbe\xd3\x85\xf0\x3e\x9d\xe9\x0e\xbf\x9d\xe9\x0e\xbf\x91\x8d\x76\x3f\x91\x8d\x76\x3f\x6b\x8b\x76\x3f\x4e\x8c\xf8\xbe\xba\x82\xe8\x3e\x59\xa6\x2a\xbf\x59\xa6\x2a\xbf\x2d\x1c\xc4\xbe\x2d\x1c\xc4\xbe\xa6\x4b\xc4\x3e\x62\x26\xf7\xbe\xac\x93\xbd\x3e\x29\x17\x18\xbf\x29\x17\x18\xbf\x1a\x7e\x5e\xbf\x1a\x7e\x5e\xbf\x35\x90\x5e\xbf\x3e\xbf\xf5\xbe\x2c\x81\x6c\x3e\xc3\x4c\xb8\xbe\xc2\x4c\xb8\xbe\x11\xec\x18\x3f\x11\xec\x18\x3f\x11\xec\x18\xbf\xe4\x56\xf4\xbe\xe6\x4f\x6a\x3d\xe9\x6b\xe1\xbc\xe3\x6b\xe1\xbc\xf0\x97\x38\x3f\xf0\x97\x38\x3f\xdf\xac\x38\x3f\x53\xed\xf2\xbe\xbb\xe4\xff\xbd\x13\x1f\xa0\x3e\x14\x1f\xa0\x3e\x7b\x0e\x47\xbf\x7b\x0e\x47\xbf\x71\xf2\x46\x3f\x90\x82\xf1\xbe\x81\x9c\x93\xbe\xec\x57\x11\x3f\xec\x57\x11\x3f\xb6\xac\x06\xbf\xb6\xac\x06\xbf\x88\xbf\x06\xbf\x99\x16\xf0\xbe\xd5\x32\xd1\xbe\x82\xda\x2a\x3f\x82\xda\x2a\x3f\x2d\x39\x69\x3f\x2d\x39\x69\x3f\x9e\xf5\x68\xbf\x74\xa9\xee\xbe\x06\xa5\xef\xbe\xfe\x7b\x15\x3f\xfe\x7b\x15\x3f\x2b\xc7\x96\x3e\x2b\xc7\x96\x3e\xc1\x26\x97\x3e\x1e\x3b\xed\xbe\x2b\x86\xea\xbe\xf3\xfb\xad\x3e\xf3\xfb\xad\x3e\x35\x9e\x7c\xbf\x35\x9e\x7c\xbf\xe6\x41\x7c\x3f\x9d\xcb\xeb\xbe\xc6\xb1\xc2\xbe\x94\x37\xf9\x3a\x94\x37\xf9\x3a\x1a\x49\x25\xbd\x1a\x49\x25\xbd\x77\xb1\x2b\xbd\xf0\x5a\xea\xbe\xd6\x44\x7c\xbe\xc0\x72\xac\xbe\xc0\x72\xac\xbe\x58\x46\x7f\x3f\x58\x46\x7f\x3f\x89\x01\x7f\xbf\x1b\xe9\xe8\xbe\xb6\x1e\x9c\xbd\xf5\x2b\x15\xbf\xf5\x2b\x15\xbf\xb8\x80\x60\xbe\xb8\x80\x60\xbe\xbe\x75\x5e\xbe\x1e\x76\xe7\xbe\x82\xfc\xd6\x3d\x7e\xdb\x2a\xbf\x7e\xdb\x2a\xbf\x84\x7b\x70\xbf\x84\x7b\x70\xbf\x6c\x77\x70\x3f\xfc\x01\xe6\xbe\x94\x8b\x8a\x3e\x95\x25\x11\xbf\x95\x25\x11\xbf\xfc\x9d\xee\x3e\xfc\x9d\xee\x3e\x1a\xd3\xed\x3e\xb3\x8c\xe4\xbe\x64\xf2\xca\x3e\xd6\x1b\x9e\xbe\xd5\x1b\x9e\xbe\x00\xdc\x50\x3f\x00\xdc\x50\x3f\xd6\x13\x51\xbf\x4a\x16\xe3\xbe\xf6\x93\xed\x3e\x02\xf2\x11\x3d\x02\xf2\x11\x3d\xa7\xb6\x2e\xbf\xa7\xb6\x2e\xbf\x06\x8c\x2e\xbf\xc0\x9e\xe1\xbe\xf5\x75\xed\x3e\x03\xaa\xbd\x3e\x03\xaa\xbd\x3e\xb3\x2c\x22\xbf\xb3\x2c\x22\xbf\x6b\x78\x22\x3f\x19\x26\xe0\xbe\x52\xb6\xca\x3e\x23\x1a\x1a\x3f\x24\x1a\x1a\x3f\xb3\x36\x5a\x3f\xb3\x36\x5a\x3f\xf2\x38\x5a\x3f\x54\xac\xde\xbe\x44\x7d\x8a\x3e\x2a\x41\x2a\x3f\x2a\x41\x2a\x3f\x58\x7e\xce\x3e\x58\x7e\xce\x3e\xcc\xfb\xce\xbe\x75\x31\xdd\xbe\x31\xd4\xd8\x3d\xf2\xa3\x0a\x3f\xf3\xa3\x0a\x3f\x49\x38\x76\xbf\x49\x38\x76\xbf\xf6\x4f\x76\xbf\x7c\xb5\xdb\xbe\xf6\x6e\x97\xbd\xd2\x0b\x88\x3e\xd2\x0b\x88\x3e\xb9\xde\x0f\xbe\xb9\xde\x0f\xbe\xe0\x94\x10\x3e\x6b\x38\xda\xbe\xd4\xb9\x78\xbe\x2c\x76\xae\xbd\x2c\x76\xae\xbd\xcc\x01\x80\x3f\xcc\x01\x80\x3f\x76\x14\x80\x3f\x44\xba\xd8\xbe\xca\xd3\xc0\xbe\xfa\x1b\xd3\xbe\xfa\x1b\xd3\xbe\x5b\x2a\x0b\xbe\x5b\x2a\x0b\xbe\x7d\xa2\x0a\x3e\x0b\x3b\xd7\xbe\x11\x6d\xe9\xbe\x7f\x87\x1f\xbf\x7f\x87\x1f\xbf\x56\x30\x76\xbf\x56\x30\x76\xbf\x8a\x5e\x76\xbf\xc1\xba\xd5\xbe\x94\x63\xf0\xbe\x16\x5f\x28\xbf\x16\x5f\x28\xbf\xec\x1c\xcf\x3e\xec\x1c\xcf\x3e\x26\x01\xcf\xbe\x66\x39\xd4\xbe\x2d\xcf\xd4\xbe\x8f\x73\x01\xbf\x8f\x73\x01\xbf\xc8\xed\x58\x3f\xc8\xed\x58\x3f\xde\x11\x59\x3f\xfc\xb6\xd2\xbe\x55\xbd\x9a\xbe\x98\xcd\x56\xbe\x98\xcd\x56\xbe\xd1\xce\x24\xbf\xd1\xce\x24\xbf\xfd\xdc\x24\x3f\x86\x33\xd1\xbe\x66\x26\x15\xbe\x7d\xa3\x15\x3e\x7b\xa3\x15\x3e\x5a\xf4\x29\xbf\x5a\xf4\x29\xbf\xfb\x06\x2a\xbf\x08\xaf\xcf\xbe\xad\x60\x01\x3d\x88\xdb\xeb\x3e\x87\xdb\xeb\x3e\x33\x54\x55\x3f\x33\x54\x55\x3f\x1b\x81\x55\xbf\x81\x29\xce\xbe\x6c\x12\x51\x3e\x99\xce\x24\x3f\x99\xce\x24\x3f\x6a\x08\xd9\x3e\x6a\x08\xd9\x3e\xee\x1f\xd9\x3e\xf2\xa2\xcc\xbe\xc6\xf1\xb1\x3e\x6f\x86\x24\x3f\x6f\x86\x24\x3f\x30\xa1\x74\xbf\x30\xa1\x74\xbf\x76\xec\x74\x3f\x60\x1b\xcb\xbe\x68\x02\xe2\x3e\x16\x12\xea\x3e\x16\x12\xea\x3e\xad\x28\x15\xbe\xad\x28\x15\xbe\x1b\x6e\x15\xbe\xcc\x92\xc9\xbe\xe9\xfb\xf1\x3e\x81\x72\x0f\x3e\x81\x72\x0f\x3e\x9d\x63\x7f\x3f\x9d\x63\x7f\x3f\x97\xdd\x7f\xbf\x36\x09\xc8\xbe\x27\xaf\xdf\x3e\x63\xd7\x5e\xbe\x61\xd7\x5e\xbe\xa4\x3e\x17\xbe\xa4\x3e\x17\xbe\xc0\x30\x17\xbe\xa1\x7e\xc6\xbe\xb0\xcd\xad\x3e\x59\x48\x03\xbf\x58\x48\x03\xbf\x88\x07\x74\xbf\x88\x07\x74\xbf\xef\xbf\x74\x3f\x10\xf3\xc4\xbe\x95\xeb\x46\x3e\xf3\xf8\x28\xbf\xf2\xf8\x28\xbf\x7f\x65\xdc\x3e\x7f\x65\xdc\x3e\xde\xce\xdc\x3e\x82\x66\xc3\xbe\xb8\xf4\xb2\x3c\x83\xc4\x1d\xbf\x82\xc4\x1d\xbf\x83\x0a\x53\x3f\x83\x0a\x53\x3f\xdc\xe6\x53\xbf\xfe\xd8\xc1\xbe\x45\x27\x1d\xbe\xcf\x93\xc9\xbe\xcd\x93\xc9\xbe\x25\x65\x2d\xbf\x25\x65\x2d\xbf\xc9\xd9\x2d\xbf\x80\x4a\xc0\xbe\xde\x3b\x9d\xbe\x27\x87\x67\xbd\x0f\x87\x67\xbd\x35\xcf\x1e\xbf\x35\xcf\x1e\xbf\x50\x9e\x1f\x3f\x0f\xbb\xbe\xbe\xe7\xcf\xd5\xbe\x25\x46\x98\x3e\x25\x46\x98\x3e\x53\x7c\x5d\x3f\x53\x7c\x5d\x3f\xc6\x15\x5e\x3f\xaa\x2a\xbd\xbe\x06\x79\xf0\xbe\x24\x9d\x10\x3f\x24\x9d\x10\x3f\xf4\x03\xb7\x3e\xf4\x03\xb7\x3e\xab\x3a\xb8\xbe\x54\x99\xbb\xbe\xd3\x94\xe9\xbe\xa9\xe4\x2a\x3f\xa9\xe4\x2a\x3f\x63\xa1\x79\xbf\x63\xa1\x79\xbf\x1d\x33\x7a\xbf\x0c\x07\xba\xbe\xe3\x2f\xc2\xbe\xb2\x29\x13\x3f\xb1\x29\x13\x3f\xc1\xe0\x6c\xbd\xc1\xe0\x6c\xbd\xe6\xb5\x74\x3d\xdb\x73\xb8\xbe\x2e\xb4\x7f\xbe\x5d\x7d\xa0\x3e\x5b\x7d\xa0\x3e\x07\x63\x7e\x3f\x07\x63\x7e\x3f\xe9\xe9\x7e\x3f\xbf\xdf\xb6\xbe\xe3\x66\xaf\xbd\xdf\xff\x24\xbd\xf7\xff\x24\xbd\xd3\x71\x80\xbe\xd3\x71\x80\xbe\x48\xe3\x7e\x3e\xb9\x4a\xb5\xbe\x05\x94\xb8\x3d\x20\xd4\xc3\xbe\x23\xd4\xc3\xbe\x9f\x70\x6a\xbf\x9f\x70\x6a\xbf\xc9\x05\x6b\xbf\xc9\xb4\xb3\xbe\x64\xaf\x81\x3e\x50\xb5\x1c\xbf\x52\xb5\x1c\xbf\xad\xbd\x09\x3f\xad\xbd\x09\x3f\x2e\x43\x09\xbf\xf6\x1d\xb2\xbe\x62\x45\xc3\x3e\x38\x3e\x29\xbf\x3a\x3e\x29\xbf\xd8\x11\x3f\x3f\xd8\x11\x3f\x3f\xa1\xc0\x3f\x3f\x3f\x86\xb0\xbe\x73\xec\xe9\x3e\x7f\xb0\x03\xbf\x80\xb0\x03\xbf\x8e\x23\x46\xbf\x8e\x23\x46\xbf\x46\xd7\x45\x3f\xaa\xed\xae\xbe\x2f\x68\xf0\x3e\xed\x32\x5c\xbe\xef\x32\x5c\xbe\xd1\x1d\x00\xbf\xd1\x1d\x00\xbf\xe0\xd2\x00\xbf\x37\x54\xad\xbe\x3f\xeb\xd5\x3e\x6f\x03\x18\x3e\x6f\x03\x18\x3e\x6a\xee\x6e\x3f\x6a\xee\x6e\x3f\x58\xec\x6e\xbf\xe6\xb9\xab\xbe\x91\x2c\x9e\x3e\xa3\xa2\xef\x3e\xa3\xa2\xef\x3e\x2f\x73\x4e\x3e\x2f\x73\x4e\x3e\x7d\xa3\x50\x3e\xb8\x1e\xaa\xbe\x36\xbc\x21\x3e\x0e\xf8\x25\x3f\x0e\xf8\x25\x3f\x09\x8a\x7f\xbf\x09\x8a\x7f\xbf\x55\xaf\x7f\x3f\xb2\x82\xa8\xbe\xd7\xb7\x6c\xbc\x11\x93\x22\x3f\x12\x93\x22\x3f\x73\xbd\xf7\x3d\x73\xbd\xf7\x3d\x82\x26\xf5\x3d\xd6\xe5\xa6\xbe\x32\x26\x3d\xbe\xce\x09\xdd\x3e\xd1\x09\xdd\x3e\xae\x86\x75\x3f\xae\x86\x75\x3f\x94\xab\x75\xbf\x26\x48\xa5\xbe\x41\xd2\xa8\xbe\xf6\x3c\xca\x3d\x06\x3d\xca\x3d\xcf\x37\xde\xbe\xcf\x37\xde\xbe\xc3\xf3\xdd\xbe\xa4\xa9\xa3\xbe\xd6\x1b\xdc\xbe\xa0\x42\x87\xbe\x9c\x42\x87\xbe\xab\x1b\x51\xbf\xab\x1b\x51\xbf\xa1\x37\x51\x3f\x52\x0a\xa2\xbe\xc7\x8f\xf1\xbe\xf2\x43\x0c\xbf\xf0\x43\x0c\xbf\x70\x09\x34\x3f\x70\x09\x34\x3f\xc8\x08\x34\x3f\x2f\x6a\xa0\xbe\xf9\x5d\xe6\xbe\x77\xaa\x2a\xbf\x76\xaa\x2a\xbf\x73\x70\x15\x3f\x73\x70\x15\x3f\xea\x94\x15\xbf\x43\xc9\x9e\xbe\xb2\x1f\xbc\xbe\xf3\x87\x15\xbf\xf3\x87\x15\xbf\x03\xb2\x65\xbf\x03\xb2\x65\xbf\x48\xd5\x65\xbf\x8d\x27\x9d\xbe\xa3\x34\x71\xbe\x09\x3b\xa6\xbe\x09\x3b\xa6\xbe\x24\x32\x91\xbe\x24\x32\x91\xbe\xaa\x86\x91\x3e\x10\x85\x9b\xbe\x36\xc6\x93\xbd\x8f\xf6\x08\x3d\x7f\xf6\x08\x3d\x8a\xea\x7d\x3f\x8a\xea\x7d\x3f\x33\x3e\x7e\x3f\xcb\xe1\x99\xbe\xf6\x5e\xce\x3d\xea\x6b\xc3\x3e\xe7\x6b\xc3\x3e\x18\x23\x50\xbd\x18\x23\x50\xbd\x63\xb9\x4f\x3d\xc5\x3d\x98\xbe\x2b\x25\x85\x3e\x9e\x33\x1d\x3f\x9c\x33\x1d\x3f\x56\x62\x79\xbf\x56\x62\x79\xbf\x38\xd2\x79\xbf\xfe\x98\x96\xbe\xe7\xd6\xc4\x3e\xab\xcf\x28\x3f\xa9\xcf\x28\x3f\xe8\x80\xc3\x3e\xe8\x80\xc3\x3e\xf9\xee\xc3\xbe\x77\xf3\x94\xbe\x49\x3c\xea\x3e\x38\xdf\x00\x3f\x36\xdf\x00\x3f\x06\xfa\x57\x3f\x06\xfa\x57\x3f\x65\x53\x58\x3f\x31\x4d\x93\xbe\x4a\x6e\xf0\x3e\x0f\xde\x45\x3e\x03\xde\x45\x3e\x7e\xcd\x2b\xbf\x7e\xcd\x2b\xbf\x02\x2b\x2c\x3f\x32\xa6\x91\xbe\x7d\xb0\xd6\x3e\x2a\xb0\x34\xbe\x32\xb0\x34\xbe\xaa\xd8\x1c\xbf\xaa\xd8\x1c\xbf\x18\xee\x1c\xbf\x79\xfe\x8f\xbe\x0f\x82\xa0\x3e\x2b\x09\xfc\xbe\x2e\x09\xfc\xbe\x65\x21\x62\x3f\x65\x21\x62\x3f\xbf\x6f\x62\xbf\x0e\x56\x8e\xbe\xd8\x43\x2a\x3e\x7c\x29\x28\xbf\x7c\x29\x28\xbf\xbc\x9d\x9c\x3e\xbc\x9d\x9c\x3e\xf3\x31\x9c\x3e\xef\xac\x8c\xbe\x76\x52\x36\xbb\x8e\x81\x1e\xbf\x8d\x81\x1e\xbf\xbd\x95\x7d\xbf\xbd\x95\x7d\xbf\xd1\xa5\x7d\x3f\x1c\x03\x8b\xbe\x55\x6f\x2f\xbe\x0c\xc6\xc7\xbe\x0a\xc6\xc7\xbe\x56\x21\x2a\x3d\x56\x21\x2a\x3d\x92\xa9\x2f\x3d\x95\x58\x89\xbe\x6e\x63\xa2\xbe\xbc\x00\x25\xbd\x9c\x00\x25\xbd\xf9\xe9\x79\x3f\xf9\xe9\x79\x3f\xc2\xb4\x79\xbf\x64\xad\x87\xbe\xb2\xa8\xd7\xbe\x06\x12\xa5\x3e\x0b\x12\xa5\x3e\x46\x33\xc6\xbe\x46\x33\xc6\xbe\x01\xd0\xc6\xbe\x88\x01\x86\xbe\x35\x9b\xf0\xbe\x21\xd4\x15\x3f\x24\xd4\x15\x3f\xd2\xb3\x56\xbf\xd2\xb3\x56\xbf\x0d\x4a\x56\x3f\x06\x55\x84\xbe\x8c\x0b\xea\xbe\x71\x8f\x2a\x3f\x74\x8f\x2a\x3f\x40\xc3\x2f\x3f\x40\xc3\x2f\x3f\xec\xee\x2f\x3f\xde\xa7\x82\xbe\x0e\xec\xc4\xbe\x8f\x25\x0a\x3f\x91\x25\x0a\x3f\x18\xab\x17\x3f\x18\xab\x17\x3f\xf5\x25\x17\xbf\x10\xfa\x80\xbe\x32\x29\x86\xbe\x74\x48\x7a\x3e\x7c\x48\x7a\x3e\x62\x66\x66\xbf\x62\x66\x66\xbf\x3e\x64\x66\xbf\x3e\x97\x7e\xbe\x44\x01\xd8\xbd\x96\x92\x02\xbe\x91\x92\x02\xbe\xf0\x91\x88\xbe\xf0\x91\x88\xbe\x98\xab\x87\x3e\x1e\x39\x7b\xbe\xd9\x64\x84\x3d\x4c\x67\xeb\xbe\x4b\x67\xeb\xbe\x63\x30\x7f\x3f\x63\x30\x7f\x3f\xc8\x11\x7f\x3f\xc0\xd9\x77\xbe\x1f\xa7\x67\x3e\x88\xe0\x25\xbf\x89\xe0\x25\xbf\xbd\xbc\xc6\xbd\xbd\xbc\xc6\xbd\x1c\xf1\xc8\x3d\x32\x79\x74\xbe\xa4\x7d\xb7\x3e\x0d\xeb\x21\xbf\x0f\xeb\x21\xbf\x09\x17\x76\xbf\x09\x17\x76\xbf\x25\xe6\x75\xbf\x70\x17\x71\xbe\xed\x64\xe3\x3e\x5a\xd9\xd5\xbe\x5f\xd9\xd5\xbe\x49\xe2\xe6\x3e\x49\xe2\xe6\x3e\x7d\xe1\xe6\xbe\x86\xb4\x6d\xbe\xd9\xf1\xf1\x3e\xbf\x02\x91\xbd\xd7\x02\x91\xbd\x31\x64\x4b\x3f\x31\x64\x4b\x3f\xda\x45\x4b\x3f\x72\x50\x6a\xbe\xb2\x59\xe1\x3e\xac\xf8\x98\x3e\xa4\xf8\x98\x3e\xa1\xe5\x3e\xbf\xa1\xe5\x3e\xbf\xa0\xaf\x3e\x3f\x3d\xeb\x66\xbe\xaf\xd4\xb3\x3e\x56\xf1\x12\x3f\x53\xf1\x12\x3f\x86\x41\x04\xbf\x86\x41\x04\xbf\xa7\x46\x04\xbf\xe7\x84\x63\xbe\xb2\x99\x5e\x3e\x6a\xcc\x2a\x3f\x67\xcc\x2a\x3f\x30\x53\x70\x3f\x30\x53\x70\x3f\x08\xfb\x6f\xbf\x7a\x1d\x60\xbe\x9a\xb9\x64\x3d\xd5\x59\x0c\x3f\xd4\x59\x0c\x3f\x41\x35\x28\x3e\x41\x35\x28\x3e\x36\xd5\x28\x3e\xf8\xb4\x5c\xbe\x35\xce\xe6\xbd\x2f\x4c\x82\x3e\x2e\x4c\x82\x3e\xef\x17\x80\xbf\xef\x17\x80\xbf\xd3\xb7\x7f\x3f\x65\x4b\x59\xbe\x01\x90\x88\xbe\x1e\x49\xf7\xbd\x1a\x49\xf7\xbd\x6c\x72\x5b\x3e\x6c\x72\x5b\x3e\x25\x2f\x5a\x3e\xc2\xe0\x55\xbe\x44\xfa\xc5\xbe\x40\x51\xea\xbe\x3e\x51\xea\xbe\x3d\x63\x6b\x3f\x3d\x63\x6b\x3f\x94\xdb\x6a\xbf\x1c\x75\x52\xbe\xcb\x30\xea\xbe\x8f\xf1\x25\xbf\x8d\xf1\x25\xbf\xca\x96\x10\xbf\xca\x96\x10\xbf\x43\x27\x10\xbf\x72\x08\x4f\xbe\xbb\xae\xf0\xbe\xea\x80\x21\xbf\xe6\x80\x21\xbf\x58\x26\x34\xbf\x58\x26\x34\xbf\x7d\x97\x33\x3f\xce\x9a\x4b\xbe\x06\xb6\xd8\xbe\x39\x40\xd2\xbe\x33\x40\xd2\xbe\x8c\xe2\x55\x3f\x8c\xe2\x55\x3f\x92\x43\x55\x3f\x2f\x2c\x48\xbe\x78\x64\xa5\xbe\x45\x63\x6d\xbd\x0d\x63\x6d\xbd\xf4\x46\xc3\x3e\xf4\x46\xc3\x3e\x67\x8f\xc2\xbe\xf0\xc4\x44\xbe\x26\x89\x3a\xbe\x7d\xa6\xa0\x3e\x84\xa6\xa0\x3e\x7f\xac\x7b\xbf\x7f\xac\x7b\xbf\x0c\x0c\x7b\xbf\x0e\x65\x41\xbe\x48\xca\x97\xbc\x05\x96\x15\x3f\x07\x96\x15\x3f\xe0\xaf\x57\x3a\xe0\xaf\x57\x3a\xdf\x6d\xae\xba\x8a\xe5\x3d\xbe\xbf\xd7\x16\x3e\x8e\x74\x2a\x3f\x8f\x74\x2a\x3f\x8a\x79\x7b\x3f\x8a\x79\x7b\x3f\xf7\x04\x7b\x3f\x61\x46\x3a\xbe\xe8\xcc\x96\x3e\x61\x06\x08\x3f\x61\x06\x08\x3f\xc5\x5d\xc5\xbe\xc5\x5d\xc5\xbe\x20\x5f\xc5\x3e\x35\xc5\x36\xbe\xd3\x3b\xcf\x3e\x98\x47\x65\x3e\x98\x47\x65\x3e\x1a\x7c\x54\xbf\x1a\x7c\x54\xbf\xb8\x52\x54\xbf\x05\x62\x33\xbe\xfc\xbd\xed\x3e\x5e\x78\x20\xbe\x66\x78\x20\xbe\x30\x67\x36\x3f\x30\x67\x36\x3f\x64\x79\x36\xbf\x68\xf5\x2f\xbe\x8b\x96\xee\x3e\x67\x14\xf9\xbe\x6d\x14\xf9\xbe\xbe\x13\x0c\x3f\xbe\x13\x0c\x3f\x02\x25\x0c\x3f\x5c\x7f\x2c\xbe\xac\xc0\xd1\x3e\x10\x4f\x28\xbf\x13\x4f\x28\xbf\x89\xe3\x6d\xbf\x89\xe3\x6d\xbf\x52\x2a\x6e\x3f\x72\x08\x29\xbe\xa1\xe5\x9a\x3e\x81\xfa\x1c\xbf\x84\xfa\x1c\xbf\xa8\x82\x34\xbe\xa8\x82\x34\xbe\x89\xbf\x34\xbe\xa7\x90\x25\xbe\x13\xcb\x21\x3e\x2a\x42\xbc\xbe\x31\x42\xbc\xbe\x35\xde\x7f\x3f\x35\xde\x7f\x3f\xad\x1d\x80\xbf\x08\x18\x22\xbe\x0e\xd1\xc2\xbb\xf0\x42\x93\xba\xf0\x48\x93\xba\x32\x1a\x67\xbe\x32\x1a\x67\xbe\x3d\x0d\x67\xbe\x94\x9e\x1e\xbe\x50\x11\x2d\xbe\xac\x74\xbb\x3e\xa6\x74\xbb\x3e\x0b\x7c\x68\xbf\x0b\x7c\x68\xbf\x69\xe5\x68\x3f\x56\x24\x1b\xbe\xbc\x49\x9f\xbe\xad\xe4\x1c\x3f\xac\xe4\x1c\x3f\xd8\xf7\x17\x3f\xd8\xf7\x17\x3f\xcd\x05\x18\x3f\x4e\xa9\x17\xbe\xc8\x61\xd4\xbe\xbf\x40\x28\x3f\xbf\x40\x28\x3f\x91\xac\x2a\x3f\x91\xac\x2a\x3f\x2c\x0f\x2b\xbf\x84\x2d\x14\xbe\x26\x5a\xef\xbe\x95\xcc\xf7\x3e\x97\xcc\xf7\x3e\x54\xad\x5d\xbf\x54\xad\x5d\xbf\xc7\xb6\x5d\xbf\xf6\xb0\x10\xbe\x6f\xf6\xec\xbe\xea\x96\x19\x3e\xf2\x96\x19\x3e\xd8\xa3\x9f\xbe\xd8\xa3\x9f\xbe\xd7\x6b\xa0\x3e\xb2\x33\x0d\xbe\x25\x96\xcd\xbe\x35\xc9\x6f\xbe\x29\xc9\x6f\xbe\x40\x83\x7e\x3f\x40\x83\x7e\x3f\x20\x8a\x7e\x3f\xb8\xb5\x09\xbe\xb2\x21\x95\xbe\x91\x69\x0a\xbf\x8e\x69\x0a\xbf\xcf\xc6\xc9\xbd\xcf\xc6\xc9\xbd\xbf\xad\xc6\x3d\x0e\x37\x06\xbe\x97\x19\x15\xbe\x66\xc4\x2a\xbf\x64\xc4\x2a\xbf\x60\x13\x74\xbf\x60\x13\x74\xbf\x22\x1a\x74\xbf\xb7\xb7\x02\xbe\x13\x8e\x90\x3c\x92\x11\x12\xbf\x8f\x11\x12\xbf\xd4\x40\xfd\x3e\xd4\x40\xfd\x3e\x61\x89\xfc\xbe\x76\x6f\xfe\xbd\x81\xe4\x36\x3e\xcc\xdf\x90\xbe\xc9\xdf\x90\xbe\xbc\x56\x3f\x3f\xbc\x56\x3f\x3f\x64\x4b\x3f\x3f\x35\x6e\xf7\xbd\x48\xb3\xa2\x3e\x3b\x65\xcc\x3d\x3b\x65\xcc\x3d\xc9\xb7\x4e\xbf\xc9\xb7\x4e\xbf\xcd\x4c\x4e\x3f\xc0\x6b\xf0\xbd\x81\x34\xd6\x3e\xbb\x0e\xe6\x3e\xbb\x0e\xe6\x3e\x40\x2e\xd1\xbe\x40\x2e\xd1\xbe\x97\xfc\xd0\xbe\x15\x68\xe9\xbd\xfa\xcb\xef\x3e\x2d\xda\x25\x3f\x2d\xda\x25\x3f\x03\xd8\x7a\x3f\x03\xd8\x7a\x3f\xfb\x4e\x7a\xbf\x52\x63\xe2\xbd\x1b\x76\xec\x3e\x64\xc7\x20\x3f\x62\xc7\x20\x3f\x6b\x86\xbc\xbb\x6b\x86\xbc\xbb\x37\x48\xc5\xbb\x77\x5d\xdb\xbd\x0f\xaf\xcc\x3e\x47\xc1\xca\x3e\x43\xc1\xca\x3e\xf0\x44\x7a\xbf\xf0\x44\x7a\xbf\x2f\x9c\x79\x3f\x8d\x56\xd4\xbd\x2f\x5c\x94\x3e\x18\x3a\xf3\x3c\xd8\x39\xf3\x3c\xa0\x43\xd8\x3e\xa0\x43\xd8\x3e\x5d\x00\xd8\x3e\x95\x4e\xcd\xbd\x96\x9f\x14\x3e\xb6\xaa\xb1\xbe\xbb\xaa\xb1\xbe\x2d\xfb\x4b\x3f\x2d\xfb\x4b\x3f\x78\x5d\x4b\xbf\x9c\x45\xc6\xbd\xaa\xe5\x88\xbc\x0a\x2b\x1b\xbf\x0c\x2b\x1b\xbf\x32\xaf\x43\xbf\x32\xaf\x43\xbf\x80\x51\x43\xbf\xa4\x3b\xbf\xbd\xa1\xa6\x34\xbe\xfc\xbb\x28\xbf\xfc\xbb\x28\xbf\xd9\x10\xef\xbe\xd9\x10\xef\xbe\x5f\x5c\xee\x3e\xd7\x30\xb8\xbd\xdb\x41\xa1\xbe\xce\x83\xf9\xbe\xce\x83\xf9\xbe\x85\x3c\x77\x3f\x85\x3c\x77\x3f\x59\xd4\x76\x3f\x36\x25\xb1\xbd\xba\xf1\xd4\xbe\xf5\x75\x18\xbe\xf1\x75\x18\xbe\x6a\xe6\x41\x3d\x6a\xe6\x41\x3d\x24\x79\x41\xbd\xbd\x18\xaa\xbd\xd4\x4d\xef\xbe\x42\x95\x76\x3e\x48\x95\x76\x3e\xc6\x46\x7c\xbf\xc6\x46\x7c\xbf\x7d\x15\x7c\xbf\x6b\x0b\xa3\xbd\xdd\x47\xed\xbe\xc8\x57\x0c\x3f\xca\x57\x0c\x3f\x45\x44\xc4\x3e\x45\x44\xc4\x3e\x6e\xfb\xc3\xbe\x60\xfd\x9b\xbd\x7e\x31\xcf\xbe\x87\xe2\x2a\x3f\x89\xe2\x2a\x3f\xdb\x06\x51\x3f\xdb\x06\x51\x3f\x10\x22\x51\x3f\x9e\xee\x94\xbd\xbd\xab\x98\xbe\x2c\xa3\x0e\x3f\x2e\xa3\x0e\x3f\x0e\xff\x3d\xbf\x0e\xff\x3d\xbf\x44\xed\x3d\x3f\x36\xdf\x8d\xbd\xf3\x69\x20\xbe\xd6\x5e\x82\x3e\xd8\x5e\x82\x3e\xbb\x23\xfa\xbe\xbb\x23\xfa\xbe\x7d\xa1\xfa\xbe\x29\xcf\x86\xbd\x9d\x5f\x50\x3b\x1d\x61\x0b\xbe\x1f\x61\x0b\xbe\x15\x4a\x75\x3f\x15\x4a\x75\x3f\xc1\x63\x75\xbf\x10\x7d\x7f\xbd\x2c\x66\x26\x3e\x6e\xcf\xf5\xbe\x6e\xcf\xf5\xbe\xfc\x0e\x81\x3d\xfc\x0e\x81\x3d\x05\x40\x82\x3d\xa4\x5a\x71\xbd\x4f\xf3\x9a\x3e\x30\x6d\x28\xbf\x32\x6d\x28\xbf\xda\x84\x7c\xbf\xda\x84\x7c\xbf\x2e\xa1\x7c\x3f\x3e\x37\x63\xbd\x87\x83\xd0\x3e\xef\x7b\x1b\xbf\xf0\x7b\x1b\xbf\x23\x84\xc1\x3e\x23\x84\xc1\x3e\x6b\x71\xc1\x3e\xde\x12\x55\xbd\x95\xaf\xed\x3e\xe9\xd6\xb0\xbe\xee\xd6\xb0\xbe\x3b\x3e\x51\x3f\x3b\x3e\x51\x3f\x5c\x32\x51\xbf\xa6\xed\x46\xbd\xab\x21\xef\x3e\x25\x93\x18\x3d\xf5\x92\x18\x3d\xe9\x04\x3f\xbf\xe9\x04\x3f\xbf\x0f\xeb\x3e\xbf\x94\xc7\x38\xbd\xa4\xc2\xd4\x3e\xc9\x7a\xd0\x3e\xc5\x7a\xd0\x3e\x75\x1f\xf6\xbe\x75\x1f\xf6\xbe\xa1\xdc\xf5\x3e\xda\xa0\x2a\xbd\x2f\xb6\xa1\x3e\x31\x8c\x22\x3f\x2f\x8c\x22\x3f\x33\xe3\x76\x3f\x33\xe3\x76\x3f\x0b\xa7\x76\x3f\x75\x79\x1c\xbd\x55\xf2\x37\x3e\xab\xea\x23\x3f\xaa\xea\x23\x3f\x5c\x55\x2d\x3d\x5c\x55\x2d\x3d\x9a\xbd\x2c\xbd\x89\x51\x0e\xbd\x68\x97\xba\x3c\x96\x6e\xd7\x3e\x96\x6e\xd7\x3e\x97\xe6\x7b\xbf\x97\xe6\x7b\xbf\x9b\xa0\x7b\xbf\x16\x29\x00\xbd\x5f\xd7\x0b\xbe\x29\x43\x59\x3d\x45\x43\x59\x3d\xd4\xfc\xd0\x3e\xd4\xfc\xd0\x3e\x6c\x9c\xd0\xbe\x8e\x00\xe4\xbc\x53\x5f\x8f\xbe\xc3\xd8\xaa\xbe\xbd\xd8\xaa\xbe\xf9\xd8\x4b\x3f\xf9\xd8\x4b\x3f\xf4\xd0\x4b\x3f\x38\xae\xc7\xbc\x61\x44\xc8\xbe\x9f\x56\x1a\xbf\x99\x56\x1a\xbf\xc6\x4b\x46\xbf\xc6\x4b\x46\xbf\xa0\x1d\x46\x3f\x86\x5b\xab\xbc\x22\x1f\xea\xbe\xe4\xb6\x28\xbf\xdf\xb6\x28\xbf\x91\x51\xe0\xbe\x91\x51\xe0\xbe\x6d\xbb\xe0\xbe\x77\x08\x8f\xbc\xfe\x1e\xf1\xbe\x1d\x9f\xf6\xbe\x15\x9f\xf6\xbe\x6a\x16\x7a\x3f\x6a\x16\x7a\x3f\xed\x1f\x7a\xbf\x99\x6a\x65\xbc\xc9\x8a\xdc\xbe\xc5\x55\x08\xbe\xb7\x55\x08\xbe\xd6\xa0\x82\xbc\xd6\xa0\x82\xbc\x18\xcc\x75\xbc\x0b\xc4\x2c\xbc\xd8\xce\xae\xbe\xa7\xb0\x86\x3e\xad\xb0\x86\x3e\xdb\xfb\x77\xbf\xdb\xfb\x77\xbf\xfb\x36\x78\x3f\xb5\x3b\xe8\xbb\xa1\x66\x5a\xbe\x43\xdc\x10\x3f\x45\xdc\x10\x3f\xdf\xf5\xef\x3e\xdf\xf5\xef\x3e\xf1\xbc\xef\x3e\x1c\xe0\x6d\xbb\x1b\xde\x79\xbd\x23\xb7\x2a\x3f\x21\xb7\x2a\x3f\x88\x82\x3f\x3f\x88\x82\x3f\x3f\x83\xc6\x3f\xbf\xb2\xdf\x34\xb9\x06\xd3\xc8\x3d\x0d\x86\x07\x3f\x0a\x86\x07\x3f\x99\xeb\x51\xbf\x99\xeb\x51\xbf\x6c\x06\x52\xbf\xfa\x3e\x57\x3b\xf1\xc5\x7b\x3e\x63\xeb\x4e\x3e\x51\xeb\x4e\x3e\xa3\xbf\xb8\xbe\xa3\xbf\xb8\xbe\x6e\xc0\xb8\x3e\xc8\xe2\xdc\x3b\x6c\x43\xbb\x3e\x46\xce\x4a\xbe\x60\xce\x4a\xbe\x3c\x97\x7d\x3f\x3c\x97\x7d\x3f\xb0\xa1\x7d\x3f\x72\x11\x27\x3c\xc0\x72\xe3\x3e\x1d\xf9\x06\xbf\x23\xf9\x06\xbf\xf4\xb0\xe1\xbd\xf4\xb0\xe1\xbd\x17\xe0\xe2\x3d\x07\xaf\x5f\x3c\xbd\xf7\xf1\x3e\x9d\xae\x2a\xbf\xa4\xae\x2a\xbf\x2d\xfa\x6f\xbf\x2d\xfa\x6f\xbf\x95\xf1\x6f\xbf\x12\x25\x8c\x3c\xc6\x43\xe5\x3e\xf2\xcb\x10\xbf\xf8\xcb\x10\xbf\x3f\xf5\x0e\x3f\x3f\xf5\x0e\x3f\xc9\x49\x0f\xbf\x21\x71\xa8\x3c\x1c\xd6\xbe\x3e\xd2\x11\x85\xbe\xdc\x11\x85\xbe\xb7\x48\x2b\x3f\xb7\x48\x2b\x3f\xf4\x08\x2b\x3f\xb0\xbb\xc4\x3c\x3f\x10\x83\x3e\xd6\x99\x0f\x3e\xce\x99\x0f\x3e\x43\x61\x61\xbf\x43\x61\x61\xbf\x3a\xc2\x61\x3f\x6a\x04\xe1\x3c\xb9\xb6\xe2\x3d\x21\xca\xfa\x3e\x21\xca\xfa\x3e\xc6\x5d\x79\xbe\xc6\x5d\x79\xbe\xff\x95\x77\xbe\x50\x4b\xfd\x3c\x41\xa4\x3f\xbd\xa0\x5d\x29\x3f\xa2\x5d\x29\x3f\x5c\x83\x7f\x3f\x5c\x83\x7f\x3f\x53\xda\x7f\xbf\x08\xc8\x0c\x3d\x69\xad\x4b\xbe\x44\xb0\x17\x3f\x49\xb0\x17\x3f\x74\xb2\x77\xbe\x74\xb2\x77\xbe\xf3\x01\x7a\xbe\x57\xe9\x1a\x3d\x5a\x58\xa8\xbe\xba\x3a\x9d\x3e\xcb\x3a\x9d\x3e\xb2\x32\x61\xbf\xb2\x32\x61\xbf\x13\x77\x61\x3f\x6a\x09\x29\x3d\x53\x16\xd8\xbe\x37\x1e\xba\xbd\xeb\x1d\xba\xbd\x66\x07\x2c\x3f\x66\x07\x2c\x3f\xd0\xc1\x2c\x3f\x43\x28\x37\x3d\x32\xd9\xef\xbe\x87\x64\xe9\xbe\x73\x64\xe9\xbe\xad\xd3\x0c\x3f\xad\xd3\x0c\x3f\x7e\xcf\x0c\xbf\xb4\x45\x45\x3d\x1f\x10\xed\xbe\x58\x62\x27\xbf\x4e\x62\x27\xbf\x82\x72\x71\xbf\x82\x72\x71\xbf\xb0\x01\x72\xbf\xbf\x61\x53\x3d\x4d\x1e\xd0\xbe\x40\x93\x1c\xbf\x38\x93\x1c\xbf\x7d\x66\xac\xbd\x7d\x66\xac\xbd\xaa\xf7\xab\x3d\x3c\x7c\x61\x3d\xd9\x45\x9c\xbe\xea\x27\xb0\xbe\xde\x27\xb0\xbe\x12\x22\x7c\x3f\x12\x22\x7c\x3f\x13\x9f\x7c\x3f\x2d\x95\x6f\x3d\xd3\x96\x2e\xbe\xf7\x3e\x4f\x3d\x17\x3f\x4f\x3d\xa0\x44\xcf\xbe\xa0\x44\xcf\xbe\xf6\x92\xcf\x3e\x6e\xac\x7d\x3d\x1f\xc6\x8c\xbc\xe5\x92\xda\x3e\xe2\x92\xda\x3e\xfa\xa9\x48\xbf\xfa\xa9\x48\xbf\x01\xf0\x48\xbf\x00\xe1\x85\x3d\x51\x2d\x0d\x3e\x11\x39\x25\x3f\x0b\x39\x25\x3f\x12\xf2\x4b\x3f\x12\xf2\x4b\x3f\x80\x02\x4c\xbf\xd3\xea\x8c\x3d\x46\x30\x8e\x3e\xf1\xe4\x1f\x3f\xe8\xe4\x1f\x3f\xee\x27\xc5\x3e\xee\x27\xc5\x3e\x1a\x85\xc5\x3e\xae\xf3\x93\x3d\xfd\x34\xc6\x3e\xf4\x4a\xbe\x3e\xde\x4a\xbe\x3e\x40\x82\x7d\xbf\x40\x82\x7d\xbf\x70\x80\x7d\x3f\x8e\xfb\x9a\x3d\x20\x96\xe8\x3e\x3c\x7d\xa3\xbc\xdc\x7e\xa3\xbc\xfa\x9d\xe8\x3d\xfa\x9d\xe8\x3d\x90\x85\xe7\x3d\x70\x02\xa2\x3d\xa8\xa5\xf1\x3e\xbe\x13\xcf\xbe\xd9\x13\xcf\xbe\xda\xcb\x6e\x3f\xda\xcb\x6e\x3f\x88\xbf\x6e\xbf\x35\x08\xa9\x3d\x11\x7a\xe0\x3e\xe2\x57\x23\xbf\xee\x57\x23\xbf\xa0\xf4\x15\xbf\xa0\xf4\x15\xbf\xc1\xe1\x15\xbf\xdc\x0c\xb0\x3d\x5f\x01\xb7\x3e\xd3\x0b\x22\xbf\xdd\x0b\x22\xbf\xab\x9c\x22\xbf\xab\x9c\x22\xbf\x2d\x70\x22\x3f\x54\x10\xb7\x3d\x02\x91\x73\x3e\x43\xdf\xc7\xbe\x4d\xdf\xc7\xbe\xed\xc7\x68\x3f\xed\xc7\x68\x3f\xa5\x99\x68\x3f\x9c\x12\xbe\x3d\xeb\xe1\xbd\x3d\xf6\x68\x67\xba\xf6\x6b\x67\xba\x99\x16\x2e\x3e\x99\x16\x2e\x3e\x8a\xae\x2d\xbe\xa6\x13\xc5\x3d\x61\x1e\x7f\xbd\xcc\x4a\xc7\x3e\xd4\x4a\xc7\x3e\x1b\xe4\x7e\xbf\x1b\xe4\x7e\xbf\x58\xc6\x7e\xbf\x6f\x13\xcc\x3d\x05\x81\x57\xbe\xc1\x05\x22\x3f\xc9\x05\x22\x3f\xc9\xfd\xae\x3e\xc9\xfd\xae\x3e\xaa\x51\xaf\xbe\xe1\x11\xd3\x3d\x5b\xfb\xab\xbe\x21\x37\x23\x3f\x2e\x37\x23\x3f\x51\xaa\x51\x3f\x51\xaa\x51\x3f\x51\x80\x51\x3f\xfb\x0e\xda\x3d\x58\xbb\xd9\xbe\x21\x41\xcd\x3e\x3f\x41\xcd\x3e\xa2\xe9\x43\xbf\xa2\xe9\x43\xbf\x84\x11\x44\x3f\xa8\x0a\xe1\x3d\xf5\x28\xf0\xbe\xda\x89\x44\x3c\xfa\x8d\x44\x3c\x9d\xed\xd7\xbe\x9d\xed\xd7\xbe\x1c\x82\xd7\xbe\xe8\x04\xe8\x3d\x34\xf0\xec\xbe\xa5\x7d\xc3\xbe\x87\x7d\xc3\xbe\xd9\x06\x7c\x3f\xd9\x06\x7c\x3f\x91\x2c\x7c\xbf\xa9\xfd\xee\x3d\x42\x7b\xd0\xbe\x8b\x6f\x21\xbf\x7f\x6f\x21\xbf\xd5\xf7\xbb\xbd\xd5\xf7\xbb\xbd\x32\xa7\xbe\xbd\xec\xf4\xf5\x3d\x4c\xe3\x9d\xbe\xa7\x9c\x23\xbf\x9e\x9c\x23\xbf\x26\xc1\x6f\xbf\x26\xc1\x6f\xbf\xf3\xc2\x6f\x3f\x96\xea\xfc\x3d\xb5\x2d\x35\xbe\x85\x94\xce\xbe\x7b\x94\xce\xbe\xc4\x36\x15\x3f\xc4\x36\x15\x3f\x4d\xa0\x15\x3f\x54\xef\x01\x3e\x37\x2d\xdc\xbc\x51\xe3\x57\xbc\x91\xe3\x57\xbc\x36\x65\x21\x3f\x36\x65\x21\x3f\x0a\x1b\x21\xbf\x8a\x68\x05\x3e\x11\xe6\x00\x3e\x70\xd2\xc3\x3e\x62\xd2\xc3\x3e\x1e\x64\x6a\xbf\x1e\x64\x6a\xbf\x21\x99\x6a\xbf\xea\xe0\x08\x3e\x08\xc9\x87\x3e\x58\xa7\x21\x3f\x4c\xa7\x21\x3f\xf2\x17\x16\xbe\xf2\x17\x16\xbe\x32\x54\x14\x3e\x6c\x58\x0c\x3e\x2d\xc1\xc0\x3e\x39\x40\x23\x3f\x2a\x40\x23\x3f\xe1\x60\x7e\x3f\xe1\x60\x7e\x3f\x7c\x3d\x7e\x3f\x0e\xcf\x0f\x3e\xd1\x68\xe5\x3e\x1f\xcb\xcb\x3e\xfb\xca\xcb\x3e\xe5\x75\xc3\xbe\xe5\x75\xc3\xbe\x6e\x16\xc4\x3e\xc6\x44\x13\x3e\x5c\xf6\xf1\x3e\xdb\xa8\x92\x3b\x5b\x9f\x92\x3b\x99\x54\x4a\xbf\x99\x54\x4a\xbf\x5b\xef\x49\xbf\x94\xb9\x16\x3e\x75\x2a\xe5\x3e\x8d\x3f\xc8\xbe\xaf\x3f\xc8\xbe\x2a\x01\x4e\x3f\x2a\x01\x4e\x3f\x9b\xe9\x4d\xbf\x6f\x2d\x1a\x3e\xbb\x6d\xc0\x3e\xe2\xad\x22\xbf\xef\xad\x22\xbf\x1a\x93\xb7\x3e\x1a\x93\xb7\x3e\x71\x05\xb7\x3e\x58\xa0\x1d\x3e\x46\xa6\x87\x3e\x4d\x16\x22\xbf\x55\x16\x22\xbf\xe0\x73\x7f\xbf\xe0\x73\x7f\xbf\x09\xf9\x7e\x3f\x3c\x12\x21\x3e\xb1\x97\x01\x3e\x46\xdb\xc4\xbe\x4a\xdb\xc4\xbe\x40\x16\x39\x3e\x40\x16\x39\x3e\xa8\xe0\x37\x3e\x1d\x83\x24\x3e\xea\xa8\xcb\xbc\x70\xe6\x69\x3c\x70\xe7\x69\x3c\x38\x43\x66\x3f\x38\x43\x66\x3f\x86\xf3\x65\xbf\xfe\xf2\x27\x3e\x9d\xba\x31\xbe\xd0\xd0\xd0\x3e\xe5\xd0\xd0\x3e\x3b\x69\x2b\xbf\x3b\x69\x2b\xbf\x50\x9e\x2a\xbf\xe0\x61\x2b\x3e\xfb\xba\x9b\xbe\xc6\x60\x24\x3f\xd5\x60\x24\x3f\x87\xa8\x08\xbf\x87\xa8\x08\xbf\xd0\x05\x09\x3f\xa8\xcf\x2e\x3e\x41\x70\xce\xbe\x93\xf7\x1f\x3f\xa5\xf7\x1f\x3f\xb2\xf2\x75\x3f\xb2\xf2\x75\x3f\xb7\x3e\x75\x3f\x58\x3c\x32\x3e\x01\xcd\xeb\xbe\x2d\x7d\xb9\x3e\x54\x7d\xb9\x3e\x39\x57\xe8\x3b\x39\x57\xe8\x3b\x35\xfa\x33\xbc\xe6\xa7\x35\x3e\x0c\xda\xf0\xbe\x0c\x51\x30\xbd\xe4\x4f\x30\xbd\xc7\xbc\x76\xbf\xc7\xbc\x76\xbf\xb0\xaf\x76\xbf\x56\x12\x39\x3e\xf1\x23\xdd\xbe\xa8\x08\xdd\xbe\x88\x08\xdd\xbe\x34\xf2\x05\x3f\x34\xf2\x05\x3f\x76\xe2\x04\xbf\xa0\x7b\x3c\x3e\xf6\xc1\xb2\xbe\x2b\x76\x26\xbf\x20\x76\x26\xbf\xb1\xa6\x2c\x3f\xb1\xa6\x2c\x3f\x88\x60\x2d\x3f\xc7\xe3\x3f\x3e\x7d\x36\x6c\xbe\x8c\xa1\x1c\xbf\x87\xa1\x1c\xbf\x97\x15\x65\xbf\x97\x15\x65\xbf\x96\xc5\x64\x3f\xba\x4a\x43\x3e\xc6\xc0\xb5\xbd\xa8\x70\xa9\xbe\xa9\x70\xa9\xbe\x22\x97\x37\xbe\x22\x97\x37\xbe\xcd\x60\x3a\xbe\x79\xb0\x46\x3e\xd2\x63\x7e\x3d\x0f\x0d\xa7\x3d\xd9\x0c\xa7\x3d\xcc\x6d\x7e\x3f\xcc\x6d\x7e\x3f\xb7\xb7\x7e\xbf\xfb\x14\x4a\x3e\xb6\x73\x53\x3e\xc7\x84\xec\x3e\xad\x84\xec\x3e\x8d\xe3\xbe\xbe\x8d\xe3\xbe\xbe\x3b\x93\xbe\xbe\x3f\x78\x4d\x3e\x98\xd6\xa8\x3e\x56\x9e\x28\x3f\x46\x9e\x28\x3f\xf0\x28\x49\xbf\xf0\x28\x49\xbf\x68\x8d\x49\x3f\x39\xda\x50\x3e\x6d\xc3\xd6\x3e\xed\xaf\x17\x3f\xdb\xaf\x17\x3f\x8d\x9d\x4f\x3f\x8d\x9d\x4f\x3f\x2e\x21\x50\x3f\xea\x3a\x54\x3e\x5d\xe6\xee\x3e\x08\x2c\x94\x3e\xe2\x2b\x94\x3e\x04\xec\xa9\x3e\x04\xec\xa9\x3e\x73\x86\xa9\xbe\x49\x9a\x57\x3e\xd6\xde\xee\x3e\x9e\xfd\x04\xbe\xe2\xfd\x04\xbe\x3f\x46\x7f\xbf\x3f\x46\x7f\xbf\x43\xc8\x7f\xbf\x56\xf8\x5a\x3e\x0b\xbf\xd6\x3e\xbb\xac\xfe\xbe\xd7\xac\xfe\xbe\xd4\x16\x6b\x3e\xd4\x16\x6b\x3e\x30\x0b\x6e\xbe\x07\x55\x5e\x3e\xd0\x05\xa9\x3e\xe9\x45\x2a\xbf\xf2\x45\x2a\xbf\x2e\x2d\x5e\x3f\x2e\x2d\x5e\x3f\x02\x03\x5e\x3f\x5c\xb0\x61\x3e\x03\xb6\x54\x3e\x3d\xab\x10\xbf\x3f\xab\x10\xbf\x20\xed\x38\xbf\x20\xed\x38\xbf\x99\x5c\x39\x3f\x4a\x0a\x65\x3e\xd3\x4d\x84\x3d\x45\xb0\x72\xbe\x35\xb0\x72\xbe\x7f\xe6\xe9\xbe\x7f\xe6\xe9\xbe\x71\xfd\xe8\xbe\xd4\x62\x68\x3e\xc0\xcb\xad\xbd\xa8\xbf\x3f\x3e\xcc\xbf\x3f\x3e\xcb\xe6\x7b\x3f\xcb\xe6\x7b\x3f\xf0\xb1\x7b\xbf\xec\xb9\x6b\x3e\x22\x21\x67\xbe\x62\x34\x09\x3f\x71\x34\x09\x3f\x03\x2b\xdb\xbd\x03\x2b\xdb\xbd\x0e\x93\xdb\xbd\x92\x0f\x6f\x3e\xfa\x16\xb0\xbe\x6e\xe3\x2a\x3f\x7f\xe3\x2a\x3f\x82\x79\x6c\xbf\x82\x79\x6c\xbf\x6c\xde\x6b\x3f\xbc\x63\x72\x3e\x25\x08\xdb\xbe\x05\x21\x07\x3f\x16\x21\x07\x3f\x1b\x09\x24\x3f\x1b\x09\x24\x3f\x51\x01\x23\x3f\x6a\xb6\x75\x3e\xce\x2b\xf0\xbe\xa0\x26\x31\x3e\xe2\x26\x31\x3e\x88\xa0\x0d\x3f\x88\xa0\x0d\x3f\xc6\xde\x0d\xbf\x0c\xfc\x78\x3e\x47\x78\xed\xbe\xbd\x60\x81\xbe\xa3\x60\x81\xbe\x7b\x33\x76\xbf\x7b\x33\x76\xbf\xe4\xf2\x74\xbf\xa2\x34\x7c\x3e\x0c\x41\xd3\xbe\xe5\x50\x13\xbf\xdc\x50\x13\xbf\x77\x4b\xb5\x3b\x77\x4b\xb5\x3b\x0b\x32\xb7\xb8\x4c\x88\x7f\x3e\x77\x31\xa4\xbe\xe6\xaf\x29\xbf\xe1\xaf\x29\xbf\x6c\x3b\x75\x3f\x6c\x3b\x75\x3f\xca\xe8\x74\x3f\x85\x7b\x81\x3e\xee\xf3\x49\xbe\x2f\xe6\xf4\xbe\x33\xe6\xf4\xbe\x16\x3a\x10\xbf\x16\x3a\x10\xbf\x39\x8a\x0e\x3f\x88\x28\x83\x3e\x88\xf5\x5e\xbd\x54\xec\xc6\xbd\x8e\xec\xc6\xbd\xd5\xd3\x20\xbf\xd5\xd3\x20\xbf\xdf\xb0\x21\xbf\x2e\xcb\x84\x3e\xc1\xa0\xbf\x3d\x54\x13\xa6\x3e\x3e\x13\xa6\x3e\xa1\xe6\x6d\x3f\xa1\xe6\x6d\x3f\x3f\x0c\x6d\xbf\xce\x6d\x86\x3e\x73\xd5\x6d\x3e\xbf\xc7\x1c\x3f\xb1\xc7\x1c\x3f\x7b\x9f\xab\x3d\x7b\x9f\xab\x3d\xbb\x34\xb5\x3d\x65\x10\x88\x3e\xda\x37\xb2\x3e\xf6\xcb\x25\x3f\xe7\xcb\x25\x3f\x1b\x02\x7a\xbf\x1b\x02\x7a\xbf\x86\x4b\x7a\x3f\x2c\xb2\x89\x3e\xcc\x0c\xdc\x3e\xf3\x66\xd4\x3e\xd9\x66\xd4\x3e\x02\x6a\xfa\x3e\x02\x6a\xfa\x3e\x80\xb3\xf9\x3e\x22\x53\x8b\x3e\x46\x61\xf0\x3e\x7a\x26\x20\x3c\xfa\x23\x20\x3c\xb3\x15\x30\x3f\xb3\x15\x30\x3f\xc3\x7b\x30\xbf\x42\xf3\x8c\x3e\x5b\x4a\xed\x3e\x94\xa3\xcc\xbe\xa1\xa3\xcc\xbe\x8b\xf0\x64\xbf\x8b\xf0\x64\xbf\x3a\x59\x65\xbf\x8b\x92\x8e\x3e\xdb\x25\xd3\x3e\xe1\xa2\x24\xbf\xe3\xa2\x24\xbf\xfc\x2a\x22\xbe\xfc\x2a\x22\xbe\xe6\x07\x21\x3e\xf9\x30\x90\x3e\xaf\x8d\xa4\x3e\xad\x57\x1e\xbf\xaa\x57\x1e\xbf\xe6\xe9\x7c\x3f\xe6\xe9\x7c\x3f\xe3\x49\x7d\x3f\x8c\xce\x91\x3e\x95\x25\x4c\x3e\x03\xc5\xab\xbe\xf4\xc4\xab\xbe\x67\x0e\xdc\xbe\x67\x0e\xdc\xbe\x9e\xd4\xdd\x3e\x3d\x6b\x93\x3e\xf1\x53\x6e\x3d\x74\x92\xb4\x3d\xc8\x92\xb4\x3d\x39\x41\x3b\xbf\x39\x41\x3b\xbf\xd1\xee\x3a\xbf\x0c\x07\x95\x3e\x4f\x2e\xb5\xbd\x68\x4c\xf3\x3e\x7e\x4c\xf3\x3e\x29\x4a\x5e\x3f\x29\x4a\x5e\x3f\x17\xfc\x5e\xbf\xf5\xa1\x96\x3e\x56\xe6\x67\xbe\xb7\xb1\x29\x3f\xc2\xb1\x29\x3f\x02\x19\x57\x3e\x02\x19\x57\x3e\xbd\x99\x53\x3e\xf8\x3b\x98\x3e\x67\x66\xaf\xbe\x1a\x5f\x12\x3f\x23\x5f\x12\x3f\x5c\xef\x7e\xbf\x5c\xef\x7e\xbf\xca\xc9\x7e\x3f\x0e\xd5\x99\x3e\xf2\xf9\xd9\xbe\x39\x46\x75\x3e\x52\x46\x75\x3e\x30\xbd\xc8\x3e\x30\xbd\xc8\x3e\xc8\xeb\xc9\x3e\x36\x6d\x9b\x3e\x70\xa6\xef\xbe\xad\xd7\x46\xbe\xa5\xd7\x46\xbe\x00\x51\x42\x3f\x00\x51\x42\x3f\x2b\x9b\x41\xbf\x6e\x04\x9d\x3e\xb6\x68\xee\xbe\xe4\xca\x0b\xbf\xe7\xca\x0b\xbf\xe7\x9f\x5a\xbf\xe7\x9f\x5a\xbf\x6c\x62\x5a\xbf\xb4\x9a\x9e\x3e\x97\x6f\xd6\xbe\x75\xb2\x2a\xbf\x7b\xb2\x2a\xbf\x1f\xc9\x74\xbe\x1f\xc9\x74\xbe\x12\xfd\x72\x3e\x03\x30\xa0\x3e\x29\x13\xaa\xbe\x9d\x1f\x01\xbf\xa7\x1f\x01\xbf\x2b\x0f\x80\x3f\x2b\x0f\x80\x3f\x89\x52\x7f\x3f\x5c\xc4\xa1\x3e\x0b\x31\x5b\xbe\x2c\x4d\x02\xbe\x5c\x4d\x02\xbe\x89\x2d\xbf\xbe\x89\x2d\xbf\xbe\x1e\x9c\xbe\x3e\xb7\x57\xa3\x3e\x8a\x1b\x9b\xbd\x12\xdc\x9b\x3e\xfb\xdb\x9b\x3e\x92\x7b\x45\xbf\x92\x7b\x45\xbf\xa9\xd2\x44\xbf\x14\xea\xa4\x3e\xd1\x98\x8e\x3d\x41\x3e\x1b\x3f\x38\x3e\x1b\x3f\xa9\x0f\x59\x3f\xa9\x0f\x59\x3f\xdb\x2b\x58\xbf\x70\x7b\xa6\x3e\xf0\x47\x55\x3e\xa3\x34\x26\x3f\x9d\x34\x26\x3f\xce\xe0\x7d\x3e\xce\xe0\x7d\x3e\xeb\xa1\x7e\x3e\xcb\x0b\xa8\x3e\x12\x83\xa7\x3e\x21\xe8\xd3\x3e\x1f\xe8\xd3\x3e\xb8\xf7\x7f\xbf\xb8\xf7\x7f\xbf\x65\x67\x7f\x3f\x1e\x9b\xa9\x3e\xe9\x8f\xd4\x3e\x7e\xe8\x2d\x3a\x7e\xfa\x2d\x3a\x0a\x2c\xbe\x3e\x0a\x2c\xbe\x3e\xe9\xc0\xbc\x3e\x69\x29\xab\x3e\xe7\x99\xed\x3e\x07\x86\xd3\xbe\xf3\x85\xd3\xbe\x3e\x7b\x44\x3f\x3e\x7b\x44\x3f\xe7\xca\x44\xbf\xa7\xb6\xac\x3e\xb4\x55\xf0\x3e\x18\x39\x26\xbf\x0a\x39\x26\xbf\xec\x00\x59\xbf\xec\x00\x59\xbf\x3f\xb4\x58\xbf\xd8\x42\xae\x3e\xd0\x91\xdc\x3e\x2d\xf9\x1a\xbf\x1c\xf9\x1a\xbf\xe0\xb4\x73\xbe\xe0\xb4\x73\xbe\x50\xda\x76\x3e\xf6\xcd\xaf\x3e\x4e\x37\xb4\x3e\x08\x60\x99\xbe\xe7\x5f\x99\xbe\x22\xa1\x7e\x3f\x22\xa1\x7e\x3f\x55\x3d\x7f\x3f\x04\x58\xb1\x3e\x88\x30\x76\x3e\x8f\x83\x0b\x3e\xcd\x83\x0b\x3e\xe2\xf8\xc4\xbe\xe2\xf8\xc4\xbe\x4a\x1b\xc4\x3e\xfa\xe0\xb2\x3e\x95\x46\xda\x3d\xf4\x6c\x03\x3f\xff\x6c\x03\x3f\x9d\x6c\x40\xbf\x9d\x6c\x40\xbf\x3c\xb8\x41\xbf\xd9\x68\xb4\x3e\x2f\xb4\x17\xbd\xaf\xde\x2a\x3f\xb3\xde\x2a\x3f\x16\x0e\x5b\x3f\x16\x0e\x5b\x3f\xe9\xd5\x5b\xbf\x9b\xef\xb5\x3e\xca\x55\x35\xbe\xcb\xe7\x07\x3f\xc8\xe7\x07\x3f\x54\x36\x5a\x3e\x54\x36\x5a\x3e\x0b\xb1\x5c\x3e\x3e\x75\xb7\x3e\xe3\xe9\x99\xbe\x87\x78\x26\x3e\x5c\x78\x26\x3e\x37\x5e\x7d\xbf\x37\x5e\x7d\xbf\xef\xa9\x7e\x3f\xc0\xf9\xb8\x3e\x74\xe2\xca\xbe\x0a\xf4\x8d\xbe\x2e\xf4\x8d\xbe\xea\x03\xd3\x3e\xea\x03\xd3\x3e\x61\x0c\xd4\x3e\x22\x7d\xba\x3e\x0d\x1b\xe9\xbe\x12\x86\x18\xbf\x2a\x86\x18\xbf\x7d\x94\x3a\x3f\x7d\x94\x3a\x3f\x14\x5e\x3b\xbf\x5b\xff\xbb\x3e\x5d\xd9\xf1\xbe\x04\x3b\x27\xbf\x20\x3b\x27\xbf\x5c\xec\x5f\xbf\x5c\xec\x5f\xbf\x38\x1a\x61\xbf\x6e\x80\xbd\x3e\x22\x5f\xe4\xbe\xd9\xe4\xd8\xbe\x11\xe5\xd8\xbe\xb6\xa6\x30\xbe\xb6\xa6\x30\xbe\x40\x6c\x2f\x3e\x54\x00\xbf\x3e\xc6\xf8\xc1\xbe\x40\xff\xe7\xbb\x80\x0b\xe8\xbb\x8b\x13\x7c\x3f\x8b\x13\x7c\x3f\x5e\x00\x7d\x3f\x0e\x7f\xc0\x3e\xe7\xda\x8d\xbe\x80\x51\xd3\x3e\x5e\x51\xd3\x3e\x11\xbc\xe9\xbe\x11\xbc\xe9\xbe\x69\x4d\xec\x3e\x97\xfc\xc1\x3e\xbf\xa9\x19\xbe\x1d\x8f\x26\x3f\x15\x8f\x26\x3f\xe5\x70\x31\xbf\xe5\x70\x31\xbf\x36\x11\x31\xbf\xee\x78\xc3\x3e\x74\xa0\x1b\xbc\xee\xbd\x19\x3f\xf1\xbd\x19\x3f\x0f\x44\x67\x3f\x0f\x44\x67\x3f\x22\xff\x67\xbf\x0f\xf4\xc4\x3e\x04\xf7\x06\x3e\xe0\x5c\x91\x3e\xfe\x5c\x91\x3e\x22\x9b\xe1\x3d\x22\x9b\xe1\x3d\x54\x67\xdb\x3d\xf9\x6d\xc6\x3e\xdc\xa2\x85\x3e\x07\xd1\x22\xbe\x9b\xd0\x22\xbe\x48\x9a\x79\xbf\x48\x9a\x79\xbf\x8c\x9f\x79\x3f\xa8\xe6\xc7\x3e\x0e\x9e\xbb\x3e\x6c\x17\x08\xbf\x49\x17\x08\xbf\x47\xaf\x05\x3f\x47\xaf\x05\x3f\xd8\x49\x06\x3f\x1c\x5e\xc9\x3e\x6c\x93\xe0\x3e\x60\xd4\x2a\xbf\x37\xd4\x2a\xbf\xe3\xfb\x22\x3f\xe3\xfb\x22\x3f\x48\x5c\x22\xbf\x4e\xd4\xca\x3e\xd4\x37\xf1\x3e\x59\x42\x01\xbf\x2f\x42\x01\xbf\x09\x5c\x70\xbf\x09\x5c\x70\xbf\x79\xee\x6f\xbf\x3e\x49\xcc\x3e\x1a\x1a\xec\x3e\xc2\x81\xee\xbd\x92\x80\xee\xbd\x90\xb2\xba\xbc\x90\xb2\xba\xbc\xca\x55\xbb\x3c\xe9\xbc\xcd\x3e\x6d\xbf\xd1\x3e\x2e\x2d\xa6\x3e\x68\x2d\xa6\x3e\x5e\x8b\x74\x3f\x5e\x8b\x74\x3f\x62\xb6\x73\x3f\x4f\x2f\xcf\x3e\x10\x95\xa4\x3e\x0c\xbf\x1e\x3f\x1e\xbf\x1e\x3f\x59\x23\x1b\xbf\x59\x23\x1b\xbf\x65\xc8\x19\x3f\x6b\xa0\xd0\x3e\x44\x68\x51\x3e\x3c\x02\x23\x3f\x3e\x02\x23\x3f\x12\x37\x0e\xbf\x12\x37\x0e\xbf\xdd\xaf\x0e\xbf\x3c\x10\xd2\x3e\xdf\x0c\x8e\x3d\x8d\x84\xbb\x3e\x70\x84\xbb\x3e\x83\xb4\x78\x3f\x83\xb4\x78\x3f\x53\xa0\x77\xbf\xbd\x7e\xd3\x3e\xf4\x24\x93\xbd\x44\x10\x8f\xbd\x3a\x11\x8f\xbd\x3e\xaa\xaf\xbd\x3e\xaa\xaf\xbd\x02\xeb\xa4\xbd\xee\xeb\xd4\x3e\xb5\x78\x53\xbe\x55\x1b\xf3\xbe\xaf\x1b\xf3\xbe\xe3\x20\x6a\xbf\xe3\x20\x6a\xbf\x17\xf8\x69\x3f\xca\x57\xd6\x3e\x30\x37\xa5\xbe\x9a\x28\x2a\xbf\xd0\x28\x2a\xbf\xf4\x51\x31\x3f\xf4\x51\x31\x3f\x3b\x85\x2f\x3f\x52\xc2\xd7\x3e\xc7\xf7\xd1\xbe\x6b\x81\x0d\xbf\xa5\x81\x0d\xbf\xb9\x38\xe7\x3e\xb9\x38\xe7\x3e\xac\xf2\xea\xbe\x80\x2b\xd9\x3e\xdf\x11\xec\xbe\xc2\xe0\x41\xbe\xa2\xe1\x41\xbe\x1d\x3f\x7d\xbf\x1d\x3f\x7d\xbf\x38\x9e\x7d\xbf\x54\x93\xda\x3e\x6f\x42\xf1\xbe\xab\x97\x85\x3e\x4d\x97\x85\x3e\xd3\x86\x53\x3e\xd3\x86\x53\x3e\x60\x30\x4e\xbe\xca\xf9\xdb\x3e\x97\x25\xe1\xbe\x2e\x99\x17\x3f\x0e\x99\x17\x3f\xe0\x56\x59\x3f\xe0\x56\x59\x3f\xf5\x33\x5b\x3f\xe1\x5e\xdd\x3e\x87\x34\xbd\xbe\xf5\x20\x27\x3f\xe8\x20\x27\x3f\x28\xa6\x45\xbf\x28\xa6\x45\xbf\x77\x3a\x46\x3f\x95\xc2\xde\x3e\xa8\xa8\x88\xbe\xb9\x31\xd4\x3e\xca\x31\xd4\x3e\x9f\x9c\xa9\xbe\x9f\x9c\xa9\xbe\x36\x89\xac\xbe\xe6\x24\xe0\x3e\x6a\x4a\x10\xbe\x4f\xa5\x70\xbc\xcf\x9d\x70\xbc\x78\x25\x7e\x3f\x78\x25\x7e\x3f\x76\x10\x80\xbf\xce\x85\xe1\x3e\xca\x34\x33\xbb\x4b\xdb\xdf\xbe\xe9\xda\xdf\xbe\x26\xfd\xab\xbe\x26\xfd\xab\xbe\x52\x78\xac\xbe\x4e\xe5\xe2\x3e\x59\xd6\x0a\x3e\xf6\x9c\x28\xbf\xb6\x9c\x28\xbf\xe0\xf8\x43\xbf\xe0\xf8\x43\xbf\x01\xc9\x45\x3f\x61\x43\xe4\x3e\x52\x1f\x86\x3e\xad\x88\x13\xbf\x63\x88\x13\xbf\x8f\xe6\x59\x3f\x8f\xe6\x59\x3f\x07\xf3\x5b\x3f\x06\xa0\xe5\x3e\x6b\x11\xbb\x3e\x5c\x8d\x68\xbe\x34\x8c\x68\xbe\x33\x19\x45\x3e\x33\x19\x45\x3e\x7e\x36\x42\xbe\x3b\xfb\xe6\x3e\x7c\xb2\xdf\x3e\xfa\xd5\x68\x3e\x06\xd7\x68\x3e\x72\x4d\x7c\xbf\x72\x4d\x7c\xbf\xff\xc1\x7c\xbf\xff\x54\xe8\x3e\x94\xde\xf0\x3e\xa3\x9c\x13\x3f\xd7\x9c\x13\x3f\x24\x8c\xf5\x3e\x24\x8c\xf5\x3e\x28\x35\xf7\xbe\x4b\xad\xe9\x3e\x0a\x28\xed\x3e\x84\x82\x28\x3f\xa4\x82\x28\x3f\x59\xe9\x28\x3f\x59\xe9\x28\x3f\xfe\x33\x28\x3f\x20\x04\xeb\x3e\xef\xed\xd4\x3e\xf6\xa1\xdd\x3e\x00\xa2\xdd\x3e\xf8\x91\x6e\xbf\xf8\x91\x6e\xbf\x1c\xa4\x6e\x3f\x7a\x59\xec\x3e\x5b\x57\xaa\x3e\xe7\x7a\xb7\x3b\xe7\x6f\xb7\x3b\x6c\x0c\xba\xbc\x6c\x0c\xba\xbc\xb4\xf8\x8f\xbc\x5b\xad\xed\x3e\x3e\x37\x62\x3e\x5a\x6f\xd9\xbe\xb9\x6f\xd9\xbe\x1b\x69\x73\x3f\x1b\x69\x73\x3f\xde\xba\x71\xbf\xba\xff\xee\x3e\xcb\xc8\xb8\x3d\xc0\x1b\x28\xbf\x06\x1c\x28\xbf\xbd\x55\x22\xbf\xbd\x55\x22\xbf\x52\xf6\x21\xbf\x99\x50\xf0\x3e\x37\x01\x45\xbd\x01\x83\x14\xbf\x56\x83\x14\xbf\x31\x79\x03\xbf\x31\x79\x03\xbf\x7b\x06\x02\x3f\xf5\x9f\xf1\x3e\xda\x8b\x3a\xbe\x3a\xb6\x6c\xbe\xa8\xb7\x6c\xbe\x04\xd5\x7d\x3f\x04\xd5\x7d\x3f\x07\xe5\x7b\x3f\xce\xed\xf2\x3e\xa2\xe1\x99\xbe\x86\x99\x68\x3e\x28\x98\x68\x3e\xb8\x78\x34\xbe\xb8\x78\x34\xbe\xae\x99\x31\x3e\x1d\x3a\xf4\x3e\x29\x4b\xc9\xbe\xa3\x2c\x14\x3f\x57\x2c\x14\x3f\xbb\x28\x5e\xbf\xbb\x28\x5e\xbf\xf5\x2a\x5d\xbf\xe2\x84\xf5\x3e\x4c\x82\xe7\xbe\x0a\x1a\x28\x3f\xd5\x19\x28\x3f\xfa\xd8\x47\x3f\xfa\xd8\x47\x3f\xe9\x1d\x46\xbf\x19\xce\xf6\x3e\xce\x00\xf2\xbe\x4d\x1d\xd9\x3e\x19\x1d\xd9\x3e\x03\x3b\xa5\x3e\x03\x3b\xa5\x3e\xb0\x78\xa6\x3e\xc2\x15\xf8\x3e\x10\xf1\xe7\xbe\x18\x0b\x26\xbc\xb8\x09\x26\xbc\xba\xe5\x80\xbf\xba\xe5\x80\xbf\x5d\x0f\x80\x3f\xda\x5b\xf9\x3e\x75\x3b\xca\xbe\xe9\x3a\xe1\xbe\x9d\x3a\xe1\xbe\x8b\xea\xc4\x3e\x8b\xea\xc4\x3e\xd5\xa0\xbf\x3e\x60\xa0\xfa\x3e\xfc\x71\x9b\xbe\x29\x0a\x29\xbf\xe6\x09\x29\xbf\x6b\x16\x3c\x3f\x6b\x16\x3c\x3f\x7f\xdc\x3c\xbf\x50\xe3\xfb\x3e\xeb\x27\x3f\xbe\x2b\xf6\x10\xbf\xd0\xf5\x10\xbf\x7a\x23\x66\xbf\x7a\x23\x66\xbf\x73\x51\x64\xbf\xa8\x24\xfd\x3e\x7c\xb7\x5d\xbd\x1e\x37\x4e\xbe\x7e\x35\x4e\xbe\x5a\x8a\xd1\xbd\x5a\x8a\xd1\xbd\xcf\xd1\xe0\x3d\x66\x64\xfe\x3e\xdb\xaa\xa9\x3d\x43\x43\x85\x3e\x17\x44\x85\x3e\xed\x2a\x78\x3f\xed\x2a\x78\x3f\x60\xed\x77\x3f\x89\xa2\xff\x3e\xbd\xd7\x59\x3e\x42\xe8\x18\x3f\xa5\xe8\x18\x3f\x77\x86\x14\xbf\x77\x86\x14\xbf\xf9\x22\x13\x3f\x86\x6f\x00\x3f\xd3\x3c\xa6\x3e\x3a\xcf\x25\x3f\x89\xcf\x25\x3f\xf1\xfb\x0e\xbf\xf1\xfb\x0e\xbf\xd6\x79\x0f\xbf\xf9\x0c\x01\x3f\xc3\x98\xd1\x3e\x3b\xd6\xc5\x3e\xa1\xd6\xc5\x3e\x7d\x18\x79\x3f\x7d\x18\x79\x3f\x30\xea\x78\xbf\x99\xa9\x01\x3f\x04\x6c\xeb\x3e\x28\x6a\x7c\xbd\x28\x69\x7c\xbd\x11\xe4\x05\xbe\x11\xe4\x05\xbe\x8a\xf1\x06\xbe\x66\x45\x02\x3f\x5f\x9c\xf1\x3e\xac\xbf\xf5\xbe\xd6\xbf\xf5\xbe\x83\xb4\x60\xbf\x83\xb4\x60\xbf\xe2\xc5\x60\x3f\x60\xe0\x02\x3f\x71\xb4\xe3\x3e\x2e\x9a\x2a\xbf\x66\x9a\x2a\xbf\xe0\xc5\x40\x3f\xe0\xc5\x40\x3f\x1f\x56\x42\x3f\x86\x7a\x03\x3f\xc8\xe9\xc2\x3e\xa9\xb3\x07\xbf\x01\xb4\x07\xbf\x18\x78\xae\x3e\x18\x78\xae\x3e\xc8\x3e\xab\xbe\xd6\x13\x04\x3f\xb9\x01\x92\x3e\xb0\x0f\x0b\xbe\x67\x11\x0b\xbe\x23\xde\x7e\xbf\x23\xde\x7e\xbf\x46\xc7\x7f\xbf\x4f\xac\x04\x3f\xaf\x25\x2a\x3e\x29\x2b\xa6\x3e\x39\x2a\xa6\x3e\x74\x99\xbe\x3e\x74\x99\xbe\x3e\x20\x55\xc4\xbe\xf0\x43\x05\x3f\x1f\x6b\x09\x3d\xe0\x8d\x20\x3f\x6b\x8d\x20\x3f\x69\x72\x3a\x3f\x69\x72\x3a\x3f\xbc\x34\x39\x3f\xba\xda\x05\x3f\xcc\x48\xd0\xbd\xbb\xb8\x1f\x3f\x53\xb8\x1f\x3f\xcd\xaf\x65\xbf\xcd\xaf\x65\xbf\x7e\xbb\x67\x3f\xa8\x70\x06\x3f\x96\xf2\x69\xbe\x25\x41\xa1\x3e\x8b\x40\xa1\x3e\x66\x6e\xa5\xbd\x66\x6e\xa5\xbd\x58\xf8\x8e\xbd\xbc\x05\x07\x3f\xd3\x37\xac\xbe\x45\xc5\x17\xbe\xeb\xc5\x17\xbe\x33\xeb\x74\x3f\x33\xeb\x74\x3f\x03\xa8\x74\xbf\xf2\x99\x07\x3f\x1a\x4e\xd5\xbe\x78\x02\x0a\xbf\x79\x02\x0a\xbf\xca\x00\x1d\xbf\xca\x00\x1d\xbf\x79\x7c\x1f\xbf\x4c\x2d\x08\x3f\x64\xea\xec\xbe\xa6\x4b\x2a\xbf\x7e\x4b\x2a\xbf\x6c\x3b\x03\xbf\x6c\x3b\x03\xbf\xcc\xbc\x00\x3f\xc9\xbf\x08\x3f\x97\x2b\xf1\xbe\x0f\x32\xed\xbe\x75\x31\xed\xbe\x78\x1f\x7d\x3f\x78\x1f\x7d\x3f\xd5\x15\x7d\x3f\x6a\x51\x09\x3f\x1a\xc7\xe1\xbe\x3a\x6e\x06\xbd\x9a\x67\x06\xbd\x7b\xa2\x56\xbe\x7b\xa2\x56\xbe\x40\x97\x5f\x3e\x29\xe2\x09\x3f\x97\x0b\xc0\xbe\x42\x23\xd4\x3e\x3d\x24\xd4\x3e\x7d\x32\x56\xbf\x7d\x32\x56\xbf\x96\x03\x54\xbf\x05\x72\x0a\x3f\x2a\xc3\x8e\xbe\x9c\x1d\x28\x3f\x1e\x1e\x28\x3f\xdb\x34\x53\x3f\xdb\x34\x53\x3f\x2b\x1f\x53\xbf\xfe\x00\x0b\x3f\xe0\xec\x23\xbe\x49\xb4\x12\x3f\xc3\xb4\x12\x3f\x87\x29\x6a\x3e\x87\x29\x6a\x3e\x29\x6e\x63\x3e\x14\x8f\x0b\x3f\xd2\x7e\xe9\xbc\xb8\x70\x51\x3e\x4e\x72\x51\x3e\x5a\x19\x7e\xbf\x5a\x19\x7e\xbf\x2e\xd0\x7c\x3f\x46\x1c\x0c\x3f\x99\x8f\xd7\x3d\x22\x3f\x88\xbe\x9a\x3e\x88\xbe\xfd\x24\x01\x3f\xfd\x24\x01\x3f\x2d\x8e\x01\x3f\x96\xa8\x0c\x3f\xec\xef\x6b\x3e\xdb\xc6\x1a\xbf\xc0\xc6\x1a\xbf\x9c\x62\x1e\x3f\x9c\x62\x1e\x3f\x5b\x07\x1d\xbf\xfe\x33\x0d\x3f\x04\x81\xac\x3e\x1a\x07\x24\xbf\x2a\x07\x24\xbf\x48\xe8\x76\xbf\x48\xe8\x76\xbf\x9a\xc7\x75\xbf\x7e\xbe\x0d\x3f\x07\x26\xd5\x3e\x46\x49\xb6\xbe\xbb\x49\xb6\xbe\xbd\x2f\xd0\x3d\xbd\x2f\xd0\x3d\xff\x06\xca\xbd\x17\x48\x0e\x3f\x8e\xaf\xec\x3e\xf9\x96\xdb\x3d\x01\x94\xdb\x3d\x76\x83\x62\x3f\x76\x83\x62\x3f\x29\x13\x63\x3f\xc8\xd0\x0e\x3f\xf5\x47\xf1\x3e\x7f\x79\x04\x3f\x04\x79\x04\x3f\x3c\x8e\x42\xbf\x3c\x8e\x42\xbf\x84\x46\x42\x3f\x8d\x58\x0f\x3f\x4a\x9f\xe2\x3e\x27\xb9\x2a\x3f\x9f\xb8\x2a\x3f\x32\xb2\xa1\xbe\x32\xb2\xa1\xbe\xa9\xa0\xa4\xbe\x68\xdf\x0f\x3f\xcd\xee\xc1\x3e\xa1\xd4\xf5\x3e\x93\xd3\xf5\x3e\x1a\x82\x7e\x3f\x1a\x82\x7e\x3f\x35\xc3\x7f\xbf\x56\x65\x10\x3f\x06\xdc\x91\x3e\x47\x42\x50\x3d\xcf\x3a\x50\x3d\x05\x59\xdb\xbe\x05\x59\xdb\xbe\x55\xf1\xd9\xbe\x57\xea\x10\x3f\x72\x83\x2c\x3e\x16\x7b\xcf\xbe\xcc\x7b\xcf\xbe\xf4\xf8\x2b\xbf\xf4\xf8\x2b\xbf\x2a\x0f\x2e\x3f\x6b\x6e\x11\x3f\x24\xff\x1e\x3d\x93\xc4\x27\xbf\xc8\xc4\x27\xbf\xae\xb9\x6e\x3f\xae\xb9\x6e\x3f\x6d\x8f\x6f\x3f\x91\xf1\x11\x3f\xe4\x13\xc0\xbd\xf9\xaf\x12\xbf\x02\xb0\x12\xbf\x52\xaf\x00\xbd\x52\xaf\x00\xbd\x33\x35\xc5\x3c\xc7\x73\x12\x3f\xd4\x20\x60\xbe\x5d\xc6\x4b\xbe\xcd\xc5\x4b\xbe\xc9\xd7\x67\xbf\xc9\xd7\x67\xbf\x0a\xbe\x6a\xbf\x0c\xf5\x12\x3f\xa2\x39\xa7\xbe\xec\xfc\x8d\x3e\x88\xfd\x8d\x3e\x9a\x40\x36\x3f\x9a\x40\x36\x3f\x5f\x59\x37\xbf\x61\x75\x13\x3f\x1c\x32\xd1\xbe\x33\x92\x1c\x3f\xa2\x92\x1c\x3f\x88\x4b\xbd\x3e\x88\x4b\xbd\x3e\x94\xaf\xbf\x3e\xc4\xf4\x13\x3f\x61\xb7\xea\xbe\x1a\x31\x22\x3f\x9d\x31\x22\x3f\xbc\xa0\x7e\xbf\xbc\xa0\x7e\xbf\x54\xdd\x7f\x3f\x33\x73\x14\x3f\x72\xd5\xf1\xbe\x9c\x54\xa9\x3e\xb2\x55\xa9\x3e\x1d\xd4\xc6\x3e\x1d\xd4\xc6\x3e\x79\x38\xc5\x3e\xad\xf0\x14\x3f\x10\x0a\xe6\xbe\xae\x21\x12\xbe\xa2\x1f\x12\xbe\x1c\x66\x32\x3f\x1c\x66\x32\x3f\x18\xab\x34\xbf\x2f\x6a\x15\x3f\xa0\x50\xc8\xbe\x0a\xe5\x0a\xbf\x9d\xe4\x0a\xbf\x8d\x0b\x6b\xbf\x8d\x0b\x6b\xbf\x64\x64\x6c\xbf\xb8\xdf\x15\x3f\xe5\x02\x9b\xbe\xe3\xd1\x29\xbf\x98\xd1\x29\xbf\xa4\x22\x4e\x3b\xa4\x22\x4e\x3b\xe8\x87\x58\xb9\x12\x59\x16\x3f\xbc\x5a\x43\xbe\xa9\x28\xe2\xbe\x67\x28\xe2\xbe\x43\xc4\x6a\x3f\x43\xc4\x6a\x3f\xfb\x51\x6c\x3f\x3d\xd6\x16\x3f\xf5\x64\x83\xbd\xf8\x2f\x17\x3c\x0c\x2d\x17\x3c\x9f\xd0\x34\xbf\x9f\xd0\x34\xbf\xa4\x58\x35\x3f\x05\x52\x17\x3f\x1c\xef\x89\x3d\x80\x0b\xe9\x3e\x0e\x0b\xe9\x3e\xdc\xc5\xc0\xbe\xdc\xc5\xc0\xbe\x60\xf4\xc1\xbe\x6c\xcc\x17\x3f\xf9\x2b\x46\x3e\x79\x53\x2a\x3f\x1a\x53\x2a\x3f\x4e\x96\x7f\x3f\x4e\x96\x7f\x3f\x1c\x01\x80\xbf\x41\x44\x18\x3f\xb2\xfc\x9b\x3e\x8b\x94\x07\x3f\x11\x94\x07\x3f\x57\xa8\xc9\xbe\x57\xa8\xc9\xbe\xd0\xc9\xc8\xbe\x84\xb9\x18\x3f\x99\xd1\xc8\x3e\x8c\x5a\xf0\x3d\x50\x56\xf0\x3d\x91\xb4\x31\xbf\x91\xb4\x31\xbf\xed\x79\x32\x3f\xcc\x2d\x19\x3f\x37\x2d\xe6\x3e\x56\x35\xb6\xbe\x63\x36\xb6\xbe\x0b\xb6\x6d\x3f\x0b\xb6\x6d\x3f\x48\x74\x6e\x3f\x18\xa1\x19\x3f\x41\xd8\xf1\x3e\x7f\xc7\x24\xbf\xf6\xc7\x24\xbf\xc2\xe0\xa5\xbc\xc2\xe0\xa5\xbc\xf7\x5e\xca\x3c\x67\x13\x1a\x3f\xa4\xfb\xea\x3e\x31\x27\x18\xbf\x8b\x27\x18\xbf\xa1\x08\x6b\xbf\xa1\x08\x6b\xbf\x07\x80\x69\xbf\xba\x84\x1a\x3f\x18\x2b\xd2\x3e\x48\x5f\x6e\xbe\x14\x60\x6e\xbe\x6a\xa7\x3c\x3f\x6a\xa7\x3c\x3f\x48\xe3\x3b\xbf\x0c\xf5\x1a\x3f\xb8\x59\xa9\x3e\xf5\x9b\x80\x3e\xe7\x9b\x80\x3e\x37\xd4\xaf\x3e\x37\xd4\xaf\x3e\xa0\x11\xae\x3e\x5f\x64\x1b\x3f\x4d\x5b\x67\x3e\xef\x7a\x1a\x3f\x13\x7b\x1a\x3f\xe2\x91\x80\xbf\xe2\x91\x80\xbf\x09\xb4\x7f\x3f\xb1\xd2\x1b\x3f\xd4\x13\xd5\x3d\xf8\x28\x23\x3f\x44\x29\x23\x3f\x09\xaf\xe1\x3e\x09\xaf\xe1\x3e\xf4\xeb\xe1\x3e\x02\x40\x1c\x3f\x79\xf3\xd1\xbc\xb8\x2b\xab\x3e\x8d\x2c\xab\x3e\x20\x05\x29\x3f\x20\x05\x29\x3f\x2b\x07\x27\xbf\x50\xac\x1c\x3f\x87\xe8\x1c\xbe\x02\xad\x15\xbe\x0e\xab\x15\xbe\x49\x9f\x75\xbf\x49\x9f\x75\xbf\xd6\xfa\x73\xbf\x99\x17\x1d\x3f\x86\xcb\x89\xbe\xba\x9c\x0c\xbf\x38\x9c\x0c\xbf\x34\x5a\xc1\x3d\x34\x5a\xc1\x3d\x4d\xaf\xc7\xbd\xde\x81\x1d\x3f\xd2\xaf\xba\xbe\xf8\x30\x29\xbf\x80\x30\x29\xbf\xae\xae\x62\x3f\xae\xae\x62\x3f\x17\x25\x60\x3f\x1c\xeb\x1d\x3f\x08\x7c\xdd\xbe\x30\x5f\xd7\xbe\x6e\x5e\xd7\xbe\x24\xa5\x4b\xbf\x24\xa5\x4b\xbf\xc1\xe6\x49\x3f\x55\x53\x1e\x3f\x39\x9c\xef\xbe\xc1\x84\x36\x3d\xa9\x88\x36\x3d\x83\x25\x81\xbe\x83\x25\x81\xbe\xbe\xb0\x80\xbe\x86\xba\x1e\x3f\xd3\xc0\xef\xbe\xa8\xad\xf8\x3e\xd5\xad\xf8\x3e\xc3\xb8\x7d\x3f\xc3\xb8\x7d\x3f\x28\xd6\x7c\xbf\xae\x20\x1f\x3f\x80\xf3\xdd\xbe\x6c\xf2\x2a\x3f\x57\xf2\x2a\x3f\x87\x53\x08\xbf\x87\x53\x08\xbf\xa2\x62\x08\xbf\xce\x85\x1f\x3f\x38\x96\xbb\xbe\x38\x92\xfb\x3e\xc0\x91\xfb\x3e\xe2\x37\x11\xbf\xe2\x37\x11\xbf\xb2\x5d\x10\x3f\xe2\xe9\x1f\x3f\x38\x44\x8b\xbe\xfb\x49\x4f\x3d\x37\x44\x4f\x3d\x5e\xf7\x7b\x3f\x5e\xf7\x7b\x3f\xe6\x64\x7b\x3f\xee\x4c\x20\x3f\xc7\x40\x21\xbe\x5f\x7e\xd5\xbe\x3f\x7f\xd5\xbe\x31\x78\x61\xbe\x31\x78\x61\xbe\x6d\xe8\x60\x3e\xeb\xae\x20\x3f\x80\x62\x00\xbd\x51\x33\x29\xbf\xcb\x33\x29\xbf\x1f\x14\x4e\xbf\x1f\x14\x4e\xbf\x07\x78\x4e\xbf\xdc\x0f\x21\x3f\x43\xa5\xc6\x3d\x2c\x17\x0c\xbf\x9f\x17\x0c\xbf\xf0\xe3\x5c\x3f\xf0\xe3\x5c\x3f\x36\x83\x5d\xbf\xbd\x6f\x21\x3f\x28\x46\x5f\x3e\xe9\xc5\x0c\xbe\x67\xc7\x0c\xbe\xcd\x18\xe6\x3d\xcd\x18\xe6\x3d\x35\xb3\xe6\x3d\x90\xce\x21\x3f\x56\x4f\xa5\x3e\x38\x85\xb1\x3e\xb6\x84\xb1\x3e\x6e\x79\x73\xbf\x6e\x79\x73\xbf\x78\x9e\x74\x3f\x54\x2c\x22\x3f\x31\xbf\xce\x3e\xa5\xd1\x24\x3f\x87\xd1\x24\x3f\x8f\xa7\x26\x3f\x8f\xa7\x26\x3f\x25\xf4\x27\x3f\x0b\x89\x22\x3f\xd4\xed\xe8\x3e\x60\x07\x17\x3f\x6a\x07\x17\x3f\x75\x12\xdb\x3e\x75\x12\xdb\x3e\xc0\x54\xda\xbe\xae\xe4\x22\x3f\x24\xfa\xf1\x3e\x12\xf2\x5b\x3e\xd2\xf2\x5b\x3e\xc3\x81\x7f\xbf\xc3\x81\x7f\xbf\xf3\xfb\x7f\xbf\x40\x3f\x23\x3f\xa0\x45\xe9\x3e\x49\x4a\x8e\xbe\xab\x49\x8e\xbe\xcf\x49\xc3\x3e\xcf\x49\xc3\x3e\x12\xcd\xc3\xbe\xbe\x98\x23\x3f\x47\x80\xcf\x3e\xbb\x97\x1e\xbf\x56\x97\x1e\xbf\x18\xdb\x2f\x3f\x18\xdb\x2f\x3f\x3a\x84\x30\x3f\x2a\xf1\x23\x3f\xfe\x97\xa6\x3e\x14\xff\x1e\xbf\xa6\xfe\x1e\xbf\x1b\x0f\x70\xbf\x1b\x0f\x70\xbf\xbc\x1a\x71\x3f\x81\x48\x24\x3f\xc1\x27\x63\x3e\x7d\x63\x90\xbe\xa7\x62\x90\xbe\x15\x9c\x9a\x3d\x15\x9c\x9a\x3d\xd8\x0c\x9d\x3d\xc2\x9e\x24\x3f\xac\x5f\xd1\x3d\x0c\x81\x59\x3e\x72\x82\x59\x3e\x51\x45\x60\x3f\x51\x45\x60\x3f\xf9\xfd\x60\xbf\xed\xf3\x24\x3f\x9d\x2e\xca\xbc\xfe\x26\x17\x3f\x3f\x27\x17\x3f\xa0\x8e\x4a\xbf\xa0\x8e\x4a\xbf\xa2\x3d\x4b\xbf\x02\x48\x25\x3f\x2c\x49\x19\xbe\x56\x72\x24\x3f\x73\x72\x24\x3f\xd9\x49\x69\xbe\xd9\x49\x69\xbe\x7d\xff\x6a\x3e\xff\x9a\x25\x3f\x2a\x0b\x87\xbe\x8f\xc1\xad\x3e\x81\xc1\xad\x3e\x1a\x58\x7a\x3f\x1a\x58\x7a\x3f\x17\x4b\x7b\x3f\xe4\xec\x25\x3f\x54\xa2\xb7\xbe\xf8\x82\x1b\xbe\xb0\x83\x1b\xbe\x64\xae\x13\xbf\x64\xae\x13\xbf\x19\x6c\x13\x3f\xb1\x3d\x26\x3f\xfa\xef\xda\xbe\x00\x35\x0f\xbf\x49\x35\x0f\xbf\x2a\x2d\x00\xbf\x2a\x2d\x00\xbf\x60\x18\x02\xbf\x64\x8d\x26\x3f\x57\x74\xee\xbe\xc8\xeb\x27\xbf\x26\xec\x27\xbf\xfa\xa6\x7c\x3f\xfa\xa6\x7c\x3f\x4c\x7a\x7e\xbf\xfc\xdb\x26\x3f\x3f\xd3\xf0\xbe\xbf\x40\xc6\xbe\x8d\x41\xc6\xbe\x38\x71\x9f\xbe\x38\x71\x9f\xbe\xb6\x72\x9f\xbe\x7a\x29\x27\x3f\xba\xed\xe1\xbe\x59\x30\xc8\x3d\x3d\x2d\xc8\x3d\xeb\x72\x3b\xbf\xeb\x72\x3b\xbf\x1c\x9b\x3c\x3f\xda\x75\x27\x3f\x99\xe0\xc2\xbe\x1f\x51\x07\x3f\xcb\x50\x07\x3f\xbf\x6d\x6b\x3f\xbf\x6d\x6b\x3f\x1d\xb3\x6b\x3f\x1f\xc1\x27\x3f\xdd\xef\x95\xbe\x5a\xe0\x29\x3f\x21\xe0\x29\x3f\xb8\x43\xf9\xbc\xb8\x43\xf9\xbc\x2a\xf5\xd5\x3c\x46\x0b\x28\x3f\xf4\xb2\x3c\xbe\x35\x3d\xda\x3e\x03\x3d\xda\x3e\xf7\x2d\x65\xbf\xf7\x2d\x65\xbf\x9e\x17\x66\xbf\x51\x54\x28\x3f\x94\x66\x80\xbd\xee\x7e\x4f\xbd\x26\x7e\x4f\xbd\x51\x48\x46\x3f\x51\x48\x46\x3f\x01\xea\x45\xbf\x3c\x9c\x28\x3f\x44\x80\x81\x3d\x04\xc9\xff\xbe\xa8\xc8\xff\xbe\xe4\x01\x81\x3e\xe4\x01\x81\x3e\xc0\x7b\x82\x3e\x07\xe3\x28\x3f\x47\xfd\x3c\x3e\x7a\xbf\x2a\xbf\x31\xbf\x2a\xbf\x2b\x4b\x7c\xbf\x2b\x4b\x7c\xbf\x36\x39\x7c\x3f\xb3\x28\x29\x3f\x8b\xde\x95\x3e\xf4\x26\xea\xbe\x38\x26\xea\xbe\x54\xc1\x11\x3f\x54\xc1\x11\x3f\x26\x7a\x11\x3f\x3f\x6d\x29\x3f\xd6\x9b\xc2\x3e\x71\x08\x35\x3c\xd1\x21\x35\x3c\x05\x43\x03\x3f\x05\x43\x03\x3f\xb3\x56\x02\xbf\xaa\xb0\x29\x3f\xb1\x97\xe1\x3e\xab\x91\xf2\x3e\x6b\x92\xf2\x3e\xfb\x48\x80\xbf\xfb\x48\x80\xbf\x7a\xa1\x7e\xbf\xf2\xf2\x29\x3f\xa7\xac\xf0\x3e\xa2\xe6\x2a\x3f\xf2\xe6\x2a\x3f\xb5\x8f\xa9\x3e\xb5\x8f\xa9\x3e\x6c\x1b\xa7\xbe\x18\x34\x2a\x3f\x13\xd7\xee\x3e\x51\x74\xf6\x3e\xb7\x74\xf6\x3e\x49\x7a\x38\x3f\x49\x7a\x38\x3f\xce\x30\x38\x3f\x1b\x74\x2a\x3f\x5d\x43\xdc\x3e\x42\xd0\xab\x3c\x52\xd2\xab\x3c\xcc\x52\x6f\xbf\xcc\x52\x6f\xbf\xdf\xb5\x6e\x3f\xfa\xb2\x2a\x3f\xdb\x4b\xba\x3e\x43\x7d\xe7\xbe\x6d\x7d\xe7\xbe\x77\x38\x88\x3d\x77\x38\x88\x3d\x7b\x05\x8b\x3d\xb5\xf0\x2a\x3f\xc5\x5a\x8b\x3e\x7f\xad\x2a\xbf\xb6\xad\x2a\xbf\xf1\xdf\x60\x3f\xf1\xdf\x60\x3f\xc9\xf1\x5f\xbf\x4c\x2d\x2b\x3f\x07\x7c\x25\x3e\x9c\x8f\xff\xbe\x43\x90\xff\xbe\x18\x75\x4f\xbf\x18\x75\x4f\xbf\x13\x09\x4f\xbf\xbe\x68\x2b\x3f\x0a\x59\x23\x3d\x4e\x39\x38\xbd\x98\x3f\x38\xbd\xa8\x6a\x41\xbe\xa8\x6a\x41\xbe\xf1\x36\x41\x3e\x09\xa3\x2b\x3f\xf6\x09\xad\xbd\x00\x18\xdf\x3e\x28\x17\xdf\x3e\xfa\xca\x77\x3f\xfa\xca\x77\x3f\xba\x12\x78\x3f\x2e\xdc\x2b\x3f\x04\xc1\x4f\xbe\x57\x5b\x2a\x3f\xf4\x5a\x2a\x3f\x6a\x59\x22\xbf\x6a\x59\x22\xbf\xd4\xc8\x22\x3f\x2c\x14\x2c\x3f\x41\x40\x9d\xbe\x7e\xd1\x02\x3f\x30\xd1\x02\x3f\x6c\x88\xd9\xbe\x6c\x88\xd9\xbe\x58\xae\xda\xbe\x02\x4b\x2c\x3f\xea\xbc\xc7\xbe\x2c\x84\x79\x3d\x24\x81\x79\x3d\xf5\x33\x7e\x3f\xf5\x33\x7e\x3f\x03\x0a\x80\xbf\xb1\x80\x2c\x3f\x0a\x60\xe4\xbe\x13\x8b\xd9\xbe\x29\x8b\xd9\xbe\x93\x57\xd7\xbe\x93\x57\xd7\xbe\x2c\x25\xdb\xbe\x36\xb5\x2c\x3f\x5b\x52\xf1\xbe\x6d\x16\x2a\xbf\x4f\x16\x2a\xbf\xf3\xd2\x22\xbf\xf3\xd2\x22\xbf\x23\x2b\x22\x3f\x92\xe8\x2c\x3f\x68\xae\xed\xbe\x8a\x7c\x04\xbf\x48\x7c\x04\xbf\x37\x20\x78\x3f\x37\x20\x78\x3f\x9e\x8f\x78\x3f\xc6\x1a\x2d\x3f\x55\xbe\xd9\xbe\x15\xa1\x8d\xbd\x11\x9e\x8d\xbd\x51\xa7\x4b\xbe\x51\xa7\x4b\xbe\x80\xa1\x4d\x3e\xce\x4b\x2d\x3f\x18\xef\xb6\xbe\x25\xf7\xd6\x3e\x0d\xf8\xd6\x3e\x43\x12\x4c\xbf\x43\x12\x4c\xbf\x7c\x2a\x4c\xbf\xad\x7b\x2d\x3f\x1f\xad\x87\xbe\x24\xfd\x29\x3f\x9d\xfd\x29\x3f\x7d\x9a\x62\x3f\x7d\x9a\x62\x3f\x5b\x51\x63\xbf\x60\xaa\x2d\x3f\xff\x70\x1e\xbe\x4c\xd8\x04\x3f\xbb\xd8\x04\x3f\x1f\xb1\x0e\x3d\x1f\xb1\x0e\x3d\x74\xbd\xf9\x3c\xe7\xd7\x2d\x3f\xfb\x68\x0b\xbd\x63\x89\x8e\x3d\x23\x8c\x8e\x3d\x88\xfd\x6a\xbf\x88\xfd\x6a\xbf\xfa\xf4\x69\x3f\x43\x04\x2e\x3f\x27\xfa\xb5\x3d\xe5\x94\xd7\xbe\x7b\x94\xd7\xbe\xc1\x25\x43\x3f\xc1\x25\x43\x3f\xc0\xdc\x42\x3f\x73\x2f\x2e\x3f\xbe\x8c\x52\x3e\xff\x10\x2a\xbf\xf4\x10\x2a\xbf\x8b\x07\x83\x3e\x8b\x07\x83\x3e\x75\xa5\x81\xbe\x76\x59\x2e\x3f\x76\xe1\x9d\x3e\x7c\xed\x03\xbf\x9d\xed\x03\xbf\xf8\x47\x7c\xbf\xf8\x47\x7c\xbf\xae\x29\x7b\xbf\x4b\x82\x2e\x3f\x49\xc8\xc7\x3e\xa7\x34\x7f\xbd\x5f\x39\x7f\xbd\xb7\xa2\x1a\x3f\xb7\xa2\x1a\x3f\x65\xcb\x19\xbf\xf4\xa9\x2e\x3f\xf6\x2f\xe4\x3e\xbc\x53\xdb\x3e\xde\x52\xdb\x3e\xf5\x38\xe9\x3e\xf5\x38\xe9\x3e\x4b\x23\xea\x3e\x6e\xd0\x2e\x3f\x8d\x38\xf1\x3e\xd2\x52\x2a\x3f\x4c\x52\x2a\x3f\xb6\x8f\x7f\xbf\xb6\x8f\x7f\xbf\x4e\xf7\x7f\x3f\xba\xf5\x2e\x3f\x7c\x0c\xee\x3e\x1f\xbc\x01\x3f\x92\xbb\x01\x3f\x84\x7e\xd4\x3e\x84\x7e\xd4\x3e\x09\x79\xd5\x3e\xd6\x19\x2f\x3f\x4e\xee\xda\x3e\xbb\x2a\x40\x3d\x8b\x22\x40\x3d\x0b\xd8\x22\x3f\x0b\xd8\x22\x3f\x72\x6c\x22\xbf\xc3\x3c\x2f\x3f\xfe\x30\xb9\x3e\x1a\x3c\xe2\xbe\xeb\x3c\xe2\xbe\x5f\x57\x79\xbf\x5f\x57\x79\xbf\x55\x1c\x79\xbf\x81\x5e\x2f\x3f\x22\x1f\x8b\x3e\x27\xac\x2a\xbf\x69\xac\x2a\xbf\x4b\x15\x62\x3e\x4b\x15\x62\x3e\x87\xc0\x61\xbe\x0f\x7f\x2f\x3f\xd5\xa5\x27\x3e\xe5\x36\xfc\xbe\x0b\x37\xfc\xbe\x5c\x42\x47\x3f\x5c\x42\x47\x3f\x7b\x54\x47\x3f\x6c\x9e\x2f\x3f\x61\x02\x38\x3d\x95\x90\xbe\xbc\xad\x8c\xbe\xbc\x7c\xcd\x67\xbf\x7c\xcd\x67\xbf\xfb\x07\x68\x3f\x9a\xbc\x2f\x3f\xb8\x2c\x9d\xbd\x64\xec\xeb\x3e\x06\xed\xeb\x3e\x59\xc7\xa2\x3c\x59\xc7\xa2\x3c\xec\x66\xb1\x3c\x96\xd9\x2f\x3f\xde\xda\x45\xbe\xd0\xe1\x2a\x3f\x4b\xe2\x2a\x3f\x6d\x77\x63\x3f\x6d\x77\x63\x3f\x44\x05\x63\xbf\x62\xf5\x2f\x3f\xa9\xf6\x97\xbe\x41\xca\xf1\x3e\x6d\xcb\xf1\x3e\x5c\x7d\x4e\xbf\x5c\x7d\x4e\xbf\xc4\x8c\x4e\xbf\xfc\x0f\x30\x3f\x60\xeb\xc2\xbe\xee\x9d\x09\xbc\x8e\x75\x09\xbc\xf2\x60\x32\xbe\xf2\x60\x32\xbe\xd8\x0f\x2f\x3e\x64\x29\x30\x3f\x25\xfe\xe0\xbe\xb6\x00\xf8\xbe\x86\xff\xf7\xbe\x1f\x9c\x76\x3f\x1f\x9c\x76\x3f\xb4\x5c\x75\x3f\x9a\x41\x30\x3f\x07\x3e\xf0\xbe\xe4\xbf\x2a\xbf\x66\xbf\x2a\xbf\x0f\x75\x2f\xbf\x0f\x75\x2f\xbf\x71\x83\x2e\x3f\x9d\x58\x30\x3f\xc5\xb5\xef\xbe\xbd\xd5\xe3\xbe\x0d\xd5\xe3\xbe\x76\x4f\xb3\xbe\x76\x4f\xb3\xbe\xf8\xa0\xb3\xbe\x6d\x6e\x30\x3f\xaa\x79\xdf\xbe\xca\xa0\x44\x3d\x12\xa3\x44\x3d\x49\x0b\x7f\x3f\x49\x0b\x7f\x3f\x09\x97\x7e\xbf\x0b\x83\x30\x3f\xb8\xa4\xc0\xbe\x41\x0a\x03\x3f\x2b\x0a\x03\x3f\x1a\x1d\x0a\xbf\x1a\x1d\x0a\xbf\x9e\xb5\x09\xbf\x76\x96\x30\x3f\x8f\x44\x95\xbe\x59\xee\x29\x3f\x0b\xee\x29\x3f\xe7\x67\x03\xbf\xe7\x67\x03\xbf\x18\x41\x03\x3f\xae\xa8\x30\x3f\x44\x6b\x40\xbe\xa5\xda\xd1\x3e\xa5\xd9\xd1\x3e\xf6\xd7\x7f\x3f\xf6\xd7\x7f\x3f\xca\x48\x7f\x3f\xb3\xb9\x30\x3f\x2c\xc9\x93\xbd\x56\x2f\xc3\xbd\x6a\x34\xc3\xbd\xe1\xad\xc4\xbe\xe1\xad\xc4\xbe\xa0\xe6\xc3\x3e\x83\xc9\x30\x3f\x3a\x41\x45\x3d\x50\xcf\x0a\xbf\x04\xd0\x0a\xbf\xda\x30\x27\xbf\xda\x30\x27\xbf\x6c\x1b\x27\xbf\x1f\xd8\x30\x3f\x3c\x35\x29\x3e\xb3\x0a\x28\xbf\x65\x0b\x28\xbf\x8f\xaf\x78\x3f\x8f\xaf\x78\x3f\x77\x60\x78\xbf\x87\xe5\x30\x3f\x7d\x06\x8b\x3e\x17\x64\xbb\xbe\x4f\x65\xbb\xbe\xd8\xe2\x64\xbe\xd8\xe2\x64\xbe\xad\xd5\x63\xbe\xbc\xf1\x30\x3f\xf0\x6c\xb8\x3e\x7d\xd4\x19\x3e\xad\xd2\x19\x3e\xfc\x78\x44\xbf\xfc\x78\x44\xbf\xf2\xd7\x44\x3f\xbb\xfc\x30\x3f\xf5\xe7\xd9\x3e\xab\xfb\x12\x3f\x6d\xfb\x12\x3f\xf4\x57\x6a\x3f\xf4\x57\x6a\x3f\x85\x03\x6b\x3f\x84\x06\x31\x3f\x15\x59\xed\x3e\x5d\x98\x24\x3f\x5f\x98\x24\x3f\x99\x68\x77\xbd\x99\x68\x77\xbd\x00\x1b\x81\x3d\x1a\x0f\x31\x3f\x0b\x8b\xf1\x3e\xf0\x19\xa0\x3e\x76\x1a\xa0\x3e\x30\x81\x5c\xbf\x30\x81\x5c\xbf\x49\x4e\x5c\xbf\x7e\x16\x31\x3f\x21\x44\xe6\x3e\x8c\xc0\x58\xbe\x9c\xbe\x58\xbe\x5d\x14\x58\x3f\x5d\x14\x58\x3f\x46\x52\x58\xbf\xaa\x1c\x31\x3f\xe3\x47\xcc\x3e\x26\xe7\x1a\xbf\x7e\xe6\x1a\xbf\xd9\x8f\xbc\x3d\xd9\x8f\xbc\x3d\xe2\x25\xbb\x3d\xa0\x21\x31\x3f\xfe\x48\xa5\x3e\x53\x09\x1f\xbf\x8f\x08\x1f\xbf\xe8\x7d\x6d\xbf\xe8\x7d\x6d\xbf\x89\x90\x6d\x3f\x60\x25\x31\x3f\xb6\x98\x67\x3e\xa4\x41\x7f\xbe\x80\x3e\x7f\xbe\x95\x7b\x41\x3f\x95\x7b\x41\x3f\xe7\x68\x41\x3f\xec\x27\x31\x3f\x89\xfb\xeb\x3d\xc0\xb3\x8e\x3e\x30\xb5\x8e\x3e\xaf\xe5\x70\x3e\xaf\xe5\x70\x3e\xd5\xca\x72\xbe\x42\x29\x31\x3f\xc5\xcc\x3f\xbb\x60\xf5\x21\x3f\xf1\xf5\x21\x3f\x0b\x67\x78\xbf\x0b\x67\x78\xbf\xec\xde\x78\xbf\x62\x29\x31\x3f\xeb\x5f\xf7\xbd\x05\xcd\x16\x3f\x60\xcd\x16\x3f\x5d\x82\x27\x3f\x5d\x82\x27\x3f\x45\x76\x27\xbf\x4e\x28\x31\x3f\x27\x74\x6c\xbe\x78\x3b\x33\x3e\xdb\x3b\x33\x3e\x00\x53\xbd\x3e\x00\x53\xbd\x3e\x7b\x01\xbe\x3e\x05\x26\x31\x3f\xf8\x19\xa7\xbe\x21\xfc\xb2\xbe\x79\xfc\xb2\xbe\x4b\xe1\x7e\xbf\x4b\xe1\x7e\xbf\x34\xbb\x7e\x3f\x85\x22\x31\x3f\xcc\x68\xcd\xbe\xaf\x6a\x27\xbf\x1d\x6b\x27\xbf\x2f\x99\x0c\x3f\x2f\x99\x0c\x3f\xf4\xa1\x0b\x3f\xd0\x1d\x31\x3f\x36\xc5\xe6\xbe\x4f\x73\x0b\xbf\xf2\x73\x0b\xbf\x4d\x46\xf9\x3e\x4d\x46\xf9\x3e\x26\xa7\xfb\xbe\xe4\x17\x31\x3f\x20\xa1\xf1\xbe\x16\x27\xb9\xbd\x62\x2d\xb9\xbd\x97\x3f\x7f\xbf\x97\x3f\x7f\xbf\xda\xcf\x7f\xbf\xc2\x10\x31\x3f\x38\x59\xed\xbe\x8b\xf6\xd7\x3e\xdc\xf4\xd7\x3e\x15\x62\xde\x3e\x15\x62\xde\x3e\xfc\xc2\xdd\xbe\x6b\x08\x31\x3f\xc3\x3c\xda\xbe\x8f\x87\x2a\x3f\xc1\x86\x2a\x3f\x3c\x3d\x18\x3f\x3c\x3d\x18\x3f\x83\xfe\x18\x3f\xde\xfe\x30\x3f\x64\x87\xb9\xbe\x8c\xef\xf8\x3e\x2d\xee\xf8\x3e\x3e\x2a\x7c\xbf\x3e\x2a\x7c\xbf\xb5\xca\x7c\x3f\x1c\xf4\x30\x3f\x2c\x4c\x8d\xbe\x25\x5c\x8b\xbb\x05\x99\x8b\xbb\xf3\x75\xa3\x3e\xf3\x75\xa3\x3e\xcd\xdc\xa3\x3e\x25\xe8\x30\x3f\x32\xa6\x30\xbe\xda\x19\xfc\xbe\x4e\x1a\xfc\xbe\x38\x51\x30\x3f\x38\x51\x30\x3f\xca\x79\x30\xbf\xf7\xda\x30\x3f\xe7\x60\x6f\xbd\xab\x54\x2a\xbf\x9a\x54\x2a\xbf\x11\x3b\x76\xbf\x11\x3b\x76\xbf\x5f\x54\x76\xbf\x94\xcc\x30\x3f\x8e\x35\x72\x3d\x84\xc2\xd2\xbe\xd5\xc1\xd2\xbe\xcd\xb1\x57\x3e\xcd\xb1\x57\x3e\x74\xb2\x55\xbe\xfc\xbc\x30\x3f\x05\x18\x31\x3e\xae\x46\xdb\x3d\x5e\x4b\xdb\x3d\x4f\x24\x43\x3f\x4f\x24\x43\x3f\x5c\x50\x44\x3f\x2f\xac\x30\x3f\x3a\x4d\x8d\x3e\xf6\x95\x0e\x3f\xba\x96\x0e\x3f\xd7\xf9\x6b\xbf\xd7\xf9\x6b\xbf\xe8\x19\x6d\x3f\x2d\x9a\x30\x3f\x41\x4e\xb9\x3e\xd5\xdc\x25\x3f\xb4\xdd\x25\x3f\xbc\x41\xce\x3d\xbc\x41\xce\x3d\x6d\xad\xcf\x3d\xf4\x86\x30\x3f\xdd\xe1\xd9\x3e\xdc\x0f\xa4\x3e\x9c\x11\xa4\x3e\xbb\xdd\x53\x3f\xbb\xdd\x53\x3f\xe9\xa2\x54\xbf\x52\x70\x30\x3f\xfd\x11\xed\x3e\x07\x3e\x5c\xbe\xec\x3a\x5c\xbe\x2d\x23\x61\xbf\x2d\x23\x61\xbf\x76\xcc\x61\xbf\x45\x56\x30\x3f\xf8\xbb\xf1\x3e\xa4\x6f\x1c\xbf\x09\x6f\x1c\xbf\x2b\x5d\xc6\x3a\x2b\x5d\xc6\x3a\x05\xf2\x8b\x37\x64\x3c\x30\x3f\xc7\x98\xe7\x3e\x64\x49\x1c\xbf\x09\x49\x1c\xbf\x80\x82\x60\x3f\x80\x82\x60\x3f\x28\xb2\x61\x3f\xae\x22\x30\x3f\xa9\x5f\xcf\x3e\xce\xe1\x59\xbe\x8e\xe1\x59\xbe\x18\x34\x54\xbf\x18\x34\x54\xbf\x3e\x0d\x55\x3f\x12\x0b\x30\x3f\xca\x8b\xaa\x3e\xc6\x23\xa6\x3e\x50\x23\xa6\x3e\xf2\x49\xbf\xbd\xf2\x49\xbf\xbd\x65\x77\xc1\xbd\x8f\xf5\x2f\x3f\x59\xc7\x76\x3e\x75\x4f\x26\x3f\xf6\x4e\x26\x3f\xb3\xa6\x6a\x3f\xb3\xa6\x6a\x3f\x19\xda\x6b\xbf\x1a\xdc\x2f\x3f\x1f\x97\x09\x3e\x64\xe2\x0c\x3f\xac\xe1\x0c\x3f\xc4\x01\x46\xbf\xc4\x01\x46\xbf\xf8\x6c\x47\xbf\xb4\xbe\x2f\x3f\x09\x6f\xa1\x3c\xb9\x8d\xb8\x3d\xd9\x86\xb8\x3d\x9a\xfc\x3d\xbe\x9a\xfc\x3d\xbe\x2a\xb6\x39\x3e\x17\xa0\x2f\x3f\x36\xb2\xc4\xbd\x0f\x3d\xdc\xbe\xdf\x3e\xdc\xbe\xc4\xf1\x73\x3f\xc4\xf1\x73\x3f\xac\x7f\x73\x3f\x46\x80\x2f\x3f\x73\xd6\x52\xbe\xac\xc6\x2a\xbf\x86\xc7\x2a\xbf\x79\x33\x39\xbf\x79\x33\x39\xbf\x7c\x6b\x39\x3f\x3f\x5f\x2f\x3f\xd2\x43\x9b\xbe\x82\x1f\xee\xbe\xec\x20\xee\xbe\x2c\x76\x86\xbe\x2c\x76\x86\xbe\x39\x49\x85\xbe\x03\x3d\x2f\x3f\xb1\xbc\xc3\xbe\xbb\x42\x35\x3d\x1b\x3b\x35\x3d\x45\x55\x79\x3f\x45\x55\x79\x3f\x0e\xfe\x78\xbf\x92\x19\x2f\x3f\x0e\x70\xe0\xbe\x55\x60\x06\x3f\x23\x60\x06\x3f\x70\x0c\x2b\xbf\x70\x0c\x2b\xbf\x71\x70\x2b\xbf\xec\xf4\x2e\x3f\x43\xae\xef\xbe\x49\x4f\x28\x3f\x63\x4f\x28\x3f\x3b\x6b\xab\xbe\x3b\x6b\xab\xbe\xb7\x86\xa9\x3e\x11\xcf\x2e\x3f\x88\x97\xf0\xbe\x4b\x75\xb5\x3e\x16\x76\xb5\x3e\x54\x63\x7d\x3f\x54\x63\x7d\x3f\x8b\xa3\x7c\x3f\x01\xa8\x2e\x3f\x81\x27\xe3\xbe\x67\x2f\x3d\xbe\xd7\x2c\x3d\xbe\xaa\xc1\x1d\xbf\xaa\xc1\x1d\xbf\x9c\xd4\x1d\x3f\xbc\x7f\x2e\x3f\x3f\x35\xc8\xbe\xb9\xf6\x19\xbf\xe9\xf5\x19\xbf\x78\x3e\xcb\xbe\x78\x3e\xcb\xbe\xce\x8d\xc9\xbe\x42\x56\x2e\x3f\x64\x64\xa1\xbe\x00\xda\x1d\xbf\x19\xd9\x1d\xbf\xf4\xd1\x7f\x3f\xf4\xd1\x7f\x3f\xa8\xc6\x7e\xbf\x93\x2b\x2e\x3f\x32\x15\x62\xbe\xdd\x4d\x61\xbe\x53\x4a\x61\xbe\x45\x9a\x11\xbf\x45\x9a\x11\xbf\x05\xe8\x10\xbf\xaf\xff\x2d\x3f\x0d\x2b\xe8\xbd\x8a\x23\xa6\x3e\x15\x25\xa6\x3e\xbd\x32\xe5\xbe\xbd\x32\xe5\xbe\x12\x80\xe5\x3e\x96\xd2\x2d\x3f\x52\xbc\x2b\x3a\x52\xdd\x26\x3f\xe5\xdd\x26\x3f\x06\x07\x80\x3f\x06\x07\x80\x3f\xaa\xc7\x7f\x3f\x47\xa4\x2d\x3f\x9c\x8d\xea\x3d\x12\x7b\x0a\x3f\x63\x7b\x0a\x3f\xec\x4c\x05\xbf\xec\x4c\x05\xbf\xd7\xef\x04\x3f\xc5\x74\x2d\x3f\xcc\xde\x62\x3e\x0c\x69\x87\x3d\x34\x69\x87\x3d\x3e\x93\xfd\xbe\x3e\x93\xfd\xbe\xf3\x92\xfd\xbe\x0f\x44\x2d\x3f\xb4\x84\xa1\x3e\x95\x41\xe8\xbe\x23\x42\xe8\xbe\x0a\x4c\x80\x3f\x0a\x4c\x80\x3f\x64\xf9\x7f\xbf\x26\x12\x2d\x3f\x0c\x16\xc8\x3e\x29\xe0\x2a\xbf\xb3\xe0\x2a\xbf\xc6\x1e\xf6\xbe\xc6\x1e\xf6\xbe\xd1\x40\xf4\xbe\x08\xdf\x2c\x3f\x62\xe8\xe2\x3e\x1c\xd9\xdb\xbe\x97\xda\xdb\xbe\x67\x73\x08\xbf\x67\x73\x08\xbf\xdc\xf7\x08\x3f\xb8\xaa\x2c\x3f\x82\x72\xf0\x3e\xf8\x5b\xcc\x3d\x18\x55\xcc\x3d\x3e\xfc\x7f\x3f\x3e\xfc\x7f\x3f\x42\x9a\x7f\x3f\x33\x75\x2c\x3f\x5b\xf4\xef\x3e\x73\xbf\x0f\x3f\x90\xbe\x0f\x3f\x89\x5c\xe3\xbe\x89\x5c\xe3\xbe\x6f\x41\xe1\x3e\x7a\x3e\x2c\x3f\x86\x7f\xe1\x3e\xfb\x51\x24\x3f\x2c\x51\x24\x3f\x0e\x51\x10\xbf\x0e\x51\x10\xbf\x1f\x60\x11\xbf\x8c\x06\x2c\x3f\x60\xf5\xc5\x3e\x89\x8a\x91\x3e\x3d\x89\x91\x3e\x8f\x4e\x7e\x3f\x8f\x4e\x7e\x3f\xea\xe3\x7e\xbf\x6e\xcd\x2b\x3f\xb6\xf7\x9e\x3e\x19\xf1\x88\xbe\xeb\xf1\x88\xbe\x4a\x0e\xd1\xbe\x4a\x0e\xd1\xbe\x44\x1f\xd1\xbe\x1e\x93\x2b\x3f\xf2\xa1\x5d\x3e\xc8\xf4\x22\xbf\xeb\xf4\x22\xbf\x73\xbf\x17\xbf\x73\xbf\x17\xbf\x25\x24\x18\x3f\x9c\x57\x2b\x3f\xf7\x3d\xe1\x3d\xcc\xee\x11\xbf\xa2\xee\x11\xbf\x42\x75\x7d\x3f\x42\x75\x7d\x3f\x52\x13\x7e\x3f\xe6\x1a\x2b\x3f\xa1\xc7\x31\xbb\xc3\xc2\xe4\xbd\x4e\xbf\xe4\xbd\xd8\x09\xc3\xbe\xd8\x09\xc3\xbe\xe3\xff\xc3\x3e\xff\xdc\x2a\x3f\xc5\xd1\xeb\xbd\x5f\xdc\xd8\x3e\xac\xdd\xd8\x3e\x14\x58\x1d\xbf\x14\x58\x1d\xbf\x2a\x69\x1d\xbf\xe7\x9d\x2a\x3f\x64\x29\x62\xbe\x90\xd6\x2a\x3f\x5b\xd7\x2a\x3f\x1f\xa3\x7c\x3f\x1f\xa3\x7c\x3f\xf6\x53\x7d\xbf\x9d\x5d\x2a\x3f\x0c\xad\xa0\xbe\x07\xdb\xe6\x3e\xbd\xdc\xe6\x3e\xd9\x3a\xb8\xbe\xd9\x3a\xb8\xbe\xcd\xf5\xb9\xbe\x22\x1c\x2a\x3f\xa2\x08\xc7\xbe\xce\x51\x9f\xbd\x4e\x4b\x9f\xbd\x46\x9c\x21\xbf\x46\x9c\x21\xbf\xff\x3d\x21\x3f\x77\xd9\x29\x3f\xe0\xfd\xe1\xbe\xc1\x84\x0d\xbf\x10\x84\x0d\xbf\xeb\x37\x7c\x3f\xeb\x37\x7c\x3f\x89\xb4\x7c\x3f\x9c\x95\x29\x3f\x4f\x0b\xf0\xbe\x30\xf4\x24\xbf\xb5\xf3\x24\xbf\xaf\xd7\xb0\xbe\xaf\xd7\xb0\xbe\x2f\x16\xb3\x3e\x92\x50\x29\x3f\xfa\x6d\xf0\xbe\x7e\xa1\x93\xbe\x0c\xa1\x93\xbe\x87\xc4\x24\xbf\x87\xc4\x24\xbf\xb9\x9c\x23\xbf\x56\x0a\x29\x3f\xa3\x29\xe3\xbe\x86\x9d\x89\x3e\x6c\x9d\x89\x3e\x06\xe5\x7c\x3f\x06\xe5\x7c\x3f\xcc\x3d\x7c\xbf\xec\xc2\x28\x3f\x60\x09\xc9\xbe\xc8\x94\x23\x3f\x75\x94\x23\x3f\x90\x95\xaf\xbe\x90\x95\xaf\xbe\x0d\x84\xaf\xbe\x54\x7a\x28\x3f\xd9\x8f\xa3\xbe\x6b\x02\x10\x3f\xdd\x01\x10\x3f\x16\xd5\x24\xbf\x16\xd5\x24\xbf\xee\x87\x24\x3f\x8c\x30\x28\x3f\xf6\xc5\x69\xbe\xf4\xcf\xbd\x3d\x30\xca\xbd\x3d\x7f\x60\x7c\x3f\x7f\x60\x7c\x3f\x34\x0b\x7c\x3f\x98\xe5\x27\x3f\xeb\xa7\xfe\xbd\x1f\xa2\xe2\xbe\xb9\xa3\xe2\xbe\x63\x11\xb0\xbe\x63\x11\xb0\xbe\x11\x5b\xaf\x3e\x75\x99\x27\x3f\x6c\x19\x5d\xbc\xd6\xee\x2a\xbf\xa1\xef\x2a\xbf\x18\x94\x23\xbf\x18\x94\x23\xbf\xc6\x16\x24\xbf\x24\x4c\x27\x3f\x09\xbb\xc8\x3d\x05\x3e\xd8\xbe\x6a\x3f\xd8\xbe\x2d\xb3\x7b\x3f\x2d\xb3\x7b\x3f\x90\x39\x7c\xbf\xa7\xfd\x26\x3f\xea\xd0\x50\x3e\x7e\x29\xf6\x3d\x4a\x25\xf6\x3d\x9a\x61\xb2\xbe\x9a\x61\xb2\xbe\xd3\x96\xb2\xbe\xfe\xad\x26\x3f\x2e\xbf\x98\x3e\x7a\x18\x14\x3f\x30\x18\x14\x3f\x32\xd6\x21\xbf\x32\xd6\x21\xbf\x7c\x5a\x22\x3f\x28\x5d\x26\x3f\x4a\x83\xc0\x3e\x01\xcd\x20\x3f\xf9\xcc\x20\x3f\x62\x13\x7c\x3f\x62\x13\x7c\x3f\x97\xc3\x7c\x3f\x28\x0b\x26\x3f\xfb\x83\xdd\x3e\x52\x54\x6d\x3e\x46\x55\x6d\x3e\x77\xe2\xb8\xbe\x77\xe2\xb8\xbe\x8b\x15\xb9\x3e\xfc\xb7\x25\x3f\x3f\x2b\xee\x3e\x2f\x3c\xa8\xbe\x42\x3b\xa8\xbe\x9e\x72\x1e\xbf\x9e\x72\x1e\xbf\x4d\x45\x1f\xbf\xa5\x63\x25\x3f\x02\x97\xf1\x3e\xaa\xf7\x27\xbf\x08\xf7\x27\xbf\x83\x20\x7c\x3f\x83\x20\x7c\x3f\xc2\x80\x7d\xbf\x25\x0e\x25\x3f\x56\x9e\xe7\x3e\x32\x3b\x04\xbf\x74\x3a\x04\xbf\xfd\x3c\xc0\xbe\xfd\x3c\xc0\xbe\xad\xb6\xc2\xbe\x7b\xb7\x24\x3f\xb0\xd8\xd0\x3e\xc4\xb6\xf0\xbb\x04\x56\xf0\xbb\x84\x45\x1b\xbf\x84\x45\x1b\xbf\xb5\xb8\x1a\x3f\xa9\x5f\x24\x3f\x9c\x8f\xae\x3e\x13\xaa\x01\x3f\xc2\xaa\x01\x3f\x77\xe5\x7d\x3f\x77\xe5\x7d\x3f\x10\x4a\x7e\x3f\xae\x06\x24\x3f\x8a\xb1\x82\x3e\xbb\x93\x28\x3f\x46\x94\x28\x3f\x43\x00\xcd\xbe\x43\x00\xcd\xbe\xde\x70\xcf\x3e\x8b\xac\x23\x3f\xa7\x5c\x1f\x3e\x91\x21\xad\x3e\x3b\x22\xad\x3e\x2f\x0d\x16\xbf\x2f\x0d\x16\xbf\xdd\x9e\x14\xbf\x3f\x51\x23\x3f\x72\xcc\x42\x3d\x4b\x92\x67\xbe\xeb\x91\x67\xbe\xd6\xd3\x7f\x3f\xd6\xd3\x7f\x3f\xcb\x0d\x7f\xbf\xce\xf4\x22\x3f\xf7\x18\x81\xbd\xf9\x8a\x20\xbf\x21\x8b\x20\xbf\x18\xb5\xde\xbe\x18\xb5\xde\xbe\xfe\x3d\xdf\xbe\x36\x97\x22\x3f\xaa\x26\x2e\xbe\xb8\x9d\x13\xbf\x1a\x9e\x13\xbf\xe5\xae\x0d\xbf\xe5\xae\x0d\xbf\x6c\xeb\x0c\x3f\x79\x38\x22\x3f\xc6\x12\x89\xbe\xe2\xce\xdf\xbd\x62\xd3\xdf\xbd\x70\x03\x80\x3f\x70\x03\x80\x3f\x2e\xb1\x7f\x3f\x95\xd8\x21\x3f\x0a\x8c\xb3\xbe\x62\x40\xe0\x3e\x0b\x3f\xe0\x3e\x49\x1f\xf1\xbe\x49\x1f\xf1\xbe\x69\xf7\xf1\x3e\x8e\x77\x21\x3f\x6a\x3e\xd4\xbe\x25\xd2\x2a\x3f\x70\xd1\x2a\x3f\xbc\x38\x04\xbf\xbc\x38\x04\xbf\xd8\x87\x03\xbf\x63\x15\x21\x3f\xca\x5e\xe9\xbe\x6a\x29\xd3\x3e\x18\x28\xd3\x3e\x89\x2b\x80\x3f\x89\x2b\x80\x3f\x54\xf7\x7f\xbf\x15\xb2\x20\x3f\x8f\xcd\xf1\xbe\x04\x56\x12\xbe\x28\x58\x12\xbe\x2c\xa9\x03\xbf\x2c\xa9\x03\xbf\x5c\xa8\x03\xbf\xa4\x4d\x20\x3f\xdc\x3b\xed\xbe\x75\x39\x18\xbf\xd0\x39\x18\xbf\x12\xbf\xf0\xbe\x12\xbf\xf0\xbe\xe4\xa4\xf0\x3e\x10\xe8\x1f\x3f\xcb\xcf\xdb\xbe\xd6\xa2\x1c\xbf\xf7\xa2\x1c\xbf\x7c\x83\x7f\x3f\x7c\x83\x7f\x3f\x78\x96\x7f\x3f\x5a\x81\x1f\x3f\x7f\x93\xbe\xbe\x04\x13\x3a\xbe\x9e\x12\x3a\xbe\xa9\x62\x0f\xbf\xa9\x62\x0f\xbf\xad\x7c\x0f\x3f\x85\x19\x1f\x3f\xfe\x1e\x97\xbe\xda\x96\xc3\x3e\x7c\x97\xc3\x3e\xab\x50\xd6\xbe\xab\x50\xd6\xbe\xef\x64\xd6\xbe\x90\xb0\x1e\x3f\x34\x37\x4f\xbe\x34\x71\x2a\x3f\xb4\x71\x2a\x3f\x67\x0b\x7e\x3f\x67\x0b\x7e\x3f\xe8\x52\x7e\xbf\x7c\x46\x1e\x3f\xe3\x4d\xca\xbd\x15\x5d\xeb\x3e\x51\x5e\xeb\x3e\x98\xc3\x1b\xbf\x98\xc3\x1b\xbf\x50\x4f\x1c\xbf\x47\xdb\x1d\x3f\x27\x69\x23\x3c\x65\x46\xae\xbd\x1d\x41\xae\xbd\x5e\x9e\xb9\xbe\x5e\x9e\xb9\xbe\x27\x33\xb8\x3e\xf5\x6e\x1d\x3f\x42\xdf\xf1\x3d\xb0\x3a\x11\xbf\x10\x3a\x11\xbf\x1f\x7f\x7c\x3f\x1f\x7f\x7c\x3f\x41\xe9\x7b\x3f\x86\x01\x1d\x3f\xb3\x1b\x61\x3e\x69\x70\x21\xbf\xe3\x6f\x21\xbf\x6f\x04\x2a\xbf\x6f\x04\x2a\xbf\xc3\xe0\x29\x3f\xfa\x92\x1c\x3f\x32\x9d\x9e\x3e\xdd\x3d\x68\xbe\x6f\x3c\x68\xbe\xd6\xaa\x96\xbe\xd6\xaa\x96\xbe\x47\xee\x95\xbe\x52\x23\x1c\x3f\x3d\x36\xc4\x3e\xb2\x04\xb1\x3e\xfe\x04\xb1\x3e\x6c\x88\x78\x3f\x6c\x88\x78\x3f\x20\xf5\x77\xbf\x8f\xb2\x1b\x3f\x1e\x63\xdf\x3e\x43\x50\x29\x3f\x32\x50\x29\x3f\x05\x37\x38\xbf\x05\x37\x38\xbf\x25\xd9\x37\xbf\xb2\x40\x1b\x3f\x11\xb9\xee\x3e\x6f\x55\xf8\x3e\xe1\x54\xf8\x3e\x79\xf3\x5e\xbe\x79\xf3\x5e\xbe\x95\xe5\x5e\x3e\xbb\xcd\x1a\x3f\x6a\x73\xf1\x3e\xe8\xd9\x5a\xbd\x10\xe1\x5a\xbd\xd4\x3d\x72\x3f\xd4\x3d\x72\x3f\xba\x0a\x72\x3f\xab\x59\x1a\x3f\x8b\x75\xe7\x3e\x53\x70\x0d\xbf\xe5\x70\x0d\xbf\x5e\xe3\x45\xbf\x5e\xe3\x45\xbf\x16\xdb\x45\x3f\x83\xe4\x19\x3f\x7b\x4f\xd1\x3e\x0b\x46\x23\xbf\xaa\x46\x23\xbf\xb3\xc7\x0a\xbe\xb3\xc7\x0a\xbe\x57\x7a\x09\xbe\x44\x6e\x19\x3f\xae\x31\xb0\x3e\xbe\x35\x7b\xbe\x1b\x38\x7b\xbe\x29\x68\x6a\x3f\x29\x68\x6a\x3f\x78\xd5\x69\xbf\xee\xf6\x18\x3f\xfa\xe1\x85\x3e\xe8\xef\xa9\x3e\xe8\xee\xa9\x3e\x68\x10\x54\xbf\x68\x10\x54\xbf\x82\x89\x53\xbf\x82\x7e\x18\x3f\x20\x38\x29\x3e\xbe\xf7\x28\x3f\x66\xf7\x28\x3f\xd2\x76\x2c\xbd\xd2\x76\x2c\xbd\x53\xea\x2f\x3d\x02\x05\x18\x3f\xd8\xc1\x77\x3d\xe1\xff\xfa\x3e\x8f\xff\xfa\x3e\x46\x3a\x5f\x3f\x46\x3a\x5f\x3f\x68\x09\x5f\x3f\x6e\x8a\x17\x3f\xae\xdf\x41\xbd\x2a\xfa\x4a\xbd\x74\xf9\x4a\xbd\x66\xe9\x60\xbf\x66\xe9\x60\xbf\xca\x6e\x60\x3f\xc7\x0e\x17\x3f\x1a\x40\x1c\xbe\x96\x6d\x0d\xbf\x56\x6d\x0d\xbf\x2c\x74\x6b\x3d\x2c\x74\x6b\x3d\x72\xb7\x63\x3d\x0e\x92\x16\x3f\x33\xd4\x7f\xbe\x01\x14\x23\xbf\x97\x13\x23\xbf\x32\x14\x51\x3f\x32\x14\x51\x3f\xc6\x49\x51\xbf\x43\x14\x16\x3f\xbd\x07\xab\xbe\x5e\x2b\x73\xbe\x3e\x29\x73\xbe\x4c\x0c\x6c\xbf\x4c\x0c\x6c\xbf\x57\xf1\x6b\xbf\x67\x95\x15\x3f\x95\x44\xcd\xbe\x90\x4d\xaf\x3e\xba\x4e\xaf\x3e\xf6\xe7\x24\x3e\xf6\xe7\x24\x3e\x06\x40\x24\xbe\x7c\x15\x15\x3f\xe6\xe1\xe4\xbe\x33\x75\x29\x3f\xc4\x75\x29\x3f\x4a\x4e\x40\x3f\x4a\x4e\x40\x3f\xff\x37\x40\x3f\x81\x94\x14\x3f\x80\xb0\xf0\xbe\xb4\x14\xf4\x3e\xaa\x15\xf4\x3e\x20\xd3\x75\xbf\x20\xd3\x75\xbf\x3d\x6a\x75\x3f\x79\x12\x14\x3f\x2b\x1d\xf0\xbe\x45\xac\x96\xbd\x8d\xa9\x96\xbd\x68\x66\x8b\x3e\x68\x66\x8b\x3e\x09\x47\x8a\x3e\x64\x8f\x13\x3f\x5a\x39\xe3\xbe\x12\x4b\x11\xbf\xe8\x4a\x11\xbf\x7c\x0a\x2b\x3f\x7c\x0a\x2b\x3f\x0f\x98\x2b\xbf\x43\x0b\x13\x3f\x20\xb6\xca\xbe\x10\x65\x20\xbf\x18\x65\x20\xbf\xe4\xad\x7b\xbf\xe4\xad\x7b\xbf\xc8\x38\x7c\xbf\x17\x86\x12\x3f\xb5\xdd\xa7\xbe\xc4\xea\x50\xbe\xaa\xeb\x50\xbe\xcb\xea\xc2\x3e\xcb\xea\xc2\x3e\xed\xf2\xc3\xbe\xe0\xff\x11\x3f\xb6\xfb\x78\xbe\x9f\xa0\xc0\x3e\xda\x9f\xc0\x3e\xd6\x88\x13\x3f\xd6\x88\x13\x3f\xc1\x4e\x13\x3f\xa0\x78\x11\x3f\x34\xa4\x15\xbe\x08\x8d\x2a\x3f\x86\x8c\x2a\x3f\xc5\x40\x7f\xbf\xc5\x40\x7f\xbf\xb0\xb5\x7f\x3f\x58\xf0\x10\x3f\x29\x24\x2b\xbd\x19\x28\xe2\x3e\xfc\x26\xe2\x3e\xbe\x75\xfb\x3e\xbe\x75\xfb\x3e\x52\xe7\xfd\x3e\x08\x67\x10\x3f\x72\x47\x84\x3d\xc0\x4a\xff\xbd\x25\x4f\xff\xbd\xc9\x8c\xf1\x3e\xc9\x8c\xf1\x3e\x16\xa0\xee\xbe\xb4\xdc\x0f\x3f\x13\x9e\x2b\x3e\x6c\x58\x18\xbf\xe4\x58\x18\xbf\x86\x00\x80\xbf\x86\x00\x80\xbf\x13\x24\x7f\xbf\x58\x51\x0f\x3f\x14\x29\x86\x3e\x67\x73\x1a\xbf\xbe\x73\x1a\xbf\xd7\x21\x1b\x3f\xd7\x21\x1b\x3f\xaf\x4f\x1b\xbf\xfa\xc4\x0e\x3f\xd7\xb3\xaf\x3e\x8b\x76\x11\xbe\x35\x77\x11\xbe\x5b\x0a\xb1\x3e\x5b\x0a\xb1\x3e\x6c\x55\xaf\x3e\x98\x37\x0e\x3f\xfb\x5c\xd0\x3e\xf3\x2e\xdc\x3e\xfd\x2e\xdc\x3e\x86\x7c\x7a\xbf\x86\x7c\x7a\xbf\xaa\xc8\x79\x3f\x34\xa9\x0d\x3f\xfe\x86\xe6\x3e\x86\xbe\x2a\x3f\xbc\xbe\x2a\x3f\xe9\x2e\x36\x3f\xe9\x2e\x36\x3f\x0c\x28\x36\x3f\xcd\x19\x0d\x3f\x30\x1c\xf1\x3e\x15\x9f\xc3\x3e\xd1\x9f\xc3\x3e\x3a\xb3\x54\x3e\x3a\xb3\x54\x3e\x04\x9e\x52\xbe\x67\x89\x0c\x3f\xca\x9d\xef\x3e\xef\x2c\x4f\xbe\x02\x2b\x4f\xbe\x97\xb2\x6f\xbf\x97\xb2\x6f\xbf\x09\x0c\x6f\xbf\x02\xf8\x0b\x3f\xcd\x26\xe2\x3e\x32\xcd\x20\xbf\xa8\xcc\x20\xbf\xea\x16\x4f\x3f\xea\x16\x4f\x3f\xf8\x7d\x4e\xbf\x9e\x65\x0b\x3f\x2c\x6c\xc9\x3e\x6a\x87\x0f\xbf\xe3\x86\x0f\xbf\x45\x86\x63\x3d\x45\x86\x63\x3d\xd0\x13\x6d\x3d\x3e\xd2\x0a\x3f\xbd\xb0\xa6\x3e\x9d\x49\x51\xbd\x55\x42\x51\xbd\x2e\x0c\x5e\xbf\x2e\x0c\x5e\xbf\xad\x7d\x5e\x3f\xe2\x3d\x0a\x3f\xd6\x6a\x77\x3e\x45\x94\xff\x3e\xf1\x94\xff\x3e\x89\x7b\x63\x3f\x89\x7b\x63\x3f\xca\x3b\x63\x3f\x8a\xa8\x09\x3f\x24\x43\x15\x3e\x32\xac\x27\x3f\x5d\xac\x27\x3f\x69\xe1\xd3\xbd\x69\xe1\xd3\xbd\x9f\xc7\xc8\x3d\x3b\x12\x09\x3f\xa1\x3f\x2f\x3d\x37\xa0\x95\x3e\x2f\xa0\x95\x3e\xb9\x8f\x45\xbf\xb9\x8f\x45\xbf\xfe\xc6\x47\xbf\xf2\x7a\x08\x3f\x1d\xd5\x7e\xbd\xd5\x0a\x9b\xbe\x39\x0b\x9b\xbe\x52\x41\x71\x3f\x52\x41\x71\x3f\xdd\x30\x73\xbf\xb2\xe2\x07\x3f\xc1\xfc\x27\xbe\xf4\x46\x28\xbf\x4f\x47\x28\xbf\xf3\x28\x83\xbe\xf3\x28\x83\xbe\xea\x39\x84\xbe\x7c\x49\x07\x3f\x85\xf3\x83\xbe\x38\x36\xfa\xbe\x2c\x37\xfa\xbe\x73\xa5\x29\xbf\x73\xa5\x29\xbf\xc3\xbc\x2a\x3f\x50\xaf\x06\x3f\x13\x62\xad\xbe\x18\x8e\x8e\x3d\xe2\x89\x8e\x3d\xd2\x44\x7b\x3f\xd2\x44\x7b\x3f\x60\x20\x7d\x3f\x30\x14\x06\x3f\x8a\x46\xce\xbe\x16\xa5\x12\x3f\x90\xa4\x12\x3f\x8a\x22\xd3\xbe\x8a\x22\xd3\xbe\xe6\xf2\xd5\x3e\x1e\x78\x05\x3f\x4e\x0a\xe5\xbe\x18\x2a\x1e\x3f\xa3\x29\x1e\x3f\x55\xd5\x07\xbf\x55\xd5\x07\xbf\xd3\x86\x07\xbf\x1a\xdb\x04\x3f\x3e\x98\xf0\xbe\x9b\xa8\x2b\x3e\x41\xa7\x2b\x3e\x84\x5b\x7f\x3f\x84\x5b\x7f\x3f\xc7\xe6\x7f\xbf\x26\x3d\x04\x3f\x51\x68\xf0\xbe\x95\xc8\xd5\xbe\xef\xc8\xd5\xbe\xae\x84\x11\xbf\xae\x84\x11\xbf\x35\x31\x12\xbf\x42\x9e\x03\x3f\x8c\x85\xe4\xbe\xcb\xcd\x2a\xbf\xc8\xcd\x2a\xbf\x32\xe9\xbd\xbe\x32\xe9\xbd\xbe\xe5\x5a\xbd\x3e\x71\xfe\x02\x3f\xac\x8c\xcd\xbe\x4d\x25\xc2\xbe\xed\x24\xc2\xbe\x38\x67\x7a\x3f\x38\x67\x7a\x3f\x2b\x90\x7a\x3f\xb3\x5d\x02\x3f\x8c\xa1\xac\xbe\x30\x23\x5c\x3e\x91\x24\x5c\x3e\x32\xb6\x35\xbf\x32\xb6\x35\xbf\x57\x1c\x36\x3f\x0a\xbc\x01\x3f\x4e\x63\x83\xbe\xd9\xc4\x22\x3f\x51\xc5\x22\x3f\xd8\xa2\x46\xbe\xd8\xa2\x46\xbe\x7d\x48\x44\xbe\x75\x19\x01\x3f\xbc\xad\x27\xbe\xe2\xa8\x0a\x3f\x68\xa9\x0a\x3f\xc1\x47\x6d\x3f\xc1\x47\x6d\x3f\x74\x59\x6c\xbf\x3c\x75\x00\x3f\x94\x34\x81\xbd\x8a\xc9\xfd\x3b\x4a\x0c\xfe\x3b\xc6\x2f\x56\xbf\xc6\x2f\x56\xbf\x2a\xe8\x54\xbf\xbc\x9e\xff\x3e\xad\xfd\x25\x3d\x54\x5f\x08\xbf\xdf\x5e\x08\xbf\x8a\xfc\x98\x3b\x8a\xfc\x98\x3b\xd8\x01\x29\xb8\x67\x4e\xfe\x3e\xa9\x82\x11\x3e\x64\xc2\x23\xbf\x0d\xc2\x23\xbf\x5b\x5f\x54\x3f\x5b\x5f\x54\x3f\x73\xc8\x54\x3f\x78\xf9\xfc\x3e\x06\x6d\x72\x3e\x7d\x14\x66\xbe\xc0\x13\x66\xbe\x42\x53\x6d\xbf\x42\x53\x6d\xbf\x26\xa6\x6c\x3f\x43\xab\xfb\x3e\x29\xd6\xa3\x3e\xb6\x88\xbf\x3e\xb8\x88\xbf\x3e\xa4\xdd\x50\x3e\xa4\xdd\x50\x3e\x83\x46\x4b\x3e\xc7\x63\xfa\x3e\xe6\x96\xc6\x3e\xf6\xc0\x2a\x3f\xc9\xc0\x2a\x3f\xf8\x6c\x32\x3f\xf8\x6c\x32\x3f\x8a\xdd\x33\xbf\xf5\x15\xf9\x3e\x4e\xd8\xdf\x3e\xbf\x90\xd3\x3e\x15\x90\xd3\x3e\x53\x6b\x7a\xbf\x53\x6b\x7a\xbf\x1e\x81\x7b\xbf\xce\xc1\xf7\x3e\x33\x6d\xee\x3e\x95\xac\x38\xbe\x68\xae\x38\xbe\xe6\xee\xc8\x3e\xe6\xee\xc8\x3e\xdd\x6e\xca\xbe\xe4\x6b\xf6\x3e\xac\xad\xf1\x3e\xa2\x41\x20\xbf\x28\x42\x20\xbf\xba\xa8\x0a\x3f\xba\xa8\x0a\x3f\x38\x2a\x0a\x3f\x3a\x14\xf5\x3e\x76\x78\xe9\x3e\x43\x3d\x0e\xbf\xc9\x3d\x0e\xbf\x4d\x06\x80\xbf\x4d\x06\x80\xbf\xf3\xe2\x7f\x3f\xd2\xba\xf3\x3e\x1b\x3a\xd6\x3e\xd6\x6e\xd7\xbc\xc6\x7d\xd7\xbc\x4f\x9d\x14\x3f\x4f\x9d\x14\x3f\x1d\xc4\x14\x3f\xaf\x5f\xf2\x3e\x6c\xe2\xb8\x3e\x62\x6b\x06\x3f\x09\x6b\x06\x3f\xfb\xd4\xb1\x3e\xfb\xd4\xb1\x3e\x4d\xa0\xb1\xbe\xd4\x02\xf1\x3e\xca\xdb\x92\x3e\x08\x46\x24\x3f\xd7\x45\x24\x3f\xc0\x1b\x78\xbf\xc0\x1b\x78\xbf\x09\x80\x78\xbf\x41\xa4\xef\x3e\x0d\xeb\x4b\x3e\x0f\xc3\x66\x3e\xff\xc2\x66\x3e\xc2\xdd\x3d\x3f\xc2\xdd\x3d\x3f\x53\xc1\x3e\xbf\xfc\x43\xee\x3e\x47\x43\xd1\x3d\x87\xc4\xc1\xbe\x30\xc4\xc1\xbe\xdf\xc0\x09\x3e\xdf\xc0\x09\x3e\xf2\x4f\x06\x3e\x05\xe2\xec\x3e\xf6\x83\x07\x3a\x66\xdb\x2a\xbf\x13\xdb\x2a\xbf\x85\xca\x64\xbf\x85\xca\x64\xbf\xac\x83\x64\x3f\x60\x7e\xeb\x3e\xe1\xff\xce\xbd\x0b\x9a\xcc\xbe\x24\x99\xcc\xbe\x7c\xeb\x5f\x3f\x7c\xeb\x5f\x3f\xed\x54\x60\x3f\x0c\x19\xea\x3e\x75\x9b\x4a\xbe\xa6\xbe\x4f\x3e\xb8\xc0\x4f\x3e\xc9\x02\xc2\xbd\xc9\x02\xc2\xbd\x93\x8f\xc8\x3d\x10\xb2\xe8\x3e\x53\x17\x92\xbe\x3a\xb1\x22\x3f\xc1\xb1\x22\x3f\x0e\xc8\x44\xbf\x0e\xc8\x44\xbf\x91\xd5\x43\xbf\x6a\x49\xe7\x3e\x04\x0b\xb8\xbe\xf8\x04\x09\x3f\x70\x05\x09\x3f\xc4\xc5\x77\x3f\xc4\xc5\x77\x3f\x4b\xcc\x76\xbf\x20\xdf\xe5\x3e\xe0\x69\xd5\xbe\x0d\xf9\x72\xbc\x0d\xe2\x72\xbc\x7d\x00\xaa\xbe\x7d\x00\xaa\xbe\xe3\x1e\xa8\xbe\x34\x73\xe4\x3e\x87\xde\xe8\xbe\x74\x8d\x0d\xbf\x3f\x8d\x0d\xbf\x84\x74\x16\xbf\x84\x74\x16\xbf\x8a\x3e\x17\x3f\xa8\x05\xe3\x3e\x5d\x89\xf1\xbe\x58\xf6\x1f\xbf\x50\xf6\x1f\xbf\x24\x49\x7f\x3f\x24\x49\x7f\x3f\x8e\xda\x7f\x3f\x7d\x96\xe1\x3e\x32\x0c\xef\xbe\xcb\x07\x2d\xbe\x69\x08\x2d\xbe\x7b\x7b\x0b\xbf\x7b\x7b\x0b\xbf\xe1\xdf\x0b\x3f\xbc\x25\xe0\x3e\x50\x8b\xe1\xbe\xb0\x3a\xdc\x3e\x0b\x3a\xdc\x3e\xfb\x58\xc1\xbe\xfb\x58\xc1\xbe\x61\xdc\xc0\xbe\x64\xb3\xde\x3e\xe8\xad\xc9\xbe\x5c\x4a\x2a\x3f\xea\x49\x2a\x3f\xb7\xbb\x79\x3f\xb7\xbb\x79\x3f\x73\xbe\x79\xbf\x77\x3f\xdd\x3e\xac\x93\xa8\xbe\xb0\xa6\xab\x3e\xa4\xa5\xab\x3e\x83\x52\x3c\xbf\x83\x52\x3c\xbf\x26\xaa\x3c\xbf\xf5\xc9\xdb\x3e\x45\x90\x7f\xbe\xeb\x7d\x8f\xbe\xfc\x7e\x8f\xbe\xc6\x05\x0a\xbe\xc6\x05\x0a\xbe\x45\x35\x08\x3e\xe2\x52\xda\x3e\x6e\x5b\x22\xbe\x07\x30\x28\xbf\x84\x30\x28\xbf\x2a\xa0\x63\x3f\x2a\xa0\x63\x3f\xa0\x85\x63\x3f\x3f\xda\xd8\x3e\x44\x4d\x77\xbd\x45\x4d\xf2\xbe\x05\x4e\xf2\xbe\xca\xff\x61\xbf\xca\xff\x61\xbf\x76\x7f\x62\x3f\x17\x60\xd7\x3e\x6a\xbb\x25\x3d\x5b\x87\xec\x3d\x91\x85\xec\x3d\x6b\xae\xfb\x3d\x6b\xae\xfb\x3d\x7a\xf1\x00\x3e\x6a\xe4\xd5\x3e\x58\xb5\x0e\x3e\x12\x19\x1b\x3f\x08\x19\x1b\x3f\x14\xb2\x3d\x3f\x14\xb2\x3d\x3f\x8f\x62\x3d\xbf\x38\x67\xd4\x3e\x6f\x69\x6d\x3e\xbe\x73\x13\x3f\xe3\x73\x13\x3f\xcc\x0f\x79\xbf\xcc\x0f\x79\xbf\x4a\xc8\x79\xbf\x7f\xe8\xd2\x3e\xc1\xa2\xa0\x3e\x24\x0b\x52\x3d\x1c\x10\x52\x3d\xb3\xa7\xc0\x3e\xb3\xa7\xc0\x3e\xe5\xf2\xc3\xbe\x4a\x68\xd1\x3e\xe4\x43\xc3\x3e\xa9\x9e\x04\xbf\x37\x9e\x04\xbf\x98\xae\x0a\x3f\x98\xae\x0a\x3f\x2d\xdb\x08\x3f\x98\xe6\xcf\x3e\x86\x0c\xdd\x3e\x06\x14\x24\xbf\x7e\x13\x24\xbf\x3f\x63\x80\xbf\x3f\x63\x80\xbf\xa7\xa8\x7f\x3f\x6e\x63\xce\x3e\xd2\xd9\xec\x3e\xd2\xba\x56\xbe\x9f\xb8\x56\xbe\x5b\x21\x1e\x3f\x5b\x21\x1e\x3f\x52\x31\x1e\x3f\xcb\xde\xcc\x3e\xbd\xfc\xf1\x3e\x6b\x39\xce\x3e\x6d\x3a\xce\x3e\x64\xb1\x93\x3e\x64\xb1\x93\x3e\xc4\x9e\x91\xbe\xb6\x58\xcb\x3e\x72\x42\xec\x3e\xd5\xb1\x2a\x3f\x3a\xb2\x2a\x3f\x57\x98\x73\xbf\x57\x98\x73\xbf\x71\x4d\x72\xbf\x2f\xd1\xc9\x3e\x4f\xf4\xdb\x3e\xd6\x0c\xb4\x3e\x56\x0d\xb4\x3e\xbc\x77\x50\x3f\xbc\x77\x50\x3f\x8f\xb4\x4f\xbf\x3c\x48\xc8\x3e\xf8\xd4\xc1\x3e\x13\x43\x8a\xbe\xf0\x42\x8a\xbe\x9e\x21\xd4\x3b\x9e\x21\xd4\x3b\x20\x6f\xbd\x3b\xdd\xbd\xc6\x3e\x6c\x15\x9f\x3e\x9d\x0e\x28\xbf\xbf\x0e\x28\xbf\x18\x42\x52\xbf\x18\x42\x52\xbf\x4f\x4c\x51\x3f\x18\x32\xc5\x3e\x61\x91\x6a\x3e\x80\x8d\xf0\xbe\x1d\x8e\xf0\xbe\x5b\xc0\x72\x3f\x5b\xc0\x72\x3f\x3c\x92\x71\x3f\xea\xa4\xc3\x3e\x39\x9e\x0c\x3e\x04\x08\x03\x3e\x3b\x06\x03\x3e\xd3\xfd\x90\xbe\xd3\xfd\x90\xbe\x97\x54\x8f\x3e\x5c\x16\xc2\x3e\x7c\x10\x22\x3d\x02\x2d\x1d\x3f\x77\x2c\x1d\x3f\x05\xc7\x1d\xbf\x05\xc7\x1d\xbf\x39\x04\x1e\xbf\x6e\x86\xc0\x3e\xf6\x27\x75\xbd\xfc\xb6\x0f\x3f\x69\xb6\x0f\x3f\x2a\xf6\x7f\x3f\x2a\xf6\x7f\x3f\xd6\xb7\x7f\xbf\x23\xf5\xbe\x3e\xc2\x49\x20\xbe\x5f\xda\x6f\x3c\x07\xb8\x6f\x3c\x66\xd3\x0c\xbf\x66\xd3\x0c\xbf\x42\x52\x0c\xbf\x7e\x62\xbd\x3e\xc2\x1f\x7c\xbe\x8e\x7c\x0b\xbf\xfd\x7c\x0b\xbf\x11\x3a\xb6\xbe\x11\x3a\xb6\xbe\x42\x7e\xb7\x3e\x84\xce\xbb\x3e\xbd\x62\xa6\xbe\x06\xc7\x1f\xbf\x4e\xc7\x1f\xbf\x5e\xd1\x76\x3f\x5e\xd1\x76\x3f\x43\x7e\x77\x3f\x34\x39\xba\x3e\x44\x5c\xc7\xbe\x06\x6b\x1b\xbe\x62\x6b\x1b\xbe\x81\x62\x45\xbf\x81\x62\x45\xbf\x61\xe3\x45\x3f\x97\xa2\xb8\x3e\xf5\x8e\xdf\xbe\x9d\x79\xe9\x3e\xd4\x79\xe9\x3e\xd3\xa0\x79\xbd\xd3\xa0\x79\xbd\x3c\x75\x79\xbd\xab\x0a\xb7\x3e\xb1\xf1\xed\xbe\x60\x92\x28\x3f\xac\x92\x28\x3f\x39\x76\x57\x3f\x39\x76\x57\x3f\x45\x15\x58\xbf\x76\x71\xb5\x3e\x5f\xea\xf1\xbe\x6e\xdd\x8d\x3e\x54\xde\x8d\x3e\x81\x16\x6d\xbf\x81\x16\x6d\xbf\x9f\x0c\x6e\xbf\xf8\xd6\xb3\x3e\xdd\x54\xeb\xbe\x4b\xf6\xb3\xbe\x2d\xf5\xb3\xbe\x5d\x28\x7c\x3e\x5d\x28\x7c\x3e\x28\xed\x7e\xbe\x37\x3b\xb2\x3e\x97\x81\xda\xbe\x0d\xee\x2a\xbf\x72\xed\x2a\xbf\x95\xdb\x22\x3f\x95\xdb\x22\x3f\xb9\xf3\x22\x3f\x32\x9e\xb0\x3e\x07\x33\xc0\xbe\xf9\xd7\xc5\xbe\xd7\xd6\xc5\xbe\x6b\x94\x7e\xbf\x6b\x94\x7e\xbf\x79\x8c\x7f\x3f\xf2\xff\xae\x3e\xfc\x93\x9d\xbe\x1a\x47\x75\x3e\x06\x49\x75\x3e\xd1\xdb\x08\x3f\xd1\xdb\x08\x3f\x42\x59\x0a\x3f\x78\x60\xad\x3e\x2f\x55\x68\xbe\xa4\xf5\x26\x3f\xf7\xf5\x26\x3f\x30\x3e\xbb\x3e\x30\x3e\xbb\x3e\x3c\x49\xb8\xbe\xc5\xbf\xab\x3e\x91\x8b\x0b\xbe\xc7\x55\xf5\x3e\x0b\x56\xf5\x3e\x20\x2b\x78\xbf\x20\x2b\x78\xbf\xe3\x15\x77\xbf\xdc\x1d\xaa\x3e\xb1\x4a\x23\xbd\x55\xcd\x00\xbe\xa4\xcd\x00\xbe\x96\xb5\x48\x3f\x96\xb5\x48\x3f\x6c\x10\x48\xbf\xc3\x7a\xa8\x3e\x58\x49\x6e\x3d\x78\xcd\x1d\xbf\xc0\xcd\x1d\xbf\x5d\x30\x1b\x3d\x5d\x30\x1b\x3d\x65\x14\x22\x3d\x7b\xd6\xa6\x3e\xe4\x4f\x1d\x3e\x33\x4d\x0d\xbf\xa6\x4d\x0d\xbf\xa0\x8f\x53\xbf\xa0\x8f\x53\xbf\x6f\xf4\x53\x3f\x09\x31\xa5\x3e\xa3\x34\x78\x3e\xa5\x4e\x45\x3c\xb5\x2a\x45\x3c\xdf\x10\x71\x3f\xdf\x10\x71\x3f\xb2\x4a\x71\x3f\x6e\x8a\xa3\x3e\xf4\x30\xa4\x3e\x6b\xc6\x10\x3f\xca\xc5\x10\x3f\xd5\xdf\x95\xbe\xd5\xdf\x95\xbe\x0e\x56\x95\x3e\xaf\xe2\xa1\x3e\x6c\x3a\xc5\x3e\x07\x13\x1b\x3f\x6a\x12\x1b\x3f\xe8\x8c\x17\xbf\xe8\x8c\x17\xbf\x83\x6a\x18\xbf\xce\x39\xa0\x3e\x78\xd3\xdd\x3e\xe1\xd6\xc4\x3d\xad\xd2\xc4\x3d\x3a\xe3\x7e\x3f\x3a\xe3\x7e\x3f\xe8\xfb\x7f\xbf\xd0\x8f\x9e\x3e\x2b\xf2\xec\x3e\xb6\x71\x00\xbf\x18\x72\x00\xbf\x61\xcb\x17\xbf\x61\xcb\x17\xbf\xe0\x90\x18\xbf\xb5\xe4\x9c\x3e\x05\xfd\xf1\x3e\xdf\x7b\x24\xbf\x0f\x7c\x24\xbf\x85\x46\x94\xbe\x85\x46\x94\xbe\xda\xdb\x93\x3e\x84\x38\x9b\x3e\x61\xc2\xec\x3e\xfa\xe1\x48\xbe\xde\xe1\x48\xbe\x50\x99\x70\x3f\x50\x99\x70\x3f\x50\xb4\x70\x3f\x3d\x8b\x99\x3e\x51\x83\xdd\x3e\xef\x36\xdc\x3e\x6b\x37\xdc\x3e\x17\xb2\x55\xbf\x17\xb2\x55\xbf\x53\xb1\x55\x3f\xe6\xdc\x97\x3e\x27\xed\xc4\x3e\x94\x8c\x29\x3f\x03\x8d\x29\x3f\xfe\xa6\x75\x3d\xfe\xa6\x75\x3d\x8d\x44\x70\x3d\x81\x2d\x96\x3e\x5b\x0f\xa4\x3e\xcd\x9f\x92\x3e\xf5\xa0\x92\x3e\xf1\xe4\x42\x3f\xf1\xe4\x42\x3f\x47\x95\x43\xbf\x12\x7d\x94\x3e\x2b\xa2\x78\x3e\x5a\xfc\xb4\xbe\x05\xfb\xb4\xbe\x58\x53\x78\xbf\x58\x53\x78\xbf\x81\x67\x79\xbf\x99\xcb\x92\x3e\x9f\xc4\x1e\x3e\x99\xf5\x2a\xbf\xef\xf4\x2a\xbf\x07\x57\xcc\x3e\x07\x57\xcc\x3e\x37\x77\xcf\xbe\x1e\x19\x91\x3e\xb5\x53\x79\x3d\xdb\x05\xbb\xbe\xab\x04\xbb\xbe\x9c\x44\xfd\x3e\x9c\x44\xfd\x3e\x1a\x66\xf9\x3e\x9f\x65\x8f\x3e\x7c\x76\x12\xbd\xd2\x7a\x8c\x3e\xbd\x7b\x8c\x3e\x9e\x5d\x7f\xbf\x9e\x5d\x7f\xbf\x31\x97\x7d\x3f\x26\xb1\x8d\x3e\x93\xef\x05\xbe\x16\x18\x29\x3f\x5a\x18\x29\x3f\xed\x66\x35\x3f\xed\x66\x35\x3f\xe8\x87\x34\x3f\xb3\xfb\x8b\x3e\xe2\x94\x61\xbe\x7a\x67\xde\x3e\x8f\x67\xde\x3e\xc0\xda\x11\x3e\xc0\xda\x11\x3e\x03\xf9\x0f\xbe\x4a\x45\x8a\x3e\xb9\xe0\x99\xbe\x5f\xeb\x48\xbe\x1f\xec\x48\xbe\xbc\x73\x61\xbf\xbc\x73\x61\xbf\x76\xd5\x5f\xbf\xea\x8d\x88\x3e\x0c\x89\xbc\xbe\x5d\xdf\x24\xbf\xc4\xdf\x24\xbf\xc7\x4f\x6c\x3f\xc7\x4f\x6c\x3f\x53\x32\x6a\xbf\x9d\xd5\x86\x3e\xca\x57\xd7\xbe\xdc\xcc\xfb\xbe\x02\xce\xfb\xbe\xa5\xd8\x74\xbe\xa5\xd8\x74\xbe\x08\x09\x6d\xbe\x62\x1c\x85\x3e\x9c\x36\xe9\xbe\x66\x21\xf6\x3d\xec\x1b\xf6\x3d\x9c\xfb\x20\xbf\x9c\xfb\x20\xbf\x4f\x62\x22\x3f\x40\x62\x83\x3e\xf2\x6e\xf1\xbe\x36\xd8\x1e\x3f\x7e\xd7\x1e\x3f\x8e\x1a\x7f\x3f\x8e\x1a\x7f\x3f\x7c\xcf\x7f\x3f\x38\xa7\x81\x3e\xd1\xb0\xef\xbe\x67\xdd\x09\x3f\xbb\xdc\x09\x3f\x2b\xb0\x13\xbf\x2b\xb0\x13\xbf\x76\xb8\x13\x3f\x9d\xd6\x7f\x3e\xe1\x15\xe4\xbe\x31\x54\x48\xbd\xf9\x5c\x48\xbd\x97\x1c\x98\xbe\x97\x1c\x98\xbe\xc5\xec\x98\xbe\x06\x5d\x7c\x3e\xf2\x1f\xcf\xbe\x2b\x26\x17\xbf\x87\x26\x17\xbf\x4b\x1d\x70\x3f\x4b\x1d\x70\x3f\xa0\x7c\x70\xbf\xbd\xe1\x78\x3e\x96\xb1\xb1\xbe\xc9\x7f\x13\xbf\xec\x7f\x13\xbf\x76\x0b\x58\xbf\x76\x0b\x58\xbf\xd9\xe6\x57\xbf\xc2\x64\x75\x3e\x7f\x04\x8d\xbe\x9c\x34\x90\xbc\x34\x31\x90\xbc\x16\x31\xb9\x3d\x16\x31\xb9\x3d\x39\xbf\xb2\xbd\x21\xe6\x71\x3e\x01\x3a\x45\xbe\x87\xcb\x0e\x3f\xde\xcb\x0e\x3f\x6f\x65\x3b\x3f\x6f\x65\x3b\x3f\xab\x92\x3c\x3f\xdb\x65\x6e\x3e\xb7\xe7\xd0\xbd\x11\xe0\x1a\x3f\x9e\xe0\x1a\x3f\x13\x2c\x7b\xbf\x13\x2c\x7b\xbf\x5f\x3d\x7c\x3f\xfe\xe3\x6a\x3e\xe7\x77\xf0\xbb\xb1\xf1\xa0\x3d\x30\xf7\xa0\x3d\x37\x86\xed\x3e\x37\x86\xed\x3e\xc1\xbd\xee\x3e\x89\x60\x67\x3e\x17\x46\xb3\x3d\xc9\x05\x06\xbf\x08\x05\x06\xbf\x80\x7d\xd4\x3e\x80\x7d\xd4\x3e\x38\x86\xd4\xbe\x8c\xdb\x63\x3e\xdd\x10\x37\x3e\xda\x9b\x20\xbf\x1c\x9b\x20\xbf\x53\x75\x78\xbf\x53\x75\x78\xbf\x72\x3b\x79\xbf\x06\x55\x60\x3e\x86\x80\x86\x3e\x4b\x3f\x07\xbe\xb4\x3c\x07\xbe\xd9\x3c\x45\x3f\xd9\x3c\x45\x3f\x3a\xdf\x46\xbf\x04\xcd\x5c\x3e\xb5\xff\xab\x3e\xe0\x3e\xfa\x3e\xd8\x3f\xfa\x3e\xf0\x25\xf7\x3c\xf0\x25\xf7\x3c\x4c\xbd\xac\x3c\x86\x43\x59\x3e\x19\x87\xca\x3e\x21\x7f\x24\x3f\x64\x7f\x24\x3f\xa0\xb9\x4f\xbf\xa0\xb9\x4f\xbf\xe1\x5a\x4d\x3f\x9c\xb8\x55\x3e\x59\xe1\xe0\x3e\xc2\xc1\x38\x3e\xc8\xc1\x38\x3e\x5e\x3d\x78\x3f\x5e\x3d\x78\x3f\x2c\xb6\x76\x3f\x48\x2c\x52\x3e\x84\x2e\xee\x3e\x7c\x53\xe9\xbe\xfc\x53\xe9\xbe\xc6\x43\xc4\xbe\xc6\x43\xc4\xbe\xd8\xea\xc3\x3e\x92\x9e\x4e\x3e\x49\xec\xf1\x3e\x71\x30\x27\xbf\xec\x30\x27\xbf\xa9\xef\xfd\xbe\xa9\xef\xfd\xbe\xc1\x1f\xfc\xbe\x7c\x0f\x4b\x3e\x54\xfb\xeb\x3e\x83\x5f\x63\xbe\x2a\x62\x63\xbe\xe3\x50\x7e\x3f\xe3\x50\x7e\x3f\x50\x21\x7d\xbf\x16\x7f\x47\x3e\xf8\x9e\xdc\x3e\x6d\x3a\xd9\x3e\xdf\x38\xd9\x3e\x7e\xd9\x3a\xbf\x7e\xd9\x3a\xbf\x28\x01\x3a\xbf\x5e\xed\x43\x3e\x29\x7b\xc4\x3e\xcf\x3f\x29\x3f\x02\x3f\x29\x3f\xf9\x49\xb8\xbd\xf9\x49\xb8\xbd\x25\x1c\xbc\x3d\x69\x5a\x40\x3e\xe6\x8b\xa4\x3e\xd8\x31\x83\x3e\x59\x30\x83\x3e\xfd\x8e\x56\x3f\xfd\x8e\x56\x3f\xb3\xf2\x56\x3f\x34\xc6\x3c\x3e\x72\x37\x7c\x3e\xe4\x27\xcb\xbe\x17\x29\xcb\xbe\x57\xe2\x71\xbf\x57\xe2\x71\xbf\x9e\x34\x72\x3f\xc8\x30\x39\x3e\xab\x6a\x25\x3e\x58\x15\x2a\xbf\xbe\x15\x2a\xbf\xb0\xde\xa9\x3e\xb0\xde\xa9\x3e\x17\xb8\xa9\x3e\x24\x9a\x35\x3e\xd6\x4f\x90\x3d\x6d\x1e\x92\xbe\xb8\x1e\x92\xbe\x2b\x57\x08\x3f\x2b\x57\x08\x3f\xce\xf5\x08\xbf\x5d\x02\x32\x3e\x4c\xfd\xbe\xbc\x80\xbd\xbe\x3e\xc1\xbd\xbe\x3e\x46\xf2\x7d\xbf\x46\xf2\x7d\xbf\x30\x97\x7e\xbf\x73\x69\x2e\x3e\x6d\xbf\xed\xbd\x7b\x81\x2a\x3f\xdd\x81\x2a\x3f\xb3\x4f\x33\x3f\xb3\x4f\x33\x3f\xa1\x0b\x33\xbf\x74\xcf\x2a\x3e\x70\x1b\x51\xbe\xf6\xf3\x9d\x3e\x28\xf5\x9d\x3e\x42\xda\xf2\x3d\x42\xda\xf2\x3d\xb1\x1d\x00\x3e\x5f\x34\x27\x3e\x14\x85\x91\xbe\xa1\x07\xb4\xbe\x21\x06\xb4\xbe\x2d\x33\x58\xbf\x2d\x33\x58\xbf\xec\xbe\x5a\x3f\x42\x98\x23\x3e\x0e\xbf\xb4\xbe\x2d\xe2\x2a\xbf\x59\xe1\x2a\xbf\x79\x0c\x6e\x3f\x79\x0c\x6e\x3f\x95\x39\x70\x3f\x1a\xfb\x1f\x3e\x2b\xdf\xd0\xbe\xb7\xfd\xa6\xbe\x13\xfc\xa6\xbe\x5d\xba\x9f\xbe\x5d\xba\x9f\xbe\x6b\x4b\xa1\x3e\xfc\x5c\x1c\x3e\x18\xd2\xe4\xbe\xbd\x6a\xac\x3e\x2f\x6c\xac\x3e\x92\xc0\x0a\xbf\x92\xc0\x0a\xbf\x7b\x85\x0b\xbf\xe4\xbd\x18\x3e\xe8\xd4\xef\xbe\x05\xe5\x2a\x3f\x90\xe5\x2a\x3f\x78\xf7\x7c\x3f\x78\xf7\x7c\x3f\x27\xc0\x7e\xbf\xe4\x1d\x15\x3e\x1f\x81\xf1\xbe\xa6\x4a\xad\x3e\x44\x4b\xad\x3e\xfe\xa8\x30\xbf\xfe\xa8\x30\xbf\xc9\xd5\x32\xbf\xfb\x7c\x11\x3e\x04\xcd\xe9\xbe\xcd\x2a\xa7\xbe\xb9\x2a\xa7\xbe\xbd\x88\x04\xbe\xbd\x88\x04\xbe\x68\xb4\xf7\x3d\x36\xdb\x0d\x3e\x8c\x0c\xd9\xbe\x88\xe1\x2a\xbf\xc4\xe1\x2a\xbf\x80\x48\x5b\x3f\x80\x48\x5b\x3f\x0b\x7d\x59\x3f\x95\x38\x0a\x3e\x74\xea\xbf\xbe\x1c\xa3\xb0\xbe\x12\xa4\xb0\xbe\xf2\x69\x72\xbf\xf2\x69\x72\xbf\x3c\x8d\x71\x3f\x28\x95\x06\x3e\xc1\x66\x9f\xbe\xee\x57\xa4\x3e\x8e\x56\xa4\x3e\x2d\x1a\xaa\x3e\x2d\x1a\xaa\x3e\x5b\x2b\xab\x3e\xf0\xf0\x02\x3e\x47\x8d\x71\xbe\x8c\xcd\x2a\x3f\xbc\xcc\x2a\x3f\x8f\xaf\x07\x3f\x8f\xaf\x07\x3f\x50\xf3\x05\xbf\xf4\x97\xfe\x3d\x57\x18\x1b\xbe\x0f\xcf\xb1\x3e\x56\xcd\xb1\x3e\xe8\xc2\x7f\xbf\xe8\xc2\x7f\xbf\xd9\xd3\x7d\xbf\x91\x4c\xf7\x3d\xcb\x07\x7b\xbd\x36\x39\xa4\xbe\xd9\x3a\xa4\xbe\x89\x4b\x3a\x3f\x89\x4b\x3a\x3f\x54\x60\x39\xbf\xd0\xff\xef\x3d\x12\x38\xff\x3c\x85\xe7\x2a\xbf\x32\xe8\x2a\xbf\xba\x76\xa7\x3d\xba\x76\xa7\x3d\x75\x49\xa2\x3d\xb0\xb1\xe8\x3d\xc9\x88\xfa\x3d\x13\x0d\xb0\xbe\x03\x0e\xb0\xbe\x74\x90\x54\xbf\x74\x90\x54\xbf\xae\xd1\x52\x3f\x52\x62\xe1\x3d\x27\xbd\x55\x3e\xc4\xcc\xa6\x3e\x52\xcc\xa6\x3e\xfd\x6b\x77\x3f\xfd\x6b\x77\x3f\xdd\xa2\x75\x3f\xb6\x11\xda\x3d\x1b\xff\x92\x3e\xf8\xed\x2a\x3f\x05\xee\x2a\x3f\x0f\xb0\xc8\xbe\x0f\xb0\xc8\xbe\x1d\xd7\xc6\x3e\xfa\xbf\xd2\x3d\x7b\x7e\xb5\x3e\x9b\xb3\xab\x3e\x43\xb4\xab\x3e\x53\x38\xf0\xbe\x53\x38\xf0\xbe\xca\xbc\xef\xbe\x1e\x6d\xcb\x3d\x91\x15\xd1\x3e\x15\x45\xac\xbe\xf0\x43\xac\xbe\x6f\x27\x7c\x3f\x6f\x27\x7c\x3f\xfa\xfd\x7a\xbf\x4d\x21\xc4\x3d\xda\xb5\xe4\x3e\xe7\xd6\x2a\xbf\x24\xd6\x2a\xbf\xd3\x8c\x47\xbf\xd3\x8c\x47\xbf\x5b\xf7\x45\xbf\x86\xdc\xbc\x3d\x2a\xb3\xef\x3e\x1d\xc3\xa4\xbe\x65\xc1\xa4\xbe\x59\xb2\xc3\x3b\x59\xb2\xc3\x3b\xee\x95\x53\xb8\x5a\x7f\xb5\x3d\xee\xa1\xf1\x3e\x0d\xed\xb3\x3e\xcd\xee\xb3\x3e\xdf\xab\x44\x3f\xdf\xab\x44\x3f\xe2\xd4\x45\x3f\xca\x09\xae\x3d\x28\x68\xea\x3e\xd6\xcb\x2a\x3f\xa1\xcc\x2a\x3f\x56\x53\x7a\xbf\x56\x53\x7a\xbf\x52\x29\x7b\x3f\xbf\xa6\xa6\x3d\xf9\x6d\xda\x3e\x6c\x9a\x9a\x3e\xb2\x9b\x9a\x3e\xb0\x63\xf1\x3e\xb0\x63\xf1\x3e\x89\xe5\xf2\x3e\x3a\x56\x9f\x3d\x54\x42\xc2\x3e\x7d\xe9\xbd\xbe\xaa\xe8\xbd\xbe\x3b\x88\xc2\x3e\x3b\x88\xc2\x3e\xe9\x08\xc1\xbe\x59\x01\x98\x3d\xb8\xd6\xa2\x3e\xd3\x47\x2a\xbf\xaf\x47\x2a\xbf\x40\x90\x74\xbf\x40\x90\x74\xbf\x24\x3b\x74\xbf\x1e\xa8\x90\x3d\x4e\xb0\x7a\x3e\xdf\x54\x8e\xbe\x26\x55\x8e\xbe\x4f\xf6\x55\x3f\x4f\xf6\x55\x3f\xc1\xc2\x56\xbf\x4d\x4e\x89\x3d\x89\x6f\x26\x3e\xcc\x8e\xca\x3e\xfa\x8d\xca\x3e\x66\xc6\xdc\xbd\x66\xc6\xdc\xbd\x75\xd0\xee\xbd\xe8\xf3\x81\x3d\xf3\x1a\x98\x3d\x33\x83\x29\x3f\x90\x82\x29\x3f\xee\x9a\x33\xbf\xee\x9a\x33\xbf\xe7\x83\x30\x3f\x18\x32\x75\x3d\x8b\x7a\x88\xbc\x16\xc7\x7c\x3e\xe8\xc3\x7c\x3e\xd4\xfe\x80\x3f\xd4\xfe\x80\x3f\xb0\x66\x7f\x3f\x72\x7b\x66\x3d\x1a\xeb\xda\xbd\xfa\x00\xd9\xbe\xb9\x02\xd9\xbe\x1d\x34\x17\xbf\x1d\x34\x17\xbf\xa1\x43\x16\x3f\x23\xc4\x57\x3d\x16\xb5\x45\xbe\xe3\x1f\x28\xbf\xbd\x20\x28\xbf\x7b\x2b\x7f\xbe\x7b\x2b\x7f\xbe\x8c\x85\x7b\xbe\x2c\x0c\x49\x3d\x43\x49\x8b\xbe\x55\x9d\x55\xbe\x5f\xa0\x55\xbe\xe0\xc8\x68\x3f\xe0\xc8\x68\x3f\xf2\xc0\x66\xbf\xc0\x53\x3a\x3d\xbb\x89\xae\xbe\x6c\x3f\xe9\x3e\x41\x3e\xe9\x3e\xd7\x3c\x6b\xbf\xd7\x3c\x6b\xbf\x1a\x1e\x69\xbf\xdf\x9a\x2b\x3d\xa0\x55\xcb\xbe\x82\x87\x25\x3f\x2a\x87\x25\x3f\x46\x40\x8c\x3e\x46\x40\x8c\x3e\x67\x4f\x89\xbe\xcf\xe1\x1c\x3d\x41\xa0\xe0\xbe\x6d\xe2\x28\x3e\x22\xe2\x28\x3e\x62\x42\x10\x3f\x62\x42\x10\x3f\x59\xbe\x10\x3f\x8e\x28\x0e\x3d\x49\xa8\xed\xbe\xe8\x73\xfa\xbe\x7c\x73\xfa\xbe\x01\x5c\x7f\xbf\x01\x5c\x7f\xbf\x75\xc0\x7e\x3f\xb9\xde\xfe\x3c\xa1\xf8\xf1\xbe\x39\xe7\x21\xbf\xc1\xe6\x21\xbf\x06\xe2\x38\x3f\x06\xe2\x38\x3f\xe0\x47\x37\x3f\x72\x6c\xe1\x3c\x48\x71\xed\xbe\xe8\xff\xe9\xbd\x78\xfa\xe9\xbd\x9c\x8a\x82\x3d\x9c\x8a\x82\x3d\x38\x72\x93\xbd\xc3\xfa\xc3\x3c\x3e\x41\xe0\xbe\x68\x20\x06\x3f\x3a\x21\x06\x3f\xed\x37\x4d\xbf\xed\x37\x4d\xbf\x2f\xec\x4e\xbf\xaa\x89\xa6\x3c\xed\xea\xca\xbe\x2b\xdc\x1c\x3f\x09\xdd\x1c\x3f\xe5\x5d\x78\x3f\xe5\x5d\x78\x3f\x8f\xac\x78\xbf\x9e\x19\x89\x3c\x40\x39\xae\xbe\x7c\xa9\x68\x3d\xd8\xb6\x68\x3d\x00\x05\xe8\xbe\x00\x05\xe8\xbe\x52\xf9\xe4\xbe\x3e\x55\x57\x3c\x43\x3d\x8b\xbe\xc1\x3e\x0f\xbf\x09\x3e\x0f\xbf\x6b\x2d\xc3\xbe\x6b\x2d\xc3\xbe\x00\xf5\xc8\x3e\x7a\x7a\x1c\x3c\x87\x7d\x46\xbe\x6e\xd4\x15\xbf\xe6\xd3\x15\xbf\xab\x52\x71\x3f\xab\x52\x71\x3f\xa5\x79\x74\x3f\xe7\x45\xc3\x3b\xef\xd1\xde\xbd\xcc\x93\xfa\x3b\xac\xb7\xfa\x3b\xc5\xfe\x55\xbf\xc5\xfe\x55\xbf\x8f\x4b\x58\x3f\x12\x3e\x1b\x3b\xff\x1b\xa3\xbc\xe6\xb9\x17\x3f\xe9\xb9\x17\x3f\x45\x2b\x0d\x3e\x45\x2b\x0d\x3e\x8b\x80\x10\x3e\x92\xfe\x9f\xba\x20\x8d\x8e\x3d\x98\xac\x0c\x3f\x54\xac\x0c\x3f\x64\x9f\x28\x3f\x64\x9f\x28\x3f\x56\x47\x29\xbf\x37\x94\x9d\xbb\xef\x4b\x20\x3e\x29\x67\x9f\xbd\x36\x6b\x9f\xbd\x18\x33\x7e\xbf\x18\x33\x7e\xbf\x2d\xfb\x7f\xbf\x56\x8f\x09\xbc\xea\x7b\x73\x3e\xcc\x60\x1f\xbf\x7e\x61\x1f\xbf\x45\x43\x21\x3f\x45\x43\x21\x3f\x02\xa1\x23\xbf\x5e\x4e\x44\xbc\x03\xf1\x9e\x3e\x3f\xfb\x00\xbf\x11\xfc\x00\xbf\x08\xe4\x34\x3e\x08\xe4\x34\x3e\x3b\x89\x2b\x3e\x34\x07\x7f\xbc\xc6\x6c\xbe\x3e\xab\xc7\x1c\x3e\x3f\xc4\x1c\x3e\x99\x15\x5d\xbf\x99\x15\x5d\xbf\xb5\x5c\x5b\x3f\x86\xdc\x9c\xbc\xf9\x16\xd7\x3e\xab\x90\x25\x3f\xdb\x8f\x25\x3f\x24\xcb\x73\x3f\x24\xcb\x73\x3f\x29\x18\x73\x3f\xf4\x31\xba\xbc\x06\x13\xe8\x3e\x8e\xf3\xe4\x3e\x36\xf2\xe4\x3e\x3c\x25\xc3\xbe\x3c\x25\xc3\xbe\x67\xeb\xc3\x3e\x5e\x83\xd7\xbc\xfc\xcc\xf0\x3e\x54\xfd\x6d\xbe\x37\xff\x6d\xbe\xa6\x55\xe8\xbe\xa6\x55\xe8\xbe\x8b\x03\xe6\xbe\xc5\xd0\xf4\xbc\xae\xfa\xf0\x3e\xd7\x7c\x29\xbf\x10\x7d\x29\xbf\x0f\x98\x79\x3f\x0f\x98\x79\x3f\x85\x38\x78\xbf\xcd\x0c\x09\xbd\x37\xa1\xe8\x3e\xcd\x1b\xc2\xbe\xb8\x1b\xc2\xbe\x4e\xca\x52\xbf\x4e\xca\x52\xbf\xc1\xcc\x51\xbf\xf0\xae\x17\xbd\x88\x11\xd8\x3e\xff\x39\xa0\x3e\x99\x3a\xa0\x3e\xba\x81\xd6\x3d\xba\x81\xd6\x3d\xc3\x2d\xd5\xbd\x98\x4e\x26\xbd\x0a\xe8\xbf\x3e\xb9\xde\x2a\x3f\x41\xdf\x2a\x3f\xb1\x8f\x2f\x3f\xb1\x8f\x2f\x3f\xf5\xbe\x2e\x3f\xc4\xeb\x34\xbd\xcf\x02\xa1\x3e\xd7\x2f\x99\x3e\x43\x31\x99\x3e\x21\xb9\x80\xbf\x21\xb9\x80\xbf\xd8\xd8\x7f\x3f\x2c\x86\x43\xbd\xed\xf9\x78\x3e\x08\x85\xc9\xbe\x6c\x83\xc9\xbe\xcc\x1c\x23\x3f\xcc\x1c\x23\x3f\x36\x43\x21\x3f\xcc\x1d\x52\xbd\xb6\x43\x27\x3e\x0c\xc3\x28\xbf\x38\xc2\x28\xbf\x7d\x83\x29\x3e\x7d\x83\x29\x3e\x85\x11\x2f\xbe\x77\xb2\x60\xbd\xd3\x8d\x9f\x3d\xe4\x20\x55\xbe\xdc\x1d\x55\xbe\x01\x60\x5a\xbf\x01\x60\x5a\xbf\xeb\xb3\x5a\xbf\x2a\x44\x6f\xbd\xfb\xb5\x26\xbc\x92\x09\xf1\x3e\xcd\x0a\xf1\x3e\xdf\x13\x75\x3f\xdf\x13\x75\x3f\x1b\x24\x74\xbf\xa0\xd2\x7d\xbd\xc9\x55\xc8\xbd\xc7\xba\x22\x3f\x32\xbb\x22\x3f\xa0\x0c\xd2\xbe\xa0\x0c\xd2\xbe\x9f\x35\xce\xbe\xec\x2e\x86\xbd\x5d\x5a\x3a\xbe\xd5\x76\xd7\x3d\x3b\x78\xd7\x3d\x9b\x65\xd3\xbe\x9b\x65\xd3\xbe\x0a\x03\xd8\x3e\xca\x72\x8d\xbd\x80\xfe\x84\xbe\xdf\x60\x0a\xbf\xf2\x60\x0a\xbf\x3e\x7f\x73\x3f\x3e\x7f\x73\x3f\x8e\x93\x75\x3f\xeb\xb4\x94\xbd\x85\x2a\xa8\xbe\x2f\x04\x18\xbf\x83\x04\x18\xbf\xbd\x09\x57\xbf\xbd\x09\x57\xbf\x8a\x76\x58\x3f\x2e\xf5\x9b\xbd\x13\x7c\xc5\xbe\xf5\xb2\xd2\x3b\xb5\x6d\xd2\x3b\x42\xca\x20\x3e\x42\xca\x20\x3e\x65\x15\x23\x3e\x96\x33\xa3\xbd\x7b\xf4\xdb\xbe\x99\x75\x19\x3f\xe6\x74\x19\x3f\xbb\x15\x22\x3f\xbb\x15\x22\x3f\x9c\x61\x22\xbf\x00\x70\xaa\xbd\xbd\xd1\xea\xbe\x31\xf6\x07\x3f\x6b\xf5\x07\x3f\xe2\xc7\x7e\xbf\xe2\xc7\x7e\xbf\xe7\xcf\x7f\xbf\x6c\xaa\xb1\xbd\x96\x97\xf1\xbe\xad\xb2\xfc\xbd\xed\xb8\xfc\xbd\x8d\x5d\x2f\x3f\x8d\x5d\x2f\x3f\x4d\xd0\x30\xbf\xc0\xe2\xb8\xbd\xcb\x0f\xf0\xbe\x24\x45\x24\xbf\xd9\x45\x24\xbf\x53\x9d\xb3\x3d\x53\x9d\xb3\x3d\x76\x9a\xa8\x3d\xf9\x18\xc0\xbd\x37\x4d\xe6\xbe\x9c\xcf\xe5\xbe\xbe\xd0\xe5\xbe\x28\x77\x4d\xbf\x28\x77\x4d\xbf\xe9\xae\x4c\x3f\xfa\x4c\xc7\xbd\xbc\xaa\xd4\xbe\x03\xf1\x77\x3e\x96\xef\x77\x3e\xc5\xd0\x7a\x3f\xc5\xd0\x7a\x3f\x16\xf3\x7a\x3f\xc2\x7e\xce\xbd\x82\xc9\xbb\xbe\xb3\x17\x2a\x3f\x93\x17\x2a\x3f\x6c\x42\x00\xbf\x6c\x42\x00\xbf\x14\x3e\x01\x3f\x2d\xae\xd5\xbd\x9f\x87\x9c\xbe\xce\xd9\xb1\x3e\x0c\xda\xb1\x3e\x2f\x34\xa0\xbe\x2f\x34\xa0\xbe\xb7\x6d\x9d\xbe\x3a\xdb\xdc\xbd\x02\xf4\x6f\xbe\x56\x67\xb7\xbe\xa6\x66\xb7\xbe\xd2\x39\x6b\x3f\xd2\x39\x6b\x3f\xdd\x03\x6a\xbf\xd4\x05\xe4\xbd\x11\xc3\x1e\xbe\x5b\x0b\x2a\xbf\xd0\x0a\x2a\xbf\x78\x06\x6a\xbf\x78\x06\x6a\xbf\x26\x66\x69\xbf\xfc\x2d\xeb\xbd\x4a\x89\x90\xbd\x5a\x1e\x67\xbe\xa4\x1b\x67\xbe\x37\x46\x9b\x3e\x37\x46\x9b\x3e\xe1\x52\x9b\xbe\x88\x53\xf2\xbd\x9f\x9d\x84\x3c\x7f\xf9\xee\x3e\xfa\xfa\xee\x3e\x4d\xfb\x01\x3f\x4d\xfb\x01\x3f\xae\x7d\x01\x3f\x7c\x76\xf9\xbd\xdf\x8a\xd1\x3d\x62\x63\x22\x3f\x1e\x64\x22\x3f\x38\x7d\x7b\xbf\x38\x7d\x7b\xbf\xf6\xbb\x7a\x3f\x5b\x4b\x00\xbe\x8d\x5e\x3d\x3e\x2e\x5e\xb3\x3d\x52\x63\xb3\x3d\x1c\x10\x4f\x3f\x1c\x10\x4f\x3f\x12\x1c\x4e\x3f\x1d\xda\x03\xbe\xcb\xc3\x85\x3e\x77\xc6\x0e\xbf\xf9\xc5\x0e\xbf\xdd\xfc\xd4\xbd\xdd\xfc\xd4\xbd\xe7\xbe\xcb\x3d\x74\x67\x07\xbe\x5f\x4e\xa8\x3e\xfa\x9f\x12\xbf\xad\x9f\x12\xbf\x3c\x94\x2a\xbf\x3c\x94\x2a\xbf\x1a\xd6\x2b\xbf\x62\xf3\x0a\xbe\x7a\x28\xc5\x3e\x78\x12\x74\x3d\xa8\x13\x74\x3d\x9f\xe0\x7e\x3f\x9f\xe0\x7e\x3f\x19\xfa\x7f\xbf\xd4\x7d\x0e\xbe\xbd\x6a\xdb\x3e\xf3\xb0\x1f\x3f\xcc\xb0\x1f\x3f\xc8\x4e\x2b\xbf\xc8\x4e\x2b\xbf\xfe\xf9\x2b\xbf\xcb\x06\x12\xbe\x3f\x4d\xea\x3e\xa3\x68\xf6\x3e\xe9\x67\xf6\x3e\x26\xa9\xc6\xbd\x26\xa9\xc6\xbd\x21\x86\xc5\x3d\x3b\x8e\x15\xbe\x1b\x63\xf1\x3e\xda\x21\x55\xbe\xff\x23\x55\xbe\xff\xc1\x4c\x3f\xff\xc1\x4c\x3f\xbf\x0d\x4d\x3f\x22\x14\x19\xbe\xda\x70\xf0\x3e\x6a\x74\x29\xbf\x11\x75\x29\xbf\x46\xb3\x7a\xbf\x46\xb3\x7a\xbf\x3a\x57\x7b\x3f\x70\x98\x1c\xbe\x5a\x82\xe7\x3e\xbb\xab\xb8\xbe\x22\xad\xb8\xbe\xea\xb9\x04\x3f\xea\xb9\x04\x3f\x73\xb3\x05\x3f\x24\x1b\x20\xbe\xda\xe8\xd6\x3e\x56\xf9\xb4\x3e\xfe\xf7\xb4\x3e\x53\x39\x90\x3e\x53\x39\x90\x3e\xaf\xc7\x8d\xbe\x30\x9c\x23\xbe\x07\x3a\xbf\x3e\x09\xd3\x29\x3f\x76\xd2\x29\x3f\xb7\x58\x66\xbf\xb7\x58\x66\xbf\x81\x47\x65\xbf\x94\x1b\x27\xbe\xcb\x41\xa1\x3e\x69\x95\x59\x3e\xb7\x93\x59\x3e\x5c\x0f\x6f\x3f\x5c\x0f\x6f\x3f\x07\xd4\x6e\xbf\x43\x99\x2a\xbe\x2c\x00\x7c\x3e\x81\x67\xf7\xbe\xf8\x67\xf7\xbe\x39\x22\xb9\xbe\x39\x22\xb9\xbe\xbe\x65\xbb\xbe\x3c\x15\x2e\xbe\x29\x42\x2d\x3e\xc5\x6d\x1f\xbf\xcb\x6d\x1f\xbf\xc1\x99\xe4\xbe\xc1\x99\xe4\xbe\x9e\xd9\xdf\x3e\x6b\x8f\x31\xbe\x28\xd1\xb1\x3d\x83\x88\x34\xbd\x84\x85\x34\xbd\x11\xf4\x77\x3f\x11\xf4\x77\x3f\xca\x30\x75\x3f\xd0\x07\x35\xbe\x7c\xe0\xdc\x3a\x4f\xbc\x15\x3f\xb0\xbc\x15\x3f\x36\x66\x5e\xbf\x36\x66\x5e\xbf\x7e\x67\x5c\x3f\x62\x7e\x38\xbe\x3e\xde\xaa\xbd\xfc\xb0\x09\x3f\x82\xb1\x09\x3f\xc0\x27\x59\x3e\xc0\x27\x59\x3e\xee\x8a\x57\x3e\x24\xf3\x3b\xbe\xf1\xbb\x29\xbe\xa6\xea\x06\xbe\x30\xe8\x06\xbe\xbb\x6c\x14\x3f\xbb\x6c\x14\x3f\x0b\x1b\x13\xbf\xfe\x65\x3f\xbe\xde\x6c\x78\xbe\xb3\x2e\x26\xbf\x0e\x2e\x26\xbf\xd5\x1d\x80\xbf\xd5\x1d\x80\xbf\x93\xab\x7d\xbf\xf1\xd6\x42\xbe\x0f\x7b\x9f\xbe\xed\x19\xd3\xbe\xb9\x18\xd3\xbe\x84\xef\x48\x3f\x84\xef\x48\x3f\x0e\xe1\x45\xbf\xf0\x45\x46\xbe\xf8\x89\xbd\xbe\x1b\xae\x9b\x3e\x1d\xaf\x9b\x3e\x00\xe0\x94\xbd\x00\xe0\x94\xbd\x27\x7c\x7c\xbd\xfb\xb2\x49\xbe\xd9\x6e\xd5\xbe\x6e\xc5\x2a\x3f\xc8\xc5\x2a\x3f\xec\x29\x2e\xbf\xec\x29\x2e\xbf\x39\x3a\x30\x3f\x03\x1e\x4d\xbe\x46\x67\xe6\xbe\xec\x79\x80\x3e\x41\x7a\x80\x3e\x52\xf3\x7e\x3f\x52\xf3\x7e\x3f\x23\xf4\x7f\x3f\x08\x87\x50\xbe\xdb\xeb\xef\xbe\xa9\xa8\xeb\xbe\xb9\xa8\xeb\xbe\x67\x21\x2d\xbf\x67\x21\x2d\xbf\x51\x0c\x2d\x3f\xfd\xed\x53\xbe\x50\xb3\xf1\xbe\x7b\x7e\x21\xbf\xb7\x7e\x21\xbf\xea\xad\x94\xbd\xea\xad\x94\xbd\x16\x27\x9c\xbd\xe2\x52\x57\xbe\x70\xb5\xeb\xbe\x72\x0b\x7b\xbd\xa2\x11\x7b\xbd\x64\x38\x46\x3f\x64\x38\x46\x3f\x0c\x9a\x47\xbf\xa4\xb5\x5a\xbe\x84\x28\xde\xbe\xb4\x87\x14\x3f\x31\x87\x14\x3f\x96\x15\x7c\xbf\x96\x15\x7c\xbf\x64\x73\x7d\xbf\x45\x16\x5e\xbe\xa6\x80\xc9\xbe\xd7\x00\x0a\x3f\x44\x00\x0a\x3f\x53\x7e\x12\x3f\x53\x7e\x12\x3f\xd4\x67\x13\xbf\xb6\x74\x61\xbe\x81\x6b\xae\xbe\x69\xaa\x0d\xbe\xc1\xac\x0d\xbe\xd9\x08\x4e\x3e\xd9\x08\x4e\x3e\x03\x84\x4d\x3e\xf8\xd0\x64\xbe\x36\xcc\x8d\xbe\x1b\x03\x27\xbf\xa2\x03\x27\xbf\x22\x04\x59\xbf\x22\x04\x59\xbf\xd9\xbb\x59\x3f\xfa\x2a\x68\xbe\xae\x61\x51\xbe\xa8\x2f\xca\xbe\x7c\x30\xca\xbe\x01\x24\x76\x3f\x01\x24\x76\x3f\x8a\x5d\x77\x3f\xbe\x82\x6b\xbe\x1f\x95\x00\xbe\x9b\xd0\xa9\x3e\x12\xd0\xa9\x3e\x32\x0b\xf2\xbe\x32\x0b\xf2\xbe\x32\x1e\xf4\x3e\x35\xd8\x6e\xbe\x32\x1a\x2f\xbd\x44\x24\x2a\x3f\x2d\x24\x2a\x3f\x8f\x34\x9f\xbe\x8f\x34\x9f\xbe\xbb\xe8\x9e\xbe\x60\x2b\x72\xbe\x37\x5a\x29\x3d\xa1\x68\x53\x3e\x02\x69\x53\x3e\x46\x3a\x66\x3f\x46\x3a\x66\x3f\x92\x3a\x67\xbf\x2f\x7c\x75\xbe\x3e\x10\xfe\x3d\x28\xf5\xfe\xbe\xa2\xf4\xfe\xbe\xf5\x0a\x6d\xbf\xf5\x0a\x6d\xbf\x9a\xd9\x6e\xbf\xa2\xca\x78\xbe\x2c\xa2\x4f\x3e\x57\x9d\x1b\xbf\xf1\x9c\x1b\xbf\x73\xf8\xbf\x3e\x73\xf8\xbf\x3e\x23\xe5\xc3\xbe\xaa\x16\x7c\xbe\x77\xcf\x8c\x3e\x1f\x88\x1a\x3c\x4f\xa7\x1a\x3c\xc3\x9d\xd2\x3e\xc3\x9d\xd2\x3e\x40\x4c\xcf\x3e\x49\x60\x7f\xbe\xc0\x57\xad\x3e\xe3\x58\x1d\x3f\x69\x59\x1d\x3f\x3b\x39\x72\xbf\x3b\x39\x72\xbf\x9c\xe2\x70\x3f\xb8\x53\x81\xbe\xcd\x67\xc8\x3e\x86\x69\xf7\x3e\x8c\x6a\xf7\x3e\xd0\x44\x66\x3f\xd0\x44\x66\x3f\xeb\x0a\x65\x3f\x0f\xf6\x82\xbe\x53\x2a\xdd\x3e\xf7\x6a\x6a\xbe\x36\x69\x6a\xbe\x5e\xde\x99\xbe\x5e\xde\x99\xbe\xb8\x99\x97\x3e\x21\x97\x84\xbe\x24\xfe\xea\x3e\x82\x81\x2a\xbf\x31\x81\x2a\xbf\x62\xb0\xf6\xbe\x62\xb0\xf6\xbe\x17\x1b\xf8\xbe\xec\x36\x86\xbe\xd5\x79\xf1\x3e\x38\xbb\x99\xbe\xe1\xba\x99\xbe\x51\xa0\x77\x3f\x51\xa0\x77\x3f\x10\x74\x77\xbf\x71\xd5\x87\xbe\x66\x6f\xf0\x3e\xfb\x14\xdb\x3e\xfb\x14\xdb\x3e\x55\x12\x5c\xbf\x55\x12\x5c\xbf\x02\xd1\x5a\xbf\xaf\x72\x89\xbe\x1f\xec\xe7\x3e\x4d\xd0\x23\x3f\x23\xd0\x23\x3f\xca\xd9\x68\x3e\xca\xd9\x68\x3e\xc2\x55\x60\xbe\x99\x0e\x8b\xbe\xf0\x38\xd8\x3e\x41\xef\x9a\x3d\xdd\xec\x9a\x3d\xe1\x4f\x0a\x3f\xe1\x4f\x0a\x3f\x7f\xd4\x0c\x3f\x2f\xa9\x8c\xbe\xbe\xd7\xc1\x3e\xb0\xc3\x14\xbf\x18\xc4\x14\xbf\x88\x39\x79\xbf\x88\x39\x79\xbf\x4a\x94\x7b\x3f\x6a\x42\x8e\xbe\xee\x7e\xa5\x3e\xf0\xd9\x07\xbf\x66\xda\x07\xbf\x8a\x33\x4f\x3f\x8a\x33\x4f\x3f\x5e\xe1\x50\x3f\x4c\xda\x8f\xbe\x87\x12\x84\x3e\x9c\xce\x29\x3e\xb2\xcc\x29\x3e\xe2\x00\x1a\xbe\xe2\x00\x1a\xbe\xa0\x78\x1c\x3e\xcf\x70\x91\xbe\xe8\x3a\x3d\x3e\x34\x24\x29\x3f\xc6\x23\x29\x3f\xd0\xc0\x19\xbf\xd0\xc0\x19\xbf\x00\x46\x1a\xbf\xf4\x05\x93\xbe\xc0\x23\xd9\x3d\xfb\x21\xb2\x3e\x4d\x21\xb2\x3e\xe2\xc1\x7c\x3f\xe2\xc1\x7c\x3f\xab\xfc\x7d\xbf\xb3\x99\x94\xbe\x53\x3a\xc5\x3c\x8d\x3e\xc8\xbe\xf8\x3e\xc8\xbe\x7e\xcc\x46\xbf\x7e\xcc\x46\xbf\x0f\xea\x47\xbf\x0a\x2c\x96\xbe\xed\xc0\x6f\xbd\x7d\x6f\x26\xbf\x8f\x6f\x26\xbf\x71\xad\xc6\x3d\x71\xad\xc6\x3d\x52\xce\xc8\xbd\xf3\xbc\x97\xbe\xae\x9e\x0e\xbe\x7c\x35\xe3\xbd\xd2\x34\xe3\xbd\x53\x05\x24\x3f\x53\x05\x24\x3f\xac\xbc\x24\x3f\x6c\x4c\x99\xbe\x89\xdf\x5c\xbe\x0d\x8c\x10\x3f\x46\x8c\x10\x3f\x8d\x19\x7e\xbf\x8d\x19\x7e\xbf\xc1\x48\x7f\x3f\x71\xda\x9a\xbe\xe7\x29\x92\xbe\x1a\x7f\x0b\x3f\x71\x7f\x0b\x3f\x24\x61\x3f\x3f\x24\x61\x3f\x3f\x09\x60\x40\x3f\x00\x67\x9c\xbe\x61\x6a\xb1\xbe\x2d\xb6\x16\xbe\x89\xb4\x16\xbe\x86\xed\x58\xbd\x86\xed\x58\xbd\xde\x0f\x62\x3d\x14\xf2\x9d\xbe\xa1\x42\xcb\xbe\xe4\x67\x28\xbf\x73\x67\x28\xbf\x3a\xce\x2c\xbf\x3a\xce\x2c\xbf\x74\x70\x2c\xbf\xad\x7b\x9f\xbe\xef\xed\xde\xbe\xd7\x38\xb5\xbe\x03\x38\xb5\xbe\x5c\x11\x80\x3f\x5c\x11\x80\x3f\x33\xd0\x7f\xbf\xc2\x03\xa1\xbe\xe3\xd8\xeb\xbe\x1f\x31\xc7\x3e\xcc\x31\xc7\x3e\xcb\x76\x3a\xbf\xcb\x76\x3a\xbf\xaf\x89\x3a\xbf\x56\x8a\xa2\xbe\x1c\xa4\xf1\xbe\xdb\x2a\x26\x3f\x17\x2b\x26\x3f\xa5\xfb\xa3\x3c\xa5\xfb\xa3\x3c\x5c\x94\xc8\xbc\x60\x0f\xa4\xbe\x87\x28\xf0\xbe\x52\xa6\xcf\x3d\x22\xa7\xcf\x3d\x24\x0f\x34\x3f\x24\x0f\x34\x3f\xd6\x92\x31\x3f\xe1\x92\xa5\xbe\x43\x76\xe7\xbe\x51\xd6\x12\xbf\x5d\xd6\x12\xbf\x16\x91\x81\xbf\x16\x91\x81\xbf\xdf\xef\x7f\x3f\xd4\x14\xa7\xbe\xd8\xd5\xd7\xbe\xcf\x21\x08\xbf\xfd\x21\x08\xbf\xab\x68\x39\x3f\xab\x68\x39\x3f\x8b\xb5\x36\x3f\x37\x95\xa8\xbe\x80\xc2\xc1\xbe\x29\x08\x33\x3e\xfc\x06\x33\x3e\xe0\xc6\x38\xbc\xe0\xc6\x38\xbc\x67\x99\xc7\x3b\x04\x14\xaa\xbe\x6e\xec\xa5\xbe\x4f\x9c\x29\x3f\xef\x9b\x29\x3f\xdb\x56\x34\xbf\xdb\x56\x34\xbf\x2c\x61\x34\xbf\x38\x91\xab\xbe\xb8\x2a\x85\xbe\x02\xcb\xa3\x3e\x30\xca\xa3\x3e\xa7\x38\x80\x3f\xa7\x38\x80\x3f\xb7\xfa\x7f\xbf\xf3\x07\xad\xbe\x7f\xf5\x40\xbe\x63\x52\xda\xbe\x33\x53\xda\xbe\xb1\x71\x35\xbf\xb1\x71\x35\xbf\x4b\x13\x35\xbf\x34\x78\xae\xbe\x80\xb8\xe3\xbd\x41\xbd\x22\xbf\x9c\xbd\x22\xbf\xf7\x5d\xf0\x3a\xf7\x5d\xf0\x3a\x89\xa5\xc8\x36\xcb\xed\xaf\xbe\x7f\x03\xfc\xbc\xda\x02\x2e\xbd\xd8\x06\x2e\xbd\x83\xa3\x33\x3f\x83\xa3\x33\x3f\x87\xf0\x34\x3f\xba\x68\xb1\xbe\x9b\xd5\x4e\x3d\x2f\x8c\x1a\x3f\x0f\x8c\x1a\x3f\x83\x74\x7d\xbf\x83\x74\x7d\xbf\x5b\xfa\x7f\x3f\x94\xe2\xb2\xbe\x72\x55\x05\x3e\xbb\x02\xf9\x3e\xbf\x02\xf9\x3e\xf3\x6d\x32\x3f\xf3\x6d\x32\x3f\x33\x9f\x35\x3f\x5c\x5b\xb4\xbe\xce\xed\x52\x3e\x99\x86\x7d\xbe\xfe\x85\x7d\xbe\xed\xea\x84\x3b\xed\xea\x84\x3b\xae\x04\xc9\x3b\x55\xcf\xb5\xbe\x88\x21\x8d\x3e\x1f\xd9\x2a\xbf\xda\xd8\x2a\xbf\x04\x35\x34\xbf\x04\x35\x34\xbf\xc3\x3e\x33\xbf\x81\x3e\xb7\xbe\x2d\x9e\xac\x3e\x69\x3c\x74\xbe\xfb\x3a\x74\xbe\x3a\x1c\x7f\x3f\x3a\x1c\x7f\x3f\x40\xee\x7f\xbf\xf6\xab\xb8\xbe\x6a\x04\xc7\x3e\xa8\xf8\xfc\x3e\x78\xf9\xfc\x3e\x59\x86\x36\xbf\x59\x86\x36\xbf\xb8\x5b\x38\xbf\xb6\x17\xba\xbe\xd4\x8f\xdb\x3e\x62\xc9\x18\x3f\xca\xc9\x18\x3f\x0f\xd1\x8d\x3c\x0f\xd1\x8d\x3c\x08\xf0\xc8\xbc\xb7\x81\xbb\xbe\xf9\xad\xe9\x3e\x8a\xb9\x81\xbd\xa2\xb6\x81\xbd\xba\x9b\x30\x3f\xba\x9b\x30\x3f\xa7\x4c\x2f\x3f\xfc\xe9\xbc\xbe\xe1\xf8\xf0\x3e\xa5\x97\x24\xbf\x5f\x97\x24\xbf\xee\x4c\x80\xbf\xee\x4c\x80\xbf\x3b\xce\x7f\x3f\x7c\x50\xbe\xbe\xa4\x3f\xf1\x3e\x5f\xd7\xcb\xbe\x12\xd7\xcb\xbe\x9b\xb7\x3d\x3f\x9b\xb7\x3d\x3f\x81\x38\x3d\x3f\x3a\xb5\xbf\xbe\xc2\x83\xea\x3e\x19\x64\xb7\x3e\x21\x64\xb7\x3e\xda\x31\x65\xbd\xda\x31\x65\xbd\x98\xfb\x61\x3d\x2c\x18\xc1\xbe\x1f\xfe\xdc\x3e\x44\x76\x27\x3f\x23\x76\x27\x3f\xae\x3a\x29\xbf\xae\x3a\x29\xbf\xba\xed\x28\xbf\x54\x79\xc2\xbe\xdf\x16\xc9\x3e\xac\x21\xdb\x3d\xa4\x1f\xdb\x3d\xa7\x13\x80\x3f\xa7\x13\x80\x3f\xcb\x48\x7f\xbf\xaa\xd8\xc3\xbe\x98\x66\xaf\x3e\x20\x35\x14\xbf\x7c\x35\x14\xbf\xa7\x08\x45\xbf\xa7\x08\x45\xbf\x6e\xf0\x43\xbf\x2e\x36\xc5\xbe\xfc\xad\x90\x3e\x83\x11\x04\xbf\xed\x11\x04\xbf\x1f\x53\xce\x3d\x1f\x53\xce\x3d\x43\xac\xc8\xbd\xd8\x91\xc6\xbe\x96\xa8\x5b\x3e\x23\xcc\x5c\x3e\x63\xca\x5c\x3e\xa5\xfe\x1f\x3f\xa5\xfe\x1f\x3f\x28\xe0\x1f\x3f\xa9\xeb\xc7\xbe\x5f\xb7\x0f\x3e\x2d\xcb\x2a\x3f\xc7\xca\x2a\x3f\x04\xdf\x7e\xbf\x04\xdf\x7e\xbf\x23\xfe\x7d\x3f\x9b\x43\xc9\xbe\xf4\xe9\x7e\x3d\x04\x05\x81\x3e\x60\x04\x81\x3e\x79\x67\x4d\x3f\x79\x67\x4d\x3f\x55\x3c\x4c\x3f\xaf\x99\xca\xbe\x15\x1e\x90\xbc\xe3\x6a\xfb\xbe\x4b\x6b\xfb\xbe\x44\x75\x20\xbe\x44\x75\x20\xbe\x12\x70\x1c\x3e\xde\xed\xcb\xbe\xec\x52\xc6\xbd\xbc\x23\x18\xbf\xcd\x23\x18\xbf\xbd\x38\x13\xbf\xbd\x38\x13\xbf\x3f\xf3\x13\xbf\x26\x40\xcd\xbe\x8f\x67\x31\xbe\x6d\x43\xa0\x3d\x29\x44\xa0\x3d\xf0\xf9\x7a\x3f\xf0\xf9\x7a\x3f\xe6\x94\x7b\xbf\x84\x90\xce\xbe\x66\x86\x7a\xbe\x08\x19\x26\x3f\x46\x19\x26\x3f\x81\x38\x55\xbf\x81\x38\x55\xbf\xa3\xc5\x55\xbf\xf5\xde\xcf\xbe\xb3\x3c\x9e\xbe\x29\x5a\xbd\x3e\xde\x5a\xbd\x3e\xd0\x71\x5f\x3e\xd0\x71\x5f\x3e\xd7\x60\x60\xbe\x74\x2b\xd1\xbe\x4f\xb2\xba\xbe\x92\x2d\xca\xbe\xb4\x2c\xca\xbe\xa1\x51\x04\x3f\xa1\x51\x04\x3f\x0d\xde\x04\x3f\x00\x76\xd2\xbe\x59\xd9\xd1\xbe\x0c\x27\x24\xbf\x95\x26\x24\xbf\xb5\xde\x75\xbf\xb5\xde\x75\xbf\xb3\x72\x77\x3f\x91\xbe\xd3\xbe\xfe\x0d\xe3\xbe\x2d\xe9\x2e\xbd\xdd\xe1\x2e\xbd\xd7\x9e\x5d\x3f\xd7\x9e\x5d\x3f\x26\xf2\x5f\x3f\x27\x05\xd5\xbe\x9e\xd9\xed\xbe\x81\xdf\x1c\x3f\xe5\xdf\x1c\x3f\xc1\xed\x92\xbe\xc1\xed\x92\xbe\xef\xa3\x97\x3e\xc0\x49\xd6\xbe\x67\xf2\xf1\xbe\x6c\x88\xea\x3e\xfb\x88\xea\x3e\x14\xf0\xe7\xbe\x14\xf0\xe7\xbe\xe5\x97\xe4\xbe\x5e\x8c\xd7\xbe\xbb\x3f\xef\xbe\x37\xe2\x9a\xbe\xef\xe1\x9a\xbe\x5c\x96\x71\x3f\x5c\x96\x71\x3f\xb1\xe0\x70\xbf\xf4\xcc\xd8\xbe\x17\xd9\xe5\xbe\xd4\x7a\x29\xbf\xdc\x7a\x29\xbf\x90\x07\x6a\xbf\x90\x07\x6a\xbf\x87\x0d\x6a\xbf\x85\x0b\xda\xbe\xfd\x07\xd6\xbe\x06\xd0\x12\xbe\xc8\xd0\x12\xbe\x3d\x41\xc3\x3e\x3d\x41\xc3\x3e\x19\xeb\xc3\xbe\x0b\x48\xdb\xbe\xad\x41\xc0\xbe\x80\x19\x11\x3f\x2b\x19\x11\x3f\x5c\xea\xb8\x3e\x5c\xea\xb8\x3e\x55\x0e\xb8\x3e\x86\x82\xdc\xbe\x74\x25\xa5\xbe\xbf\x9c\x05\x3f\x4d\x9c\x05\x3f\x7a\xeb\x67\xbf\x7a\xeb\x67\xbf\x4a\x3b\x67\x3f\xef\xba\xdd\xbe\x78\x77\x85\xbe\x4d\xb3\x60\xbe\x55\xb5\x60\xbe\x65\x9e\x74\x3f\x65\x9e\x74\x3f\x13\x57\x73\x3f\x44\xf1\xde\xbe\x96\x3a\x44\xbe\x4d\xcb\x2a\xbf\xd0\xcb\x2a\xbf\x87\x1c\xf8\xbe\x87\x1c\xf8\xbe\x60\x1c\xf4\x3e\x83\x25\xe0\xbe\x29\x4e\xf0\xbd\xaa\x1a\x64\xbe\x94\x1c\x64\xbe\x7b\xee\x7d\xbe\x7b\xee\x7d\xbe\x53\xd3\x83\xbe\xab\x57\xe1\xbe\xba\x4e\x23\xbd\xc3\x65\x05\x3f\x63\x65\x05\x3f\xab\x84\x57\x3f\xab\x84\x57\x3f\x25\xbe\x59\xbf\xb6\x87\xe2\xbe\x7f\x35\x1e\x3d\x3f\xb8\x10\x3f\x05\xb8\x10\x3f\x80\x70\x79\xbf\x80\x70\x79\xbf\x8e\xc9\x7a\xbf\xa5\xb5\xe3\xbe\x77\x86\xed\x3d\x4e\xfa\x1a\xbe\x92\xfa\x1a\xbe\xb9\x55\x13\x3f\xb9\x55\x13\x3f\xbc\x66\x13\xbf\x71\xe1\xe4\xbe\x2c\xa2\x42\x3e\x35\xed\x29\xbf\x1a\xed\x29\xbf\x4a\xc9\x0a\x3e\x4a\xc9\x0a\x3e\x67\xa0\x0f\x3e\x1a\x0b\xe6\xbe\xd1\x8b\x84\x3e\xd7\x01\x90\xbe\x47\x01\x90\xbe\xbf\x7e\x45\xbf\xbf\x7e\x45\xbf\xe0\x98\x47\x3f\x9a\x32\xe7\xbe\xd6\x1d\xa4\x3e\xe1\xfc\xf6\x3e\xbb\xfd\xf6\x3e\x90\xe2\x7c\x3f\x90\xe2\x7c\x3f\xa3\x37\x7f\x3f\xf2\x57\xe8\xbe\x36\x2b\xbf\x3e\xf5\xcd\x17\x3f\x7b\xce\x17\x3f\xb0\x4b\x2b\xbf\xb0\x4b\x2b\xbf\x08\x0f\x2d\x3f\x1a\x7b\xe9\xbe\x20\xfa\xd4\x3e\x79\xfa\xcf\xbd\xf5\xf5\xcf\xbd\x80\xa2\x2d\xbc\x80\xa2\x2d\xbc\xb5\xaa\x0f\xbc\x14\x9c\xea\xbe\xf7\xf6\xe4\x3e\x37\x41\x28\xbf\xaa\x40\x28\xbf\x54\x07\x2f\x3f\x54\x07\x2f\x3f\xfa\x33\x30\xbf\xdb\xba\xeb\xbe\x2a\xb7\xee\x3e\xb3\x8b\xa3\xbe\xbd\x8a\xa3\xbe\x29\xf9\x7c\xbf\x29\xf9\x7c\xbf\x9f\x7c\x7f\xbf\x70\xd7\xec\xbe\x14\xfa\xf1\x3e\x08\x5f\xe8\x3e\xbe\x5f\xe8\x3e\x19\x02\x43\x3f\x19\x02\x43\x3f\xb0\xe3\x45\xbf\xca\xf1\xed\xbe\x93\xae\xee\x3e\x22\xae\x1b\x3f\x52\xae\x1b\x3f\x27\x4d\x02\xbe\x27\x4d\x02\xbe\xad\x3c\x0a\xbe\xe8\x09\xef\xbe\x23\xf0\xe4\x3e\x23\xea\x8e\xbd\x1b\xea\x8e\xbd\x61\x39\x13\xbf\x61\x39\x13\xbf\x9e\x16\x13\x3f\xcb\x1f\xf0\xbe\x70\x07\xd5\x3e\x82\xdf\x26\xbf\xb1\xdf\x26\xbf\x57\x69\x78\x3f\x57\x69\x78\x3f\xe0\x47\x7a\x3f\x71\x33\xf1\xbe\xdf\x65\xbf\x3e\x76\x27\xae\xbe\x2c\x28\xae\xbe\x2f\x2d\x59\xbf\x2f\x2d\x59\xbf\x9b\x64\x5c\x3f\xd2\x44\xf2\xbe\x75\xa3\xa4\x3e\x07\xf5\xe0\x3e\x0b\xf4\xe0\x3e\x91\x42\x8c\x3e\x91\x42\x8c\x3e\xad\x4c\x93\x3e\xee\x53\xf3\xbe\x05\x7c\x85\x3e\x48\x4e\x1d\x3f\xb6\x4d\x1d\x3f\x6e\xc4\xe5\x3e\x6e\xc4\xe5\x3e\xc4\xe0\xdf\xbe\xc1\x60\xf4\xbe\xc7\x96\x45\x3e\x9e\x75\x6d\xbd\x5a\x7f\x6d\xbd\x1f\x2a\x70\xbf\x1f\x2a\x70\xbf\x55\x39\x6e\xbf\x4c\x6b\xf5\xbe\xea\xfb\xf5\x3d\x37\x74\x26\xbf\xcb\x74\x26\xbf\xbe\xa8\x6f\x3f\xbe\xa8\x6f\x3f\x84\xce\x6e\xbf\x88\x73\xf6\xbe\x38\xab\x34\x3d\xbf\xf9\xaf\xbe\xb7\xfa\xaf\xbe\x02\x03\xe3\xbe\x02\x03\xe3\xbe\x76\x80\xe3\xbe\x78\x79\xf7\xbe\xf8\x26\x07\xbd\x60\xf0\xe0\x3e\xb3\xef\xe0\x3e\x69\x9d\x90\xbe\x69\x9d\x90\xbe\x18\xd6\x8d\x3e\x14\x7d\xf8\xbe\x67\x84\xdf\xbd\x6b\xe5\x1c\x3f\x43\xe5\x1c\x3f\x98\xb8\x5c\x3f\x98\xb8\x5c\x3f\xb1\x43\x5a\x3f\x5f\x7e\xf9\xbe\xc8\xb0\x3a\xbe\x3b\x6f\x85\xbd\xed\x6e\x85\xbd\xa3\x6b\x7e\xbf\xa3\x6b\x7e\xbf\x1d\x56\x7b\x3f\x50\x7d\xfa\xbe\xfa\x4d\x80\xbe\x5a\x3e\x27\xbf\x1c\x3e\x27\xbf\x2a\x17\x1c\x3f\x2a\x17\x1c\x3f\x15\x30\x19\x3f\xe9\x79\xfb\xbe\xb1\xd8\x9f\xbe\x6c\x77\xa9\xbe\x9c\x76\xa9\xbe\xab\x8a\xb6\x3d\xab\x8a\xb6\x3d\x5c\x8c\xc5\xbd\x25\x74\xfc\xbe\x30\x20\xbb\xbe\x9a\x6b\xe9\x3e\xb1\x6c\xe9\x3e\x5f\x2a\x3d\xbf\x5f\x2a\x3d\xbf\x3c\x9a\x3d\xbf\x06\x6c\xfd\xbe\xad\x6a\xd1\xbe\x42\x7d\x1a\x3f\xe1\x7d\x1a\x3f\xab\x5c\x80\x3f\xab\x5c\x80\x3f\xc6\xfe\x7f\xbf\x84\x61\xfe\xbe\x40\xf3\xe1\xbe\xf2\x9a\xc2\xbd\xde\x95\xc2\xbd\xc2\xdf\x3e\xbf\xc2\xdf\x3e\xbf\x63\xc1\x3d\xbf\xa2\x54\xff\xbe\x66\xc0\xec\xbe\x41\x48\x28\xbf\xae\x47\x28\xbf\xb0\xcb\xd1\x3d\xb0\xcb\xd1\x3d\x3e\xf2\xcb\xbd\xac\x22\x00\xbf\x83\x61\xf1\xbe\x40\xbd\x97\xbe\x4e\xbc\x97\xbe\x8b\xbd\x17\x3f\x8b\xbd\x17\x3f\x45\xc6\x17\x3f\xd5\x99\x00\xbf\x4e\xb7\xef\xbe\xef\x78\xf6\x3e\x92\x79\xf6\x3e\x1a\x23\x7b\xbf\x1a\x23\x7b\xbf\xd9\xbf\x7a\x3f\xc8\x0f\x01\xbf\x53\xcb\xe7\xbe\xe8\xa5\x14\x3f\x08\xa6\x14\x3f\xa5\x08\x5d\x3f\xa5\x08\x5d\x3f\x0c\xcf\x5c\x3f\x85\x84\x01\xbf\x53\xd7\xd9\xbe\x36\xc2\x0e\xbe\x88\xc2\x0e\xbe\x1f\x89\x9a\xbe\x1f\x89\x9a\xbe\xc9\x5b\x9b\x3e\x0c\xf8\x01\xbf\xdd\x3c\xc6\xbe\x1e\xd3\x29\xbf\x67\xd3\x29\xbf\x2c\x73\xd4\xbe\x2c\x73\xd4\xbe\x94\x25\xd2\xbe\x5a\x6a\x02\xbf\xfe\x84\xad\xbe\xe3\x07\x7e\xbe\xab\x09\x7e\xbe\xdd\xa8\x6b\x3f\xdd\xa8\x6b\x3f\xe1\x02\x6a\xbf\x70\xdb\x02\xbf\xc2\x56\x90\xbe\xd1\x84\x05\x3f\x3f\x84\x05\x3f\x50\x51\x75\xbf\x50\x51\x75\xbf\x02\x93\x73\xbf\x4c\x4b\x03\xbf\xc5\xe6\x5e\xbe\xab\x7c\x0c\x3f\x06\x7c\x0c\x3f\xff\xa8\x02\x3f\xff\xa8\x02\x3f\x45\x3c\x01\xbf\xec\xb9\x03\xbf\x51\x6f\x17\xbe\xe0\x5f\x53\xbe\x78\x62\x53\xbe\x17\x93\x47\x3e\x17\x93\x47\x3e\x5d\x75\x4a\x3e\x4e\x27\x04\xbf\x8c\x4e\x98\xbd\xb9\x93\x2a\xbf\x4f\x94\x2a\xbf\x57\xfc\x4c\xbf\x57\xfc\x4c\xbf\xab\xac\x4c\x3f\x74\x93\x04\xbf\xcd\xc6\x82\x3a\x09\xc0\x32\xbe\xec\xc1\x32\xbe\xea\x4e\x80\x3f\xea\x4e\x80\x3f\xb8\x1f\x7f\x3f\x5e\xfe\x04\xbf\x62\x37\x9c\x3d\x44\x3a\x11\x3f\xf7\x39\x11\x3f\x4e\x47\x33\xbf\x4e\x47\x33\xbf\x02\xce\x30\x3f\x06\x68\x05\xbf\x18\x1e\x19\x3e\x4a\xe7\xfd\x3e\x16\xe7\xfd\x3e\xaa\x39\x46\x3d\xaa\x39\x46\x3d\xed\x79\x18\x3d\x70\xd0\x05\xbf\x84\x23\x60\x3e\x52\x2c\x93\xbe\x1d\x2c\x93\xbe\x31\xf0\x1f\x3f\x31\xf0\x1f\x3f\x6a\x61\x22\xbf\x96\x37\x06\xbf\x78\xb0\x90\x3e\x66\x4b\x28\xbf\x19\x4b\x28\xbf\x97\x5d\x7b\xbf\x97\x5d\x7b\xbf\xa0\xb3\x7c\xbf\x7c\x9d\x06\xbf\x9e\x99\xad\x3e\xfa\x2d\xa5\xbd\x3c\x2a\xa5\xbd\xb4\x96\x58\x3f\xb4\x96\x58\x3f\x81\x78\x58\xbf\x1c\x02\x07\xbf\x9f\x14\xc6\x3e\x38\xe8\x1c\x3f\xce\xe8\x1c\x3f\x24\x6c\x93\xbe\x24\x6c\x93\xbe\x8c\x4d\x90\xbe\x7a\x65\x07\xbf\xc8\x83\xd9\x3e\x51\x65\xd7\x3e\x9f\x66\xd7\x3e\x27\x91\xd2\xbe\x27\x91\xd2\xbe\xbe\x05\xd8\x3e\x92\xc7\x07\xbf\x5e\x6c\xe7\x3e\x5e\xc4\xc2\xbe\x10\xc3\xc2\xbe\xf2\xe5\x66\x3f\xf2\xe5\x66\x3f\x8d\x4b\x6a\x3f\x64\x28\x08\xbf\x24\x7a\xef\x3e\x3c\x66\x21\xbf\xa8\x65\x21\xbf\x91\xdc\x70\xbf\x91\xdc\x70\xbf\x92\x28\x74\x3f\xf0\x87\x08\xbf\x8c\x7d\xf1\x3e\xaf\xee\x0e\x3d\xff\xf5\x0e\x3d\x40\xd3\x02\x3f\x40\xd3\x02\x3f\xc5\x0a\x05\x3f\x32\xe6\x08\xbf\xcf\x6b\xed\x3e\x16\x83\x26\x3f\x5f\x83\x26\x3f\x81\x22\x30\x3e\x81\x22\x30\x3e\x8c\x12\x2f\xbe\x2d\x43\x09\xbf\x70\x64\xe3\x3e\x1d\xd4\xa2\x3e\x4f\xd4\xa2\x3e\x00\xde\x44\xbf\x00\xde\x44\xbf\xf9\xd4\x46\xbf\xde\x9e\x09\xbf\xa3\xac\xd3\x3e\x76\x53\xf5\xbe\xb4\x53\xf5\xbe\xa8\x43\x7c\x3f\xa8\x43\x7c\x3f\x21\xd9\x7f\xbf\x44\xf9\x09\xbf\x88\xad\xbe\x3e\x34\x5e\x13\xbf\x83\x5e\x13\xbf\x37\x2f\x37\xbf\x37\x2f\x37\xbf\xd5\x15\x3b\xbf\x5f\x52\x0a\xbf\xd1\xf0\xa4\x3e\x74\x44\x2f\x3e\x92\x42\x2f\x3e\x67\x3c\xbe\x3d\x67\x3c\xbe\x3d\x7c\x25\xd5\xbd\x2d\xaa\x0a\xbf\xf1\x1c\x87\x3e\x71\x93\x2a\x3f\xdb\x92\x2a\x3f\xce\xc3\x13\x3f\xce\xc3\x13\x3f\x5b\xae\x12\x3f\xaf\x00\x0b\xbf\x37\xe6\x4b\x3e\x6e\x4a\x3b\x3e\xe0\x47\x3b\x3e\x05\x9f\x77\xbf\x05\x9f\x77\xbf\x5a\x34\x78\x3f\xe4\x55\x0b\xbf\x37\x94\x04\x3e\x0c\xaa\x11\xbf\xb0\xaa\x11\xbf\xe8\x18\x63\x3f\xe8\x18\x63\x3f\x44\xab\x64\x3f\xca\xa9\x0b\xbf\xc9\x2a\x68\x3d\x64\x98\xf7\xbe\x86\x99\xf7\xbe\xa7\x30\xc0\xbe\xa7\x30\xc0\xbe\xe8\xe0\xc3\x3e\x60\xfc\x0b\xbf\x9d\xf1\x8e\xbc\xae\xc7\xa1\x3e\xc9\xc6\xa1\x3e\x04\xd8\xa3\xbe\x04\xd8\xa3\xbe\xa2\x6b\xa0\xbe\xa6\x4d\x0c\xbf\x6a\x88\xba\xbd\x0f\x25\x26\x3f\xc9\x24\x26\x3f\x3f\xd3\x5c\x3f\x3f\xd3\x5c\x3f\xc7\x5b\x5b\xbf\x9a\x9d\x0c\xbf\x86\x4a\x26\xbe\xc2\xb5\xa6\x3c\xde\xb2\xa6\x3c\x3e\x86\x7d\xbf\x3e\x86\x7d\xbf\xc0\x5c\x7c\xbf\x40\xec\x0c\xbf\xc2\x28\x6b\xbe\x73\x5f\x23\xbf\x57\x5f\x23\xbf\xf7\x4c\x24\x3f\xf7\x4c\x24\x3f\x24\x9b\x23\xbf\x90\x39\x0d\xbf\x48\x18\x95\xbe\x17\xa2\xb2\xbe\x7b\xa1\xb2\xbe\xa4\x96\x72\x3c\xa4\x96\x72\x3c\x31\x66\x75\x3c\x8d\x85\x0d\xbf\xf7\xed\xb0\xbe\x2d\x13\xeb\x3e\x17\x14\xeb\x3e\x02\xe1\x29\xbf\x02\xe1\x29\xbf\x94\x4a\x29\x3f\x38\xd0\x0d\xbf\x8c\x68\xc8\xbe\xbc\x69\x15\x3f\x4e\x6a\x15\x3f\x8a\x55\x7e\x3f\x8a\x55\x7e\x3f\xa4\x72\x7d\x3f\x91\x19\x0e\xbf\xad\xf7\xda\xbe\x92\x0c\x27\xbe\x1a\x0a\x27\xbe\x2d\xfe\x58\xbf\x2d\xfe\x58\xbf\xe5\x48\x58\x3f\x94\x61\x0e\xbf\xc4\x2c\xe8\xbe\x55\xc0\x2a\xbf\xb8\xbf\x2a\xbf\x5e\x5c\x98\x3e\x5e\x5c\x98\x3e\x5b\xd2\x97\x3e\x3f\xa8\x0e\xbf\x38\xba\xef\xbe\x88\x88\x2f\xbe\x58\x86\x2f\xbe\x41\xde\xc8\x3e\x41\xde\xc8\x3e\xa3\xf8\xc8\xbe\x94\xed\x0e\xbf\x15\x74\xf1\xbe\x4d\x08\x15\x3f\xbc\x08\x15\x3f\xf5\x80\x64\xbf\xf5\x80\x64\xbf\xfb\xf0\x64\xbf\x90\x31\x0f\xbf\xcf\x52\xed\xbe\xd7\x90\xeb\x3e\x61\x91\xeb\x3e\xb9\x53\x77\x3f\xb9\x53\x77\x3f\x91\xab\x78\xbf\x36\x74\x0f\xbf\x1d\x75\xe3\xbe\xcb\x86\xb5\xbe\x9f\x86\xb5\xbe\x66\x83\x14\xbf\x66\x83\x14\xbf\x2e\xaa\x16\xbf\x86\xb5\x0f\xbf\x7b\x1c\xd4\xbe\x4d\x2b\x22\xbf\x67\x2b\x22\xbf\xd6\xec\xa3\xbd\xd6\xec\xa3\xbd\x70\x6c\x93\x3d\x7c\xf5\x0f\xbf\xe0\xab\xbf\xbe\x90\x64\x30\x3d\x10\x60\x30\x3d\xfd\x5a\x33\x3f\xfd\x5a\x33\x3f\x2f\xb0\x32\x3f\x18\x34\x10\xbf\x21\xa4\xa6\xbe\xc4\x38\x27\x3f\x56\x38\x27\x3f\xf4\x13\x7d\xbf\xf4\x13\x7d\xbf\x5d\xc0\x7e\x3f\x5c\x71\x10\xbf\x92\xa1\x89\xbe\x7f\x67\x8d\x3e\x6d\x66\x8d\x3e\x35\x37\x4f\x3f\x35\x37\x4f\x3f\x98\x26\x53\x3f\x44\xad\x10\xbf\x3c\xb6\x52\xbe\xab\x08\x05\xbf\x42\x09\x05\xbf\x4b\x99\x7e\xbe\x4b\x99\x7e\xbe\x55\x52\x89\x3e\xd2\xe7\x10\xbf\x7a\x31\x0d\xbe\x4a\x4f\x07\xbf\xdf\x4f\x07\xbf\x3f\x58\xdc\xbe\x3f\x58\xdc\xbe\x05\x9e\xd3\xbe\x05\x21\x11\xbf\xba\xbc\x88\xbd\x74\x7d\x89\x3e\x67\x7c\x89\x3e\x9c\x10\x69\x3f\x9c\x10\x69\x3f\x43\xc2\x66\xbf\xdb\x58\x11\xbf\x47\xa0\xc0\x3b\x1b\x76\x28\x3f\xb0\x75\x28\x3f\x50\xe7\x77\xbf\x50\xe7\x77\xbf\x7a\x2a\x78\xbf\x54\x8f\x11\xbf\x3b\x64\xa0\x3d\xeb\x98\x27\x3d\xad\x94\x27\x3d\xfc\xd9\x13\x3f\xfc\xd9\x13\x3f\x5b\x46\x16\xbf\x71\xc4\x11\xbf\x9c\x64\x18\x3e\x5a\x9a\x23\xbf\x73\x9a\x23\xbf\x54\xdd\xa6\x3d\x54\xdd\xa6\x3d\x80\x63\x89\x3d\x31\xf8\x11\xbf\xd1\xea\x5c\x3e\x91\x57\xad\xbe\x65\x57\xad\xbe\x7f\x8b\x34\xbf\x7f\x8b\x34\xbf\xd8\x81\x30\x3f\x93\x2a\x12\xbf\xb0\x13\x8e\x3e\x0b\x10\xf6\x3e\x8b\x10\xf6\x3e\x6a\xf7\x80\x3f\x6a\xf7\x80\x3f\x9a\x36\x7e\x3f\x98\x5b\x12\xbf\x4d\x51\xaa\x3e\x31\x6e\x0f\x3f\x97\x6e\x0f\x3f\x9b\xb4\x59\xbf\x9b\xb4\x59\xbf\x2b\xc3\x56\x3f\x3e\x8b\x12\xbf\x6c\x83\xc2\x3e\xca\xbf\x61\xbe\xcc\xbd\x61\xbe\xb2\xf9\x9c\x3e\xb2\xf9\x9c\x3e\xa5\x4a\x99\x3e\x86\xb9\x12\xbf\xb3\x1d\xd6\x3e\x58\x87\x29\xbf\xca\x86\x29\xbf\xd2\xd5\xbf\x3e\xd2\xd5\xbf\x3e\xf6\xfe\xc0\xbe\x6e\xe6\x12\xbf\x94\xaf\xe4\x3e\xda\x36\xa9\xbd\x74\x32\xa9\xbd\x91\xe1\x61\xbf\x91\xe1\x61\xbf\x3e\x54\x61\xbf\xf8\x11\x13\xbf\xf3\xe3\xed\x3e\x9d\x75\x20\x3f\x1d\x76\x20\x3f\x89\x5d\x7c\x3f\x89\x5d\x7c\x3f\xce\x24\x7b\xbf\x2a\x39\x13\xbf\xc9\x83\xf1\x3e\xae\x81\xba\x3e\x78\x82\xba\x3e\x4b\xbf\x23\xbf\x4b\xbf\x23\xbf\x7f\x7b\x22\xbf\x04\x5c\x13\xbf\x50\x7c\xef\x3e\x14\xa3\xed\xbe\x8d\xa2\xed\xbe\xf0\x9b\x56\x3b\xf0\x9b\x56\x3b\xb8\x50\xf3\xb7\xcc\x80\x13\xbf\x39\xe7\xe7\x3e\xba\xe8\x11\xbf\xa1\xe8\x11\xbf\xcc\x06\x22\x3f\xcc\x06\x22\x3f\xc4\x52\x22\x3f\x82\xa7\x13\xbf\xce\xe7\xda\x3e\x80\xcd\x57\x3e\x44\xcd\x57\x3e\xf6\xf7\x7a\xbf\xf6\xf7\x7a\xbf\x5a\xff\x7a\x3f\xcd\xce\x13\xbf\xe6\xde\xc8\x3e\x38\x72\x29\x3f\xfe\x71\x29\x3f\x55\x01\x62\x3f\x55\x01\x62\x3f\xd0\x2c\x62\x3f\xae\xf6\x13\xbf\x44\x32\xb2\x3e\x08\x47\xa6\x3d\x38\x44\xa6\x3d\x8c\x8f\xc5\xbe\x8c\x8f\xc5\xbe\xe8\xcf\xc6\x3e\x94\x1a\x14\xbf\xcd\x6c\x97\x3e\x4c\x58\x20\xbf\xc0\x58\x20\xbf\x2e\x59\x92\xbe\x2e\x59\x92\xbe\x94\xe9\x8f\xbe\x7e\x3a\x14\xbf\xfe\x58\x72\x3e\x01\xa1\xb5\xbe\x02\xa2\xb5\xbe\x58\xae\x54\x3f\x58\xae\x54\x3f\x34\xd9\x52\xbf\x05\x59\x14\xbf\xf8\x57\x30\x3e\xcc\x2c\xf3\x3e\xc4\x2b\xf3\x3e\xcf\xc9\x80\xbf\xcf\xc9\x80\xbf\x6b\x29\x7f\xbf\x29\x76\x14\xbf\x79\xb0\xd4\x3d\x83\xfb\x0e\x3f\x0d\xfb\x0e\x3f\x2b\x37\x3c\x3f\x2b\x37\x3c\x3f\x2c\x62\x39\xbf\xea\x91\x14\xbf\x70\xea\x07\x3d\xaa\x47\x73\xbe\x2d\x49\x73\xbe\x0c\x05\x0f\xbe\x0c\x05\x0f\xbe\xb1\xef\x03\xbe\x47\xac\x14\xbf\x8a\x6e\x1c\xbd\x33\xac\x28\xbf\x73\xac\x28\xbf\xe6\x17\x04\xbf\xe6\x17\x04\xbf\x10\xf6\x05\x3f\x40\xc5\x14\xbf\x38\x76\xde\xbd\x39\x00\x26\xbd\x0d\x02\x26\xbd\x89\x3c\x71\x3f\x89\x3c\x71\x3f\x68\x44\x71\x3f\xd4\xdc\x14\xbf\xb3\xbf\x34\xbe\x81\x8f\x24\x3f\x8c\x8f\x24\x3f\x53\xdb\x73\xbf\x53\xdb\x73\xbf\x1e\x90\x71\x3f\x03\xf3\x14\xbf\x03\x16\x76\xbe\x56\x62\x9d\x3e\xb3\x62\x9d\x3e\x3e\x3a\x0b\x3f\x3e\x3a\x0b\x3f\x02\x0c\x07\x3f\xcd\x07\x15\xbf\x27\xe3\x98\xbe\x56\x02\x04\xbf\x08\x02\x04\xbf\x8f\x3b\xd2\x3d\x8f\x3b\xd2\x3d\x35\x95\xf7\xbd\x31\x1b\x15\xbf\x75\x3c\xb3\xbe\xe6\xcc\x04\xbf\x7f\xcc\x04\xbf\x86\xd0\x33\xbf\x86\xd0\x33\xbf\xde\x26\x37\xbf\x30\x2d\x15\xbf\xba\x80\xc9\xbe\x9f\xf8\x9a\x3e\x88\xf9\x9a\x3e\x1f\x21\x7e\x3f\x1f\x21\x7e\x3f\x77\xbf\x7e\xbf\xc7\x3d\x15\xbf\x92\x31\xdb\xbe\x12\x52\x24\x3f\x8a\x52\x24\x3f\x9c\xf8\x58\xbf\x9c\xf8\x58\xbf\x78\x9d\x56\xbf\xf7\x4c\x15\xbf\x24\xed\xe7\xbe\xae\x7f\x30\xbd\xc6\x78\x30\xbd\x38\xf3\xa9\x3e\x38\xf3\xa9\x3e\x28\x54\xa1\xbe\xc0\x5a\x15\xbf\x6a\x6c\xef\xbe\x94\xbf\x28\xbf\x39\xbf\x28\xbf\x87\xcd\xa7\x3e\x87\xcd\xa7\x3e\xe5\xb4\xb0\x3e\x24\x67\x15\xbf\x42\x89\xf1\xbe\x6e\x42\x62\xbe\x72\x41\x62\xbe\x23\xef\x57\xbf\x23\xef\x57\xbf\xb6\xbc\x5a\x3f\x1e\x72\x15\xbf\x81\x39\xee\xbe\x3a\x99\x12\x3f\x59\x99\x12\x3f\x18\xdb\x7d\x3f\x18\xdb\x7d\x3f\x52\xf6\x7d\x3f\xb1\x7b\x15\xbf\xb5\x95\xe5\xbe\xfb\x38\xe5\x3e\xf2\x38\xe5\x3e\x32\xa1\x35\xbf\x32\xa1\x35\xbf\x80\x0d\x33\x3f\xdc\x83\x15\xbf\x9b\xd2\xd7\xbe\x78\xb5\xcc\xbe\xc2\xb5\xcc\xbe\x09\xa1\xf8\x3d\x09\xa1\xf8\x3d\x4f\x06\xd6\x3d\xa1\x8a\x15\xbf\x37\x43\xc5\xbe\x90\x3a\x1a\xbf\xd5\x3a\x1a\xbf\x60\x4c\x04\x3f\x60\x4c\x04\x3f\x32\xf5\x08\xbf\xfd\x8f\x15\xbf\x40\x54\xae\xbe\x29\xba\x2c\x3e\xc2\xb8\x2c\x3e\x82\xe7\x6d\xbf\x82\xe7\x6d\xbf\x0b\x88\x71\xbf\xf0\x93\x15\xbf\x0c\x8b\x93\xbe\x26\x8d\x2a\x3f\xbe\x8c\x2a\x3f\xe8\x7c\x70\x3f\xe8\x7c\x70\x3f\xb6\x35\x72\xbf\x7a\x96\x15\xbf\x6a\x04\x6b\xbe\x66\xff\xac\x3d\x0d\xfc\xac\x3d\x74\x58\x0b\xbf\x74\x58\x0b\xbf\x79\x08\x0b\xbf\x98\x97\x15\xbf\xf8\xcd\x29\xbe\xcd\x33\x22\xbf\x32\x34\x22\xbf\xd7\x36\xae\xbd\xd7\x36\xae\xbd\xe0\x27\xbc\x3d\x51\x97\x15\xbf\x8d\xcf\xc9\xbd\x7c\xf4\xa4\xbe\x25\xf5\xa4\xbe\x16\xc3\x2d\x3f\x16\xc3\x2d\x3f\xd9\xdc\x2f\x3f\xa2\x95\x15\xbf\x71\xd0\xee\xbc\xd3\x1e\x03\x3f\x96\x1e\x03\x3f\x7f\xc7\x7b\xbf\x7f\xc7\x7b\xbf\xc1\x24\x7d\x3f\x8a\x92\x15\xbf\x29\x2d\x27\x3d\x9d\x58\x03\x3f\x7b\x58\x03\x3f\x9b\xc6\x5e\x3f\x9b\xc6\x5e\x3f\x4f\xc4\x5e\x3f\x07\x8e\x15\xbf\x09\xe7\xe0\x3d\x59\xa3\xa5\xbe\x5d\xa3\xa5\xbe\x8f\x6f\xc6\xbe\x8f\x6f\xc6\xbe\xad\xec\xc3\x3e\x1c\x88\x15\xbf\x20\x95\x34\x3e\x31\xd5\x21\xbf\x13\xd5\x21\xbf\x75\x14\x85\xbe\x75\x14\x85\xbe\x63\x55\x88\xbe\xc9\x80\x15\xbf\x19\xb2\x74\x3e\x3b\x13\xc3\x3d\xfb\x14\xc3\x3d\x41\xa3\x4c\x3f\x41\xa3\x4c\x3f\xad\x5c\x4d\xbf\x0c\x78\x15\xbf\x2f\xb4\x97\x3e\xa7\x60\x2a\x3f\xf3\x60\x2a\x3f\x3c\x9d\x80\xbf\x3c\x9d\x80\xbf\x61\xed\x7f\xbf\xe6\x6d\x15\xbf\xa4\xb9\xb1\x3e\xd3\xb0\x12\x3e\x3b\xb2\x12\x3e\x06\xaa\x4a\x3f\x06\xaa\x4a\x3f\xbf\xe1\x46\xbf\x56\x62\x15\xbf\xc8\xda\xc7\x3e\x74\x4d\x1d\xbf\x15\x4d\x1d\xbf\xf7\x80\x80\xbe\xf7\x80\x80\xbe\x0b\xf1\x69\xbe\x5e\x55\x15\xbf\x1f\x9f\xd9\x3e\x69\xa8\xb8\xbe\xb5\xa7\xb8\xbe\xba\xcc\xc7\xbe\xba\xcc\xc7\xbe\x4c\x80\xd4\x3e\xfc\x46\x15\xbf\x92\xa7\xe6\x3e\xce\x5c\xfa\x3e\x6a\x5d\xfa\x3e\x33\x71\x5d\x3f\x33\x71\x5d\x3f\xf2\x77\x62\x3f\x32\x37\x15\xbf\x79\xaf\xee\x3e\x77\xda\x07\x3f\xb1\xda\x07\x3f\x75\x51\x7a\xbf\x75\x51\x7a\xbf\x86\x3b\x7c\x3f\xff\x25\x15\xbf\xa6\x8e\xf1\x3e\x35\xf2\x9c\xbe\xf3\xf1\x9c\xbe\x34\x58\x2f\x3f\x34\x58\x2f\x3f\x4b\x25\x2d\x3f\x63\x13\x15\xbf\x9b\x38\xef\x3e\x69\xcb\x22\xbf\x63\xcb\x22\xbf\x22\x67\xe3\xbd\x22\x67\xe3\xbd\x9a\xcf\xb2\x3d\x5f\xff\x14\xbf\xbb\xbd\xe7\x3e\xf7\xd5\xbb\x3d\x5b\xd5\xbb\x3d\xeb\x19\x01\xbf\xeb\x19\x01\xbf\xbd\x86\x09\xbf\xf2\xe9\x14\xbf\xe4\x49\xdb\x3e\x72\x78\x2a\x3f\x46\x78\x2a\x3f\x76\x12\x68\x3f\x76\x12\x68\x3f\x1b\x78\x70\xbf\x1d\xd3\x14\xbf\x99\x25\xca\x3e\x93\xc2\x05\x3e\x93\xc1\x05\x3e\xb9\x5c\x6e\xbf\xb9\x5c\x6e\xbf\x9b\x46\x74\xbf\xdf\xba\x14\xbf\x6b\xb2\xb4\x3e\x9e\x03\x1f\xbf\xec\x03\x1f\xbf\x06\xf7\x11\x3f\x06\xf7\x11\x3f\x83\xb5\x13\xbf\x39\xa1\x14\xbf\x4c\x69\x9b\x3e\x95\x59\xac\xbe\x39\x5a\xac\xbe\x60\xcb\xd1\x3c\x60\xcb\xd1\x3c\x05\x21\x15\x3d\x2c\x86\x14\xbf\x25\xae\x7d\x3e\x21\xfa\x02\x3f\xd3\xf9\x02\x3f\xd2\x34\x1c\xbf\xd2\x34\x1c\xbf\xf2\x63\x22\x3f\xb7\x69\x14\xbf\x8a\x31\x3f\x3e\x63\xe3\x00\x3f\x1e\xe3\x00\x3f\x7c\x8a\x71\x3f\x7c\x8a\x71\x3f\xff\x0a\x79\x3f\xda\x4b\x14\xbf\x7a\x68\xf9\x3d\x88\xb4\xb3\xbe\xf2\xb4\xb3\xbe\x10\xc5\x63\xbf\x10\xc5\x63\xbf\xa2\x33\x6a\x3f\x97\x2c\x14\xbf\x4b\x89\x5e\x3d\x7d\x99\x1d\xbf\x9d\x99\x1d\xbf\x1d\x85\xf1\x3e\x1d\x85\xf1\x3e\x21\x71\xf8\x3e\xed\x0b\x14\xbf\xef\xc8\x68\xbc\x1f\xf0\x20\x3e\xf8\xef\x20\x3e\xef\x96\x0e\x3e\xef\x96\x0e\x3e\x29\x05\x10\xbe\xdc\xe9\x13\xbf\xe8\xb6\xa8\xbd\xaf\x27\x2a\x3f\xbb\x27\x2a\x3f\xaf\xbd\x31\xbf\xaf\xbd\x31\xbf\xe5\x80\x35\xbf\x64\xc6\x13\xbf\xff\x52\x18\xbe\x18\xba\x49\x3d\x3d\xbc\x49\x3d\xc1\xea\x77\x3f\xc1\xea\x77\x3f\xfe\x9b\x7d\xbf\x87\xa1\x13\xbf\xa2\x05\x59\xbe\xb2\x31\x26\xbf\x7f\x31\x26\xbf\x4e\xec\x59\xbf\x4e\xec\x59\xbf\xa9\x8a\x5f\xbf\x44\x7b\x13\xbf\x23\x8d\x8a\xbe\x65\xa1\x7e\xbe\x69\xa0\x7e\xbe\x42\x0b\xc8\x3e\x42\x0b\xc8\x3e\xb2\x73\xcf\xbe\x9c\x53\x13\xbf\xbc\xa9\xa5\xbe\xd2\x43\x13\x3f\x15\x44\x13\x3f\xfc\x04\x69\x3e\xfc\x04\x69\x3e\x5f\x15\x66\x3e\x8d\x2a\x13\xbf\xc7\x48\xbd\xbe\xfb\xb4\xd7\x3e\x80\xb5\xd7\x3e\x88\x6f\x41\xbf\x88\x6f\x41\xbf\x38\x99\x43\x3f\x1b\x00\x13\xbf\x67\xf0\xd0\xbe\xe9\x78\xe7\xbe\x73\x78\xe7\xbe\x99\x98\x7b\x3f\x99\x98\x7b\x3f\xb9\x83\x7f\x3f\x45\xd4\x12\xbf\x95\x36\xe0\xbe\x90\x6d\x0d\xbf\x61\x6d\x0d\xbf\xa0\xc5\x51\xbf\xa0\xc5\x51\xbf\xfb\xaf\x55\x3f\x0b\xa7\x12\xbf\x41\xd1\xea\xbe\x2f\xc8\x94\x3e\x6c\xc8\x94\x3e\x92\xbb\xa9\x3e\x92\xbb\xa9\x3e\x51\x1d\xae\x3e\x6c\x78\x12\xbf\x4d\x87\xf0\xbe\xf9\x83\x22\x3f\x05\x84\x22\x3f\x39\xaf\x92\x3e\x39\xaf\x92\x3e\x08\xe0\x93\xbe\x6b\x48\x12\xbf\xf0\x44\xf1\xbe\x71\x3c\xda\xbd\xad\x3c\xda\xbd\xe9\x25\x4a\xbf\xe9\x25\x4a\xbf\xfc\x8d\x4d\xbf\x08\x17\x12\xbf\x9e\x03\xed\xbe\x6b\x63\x2a\xbf\x85\x63\x2a\xbf\x26\xd0\x7a\x3f\x26\xd0\x7a\x3f\x1b\xfd\x7f\xbf\x42\xe4\x11\xbf\x30\xdf\xe3\xbe\xb9\x10\xa8\xbd\xf5\x11\xa8\xbd\x02\x85\x48\xbf\x02\x85\x48\xbf\xbd\xaa\x4d\xbf\x1b\xb0\x11\xbf\x7e\x0a\xd6\xbe\x4c\x11\x25\x3f\x1a\x11\x25\x3f\xc6\x14\x8f\x3e\xc6\x14\x8f\x3e\xd5\x5b\x95\xbe\x92\x7a\x11\xbf\x20\xd2\xc3\xbe\xb9\xa8\x84\x3e\x4c\xa8\x84\x3e\x80\x18\xaa\x3e\x80\x18\xaa\x3e\xed\xcf\xaa\x3e\xa7\x43\x11\xbf\x12\x98\xad\xbe\x91\x3c\x13\xbf\xc7\x3c\x13\xbf\x66\xab\x4f\xbf\x66\xab\x4f\xbf\x1d\xf4\x53\x3f\x5d\x0b\x11\xbf\xdc\xd5\x93\xbe\x22\x1a\xd3\xbe\x82\x1a\xd3\xbe\x02\x6f\x78\x3f\x02\x6f\x78\x3f\xbd\xc2\x7f\x3f\xb3\xd1\x10\xbf\xc7\x28\x6e\xbe\x5e\x2c\xed\x3e\x0e\x2c\xed\x3e\x07\xb2\x3f\xbf\x07\xb2\x3f\xbf\x9e\x14\x48\x3f\xaa\x96\x10\xbf\x6a\xd3\x2f\xbe\xaa\xdd\x08\x3f\x8e\xdd\x08\x3f\x14\x67\x6f\x3e\x14\x67\x6f\x3e\x94\xb1\x85\x3e\x42\x5a\x10\xbf\x61\xf5\xdb\xbd\xb9\x11\xa4\xbe\xd2\x11\xa4\xbe\xe8\x62\xbf\x3e\xe8\x62\xbf\x3e\xbf\x3e\xb8\xbe\x7c\x1c\x10\xbf\x41\xc6\x27\xbd\x22\x96\x1e\xbf\x21\x96\x1e\xbf\xe0\xa2\x56\xbf\xe0\xa2\x56\xbf\x15\x5e\x57\xbf\x5a\xdd\x0f\xbf\x79\xd4\xd6\x3c\x14\x82\x24\x3e\x55\x82\x24\x3e\xa4\x17\x7b\x3f\xa4\x17\x7b\x3f\xf1\x87\x7f\xbf\xda\x9c\x0f\xbf\xf3\x1f\xbe\x3d\xb6\x7a\x29\x3f\xd3\x7a\x29\x3f\x18\x1d\x3f\xbf\x18\x1d\x3f\xbf\xae\x73\x45\xbf\xfe\x5a\x0f\xbf\x7c\x44\x21\x3e\xc6\x17\xb1\x3b\x96\x2a\xb1\x3b\xa3\x3e\x67\x3e\xa3\x3e\x67\x3e\x0c\xe6\x7e\xbe\xc6\x17\x0f\xbf\xbc\x2a\x60\x3e\x47\x66\x29\xbf\x1d\x66\x29\xbf\xb4\x7c\xc3\x3e\xb4\x7c\xc3\x3e\x29\x7a\xbc\x3e\x34\xd3\x0e\xbf\xcf\x3d\x8d\x3e\x65\x8e\x2b\xbe\xb9\x8d\x2b\xbe\xec\x38\x58\xbf\xec\x38\x58\xbf\xe0\x11\x58\x3f\x47\x8d\x0e\xbf\x1a\x88\xa7\x3e\x92\x17\x1f\x3f\xba\x17\x1f\x3f\xf1\xb8\x7c\x3f\xf1\xb8\x7c\x3f\x88\x82\x7f\x3f\x00\x46\x0e\xbf\x6c\x70\xbe\x3e\x27\xda\xa1\x3e\x69\xda\xa1\x3e\x58\xbc\x41\xbf\x58\xbc\x41\xbf\x69\xde\x45\x3f\x61\xfd\x0d\xbf\x06\x82\xd1\x3e\xe9\xb2\x0b\xbf\xd2\xb2\x0b\xbf\x51\x03\x78\x3e\x51\x03\x78\x3e\xf8\xa7\x82\x3e\x6a\xb3\x0d\xbf\xc1\x5f\xe0\x3e\x05\x94\xe3\xbe\xeb\x93\xe3\xbe\x6c\xd8\xb8\x3e\x6c\xd8\xb8\x3e\x9f\x81\xb7\xbe\x1b\x68\x0d\xbf\x2a\xbf\xea\x3e\x23\x3c\xe2\x3e\x27\x3c\xe2\x3e\x34\x52\x53\xbf\x34\x52\x53\xbf\x4d\x10\x56\xbf\x75\x1b\x0d\xbf\x7c\x6f\xf0\x3e\x8a\xdd\x0b\x3f\x82\xdd\x0b\x3f\x39\x44\x7a\x3f\x39\x44\x7a\x3f\xd4\xb7\x7f\xbf\x7a\xcd\x0c\xbf\x8e\x57\xf1\x3e\x7e\xdb\xa2\xbe\xa2\xdb\xa2\xbe\xc7\x1b\x43\xbf\xc7\x1b\x43\xbf\xb6\x5c\x49\xbf\x28\x7e\x0c\xbf\xdd\x73\xed\x3e\x8a\x06\x1e\xbf\xa3\x06\x1e\xbf\x40\xd7\x85\x3e\x40\xd7\x85\x3e\x1e\x57\x8f\xbe\x84\x2d\x0c\xbf\xd2\xdf\xe4\x3e\x3a\x06\x39\x3e\xc6\x05\x39\x3e\xf2\x64\xac\x3e\xf2\x64\xac\x3e\x11\x54\xa9\x3e\x8a\xdb\x0b\xbf\x4c\xc6\xd7\x3e\x85\x3f\x28\x3f\x67\x3f\x28\x3f\xf7\x30\x4f\xbf\xf7\x30\x4f\xbf\x75\x4b\x51\x3f\x40\x88\x0b\xbf\x12\x71\xc6\x3e\xbb\x4d\x1d\xbd\x97\x4f\x1d\xbd\x27\x34\x7b\x3f\x27\x34\x7b\x3f\xb9\xfe\x7f\x3f\xa2\x33\x0b\xbf\x7d\x36\xb1\x3e\x6f\x8f\x2a\xbf\x89\x8f\x2a\xbf\x73\x05\x4a\xbf\x73\x05\x4a\xbf\xc3\xb5\x4f\x3f\xb4\xdd\x0a\xbf\x96\x85\x98\x3e\x5b\x12\xcf\xbd\xfd\x12\xcf\xbd\xa3\xc0\x9b\x3e\xa3\xc0\x9b\x3e\x7f\x44\xa5\x3e\x74\x86\x0a\xbf\x8f\xba\x79\x3e\xa2\x10\x25\x3f\x93\x10\x25\x3f\xa1\xda\x96\x3e\xa1\xda\x96\x3e\xf1\x98\x91\xbe\xe6\x2d\x0a\xbf\xb5\x91\x3d\x3e\x25\xff\x6e\x3e\x0f\xff\x6e\x3e\x8a\x73\x49\xbf\x8a\x73\x49\xbf\x6a\x40\x49\xbf\x09\xd4\x09\xbf\x41\x8d\xfb\x3d\x20\xe4\x18\xbf\x1c\xe4\x18\xbf\x66\xe3\x7d\x3f\x66\xe3\x7d\x3f\xcc\xa4\x7f\xbf\xe0\x78\x09\xbf\xc0\x4d\x6e\x3d\x7b\xab\xb4\xbe\x68\xab\xb4\xbe\x28\x87\x55\xbf\x28\x87\x55\xbf\xbf\x4f\x58\xbf\x68\x1c\x09\xbf\x9a\xab\xf6\xbb\x5f\x1e\x07\x3f\x6d\x1e\x07\x3f\x3a\x77\xbe\x3e\x3a\x77\xbe\x3e\x47\xed\xc3\xbe\xa6\xbe\x08\xbf\xfa\x8f\x95\xbd\x5b\x29\xe9\x3e\x80\x29\xe9\x3e\xc4\x81\x66\x3e\xc4\x81\x66\x3e\x35\xe6\x5f\x3e\x97\x5f\x08\xbf\xaf\x58\x0c\xbe\xf9\x4d\xe1\xbe\xd1\x4d\xe1\xbe\xb9\x30\x3d\xbf\xb9\x30\x3d\xbf\xf1\x63\x3d\x3f\x40\xff\x07\xbf\x97\x1f\x4b\xbe\x69\x24\x0a\xbf\x53\x24\x0a\xbf\x50\xa2\x7b\x3f\x50\xa2\x7b\x3f\xd8\xf1\x7d\x3f\xa1\x9d\x07\xbf\xfe\xf7\x82\xbe\x56\x59\xae\x3e\x7d\x59\xae\x3e\xe8\x9a\x5e\xbf\xe8\x9a\x5e\xbf\x56\x81\x62\x3f\xb9\x3a\x07\xbf\xc7\xcf\x9d\xbe\xec\x45\x1a\x3f\xfc\x45\x1a\x3f\x26\x4e\xe2\x3e\x26\x4e\xe2\x3e\x98\x97\xea\x3e\x88\xd6\x06\xbf\x9b\x99\xb5\xbe\x9b\x63\x6f\xbe\x67\x63\x6f\xbe\x41\x81\x12\x3e\x41\x81\x12\x3e\x14\x39\x08\xbe\x14\x71\x06\xbf\x84\xdf\xc9\xbe\x32\x64\x24\xbf\x2b\x64\x24\xbf\xe2\x72\x2c\xbf\xe2\x72\x2c\xbf\x54\x01\x2d\xbf\x5e\x0a\x06\xbf\x8d\x41\xda\xbe\x54\x93\xf8\x3d\x6a\x93\xf8\x3d\x09\x9a\x75\x3f\x09\x9a\x75\x3f\x1c\xc7\x79\xbf\x62\xa2\x05\xbf\x19\x73\xe6\xbe\x99\x41\x29\x3f\x97\x41\x29\x3f\x89\x53\x66\xbf\x89\x53\x66\xbf\x52\x23\x6d\xbf\x20\x39\x05\xbf\x78\x38\xee\xbe\x4a\xac\xea\xbb\x8a\xaf\xea\xbb\x2e\xa9\x04\x3f\x2e\xa9\x04\x3f\x86\xeb\x0b\xbf\x9e\xce\x04\xbf\xca\x74\xf1\xbe\x05\xc9\x29\xbf\x10\xc9\x29\xbf\xf0\xcf\x42\x3d\xf0\xcf\x42\x3d\xe8\x17\xdf\x3c\xdb\x62\x04\xbf\x5b\x15\xf0\xbe\xda\x3d\xd2\xbd\x3a\x3e\xd2\xbd\x11\x9d\x18\xbf\x11\x9d\x18\xbf\x12\x37\x17\x3f\xd9\xf5\x03\xbf\xed\x28\xea\xbe\xf5\x19\x26\x3f\xe9\x19\x26\x3f\x9a\x0a\x6f\x3f\x9a\x0a\x6f\x3f\x82\xbf\x71\x3f\x99\x87\x03\xbf\x00\xcc\xdf\xbe\xfc\x64\x51\x3e\xcb\x64\x51\x3e\xad\x22\x71\xbf\xad\x22\x71\xbf\xff\xc9\x76\x3f\x1c\x18\x03\xbf\x1c\x35\xd1\xbe\xde\x4b\x1e\xbf\xed\x4b\x1e\xbf\x8b\x46\x1e\x3f\x8b\x46\x1e\x3f\xf6\xdd\x24\x3f\x64\xa7\x02\xbf\x63\xb0\xbe\xbe\xa6\x35\x98\xbe\xbe\x35\x98\xbe\x1d\x8d\x9c\xbd\x1d\x8d\x9c\xbd\xc1\xa6\xc8\x3d\x70\x35\x02\xbf\xbc\x94\xa8\xbe\xfd\xf9\x12\x3f\xf3\xf9\x12\x3f\xc6\xdf\xfc\xbe\xc6\xdf\xfc\xbe\xef\xb4\xf6\xbe\x44\xc2\x01\xbf\xd6\x54\x8f\xbe\x2a\x86\xc2\x3e\x1d\x86\xc2\x3e\x83\xb9\x64\x3f\x83\xb9\x64\x3f\xa2\x7c\x64\xbf\xde\x4d\x01\xbf\x1a\xcf\x66\xbe\xcc\xaa\x04\xbf\xd0\xaa\x04\xbf\xdc\x96\x7b\xbf\xdc\x96\x7b\xbf\x57\xc9\x7d\xbf\x41\xd8\x00\xbf\xee\xb1\x2a\xbe\x33\xdc\xe7\xbe\x35\xdc\xe7\xbe\xc5\x0c\x3b\x3f\xc5\x0c\x3b\x3f\xa8\xba\x3e\xbf\x6e\x61\x00\xbf\xaf\xe5\xd6\xbd\xaa\x8a\xe8\x3e\xab\x8a\xe8\x3e\x28\x41\x66\xbe\x28\x41\x66\xbe\x10\x1c\x76\xbe\xca\xd2\xff\xbe\x90\xe9\x28\xbd\xb0\x15\x04\x3f\xb4\x15\x04\x3f\xa8\xc6\xb7\xbe\xa8\xc6\xb7\xbe\x83\xa8\xb1\x3e\x54\xe0\xfe\xbe\x74\x79\xbd\x3c\x13\xd6\xc5\xbe\x06\xd6\xc5\xbe\x91\x8b\x51\x3f\x91\x8b\x51\x3f\x38\x52\x50\x3f\x78\xeb\xfd\xbe\x10\x49\xb2\x3d\xfa\xf9\x10\xbf\xf3\xf9\x10\xbf\x6f\xe0\x7e\xbf\x6f\xe0\x7e\xbf\xe7\xe3\x7f\x3f\x3c\xf4\xfc\xbe\x4e\xd4\x18\x3e\x2d\x5f\xa1\x3e\x43\x5f\xa1\x3e\xc5\x8a\x54\x3f\xc5\x8a\x54\x3f\x7e\x74\x57\x3f\xa0\xfa\xfb\xbe\xdf\xac\x55\x3e\xbc\xbb\x1a\x3f\xc6\xbb\x1a\x3f\x73\xf7\xc2\xbe\x73\xf7\xc2\xbe\x5c\x67\xca\x3e\xa8\xfe\xfa\xbe\x67\x3d\x87\x3e\x6d\x8c\x76\xbe\x42\x8c\x76\xbe\x98\xf7\x49\xbe\x98\xf7\x49\xbe\xfc\x1f\x3e\xbe\x54\x00\xfa\xbe\x8b\x1f\xa1\x3e\x44\x50\x22\xbf\x3a\x50\x22\xbf\x2d\x9f\x34\x3f\x2d\x9f\x34\x3f\x25\xe3\x33\xbf\xab\xff\xf8\xbe\x59\x03\xb8\x3e\x05\x96\x2b\x3e\x25\x96\x2b\x3e\xca\xad\x78\xbf\xca\xad\x78\xbf\xbc\xe3\x7a\xbf\xab\xfc\xf7\xbe\x97\x7a\xcb\x3e\x13\x95\x27\x3f\x19\x95\x27\x3f\xd8\xf5\x67\x3f\xd8\xf5\x67\x3f\xdb\xa7\x6c\xbf\x19\xf3\xf6\xbe\xdf\x3a\xdb\x3e\x3d\x40\xc8\xbd\x19\x40\xc8\xbd\x93\xba\x08\xbf\x93\xba\x08\xbf\xe4\x4e\x0e\xbf\xf4\xe2\xf5\xbe\x0a\xe4\xe6\x3e\x42\x1c\x2a\xbf\x40\x1c\x2a\xbf\x37\x3e\x89\xbc\x37\x3e\x89\xbc\x5b\x69\xfc\xb6\xf8\xd4\xf4\xbe\x29\x5f\xee\x3e\x34\x7c\xf1\x3c\x14\x7c\xf1\x3c\x67\x48\x0f\x3f\x67\x48\x0f\x3f\x9e\x24\x0e\x3f\x22\xc9\xf3\xbe\x17\x76\xf1\x3e\x17\x8c\x2a\x3f\x13\x8c\x2a\x3f\xf3\x97\x69\xbf\xf3\x97\x69\xbf\x34\x5b\x6c\x3f\x5b\xbe\xf2\xbe\xcd\x2d\xf0\x3e\xc3\xdc\x16\x3d\x53\xdc\x16\x3d\xea\x47\x75\x3f\xea\x47\x75\x3f\xc9\x3c\x7b\x3f\xa0\xb4\xf1\xbe\x95\x7b\xea\x3e\x1e\xb4\x29\xbf\x27\xb4\x29\xbf\x72\xd9\x2e\xbf\x72\xd9\x2e\xbf\x81\x1c\x36\x3f\xb2\xa4\xf0\xbe\xa3\x96\xe0\x3e\xed\x58\xc9\xbd\x47\x59\xc9\xbd\xd8\x40\x38\x3e\xd8\x40\x38\x3e\xa5\x62\x51\x3e\x90\x8e\xef\xbe\x42\x96\xd2\x3e\x9c\x8c\x27\x3f\x90\x8c\x27\x3f\x35\x6c\xc4\x3e\x35\x6c\xc4\x3e\x1d\x58\xbd\xbe\x33\x76\xee\xbe\x27\xd3\xc0\x3e\xd2\x3a\x1e\x3e\xa2\x3a\x1e\x3e\x76\x47\x52\xbf\x76\x47\x52\xbf\x5f\x1c\x52\xbf\x9a\x5b\xed\xbe\x1e\x91\xab\x3e\x89\x10\x24\xbf\x93\x10\x24\xbf\x16\x45\x7d\x3f\x16\x45\x7d\x3f\x10\xe4\x7f\xbf\xcc\x3e\xec\xbe\xfe\x42\x93\x3e\xab\x17\x54\xbe\xd1\x17\x54\xbe\x86\x17\x55\xbf\x86\x17\x55\xbf\xfb\x27\x59\xbf\xc8\x1f\xeb\xbe\x51\xa4\x70\x3e\x47\x11\x20\x3f\x40\x11\x20\x3f\xfc\xc1\xcd\x3e\xfc\xc1\xcd\x3e\x38\xee\xd5\xbe\x94\xfe\xe9\xbe\x3e\x7f\x36\x3e\xed\x1b\x82\x3e\xe8\x1b\x82\x3e\x96\xb5\x25\x3e\x96\xb5\x25\x3e\x0d\xf1\x18\x3e\x30\xdb\xe8\xbe\x4b\x4a\xf2\x3d\x09\xa0\x1b\xbf\x08\xa0\x1b\xbf\xd5\xdf\x2c\xbf\xd5\xdf\x2c\xbf\x2e\xc0\x2a\x3f\xa0\xb5\xe7\xbe\x3b\xaf\x66\x3d\xf5\xd9\x96\xbe\xed\xd9\x96\xbe\x66\xcd\x78\x3f\x66\xcd\x78\x3f\xf2\x52\x77\x3f\xe6\x8d\xe6\xbe\x2f\x28\xd8\xbb\xfe\x43\x16\x3f\x07\x44\x16\x3f\x8a\xad\x74\xbf\x8a\xad\x74\xbf\x99\x34\x73\x3f\x05\x64\xe5\xbe\x76\x05\x8e\xbd\x37\x2a\xaa\x3e\x50\x2a\xaa\x3e\x74\xf8\x21\x3f\x74\xf8\x21\x3f\xcf\x09\x20\x3f\xff\x37\xe4\xbe\xd5\xf1\x05\xbe\x50\xd7\x10\xbf\x42\xd7\x10\xbf\xcf\x48\xdc\xbd\xcf\x48\xdc\xbd\x9d\xba\xc8\x3d\xd9\x09\xe3\xbe\x94\x6e\x42\xbe\xe4\x0a\xbc\xbe\xc8\x0a\xbc\xbe\x1e\x78\xe6\xbe\x1e\x78\xe6\xbe\x9f\x99\xeb\xbe\x93\xd9\xe1\xbe\x59\x6f\x7b\xbe\x90\x26\x0c\x3f\x9e\x26\x0c\x3f\xb6\x89\x5c\x3f\xb6\x89\x5c\x3f\x40\x85\x5e\xbf\x32\xa7\xe0\xbe\x1b\xf5\x97\xbe\x95\x88\xca\x3e\xae\x88\xca\x3e\xea\xeb\x7e\xbf\xea\xeb\x7e\xbf\xf8\x88\x7f\xbf\xb7\x72\xdf\xbe\x49\x81\xaf\xbe\xea\x9b\x07\xbf\xe2\x9b\x07\xbf\x75\xe7\x4f\x3f\x75\xe7\x4f\x3f\x54\x86\x4e\xbf\x27\x3c\xde\xbe\xa2\xed\xc3\xbe\xa1\xda\xd5\xbe\x97\xda\xd5\xbe\x08\x33\xbe\xbe\x08\x33\xbe\xbe\x30\xf6\xb6\xbe\x83\x03\xdd\xbe\x43\xe5\xd4\xbe\x65\xc0\x02\x3f\x66\xc0\x02\x3f\x69\x29\x3c\xbe\x69\x29\x3c\xbe\xe0\x87\x52\x3e\xd2\xc8\xdb\xbe\x43\x1c\xe2\xbe\xda\xc4\xdf\x3e\xd4\xc4\xdf\x3e\x39\x0e\x2d\x3f\x39\x0e\x2d\x3f\x40\xd4\x33\x3f\x15\x8c\xda\xbe\xff\x59\xeb\xbe\x24\x04\xfc\xbe\x36\x04\xfc\xbe\x18\x05\x73\xbf\x18\x05\x73\xbf\xab\xc7\x79\x3f\x4e\x4d\xd9\xbe\x9a\x79\xf0\xbe\xec\x22\xe9\xbe\x02\x23\xe9\xbe\xec\x21\x6b\x3f\xec\x21\x6b\x3f\xa4\x8a\x70\x3f\x7f\x0c\xd8\xbe\x24\x64\xf1\xbe\x79\x48\xf4\x3e\x5e\x48\xf4\x3e\x9a\x6a\x18\xbf\x9a\x6a\x18\xbf\x7c\x54\x1b\x3f\xab\xc9\xd6\xbe\x6e\x1b\xee\xbe\x04\x44\xf1\x3e\xe6\x43\xf1\x3e\x4d\x09\xac\x3d\x4d\x09\xac\x3d\x87\x45\xaa\x3d\xd2\x84\xd5\xbe\x0e\xb0\xe6\xbe\x80\xd4\xee\xbe\x9e\xd4\xee\xbe\x1d\xfb\xe7\x3e\x1d\xfb\xe7\x3e\xdd\x90\xee\xbe\x01\x3e\xd4\xbe\xd3\x45\xdb\xbe\x23\x02\xf7\xbe\x3b\x02\xf7\xbe\xd8\xb2\x58\xbf\xd8\xb2\x58\xbf\x46\x4a\x5e\xbf\x38\xf5\xd2\xbe\x18\x13\xcc\xbe\xaf\x0e\xeb\x3e\x9a\x0e\xeb\x3e\x13\x1b\x79\x3f\x13\x1b\x79\x3f\xcc\xaf\x7f\xbf\x77\xaa\xd1\xbe\xb9\x5b\xb9\xbe\xee\xea\xf9\x3e\xe2\xea\xf9\x3e\x43\x49\x4b\xbf\x43\x49\x4b\xbf\xc6\x55\x51\xbf\xbf\x5d\xd0\xbe\xfe\x76\xa3\xbe\xf3\x6e\xe7\xbe\xfb\x6e\xe7\xbe\xf2\x93\xbb\x3e\xf2\x93\xbb\x3e\xce\xe8\xc3\xbe\x19\x0f\xcf\xbe\xbd\xc6\x8a\xbe\x64\xab\xfb\xbe\x62\xab\xfb\xbe\xe6\x80\x34\x3e\xe6\x80\x34\x3e\xd5\xaa\x2e\x3e\x85\xbe\xcd\xbe\x6f\x72\x5f\xbe\x95\x48\xe4\x3e\xa1\x48\xe4\x3e\xa7\x4d\x2a\xbf\xa7\x4d\x2a\xbf\xf9\x9d\x2b\x3f\x08\x6c\xcc\xbe\xdb\x92\x25\xbe\x91\xab\xfd\x3e\xa4\xab\xfd\x3e\x59\x20\x73\x3f\x59\x20\x73\x3f\xed\x7a\x76\x3f\xa1\x17\xcb\xbe\xd4\xce\xd1\xbd\x97\xdf\xe3\xbe\x7d\xdf\xe3\xbe\x4e\x62\x71\xbf\x4e\x62\x71\xbf\x63\x6c\x75\x3f\x59\xc1\xc9\xbe\x8d\x0b\x2a\xbd\xcb\x31\xfe\xbe\xb1\x31\xfe\xbe\xa5\xec\x25\x3f\xa5\xec\x25\x3f\xca\x0e\x29\x3f\x30\x69\xc8\xbe\x3b\x7c\xa4\x3c\x0e\xd9\xe5\x3e\x2c\xd9\xe5\x3e\xc4\x96\x20\xbe\xc4\x96\x20\xbe\xa5\x2c\x24\x3e\x2b\x0f\xc7\xbe\x59\x71\xa6\x3d\xcd\x21\xfc\x3e\xe5\x21\xfc\x3e\xb0\xca\xc2\xbe\xb0\xca\xc2\xbe\x4e\xaf\xc6\xbe\x4c\xb3\xc5\xbe\xfc\x66\x10\x3e\x41\xaa\xe8\xbe\x2a\xaa\xe8\xbe\xe5\xe6\x4c\x3f\xe5\xe6\x4c\x3f\xeb\x4f\x51\xbf\x98\x55\xc4\xbe\x0f\x16\x4b\x3e\x22\xa1\xf8\xbe\x12\xa1\xf8\xbe\x8f\x05\x7a\xbf\x8f\x05\x7a\xbf\xe8\x98\x7f\xbf\x0e\xf6\xc2\xbe\x25\x23\x81\x3e\xc6\x70\xec\x3e\xca\x70\xec\x3e\xb8\x84\x5b\x3f\xb8\x84\x5b\x3f\x83\x70\x60\xbf\xb8\x94\xc1\xbe\x1e\x86\x9a\x3e\xd8\x24\xf4\x3e\xd8\x24\xf4\x3e\xce\x10\xf6\xbe\xce\x10\xf6\xbe\x0d\x1e\xfb\xbe\x96\x31\xc0\xbe\xda\x48\xb1\x3e\x0c\xfa\xf1\xbe\x15\xfa\xf1\xbe\x86\xc6\x20\xbd\x86\xc6\x20\xbd\xab\xfd\x2f\x3d\xac\xcc\xbe\xbe\xbe\x06\xc5\x3e\xbf\xde\xed\xbe\xcf\xde\xed\xbe\x48\x93\x0b\x3f\x48\x93\x0b\x3f\x74\x14\x10\x3f\xfa\x65\xbd\xbe\x13\x76\xd5\x3e\x78\xbb\xf8\x3e\x60\xbb\xf8\x3e\x43\xb4\x62\xbf\x43\xb4\x62\xbf\xfd\xd7\x69\x3f\x8a\xfd\xbb\xbe\x8a\x47\xe2\x3e\x54\x9f\xe5\x3e\x36\x9f\xe5\x3e\x8c\x77\x75\x3f\x8c\x77\x75\x3f\xd2\xa6\x7d\x3f\x5c\x93\xba\xbe\x51\x52\xeb\x3e\x10\x02\x00\xbf\x1c\x02\x00\xbf\x57\x6c\x3e\xbf\x57\x6c\x3e\xbf\x9e\xdf\x45\x3f\x74\x27\xb9\xbe\x28\x66\xf0\x3e\x1c\x3c\xdc\xbe\x33\x3c\xdc\xbe\x3d\x54\x9c\x3e\x3d\x54\x9c\x3e\x0d\xbd\xa6\x3e\xd4\xb9\xb7\xbe\xc6\x79\xf1\x3e\x45\x35\x04\x3f\x3c\x35\x04\x3f\x3b\xf0\x66\x3e\x3b\xf0\x66\x3e\x1c\xd3\x5e\xbe\x83\x4a\xb6\xbe\xc6\x87\xee\x3e\x98\x92\xd1\x3e\x8c\x92\xd1\x3e\x2d\xcc\x30\xbf\x2d\xcc\x30\xbf\xbb\x27\x32\xbf\x82\xd9\xb4\xbe\x7b\x9f\xe7\x3e\x0c\x4b\x09\xbf\x0f\x4b\x09\xbf\xfc\xb4\x73\x3f\xfc\xb4\x73\x3f\xe7\xf2\x77\xbf\xd6\x66\xb3\xbe\x48\xe3\xdc\x3e\x3b\x15\xc4\xbe\x3b\x15\xc4\xbe\x92\xbf\x6e\xbf\x92\xbf\x6e\xbf\x4c\xc7\x74\xbf\x7f\xf2\xb1\xbe\x78\x7f\xce\x3e\xb0\xb0\x0e\x3f\xb3\xb0\x0e\x3f\xe1\x83\x23\x3f\xe1\x83\x23\x3f\x82\xdd\x29\xbf\x87\x7c\xb0\xbe\x47\xb6\xbc\x3e\x9a\x5f\xb3\x3e\xa8\x5f\xb3\x3e\xc6\xf3\x20\xbe\xc6\xf3\x20\xbe\x9e\x99\x35\xbe\xed\x04\xaf\xbe\xf3\xd7\xa7\x3e\xf9\x91\x13\xbf\xf0\x91\x13\xbf\xeb\xec\xbd\xbe\xeb\xec\xbd\xbe\x6d\x43\xb8\x3e\xb7\x8b\xad\xbe\x68\x33\x90\x3e\xa6\x06\xa1\xbe\x91\x06\xa1\xbe\x09\xcc\x4a\x3f\x09\xcc\x4a\x3f\xa2\xb2\x4a\x3f\xe5\x10\xac\xbe\x89\x86\x6c\x3e\x13\x3d\x18\x3f\x1f\x3d\x18\x3f\xf0\x3f\x7c\xbf\xf0\x3f\x7c\xbf\xef\x5b\x7e\x3f\x80\x94\xaa\xbe\x4f\xab\x34\x3e\xc4\x98\x8d\x3e\xd5\x98\x8d\x3e\xc4\x6c\x65\x3f\xc4\x6c\x65\x3f\xb0\x6b\x68\x3f\x89\x16\xa9\xbe\xae\x3e\xf4\x3d\x33\x6d\x1d\xbf\x2a\x6d\x1d\xbf\x2c\x4b\x0d\xbf\x2c\x4b\x0d\xbf\x81\x80\x0f\x3f\x05\x97\xa7\xbe\x46\x8e\x75\x3d\x11\xcf\x6d\xbe\xfb\xce\x6d\xbe\x39\x98\x56\x3d\x39\x98\x56\x3d\x5d\xed\x56\x3d\xf6\x15\xa6\xbe\xb7\x48\xd3\xb7\x93\x4a\x22\x3f\x96\x4a\x22\x3f\xf8\x34\xeb\x3e\xf8\x34\xeb\x3e\x3f\xa8\xf0\xbe\x62\x93\xa4\xbe\xe7\xb6\x76\xbd\x8c\x6f\x39\x3e\x8e\x6f\x39\x3e\xae\x99\x56\xbf\xae\x99\x56\xbf\xf6\x84\x5b\xbf\x49\x0f\xa3\xbe\xff\xd9\xf3\xbd\x15\x14\x26\xbf\x16\x14\x26\xbf\x36\x63\x7a\x3f\x36\x63\x7a\x3f\xf0\xfc\x7f\xbf\xb4\x89\xa1\xbe\x85\x7d\x34\xbe\x4d\x3f\x00\xbe\x62\x3f\x00\xbe\x1c\x48\x57\xbf\x1c\x48\x57\xbf\xb1\x9d\x5b\xbf\xa4\x02\xa0\xbe\x76\xce\x6b\xbe\x78\xd8\x28\x3f\x71\xd8\x28\x3f\x81\x46\xef\x3e\x81\x46\xef\x3e\x21\x07\xf2\xbe\x1e\x7a\x9e\xbe\x3f\xb7\x8f\xbe\x35\x65\x84\x3d\xf9\x64\x84\x3d\x1c\x00\x14\x3d\x1c\x00\x14\x3d\xa4\xcc\x3a\x3d\x22\xf0\x9c\xbe\x09\x23\xa7\xbe\xa6\x77\x2a\xbf\xae\x77\x2a\xbf\x66\xf1\x06\xbf\x66\xf1\x06\xbf\x5c\xe4\x0c\x3f\xbb\x64\x9b\xbe\xbe\xdf\xbb\xbe\x2a\xdf\xb7\x3a\x2a\xcf\xb7\x3a\x9c\x1d\x5e\x3f\x9c\x1d\x5e\x3f\x2b\x51\x66\x3f\xe7\xd7\x99\xbe\xd0\x92\xcd\xbe\x88\x29\x2a\x3f\x82\x29\x2a\x3f\x2e\x67\x76\xbf\x2e\x67\x76\xbf\xb1\x0a\x7f\x3f\xad\x49\x98\xbe\x1e\xec\xdb\xbe\x21\x73\x8f\xbd\x4d\x73\x8f\xbd\x1d\x20\x49\x3f\x1d\x20\x49\x3f\xe6\x6a\x50\x3f\x0e\xba\x96\xbe\x67\xcf\xe6\xbe\xa1\xff\x27\xbf\xa4\xff\x27\xbf\xe8\x1e\xc6\xbe\xe8\x1e\xc6\xbe\x54\x77\xcf\x3e\x12\x29\x95\xbe\x02\xeb\xed\xbe\x15\x84\x0f\x3e\x11\x84\x0f\x3e\xa4\x90\xf9\xbd\xa4\x90\xf9\xbd\x2c\x5c\xed\xbd\xb8\x96\x93\xbe\xba\x51\xf1\xbe\xc4\x66\x24\x3f\xc5\x66\x24\x3f\x16\x3e\x19\x3f\x16\x3e\x19\x3f\xfe\xae\x1a\xbf\x0a\x03\x92\xbe\xff\xc9\xf0\xbe\x6e\xdf\x5b\xbe\x62\xdf\x5b\xbe\xad\x05\x69\xbf\xad\x05\x69\xbf\x7a\xc4\x6c\xbf\x07\x6e\x90\xbe\xda\x82\xec\xbe\xbe\x47\x1e\xbf\xba\x47\x1e\xbf\x17\x46\x78\x3f\x17\x46\x78\x3f\x22\x74\x7d\xbf\xb6\xd7\x8e\xbe\x2b\x71\xe4\xbe\x7b\x90\x95\x3e\x85\x90\x95\x3e\x10\xa9\x42\xbf\x10\xa9\x42\xbf\xcc\x6a\x48\xbf\x19\x40\x8d\xbe\x44\xc9\xd8\xbe\x81\xc5\x14\x3f\x86\xc5\x14\x3f\xf4\xc6\xad\x3e\xf4\xc6\xad\x3e\xd1\xfb\xb8\xbe\x37\xa7\x8b\xbe\xab\xb9\xc9\xbe\x16\x21\xbc\xbe\x0c\x21\xbc\xbe\xaf\xc8\x35\x3e\xaf\xc8\x35\x3e\x2e\x50\x22\x3e\x10\x0d\x8a\xbe\x24\x79\xb7\xbe\xbb\x24\x08\xbf\xb6\x24\x08\xbf\x80\x16\x26\xbf\x80\x16\x26\xbf\x9a\x66\x22\x3f\xae\x71\x88\xbe\x15\x65\xa2\xbe\x92\xc6\xe0\x3e\x99\xc6\xe0\x3e\x63\x16\x72\x3f\x63\x16\x72\x3f\xdf\xe6\x6f\x3f\x0f\xd5\x86\xbe\x89\xbf\x8a\xbe\xaf\xe9\xf0\x3e\xb4\xe9\xf0\x3e\x83\xc1\x7c\xbf\x83\xc1\x7c\xbf\xe2\x42\x7c\x3f\x3c\x37\x85\xbe\x9c\xf1\x61\xbe\x37\x45\x01\xbf\x35\x45\x01\xbf\x3c\x2f\x43\x3f\x3c\x2f\x43\x3f\x35\x6a\x44\x3f\x34\x98\x83\xbe\x76\xe6\x2a\xbe\xae\x42\xcb\xbe\xae\x42\xcb\xbe\x96\xcc\xa9\xbe\x96\xcc\xa9\xbe\x88\x66\xaf\x3e\x00\xf8\x81\xbe\x6a\x67\xe2\xbd\xcd\xe6\x0f\x3f\xcd\xe6\x0f\x3f\x59\xc7\x41\xbe\x59\xc7\x41\xbe\x93\xc8\x31\xbe\xa0\x56\x80\xbe\x02\x8b\x57\xbd\x72\x63\xa0\x3e\x6d\x63\xa0\x3e\xd7\x1e\x29\x3f\xd7\x1e\x29\x3f\xfa\x82\x24\xbf\x38\x68\x7d\xbe\xb9\xa0\xca\x3b\xc5\x13\x1c\xbf\xc8\x13\x1c\xbf\xd1\xec\x74\xbf\xd1\xec\x74\xbf\x77\x75\x70\xbf\xea\x20\x7a\xbe\xa1\x8d\x84\x3d\xed\xd9\x5f\xbe\xfb\xd9\x5f\xbe\xe8\xc2\x7f\x3f\xe8\xc2\x7f\x3f\x4e\x3a\x7c\xbf\x65\xd7\x76\xbe\x4f\x7c\xfa\x3d\xe7\xef\x24\x3f\xe4\xef\x24\x3f\x21\xe8\x46\xbf\x21\xe8\x46\xbf\x53\xf4\x44\xbf\xa8\x8b\x73\xbe\x54\x26\x36\x3e\x6c\xf1\xea\x3d\x56\xf1\xea\x3d\xea\x39\xb3\x3e\xea\x39\xb3\x3e\xfc\x21\xb3\xbe\xc7\x3d\x70\xbe\x2e\x34\x6c\x3e\x1f\xdd\x29\xbf\x22\xdd\x29\xbf\x0c\x55\x2c\x3e\x0c\x55\x2c\x3e\x23\x5b\x25\x3e\xc1\xed\x6c\xbe\x1e\x4e\x8f\x3e\x7b\xc2\x6c\xbb\xbb\xc4\x6c\xbb\x11\x2c\x24\xbf\x11\x2c\x24\xbf\xe8\x2b\x21\x3f\xa6\x9b\x69\xbe\xbb\x3d\xa6\x3e\xaf\x68\x2a\x3f\xad\x68\x2a\x3f\x10\xf6\x71\x3f\x10\xf6\x71\x3f\xc1\x7f\x6e\x3f\x77\x47\x66\xbe\x10\xa8\xba\x3e\x0a\x4b\xe9\xbd\x16\x4b\xe9\xbd\x1c\x2f\x80\xbf\x1c\x2f\x80\xbf\x9d\x40\x7d\x3f\x45\xf1\x62\xbe\xc9\x24\xcc\x3e\xb4\x46\x25\xbf\xb5\x46\x25\xbf\x15\x09\x4c\x3f\x15\x09\x4c\x3f\x4f\xd9\x49\x3f\x11\x99\x5f\xbe\x4b\x87\xda\x3e\x5d\xd3\x6d\x3e\x5d\xd3\x6d\x3e\x01\x00\xc6\xbe\x01\x00\xc6\xbe\xb1\xe9\xc3\x3e\xe9\x3e\x5c\xbe\xad\x8d\xe5\x3e\x18\xea\x19\x3f\x18\xea\x19\x3f\xc1\x58\xf9\xbd\xc1\x58\xf9\xbd\x40\xda\xf9\xbd\xce\xe2\x58\xbe\xef\x0e\xed\x3e\x60\x5f\xb0\xbe\x5d\x5f\xb0\xbe\x0e\xa9\x18\x3f\x0e\xa9\x18\x3f\x9c\x2a\x18\xbf\xd2\x84\x55\xbe\x9d\xfd\xf0\x3e\xeb\xd8\x08\xbf\xe9\xd8\x08\xbf\xc2\x36\x6a\xbf\xc2\x36\x6a\xbf\x8f\xaa\x69\xbf\xf6\x24\x52\xbe\x80\x35\xf1\x3e\x93\x87\xe4\x3e\x97\x87\xe4\x3e\x53\x1c\x7f\x3f\x53\x1c\x7f\x3f\x94\xea\x7e\xbf\x4a\xc3\x4e\xbe\xd7\xd3\xed\x3e\xf8\x30\xe5\x3e\xfa\x30\xe5\x3e\x10\x5c\x52\xbf\x10\x5c\x52\xbf\xa0\xb6\x52\xbf\xd0\x5f\x4b\xbe\x60\xcf\xe6\x3e\x92\x1a\x09\xbf\x8f\x1a\x09\xbf\x0d\x9c\xdf\x3e\x0d\x9c\xdf\x3e\x40\x4a\xe1\xbe\x98\xfa\x47\xbe\xf6\x56\xdc\x3e\x37\x01\xae\xbe\x33\x01\xae\xbe\xde\x38\x71\x3d\xde\x38\x71\x3d\x5d\x86\x60\x3d\xa3\x93\x44\xbe\xbc\x91\xce\x3e\x30\x4a\x1b\x3f\x32\x4a\x1b\x3f\xcc\xcb\x09\xbf\xcc\xcb\x09\xbf\x8c\xf6\x08\x3f\x01\x2b\x41\xbe\x70\xab\xbd\x3e\x2e\x95\x58\x3e\x34\x95\x58\x3e\xbf\x2d\x61\x3f\xbf\x2d\x61\x3f\xdd\xf9\x60\x3f\xb0\xc0\x3d\xbe\x1c\xff\xa9\x3e\xa1\x80\x26\xbf\x9f\x80\x26\xbf\xdf\x3c\x7f\xbf\xdf\x3c\x7f\xbf\x99\xf7\x7f\x3f\xc5\x54\x3a\xbe\xf8\xb9\x93\x3e\x9e\x8b\x90\xbd\x98\x8b\x90\xbd\x47\x9e\x5c\x3f\x47\x9e\x5c\x3f\x45\x60\x5e\x3f\x3e\xe7\x36\xbe\xe5\xab\x76\x3e\xd4\xca\x29\x3f\xd5\xca\x29\x3f\x90\x48\x02\xbf\x90\x48\x02\xbf\x3c\xef\x04\x3f\x2f\x78\x33\xbe\x3a\x29\x42\x3e\xae\xbd\x97\xbd\xb0\xbd\x97\xbd\xa0\xe1\xe2\x3c\xa0\xe1\xe2\x3c\xbf\xdd\x24\x3d\x96\x07\x30\xbe\x77\xda\x0a\x3e\x16\xca\x25\xbf\x16\xca\x25\xbf\xbd\x1e\xec\x3e\xbd\x1e\xec\x3e\x1b\x76\xe5\xbe\x87\x95\x2c\xbe\x08\x17\xa3\x3d\xce\xfd\x61\x3e\xca\xfd\x61\x3e\xe3\xfc\x55\xbf\xe3\xfc\x55\xbf\xe7\x02\x53\xbf\x02\x22\x29\xbe\x2c\x1c\xb8\x3c\x27\x74\x19\x3f\x26\x74\x19\x3f\x2d\x7b\x80\x3f\x2d\x7b\x80\x3f\xe9\xbe\x7e\xbf\x16\xad\x25\xbe\x17\xd2\x0e\xbd\xaa\x34\xba\xbe\xb1\x34\xba\xbe\x06\x80\x6c\xbf\x06\x80\x6c\xbf\x47\x53\x6b\xbf\xc5\x36\x22\xbe\xa1\xe0\xbb\xbd\xd0\x7a\x03\xbf\xd3\x7a\x03\xbf\xcc\xd6\x1d\x3f\xcc\xd6\x1d\x3f\x5d\xd0\x1d\xbf\x1f\xbf\x1e\xbe\xdb\xa8\x16\xbe\xe1\x77\xfb\x3e\xdd\x77\xfb\x3e\xaf\x0f\x22\xbe\xaf\x0f\x22\xbe\xff\x2f\x26\xbe\x26\x46\x1b\xbe\xe8\x20\x4d\xbe\x7d\x8f\xc7\x3e\x78\x8f\xc7\x3e\x9e\x1d\xad\xbe\x9e\x1d\xad\xbe\x76\x85\xa9\x3e\xea\xcb\x17\xbe\xe0\x4a\x80\xbe\x03\x5c\x16\xbf\x07\x5c\x16\xbf\x9a\x48\x40\x3f\x9a\x48\x40\x3f\xe1\x24\x3e\x3f\x6a\x50\x14\xbe\x58\x0d\x98\xbe\x08\xdb\x73\xbe\x0c\xdb\x73\xbe\xac\x06\x7b\xbf\xac\x06\x7b\xbf\x26\xfa\x78\x3f\xbd\xd3\x10\xbe\x1c\xa8\xad\xbe\x65\x4c\x24\x3f\x64\x4c\x24\x3f\xec\xd2\x78\x3f\xec\xd2\x78\x3f\x75\x27\x77\x3f\xe1\x55\x0d\xbe\x1b\x97\xc0\xbe\x53\x4e\x9b\x3d\x53\x4e\x9b\x3d\x9a\xa7\x3a\xbf\x9a\xa7\x3a\xbf\x55\x64\x39\x3f\xe7\xd6\x09\xbe\x5f\xd0\xd0\xbe\x24\x93\x28\xbf\x23\x93\x28\xbf\xe8\x00\xa0\x3e\xe8\x00\xa0\x3e\x4d\xca\x9d\x3e\xce\x56\x06\xbe\x74\xe0\xdd\xbe\x2f\x35\xbb\x3d\x3d\x35\xbb\x3d\xa6\x63\x34\x3e\xa6\x63\x34\x3e\x22\xdc\x39\xbe\xaa\xd5\x02\xbe\x43\xc8\xe7\xbe\x1f\x83\x23\x3f\x21\x83\x23\x3f\xbd\x7b\x1e\xbf\xbd\x7b\x1e\xbf\xcb\x7a\x20\xbf\xf4\xa6\xfe\xbd\x96\x47\xee\xbe\x6a\xff\x86\xbe\x62\xff\x86\xbe\x18\x2a\x69\x3f\x18\x2a\x69\x3f\x48\xe2\x6b\xbf\xa0\xa0\xf7\xbd\x68\x51\xf1\xbe\x82\x28\x12\xbf\x80\x28\x12\xbf\x60\xb4\x7b\xbf\x60\xb4\x7b\xbf\xae\xd5\x7e\xbf\x56\x98\xf0\xbd\x87\xea\xf0\xbe\x84\x40\xda\x3e\x8a\x40\xda\x3e\x6c\x33\x52\x3f\x6c\x33\x52\x3f\xe6\x10\x55\xbf\x36\x8b\xe9\xbd\x90\xf2\xec\xbe\x1e\x4e\xe6\x3e\x24\x4e\xe6\x3e\xa3\xfa\xed\xbe\xa3\xfa\xed\xbe\xa9\x85\xf1\xbe\x3e\x79\xe2\xbd\x90\xb3\xe5\xbe\x16\x13\x0e\xbf\x13\x13\x0e\xbf\x84\x31\xf6\xb7\x84\x31\xf6\xb7\x09\x9c\xdf\x36\xa8\x68\xdb\xbd\x03\xff\xda\xbe\xc3\x79\x93\xbe\xc1\x79\x93\xbe\x0a\x31\xed\x3e\x0a\x31\xed\x3e\x74\x2e\xf1\x3e\x74\x59\xd4\xbd\x11\x5c\xcd\xbe\xe4\xe9\x22\x3f\xe4\xe9\x22\x3f\xb0\xf6\x50\xbf\xb0\xf6\x50\xbf\xd5\xa0\x54\x3f\x50\x4b\xcd\xbd\x15\x99\xbc\xbe\x13\x45\xd0\x3d\x11\x45\xd0\x3d\x05\x23\x7a\x3f\x05\x23\x7a\x3f\x9f\xa7\x7e\x3f\x3a\x3e\xc6\xbd\xf3\x57\xa9\xbe\xfc\x3f\x2a\xbf\xfd\x3f\x2a\xbf\x79\xbc\x68\xbf\x79\xbc\x68\xbf\x1e\x13\x6d\x3f\xd9\x2c\xbf\xbd\x89\x84\x93\xbe\xbe\x33\xc5\x3d\xab\x33\xc5\x3d\x5a\x02\x21\x3f\x5a\x02\x21\x3f\x23\x43\x24\x3f\x2b\x17\xb8\xbd\xc0\x89\x77\xbe\xd7\xab\x22\x3f\xd4\xab\x22\x3f\x30\xe0\x4e\xbe\x30\xe0\x4e\xbe\x97\x8f\x55\x3e\x3f\x00\xb1\xbd\x7a\x53\x44\xbe\x09\x0f\x94\xbe\x10\x0f\x94\xbe\x98\x9c\x8b\xbe\x98\x9c\x8b\xbe\x01\x60\x8b\xbe\x16\xe8\xa9\xbd\x91\x8e\x0e\xbe\x5a\xc2\x0b\xbf\x5e\xc2\x0b\xbf\x44\x8a\x2f\x3f\x44\x8a\x2f\x3f\x1c\x7f\x30\xbf\xd2\xce\xa2\xbd\xb2\x6d\xad\xbd\xe1\xef\xe9\x3e\xdb\xef\xe9\x3e\x15\x32\x71\xbf\x15\x32\x71\xbf\xa8\x85\x72\xbf\x72\xb4\x9b\xbd\x37\xea\xed\xbc\x97\x3c\xcf\x3e\x92\x3c\xcf\x3e\x62\xc3\x7b\x3f\x62\xc3\x7b\x3f\x79\xca\x7c\xbf\x20\x99\x94\xbd\xcb\xc3\xdc\x3c\xcb\x15\x16\xbf\xcc\x15\x16\xbf\x4b\xe8\x4c\xbf\x4b\xe8\x4c\xbf\x68\x33\x4d\xbf\xda\x7c\x8d\xbd\x85\x0d\xa9\x3d\x78\xf4\x5f\xbe\x7a\xf4\x5f\xbe\x5e\xde\xde\x3e\x5e\xde\xde\x3e\x9c\xbb\xdd\xbe\xc0\x5f\x86\xbd\x57\x2b\x0c\x3e\x04\x51\x29\x3f\x05\x51\x29\x3f\xad\x40\xe8\x3c\xad\x40\xe8\x3c\x70\xba\x08\x3d\xa6\x83\x7e\xbd\x5f\xd3\x41\x3e\x3a\xec\xb3\xba\xba\xe8\xb3\xba\x80\x4b\xf8\xbe\x80\x4b\xf8\xbe\xd1\xb0\xfb\x3e\x71\x46\x70\xbd\x8a\xb5\x74\x3e\xe2\x30\x29\xbf\xe0\x30\x29\xbf\x66\xcb\x54\x3f\x66\xcb\x54\x3f\xd2\x87\x56\x3f\xe2\x07\x62\xbd\xb1\x0e\x92\x3e\xce\xcb\x66\x3e\xda\xcb\x66\x3e\x5b\x58\x7d\xbf\x5b\x58\x7d\xbf\x9c\xc1\x7e\x3f\x42\xc8\x53\xbd\xde\xb8\xa7\x3e\x01\xa2\x14\x3f\x04\xa2\x14\x3f\x4a\xf4\x6c\x3f\x4a\xf4\x6c\x3f\x7b\xb7\x6d\x3f\x91\x87\x45\xbd\x0f\x03\xbb\x3e\x45\x9c\xd7\xbe\x3f\x9c\xd7\xbe\x6a\xa7\x27\xbf\x6a\xa7\x27\xbf\x2f\x7f\x27\x3f\x14\x46\x37\xbd\xa7\xb3\xcb\x3e\x25\x3c\xde\xbe\x1f\x3c\xde\xbe\x70\x26\x75\x3e\x70\x26\x75\x3e\xff\x0b\x70\x3e\xcd\x03\x29\xbd\x92\x8c\xd9\x3e\x13\x63\x11\x3f\x15\x63\x11\x3f\xc4\xbf\x68\x3e\xc4\xbf\x68\x3e\xda\xa4\x72\xbe\x00\xc1\x1a\xbd\x42\x5c\xe4\x3e\xe6\x88\x73\x3e\xea\x88\x73\x3e\xf8\x1f\x24\xbf\xf8\x1f\x24\xbf\x6f\xb5\x27\xbf\xae\x7d\x0c\xbd\xac\x09\xec\x3e\x0d\xf2\x26\xbf\x0c\xf2\x26\xbf\x56\x21\x69\x3f\x56\x21\x69\x3f\xbf\x88\x6d\xbf\x52\x74\xfc\xbc\x76\x6b\xf0\x3e\x94\x11\xfa\xbb\xd4\x11\xfa\xbb\xb0\x2c\x7a\xbf\xb0\x2c\x7a\xbf\xfc\xeb\x7e\xbf\xe3\xec\xdf\xbc\x9f\x86\xf1\x3e\xb8\x9a\x28\x3f\xb7\x9a\x28\x3f\x76\xcd\x53\x3f\x76\xcd\x53\x3f\x41\x4a\x58\xbf\x8d\x65\xc3\xbc\x2c\x4a\xef\x3e\xa0\x7c\x70\xbe\xa7\x7c\x70\xbe\xe1\x80\xfd\xbe\xe1\x80\xfd\xbe\x2e\x5b\x02\xbf\x51\xde\xa6\xbc\xab\xc8\xe9\x3e\xf9\x48\x12\xbf\xfc\x48\x12\xbf\x42\x5c\x5e\x3d\x42\x5c\x5e\x3d\x77\xc8\x80\xbd\xc2\x57\x8a\xbc\xa5\x18\xe1\x3e\xc5\x2a\xe5\x3e\xc1\x2a\xe5\x3e\xab\xf0\xcb\x3e\xab\xf0\xcb\x3e\xb7\xf9\xca\x3e\xc1\xa3\x5b\xbc\xb0\x52\xd5\x3e\xea\xac\xcd\x3e\xe6\xac\xcd\x3e\xdd\x98\x43\xbf\xdd\x98\x43\xbf\x55\xe1\x44\x3f\x99\x9a\x22\xbc\xdb\xac\xc6\x3e\xfc\xc2\x18\xbf\xff\xc2\x18\xbf\xd4\xbb\x76\x3f\xd4\xbb\x76\x3f\x28\x90\x79\x3f\x1c\x28\xd3\xbb\x9d\x54\xb5\x3e\xca\xcf\x33\xbe\xd2\xcf\x33\xbe\x99\x73\x74\xbf\x99\x73\x74\xbf\x3f\x64\x78\x3f\x5e\x44\x42\xbb\x03\x86\xa1\x3e\xce\xb6\x29\x3f\xcc\xb6\x29\x3f\x9e\x62\x3d\x3f\x9e\x62\x3d\x3f\x89\xe0\x41\x3f\xab\xe4\x06\x3a\xf1\x98\x8b\x3e\xca\x12\xa1\xbd\xce\x12\xa1\xbd\x92\xef\xba\xbe\x92\xef\xba\xbe\x2b\xe4\xc3\x3e\xc9\xd1\x82\x3b\x58\x72\x67\x3e\x60\x36\x22\xbf\x5f\x36\x22\xbf\x9f\xe9\xb5\xbd\x9f\xe9\xb5\xbd\x24\xe9\x95\xbd\x6b\xbd\xf4\x3b\xde\xd1\x34\x3e\xd5\xf4\xa7\x3e\xd8\xf4\xa7\x3e\x23\x81\x06\x3f\x23\x81\x06\x3f\x7b\x43\x03\xbf\x94\x4e\x33\x3c\x00\x31\xff\x3d\xf0\xfe\x00\x3f\xf1\xfe\x00\x3f\x45\x33\x5a\xbf\x45\x33\x5a\xbf\x50\xcb\x57\xbf\x7e\x38\x6c\x3c\x15\xc2\x91\x3d\x2e\xbb\x07\xbf\x2c\xbb\x07\xbf\x56\x22\x80\x3f\x56\x22\x80\x3f\x22\x99\x7e\xbf\xb1\x8d\x92\x3c\xda\x0a\x89\x3c\x57\x92\x93\xbe\x53\x92\x93\xbe\x61\xd4\x70\xbf\x61\xd4\x70\xbf\xab\xb6\x6f\xbf\x9f\xfb\xae\x3c\x8b\x15\x1b\xbd\x25\x00\x25\x3f\x27\x00\x25\x3f\xb7\x37\x2f\x3f\xb7\x37\x2f\x3f\xa2\x84\x2e\xbf\x73\x65\xcb\x3c\x20\x19\xbc\xbd\xb0\x1c\xd6\x3c\xf2\x1c\xd6\x3c\x2c\x4c\x92\xbe\x2c\x4c\x92\xbe\x0f\xcb\x91\xbe\x2c\xcb\xe7\x3c\x53\x1e\x14\xbe\x1a\x8d\x27\xbf\x19\x8d\x27\xbf\x3f\xed\x30\xbe\x3f\xed\x30\xbe\x40\x18\x2f\x3e\x24\x16\x02\x3d\xfd\x11\x48\xbe\xfc\x78\x79\x3e\x00\x79\x79\x3e\xa2\xca\x18\x3f\xa2\xca\x18\x3f\x72\x28\x17\x3f\x63\x44\x10\x3d\x97\x5a\x79\xbe\xcb\xeb\x0d\x3f\xcb\xeb\x0d\x3f\x80\x62\x66\xbf\x80\x62\x66\xbf\xe6\x0b\x63\x3f\x06\x70\x1e\x3d\x8d\xab\x93\xbe\x8c\xcc\xf4\xbe\x8a\xcc\xf4\xbe\x35\xab\x82\x3f\x35\xab\x82\x3f\x81\xeb\x7f\x3f\x0e\x99\x2c\x3d\x44\x97\xa8\xbe\x85\x2d\xb4\xbe\x87\x2d\xb4\xbe\x34\x8b\x6f\xbf\x34\x8b\x6f\xbf\x4e\x11\x68\x3f\x31\xbf\x3a\x3d\xc0\x6b\xbb\xbe\x84\x8d\x21\x3f\x83\x8d\x21\x3f\x07\x97\x29\x3f\x07\x97\x29\x3f\x54\xa4\x20\x3f\x72\xe2\x48\x3d\xf1\x8e\xcb\xbe\xf7\x87\x9f\x3d\xed\x87\x9f\x3d\x1f\x79\x83\xbe\x1f\x79\x83\xbe\x60\xeb\x61\x3e\x86\x02\x57\x3d\x36\x38\xd9\xbe\xb7\x74\x2a\xbf\xb8\x74\x2a\xbf\xeb\x1a\x4c\xbe\xeb\x1a\x4c\xbe\x5e\x21\x6c\xbe\x6e\x1f\x65\x3d\x61\xce\xe3\xbe\x08\x06\x5e\x3e\x01\x06\x5e\x3e\x2b\x3b\x1d\x3f\x2b\x3b\x1d\x3f\x39\x60\x22\xbf\xe4\x38\x73\x3d\x5e\x8d\xeb\xbe\x3a\x79\x11\x3f\x38\x79\x11\x3f\xb4\xa8\x67\xbf\xb4\xa8\x67\xbf\x75\xae\x68\xbf\x73\xa7\x80\x3d\x2c\x1e\xf0\xbe\xa2\x2c\xf1\xbe\xa6\x2c\xf1\xbe\x03\xca\x81\x3f\x03\xca\x81\x3f\x98\xea\x7f\xbf\x99\xb0\x87\x3d\x96\x8e\xf1\xbe\xd0\xc8\xb4\xbe\xd4\xc8\xb4\xbe\xf0\xac\x6b\xbf\xf0\xac\x6b\xbf\x7c\xa1\x63\xbf\xe4\xb7\x8e\x3d\x73\xe2\xef\xbe\x4f\x7d\x20\x3f\x4e\x7d\x20\x3f\x1e\x14\x25\x3f\x1e\x14\x25\x3f\x5d\xbf\x19\xbf\x2f\xbd\x95\x3d\x7c\x04\xeb\xbe\x3b\x8b\x8c\x3d\x3b\x8b\x8c\x3d\x1b\x06\x79\xbe\x1b\x06\x79\xbe\x94\x06\x45\xbe\x7c\xc0\x9c\x3d\x6e\x29\xe3\xbe\x89\xec\x27\xbf\x88\xec\x27\xbf\xd7\xe5\x4f\xbe\xd7\xe5\x4f\xbe\x64\xc0\x81\x3e\xa0\xc1\xa3\x3d\xbb\x5d\xd8\xbe\xc9\xf0\x6b\x3e\xcd\xf0\x6b\x3e\x19\xb5\x1a\x3f\x19\xb5\x1a\x3f\x1e\xf2\x25\x3f\x9e\xc0\xaa\x3d\xcb\xac\xca\xbe\x78\x30\x0d\x3f\x79\x30\x0d\x3f\x85\x93\x61\xbf\x85\x93\x61\xbf\x8d\x06\x6a\x3f\x57\xbd\xb1\x3d\x1a\x9f\xba\xbe\xf7\x69\xfa\xbe\xf5\x69\xfa\xbe\x25\xcf\x7a\x3f\x25\xcf\x7a\x3f\xc7\xdc\x7f\x3f\xcd\xb7\xb8\x3d\x58\xc4\xa7\xbe\x1f\x16\xa5\xbe\x1d\x16\xa5\xbe\xaa\xe1\x61\xbf\xaa\xe1\x61\xbf\x04\x66\x63\x3f\xd7\xaf\xbf\x3d\x65\x5a\x93\xbe\x36\x15\x25\x3f\x37\x15\x25\x3f\x7e\x46\x1c\x3f\x7e\x46\x1c\x3f\xdb\x74\x1a\x3f\x75\xa5\xc6\x3d\xdb\xa2\x78\xbe\x76\x7f\x36\x3c\x96\x7f\x36\x3c\xd7\xe4\x60\xbe\xd7\xe4\x60\xbe\xaf\xf3\x4d\x3e\x84\x98\xcd\x3d\x8a\x30\x49\xbe\x74\xc3\x25\xbf\x73\xc3\x25\xbf\x19\xf6\x58\xbe\x19\xf6\x58\xbe\x14\x55\x75\xbe\x05\x89\xd4\x3d\x1c\x3a\x15\xbe\xa8\xf4\x99\x3e\xa9\xf4\x99\x3e\xaa\x4b\x19\x3f\xaa\x4b\x19\x3f\x03\x17\x22\xbf\xd7\x76\xdb\x3d\x01\x11\xc3\xbd\x0a\x46\x00\x3f\x0a\x46\x00\x3f\xdb\x9c\x5d\xbf\xdb\x9c\x5d\xbf\x6a\x5f\x67\xbf\xfa\x61\xe2\x3d\x8f\xfe\x29\xbd\x1a\x7e\x0b\xbf\x1a\x7e\x0b\xbf\xa9\x0f\x76\x3f\xa9\x0f\x76\x3f\xc9\xfe\x7f\xbf\x49\x4a\xe9\x3d\x1d\x1a\x30\x3c\xe1\x06\x71\xbe\xe2\x06\x71\xbe\xca\x26\x5e\xbf\xca\x26\x5e\xbf\x41\x74\x67\xbf\xc4\x2f\xf0\x3d\x0c\x2e\x84\x3d\x9b\x88\x2a\x3f\x9c\x88\x2a\x3f\xfd\xc5\x1a\x3f\xfd\xc5\x1a\x3f\x70\xb1\x22\xbf\x47\x12\xf7\x3d\x86\xb4\xed\x3d\xd2\xdd\xcb\xbd\xd8\xdd\xcb\xbd\xc9\x8e\x64\xbe\xc9\x8e\x64\xbe\xca\x2d\x7c\xbe\xd2\xf1\xfd\x3d\x9e\x11\x2b\x3e\xaf\x02\x1f\xbf\xb0\x02\x1f\xbf\x29\x5c\x4f\xbe\x29\x5c\x4f\xbe\x4c\x9f\x41\x3e\x23\x67\x02\x3e\x27\x91\x5c\x3e\xf0\x30\xd9\x3e\xee\x30\xd9\x3e\x5d\x37\x17\x3f\x5d\x37\x17\x3f\xcc\x81\x16\x3f\xd1\xd3\x05\x3e\x44\x9a\x85\x3e\xfd\xf5\xcb\x3e\xfb\xf5\xcb\x3e\x7c\x00\x5e\xbf\x7c\x00\x5e\xbf\x63\x0e\x60\x3f\xe2\x3e\x09\x3e\xfe\x7c\x9b\x3e\x20\xe2\x21\xbf\x20\xe2\x21\xbf\xc3\xbe\x7a\x3f\xc3\xbe\x7a\x3f\xeb\x60\x7f\x3f\x54\xa8\x0c\x3e\xd0\xec\xae\x3e\x16\x2f\x75\xbd\x1a\x2f\x75\xbd\xb1\x04\x68\xbf\xb1\x04\x68\xbf\xa4\xd2\x6e\x3f\x1a\x10\x10\x3e\x7c\xc2\xc0\x3e\xb9\xfe\x26\x3f\xb9\xfe\x26\x3f\x33\x5d\x29\x3f\x33\x5d\x29\x3f\xc0\xb7\x31\x3f\x31\x76\x13\x3e\x5f\x81\xcf\x3e\xe1\xf7\x8e\xbe\xe1\xf7\x8e\xbe\x78\x18\x95\xbe\x78\x18\x95\xbe\x27\x4d\xa7\x3e\x87\xda\x16\x3e\xc5\x42\xdc\x3e\x1d\xd6\xfe\xbe\x1d\xd6\xfe\xbe\x9c\xe0\x0a\xbe\x9c\xe0\x0a\xbe\xa5\x35\xce\xbd\x1c\x3d\x1a\x3e\x94\xc5\xe5\x3e\x65\xfd\x07\x3f\x65\xfd\x07\x3f\x1e\x25\x0a\x3f\x1e\x25\x0a\x3f\x70\x44\x02\xbf\xe2\x9d\x1d\x3e\xb2\xb7\xec\x3e\xff\x53\x64\x3e\xff\x53\x64\x3e\x0b\xa6\x58\xbf\x0b\xa6\x58\xbf\xf8\x9a\x52\xbf\xd8\xfc\x20\x3e\xa1\x9d\xf0\x3e\xc5\xb9\x26\xbf\xc5\xb9\x26\xbf\xf5\xdd\x7f\x3f\xf5\xdd\x7f\x3f\xc5\x2b\x7c\xbf\xec\x59\x24\x3e\x89\x70\xf1\x3e\x89\x58\xf8\x3d\x89\x58\xf8\x3d\x72\xb8\x78\xbf\x72\xb8\x78\xbf\xdb\x90\x77\xbf\x1c\xb5\x27\x3e\x61\x80\xef\x3e\xcd\x62\x18\x3f\xcd\x62\x18\x3f\x7a\x9b\x44\x3f\x7a\x9b\x44\x3f\x83\xdf\x45\xbf\x5a\x0e\x2b\x3e\x28\x53\xea\x3e\xa0\xb3\xe7\xbe\xa0\xb3\xe7\xbe\xd8\x11\xda\xbe\xd8\x11\xda\xbe\x4d\xb4\xe0\xbe\xa5\x65\x2e\x3e\x16\x84\xe2\x3e\xd7\x39\xb2\xbe\xd7\x39\xb2\xbe\xe0\xbd\xe5\x3b\xe0\xbd\xe5\x3b\xa0\x2e\xd5\xbc\xee\xba\x31\x3e\x70\xc7\xd7\x3e\xc5\x03\x27\x3f\xc6\x03\x27\x3f\xb9\xe1\xd3\x3e\xb9\xe1\xd3\x3e\x3d\x17\xc8\x3e\x34\x0e\x35\x3e\x10\x66\xca\x3e\xa0\x49\xaf\xbc\xa0\x49\xaf\xbc\x61\x11\x43\xbf\x61\x11\x43\xbf\xe4\x9a\x3c\x3f\x66\x5f\x38\x3e\x10\xb9\xba\x3e\x36\xdd\x23\xbf\x36\xdd\x23\xbf\x86\xe9\x79\x3f\x86\xe9\x79\x3f\x42\x44\x73\x3f\x86\xae\x3b\x3e\x10\x76\xa8\x3e\x41\x0b\xc6\x3e\x41\x0b\xc6\x3e\x43\x78\x82\xbf\x43\x78\x82\xbf\xec\x75\x7e\x3f\x80\xfb\x3e\x3e\xa5\x8e\x94\x3e\x9a\xd1\xd4\x3e\x9a\xd1\xd4\x3e\x71\x5a\x62\x3f\x71\x5a\x62\x3f\xa4\x6b\x5c\x3f\x57\x46\x42\x3e\x12\xec\x7c\x3e\x42\x3a\x1f\xbf\x42\x3a\x1f\xbf\xa9\x53\x18\xbf\xa9\x53\x18\xbf\xee\x67\x13\x3f\xf9\x8e\x45\x3e\x43\x58\x4e\x3e\xa2\xc2\x6c\xbd\xa0\xc2\x6c\xbd\xb5\x6c\x4f\x3e\xb5\x6c\x4f\x3e\xe4\x02\x42\x3e\x67\xd5\x48\x3e\xd1\xef\x1c\x3e\xf0\x9b\x27\x3f\xf0\x9b\x27\x3f\xaf\x2e\x66\x3e\xaf\x2e\x66\x3e\xeb\x0b\x6b\xbe\x90\x19\x4c\x3e\xfb\x60\xd3\x3d\x65\xa7\xa5\xbe\x66\xa7\xa5\xbe\xb9\xe6\x1c\xbf\xb9\xe6\x1c\xbf\x65\x8c\x1b\xbf\x72\x5b\x4f\x3e\x4d\x21\x56\x3d\xea\x4d\xee\xbe\xeb\x4d\xee\xbe\x8a\x0f\x65\x3f\x8a\x0f\x65\x3f\x70\x03\x61\xbf\x01\x9b\x52\x3e\xd7\x90\x54\x39\x68\xad\x19\x3f\x68\xad\x19\x3f\x74\xd3\x82\xbf\x74\xd3\x82\xbf\x57\x38\x7f\xbf\x3c\xd8\x55\x3e\xa2\x8e\x51\xbd\x0b\xb2\xd7\x3d\x08\xb2\xd7\x3d\xab\x32\x79\x3f\xab\x32\x79\x3f\xdd\x24\x71\xbf\x11\x13\x59\x3e\x43\xdc\xd1\xbd\xab\xe4\x28\xbf\xac\xe4\x28\xbf\x40\x07\x42\xbf\x40\x07\x42\xbf\x7d\x74\x39\xbf\x81\x4b\x5c\x3e\xe4\xbf\x1b\xbe\x4d\x7e\x94\x3e\x4d\x7e\x94\x3e\x61\xab\xd3\x3e\x61\xab\xd3\x3e\x7e\xea\xc3\xbe\x7c\x81\x5f\x3e\xf3\xc0\x4c\xbe\x73\x06\xf7\x3e\x73\x06\xf7\x3e\x27\x54\x47\x39\x27\x54\x47\x39\x56\xbc\xc5\x3c\x03\xb5\x62\x3e\x85\x82\x7b\xbe\xd9\x68\x14\xbf\xd9\x68\x14\xbf\x22\xb1\xd2\xbe\x22\xb1\xd2\xbe\xde\x2a\xda\x3e\x06\xe6\x65\x3e\x24\x57\x93\xbe\xcd\x79\x05\xbe\xcd\x79\x05\xbe\xd7\x08\x40\x3f\xd7\x08\x40\x3f\xbf\x3f\x41\x3f\x87\x14\x69\x3e\x21\x81\xa7\xbe\xb7\xaf\x28\x3f\xb7\xaf\x28\x3f\x4f\x76\x75\xbf\x4f\x76\x75\xbf\x41\x80\x74\x3f\x70\x40\x6c\x3e\xd5\x4c\xb9\xbe\x22\x8e\x8c\xbe\x24\x8e\x8c\xbe\x50\x6a\x80\x3f\x50\x6a\x80\x3f\x43\x5a\x7e\x3f\xc0\x69\x6f\x3e\x67\x27\xc9\xbe\x17\x23\xfa\xbe\x17\x23\xfa\xbe\x66\xa0\x60\xbf\x66\xa0\x60\xbf\x7e\x5d\x5d\x3f\x74\x90\x72\x3e\x78\x7d\xd6\xbe\x22\xd3\x13\x3f\x22\xd3\x13\x3f\xc4\xc2\x1a\x3f\xc4\xc2\x1a\x3f\x94\x4d\x17\x3f\x88\xb4\x75\x3e\x14\x34\xe1\xbe\xe5\x87\x02\x3e\xe6\x87\x02\x3e\x5d\xb7\x6d\xbe\x5d\xb7\x6d\xbe\x52\x51\x60\x3e\xe7\xd5\x78\x3e\x92\x82\xe9\xbe\xde\x22\x28\xbf\xde\x22\x28\xbf\x6f\x50\x34\xbe\x6f\x50\x34\xbe\x9c\x3e\x41\xbe\x8f\xf4\x7b\x3e\xc8\xa7\xee\xbe\x73\x1a\x93\x3e\x73\x1a\x93\x3e\xdf\x33\x0d\x3f\xdf\x33\x0d\x3f\x6c\x7f\x10\xbf\x72\x10\x7f\x3e\xcc\x74\xf1\xbe\x33\x91\xf2\x3e\x33\x91\xf2\x3e\x34\x12\x55\xbf\x34\x12\x55\xbf\x2e\xa1\x58\xbf\xc8\x14\x81\x3e\x86\xfb\xf0\xbe\x04\xe9\x16\xbf\x04\xe9\x16\xbf\xb5\x16\x79\x3f\xb5\x16\x79\x3f\x22\xf7\x7c\xbf\xf1\x9f\x82\x3e\x33\x01\xee\xbe\x04\xcd\xc1\xbd\x04\xcd\xc1\xbd\x57\xc0\x73\xbf\x57\xc0\x73\xbf\x44\xbe\x77\xbf\xb2\x29\x84\x3e\x1d\x1c\xe8\xbe\xed\x0d\x26\x3f\xee\x0d\x26\x3f\x39\x69\x46\x3f\x39\x69\x46\x3f\x25\x0b\x4a\xbf\x03\xb2\x85\x3e\xd5\x71\xdf\xbe\x05\x58\xa5\xbe\x07\x58\xa5\xbe\xc0\xce\xf1\xbe\xc0\xce\xf1\xbe\xf9\x0c\xf7\xbe\xe3\x38\x87\x3e\xe4\x6d\xd4\xbe\x7e\x84\xe2\xbe\x7e\x84\xe2\xbe\x90\x3a\xc1\x3d\x90\x3a\xc1\x3d\xf5\xce\xc8\xbd\x4c\xbe\x88\x3e\x2b\x9a\xc6\xbe\xcd\xc5\x1d\x3f\xcd\xc5\x1d\x3f\x9d\x01\x98\x3e\x9d\x01\x98\x3e\x6e\x6c\x9a\x3e\x3c\x42\x8a\x3e\x6d\xd8\xb6\xbe\x40\x90\x19\x3d\x38\x90\x19\x3d\x30\x65\x23\xbf\x30\x65\x23\xbf\xe8\xe9\x26\x3f\xae\xc4\x8b\x3e\xbc\xb8\xa4\xbe\x4f\xb5\x25\xbf\x4f\xb5\x25\xbf\x27\x1a\x60\x3f\x27\x1a\x60\x3f\x6e\xad\x65\x3f\xa0\x45\x8d\x3e\xaa\xc5\x90\xbe\x96\x08\xcd\x3e\x95\x08\xcd\x3e\x6a\x9f\x78\xbf\x6a\x9f\x78\xbf\x3f\x9d\x7f\x3f\x0c\xc5\x8e\x3e\x30\xc1\x76\xbe\x0b\xf5\xc0\x3e\x0a\xf5\xc0\x3e\x63\x4e\x69\x3f\x63\x4e\x69\x3f\xf3\xcb\x70\x3f\xf1\x42\x90\x3e\x45\x2e\x48\xbe\x53\x5b\x28\xbf\x53\x5b\x28\xbf\xbb\xd5\x34\xbf\xbb\xd5\x34\xbf\xd7\xce\x3b\x3f\x4a\xbf\x91\x3e\xf0\xd6\x18\xbe\x80\x46\x97\x3d\x7e\x46\x97\x3d\x53\x6d\xc7\x3e\x53\x6d\xc7\x3e\xc1\x7b\xd2\x3e\x14\x3a\x93\x3e\x86\xe2\xcb\xbd\x07\xca\x1a\x3f\x07\xca\x1a\x3f\x12\xdf\x36\xbc\x12\xdf\x36\xbc\x54\x8b\xc8\x3c\x4c\xb3\x94\x3e\x75\x90\x4f\xbd\xa9\xbb\xfa\xbe\xa9\xbb\xfa\xbe\xca\xf6\xbc\xbe\xca\xf6\xbc\xbe\x55\x01\xbb\xbe\xef\x2a\x96\x3e\x48\x7d\x04\x3a\xc7\x3f\x86\xbe\xc7\x3f\x86\xbe\x8c\x1b\x31\x3f\x8c\x1b\x31\x3f\x0a\x7b\x32\xbf\xf7\xa0\x97\x3e\xc6\xe6\x4d\x3d\xf9\x62\x2a\x3f\xf9\x62\x2a\x3f\xbd\x38\x68\xbf\xbd\x38\x68\xbf\x34\x87\x6b\xbf\x62\x15\x99\x3e\xa5\x1a\xcd\x3d\xe0\xce\x4b\xbe\xdf\xce\x4b\xbe\x68\x5a\x7b\x3f\x68\x5a\x7b\x3f\x0f\xf6\x7f\xbf\x2c\x88\x9a\x3e\x1f\x78\x18\x3e\xa8\xb9\x05\xbf\xa7\xb9\x05\xbf\xc7\x9c\x67\xbf\xc7\x9c\x67\xbf\xb6\xd3\x6c\xbf\x52\xf9\x9b\x3e\x7e\xa6\x47\x3e\x10\x19\x0f\x3f\x11\x19\x0f\x3f\x3d\x14\x30\x3f\x3d\x14\x30\x3f\xc5\x49\x35\xbf\x9f\x65\x9d\x3e\x8b\x66\x76\x3e\x02\x09\x08\x3e\x02\x09\x08\x3e\x65\x90\xba\xbe\x65\x90\xba\xbe\x63\x1d\xc4\xbe\x11\xcd\x9e\x3e\xb7\xcc\x8f\x3e\x7e\x5d\x27\xbf\x7e\x5d\x27\xbf\x1c\x5e\x84\xbc\x1c\x5e\x84\xbc\x21\x9a\x05\xb7\xc9\x37\xa0\x3e\x95\x7a\xa4\x3e\x87\x0e\xa9\x3e\x87\x0e\xa9\x3e\xd6\xb4\xca\x3e\xd6\xb4\xca\x3e\xf7\xbf\xc3\x3e\xc8\xa5\xa1\x3e\x95\x4b\xb5\x3e\x3a\xb1\xd7\x3e\x3a\xb1\xd7\x3e\xd9\x9b\x37\xbf\xd9\x9b\x37\xbf\xb3\xbc\x34\x3f\xcd\x11\xa3\x3e\x9a\x37\xc6\x3e\xc0\xfd\x22\xbf\xc0\xfd\x22\xbf\x5c\x73\x6e\x3f\x5c\x73\x6e\x3f\x06\x29\x6c\x3f\xda\x7b\xa4\x3e\xb3\xac\xd2\x3e\xe6\xfd\x29\x3d\xee\xfd\x29\x3d\xc0\xcc\x80\xbf\xc0\xcc\x80\xbf\xd7\xf8\x7f\x3f\x66\xe2\xa5\x3e\xd0\xee\xde\x3e\xe1\xd2\x1a\x3f\xe0\xd2\x1a\x3f\xd5\x2e\x6e\x3f\xd5\x2e\x6e\x3f\xaf\x69\x6d\x3f\x71\x45\xa7\x3e\xd1\xb1\xe6\x3e\x75\xb6\xf6\xbe\x76\xb6\xf6\xbe\x02\x25\x37\xbf\x02\x25\x37\xbf\x99\x79\x37\x3f\xba\xa6\xa8\x3e\x4c\x96\xed\x3e\xf0\x9d\x80\xbe\xf1\x9d\x80\xbe\xf1\x8c\xc9\x3e\xf1\x8c\xc9\x3e\x4a\xc2\xcc\x3e\x3e\x06\xaa\x3e\x02\x7a\xf0\x3e\xb2\x47\x2a\x3f\xb2\x47\x2a\x3f\x04\x82\x5b\xbc\x04\x82\x5b\xbc\xe7\x0c\xc9\x3c\xfa\x63\xab\x3e\xf1\xa3\xf1\x3e\x5f\xe3\x74\xbe\x60\xe3\x74\xbe\x66\xba\xbc\xbe\x66\xba\xbc\xbe\x04\x21\xb5\xbe\xec\xbf\xac\x3e\xa6\x94\xef\x3e\x8f\xb3\xf9\xbe\x8f\xb3\xf9\xbe\x35\x1e\x32\x3f\x35\x1e\x32\x3f\x1a\xef\x2d\xbf\x0d\x1a\xae\x3e\xd0\x0c\xeb\x3e\xdf\x23\x1a\x3f\xdf\x23\x1a\x3f\xbb\x8d\x6b\xbf\xbb\x8d\x6b\xbf\x80\xb4\x67\xbf\x5c\x72\xaf\x3e\x2e\x04\xe4\x3e\x78\x12\x19\x3d\x78\x12\x19\x3d\x3d\x34\x81\x3f\x3d\x34\x81\x3f\x86\x9a\x7f\xbf\xd6\xc8\xb0\x3e\x5e\x3e\xda\x3e\xcc\x82\x21\xbf\xcc\x82\x21\xbf\x5f\x99\x73\xbf\x5f\x99\x73\xbf\xdb\x5a\x72\xbf\x79\x1d\xb2\x3e\xaa\x51\xce\x3e\x6a\x6a\xe1\x3e\x6a\x6a\xe1\x3e\xfd\x94\x41\x3f\xfd\x94\x41\x3f\xb7\x17\x42\xbf\x3f\x70\xb3\x3e\x8e\x02\xc0\x3e\xa1\x74\x97\x3e\xa3\x74\x97\x3e\xca\xc0\xe7\xbe\xca\xc0\xe7\xbe\xd7\xf2\xeb\xbe\x26\xc1\xb4\x3e\xd4\x87\xaf\x3e\xe8\x56\x2a\xbf\xe8\x56\x2a\xbf\xc5\xed\xae\x3d\xc5\xed\xae\x3d\xda\xad\xc8\xbd\x28\x10\xb6\x3e\x12\x7a\x9d\x3e\x0e\x1c\x5b\x3e\x0e\x1c\x5b\x3e\x51\xd4\x95\x3e\x51\xd4\x95\x3e\x2a\x68\x8e\x3e\x45\x5d\xb7\x3e\xbe\x28\x89\x3e\xe4\x1e\x00\x3f\xe4\x1e\x00\x3f\x46\xbf\x20\xbf\x46\xbf\x20\xbf\x34\x2c\x1d\x3f\x78\xa8\xb8\x3e\x25\x2a\x68\x3e\xa2\xd9\x19\xbf\xa1\xd9\x19\xbf\x87\xa6\x5f\x3f\x87\xa6\x5f\x3f\x7e\xb4\x5c\x3f\xc1\xf1\xb9\x3e\x92\xfd\x39\x3e\xfd\x9f\x09\xbd\xf9\x9f\x09\xbd\x80\x02\x7f\xbf\x80\x02\x7f\xbf\xba\xf7\x7c\x3f\x19\x39\xbb\x3e\x8f\x3c\x0b\x3e\x79\x9a\x20\x3f\x79\x9a\x20\x3f\x6b\xb1\x7a\x3f\x6b\xb1\x7a\x3f\x0b\x9c\x79\x3f\x80\x7e\xbc\x3e\xd1\xec\xb3\x3d\x03\xc8\xea\xbe\x03\xc8\xea\xbe\x05\x8a\x53\xbf\x05\x8a\x53\xbf\x13\x4f\x53\x3f\xf0\xc1\xbd\x3e\xda\x67\x21\x3d\x11\x16\x88\xbe\x10\x16\x88\xbe\xa3\x2a\x0f\x3f\xa3\x2a\x0f\x3f\x4a\x9c\x0f\x3f\x6a\x03\xbf\x3e\x19\x1b\x1c\xbc\xbb\x20\x2b\x3f\xbb\x20\x2b\x3f\x67\x90\x5c\xbe\x67\x90\x5c\xbe\x6a\x5e\x60\x3e\xe7\x42\xc0\x3e\xab\xf6\x6f\xbd\x5f\x45\x88\xbe\x60\x45\x88\xbe\xd3\x77\x21\xbe\xd3\x77\x21\xbe\x69\x14\x1c\xbe\x66\x80\xc1\x3e\x0e\x20\xda\xbd\x44\x53\xe8\xbe\x46\x53\xe8\xbe\x56\x44\x02\x3f\x56\x44\x02\x3f\xcc\x91\x00\xbf\xe1\xbb\xc2\x3e\x4b\x59\x1d\xbe\x85\x7b\x20\x3f\x84\x7b\x20\x3f\x91\x54\x4a\xbf\x91\x54\x4a\xbf\x05\x4c\x48\xbf\x57\xf5\xc3\x3e\xc8\xb5\x4b\xbe\x0e\x9e\x46\xbd\x0e\x9e\x46\xbd\xbf\xd7\x76\x3f\xbf\xd7\x76\x3f\x68\x81\x74\xbf\xc6\x2c\xc5\x3e\x41\xa8\x77\xbe\xec\xbc\x16\xbf\xec\xbc\x16\xbf\xd2\xf2\x80\xbf\xd2\xf2\x80\xbf\x19\x59\x7f\xbf\x2e\x62\xc6\x3e\xb5\xc5\x90\xbe\x71\xd6\x06\x3f\x70\xd6\x06\x3f\x78\x29\x6a\x3f\x78\x29\x6a\x3f\xa9\x8f\x67\xbf\x86\x95\xc7\x3e\x64\xa8\xa3\xbe\x8c\xc6\x22\x3e\x8b\xc6\x22\x3e\xe8\x04\x33\xbf\xe8\x04\x33\xbf\xf6\x91\x30\xbf\xd0\xc6\xc8\x3e\x21\x62\xb5\xbe\x7f\xcb\x27\xbf\x7f\xcb\x27\xbf\x75\x1d\xc8\x3e\x75\x1d\xc8\x3e\x46\xea\xc3\xbe\x06\xf6\xc9\x3e\xbd\x90\xc4\xbe\x2f\x8d\xc1\x3e\x2f\x8d\xc1\x3e\x17\x1c\x00\xbd\x17\x1c\x00\xbd\xad\x66\xcc\xbc\x28\x23\xcb\x3e\x28\x27\xd2\xbe\xf2\xae\xb0\x3e\xf2\xae\xb0\x3e\xd1\x7d\xa9\xbe\xd1\x7d\xa9\xbe\x12\xb6\xab\x3e\x30\x4e\xcc\x3e\x6b\x2c\xdd\xbe\xbc\x62\x2a\xbf\xbc\x62\x2a\xbf\x28\xd7\x25\x3f\x28\xd7\x25\x3f\x82\x85\x26\x3f\x1c\x77\xcd\x3e\x26\xfb\xe5\xbe\x96\xaa\x57\x3e\x96\xaa\x57\x3e\xe0\x9a\x60\xbf\xe0\x9a\x60\xbf\x29\x03\x61\x3f\xea\x9d\xce\x3e\x74\x66\xec\xbe\xff\x9e\xf9\x3e\x00\x9f\xf9\x3e\x33\x74\x7d\x3f\x33\x74\x7d\x3f\x8b\xc1\x7d\x3f\x98\xc2\xcf\x3e\x2c\x2c\xf0\xbe\xe6\x56\x1e\xbf\xe6\x56\x1e\xbf\x52\xd9\x78\xbf\x52\xd9\x78\xbf\x50\x29\x79\x3f\x23\xe5\xd0\x3e\xe1\x98\xf1\xbe\x56\x68\x0e\x3d\x5e\x68\x0e\x3d\x94\xb1\x53\x3f\x94\xb1\x53\x3f\xe2\x07\x54\x3f\x89\x05\xd2\x3e\xde\x60\xf0\xbe\x72\xea\x15\x3f\x72\xea\x15\x3f\x7f\x21\x13\xbf\x7f\x21\x13\xbf\x56\x65\x13\x3f\xc6\x23\xd3\x3e\x30\x9d\xec\xbe\x5e\x0e\x07\xbf\x5e\x0e\x07\xbf\x93\x1e\x7f\x3e\x93\x1e\x7f\x3e\x98\x37\x7f\x3e\xda\x3f\xd4\x3e\x25\x97\xe6\xbe\xe9\xc1\x0f\xbe\xe7\xc1\x0f\xbe\x8d\x9a\xdb\x3d\x8d\x9a\xdb\x3d\xf6\xb6\xde\xbd\xbe\x59\xd5\x3e\x9b\xcd\xdd\xbe\x12\xf5\x26\x3f\x12\xf5\x26\x3f\x71\xa1\xe5\xbe\x71\xa1\xe5\xbe\x00\x6e\xe7\xbe\x74\x71\xd6\x3e\x19\x31\xd3\xbe\x80\x29\xd9\xbe\x7e\x29\xd9\xbe\xaf\x3d\x3b\x3f\xaf\x3d\x3b\x3f\x27\x9c\x3c\xbf\xf4\x86\xd7\x3e\x18\xe2\xc5\xbe\x44\xb8\x90\xbe\x44\xb8\x90\xbe\x17\xb3\x6b\xbf\x17\xb3\x6b\xbf\x4b\x57\x6d\xbf\x42\x9a\xd8\x3e\xfd\x03\xb7\xbe\x89\x9e\x2a\x3f\x89\x9e\x2a\x3f\x32\x49\x7e\x3f\x32\x49\x7e\x3f\x19\xe2\x7f\xbf\x57\xab\xd9\x3e\x61\xe4\xa5\xbe\x42\x8e\x97\xbe\x42\x8e\x97\xbe\xc2\xe2\x70\xbf\xc2\xe2\x70\xbf\xea\x15\x72\xbf\x34\xba\xda\x3e\x74\x4f\x93\xbe\x00\xa1\xd0\xbe\x00\xa1\xd0\xbe\x6f\x5e\x45\x3f\x6f\x5e\x45\x3f\xd6\xe1\x45\xbf\xd3\xc6\xdb\x3e\xca\x41\x7e\xbe\x6a\xe2\x26\x3f\x6a\xe2\x26\x3f\x4f\x4c\x01\xbf\x4f\x4c\x01\xbf\x45\xfe\x00\xbf\x34\xd1\xdc\x3e\xba\x4f\x53\xbe\x9c\xcb\x28\xbe\x9c\xcb\x28\xbe\x97\xda\x34\x3e\x97\xda\x34\x3e\x79\xa3\x30\xbe\x53\xd9\xdd\x3e\x8b\x52\x26\xbe\x8b\xe7\x01\xbf\x8b\xe7\x01\xbf\xe0\xc0\x31\x3e\xe0\xc0\x31\x3e\x56\xf0\x37\x3e\x32\xdf\xde\x3e\xf4\x38\xef\xbd\xc6\xd3\x1d\x3f\xc6\xd3\x1d\x3f\x47\x96\x00\xbf\x47\x96\x00\xbf\x59\x42\x02\x3f\xca\xe2\xdf\x3e\x01\x53\x8f\xbd\xac\xad\x34\xbd\xb0\xad\x34\xbd\xcf\xe6\x44\x3f\xcf\xe6\x44\x3f\xe2\x52\x46\x3f\x1b\xe4\xe0\x3e\x8c\x65\xba\xbc\xaa\xe8\x12\xbf\xaa\xe8\x12\xbf\x01\x0c\x71\xbf\x01\x0c\x71\xbf\x6b\xf0\x71\x3f\x21\xe3\xe1\x3e\x5c\x58\xce\x3c\xf5\x63\x0e\x3f\xf5\x63\x0e\x3f\x02\xb3\x7f\x3f\x02\xb3\x7f\x3f\x9a\xf0\x7f\x3f\xdc\xdf\xe2\x3e\xcc\x92\x93\x3d\x75\x5c\x98\x3d\x75\x5c\x98\x3d\x88\x2e\x6f\xbf\x88\x2e\x6f\xbf\xe3\xd1\x6e\x3f\x48\xda\xe3\x3e\x3c\xfa\xf3\x3d\x90\xa7\x1f\xbf\x90\xa7\x1f\xbf\x38\xa5\x41\x3f\x38\xa5\x41\x3f\xa4\xda\x40\x3f\x65\xd2\xe4\x3e\x99\xba\x27\x3e\x8c\x78\xfb\x3e\x8c\x78\xfb\x3e\xdd\x88\xf9\xbe\xdd\x88\xf9\xbe\xc1\x88\xf7\x3e\x2f\xc8\xe5\x3e\xcc\x0f\x55\x3e\x62\x97\x34\x3e\x62\x97\x34\x3e\x76\x0c\x24\x3e\x76\x0c\x24\x3e\xd5\xf4\x1f\x3e\xa5\xbb\xe6\x3e\x1a\xc1\x7e\x3e\x18\x08\x27\xbf\x18\x08\x27\xbf\x03\xbe\x3d\x3e\x03\xbe\x3d\x3e\x2c\x8c\x41\xbe\xc4\xac\xe7\x3e\xf4\xaf\x93\x3e\x62\x7e\xd8\x3e\x62\x7e\xd8\x3e\x21\xf0\x01\xbf\x21\xf0\x01\xbf\x74\xd4\x02\xbf\x8a\x9b\xe8\x3e\x8b\xb4\xa5\x3e\xea\x5d\x86\x3e\xeb\x5d\x86\x3e\x69\xb1\x44\x3f\x69\xb1\x44\x3f\x76\x9e\x45\xbf\xf6\x87\xe9\x3e\x09\xd5\xb6\x3e\x31\x5a\x2a\xbf\x31\x5a\x2a\xbf\xf3\xe7\x6f\xbf\xf3\xe7\x6f\xbf\x9a\xfb\x70\xbf\x08\x72\xea\x3e\xa5\x56\xc5\x3e\x93\x0e\xb6\x3e\x93\x0e\xb6\x3e\x60\xad\x7e\x3f\x60\xad\x7e\x3f\x2c\xfc\x7f\xbf\xb9\x59\xeb\x3e\x72\x92\xd2\x3e\x2d\xac\xaa\x3e\x2d\xac\xaa\x3e\xfd\x83\x6f\xbf\xfd\x83\x6f\xbf\xa3\x0d\x71\xbf\x0a\x3f\xec\x3e\x2e\x1c\xdd\x3e\xd6\xa5\x2a\xbf\xd6\xa5\x2a\xbf\x18\x72\x44\x3f\x18\x72\x44\x3f\xbb\x1e\x46\xbf\xf9\x21\xed\x3e\xfb\xd0\xe5\x3e\xb3\xc3\x95\x3e\xb3\xc3\x95\x3e\x2c\xb2\x02\xbf\x2c\xb2\x02\xbf\x72\x58\x04\xbf\x84\x02\xee\x3e\x97\x14\xec\x3e\xe9\x5f\xc7\x3e\xe9\x5f\xc7\x3e\x82\x17\x48\x3e\x82\x17\x48\x3e\x1d\xdd\x4d\xbe\xa9\xe0\xee\x3e\x45\xec\xef\x3e\x29\x8f\x28\xbf\x29\x8f\x28\xbf\xc5\xe3\x10\x3e\xc5\xe3\x10\x3e\x5b\x8d\x0c\x3e\x68\xbc\xef\x3e\xc6\xab\xf1\x3e\x2e\x69\x6f\x3e\x2e\x69\x6f\x3e\x4b\x5f\xec\xbe\x4b\x5f\xec\xbe\xea\x13\xeb\x3e\xbc\x95\xf0\x3e\xcb\x91\xf0\x3e\xf7\x4a\xdf\x3e\xf5\x4a\xdf\x3e\xd9\xa0\x3a\x3f\xd9\xa0\x3a\x3f\xf3\x65\x3a\x3f\xa8\x6c\xf1\x3e\x52\xa6\xed\x3e\x84\x88\x26\xbf\x84\x88\x26\xbf\x0d\xf2\x69\xbf\x0d\xf2\x69\xbf\x56\x03\x6a\x3f\x26\x41\xf2\x3e\xbc\xd4\xe7\x3e\xd7\xe2\x40\x3e\xd7\xe2\x40\x3e\xf9\xfb\x7e\x3f\xf9\xfb\x7e\x3f\x52\x28\x7f\x3f\x36\x13\xf3\x3e\xee\x38\xe0\x3e\x30\x7d\xef\x3e\x30\x7d\xef\x3e\x4f\x92\x77\xbf\x4f\x92\x77\xbf\x2d\xa2\x77\x3f\xd6\xe2\xf3\x3e\xab\x12\xd6\x3e\xbb\x73\x23\xbf\xbb\x73\x23\xbf\x98\xb5\x54\x3f\x98\xb5\x54\x3f\xfb\x77\x54\x3f\x04\xb0\xf4\x3e\x28\x07\xca\x3e\x1e\x4e\x19\x3e\x1e\x4e\x19\x3e\xa6\x6b\x1a\xbf\xa6\x6b\x1a\xbf\x7b\xc1\x19\x3f\xc0\x7a\xf5\x3e\x9b\xff\xbb\x3e\xb3\xed\xfc\x3e\xb3\xed\xfc\x3e\x43\x89\x9e\x3e\x43\x89\x9e\x3e\x79\x4d\x9c\x3e\x09\x43\xf6\x3e\x87\x07\xac\x3e\xf9\x19\x22\xbf\xf9\x19\x22\xbf\xba\xd4\x8c\x3c\xba\xd4\x8c\x3c\x08\xb0\xbc\xbc\xdb\x08\xf7\x3e\xec\x94\x9a\x3e\x16\x58\x03\x3e\x16\x58\x03\x3e\xba\xc4\xae\xbe\xba\xc4\xae\xbe\x31\x37\xb2\xbe\x34\xcc\xf7\x3e\x67\x7a\x87\x3e\xb6\x22\x01\x3f\xb6\x22\x01\x3f\x59\xa3\x20\x3f\x59\xa3\x20\x3f\xd3\x66\x22\xbf\x16\x8d\xf8\x3e\xbe\x64\x66\x3e\x46\x91\x1f\xbf\x46\x91\x1f\xbf\xcf\x40\x58\xbf\xcf\x40\x58\xbf\x8f\xe1\x59\xbf\x7f\x4b\xf9\x3e\xd9\x98\x3b\x3e\x24\x30\xe3\x3d\x24\x30\xe3\x3d\xe6\x4c\x78\x3f\xe6\x4c\x78\x3f\x53\xab\x79\xbf\x6b\x07\xfa\x3e\xaa\xd1\x0e\x3e\x6d\x7e\x03\x3f\x6d\x7e\x03\x3f\x4b\x71\x7d\xbf\x4b\x71\x7d\xbf\x64\x82\x7e\xbf\xda\xc0\xfa\x3e\x63\x40\xc2\x3d\x8b\x70\x1f\xbf\x8b\x70\x1f\xbf\x14\x44\x67\x3f\x14\x44\x67\x3f\x4b\x11\x68\xbf\xca\x77\xfb\x3e\xd6\x10\x48\x3d\xd1\x9a\xdf\x3d\xd1\x9a\xdf\x3d\xc8\x4a\x38\xbf\xc8\x4a\x38\xbf\x6d\xec\x38\xbf\x3d\x2c\xfc\x3e\x42\x53\x3e\x3b\x6a\x6f\x03\x3f\x6b\x6f\x03\x3f\xf0\x58\xeb\x3e\xf0\x58\xeb\x3e\x27\x7f\xec\xbe\x2d\xde\xfc\x3e\x23\xbf\x31\xbd\x9f\x9a\x20\xbf\x9f\x9a\x20\xbf\xf7\x72\x1a\xbe\xf7\x72\x1a\xbe\x9e\xe2\x1c\xbe\x9c\x8d\xfd\x3e\x98\x59\xb6\xbd\xd4\x35\xfb\x3d\xd4\x35\xfb\x3d\x07\xc4\x31\xbe\x07\xc4\x31\xbe\x25\x08\x2f\x3e\x87\x3a\xfe\x3e\x19\xf7\x08\xbe\x6c\x38\x00\x3f\x6c\x38\x00\x3f\x45\x69\xf5\x3e\x45\x69\xf5\x3e\xec\xef\xf3\x3e\xee\xe4\xfe\x3e\x27\xa8\x35\xbe\x31\x85\x21\xbf\x30\x85\x21\xbf\xcf\x02\x3c\xbf\xcf\x02\x3c\xbf\xe4\x49\x3b\x3f\xd0\x8c\xff\x3e\xba\x35\x60\xbe\xc4\x4e\x12\x3e\xc4\x4e\x12\x3e\x4a\xa7\x69\x3f\x4a\xa7\x69\x3f\x15\x07\x69\x3f\x15\x19\x00\x3f\x5b\x7b\x84\xbe\x75\xf4\xf7\x3e\x75\xf4\xf7\x3e\xb9\x12\x7f\xbf\xb9\x12\x7f\xbf\x00\x99\x7e\x3f\x7f\x6a\x00\x3f\xcf\x72\x97\xbe\x07\xd1\x23\xbf\x07\xd1\x23\xbf\x62\x48\x7a\x3f\x62\x48\x7a\x3f\xf6\xf3\x79\x3f\xa5\xba\x00\x3f\x8f\x00\xa9\xbe\xd8\x39\x33\x3e\xd8\x39\x33\x3e\x7f\x03\x5c\xbf\x7f\x03\x5c\xbf\xb9\xc1\x5b\x3f\x86\x09\x01\x3f\x86\x05\xb9\xbe\xfe\xfb\xea\x3e\xfe\xfb\xea\x3e\xaa\x93\x27\x3f\xaa\x93\x27\x3f\x00\x44\x27\x3f\x22\x57\x01\x3f\x3d\x19\xc7\xbe\xe1\xa8\x26\xbf\xe1\xa8\x26\xbf\x4c\xf0\xc4\xbe\x4c\xf0\xc4\xbe\x81\xe9\xc3\x3e\x78\xa3\x01\x3f\xf8\x88\xd3\xbe\xda\xf2\x5f\x3e\xd8\xf2\x5f\x3e\x07\x3a\x9e\x3d\x07\x3a\x9e\x3d\x82\x74\x97\x3d\x87\xee\x01\x3f\xe3\xb8\xdd\xbe\xc9\x37\xd8\x3e\xc8\x37\xd8\x3e\x20\x36\x72\x3e\x20\x36\x72\x3e\x94\x3d\x77\xbe\x50\x38\x02\x3f\xbc\x03\xe6\xbe\xe1\x3c\x29\xbf\xe1\x3c\x29\xbf\xdf\x84\x06\xbf\xdf\x84\x06\xbf\x42\x32\x08\xbf\xd4\x80\x02\x3f\x7c\x10\xec\xbe\xa4\xfa\x8b\x3e\xa4\xfa\x8b\x3e\xca\xd5\x42\x3f\xca\xd5\x42\x3f\x6c\xe0\x44\xbf\x0e\xc8\x02\x3f\x85\xda\xef\xbe\x9e\x43\xbe\x3e\x9e\x43\xbe\x3e\x53\xa2\x6b\xbf\x53\xa2\x6b\xbf\x73\xf1\x6d\xbf\xff\x0d\x03\x3f\x16\x92\xf1\xbe\x9e\x70\x2a\xbf\x9e\x70\x2a\xbf\xf4\x05\x7d\x3f\xf4\x05\x7d\x3f\x01\x7d\x7f\xbf\xaa\x52\x03\x3f\x7a\xcc\xf0\xbe\x1a\x96\xab\x3e\x19\x96\xab\x3e\xb4\x70\x75\xbf\xb4\x70\x75\xbf\xc3\xf5\x77\xbf\x10\x96\x03\x3f\x50\x08\xee\xbe\x03\xbd\x9d\x3e\x03\xbd\x9d\x3e\xe1\xc7\x55\x3f\xe1\xc7\x55\x3f\xc7\x45\x58\xbf\x2a\xd8\x03\x3f\x50\xe5\xe8\xbe\x0a\xc8\x29\xbf\x0b\xc8\x29\xbf\xa1\x47\x21\xbf\xa1\x47\x21\xbf\x25\xad\x23\xbf\xf9\x18\x04\x3f\xb4\xa7\xe1\xbe\xcc\x06\xce\x3e\xcc\x06\xce\x3e\x17\x57\xba\x3e\x17\x57\xba\x3e\xe0\xcf\xbe\xbe\x7f\x58\x04\x3f\xbd\x72\xd8\xbe\x7c\x80\x6b\x3e\x7c\x80\x6b\x3e\xdd\x1e\x81\xbd\xdd\x1e\x81\xbd\x56\x19\x91\xbd\xbb\x96\x04\x3f\xd8\xfd\xcc\xbe\xff\x5d\x26\xbf\xff\x5d\x26\xbf\x44\x55\x79\xbe\x44\x55\x79\xbe\x99\xb3\x72\x3e\xad\xd3\x04\x3f\x31\x03\xc0\xbe\x87\x61\xf2\x3e\x88\x61\xf2\x3e\xa8\xb9\x06\x3f\xa8\xb9\x06\x3f\xd4\x86\x05\x3f\x56\x0f\x05\x3f\x52\xef\xb0\xbe\x22\xfc\x09\x3e\x24\xfc\x09\x3e\x77\x2e\x42\xbf\x77\x2e\x42\xbf\x05\x91\x41\x3f\xb4\x49\x05\x3f\x46\x81\xa0\xbe\x13\x35\x1e\xbf\x12\x35\x1e\xbf\x46\x29\x6b\x3f\x46\x29\x6b\x3f\x7a\x3b\x6b\x3f\xc9\x82\x05\x3f\xf0\x84\x8e\xbe\x42\xcd\x09\x3f\x42\xcd\x09\x3f\xd4\xee\x7d\xbf\xd4\xee\x7d\xbf\x34\xc0\x7e\x3f\x92\xba\x05\x3f\x83\x59\x76\xbe\x3f\x87\xf1\x3c\x4f\x87\xf1\x3c\xca\xe4\x78\x3f\xca\xe4\x78\x3f\x44\x76\x7a\x3f\x0f\xf1\x05\x3f\xe0\xf6\x4d\xbe\x6d\x5e\x12\xbf\x6d\x5e\x12\xbf\xb1\xad\x5c\xbf\xb1\xad\x5c\xbf\x59\xef\x5e\x3f\x41\x26\x06\x3f\xe0\xfc\x22\xbe\x7c\x39\x1a\x3f\x7c\x39\x1a\x3f\x37\x0f\x2c\x3f\x37\x0f\x2c\x3f\x6f\xe1\x2e\x3f\x27\x5a\x06\x3f\x60\x93\xee\xbd\xec\x77\xc5\xbd\xec\x77\xc5\xbd\x4a\x4f\xd7\xbe\x4a\x4f\xd7\xbe\xec\xbc\xdd\x3e\xc1\x8c\x06\x3f\xb4\x37\x94\xbd\x9c\xc7\xfc\xbe\x9c\xc7\xfc\xbe\x3a\xe0\x05\x3e\x3a\xe0\x05\x3e\xc5\x80\x13\x3e\x10\xbe\x06\x3f\xcc\xb6\xe2\xbc\xa3\x0c\x25\x3f\xa2\x0c\x25\x3f\x58\xb3\x2e\x3e\x58\xb3\x2e\x3e\xb6\x25\x21\xbe\x12\xee\x06\x3f\xfe\x3e\x89\x3c\xce\x5a\x67\xbe\xd0\x5a\x67\xbe\xe0\x8e\xe9\xbe\xe0\x8e\xe9\xbe\x9e\x36\xe3\xbe\xca\x1c\x07\x3f\x6c\xe6\x7d\x3d\xf1\x42\xc8\xbe\xf2\x42\xc8\xbe\xc6\x4c\x33\x3f\xc6\x4c\x33\x3f\xa8\x82\x30\xbf\x34\x4a\x07\x3f\xe5\xa8\xd7\x3d\x9a\x29\x2a\x3f\x99\x29\x2a\x3f\x5b\xbb\x61\xbf\x5b\xbb\x61\xbf\x9b\x70\x5f\xbf\x53\x76\x07\x3f\x68\x90\x18\x3e\x81\x20\xb7\xbe\x82\x20\xb7\xbe\x75\x12\x7c\x3f\x75\x12\x7c\x3f\x1a\x56\x7a\xbf\x26\xa1\x07\x3f\x9c\xc9\x42\x3e\x92\x24\x85\xbe\x94\x24\x85\xbe\x7d\x13\x80\xbf\x7d\x13\x80\xbf\x5d\xf7\x7e\xbf\xad\xca\x07\x3f\x8d\xb5\x6b\x3e\xc4\xbf\x26\x3f\xc3\xbf\x26\x3f\x47\xc9\x6d\x3f\x47\xc9\x6d\x3f\xc4\x16\x6d\xbf\xe8\xf2\x07\x3f\x30\x6d\x89\x3e\xfb\x60\xf5\xbe\xfb\x60\xf5\xbe\xea\xbf\x46\xbf\xea\xbf\x46\xbf\x91\x70\x46\xbf\xd7\x19\x08\x3f\xcc\x1d\x9b\x3e\x03\x78\xd8\xbd\x03\x78\xd8\xbd\x24\x97\x0e\x3f\x24\x97\x0e\x3f\xe2\x8c\x0e\xbf\xbc\x3c\x08\x3f\xdc\x7b\xac\x3e\xdb\xaa\x19\x3f\xdc\xaa\x19\x3f\x43\x96\x94\xbe\x43\x96\x94\xbe\x96\xd0\x94\xbe\x9a\x5b\x08\x3f\x73\xe7\xba\x3e\xe2\x14\x15\xbf\xe1\x14\x15\xbf\x8f\xa9\x33\xba\x8f\xa9\x33\xba\x77\x7d\x73\xb6\xda\x7d\x08\x3f\xba\x32\xc9\x3e\xbb\x7c\x8d\x3d\xbf\x7c\x8d\x3d\xa7\xcb\x94\x3e\xa7\xcb\x94\x3e\x19\x70\x94\x3e\x80\xa3\x08\x3f\xf2\x2e\xd4\x3e\xa5\xc1\x00\x3f\xa6\xc1\x00\x3f\xfc\x0b\x0e\xbf\xfc\x0b\x0e\xbf\xd2\xe5\x0d\x3f\xe4\xc6\x08\x3f\x3f\xa8\xde\x3e\x9b\xd2\x26\xbf\x9a\xd2\x26\xbf\x75\x6b\x45\x3f\x75\x6b\x45\x3f\xf1\x51\x45\x3f\x06\xe8\x08\x3f\x6f\x0b\xe6\x3e\xc6\x78\x82\x3e\xc8\x78\x82\x3e\xd9\xe8\x6b\xbf\xd9\xe8\x6b\xbf\xff\xe2\x6b\x3f\xae\x06\x09\x3f\xc0\x34\xec\x3e\xdf\x81\xb4\x3e\xe1\x81\xb4\x3e\x87\x61\x7e\x3f\x87\x61\x7e\x3f\xde\x7b\x7e\x3f\xd8\x22\x09\x3f\x09\xc5\xef\x3e\x85\xef\x29\xbf\x85\xef\x29\xbf\xb9\x6a\x7b\xbf\xb9\x6a\x7b\xbf\xa1\xb6\x7b\x3f\xb9\x3d\x09\x3f\x22\x86\xf1\x3e\x73\x8a\xd8\x3e\x73\x8a\xd8\x3e\xa7\x69\x63\x3f\xa7\x69\x63\x3f\x24\xf9\x63\x3f\x50\x57\x09\x3f\xf2\xfe\xf0\x3e\xc8\x2a\x2b\x3e\xc8\x2a\x2b\x3e\xd4\x85\x38\xbf\xd4\x85\x38\xbf\x9b\x64\x39\x3f\x9c\x6f\x09\x3f\x3f\x84\xee\x3e\x6b\x64\x1e\xbf\x6b\x64\x1e\xbf\x93\xe8\xfc\x3e\x93\xe8\xfc\x3e\xe2\x42\xff\x3e\x9f\x86\x09\x3f\x12\xc7\xe9\x3e\x91\x36\x10\x3f\x90\x36\x10\x3f\xf7\x85\x68\xbe\xf7\x85\x68\xbe\x7e\x29\x6e\x3e\x58\x9c\x09\x3f\xff\x3b\xe3\x3e\x7f\xeb\x4b\xbd\x8f\xeb\x4b\xbd\x0b\xe5\x6b\xbd\x0b\xe5\x6b\xbd\x5e\xcd\x53\xbd\xc6\xb0\x09\x3f\x9c\x79\xda\x3e\xfc\x9a\x00\xbf\xfd\x9a\x00\xbf\x3a\x5a\xac\x3e\x3a\x5a\xac\x3e\x2a\x83\xa9\xbe\xec\xc3\x09\x3f\x4f\x16\xd0\x3e\x5b\x8a\x25\x3f\x5a\x8a\x25\x3f\xf1\x63\x16\xbf\xf1\x63\x16\xbf\x73\x3e\x15\xbf\xc6\xd5\x09\x3f\xa1\xb9\xc3\x3e\xb4\x95\x89\xbe\xb7\x95\x89\xbe\x11\x4b\x4a\x3f\x11\x4b\x4a\x3f\x90\x92\x49\xbf\x58\xe6\x09\x3f\x8a\xbb\xb5\x3e\x03\x11\xa7\xbe\x05\x11\xa7\xbe\xff\xdd\x6d\xbf\xff\xdd\x6d\xbf\xa4\xa7\x6d\xbf\x9f\xf5\x09\x3f\xbe\x40\xa6\x3e\x69\x88\x29\x3f\x68\x88\x29\x3f\xbd\x76\x7e\x3f\xbd\x76\x7e\x3f\xfe\xc0\x7e\xbf\x9e\x03\x0a\x3f\xaf\x3d\x95\x3e\x54\x23\xf2\xbe\x55\x23\xf2\xbe\xd5\xf8\x7a\xbf\xd5\xf8\x7a\xbf\xd1\xab\x7b\xbf\x52\x10\x0a\x3f\xfe\x18\x83\x3e\xe3\xfe\xb6\xbd\xe2\xfe\xb6\xbd\x76\xdc\x63\x3f\x76\xdc\x63\x3f\x41\xd1\x64\xbf\xbf\x1b\x0a\x3f\x57\x86\x5f\x3e\x0b\x22\x14\x3f\x0c\x22\x14\x3f\xdc\x1a\x3b\xbf\xdc\x1a\x3b\xbf\xff\x23\x3c\xbf\xe2\x25\x0a\x3f\x79\xec\x36\x3e\xf6\x3c\x1c\xbf\xf5\x3c\x1c\xbf\xec\xff\x03\x3f\xec\xff\x03\x3f\x5a\xf2\x04\xbf\xbd\x2e\x0a\x3f\x61\x24\x0d\x3e\x7d\xd1\x25\x3e\x81\xd1\x25\x3e\xc9\xc7\x85\xbe\xc9\xc7\x85\xbe\xe5\x3c\x87\xbe\x4e\x36\x0a\x3f\x1f\x21\xc3\x3d\xe7\x03\xd4\x3e\xeb\x03\xd4\x3e\x9c\x55\x4b\xbc\x9c\x55\x4b\xbc\xf1\x35\x2f\x3c\x98\x3c\x0a\x3f\x33\x25\x58\x3d\x83\x93\x2b\xbf\x81\x93\x2b\xbf\x05\xad\x91\x3e\x05\xad\x91\x3e\x70\x66\x91\x3e\x9b\x41\x0a\x3f\x4f\x57\x14\x3c\x8b\x71\xd2\x3e\x8d\x71\xd2\x3e\xec\xd0\x08\xbf\xec\xd0\x08\xbf\x53\xf2\x08\x3f\x56\x45\x0a\x3f\x6a\xb7\x0b\xbd\x70\x93\x24\x3e\x74\x93\x24\x3e\x2d\x51\x3e\x3f\x2d\x51\x3e\x3f\x57\xa9\x3e\x3f\xca\x47\x0a\x3f\xba\x32\x9e\xbd\x21\xf4\x1a\xbf\x20\xf4\x1a\xbf\x2c\x63\x65\xbf\x2c\x63\x65\xbf\x15\xe2\x65\x3f\xf6\x48\x0a\x3f\x3f\x26\xf5\xbd\xce\xbd\x15\x3f\xcf\xbd\x15\x3f\xdb\x32\x7b\x3f\xdb\x32\x7b\x3f\xed\xca\x7b\x3f\xdb\x48\x0a\x3f\x48\x9f\x24\xbe\x97\xa9\xf2\xbd\x97\xa9\xf2\xbd\x68\x3e\x7e\xbf\x68\x3e\x7e\xbf\x47\xe7\x7e\x3f\x7a\x47\x0a\x3f\xd9\xd2\x4d\xbe\x77\x6e\xe0\xbe\x79\x6e\xe0\xbe\x12\x6e\x6e\x3f\x12\x6e\x6e\x3f\xcc\x24\x6f\x3f\xd4\x44\x0a\x3f\xbb\xb3\x74\xbe\x96\x5d\x2a\x3f\x95\x5d\x2a\x3f\xf9\x0f\x4d\xbf\xf9\x0f\x4d\xbf\x1f\xd5\x4d\x3f\xe8\x40\x0a\x3f\x92\xe9\x8c\xbe\x50\xa1\xc9\xbe\x52\xa1\xc9\xbe\xfb\xb7\x1c\x3f\xfb\xb7\x1c\x3f\xb6\x8e\x1d\x3f\xb8\x3b\x0a\x3f\xfa\x49\x9e\xbe\xc4\x47\x30\xbe\xca\x47\x30\xbe\xf8\x10\xc2\xbe\xf8\x10\xc2\xbe\x51\xe9\xc3\x3e\x42\x35\x0a\x3f\x2b\x20\xae\xbe\xbe\x6b\x1c\x3f\xbc\x6b\x1c\x3f\x43\x4b\xf3\x3d\x43\x4b\xf3\x3d\x95\x7b\xfb\x3d\x8a\x2d\x0a\x3f\x1d\xe2\xbc\xbe\xf4\x73\x19\xbf\xf5\x73\x19\xbf\xd5\x33\x19\x3e\xd5\x33\x19\x3e\xec\xa7\x14\xbe\x8c\x24\x0a\x3f\x9a\x8e\xc9\xbe\xe2\xa9\x18\x3e\xde\xa9\x18\x3e\xb5\x59\xd0\xbe\xb5\x59\xd0\xbe\xda\xd5\xcd\xbe\x4b\x1a\x0a\x3f\xde\x08\xd5\xbe\xfd\x65\xd0\x3e\xfc\x65\xd0\x3e\x4d\x8d\x22\x3f\x4d\x8d\x22\x3f\x11\x2c\x21\xbf\xc7\x0e\x0a\x3f\x35\x5f\xde\xbe\xa9\x95\x29\xbf\xa9\x95\x29\xbf\x28\x5d\x51\xbf\x28\x5d\x51\xbf\x00\xde\x4f\xbf\x01\x02\x0a\x3f\xa5\x0d\xe6\xbe\x22\x14\xde\x3e\x22\x14\xde\x3e\xc1\x68\x71\x3f\xc1\x68\x71\x3f\x80\xd0\x6f\xbf\xfa\xf3\x09\x3f\x72\xdd\xeb\xbe\x8e\xf7\xe1\x3d\x96\xf7\xe1\x3d\xe7\x47\x80\xbf\xe7\x47\x80\xbf\xdc\xe6\x7e\xbf\xb2\xe4\x09\x3f\xc6\x7b\xef\xbe\xbc\x78\x13\xbf\xbb\x78\x13\xbf\x5e\xe7\x7d\x3f\x5e\xe7\x7d\x3f\xfc\x38\x7c\xbf\x29\xd4\x09\x3f\xde\x7a\xf1\xbe\x89\x7b\x21\x3f\x8a\x7b\x21\x3f\xf8\xc4\x69\xbf\xf8\xc4\x69\xbf\x73\x1d\x68\xbf\x60\xc2\x09\x3f\x75\x2b\xf1\xbe\x75\x0c\x74\xbe\x71\x0c\x74\xbe\x78\xb2\x45\x3f\x78\xb2\x45\x3f\x9d\x1d\x44\xbf\x57\xaf\x09\x3f\xab\x18\xef\xbe\xd4\x0b\xa4\xbe\xd0\x0b\xa4\xbe\x11\x4d\x14\xbf\x11\x4d\x14\xbf\x3e\xd3\x12\xbf\x0e\x9b\x09\x3f\x48\x10\xeb\xbe\x21\x7e\x26\x3f\x22\x7e\x26\x3f\x63\x24\xb2\x3e\x63\x24\xb2\x3e\xe9\x6a\xaf\xbe\x88\x85\x09\x3f\x52\xdf\xe4\xbe\x50\x5d\x05\xbf\x4f\x5d\x05\xbf\x8b\xe5\xc0\xbd\x8b\xe5\xc0\xbd\xb3\xbc\xb6\xbd\xc3\x6e\x09\x3f\x98\x4d\xdd\xbe\xbc\x9f\xcf\x3c\xcc\x9f\xcf\x3c\xe9\x9c\x28\xbe\xe9\x9c\x28\xbe\x3a\x7b\x2d\x3e\xc3\x56\x09\x3f\x8b\x54\xd3\xbe\xef\x80\xfa\x3e\xf0\x80\xfa\x3e\xa6\x95\xd2\x3e\xa6\x95\xd2\x3e\xc8\xff\xd4\x3e\x86\x3d\x09\x3f\x78\x3e\xc8\xbe\x8c\x75\x2a\xbf\x8c\x75\x2a\xbf\x4a\x27\x21\xbf\x4a\x27\x21\xbf\x40\x62\x22\x3f\x0e\x23\x09\x3f\xd1\x1f\xbb\xbe\xde\xbb\xc4\x3e\xdc\xbb\xc4\x3e\x32\x23\x4e\x3f\x32\x23\x4e\x3f\xe4\x66\x4f\x3f\x5a\x07\x09\x3f\x43\xb7\xac\xbe\xe1\x3d\x23\x3e\xdd\x3d\x23\x3e\x14\x6b\x6d\xbf\x14\x6b\x6d\xbf\x4e\xb1\x6e\x3f\x6c\xea\x08\x3f\x3c\xf2\x9c\xbe\x8b\x65\x17\xbf\x8c\x65\x17\xbf\x4a\x1a\x7d\x3f\x4a\x1a\x7d\x3f\x99\x55\x7e\x3f\x44\xcc\x08\x3f\xfe\xac\x8b\xbe\x07\x44\x1e\x3f\x06\x44\x1e\x3f\x8a\x53\x7c\xbf\x8a\x53\x7c\xbf\x95\x72\x7d\x3f\xe4\xac\x08\x3f\x47\x6e\x73\xbe\x9b\x0b\x66\xbe\x9f\x0b\x66\xbe\xba\x49\x6b\x3f\xba\x49\x6b\x3f\xb9\x3c\x6c\x3f\x4b\x8c\x08\x3f\xb1\xd1\x4c\xbe\xaa\x63\xa4\xbe\xac\x63\xa4\xbe\x28\x37\x4b\xbf\x28\x37\x4b\xbf\x4c\xf4\x4b\x3f\x7c\x6a\x08\x3f\x13\xf2\x24\xbe\x8d\xfc\x26\x3f\x8c\xfc\x26\x3f\x73\x44\x1e\x3f\x73\x44\x1e\x3f\xc4\xca\x1e\x3f\x74\x47\x08\x3f\xa2\x1e\xf8\xbd\x9d\xc3\x0c\xbf\x9d\xc3\x0c\xbf\x30\xc5\xce\xbe\x30\xc5\xce\xbe\xff\x72\xcf\x3e\x38\x23\x08\x3f\x3d\xa7\xa2\xbd\x7c\x90\xad\x3d\x7c\x90\xad\x3d\x99\x63\x28\x3e\x99\x63\x28\x3e\x0c\x39\x29\x3e\xc8\xfd\x07\x3f\xc2\xdd\x1d\xbd\xa4\x3e\xde\x3e\xa4\x3e\xde\x3e\x61\xa3\xad\x3d\x61\xa3\xad\x3d\x25\x8f\xac\xbd\x23\xd7\x07\x3f\x21\x4b\x91\x3b\x49\x92\x2a\xbf\x48\x92\x2a\xbf\xfb\x09\xa8\xbe\xfb\x09\xa8\xbe\x1d\xd4\xa7\xbe\x4c\xaf\x07\x3f\x0a\x6e\x3a\x3d\xd2\xda\xec\x3e\xd4\xda\xec\x3e\xf4\xfc\x0c\x3f\xf4\xfc\x0c\x3f\x48\xe5\x0c\xbf\x41\x86\x07\x3f\xaa\x42\xb3\x3d\x97\xda\x28\x3d\xa7\xda\x28\x3d\x46\x22\x3d\xbf\x46\x22\x3d\xbf\xc8\x10\x3d\xbf\x04\x5c\x07\x3f\x5a\x4e\x03\x3e\x9a\x2f\x04\xbf\x9a\x2f\x04\xbf\xc9\x93\x61\x3f\xc9\x93\x61\x3f\xf2\x90\x61\xbf\x97\x30\x07\x3f\xdb\xbf\x2b\x3e\x0c\xdc\x27\x3f\x0e\xdc\x27\x3f\xbe\x35\x78\xbf\xbe\x35\x78\xbf\xb9\x49\x78\xbf\xfb\x03\x07\x3f\x80\xad\x53\x3e\x18\x29\xbe\xbe\x17\x29\xbe\xbe\xc9\xce\x7f\x3f\xc9\xce\x7f\x3f\xb2\xfc\x7f\xbf\x30\xd6\x06\x3f\x5b\x65\x78\x3e\x1a\xc5\x1b\xbe\x18\xc5\x1b\xbe\x4d\x12\x78\xbf\x4d\x12\x78\xbf\x35\x56\x78\xbf\x36\xa7\x06\x3f\xd9\x82\x8e\x3e\xa3\x85\x14\x3f\xa4\x85\x14\x3f\x9e\xa1\x61\x3f\x9e\xa1\x61\x3f\x88\xef\x61\xbf\x10\x77\x06\x3f\x84\xb3\x9e\x3e\xfb\x8a\x24\xbf\xfb\x8a\x24\xbf\xd2\xf8\x3d\xbf\xd2\xf8\x3d\xbf\x36\x40\x3e\xbf\xbd\x45\x06\x3f\x30\x96\xae\x3e\x98\x6d\x9b\x3e\x96\x6d\x9b\x3e\x31\x51\x0f\x3f\x31\x51\x0f\x3f\x5d\x81\x0f\xbf\x40\x13\x06\x3f\xc3\x5b\xbc\x3e\x3c\x34\x63\x3e\x3c\x34\x63\x3e\x87\xf6\xb0\xbe\x87\xf6\xb0\xbe\x8d\x11\xb1\xbe\x99\xdf\x05\x3f\x36\x01\xc9\x3e\xde\x0c\x1b\xbf\xde\x0c\x1b\xbf\x10\x9b\xe5\x3d\x10\x9b\xe5\x3d\x94\xd3\xe4\xbd\xc9\xaa\x05\x3f\x62\x0c\xd4\x3e\xac\xab\x1c\x3f\xab\xab\x1c\x3f\x35\x3f\x02\x3e\x35\x3f\x02\x3e\x0a\x28\x03\x3e\xd0\x74\x05\x3f\x57\x5b\xdd\x3e\xa9\xea\x75\xbe\xab\xea\x75\xbe\x11\x9d\xb7\xbe\x11\x9d\xb7\xbe\x8d\x3a\xb8\x3e\xb2\x3d\x05\x3f\x33\x0f\xe5\x3e\xea\x16\x8f\xbe\xea\x16\x8f\xbe\x83\xb0\x11\x3f\x83\xb0\x11\x3f\x2f\x04\x12\x3f\x6c\x05\x05\x3f\x6e\xe3\xea\x3e\x71\x1d\x21\x3f\x71\x1d\x21\x3f\x4e\x34\x3f\xbf\x4e\x34\x3f\xbf\x6d\x7f\x3f\x3f\x02\xcc\x04\x3f\x5a\xd7\xee\x3e\x9f\x54\x19\xbf\x9f\x54\x19\xbf\x5a\xd9\x61\x3f\x5a\xd9\x61\x3f\xde\x14\x62\x3f\x74\x91\x04\x3f\xf0\x3a\xf1\x3e\x19\x56\x56\x3e\x19\x56\x56\x3e\x2b\xc4\x77\xbf\x2b\xc4\x77\xbf\x54\xef\x77\x3f\xc3\x55\x04\x3f\x3e\x62\xf1\x3e\x56\x5f\x9b\x3e\x56\x5f\x9b\x3e\xe3\xd5\x7f\x3f\xe3\xd5\x7f\x3f\x6b\xf6\x7f\x3f\xf0\x18\x04\x3f\x06\x15\xf0\x3e\x1e\x0b\x22\xbf\x1e\x0b\x22\xbf\x43\xba\x79\xbf\x43\xba\x79\xbf\x16\xdb\x79\x3f\xfe\xda\x03\x3f\x5b\x93\xec\x3e\x84\xb0\x15\x3f\x84\xb0\x15\x3f\x44\xe8\x65\x3f\x44\xe8\x65\x3f\x86\x16\x66\x3f\xea\x9b\x03\x3f\xef\x83\xe7\x3e\x7a\x32\x42\xbe\x7b\x32\x42\xbe\xe0\x97\x45\xbf\xe0\x97\x45\xbf\xe7\xde\x45\x3f\xba\x5b\x03\x3f\x31\xb2\xe0\x3e\x24\xaa\xa2\xbe\x25\xaa\xa2\xbe\x20\xa9\x1a\x3f\x20\xa9\x1a\x3f\x56\x11\x1b\x3f\x6d\x1a\x03\x3f\x99\xf3\xd7\x3e\xe6\xc6\x23\x3f\xe6\xc6\x23\x3f\x6e\x0c\xcf\xbe\x6e\x0c\xcf\xbe\xad\x2a\xd0\x3e\x03\xd8\x02\x3f\xac\xde\xcd\x3e\x56\x43\x17\xbf\x57\x43\x17\xbf\x57\xfa\x3b\x3e\x57\xfa\x3b\x3e\xd8\xe0\x3e\x3e\x7d\x94\x02\x3f\xc5\xf8\xc1\x3e\x95\x01\x4f\x3e\x91\x01\x4f\x3e\x11\x18\x3e\x3d\x11\x18\x3e\x3d\xd6\xc7\x2f\xbd\xdf\x4f\x02\x3f\xfd\xda\xb4\x3e\x30\xfb\x99\x3e\x30\xfb\x99\x3e\x3b\xf9\x8b\xbe\x3b\xf9\x8b\xbe\xce\xd9\x89\xbe\x28\x0a\x02\x3f\x81\x3f\xa6\x3e\xcb\x47\x21\xbf\xcb\x47\x21\xbf\xfb\x98\xf8\x3e\xfb\x98\xf8\x3e\x3a\x27\xf6\xbe\x5a\xc3\x01\x3f\x01\x52\x96\x3e\xd8\x7e\x19\x3f\xd9\x7e\x19\x3f\xf6\x08\x2c\xbf\xf6\x08\x2c\xbf\xa7\xa9\x2a\xbf\x75\x7b\x01\x3f\x3f\x92\x85\x3e\x45\x73\x6a\xbe\x44\x73\x6a\xbe\x60\xcb\x52\x3f\x60\xcb\x52\x3f\x2d\x4a\x51\xbf\x7b\x32\x01\x3f\xf0\xf0\x66\x3e\x74\xe0\x8a\xbe\x70\xe0\x8a\xbe\x07\xad\x6e\xbf\x07\xad\x6e\xbf\xc2\x10\x6d\xbf\x6e\xe8\x00\x3f\xba\xb0\x41\x3e\xe7\xc4\x1e\x3f\xe9\xc4\x1e\x3f\x71\x5c\x7e\x3f\x71\x5c\x7e\x3f\x91\xae\x7c\xbf\x4f\x9d\x00\x3f\x88\x94\x1a\x3e\xc4\xf8\x1f\xbf\xc3\xf8\x1f\xbf\xe4\x95\x80\xbf\xe4\x95\x80\xbf\xe2\x77\x7f\xbf\x1e\x51\x00\x3f\x48\x05\xe5\x3d\x17\x5a\x92\x3e\x1a\x5a\x92\x3e\xda\x15\x77\x3f\xda\x15\x77\x3f\x13\x6a\x75\xbf\xde\x03\x00\x3f\x82\x9c\x93\x3d\x23\xee\x53\x3e\x25\xee\x53\x3e\x53\xbb\x60\xbf\x53\xbb\x60\xbf\x1f\x28\x5f\xbf\x1e\x6b\xff\x3e\x33\x65\x00\x3d\xfc\x19\x15\xbf\xfb\x19\x15\xbf\x84\x55\x3f\x3f\x84\x55\x3f\x3f\xee\xec\x3d\xbf\x68\xcc\xfe\x3e\xc9\xde\x11\xbc\xf4\x4a\x23\x3f\xf5\x4a\x23\x3f\xf9\xa3\x14\xbf\xf9\xa3\x14\xbf\x1a\x78\x13\xbf\x98\x2b\xfe\x3e\x97\x7f\x4b\xbd\x4a\x54\xb1\xbe\x49\x54\xb1\xbe\x66\xa6\xc5\x3e\x66\xa6\xc5\x3e\x99\xe9\xc3\xbe\xb4\x88\xfd\x3e\x6e\xa7\xb7\xbd\x94\x12\x08\xbe\x96\x12\x08\xbe\xd1\x80\x31\xbe\xd1\x80\x31\xbe\xe8\x72\x2f\xbe\xbc\xe3\xfc\x3e\x06\x28\x04\xbe\x38\xef\x0a\x3f\x36\xef\x0a\x3f\xeb\x80\x40\xbd\xeb\x80\x40\xbd\x91\x8f\x42\x3d\xb5\x3c\xfc\x3e\xc8\xa4\x2b\xbe\xd3\x83\x2a\xbf\xd5\x83\x2a\xbf\x89\x54\x87\x3e\x89\x54\x87\x3e\xb6\xd2\x86\x3e\xa1\x93\xfb\x3e\x8c\x70\x51\xbe\x5b\x5c\xe1\x3e\x57\x5c\xe1\x3e\x13\xbe\xef\xbe\x13\xbe\xef\xbe\xb7\x8c\xee\x3e\x82\xe8\xfa\x3e\xe7\x2c\x76\xbe\x5b\x6d\x5c\x3c\xcb\x6c\x5c\x3c\xa1\x33\x26\x3f\xa1\x33\x26\x3f\xc1\x55\x25\x3f\x59\x3b\xfa\x3e\x7a\x51\x8c\xbe\x12\x87\xe9\xbe\x16\x87\xe9\xbe\xd5\x87\x4c\xbf\xd5\x87\x4c\xbf\x22\x7d\x4b\x3f\x30\x8c\xf9\x3e\x1e\x9c\x9c\xbe\x66\x84\x28\x3f\x63\x84\x28\x3f\x60\x28\x69\x3f\x60\x28\x69\x3f\x7f\x0a\x68\x3f\x07\xdb\xf8\x3e\x82\xc4\xab\xbe\xa1\x7b\x04\xbf\xa3\x7b\x04\xbf\x8e\xe0\x7a\xbf\x8e\xe0\x7a\xbf\xbc\xc5\x79\x3f\xde\x27\xf8\x3e\xc4\x84\xb9\xbe\x4f\x5e\xde\x3d\x4b\x5e\xde\x3d\x89\x82\x80\x3f\x89\x82\x80\x3f\x76\xfb\x7f\x3f\xb3\x72\xf7\x3e\xbd\x2c\xc6\xbe\x05\x5b\xb7\x3e\x04\x5b\xb7\x3e\x70\x76\x7b\xbf\x70\x76\x7b\xbf\xfc\x82\x7a\x3f\x90\xbb\xf6\x3e\x57\x11\xd1\xbe\x4d\x48\x25\xbf\x4c\x48\x25\xbf\xb0\x9d\x6a\x3f\xb0\x9d\x6a\x3f\x1a\xbc\x69\x3f\x75\x02\xf6\x3e\x8d\xa9\xda\xbe\xb2\x53\x1c\x3f\xb5\x53\x1c\x3f\x6e\x60\x4f\xbf\x6e\x60\x4f\xbf\xc4\x87\x4e\x3f\x68\x47\xf5\x3e\xe9\x89\xe2\xbe\x37\x02\x8c\xbe\x31\x02\x8c\xbe\x13\x12\x2b\x3f\x13\x12\x2b\x3f\x15\x39\x2a\x3f\x6b\x8a\xf4\x3e\x97\xe6\xe8\xbe\x41\x03\x48\xbe\x35\x03\x48\xbe\xaf\xc4\xfe\xbe\xaf\xc4\xfe\xbe\xc7\x08\xfd\x3e\x82\xcb\xf3\x3e\x1e\x81\xed\xbe\x87\x08\x10\x3f\x8b\x08\x10\x3f\xa1\x93\x9c\x3e\xa1\x93\x9c\x3e\xaa\xd1\x9a\x3e\xad\x0a\xf3\x3e\x54\x52\xf0\xbe\x79\x16\x26\xbf\x75\x16\x26\xbf\x4f\x99\xcf\xbd\x4f\x99\xcf\xbd\x72\xd1\xc8\x3d\xf2\x47\xf2\x3e\xc8\x8b\xf1\xbe\xf0\x08\xd4\x3e\xf6\x08\xd4\x3e\xc1\xe1\xda\xbd\xc1\xe1\xda\xbd\xba\xd9\xe0\xbd\x4f\x83\xf1\x3e\x39\x05\xf1\xbe\xc3\x2a\xcc\x3c\x03\x2b\xcc\x3c\x5c\xb6\x9e\x3e\x5c\xb6\x9e\x3e\x18\xd6\x9f\xbe\xcc\xbc\xf0\x3e\x96\xb1\xee\xbe\x02\xc1\xe8\xbe\xfe\xc0\xe8\xbe\x82\xac\xff\xbe\x82\xac\xff\xbe\x93\x22\x00\xbf\x69\xf4\xef\x3e\xbd\xbc\xea\xbe\xa1\x1c\x2b\x3f\xa1\x1c\x2b\x3f\xd5\xc7\x2a\x3f\xd5\xc7\x2a\x3f\xd1\xbf\x2a\xbf\x2b\x2a\xef\x3e\x02\x0a\xe5\xbe\x1a\xdd\x10\xbf\x1c\xdd\x10\xbf\x60\x6e\x4e\xbf\x60\x6e\x4e\xbf\xa3\x06\x4e\xbf\x12\x5e\xee\x3e\xe0\xeb\xdd\xbe\x49\xe7\x4a\x3e\x3f\xe7\x4a\x3e\x83\x5d\x69\x3f\x83\x5d\x69\x3f\xc3\x92\x68\xbf\x27\x90\xed\x3e\xad\xe6\xd4\xbe\x8d\xf1\x84\x3e\x84\xf1\x84\x3e\x85\x8d\x7a\xbf\x85\x8d\x7a\xbf\x11\x64\x79\xbf\x68\xc0\xec\x3e\x00\xb7\xca\xbe\xb1\xc7\x17\xbf\xb6\xc7\x17\xbf\xd2\xb1\x80\x3f\xd2\xb1\x80\x3f\xa3\xe5\x7f\xbf\xdc\xee\xeb\x3e\x38\xcd\xbe\xbe\x33\xe0\x25\x3f\x2e\xe0\x25\x3f\xc4\xb5\x7d\xbf\xc4\xb5\x7d\xbf\xe2\xf1\x7b\xbf\x83\x1b\xeb\x3e\xad\x00\xb2\xbe\xe3\xca\xcd\xbe\xed\xca\xcd\xbe\x9c\xc7\x6f\x3f\x9c\xc7\x6f\x3f\x3d\xd0\x6d\xbf\x62\x46\xea\x3e\x01\x58\xa3\xbe\xae\xd1\xf1\xbc\x2e\xd2\xf1\xbc\x34\x45\x58\xbf\x34\x45\x58\xbf\xc3\x2f\x56\xbf\x7c\x6f\xe9\x3e\xda\x24\x94\xbe\xaf\x74\xe5\x3e\xaa\x74\xe5\x3e\xca\x3a\x38\x3f\xca\x3a\x38\x3f\xba\x1c\x36\xbf\xd4\x96\xe8\x3e\x2e\x75\x83\xbe\xdd\x0f\x2a\xbf\xdf\x0f\x2a\xbf\x6b\x06\x11\xbf\x6b\x06\x11\xbf\x73\xf4\x0e\xbf\x6a\xbc\xe7\x3e\xde\x87\x64\xbe\xfd\x0c\x15\x3f\xfd\x0c\x15\x3f\x9b\x90\xc8\x3e\x9b\x90\xc8\x3e\xf7\xa9\xc4\xbe\xb8\xdb\xe6\x3e\xbe\x0c\x40\xbe\x11\x4a\x77\xbe\x0b\x4a\x77\xbe\x86\x41\x4f\xbe\x86\x41\x4f\xbe\xce\x2b\x48\xbe\xbc\xf4\xe5\x3e\x0e\xfe\x19\xbe\x04\xb2\x50\xbe\xf6\xb1\x50\xbe\x73\x8a\xc5\x3b\x73\x8a\xc5\x3b\x5c\xf0\xbd\x36\xdf\x14\xe5\x3e\x62\x9a\xe8\xbd\xe1\x79\x0e\x3f\xe6\x79\x0e\x3f\xc3\x47\x42\x3e\xc3\x47\x42\x3e\x0d\x66\x47\x3e\x20\x3c\xe4\x3e\x3b\x51\x97\xbd\x8c\x05\x2a\xbf\x86\x05\x2a\xbf\x0b\x34\xc1\xbe\x0b\x34\xc1\xbe\x11\x36\xc3\x3e\x66\x5e\xe3\x3e\xdb\x80\x13\xbd\x5b\x4f\xf7\x3e\x67\x4f\xf7\x3e\x9d\xbe\x0c\x3f\x9d\xbe\x0c\x3f\xf1\x7c\x0d\x3f\xb2\x7b\xe2\x3e\xee\xa6\x8b\x3b\x41\x83\xc1\xbd\x11\x83\xc1\xbd\xd7\x61\x33\xbf\xd7\x61\x33\xbf\xa8\xe4\x33\x3f\x1b\x96\xe1\x3e\xc1\x2b\x2d\x3d\x9b\x4f\xaa\xbe\x92\x4f\xaa\xbe\x60\x25\x53\x3f\x60\x25\x53\x3f\x85\x75\x53\x3f\xa2\xad\xe0\x3e\x95\x6a\xa8\x3d\x76\xa1\x1d\x3f\x79\xa1\x1d\x3f\x02\xf3\x6a\xbf\x02\xf3\x6a\xbf\x82\x1b\x6b\x3f\x8d\xc3\xdf\x3e\x1f\xc9\xf4\x3d\x0d\xcc\x22\xbf\x0b\xcc\x22\xbf\xbc\x04\x7a\x3f\xbc\x04\x7a\x3f\xc2\x10\x7a\x3f\xdb\xd7\xde\x3e\xb7\x2c\x21\x3e\x3b\xe4\xc5\x3e\x3a\xe4\xc5\x3e\xaa\xeb\x7f\xbf\xaa\xeb\x7f\xbf\x0f\xe5\x7f\x3f\x93\xea\xdd\x3e\x97\xfe\x45\x3e\xf3\x6f\xd4\x3c\x9b\x6f\xd4\x3c\x96\x90\x7c\x3f\x96\x90\x7c\x3f\xa4\x7d\x7c\x3f\xb6\xfb\xdc\x3e\x60\xef\x69\x3e\xab\x1c\xdb\xbe\xb4\x1c\xdb\xbe\x4a\x32\x70\xbf\x4a\x32\x70\xbf\xc1\x15\x70\x3f\x4a\x0b\xdc\x3e\xe6\xf8\x85\x3e\xcb\x37\x27\x3f\xc5\x37\x27\x3f\x65\x5f\x5b\x3f\x65\x5f\x5b\x3f\xa4\x38\x5b\x3f\x4e\x19\xdb\x3e\xb2\x07\x96\x3e\xef\x7e\x1c\xbf\xf6\x7e\x1c\xbf\x84\xef\x3e\xbf\x84\xef\x3e\xbf\x9b\xbb\x3e\x3f\xca\x25\xda\x3e\x09\x2f\xa5\x3e\x7d\x0c\xa5\x3e\x6f\x0c\xa5\x3e\xb3\xf9\x1b\x3f\xb3\xf9\x1b\x3f\x0c\xb5\x1b\x3f\xbc\x30\xd9\x3e\xff\x2d\xb3\x3e\xa8\xc1\xc1\x3d\x70\xc1\xc1\x3d\x57\x8f\xe7\xbe\x57\x8f\xe7\xbe\x5f\xe1\xe6\x3e\x2c\x3a\xd8\x3e\x3a\xb6\xbf\x3e\x55\x84\xf1\xbe\x61\x84\xf1\xbe\xed\x93\x8f\x3e\xed\x93\x8f\x3e\xe7\xc2\x8e\x3e\x18\x42\xd7\x3e\xc2\x4e\xcb\x3e\x2e\xdd\x28\x3f\x2a\xdd\x28\x3f\x0b\x57\xcc\xbd\x0b\x57\xcc\xbd\xfb\xa1\xc8\x3d\x8a\x48\xd6\x3e\x61\x3c\xd5\x3e\xd6\x1d\x16\xbf\xd8\x1d\x16\xbf\x98\xf4\xaa\xbd\x98\xf4\xaa\xbd\xba\xff\xae\xbd\x82\x4d\xd5\x3e\x06\xea\xdd\x3e\xdb\x37\x91\x3e\xdd\x37\x91\x3e\xec\xbc\x86\x3e\xec\xbc\x86\x3e\x63\xcc\x87\xbe\x02\x51\xd4\x3e\xd4\xd0\xe4\x3e\xdf\x89\x03\x3e\xed\x89\x03\x3e\x2a\xdf\xdd\xbe\x2a\xdf\xdd\xbe\xbb\xf5\xde\xbe\x0e\x53\xd3\x3e\x32\x89\xea\x3e\xe6\x9c\xfa\xbe\xdc\x9c\xfa\xbe\x22\xa9\x16\x3f\x22\xa9\x16\x3f\x1f\x37\x17\xbf\xab\x53\xd2\x3e\x87\x70\xee\x3e\xec\x3a\x29\x3f\xf4\x3a\x29\x3f\x6f\x49\x39\xbf\x6f\x49\x39\xbf\xd7\xdb\x39\xbf\xda\x52\xd1\x3e\x66\xc8\xf0\x3e\x6d\x4f\x14\xbf\x64\x4f\x14\xbf\x42\xc1\x55\x3f\x42\xc1\x55\x3f\xc7\x59\x56\xbf\xa2\x50\xd0\x3e\xc0\x85\xf1\x3e\xc8\x46\x8e\x3e\xd8\x46\x8e\x3e\x1d\x3a\x6b\xbf\x1d\x3a\x6b\xbf\xda\xda\x6b\xbf\x04\x4d\xcf\x3e\xd2\xbf\xf0\x3e\x78\x98\x02\x3e\x9e\x98\x02\x3e\x49\x1c\x79\x3f\x49\x1c\x79\x3f\x64\xc5\x79\xbf\x04\x48\xce\x3e\xcb\x40\xee\x3e\xa2\x3d\xf8\xbe\x95\x3d\xf8\xbe\x1f\x11\x7f\xbf\x1f\x11\x7f\xbf\x52\xc1\x7f\xbf\xa3\x41\xcd\x3e\x8d\x3b\xea\x3e\x5c\xa9\x29\x3f\x60\xa9\x29\x3f\x40\x04\x7d\x3f\x40\x04\x7d\x3f\x3a\xb8\x7d\xbf\xe9\x39\xcc\x3e\x54\x9d\xe4\x3e\x38\x1a\x19\xbf\x37\x1a\x19\xbf\xc6\x20\x73\xbf\xc6\x20\x73\xbf\x71\xd4\x73\xbf\xd4\x30\xcb\x3e\x76\x9c\xdd\x3e\x6c\x34\xa2\x3e\x6a\x34\xa2\x3e\x37\xce\x61\x3f\x37\xce\x61\x3f\x7f\x7e\x62\xbf\x6e\x26\xca\x3e\x91\x05\xd5\x3e\x2d\x14\x9e\x3d\x0d\x14\x9e\x3d\x4f\xac\x49\xbf\x4f\xac\x49\xbf\x34\x57\x4a\xbf\xb5\x1a\xc9\x3e\x06\x23\xcb\x3e\xec\xf1\xe1\xbe\xf9\xf1\xe1\xbe\x36\x8c\x2b\x3f\x36\x8c\x2b\x3f\xaf\x30\x2c\xbf\xb1\x0d\xc8\x3e\x27\xcb\xbf\x3e\x77\x4c\x25\x3f\x6f\x4c\x25\x3f\xb9\x68\x08\xbf\xb9\x68\x08\xbf\x89\x06\x09\xbf\x61\xff\xc6\x3e\xbf\x60\xb3\x3e\xbc\xac\x1e\xbf\xc6\xac\x1e\xbf\x0b\xbb\xc2\x3e\x0b\xbb\xc2\x3e\xb5\xe9\xc3\xbe\xcd\xef\xc5\x3e\xd8\xa6\xa5\x3e\x0d\x67\xc0\x3e\xf9\x66\xc0\x3e\xa8\x77\x5e\xbe\xa8\x77\x5e\xbe\x3b\xbd\x60\xbe\xf4\xde\xc4\x3e\x39\xff\x96\x3e\x9e\x6b\xb5\xba\x9e\x7b\xb5\xba\xb8\x9f\x46\x3d\xb8\x9f\x46\x3d\x9b\x62\x4f\xbd\xde\xcc\xc3\x3e\x06\x2a\x87\x3e\x0b\x08\xbf\xbe\x19\x08\xbf\xbe\xeb\xd6\xf7\x3d\xeb\xd6\xf7\x3d\xe0\x93\xf3\x3d\x8c\xb9\xc2\x3e\x5d\x4d\x6d\x3e\x94\x9e\x1e\x3f\x90\x9e\x1e\x3f\xe7\xa5\x92\xbe\xe7\xa5\x92\xbe\xd1\x97\x91\x3e\x02\xa5\xc1\x3e\xa2\xb7\x4a\x3e\x85\xb2\x27\xbf\x86\xb2\x27\xbf\xf0\xdd\xe2\x3e\xf0\xdd\xe2\x3e\xa2\xca\xe1\x3e\x43\x8f\xc0\x3e\x5f\xbe\x26\x3e\x7b\x43\xf0\x3e\x7f\x43\xf0\x3e\x99\x35\x16\xbf\x99\x35\x16\xbf\x74\xa4\x15\x3f\x55\x78\xbf\x3e\xdf\xac\x01\x3e\x98\x44\x02\xbe\x86\x44\x02\xbe\x58\xab\x36\x3f\x58\xab\x36\x3f\x63\x0e\x36\x3f\x3a\x60\xbe\x3e\xef\xb6\xb7\x3d\x2b\xc2\x82\xbe\x1b\xc2\x82\xbe\xd4\xf7\x51\xbf\xd4\xf7\x51\xbf\xd2\x4c\x51\x3f\xf6\x46\xbd\x3e\x66\xa0\x56\x3d\xfb\x73\x0d\x3f\x05\x74\x0d\x3f\x61\x6b\x67\x3f\x61\x6b\x67\x3f\x62\xb2\x66\x3f\x89\x2c\xbc\x3e\x4f\x82\x70\x3c\x59\x3d\x2b\xbf\x4e\x3d\x2b\xbf\x98\x82\x76\xbf\x98\x82\x76\xbf\x0b\xbf\x75\x3f\xfd\x10\xbb\x3e\x75\xe6\xbf\xbc\xa7\xa4\x11\x3f\xb2\xa4\x11\x3f\xe0\xe9\x7e\x3f\xe0\xe9\x7e\x3f\x85\x22\x7e\x3f\x52\xf4\xb9\x3e\x7b\xb6\x78\xbd\x76\x03\x93\xbe\x62\x03\x93\xbe\x11\x3f\x80\xbf\x11\x3f\x80\xbf\x5f\xbc\x7f\x3f\x8d\xd6\xb8\x3e\x1f\xf5\xc8\xbd\x4c\x91\xac\xbd\x14\x91\xac\xbd\x80\x4c\x7b\x3f\x80\x4c\x7b\x3f\x4f\x9a\x7a\x3f\xae\xb7\xb7\x3e\xd8\xbe\x09\xbe\xa5\x63\xda\x3e\xaf\x63\xda\x3e\xe9\x90\x6f\xbf\xe9\x90\x6f\xbf\xad\xf6\x6e\x3f\xbf\x97\xb6\x3e\x4f\x6c\x2e\xbe\x0c\xeb\x21\xbf\x0b\xeb\x21\xbf\x1d\xb3\x5d\x3f\x1d\xb3\x5d\x3f\xaf\x35\x5d\x3f\xc0\x76\xb5\x3e\x07\x9c\x51\xbe\xe1\xbc\x23\x3f\xde\xbc\x23\x3f\x14\x42\x46\xbf\x14\x42\x46\xbf\x01\xe2\x45\x3f\xb6\x54\xb4\x3e\x60\x9d\x73\xbe\xc1\x89\xe5\xbe\xcd\x89\xe5\xbe\x2a\xed\x29\x3f\x2a\xed\x29\x3f\x8c\xa6\x29\x3f\xa2\x31\xb3\x3e\x83\x22\x8a\xbe\xae\xde\xf5\x3d\x6a\xde\xf5\x3d\xe9\x7e\x09\xbf\xe9\x7e\x09\xbf\xed\x4a\x09\x3f\x8c\x0d\xb2\x3e\xf5\x4c\x99\xbe\x35\xca\x79\x3e\x0c\xca\x79\x3e\xf4\xae\xcb\x3e\xf4\xae\xcb\x3e\x75\x58\xcb\x3e\x72\xe8\xb0\x3e\x85\xb1\xa7\xbe\x6d\xb8\x08\xbf\x79\xb8\x08\xbf\x97\x98\x7f\xbe\x97\x98\x7f\xbe\xf1\xe1\x7e\x3e\x5e\xc2\xaf\x3e\xa1\x03\xb5\xbe\xbe\x33\x2a\x3f\xb2\x33\x2a\x3f\xa6\x0d\xc5\x3d\xa6\x0d\xc5\x3d\x60\x33\xc3\x3d\x4f\x9b\xae\x3e\xe6\x0a\xc1\xbe\x7e\x60\x19\xbf\x88\x60\x19\xbf\xb6\xc7\x6f\x3d\xb6\xc7\x6f\x3d\x44\x10\x75\xbd\x4c\x73\xad\x3e\x64\x08\xcc\xbe\x2b\x85\xb7\x3e\x1b\x85\xb7\x3e\xb3\xfc\x57\xbe\xb3\xfc\x57\xbe\x6b\xdf\x59\xbe\x57\x4a\xac\x3e\x42\x70\xd5\xbe\x7f\x04\x74\xbc\xbf\x05\x74\xbc\x34\xf7\xb6\x3e\x34\xf7\xb6\x3e\xeb\x43\xb8\xbe\x75\x20\xab\x3e\xd4\xf0\xdd\xbe\xca\x9b\xa9\xbe\xcc\x9b\xa9\xbe\xfc\x30\xfd\xbe\xfc\x30\xfd\xbe\x61\xe6\xfe\xbe\xa7\xf5\xa9\x3e\x81\xa8\xe4\xbe\xb4\xe8\x14\x3f\xb8\xe8\x14\x3f\xe2\x8f\x1e\x3f\xe2\x8f\x1e\x3f\xf3\xa2\x1f\xbf\xf5\xc9\xa8\x3e\x82\x1d\xea\xbe\x84\xcb\x2a\xbf\x7e\xcb\x2a\xbf\x05\xb4\x3a\xbf\x05\xb4\x3a\xbf\xdd\xff\x3b\xbf\x5f\x9d\xa7\x3e\xb6\x11\xee\xbe\xa2\xfc\x10\x3f\xab\xfc\x10\x3f\x8a\x71\x52\x3f\x8a\x71\x52\x3f\x5f\xf3\x53\xbf\xec\x6f\xa6\x3e\xed\x84\xf0\xbe\x6a\x62\x9e\xbe\x52\x62\x9e\xbe\x0b\x52\x65\xbf\x0b\x52\x65\xbf\x75\x04\x67\xbf\x9c\x41\xa5\x3e\xc7\xbc\xf1\xbe\xc7\x8b\x02\xbd\xff\x8a\x02\xbd\x86\xfe\x72\x3f\x86\xfe\x72\x3f\xde\xd7\x74\xbf\x77\x12\xa4\x3e\x06\xdd\xf0\xbe\x5f\x44\xba\x3e\x77\x44\xba\x3e\x58\x3e\x7b\xbf\x58\x3e\x7b\xbf\x1a\x33\x7d\xbf\x7e\xe2\xa2\x3e\xfb\x24\xef\xbe\xe3\xac\x18\xbf\xd8\xac\x18\xbf\x51\xf8\x7d\x3f\x51\xf8\x7d\x3f\xcd\xfc\x7f\xbf\xb7\xb1\xa1\x3e\x38\x9e\xeb\xbe\x5e\xfe\x2a\x3f\x66\xfe\x2a\x3f\xa5\x31\x7b\xbf\xa5\x31\x7b\xbf\x07\x3b\x7d\xbf\x23\x80\xa0\x3e\x68\xb9\xe6\xbe\xe2\xd7\x0f\xbf\xdd\xd7\x0f\xbf\x72\x0f\x73\x3f\x72\x0f\x73\x3f\x89\x12\x75\xbf\xc8\x4d\x9f\x3e\x16\x3f\xe0\xbe\xe1\xaa\x9e\x3e\xe1\xaa\x9e\x3e\xc1\xd4\x65\xbf\xc1\xd4\x65\xbf\x1f\xc6\x67\xbf\xa8\x1a\x9e\x3e\x4c\xc2\xd8\xbe\xf8\x3c\x9f\x3c\x98\x3c\x9f\x3c\x73\xde\x53\x3f\x73\xde\x53\x3f\x9c\xb2\x55\xbf\xc9\xe6\x9c\x3e\x79\xbf\xcf\xbe\x39\x29\xae\xbe\x49\x29\xae\xbe\xe3\x9e\x3d\xbf\xe3\x9e\x3d\xbf\xfd\x4b\x3f\xbf\x2e\xb2\x9b\x3e\x7d\x50\xc5\xbe\xae\x3d\x12\x3f\xa4\x3d\x12\x3f\x08\x9c\x23\x3f\x08\x9c\x23\x3f\xc9\x19\x25\xbf\xdb\x7c\x9a\x3e\x08\xdb\xb9\xbe\x43\xd8\x27\xbf\x4f\xd8\x27\xbf\x76\x6a\x06\xbf\x76\x6a\x06\xbf\x69\xb3\x07\xbf\xd1\x46\x99\x3e\xc1\x7f\xad\xbe\x27\xd9\x12\x3f\x1a\xd9\x12\x3f\xa5\x56\xcd\x3e\xa5\x56\xcd\x3e\x87\x7a\xcf\xbe\x18\x10\x98\x3e\xf6\xb4\x9f\xbe\x1c\xe7\xb1\xbe\x38\xe7\xb1\xbe\x54\x10\x8a\xbe\x54\x10\x8a\xbe\xb8\xc7\x8b\xbe\xb1\xd8\x96\x3e\xee\x18\x91\xbe\x9f\x17\x10\x3d\xeb\x16\x10\x3d\x2e\xbe\x08\x3e\x2e\xbe\x08\x3e\x43\x66\x0b\xbe\xa3\xa0\x95\x3e\xbf\xb0\x81\xbe\x91\x34\x92\x3e\x81\x34\x92\x3e\x18\xd4\x96\x3b\x18\xd4\x96\x3b\xdf\xbf\x2d\x3b\xef\x67\x94\x3e\xca\x21\x63\xbe\x1b\xa0\x09\xbf\x21\xa0\x09\xbf\xde\x81\x11\xbe\xde\x81\x11\xbe\xb5\x03\x10\x3e\x9b\x2e\x93\x3e\xad\x49\x41\xbe\x6c\x99\x29\x3f\x6d\x99\x29\x3f\x31\x7c\x8d\x3e\x31\x7c\x8d\x3e\x35\xe7\x8c\x3e\xa7\xf4\x91\x3e\x12\x19\x1e\xbe\x24\xe1\x21\xbf\x20\xe1\x21\xbf\x5d\x48\xcf\xbe\x5d\x48\xcf\xbe\xd9\xc4\xce\x3e\x1c\xba\x90\x3e\x88\x7a\xf5\xbd\x2b\x31\xe9\x3e\x3a\x31\xe9\x3e\x60\x7b\x06\x3f\x60\x7b\x06\x3f\x72\x36\x06\x3f\xf9\x7e\x8f\x3e\xad\x0d\xac\xbd\x83\x75\x32\xbe\x55\x75\x32\xbe\xc0\xba\x22\xbf\xc0\xba\x22\xbf\xba\x66\x22\x3f\x46\x43\x8e\x3e\x48\xeb\x43\xbd\x96\x5e\x14\xbe\x66\x5e\x14\xbe\xb8\xe8\x3b\x3f\xb8\xe8\x3b\x3f\x4f\x7b\x3b\x3f\x04\x07\x8d\x3e\xa8\x0b\x3d\xbc\x20\x77\xdb\x3e\x3b\x77\xdb\x3e\x97\x9d\x51\xbf\x97\x9d\x51\xbf\x98\x0e\x51\x3f\x38\xca\x8b\x3e\x2c\xf6\xcb\x3c\x82\x27\x1d\xbf\x75\x27\x1d\xbf\xa7\x83\x63\x3f\xa7\x83\x63\x3f\xd0\xcd\x62\x3f\xe6\x8c\x8a\x3e\x46\xbc\x79\x3d\x78\x4b\x29\x3f\x83\x4b\x29\x3f\xa2\x58\x71\xbf\xa2\x58\x71\xbf\x1d\x7a\x70\x3f\x12\x4f\x89\x3e\xfd\xe6\xc6\x3d\x8f\x12\x10\xbf\x88\x12\x10\xbf\xff\xec\x7a\x3f\xff\xec\x7a\x3f\x0f\xe8\x79\x3f\xbf\x10\x88\x3e\xa6\x3b\x07\x3e\x67\x0e\xaf\x3e\x6c\x0e\xaf\x3e\xb7\x12\x80\xbf\xb7\x12\x80\xbf\xce\x00\x7f\x3f\xf2\xd1\x86\x3e\xbd\x80\x2a\x3e\xe6\xe2\x43\xbd\xf8\xe2\x43\xbd\x57\x7d\x80\x3f\x57\x7d\x80\x3f\x35\xc1\x7f\x3f\xad\x92\x85\x3e\xc0\xdd\x4c\x3e\x79\x0d\x83\xbe\x82\x0d\x83\xbe\x9c\x7a\x7d\xbf\x9c\x7a\x7d\xbf\xfe\x38\x7c\x3f\xf6\x52\x84\x3e\xee\x85\x6d\x3e\xc4\x42\x01\x3f\xbb\x42\x01\x3f\xa9\xc6\x75\x3f\xa9\xc6\x75\x3f\x04\x8a\x74\x3f\xcd\x12\x83\x3e\xd5\xaa\x86\x3e\xa5\xba\x25\xbf\xb1\xba\x25\xbf\x1a\x13\x6a\xbf\x1a\x13\x6a\xbf\x16\xe7\x68\x3f\x3c\xd2\x81\x3e\x15\x91\x95\x3e\x83\xdc\x27\x3f\x75\xdc\x27\x3f\xd1\xa4\x5a\x3f\xd1\xa4\x5a\x3f\xce\x92\x59\x3f\x41\x91\x80\x3e\x0d\x9a\xa3\x3e\x6c\x11\x08\xbf\x7a\x11\x08\xbf\x23\xcf\x47\xbf\x23\xcf\x47\xbf\xea\xdd\x46\x3f\xc9\x9f\x7e\x3e\x86\xb6\xb0\x3e\xe7\x03\x9b\x3e\xcb\x03\x9b\x3e\xd4\xf0\x31\x3f\xd4\xf0\x31\x3f\x26\x24\x31\x3f\x4e\x1c\x7c\x3e\x1e\xc7\xbc\x3e\x10\x6e\x86\xbc\x68\x6f\x86\xbc\x7d\x71\x19\xbf\x7d\x71\x19\xbf\x43\xcb\x18\x3f\x1e\x98\x79\x3e\xc9\xd1\xc7\x3e\x8e\xd8\x8a\xbe\x9d\xd8\x8a\xbe\xa0\x80\xfd\x3e\xa0\x80\xfd\x3e\x99\x80\xfc\x3e\x39\x13\x77\x3e\x2a\x5e\xd1\x3e\x8c\xf7\x00\x3f\x88\xf7\x00\x3f\x15\xa3\xc4\xbe\x15\xa3\xc4\xbe\x59\xea\xc3\x3e\xb0\x8d\x74\x3e\xaa\x0a\xda\x3e\x21\x02\x23\xbf\x20\x02\x23\xbf\x66\x37\x89\x3e\x66\x37\x89\x3e\xa5\xbe\x88\x3e\x80\x07\x72\x3e\x05\x64\xe1\x3e\x92\x5c\x25\x3f\x97\x5c\x25\x3f\x02\x58\x18\xbe\x02\x58\x18\xbe\x7e\xd5\x17\x3e\xbc\x80\x6f\x3e\xfb\x37\xe7\x3e\x05\x22\x08\xbf\xfb\x21\x08\xbf\x60\xbe\xe6\x3c\x60\xbe\xe6\x3c\xc6\xb0\xe5\x3c\x62\xf9\x6c\x3e\xcb\xe4\xeb\x3e\x31\x90\xa2\x3e\x49\x90\xa2\x3e\x5b\x8e\xbc\x3d\x5b\x8e\xbc\x3d\xdf\x1e\xbc\xbd\x82\x71\x6a\x3e\xe0\x27\xef\x3e\x60\xba\x35\xbd\x78\xb9\x35\xbd\x61\x4d\x57\xbe\x61\x4d\x57\xbe\x92\xba\x56\xbe\x1a\xe9\x67\x3e\x96\x17\xf1\x3e\x3a\x6d\x72\xbe\x02\x6d\x72\xbe\x51\x4b\xa6\x3e\x51\x4b\xa6\x3e\x0c\xce\xa5\xbe\x3e\x60\x65\x3e\xc4\x8b\xf1\x3e\x2f\x15\xf3\x3e\x49\x15\xf3\x3e\x2b\x4b\xde\xbe\x2b\x4b\xde\xbe\x0f\x90\xdd\xbe\xed\xd6\x62\x3e\xbc\x98\xf0\x3e\x8e\xbb\x20\xbf\x84\xbb\x20\xbf\x08\x76\x09\x3f\x08\x76\x09\x3f\x3d\xf5\x08\xbf\x32\x4d\x60\x3e\xd8\x83\xee\x3e\x13\x8b\x2b\x3f\x19\x8b\x2b\x3f\xd1\xc1\x21\xbf\xd1\xc1\x21\xbf\xcc\x1b\x21\xbf\x0d\xc3\x5d\x3e\x63\xbb\xea\x3e\x5e\x83\x18\xbf\x5b\x83\x18\xbf\x58\xbc\x37\x3f\x58\xbc\x37\x3f\xf4\xf1\x36\xbf\x90\x38\x5b\x3e\xa3\xdb\xe5\x3e\x5e\xdb\xd6\x3e\x5a\xdb\xd6\x3e\x03\x23\x4b\xbf\x03\x23\x4b\xbf\xc8\x39\x4a\xbf\xb8\xad\x58\x3e\xa7\xa7\xdf\x3e\xd9\xd4\x31\xbe\xf4\xd4\x31\xbe\x07\xbe\x5b\x3f\x07\xbe\x5b\x3f\xfe\xbe\x5a\xbf\x98\x22\x56\x3e\xa2\x09\xd8\x3e\x09\xdf\xcc\xbd\x59\xdf\xcc\xbd\x15\x62\x69\xbf\x15\x62\x69\xbf\x42\x5a\x68\xbf\x30\x97\x53\x3e\xfc\x56\xcf\x3e\x82\x72\xb6\x3e\x68\x72\xb6\x3e\x2f\xf0\x73\x3f\x2f\xf0\x73\x3f\xb1\xed\x72\xbf\x8c\x0b\x51\x3e\xe4\x8a\xc5\x3e\x04\xe4\x0d\xbf\x13\xe4\x0d\xbf\x0a\x56\x7b\xbf\x0a\x56\x7b\xbf\x68\x67\x7a\xbf\xae\x7f\x4e\x3e\x4c\x81\xba\x3e\x02\xb6\x29\x3f\xf5\xb5\x29\x3f\x83\x8c\x7f\x3f\x83\x8c\x7f\x3f\x5d\xbf\x7e\xbf\xa5\xf3\x4b\x3e\x67\x5a\xae\x3e\x06\xb9\x2a\xbf\x13\xb9\x2a\xbf\xd7\x4b\x80\xbf\xd7\x4b\x80\xbf\x54\xf8\x7f\xbf\x71\x67\x49\x3e\x05\x60\xa1\x3e\x32\x61\x11\x3f\x28\x61\x11\x3f\x80\x85\x7e\x3f\x80\x85\x7e\x3f\xc1\x1d\x7e\xbf\x1f\xdb\x46\x3e\xd9\xd6\x93\x3e\x8c\x4d\xc4\xbe\x9a\x4d\xc4\xbe\x0a\x6d\x79\xbf\x0a\x6d\x79\xbf\x87\x45\x79\xbf\xaf\x4e\x44\x3e\x19\x9e\x84\x3e\x86\x4a\x12\x3e\x84\x4a\x12\x3e\x78\x6e\x71\x3f\x78\x6e\x71\x3f\x6d\x8d\x71\xbf\x31\xc2\x41\x3e\x91\xb2\x6a\x3e\xc4\x2a\xee\x3d\xe4\x2a\xee\x3d\xed\xb2\x66\xbf\xed\xb2\x66\xbf\x1f\x1d\x67\xbf\xa6\x35\x3f\x3e\x2a\xf9\x4a\x3e\x20\xa3\xb5\xbe\x11\xa3\xb5\xbe\x16\x6c\x59\x3f\x16\x6c\x59\x3f\xfb\x21\x5a\xbf\x1c\xa9\x3c\x3e\x74\x65\x29\x3e\xbb\xc0\x09\x3f\xc6\xc0\x09\x3f\x46\xd2\x49\xbf\x46\xd2\x49\xbf\x3b\xd0\x4a\xbf\x94\x1c\x3a\x3e\xa3\x1c\x07\x3e\xc0\x43\x24\xbf\xb2\x43\x24\xbf\xf2\x22\x38\x3f\xf2\x22\x38\x3f\x65\x61\x39\xbf\x1c\x90\x37\x3e\x3c\x6d\xc8\x3d\x45\x08\x27\x3f\x54\x08\x27\x3f\x73\x9e\x24\xbf\x73\x9e\x24\xbf\x08\x12\x26\xbf\xb2\x03\x35\x3e\x95\x7c\x82\x3d\x87\x0c\x12\xbf\x78\x0c\x12\xbf\x95\x86\x0f\x3f\x95\x86\x0f\x3f\xfd\x21\x11\xbf\x68\x77\x32\x3e\xd7\x87\xeb\x3c\xe8\x57\xd1\x3e\x02\x58\xd1\x3e\x52\x3a\xf2\xbe\x52\x3a\xf2\xbe\x3a\xa7\xf5\xbe\x3c\xeb\x2f\x3e\xb8\xe0\xf4\xbb\x0c\xc4\x44\xbe\xe7\xc3\x44\xbe\xa8\x47\xc3\x3e\xa8\x47\xc3\x3e\xf0\xd3\xc6\xbe\x3d\x5f\x2d\x3e\x1f\xc3\x22\xbd\x8a\xd7\x44\xbd\x3c\xd7\x44\xbd\xc5\xb7\x92\xbe\xc5\xb7\x92\xbe\xbb\x52\x96\xbe\x6a\xd3\x2a\x3e\x5a\x64\x9f\xbd\x5d\x68\x8e\x3e\x5e\x68\x8e\x3e\x5c\x1b\x42\x3e\x5c\x1b\x42\x3e\x1d\x57\x49\xbe\x01\x46\x28\x3e\x9b\xb6\xdf\xbd\x9a\x6c\xef\xbe\xa2\x6c\xef\xbe\x5e\x31\xbb\xbd\x5e\x31\xbb\xbd\x18\x8d\xc9\xbd\x00\xb7\x25\x3e\x36\xb5\x13\xbe\x73\xc9\x17\x3f\x6c\xc9\x17\x3f\xbd\xa3\xe2\xbb\xbd\xa3\xe2\xbb\xcb\xca\xfe\x36\x10\x2d\x23\x3e\xc8\xcb\x34\xbe\x91\xa4\x23\xbf\x9d\xa4\x23\xbf\x13\xe3\xd5\x3d\x13\xe3\xd5\x3d\xcb\xff\xc7\x3d\x2e\xa8\x20\x3e\x4a\x15\x56\xbe\xca\x14\x1a\x3f\xbd\x14\x1a\x3f\x2d\x09\x4d\xbe\x2d\x09\x4d\xbe\xf5\x41\x46\x3e\x38\x20\x1e\x3e\xc9\xf6\x73\xbe\xe6\x3e\xf9\xbe\x02\x3f\xf9\xbe\x3d\x3b\x96\x3e\x3d\x3b\x96\x3e\x2a\xf0\x92\x3e\x2d\x95\x1b\x3e\x79\xc5\x89\xbe\xc5\x6d\x9e\x3e\xa9\x6d\x9e\x3e\x4f\x32\xc4\xbe\x4f\x32\xc4\xbe\x51\x05\xc1\x3e\xf5\x0a\x19\x3e\x46\xa4\x97\xbe\x1c\x3c\xbc\xbd\x78\x3c\xbc\xbd\x48\x0a\xf0\x3e\x48\x0a\xf0\x3e\x6f\xfe\xec\x3e\x92\x81\x16\x3e\xea\xc2\xa4\xbe\x9a\x85\x0e\xbe\xb8\x85\x0e\xbe\x2a\xb7\x0c\xbf\x2a\xb7\x0c\xbf\xd0\x41\x0b\x3f\xa6\xf8\x13\x3e\xf7\x26\xb2\xbe\xbe\x06\xb6\x3e\xb6\x06\xb6\x3e\x5a\x09\x20\x3f\x5a\x09\x20\x3f\xb8\xa2\x1e\x3f\x30\x70\x11\x3e\xe5\x92\xbc\xbe\xa6\xf0\x07\xbf\xa6\xf0\x07\xbf\x2c\xda\x31\xbf\x2c\xda\x31\xbf\x3e\x7f\x30\x3f\x42\xe8\x0e\x3e\x7f\xed\xc7\xbe\xa8\x81\x25\x3f\xae\x81\x25\x3f\xfb\x0b\x42\x3f\xfb\x0b\x42\x3f\xec\xb9\x40\x3f\xd8\x60\x0c\x3e\x50\xfa\xd0\xbe\x30\x0d\x31\xbf\x27\x0d\x31\xbf\x46\x85\x50\xbf\x46\x85\x50\xbf\xd3\x39\x4f\x3f\x03\xda\x09\x3e\x12\x52\xd9\xbe\x1c\xeb\x29\x3f\x29\xeb\x29\x3f\x6a\x30\x5d\x3f\x6a\x30\x5d\x3f\x70\xea\x5b\x3f\xc2\x53\x07\x3e\x79\x8b\xe0\xbe\x27\x0b\x11\xbf\x18\x0b\x11\xbf\x20\xfd\x67\xbf\x20\xfd\x67\xbf\xa4\xbc\x66\x3f\x21\xce\x04\x3e\x8f\x41\xe6\xbe\x45\x2a\xd2\x3e\x62\x2a\xd2\x3e\x66\xe0\x70\x3f\x66\xe0\x70\x3f\xa7\xa4\x6f\x3f\x20\x49\x02\x3e\x47\x30\xeb\xbe\xe8\x90\x59\xbe\xb4\x90\x59\xbe\x33\xd5\x77\xbf\x33\xd5\x77\xbf\x8b\x9d\x76\x3f\x9e\x89\xff\x3d\xab\x83\xee\xbe\xe9\x58\xb4\xbb\x69\x53\xb4\xbb\xcf\xda\x7c\x3f\xcf\xda\x7c\x3f\x67\xa5\x7b\x3f\x5c\x82\xfa\x3d\xe8\x8a\xf0\xbe\x3c\x69\x61\x3e\x5a\x69\x61\x3e\x75\xf5\x7f\xbf\x75\xf5\x7f\xbf\xf7\xbf\x7e\x3f\x93\x7c\xf5\x3d\x74\xb6\xf1\xbe\x48\xe8\xd1\xbe\x42\xe8\xd1\xbe\x75\x96\x80\x3f\x75\x96\x80\x3f\x80\xf4\x7f\x3f\x46\x78\xf0\x3d\x34\xff\xf0\xbe\x40\xe2\x0e\x3f\x3e\xe2\x0e\x3f\xf9\x45\x80\xbf\xf9\x45\x80\xbf\xba\x4e\x7f\x3f\x8c\x75\xeb\x3d\x49\xb2\xef\xbe\x0a\x11\x27\xbf\x10\x11\x27\xbf\x3e\x1f\x7e\x3f\x3e\x1f\x7e\x3f\x13\xdc\x7c\x3f\x66\x74\xe6\x3d\xbd\x5c\xec\xbe\x44\xb8\x2f\x3f\x3a\xb8\x2f\x3f\x5d\xf6\x79\xbf\x5d\xf6\x79\xbf\x5d\xae\x78\x3f\xef\x74\xe1\x3d\x75\x7d\xe8\xbe\x83\x51\x28\xbf\x8f\x51\x28\xbf\xbf\x23\x74\x3f\xbf\x23\x74\x3f\xe7\xd7\x72\x3f\x27\x77\xdc\x3d\x42\x0b\xe3\xbe\xc3\xd4\x11\x3f\xb4\xd4\x11\x3f\xf2\xbb\x6c\xbf\xf2\xbb\x6c\xbf\x61\x6f\x6b\x3f\x2a\x7b\xd7\x3d\xa5\x5b\xdc\xbe\x16\x62\xdd\xbe\x34\x62\xdd\xbe\x10\xd7\x63\x3f\x10\xd7\x63\x3f\x02\x8c\x62\x3f\xf8\x80\xd2\x3d\xdf\xd7\xd4\xbe\x96\x14\x85\x3e\x7a\x14\x85\x3e\x96\x8f\x59\xbf\x96\x8f\x59\xbf\x9b\x47\x58\x3f\xab\x88\xcd\x3d\xc9\xd8\xcb\xbe\x4c\xf2\x8b\xbd\xa0\xf2\x8b\xbd\x23\x02\x4e\x3f\x23\x02\x4e\x3f\x00\xbd\x4c\x3f\x43\x92\xc8\x3d\x47\xf6\xc1\xbe\xfc\x25\x01\xbe\x18\x26\x01\xbe\xbd\x4b\x41\xbf\xbd\x4b\x41\xbf\xcc\x08\x40\x3f\xdb\x9d\xc3\x3d\x65\x4e\xb7\xbe\x72\x85\x9d\x3e\x6e\x85\x9d\x3e\xfe\x89\x33\x3f\xfe\x89\x33\x3f\x44\x48\x32\x3f\x73\xab\xbe\x3d\xa3\x44\xab\xbe\x79\x4d\xec\xbe\x71\x4d\xec\xbe\x1c\xda\x24\xbf\x1c\xda\x24\xbf\x37\x9a\x23\x3f\x24\xbb\xb9\x3d\x30\xbb\x9e\xbe\x91\x48\x13\x3f\x99\x48\x13\x3f\x19\x59\x15\x3f\x19\x59\x15\x3f\x50\x1c\x14\x3f\xef\xcc\xb4\x3d\x95\x06\x91\xbe\x82\x06\x24\xbf\x77\x06\x24\xbf\x5c\x23\x05\xbf\x5c\x23\x05\xbf\xd2\xed\x03\x3f\xec\xe0\xaf\x3d\x94\x1b\x83\xbe\x85\x90\x27\x3f\x93\x90\x27\x3f\x93\xab\xe8\x3e\x93\xab\xe8\x3e\x41\x58\xe6\x3e\x1d\xf7\xaa\x3d\xf7\xe3\x67\xbe\x3e\x30\x1e\xbf\x2f\x30\x1e\xbf\x9c\x1a\xc6\xbe\x9c\x1a\xc6\xbe\xdf\xe9\xc3\x3e\x9a\x0f\xa6\x3d\x97\x0d\x49\xbe\xb8\x05\x09\x3f\xc7\x05\x09\x3f\x52\xcd\xa2\x3e\x52\xcd\xa2\x3e\x98\xc8\xa0\x3e\x62\x2a\xa1\x3d\x48\x50\x29\xbe\x54\xec\xd3\xbe\x3a\xec\xd3\xbe\xf0\xf7\x7d\xbe\xf0\xf7\x7d\xbe\x2a\x58\x7a\x3e\x94\x47\x9c\x3d\x28\x4f\x08\xbe\xa2\x58\x87\x3e\xb4\x58\x87\x3e\x0b\xbb\x35\x3e\x0b\xbb\x35\x3e\x2a\x92\x32\x3e\x2e\x67\x97\x3d\xe1\xc0\xcd\xbd\xe9\xbc\xc9\xbd\xbd\xbc\xc9\xbd\xe1\x97\xda\xbd\xe1\x97\xda\xbd\xd4\x4e\xd5\x3d\x47\x89\x92\x3d\x16\x06\x8a\xbd\x6e\xc5\x91\xbd\x66\xc5\x91\xbd\x15\x34\x14\x3d\x15\x34\x14\x3d\xd6\xde\x0b\x3d\xe0\xad\x8d\x3d\x60\x54\x0a\xbd\xaf\xa6\x6e\x3e\x9e\xa6\x6e\x3e\xaa\x91\x0a\x3d\xaa\x91\x0a\x3d\x85\x73\x10\xbd\x11\xd5\x88\x3d\xc2\x11\xc2\xb9\x16\x01\xc1\xbe\x27\x01\xc1\xbe\x46\xe1\xd2\xbd\x46\xe1\xd2\xbd\x1a\x7b\xd4\xbd\xdc\xfe\x83\x3d\xb1\x2f\x09\x3d\x44\x4e\xfd\x3e\x2c\x4e\xfd\x3e\x4f\x02\x2f\x3e\x4f\x02\x2f\x3e\xc3\x16\x2f\xbe\xac\x56\x7e\x3d\x34\x16\x88\x3d\x7d\x64\x14\xbf\x8b\x64\x14\xbf\xae\x06\x73\xbe\xae\x06\x73\xbe\xa3\x5c\x72\xbe\x01\xb5\x74\x3d\x08\xf4\xcc\x3d\xc4\x82\x20\x3f\xb5\x82\x20\x3f\x0b\x98\x9a\x3e\x0b\x98\x9a\x3e\x1c\xe4\x99\xbe\xec\x18\x6b\x3d\x2c\x23\x07\x3e\xe5\x77\x22\xbf\xf3\x77\x22\xbf\xe8\x9a\xba\xbe\xe8\x9a\xba\xbe\xe3\x8c\xb9\xbe\x6e\x82\x61\x3d\x28\xe5\x27\x3e\x8c\x7e\x1a\x3f\x7f\x7e\x1a\x3f\x43\x6b\xd9\x3e\x43\x6b\xd9\x3e\xed\x0c\xd8\xbe\xb4\xf1\x57\x3d\x56\xc9\x47\x3e\xd2\x74\x09\xbf\xdb\x74\x09\xbf\x71\xec\xf6\xbe\x71\xec\xf6\xbe\xca\x4c\xf5\xbe\xbc\x66\x4e\x3d\x56\x1c\x66\x3e\xee\x80\xe1\x3e\xe6\x80\xe1\x3e\x4f\x83\x09\x3f\x4f\x83\x09\x3f\xc7\x9b\x08\xbf\xbc\xe1\x44\x3d\x05\xcc\x81\x3e\x05\x54\xa4\xbe\x03\x54\xa4\xbe\x4b\xd3\x16\xbf\x4b\xd3\x16\xbf\x07\xdd\x15\xbf\xb0\x62\x3b\x3d\x3b\x06\x90\x3e\xad\x78\x3e\x3e\xc3\x78\x3e\x3e\xca\x5d\x23\x3f\xca\x5d\x23\x3f\x7f\x62\x22\xbf\xca\xe9\x31\x3d\x30\x28\x9d\x3e\xfa\xe0\x30\xbd\x52\xe0\x30\xbd\x30\x1c\x2f\xbf\x30\x1c\x2f\xbf\x7f\x25\x2e\xbf\x0a\x77\x28\x3d\x48\xd5\xa9\x3e\x66\xca\xcc\xbd\xf8\xc9\xcc\xbd\xc2\x09\x3a\x3f\xc2\x09\x3a\x3f\x7b\x20\x39\xbf\x98\x0a\x1f\x3d\x4b\x5e\xb5\x3e\xd9\x56\x71\x3e\x15\x57\x71\x3e\x6e\x23\x44\xbf\x6e\x23\x44\xbf\x2d\x4f\x43\xbf\x76\xa4\x15\x3d\xfa\x5a\xc0\x3e\x6d\x98\xb6\xbe\x4d\x98\xb6\xbe\xff\x66\x4d\x3f\xff\x66\x4d\x3f\x3a\xae\x4c\xbf\xd7\x44\x0c\x3d\x7f\xe0\xc9\x3e\xf9\x23\xea\x3e\x17\x24\xea\x3e\x47\xd4\x55\xbf\x47\xd4\x55\xbf\x61\x3c\x55\xbf\xba\xeb\x02\x3d\x3e\x07\xd3\x3e\x17\xb7\x08\xbf\x0b\xb7\x08\xbf\x98\x6c\x5d\x3f\x98\x6c\x5d\x3f\x37\xf9\x5c\xbf\x9a\x32\xf3\x3c\x90\x88\xda\x3e\x2d\x91\x15\x3f\x34\x91\x15\x3f\xc3\x32\x64\xbf\xc3\x32\x64\xbf\xcd\xe5\x63\xbf\x21\x9b\xe0\x3c\x64\x1c\xe1\x3e\x30\x4c\x1b\xbf\x2d\x4c\x1b\xbf\x7f\x2a\x6a\x3f\x7f\x2a\x6a\x3f\x8d\x04\x6a\xbf\x5d\x11\xce\x3c\xe8\xfd\xe6\x3e\x94\xf4\x19\x3f\x91\xf4\x19\x3f\x15\x59\x6f\xbf\x15\x59\x6f\xbf\xdb\x58\x6f\xbf\x50\x95\xbb\x3c\x77\x55\xeb\x3e\xfa\xdc\x11\xbf\x01\xdd\x11\xbf\x93\xc4\x73\x3f\x93\xc4\x73\x3f\x4b\xe6\x73\xbf\x54\x27\xa9\x3c\xeb\x2e\xee\x3e\xa1\x76\x03\x3f\x96\x76\x03\x3f\xb4\x73\x77\xbf\xb4\x73\x77\xbf\xfa\xb0\x77\xbf\x6b\xc7\x96\x3c\x4d\x13\xf1\x3e\x11\x1c\xdf\xbe\x2d\x1c\xdf\xbe\xb6\x6b\x7a\x3f\xb6\x6b\x7a\x3f\x26\xbe\x7a\xbf\xf0\x75\x84\x3c\x25\xe0\xf0\x3e\x52\x7b\xae\x3e\x32\x7b\xae\x3e\x46\xb1\x7c\xbf\x46\xb1\x7c\xbf\x3e\x13\x7d\xbf\xc7\x65\x64\x3c\xe9\xcb\xf1\x3e\x29\x90\x6e\xbe\x68\x90\x6e\xbe\xd2\x49\x7e\x3f\xd2\x49\x7e\x3f\x12\xb6\x7e\xbf\x2f\xfd\x3f\x3c\xa8\x01\xf0\x3e\x25\x24\xee\x3d\xb5\x23\xee\x3d\xc4\x3a\x7f\xbf\xc4\x3a\x7f\xbf\xbc\xac\x7f\xbf\x16\xb2\x1b\x3c\xd1\x69\xec\x3e\x0b\x05\x8b\x3b\xcb\xff\x8a\x3b\xf1\x88\x7f\x3f\xf1\x88\x7f\x3f\xc6\xfd\x7f\xbf\x63\x0a\xef\x3b\x58\x4b\xea\x3e\x21\x42\xfc\xbd\x4f\x42\xfc\xbd\x59\x3a\x7f\xbf\x59\x3a\x7f\xbf\xbe\xaf\x7f\xbf\x01\xed\xa6\x3b\x6a\x53\xe4\x3e\x38\x3a\x72\x3e\x34\x3a\x72\x3e\xf4\x55\x7e\x3f\xf4\x55\x7e\x3f\x2b\xca\x7e\xbf\x93\x1a\x3e\x3b\x1f\xe2\xde\x3e\xea\xfd\xae\xbe\xe2\xfd\xae\xbe\x9c\xe4\x7c\xbf\x9c\xe4\x7c\xbf\xc7\x55\x7d\xbf\xe1\x59\x3b\x3a\x9e\x72\xd7\x3e\x1e\x15\xdf\x3e\x30\x15\xdf\x3e\x18\xf0\x7a\x3f\x18\xf0\x7a\x3f\xe8\x5a\x7b\xbf\x34\xdf\xbf\xba\x1f\xca\xcf\x3e\xf5\xcf\x03\xbf\xe8\xcf\x03\xbf\x6a\x81\x78\xbf\x6a\x81\x78\xbf\x18\xe2\x78\xbf\xa3\x37\x6e\xbb\xaa\x6f\xc6\x3e\x82\xb6\x13\x3f\x93\xb6\x13\x3f\xf8\xa0\x75\x3f\xf8\xa0\x75\x3f\x7e\xf3\x75\xbf\x82\xff\xbd\xbb\x2e\xda\xbc\x3e\xc4\x16\x1f\xbf\xb4\x16\x1f\xbf\x1f\x56\x72\xbf\x1f\x56\x72\xbf\xe5\x96\x72\xbf\x6f\x51\x02\xbc\x49\x98\xb1\x3e\xc6\xf6\x25\x3f\xd6\xf6\x25\x3f\x72\xa7\x6e\x3f\x72\xa7\x6e\x3f\xf1\xd3\x6e\xbf\x61\x82\x25\xbc\xc7\xf7\xa5\x3e\x26\x96\x28\xbf\x18\x96\x28\xbf\xb4\x9b\x6a\xbf\xb4\x9b\x6a\xbf\x46\xb2\x6a\xbf\x96\x92\x48\xbc\x30\x78\x99\x3e\x71\x33\x27\x3f\x79\x33\x27\x3f\x52\x39\x66\x3f\x52\x39\x66\x3f\x6a\x39\x66\xbf\x4f\x81\x6b\xbc\x3e\x96\x8c\x3e\x34\xe1\x21\xbf\x2f\xe1\x21\xbf\x68\x87\x61\xbf\x68\x87\x61\xbf\xd1\x70\x61\xbf\x46\x27\x87\xbc\x56\xcd\x7c\x3e\xbe\xba\x18\x3f\xbd\xba\x18\x3f\x3a\x8c\x5c\x3f\x3a\x8c\x5c\x3f\x3d\x60\x5c\xbf\xee\x7c\x98\xbc\x78\xb3\x5f\x3e\x64\x51\x0c\xbf\x69\x51\x0c\xbf\x6f\x4e\x57\xbf\x6f\x4e\x57\xbf\x3b\x0f\x57\xbf\xa0\xc1\xa9\xbc\xb1\x30\x42\x3e\xab\xcc\xfa\x3e\x95\xcc\xfa\x3e\xb0\xd4\x51\x3f\xb0\xd4\x51\x3f\x7e\x84\x51\xbf\xf9\xf4\xba\xbc\x05\xcc\x23\x3e\xae\xee\xd8\xbe\xcb\xee\xd8\xbe\xe6\x24\x4c\xbf\xe6\x24\x4c\xbf\x55\xc7\x4b\xbf\xfa\x16\xcc\xbc\x13\x71\x03\x3e\x23\x7d\xb3\x3e\x03\x7d\xb3\x3e\x65\x44\x46\x3f\x65\x44\x46\x3f\xd0\xde\x45\xbf\x5c\x27\xdd\xbc\xa0\x32\xc7\x3d\xbb\x41\x8b\xbe\xdd\x41\x8b\xbe\x8d\x38\x40\xbf\x8d\x38\x40\xbf\x47\xd2\x3f\xbf\x1f\x26\xee\xbc\x72\x7f\x86\x3d\xbb\x11\x43\x3e\x7c\x11\x43\x3e\x66\x06\x3a\x3f\x66\x06\x3a\x3f\xc4\xa7\x39\xbf\xfd\x12\xff\xbc\x43\xca\x08\x3d\xbe\xd3\xde\xbd\x23\xd4\xde\xbd\x04\xb3\x33\xbf\x04\xb3\x33\xbf\x57\x65\x33\xbf\xfa\xf6\x07\xbd\xdc\xdd\x9f\x3a\x5f\xc6\xe9\x3c\x49\xc5\xe9\x3c\x00\x44\x2d\x3f\x00\x44\x2d\x3f\x66\x10\x2d\xbf\x5f\x5b\x10\xbd\x62\xe4\xfc\xbc\x19\x7c\x4c\x3d\xde\x7b\x4c\x3d\x6a\xbf\x26\xbf\x6a\xbf\x26\xbf\x83\xae\x26\xbf\xae\xb6\x18\xbd\xa8\x63\x81\xbd\x0f\x5e\x01\xbe\x08\x5e\x01\xbe\x4b\x2c\x20\x3f\x4b\x2c\x20\x3f\x86\x44\x20\xbf\xbd\x08\x21\xbd\x6f\x33\xc1\xbd\x0e\x18\x4c\x3e\x29\x18\x4c\x3e\x71\x91\x19\xbf\x71\x91\x19\xbf\x69\xd6\x19\xbf\x8e\x51\x29\xbd\x2b\x24\x01\xbe\x30\x6c\x88\xbe\x18\x6c\x88\xbe\x95\xf5\x12\x3f\x95\xf5\x12\x3f\xd4\x68\x13\xbf\x00\x91\x31\xbd\x6d\x35\x20\xbe\x13\x2f\xa7\x3e\x32\x2f\xa7\x3e\x7a\x5e\x0c\xbf\x7a\x5e\x0c\xbf\xd1\xff\x0c\xbf\x14\xc7\x39\xbd\x16\x9d\x3e\xbe\x1c\x93\xc2\xbe\xfc\x92\xc2\xbe\xb3\xd1\x05\x3f\xb3\xd1\x05\x3f\xc9\x9f\x06\xbf\xa0\xf3\x41\xbd\x2a\x7c\x5c\xbe\x73\x2e\xdb\x3e\x92\x2e\xdb\x3e\xfb\xa7\xfe\xbe\xfb\xa7\xfe\xbe\xf2\x4c\x00\xbf\xa3\x16\x4a\xbd\x5a\x43\x79\xbe\xba\x23\xf1\xbe\x9e\x23\xf1\xbe\x8d\xd4\xf1\x3e\x8d\xd4\xf1\x3e\xa2\x16\xf4\xbe\x07\x30\x52\xbd\x35\x3c\x8a\xbe\xf3\x05\x02\x3f\xff\x05\x02\x3f\x12\x32\xe5\xbe\x12\x32\xe5\xbe\x5e\xbd\xe7\xbe\xca\x3f\x5a\xbd\x8b\x46\x97\xbe\xfd\xcd\x09\xbf\xf4\xcd\x09\xbf\xa9\xca\xd8\x3e\xa9\xca\xd8\x3e\xcb\x94\xdb\xbe\xc4\x45\x62\xbd\xcf\xbe\xa3\xbe\x6d\x19\x10\x3f\x6f\x19\x10\x3f\x64\xa8\xcc\xbe\x64\xa8\xcc\xbe\xb5\xa1\xcf\xbe\xf2\x41\x6a\xbd\x96\x64\xaf\xbe\x5a\x2b\x15\xbf\x5d\x2b\x15\xbf\xb6\xd2\xc0\x3e\xb6\xd2\xc0\x3e\x76\xe9\xc3\xbe\x3a\x34\x72\xbd\x1f\x14\xba\xbe\xd6\x08\x19\x3f\xce\x08\x19\x3f\x5d\x50\xb5\xbe\x5d\x50\xb5\xbe\x0a\x70\xb8\xbe\x9a\x1c\x7a\xbd\x09\x27\xc4\xbe\xe3\x8a\x1b\xbf\xf0\x8a\x1b\xbf\xfc\x26\xaa\x3e\xfc\x26\xaa\x3e\x9f\x39\xad\xbe\x7b\xfd\x80\xbd\xac\x05\xcd\xbe\xf2\xc3\x1c\x3f\xe1\xc3\x1c\x3f\x6a\x59\x9f\xbe\x6a\x59\x9f\xbe\xd8\x49\xa2\xbe\xa6\xe7\x84\xbd\xa4\x66\xd5\xbe\x67\xea\x1c\xbf\x79\xea\x1c\xbf\x84\xe8\x94\x3e\x84\xe8\x94\x3e\xb6\xa3\x97\xbe\xb8\xcc\x88\xbd\x92\x4e\xdc\xbe\x92\x28\x1c\x3f\x81\x28\x1c\x3f\xdd\xd4\x8a\xbe\xdd\xd4\x8a\xbe\x40\x4a\x8d\xbe\xb0\xac\x8c\xbd\xcf\x81\xe2\xbe\x9c\x79\x1a\xbf\xab\x79\x1a\xbf\x75\x1f\x81\x3e\x75\x1f\x81\x3e\x1d\x41\x83\xbe\x90\x87\x90\xbd\x58\xbf\xe7\xbe\xf5\xe2\x17\x3f\xea\xe2\x17\x3f\x43\x93\x6f\xbe\x43\x93\x6f\xbe\x7f\x15\x73\xbe\x57\x5d\x94\xbd\xc0\xa7\xeb\xbe\xf1\x92\x14\xbf\xf8\x92\x14\xbf\xd6\xa9\x5d\x3e\xd6\xa9\x5d\x3e\xf7\x54\x60\xbe\xe5\x2d\x98\xbd\x05\xac\xee\xbe\x78\xc4\x10\x3f\x76\xc4\x10\x3f\x4e\x85\x4c\xbe\x4e\x85\x4c\xbe\xe4\x45\x4e\xbe\x3a\xf9\x9b\xbd\x89\xbe\xf0\xbe\x5b\x93\x0c\xbf\x55\x93\x0c\xbf\x52\x27\x3c\x3e\x52\x27\x3c\x3e\x29\xed\x3c\xbe\x4c\xbf\x9f\xbd\xb7\x7e\xf1\xbe\x12\xff\x07\x3f\x1d\xff\x07\x3f\x65\x89\x2c\xbe\x65\x89\x2c\xbe\x35\x4e\x2c\xbe\x1b\x80\xa3\xbd\x45\x43\xf1\xbe\xaf\x02\x03\xbf\xa0\x02\x03\xbf\x58\xa5\x1d\x3e\x58\xa5\x1d\x3e\x0c\x6e\x1c\xbe\x9f\x3b\xa7\xbd\x18\x03\xf0\xbe\x1b\x72\xfb\x3e\x3e\x72\xfb\x3e\x83\x72\x0f\xbe\x83\x72\x0f\xbe\x74\x4c\x0d\xbe\xd8\xf1\xaa\xbd\xb0\xbc\xed\xbe\xd9\x65\xf0\xbe\xb5\x65\xf0\xbe\xcd\xea\x01\x3e\xcd\xea\x01\x3e\x62\xd7\xfd\xbd\xb4\xa2\xae\xbd\xff\xf1\xe9\xbe\xa5\xd5\xe4\x3e\xc8\xd5\xe4\x3e\x63\x0f\xea\xbd\x63\x0f\xea\xbd\xe0\x94\xe2\xbd\x32\x4e\xb2\xbd\xbb\x1e\xe6\xbe\x2d\xb1\xd8\xbe\x0f\xb1\xd8\xbe\x76\x94\xd1\x3d\x76\x94\xd1\x3d\x07\xd3\xc8\xbd\x46\xf4\xb5\xbd\x08\x3f\xe0\xbe\x2a\x16\xcc\x3e\x40\x16\xcc\x3e\x92\x61\xba\xbd\x92\x61\xba\xbd\x99\x90\xb0\xbd\xec\x94\xb9\xbd\x65\xa9\xd9\xbe\x42\x14\xbf\xbe\x34\x14\xbf\xbe\x91\x76\xa4\x3d\x91\x76\xa4\x3d\xe2\xd3\x99\xbd\x19\x30\xbd\xbd\x4a\x98\xd2\xbe\xbd\xf2\xb1\x3e\xba\xf2\xb1\x3e\x33\xd1\x8f\xbd\x33\xd1\x8f\xbd\xe3\xa0\x84\xbd\xcb\xc5\xc0\xbd\x73\x33\xca\xbe\x79\x55\xa5\xbe\x87\x55\xa5\xbe\x19\xe9\x78\x3d\x19\xe9\x78\x3d\x78\xf7\x61\xbd\xfa\x55\xc4\xbd\x8f\x1b\xc1\xbe\x4a\x80\x99\x3e\x35\x80\x99\x3e\x10\xc5\x54\xbd\x10\xc5\x54\xbd\x4b\xcc\x3d\xbd\xa4\xe0\xc7\xbd\xfc\xc5\xb6\xbe\x8e\xc9\x8d\xbe\xae\xc9\x8d\xbe\x7a\x2d\x33\x3d\x7a\x2d\x33\x3d\x4a\xca\x1c\xbd\xbd\x65\xcb\xbd\x63\xdb\xab\xbe\x02\xdf\x81\x3e\xdd\xde\x81\x3e\x44\x18\x14\xbd\x44\x18\x14\xbd\x93\xf0\xfd\xbc\x43\xe5\xce\xbd\x2e\x21\xa1\xbe\xd6\xc0\x6c\xbe\x1c\xc1\x6c\xbe\x9c\x03\xef\x3c\x9c\x03\xef\x3c\xb5\xb7\xc8\xbc\x2d\x5f\xd2\xbd\xf3\xfc\x93\xbe\xd2\xba\x57\x3e\x8a\xba\x57\x3e\xac\xb3\xba\xbc\xac\xb3\xba\xbc\xe7\xc2\x99\xbc\x7a\xd3\xd5\xbd\x15\x8d\x87\xbe\x9d\x19\x44\xbe\xdb\x19\x44\xbe\x10\x11\x8b\x3c\x10\x11\x8b\x3c\x4d\x0c\x62\xbc\x1e\x42\xd9\xbd\x74\x69\x73\xbe\xd8\x9d\x31\x3e\xb2\x9d\x31\x3e\xa7\x3d\x40\xbc\xa7\x3d\x40\xbc\xae\x19\x1d\xbc\x19\xab\xdc\xbd\xcf\xd5\x58\xbe\xd1\x21\x21\xbe\xe3\x21\x21\xbe\x3d\x54\xe7\x3b\x3d\x54\xe7\x3b\xed\x84\xc9\xbb\x5e\x0e\xe0\xbd\x6d\x90\x3a\xbe\x8f\x73\x13\x3e\x94\x73\x13\x3e\xab\xec\x40\xbb\xab\xec\x40\xbb\x40\x9d\x63\xbb\xee\x6b\xe3\xbd\x92\x33\x1d\xbe\x15\xc2\x08\xbe\xf5\xc1\x08\xbe\x6a\xfe\x26\xba\x6a\xfe\x26\xba\x27\x89\xcf\xba\x44\xb7\xe6\xbd\x89\x45\x02\xbe\x50\xae\x01\x3e\x7e\xae\x01\x3e\xc8\x95\x73\x3b\xc8\x95\x73\x3b\xdf\xdb\xf2\xb9\x5f\xf0\xe9\xbd\x14\xfc\xb2\xbd\x68\xde\xfb\xbd\xe4\xdd\xfb\xbd"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-clusterfuzz-testcase-minimized-4857057310146560 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-clusterfuzz-testcase-minimized-4857057310146560
new file mode 100644 (file)
index 0000000..19cfaff
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x44\x05\x3a\x70\x61\x74\x68"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-crash-5ac3e1ea7764cfb6383629574262f82dc7b3cada b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-crash-5ac3e1ea7764cfb6383629574262f82dc7b3cada
new file mode 100644 (file)
index 0000000..5175de2
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x52\x04\x67\x72\x70\x63\x00\x07\x3a\x73\x74\x61\x74\x75\x73\x03\x32\x30\x30\x0e\x7f"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-d000502f32ca5620d7745f39ff6be3b547e26a6d b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-d000502f32ca5620d7745f39ff6be3b547e26a6d
new file mode 100644 (file)
index 0000000..c886921
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x17\x00\x00\x00\x00\x00\x00\xa4\x2f\xa4\x7e\x1f\xa4\x5b\x28\xa4\x21\x21\x1f\xff\xff\xff\xff\x0f\xa4\x00\x00"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-d131f83ee73450ff45565d0c638be7d8beeb30d9 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-d131f83ee73450ff45565d0c638be7d8beeb30d9
new file mode 100644 (file)
index 0000000..693e47b
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x29\xa0\xa4\x5b\x27\x28\x3d\x63\x62\x69\x6e\x09\x61\x21\x3f\xe4\x1f\xdb\xf0\x21\x10\xf0\x7b\x28\x2d\x62\x69\x6e\xa4\xf0\x1f\xa4"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-d1c7ae01a81a122c2fd7c5d8debcae7566e9ee2f b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-d1c7ae01a81a122c2fd7c5d8debcae7566e9ee2f
new file mode 100644 (file)
index 0000000..35f11b2
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x17\x00\x00\x00\x00\x04\x00\xa4\x2f\xa4\x7e\x1f\xa4\x5b\x28\xa4\x21\x21\x1f\xff\xff\xff\x1f\x00\xff\x0f\xa5\x00\x00"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-d2817b89d7aaa7fa880c077b1a67168ec2f4f0f7 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-d2817b89d7aaa7fa880c077b1a67168ec2f4f0f7
new file mode 100644 (file)
index 0000000..3e54241
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x83\x1f\x00\x27\x5b\xf0\x69\x28\x62\x6e\x2d\x21\x3f\xa4\x1f\xdb\xf0\x21\x28\x21\x5c\xf0\x09\x63"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-d3ccd7039dd34baef465c4b78baa7a30312a8f07 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-d3ccd7039dd34baef465c4b78baa7a30312a8f07
new file mode 100644 (file)
index 0000000..eb48136
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3f\x2a\xa0\xa4\xae\x40\x08\x10\x07\x3a\xf0\x5b\x28\xf8\x63\x09\x28\x33\xfe\x21\x21\x5c\xf0\x09\x21\x63\x09\x28\xdb\xe5\x47\xfd\x21\xf0\x63\x6d\x3a\x27"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-d4cfaf3b59b22b654d7af80ee6715ce5015bfdc0 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-d4cfaf3b59b22b654d7af80ee6715ce5015bfdc0
new file mode 100644 (file)
index 0000000..0ec86ef
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\x2a\xa0\xa4\xae\xa0\xa4\xae\x08\x00\x07\x10\x63\x21\x09\x5b\xf4\x28\xf0\x28\x21\x5c\x09\x21\x63\x47\xfd\x3a\x08\x00\x07\x10\x63\x21\x09\x2a\xf4\x28\xf0\x28\x21\x5c\x4d\x21\x63\x47\xfd\x3a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-d5670827c8e8d4c95ac0f738c0790c19916c0336 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-d5670827c8e8d4c95ac0f738c0790c19916c0336
new file mode 100644 (file)
index 0000000..67c5d5b
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\xa4\x0f\xa4\xa4\xb8\x10\x07\xf0\x0f\xa4\x2d\xdb\x27\x28\x3f\xa4\x07\xf0\x3b\x5b\x28"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-d59d7e94863f1ed89cacfbaabf7bc59946036c8f b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-d59d7e94863f1ed89cacfbaabf7bc59946036c8f
new file mode 100644 (file)
index 0000000..d5ef2d1
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x83\x28\x1f\x80\x27\x5b\xf0\x69\x28\x62\x6e\x2d\x21\x3f\xa0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-d6d8b478e6d13945f7a6f7d27f424ff57ca12f7f b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-d6d8b478e6d13945f7a6f7d27f424ff57ca12f7f
new file mode 100644 (file)
index 0000000..b2fca86
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x52\x00\x07\x3a\x73\x74\x61\x74\x75\x73\x03\x32\x30\x30\x0e\x7f"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-d76d0c7f24ae3cc3f530d5306b8dcc15290c7ff2 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-d76d0c7f24ae3cc3f530d5306b8dcc15290c7ff2
new file mode 100644 (file)
index 0000000..a3befc9
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x1f\xe4\x97"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-d8b15e9e555ad9900ba4be8cc9f87bef75725b24 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-d8b15e9e555ad9900ba4be8cc9f87bef75725b24
new file mode 100644 (file)
index 0000000..556eeb5
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3f\x2a\xa0\xa4\xae\x40\x08\x10\x07\x3a\xf0\x5b\x06\xf8\x63\x09\x28\x21\x21\x5c\xfe\x3b\xf0\x01\x21\x7e\x09\x1f\xdb\xe5\x47\xfd\x21\xd0\x69\x6d\x3a\x27"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-d9748abd540810c2449c3dd39a0ebb62754e520f b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-d9748abd540810c2449c3dd39a0ebb62754e520f
new file mode 100644 (file)
index 0000000..40baa1c
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\x2a\xa0\xa4\xae\xa0\xa4\xae\x08\x00\x07\x10\x63\x21\x09\x5b\xf4\x28\xf0\x28\x25\x5c\x09\x21\x63\x47\xfd\x28\x3a\x08\x00\x07\x10\x63\x21\x09\x5b\xf4\x28\xf0\x28\x21\x3a\x5c\x09\x21\x63\x47\xfd\x3a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-da9fc821f0c1e00728b139b36269bc3d21c0a8cc b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-da9fc821f0c1e00728b139b36269bc3d21c0a8cc
new file mode 100644 (file)
index 0000000..cf16b80
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x72\x62\x69\x6e\x8b\x63\x5b\x29\x28\x2d\x27\x62\x69\x6e\x09\x21\x21\x3f\xa4\x1f\xdb\xf0\x21\x10\x07\xf0\x7b\x28\x2d\x62\x69\x6e\xf0\x09\x21\x5c\x09\x21\xe5\x1f\xe9\x1b\x3b\x3f\x47\x5b\x28\x28\x21\x21\x5c\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-dcd1bd94ad97b4e67fd7e12ff1bf7c039eb17f66 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-dcd1bd94ad97b4e67fd7e12ff1bf7c039eb17f66
new file mode 100644 (file)
index 0000000..4602a15
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\xdb\x29\x80\xf0\xf0\x8e\x63\x63\x27"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-dd3ba9b139e13324fc76cd62af84b00ca8b87205 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-dd3ba9b139e13324fc76cd62af84b00ca8b87205
new file mode 100644 (file)
index 0000000..9c02c82
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x70\x83\xdb\xf0\xf0\xa4\x1f\x21\x83\xcb\x54\xf0\x2a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-de0a9dce0ea4e4bfdcb13f788ae728bf979fed25 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-de0a9dce0ea4e4bfdcb13f788ae728bf979fed25
new file mode 100644 (file)
index 0000000..04cb592
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x23\x5a\x29\xa4\x28\x1f\x2d\xa4\xa4\x10\x07\x09\x0e\x62\xf0\xa4\x0f\x2d\x62\x69\x6e\x3f\xf0\x8b\x63\x5b\x29\x28\x2d\x7f\x6e\x69\x27\x27\x62\x69\x6e\x21\x3b\x09\x21\x2f\xa4\x21\x3f\x1f\x27\xf0\x21"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-deb6f9a930d9b31586ede19fd8fd3caae0e5b1f2 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-deb6f9a930d9b31586ede19fd8fd3caae0e5b1f2
new file mode 100644 (file)
index 0000000..afa20b9
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x29\x5b\x27\x28\x3b\x2d\x63\x62\x69\x6e\x09\x21\x21\x3f\xa4\x1f\xdb\xf0\x21\x10\x07\xf0\x7b\x28\x2d\x62\x69\x6e\xf0\x09\x21\x5c\x09\x21\xe5\x1f\xe9\x1b\x3b\x3f\x47\xed\x3a\x5b\x28\x28\x21\x21\x5c\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-dee95e0280b70681eddfb68e3b418126c5661e18 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-dee95e0280b70681eddfb68e3b418126c5661e18
new file mode 100644 (file)
index 0000000..a29eb61
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x83\x63\x1f\xdb\x83\x21\x1d\xa4\xf0\xf0\xa4\x1f\x1f\x21\x83\xdb\x00\x27\x5b\x2a\xf0\xae\xa0\xa4\xba\xf0\x69\x28\x08"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-df01203edfa2dfe9e108ddde786ae48235624fef b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-df01203edfa2dfe9e108ddde786ae48235624fef
new file mode 100644 (file)
index 0000000..c26422e
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa0\xa4\xae\x40\x00\x10\x07\xf0\x5b\x63\x3b\xf8\x21\x28\x09\xfe\x28\x21\x5c\x09\x21\x63\xe5\x47\xfd\x3a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-df0adbe2523508e9afb42a58d98c2657710d6033 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-df0adbe2523508e9afb42a58d98c2657710d6033
new file mode 100644 (file)
index 0000000..78a7ff4
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\x2a\xa0\xa4\xae\xa0\xa4\xae\x08\x00\x07\x10\x63\x28\x21\xf0\xf4\x09\x28\x5b\x21\x5c\x09\x21\x63\x47\xfd\x3a\x08\x00\x07\x10\x63\x21\x09\x5b\xf4\x28\xf0\x28\x21\x5c\x09\x21\x63\x47\xfd\x3a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-e05fcba1b22f658c8bd6f3c330b2b3c9faebf977 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-e05fcba1b22f658c8bd6f3c330b2b3c9faebf977
new file mode 100644 (file)
index 0000000..73de2e4
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x10\x07\xf0\x5b\x28\x2d\x60\x69\x6e\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\xde\x69\x6e\x8b\x63\x5b\x29\x28\x3a\x27\x62\x69\x6e\x09\x21\x21\x29\x3f\xa4\x1f\xdb\xf0\x21\x10\x07\xf0\x7b\x28\x3a\x2d\x62\x69\x6e\xf0\x21\x09\xf0\x28\x09\x21\x21"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-e145caa75d73e3d819a9cb4b6217f1f53112f3f8 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-e145caa75d73e3d819a9cb4b6217f1f53112f3f8
new file mode 100644 (file)
index 0000000..f1d3548
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x1f\x21\x83\xdf\xf0\xa4\x1f\x21\x83\xdb\xa4\x10\x07\xf0\xa4\x1f\xa4\x0f\x2d\x62\x69\x6e\x83\x63\x5b\x2d\x27\x62\xe4\x3a\x6e\xf0\x09\x21\x3f\xa4\x1f\xdb\xf0\x21\x28\x21\x5c\xf0\x09\x63"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-e1d86c0094657386197d191855b5645ac1dd5936 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-e1d86c0094657386197d191855b5645ac1dd5936
new file mode 100644 (file)
index 0000000..920f701
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\x2a\xa0\xa4\xae\xa0\xa4\xae\x08\x00\x07\x10\x63\x21\x09\x85\x5b\x28\xf0\x28\x21\x5c\x09\x21\x63\x47\xfd\x3a\x08\x00\x07\x10\x63\x21\x09\x5b\xf4\x28\xf0\x28\x21\x5c\x09\x21\x63\x47\xfd\x3a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-e25adf8de44f5978d00b7e8c52aee89c5cd1fe93 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-e25adf8de44f5978d00b7e8c52aee89c5cd1fe93
new file mode 100644 (file)
index 0000000..513e8db
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3f\xa4\x1f\xdb\xf0\x21\xf0\x09\x63\x27"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-e29f05162e3d96d5549f96aa4a54c868535b2847 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-e29f05162e3d96d5549f96aa4a54c868535b2847
new file mode 100644 (file)
index 0000000..068d63a
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x0f\xa4\xdb\xf0\xf0\x83\x63\x63\x27"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-e3a970ac8636d29da3ded328b876ed3550cb3209 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-e3a970ac8636d29da3ded328b876ed3550cb3209
new file mode 100644 (file)
index 0000000..ed223a1
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x2d\x5b\x63\x2a\x28\x29\x62\x69\x6e\x09\x21\x21\x3f\xa4\x1f\xdb\xf0\x21\x3b\x07\xf0\x7b\x28\x2d\x62\x69\x6e\xf0\x09\x21\x5c\x09\x21\x2a\x1f\xe9\x1b\x3b\x3f\x47\xed\x3a\x5b\x28\x28\x21\x21\x5c\xf0"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-e3cfdc862187b4ec28bd4fb2ced5094bb5b09909 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-e3cfdc862187b4ec28bd4fb2ced5094bb5b09909
new file mode 100644 (file)
index 0000000..5cf0392
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa0\xa4\xae\x08\x00\x07\x10\xb1\xf4\x5b\x28\x21\x09\x63\x27\xf0\x28\x21\x5c\x09\x21\x63\x47\xfd\x5a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-e4ce52007d001806fc9368b62c124dfc56e8471c b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-e4ce52007d001806fc9368b62c124dfc56e8471c
new file mode 100644 (file)
index 0000000..0af4084
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x29\x07\x3a\x3b\x21\x9c\xca\x27\xd2\xd8\x29\x2a\x3b\x7d\x76\x2d\x37\x49\xcf\x21\xa4\x29\x1b\x1e\x96\x2d\x4d\x2a\xb1\xe4\xe2\x21\x27\x64\x2a\x43\x75\x18\x0e\xab\x58\x24\x30\x0e\x29\x3a\xf3\x2a\x3b\x3a\xe4\xdd\x3b\x3b\x28\x29\x3b\x3a\x5d\xef\xe6\x40"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-e52173f0bc3325629046e85e2dc41acc6ba7d1c3 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-e52173f0bc3325629046e85e2dc41acc6ba7d1c3
new file mode 100644 (file)
index 0000000..a9d2dd8
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x1f\x2d\x62\x69\x6e\x63\x28\x5b\x29\xa4\x28\xa4\x2d\x0f\xdb"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-e6589006e3bda4c57247ad66fcd73ac00ee2cbe2 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-e6589006e3bda4c57247ad66fcd73ac00ee2cbe2
new file mode 100644 (file)
index 0000000..4998c2b
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3b\x27\x63\x07\xf0\x5b\x28\x21\x09\xf0\x5b\x4e\x21\x5c\x87\x21\xe5\x47\xfd\x21\x2a\x28\x21\x09\x21\xe5\x47\xfd\x41\x29\x28\x21\x29\xed\x21\xbc\x2a\x29\xe5\x47\xfd\x49\x29\x28\xd9\x3b\x29\x8a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-e67c79d0ed89ab2d5e8d81127df22876e636ac44 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-e67c79d0ed89ab2d5e8d81127df22876e636ac44
new file mode 100644 (file)
index 0000000..eb78569
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3b\xa0\xa4\xae\x08\x00\x07\x00\x63\x00\x00\x21\x00\x09\x29\x5b\x28\xf0\x28\x21\x09\x21\x5c\x63\x47\x00\x2f\xa4\x1f\xa4\x3c\x1f\xfd\x3a\xdb\xa4\xdb\x2a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-e6fab7572fb2a1c6e107b6f83cffd103a233d021 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-e6fab7572fb2a1c6e107b6f83cffd103a233d021
new file mode 100644 (file)
index 0000000..efdfb80
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x83\x63\x00\x1f\x27\x5b\xf0\x69\x62\x6e\x2d\x21\x3f\xa4\x1f\xdb\xf0\x21\x28\x21\x5c\xf0\x09\x43"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-e790f5d312957dbfd20abdefe4b1735779ff9689 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-e790f5d312957dbfd20abdefe4b1735779ff9689
new file mode 100644 (file)
index 0000000..53ff267
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x13\x01\x32\x00\x00\x00\x00\x00\x00\x00\x00\x00\x3a\x7e\xa4\xa4\x2f\x1f\xa4\x5b\x28\xa4\x21\x21\x1f\xff\xff\xff\xff\x0f\xa4\x0e\x7f\xa4\x00\x00"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-e8809017a4cf6c1e80a93f661166ead961f26bb4 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-e8809017a4cf6c1e80a93f661166ead961f26bb4
new file mode 100644 (file)
index 0000000..40926d9
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\x2a\xa0\xa4\xae\xa0\xa4\xae\x08\x00\x07\x10\x63\x21\x5b\xf4\x28\xf0\x28\x21\x5c\x09\x21\x63\x47\xfd\x3a\x1e\x00\x03\x10\x63\x21\x09\x5b\xf4\x28\xf0\x28\x21\x5c\x09\x21\x63\x47\xfd\x3a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-e9733e973c33b38c2087b7f1deb36688b3b14259 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-e9733e973c33b38c2087b7f1deb36688b3b14259
new file mode 100644 (file)
index 0000000..f11282b
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x63\x2a\x5b\x29\xa4\x0f\x28\x2a\xa0\xa4\xae\x40\x08\x10\x3a\xf0\x07\x5b\x28\x3f\xa4\x07\x3b\x5b\x28\x27\xa4\xf0\x28\x2d\xa4\xdb\x21\x09\xf0\x27\xf0\x1f\x62"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-ea8134769855d574f6673bf0301eb2e24632c6eb b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-ea8134769855d574f6673bf0301eb2e24632c6eb
new file mode 100644 (file)
index 0000000..c1e2bc4
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x10\x07\xf0\x5b\x28\x2d\x62\x69\x6e\xa4\xa4\x10\x07\xf0\xa4\x2d\x62\x69\x6e\x8b\x63\x5b\x29\x28\x2d\x27\x62\x69\x6e\x09\x21\x21\x3f\xa4\x1f\xdb\xf0\x21\x10\x07\xf0\x7b\x28\x2d\x62\x69\x6e\xf0\x21\x09\xf0\x28\x09\x21\x21"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-eb489536e4e5589a93a17cd36669475b8f2a5e1b b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-eb489536e4e5589a93a17cd36669475b8f2a5e1b
new file mode 100644 (file)
index 0000000..83bdd49
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x23\x5a\x29\xa4\x28\x2d\xa4\x0e\x09\x62\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x3f\xf0\x8b\x63\x5b\x29\x28\x2d\x7f\x6e\x69\x27\x27\x62\x69\x6e\x21\x21\x09\x21\x2f\xa4\x21\x3f\x1f\xdb\xf0\x21"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-eb48ebd4d01e5623dd16ae61938b3333fab3ce78 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-eb48ebd4d01e5623dd16ae61938b3333fab3ce78
new file mode 100644 (file)
index 0000000..749d30f
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x1f\xa4\xdb\xf0\xf0\xdc\x63\x63\x27"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-eb6ca7624384239c7f7e0d83edb7cc334b7926d7 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-eb6ca7624384239c7f7e0d83edb7cc334b7926d7
new file mode 100644 (file)
index 0000000..8afcd91
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa0\xa4\xae\x08\x00\x07\x10\x63\x00\x00\x21\x09\x00\x5b\xf4\x28\xf0\x28\x21\x5c\x09\x21\x63\x47\x00\x2f\xa4\x1f\xa4\xa4\x1f\xfd\x3a\xdb\xa4\xdb\x2a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-ec9457ad41ed745ea9377ffdb16ad09f981daa7f b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-ec9457ad41ed745ea9377ffdb16ad09f981daa7f
new file mode 100644 (file)
index 0000000..517bc17
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\x2a\xa0\xa4\xae\xa0\xa4\xae\x08\x00\x07\x10\x63\x21\x09\x5b\xf4\x28\xf0\x28\x25\x5c\x09\x21\x63\x47\xfd\x3a\x08\x00\x07\x10\x63\x21\x09\x5b\xf4\x28\xf0\x28\x21\x5c\x09\x21\x63\x47\xfd\x3a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-edff5256a2d60d0e51caef25dc1d6f1643dad6d5 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-edff5256a2d60d0e51caef25dc1d6f1643dad6d5
new file mode 100644 (file)
index 0000000..44fd648
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\xc3\x00\x6a\x21\xa0\xae\x08\xa4\x10\x07\xf0\x5b\x28\x63\xa4\x1f\x1f\x2a\x27\x5b\x5b\xf0\x28\x00\x21\x21\x09"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-ee4d9c5d22512da42726f47213ff56404d1d81d1 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-ee4d9c5d22512da42726f47213ff56404d1d81d1
new file mode 100644 (file)
index 0000000..9ac4929
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa4\xae\x08\x00\x1e\x00\x63\x21\x09\x5b\xf4\xf1\x28\x21\x5c\x09\x21\x63\x47\xfd\x3a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-eef2f30b5e2ecd98ebefb12d57aba8b4ad52d904 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-eef2f30b5e2ecd98ebefb12d57aba8b4ad52d904
new file mode 100644 (file)
index 0000000..f1f5759
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3f\xf0\x09\x1f\xdb\x21\xf0\x63\x6d\x27"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-ef23911de1a27d03d2d4983ca1527e17d6a7092b b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-ef23911de1a27d03d2d4983ca1527e17d6a7092b
new file mode 100644 (file)
index 0000000..e7b2c60
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x30\x63\x27\xf0\x5b\x28\x21\x09\xf0\x5b\x28\x21\x5c\x09\x21\xe5\x47\xfd\x21\x5b\x28\x21\x21\x09\x21\xe5\x47\xfd\x41\x29\x28\x21\x29\xed\x21\xbc\x2a\x29\xe5\x47\xfd\x41\x29\x28\xd9\x3b\x29\x8a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-ef5b7fc62a2daecf1e8f928b1fa3ebd028413a41 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-ef5b7fc62a2daecf1e8f928b1fa3ebd028413a41
new file mode 100644 (file)
index 0000000..5199df3
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x63\x5b\x28\x21\x21\x09\x21\xe5\x47\xfd\x41\x29\x28\x21\x29\xed\x21\xbc\x2a\x29\xd9\x8a\x3b\x2a\x87\x3a\x2a\xd5\xee\x28\xf9\x29\x5d\x28\x28\x3b\x27\x27\x3b\x96\x25\xef\x29\xe6\xd3\x90\xf5\x33\x29\x27\xd3\x29\xca\xd1\x43\x2a\x29\x9c\x95\x00\x29\x28\xf0\x65"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-ef718258ca1870198e91a2fbc1eaa90b620673fb b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-ef718258ca1870198e91a2fbc1eaa90b620673fb
new file mode 100644 (file)
index 0000000..afebc4e
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x63\x5b\x29\xb2\x28\x2d\x27\x62\x69\x6e\xa4"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-efb46deb37a78f41dd760f6b7203b20956eb114e b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-efb46deb37a78f41dd760f6b7203b20956eb114e
new file mode 100644 (file)
index 0000000..e96889e
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3b\x3f\x30\x63\x21\x28\x07\xf0\x4b\x09\xf0\x13\x4e\xd4\x5c\x09\x21\xe5\x47\x21\x5b\x28\x21\x21\x09\x21\xe5\x47\xfd\x41\x29\x28\x3a\x29\xed\x21\x2a\xe5\xbc\x47\x80\xfd\x41\x29\x28\xd9\x3b\x29\x8a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-efdd6824bd2456e3e408e0e84369c4fa3aa14f41 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-efdd6824bd2456e3e408e0e84369c4fa3aa14f41
new file mode 100644 (file)
index 0000000..6fd7674
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x30\x63\x07\xf0\x5b\x28\x21\x09\xf0\x5b\x28\x21\x5c\x09\x21\xe5\x47\xfd\x21\x5b\x28\x21\x21\x09\x21\xe5\x47\xfd\x41\x29\x28\x21\x29\xed\x21\xbc\x2a\x29\xe5\x47\xfd\x41\x29\x28\xd9\x3b\x29\x8a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-efec040a5de1969df5e37e4bc50a0a8f0de341d8 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-efec040a5de1969df5e37e4bc50a0a8f0de341d8
new file mode 100644 (file)
index 0000000..e764779
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x28\x3f\xa4\x3a\x1f\x9b\xf0\x21\x09\x63"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-f1e30464c24dc1d7cec7ec1dd2adec8512232b43 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-f1e30464c24dc1d7cec7ec1dd2adec8512232b43
new file mode 100644 (file)
index 0000000..3d731b8
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\xa4\x2d\x5b\x63\x27\x21\x29\xa4\x24\x0f\xa4\xdb\x3b\xf0\x83\x00\x10\x62\x69\x07\x63\x63\x27"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-f27a617b936814476770a3b31a5afb80d0f3b423 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-f27a617b936814476770a3b31a5afb80d0f3b423
new file mode 100644 (file)
index 0000000..939decb
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x13\x00\x00\x00\x00\x00\x00\xa4\x2f\xa4\x7e\x1f\xa4\x5b\x28\xa4\x21\x21\x1f\xff\xff\xff\xff\x0f\xa4\x00\x00"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-f3f0d99ac2962f8fddb25c65fb4c8c6eb63518a9 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-f3f0d99ac2962f8fddb25c65fb4c8c6eb63518a9
new file mode 100644 (file)
index 0000000..7c8e10c
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x63\x5b\x29\x28\x3f\x2a\xa0\xa4\xae\x40\x08\x10\x07\x3a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-f4628084cf46f139babb886a782b4ab5977d5d2e b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-f4628084cf46f139babb886a782b4ab5977d5d2e
new file mode 100644 (file)
index 0000000..de954c3
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x28\x3f\xa4\x07\x3b\x5b\x28\x27\xa4\xf0\x21\x09\x1f\x28"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-f4753e8881e4b3c71f2728149be7d04cc648f6a6 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-f4753e8881e4b3c71f2728149be7d04cc648f6a6
new file mode 100644 (file)
index 0000000..066493f
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3f\x2a\xa0\xa4\xae\x40\x08\x10\x07\x5a\x6e\xf0\x3a\x28\x63\x09\x28\x3b\xfe\x21\x28\x63\x1f\x21\x09\x3b\x5c\x09\xdb\xe4\x47\xfd\x21\xf0\x63\x6d\x3a\x27"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-f4b48c4f3f310ed767755267210f212dd62bd715 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-f4b48c4f3f310ed767755267210f212dd62bd715
new file mode 100644 (file)
index 0000000..63fda34
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x10\xa4\x07\xa4\xf0\xa4\x0f\x2d\x62\x00\x10\x63\x6f\x6e\x74\x65\x6e\x74\x2d\x6c\x6f\x63\x61\x74\x69\x6f\x6e\x00\x69\x6e\x8b\x63\x5b\x29\x28\x3f\x2a\xa0\xa4\xae\x40\x08\x10\xa4\x1f\x07\x3a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-f4d6ff635ae4fda497221da4bfa3e593df59a44e b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-f4d6ff635ae4fda497221da4bfa3e593df59a44e
new file mode 100644 (file)
index 0000000..9d30148
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x29\x6e\x8b\x63\x5b\x29\x28\x3a\x2a\xa0\xa4\xae\x40\x08\x31\x07\x3a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-f52f4d51aaaed0f9c3a20936cf5efd25d0692f67 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-f52f4d51aaaed0f9c3a20936cf5efd25d0692f67
new file mode 100644 (file)
index 0000000..a50b5a1
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x70\x83\xdb\xf0\xf0\xa4\x1f\x21\x83\xdb\xf0\x54\xf0\x2a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-f7cf30724ab740918eee6e4a6b6658ae3d7706e8 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-f7cf30724ab740918eee6e4a6b6658ae3d7706e8
new file mode 100644 (file)
index 0000000..586978b
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x08\x63"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-f823828ffd2a60efee36f1de52cb0f024ac5b4bb b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-f823828ffd2a60efee36f1de52cb0f024ac5b4bb
new file mode 100644 (file)
index 0000000..c20432c
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\x1f\xdb\xf0\x21\xf0\x09\x63\x27"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-f8760761bd5ab7b47376bfbc5a44e16b2d5ca800 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-f8760761bd5ab7b47376bfbc5a44e16b2d5ca800
new file mode 100644 (file)
index 0000000..c5f9302
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x63\x5b\x27\x27\x28\x2d\x27\x62\x69\x6e\x09\x21\x21\x3f\xa4\x1f\xa4\x08\x63\xdb\xf0\x21\x10"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-fb15042c268625089ef6c8aa3d8a6f12d1d02c74 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-fb15042c268625089ef6c8aa3d8a6f12d1d02c74
new file mode 100644 (file)
index 0000000..76c178d
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x10\x07\xf0\x5b\x28\x21\x09\xf0\x28\x21\x5c\x09\x21\xe5\x47\xfd\x3a\x5b\x28\x21\x27\xf0\x5b\x28\x21\x21\x09\xf0\x5b\x28\x21\x21\x09\x21\xe5\x47\xfd\x21\xe5\x47\xfd\x41\x29\x28\x13\x5b\x28\x09\x21\x21\xe5"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-fc3dd4292d6884a770199596f5e9cbc1e869e5fb b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-fc3dd4292d6884a770199596f5e9cbc1e869e5fb
new file mode 100644 (file)
index 0000000..b7fd983
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\x2a\xa0\xa4\xae\xa0\xa4\xae\x08\x00\x07\x10\x63\x21\x09\x5b\xf4\xb1\xf0\x25\x5c\x09\x27\x21\x63\x47\xfd\x3a\x08\x00\x07\x10\x63\x21\x09\x5b\xf4\x28\xf0\x28\x21\x5c\x09\x21\x63\x47\xfd\x3a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-fcc06696e641a7743bfd2f3b7ecd88e7b727e00a b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-fcc06696e641a7743bfd2f3b7ecd88e7b727e00a
new file mode 100644 (file)
index 0000000..4b64eb3
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x3b\x3f\x27\x63\x07\xf0\x5b\x28\x21\x09\xf0\x5b\x4e\x21\x5c\x09\x21\xe5\x47\xfd\x21\x06\x61\x63\x63\x65\x70\x74\xfd\x2e\x3a\xa4\x63\x41\x29\x28\x21\x29\xed\x21\xbc\xaa\x29\xe5\x67\xdd\x49\x29\x28\xd9\x3b\x29\x8a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-fd34ec90fe8f9218fd25c3eac151aec998cff6d8 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-fd34ec90fe8f9218fd25c3eac151aec998cff6d8
new file mode 100644 (file)
index 0000000..9ada2c5
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x2a\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x83\x63\x1f\x00\x27\x5b\xf0\x69\x28\xe2\x6e\x2d\x21\x3f\xa4\x1f\xdb\xf0\x21\x28\x21\x5c\xf0\x09\x63"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-fdf548cde981fab4fb17bd63a124b75eddc5c836 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-fdf548cde981fab4fb17bd63a124b75eddc5c836
new file mode 100644 (file)
index 0000000..8e46d16
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x1f\xca\x21\xf0\x09\x63\x28\x3f\xa4\x29\x5b\x27\x1f\x9b\xf0\x21\x09\x63\x27\x28"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-fe47fb18b064e26479c3c3140082bd01065e897a b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-fe47fb18b064e26479c3c3140082bd01065e897a
new file mode 100644 (file)
index 0000000..11c086b
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x28\x3f\x3f\x81\x3b\x5b\x28\xa4\x28\x27\x3f\xa4\x07"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-ff2097734bd7bb8451aece13c9336c4624735170 b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-ff2097734bd7bb8451aece13c9336c4624735170
new file mode 100644 (file)
index 0000000..a5213e9
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x63\x28\xa0\xa4\xae\x08\x00\x07\x10\xf4\x5b\x28\x21\x09\x63\xf0\x28\x21\x5c\x09\x21\x63\x2a\x5b\x29\x47\xfd\xa4\x0f\x28\x3a\x0f\x2a\xa0\xa4\xae\x40\x08\x10\x3a"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-ff2c949863eb4e14d9e835c51591304403d91b6c b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-ff2c949863eb4e14d9e835c51591304403d91b6c
new file mode 100644 (file)
index 0000000..9c12598
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\x04\x00\xa4\x08\x63"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/upgraded-ff7d6ff060e63355701b2e655c802902338497de b/test/core/transport/chttp2/hpack_parser_corpus/upgraded-ff7d6ff060e63355701b2e655c802902338497de
new file mode 100644 (file)
index 0000000..2c55fd0
--- /dev/null
@@ -0,0 +1,4 @@
+frames {
+  max_metadata_length: 4096
+  parse: "\xa4\xa4\x10\x07\xf0\xa4\x0f\x2d\x62\x69\x6e\x8b\x63\x97\x2a\x5b\x29\xa4\x0f\x28\x2d\xa4\xdb\xf0\x27\xf0\x21\x62\x83\x63\x69\x6e\x09\x3b\x21\x21"
+}
diff --git a/test/core/transport/chttp2/hpack_parser_fuzzer.proto b/test/core/transport/chttp2/hpack_parser_fuzzer.proto
new file mode 100644 (file)
index 0000000..da2eb62
--- /dev/null
@@ -0,0 +1,33 @@
+// 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.
+
+syntax = "proto3";
+
+package hpack_parser_fuzzer;
+
+message Empty {}
+
+message Frame {
+  bool end_of_headers = 1;
+  bool end_of_stream = 2;
+  bool priority = 3;
+  int32 stop_buffering_after_segments = 4;
+  int32 max_metadata_length = 5;
+  repeated bytes parse = 6;
+}
+
+message Msg {
+  repeated Frame frames = 2;
+}
+
index 3914fc7..99e0eea 100644 (file)
 #include "src/core/ext/transport/chttp2/transport/hpack_parser.h"
 #include "src/core/lib/iomgr/exec_ctx.h"
 #include "src/core/lib/slice/slice_internal.h"
+#include "src/libfuzzer/libfuzzer_macro.h"
+#include "test/core/transport/chttp2/hpack_parser_fuzzer.pb.h"
 
 bool squelch = true;
 bool leak_check = true;
 
-static grpc_error_handle onhdr(grpc_mdelem md) {
-  GRPC_MDELEM_UNREF(md);
-  return GRPC_ERROR_NONE;
-}
 static void dont_log(gpr_log_func_args* /*args*/) {}
 
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+DEFINE_PROTO_FUZZER(const hpack_parser_fuzzer::Msg& msg) {
   grpc_test_only_set_slice_hash_seed(0);
   if (squelch) gpr_set_log_function(dont_log);
   grpc_init();
   {
-    grpc_core::ExecCtx exec_ctx;
-    grpc_core::HPackParser parser;
-    parser.BeginFrame(onhdr, grpc_core::HPackParser::Boundary::None,
-                      grpc_core::HPackParser::Priority::None);
-    GRPC_ERROR_UNREF(
-        parser.Parse(grpc_slice_from_static_buffer(data, size), true));
+    std::unique_ptr<grpc_core::HPackParser> parser(new grpc_core::HPackParser);
+    for (int i = 0; i < msg.frames_size(); i++) {
+      auto arena = grpc_core::MakeScopedArena(1024);
+      grpc_core::ExecCtx exec_ctx;
+      grpc_metadata_batch b(arena.get());
+
+      const auto& frame = msg.frames(i);
+      grpc_core::HPackParser::Boundary boundary =
+          grpc_core::HPackParser::Boundary::None;
+      if (frame.end_of_headers()) {
+        boundary = grpc_core::HPackParser::Boundary::EndOfHeaders;
+      }
+      if (frame.end_of_stream()) {
+        boundary = grpc_core::HPackParser::Boundary::EndOfStream;
+      }
+      grpc_core::HPackParser::Priority priority =
+          grpc_core::HPackParser::Priority::None;
+      if (frame.priority()) {
+        priority = grpc_core::HPackParser::Priority::Included;
+      }
+      int max_length = 1024;
+      if (frame.max_metadata_length() != 0) {
+        max_length = frame.max_metadata_length();
+      }
+
+      parser->BeginFrame(
+          &b, max_length, boundary, priority,
+          grpc_core::HPackParser::LogInfo{
+              1, grpc_core::HPackParser::LogInfo::kHeaders, false});
+      int stop_buffering_ctr =
+          std::max(-1, frame.stop_buffering_after_segments());
+      for (const auto& parse : frame.parse()) {
+        grpc_slice buffer =
+            grpc_slice_from_copied_buffer(parse.data(), parse.size());
+        GRPC_ERROR_UNREF(parser->Parse(buffer, i == msg.frames_size() - 1));
+        grpc_slice_unref(buffer);
+        stop_buffering_ctr--;
+        if (0 == stop_buffering_ctr) parser->StopBufferingFrame();
+      }
+      parser->FinishFrame();
+    }
   }
   grpc_shutdown();
-  return 0;
 }
index 6c47e52..ab4cb60 100644 (file)
@@ -23,6 +23,8 @@
 
 #include <string>
 
+#include <gtest/gtest.h>
+
 #include "absl/strings/str_cat.h"
 
 #include <grpc/grpc.h>
 #include "src/core/lib/slice/slice_internal.h"
 #include "test/core/util/test_config.h"
 
-#define LOG_TEST(x) gpr_log(GPR_INFO, "%s", x)
-
-using grpc_core::HPackTable;
-
-static void assert_str(const HPackTable* /*tbl*/, grpc_slice mdstr,
-                       const char* str) {
-  GPR_ASSERT(grpc_slice_str_cmp(mdstr, str) == 0);
+namespace grpc_core {
+namespace {
+void AssertIndex(const HPackTable* tbl, uint32_t idx, const char* key,
+                 const char* value) {
+  const auto* md = tbl->Lookup(idx);
+  ASSERT_NE(md, nullptr);
+  EXPECT_EQ(md->DebugString(), absl::StrCat(key, ": ", value));
 }
+}  // namespace
 
-static void assert_index(const HPackTable* tbl, uint32_t idx, const char* key,
-                         const char* value) {
-  grpc_mdelem md = tbl->Peek(idx);
-  assert_str(tbl, GRPC_MDKEY(md), key);
-  assert_str(tbl, GRPC_MDVALUE(md), value);
-}
-
-static void test_static_lookup(void) {
+TEST(HpackParserTableTest, StaticTable) {
   grpc_core::ExecCtx exec_ctx;
   HPackTable tbl;
 
-  LOG_TEST("test_static_lookup");
-  assert_index(&tbl, 1, ":authority", "");
-  assert_index(&tbl, 2, ":method", "GET");
-  assert_index(&tbl, 3, ":method", "POST");
-  assert_index(&tbl, 4, ":path", "/");
-  assert_index(&tbl, 5, ":path", "/index.html");
-  assert_index(&tbl, 6, ":scheme", "http");
-  assert_index(&tbl, 7, ":scheme", "https");
-  assert_index(&tbl, 8, ":status", "200");
-  assert_index(&tbl, 9, ":status", "204");
-  assert_index(&tbl, 10, ":status", "206");
-  assert_index(&tbl, 11, ":status", "304");
-  assert_index(&tbl, 12, ":status", "400");
-  assert_index(&tbl, 13, ":status", "404");
-  assert_index(&tbl, 14, ":status", "500");
-  assert_index(&tbl, 15, "accept-charset", "");
-  assert_index(&tbl, 16, "accept-encoding", "gzip, deflate");
-  assert_index(&tbl, 17, "accept-language", "");
-  assert_index(&tbl, 18, "accept-ranges", "");
-  assert_index(&tbl, 19, "accept", "");
-  assert_index(&tbl, 20, "access-control-allow-origin", "");
-  assert_index(&tbl, 21, "age", "");
-  assert_index(&tbl, 22, "allow", "");
-  assert_index(&tbl, 23, "authorization", "");
-  assert_index(&tbl, 24, "cache-control", "");
-  assert_index(&tbl, 25, "content-disposition", "");
-  assert_index(&tbl, 26, "content-encoding", "");
-  assert_index(&tbl, 27, "content-language", "");
-  assert_index(&tbl, 28, "content-length", "");
-  assert_index(&tbl, 29, "content-location", "");
-  assert_index(&tbl, 30, "content-range", "");
-  assert_index(&tbl, 31, "content-type", "");
-  assert_index(&tbl, 32, "cookie", "");
-  assert_index(&tbl, 33, "date", "");
-  assert_index(&tbl, 34, "etag", "");
-  assert_index(&tbl, 35, "expect", "");
-  assert_index(&tbl, 36, "expires", "");
-  assert_index(&tbl, 37, "from", "");
-  assert_index(&tbl, 38, "host", "");
-  assert_index(&tbl, 39, "if-match", "");
-  assert_index(&tbl, 40, "if-modified-since", "");
-  assert_index(&tbl, 41, "if-none-match", "");
-  assert_index(&tbl, 42, "if-range", "");
-  assert_index(&tbl, 43, "if-unmodified-since", "");
-  assert_index(&tbl, 44, "last-modified", "");
-  assert_index(&tbl, 45, "link", "");
-  assert_index(&tbl, 46, "location", "");
-  assert_index(&tbl, 47, "max-forwards", "");
-  assert_index(&tbl, 48, "proxy-authenticate", "");
-  assert_index(&tbl, 49, "proxy-authorization", "");
-  assert_index(&tbl, 50, "range", "");
-  assert_index(&tbl, 51, "referer", "");
-  assert_index(&tbl, 52, "refresh", "");
-  assert_index(&tbl, 53, "retry-after", "");
-  assert_index(&tbl, 54, "server", "");
-  assert_index(&tbl, 55, "set-cookie", "");
-  assert_index(&tbl, 56, "strict-transport-security", "");
-  assert_index(&tbl, 57, "transfer-encoding", "");
-  assert_index(&tbl, 58, "user-agent", "");
-  assert_index(&tbl, 59, "vary", "");
-  assert_index(&tbl, 60, "via", "");
-  assert_index(&tbl, 61, "www-authenticate", "");
+  AssertIndex(&tbl, 1, ":authority", "");
+  AssertIndex(&tbl, 2, ":method", "GET");
+  AssertIndex(&tbl, 3, ":method", "POST");
+  AssertIndex(&tbl, 4, ":path", "/");
+  AssertIndex(&tbl, 5, ":path", "/index.html");
+  AssertIndex(&tbl, 6, ":scheme", "http");
+  AssertIndex(&tbl, 7, ":scheme", "https");
+  AssertIndex(&tbl, 8, ":status", "200");
+  AssertIndex(&tbl, 9, ":status", "204");
+  AssertIndex(&tbl, 10, ":status", "206");
+  AssertIndex(&tbl, 11, ":status", "304");
+  AssertIndex(&tbl, 12, ":status", "400");
+  AssertIndex(&tbl, 13, ":status", "404");
+  AssertIndex(&tbl, 14, ":status", "500");
+  AssertIndex(&tbl, 15, "accept-charset", "");
+  AssertIndex(&tbl, 16, "accept-encoding", "gzip, deflate");
+  AssertIndex(&tbl, 17, "accept-language", "");
+  AssertIndex(&tbl, 18, "accept-ranges", "");
+  AssertIndex(&tbl, 19, "accept", "");
+  AssertIndex(&tbl, 20, "access-control-allow-origin", "");
+  AssertIndex(&tbl, 21, "age", "");
+  AssertIndex(&tbl, 22, "allow", "");
+  AssertIndex(&tbl, 23, "authorization", "");
+  AssertIndex(&tbl, 24, "cache-control", "");
+  AssertIndex(&tbl, 25, "content-disposition", "");
+  AssertIndex(&tbl, 26, "content-encoding", "");
+  AssertIndex(&tbl, 27, "content-language", "");
+  AssertIndex(&tbl, 28, "content-length", "");
+  AssertIndex(&tbl, 29, "content-location", "");
+  AssertIndex(&tbl, 30, "content-range", "");
+  AssertIndex(&tbl, 31, "content-type", "");
+  AssertIndex(&tbl, 32, "cookie", "");
+  AssertIndex(&tbl, 33, "date", "");
+  AssertIndex(&tbl, 34, "etag", "");
+  AssertIndex(&tbl, 35, "expect", "");
+  AssertIndex(&tbl, 36, "expires", "");
+  AssertIndex(&tbl, 37, "from", "");
+  AssertIndex(&tbl, 38, "host", "");
+  AssertIndex(&tbl, 39, "if-match", "");
+  AssertIndex(&tbl, 40, "if-modified-since", "");
+  AssertIndex(&tbl, 41, "if-none-match", "");
+  AssertIndex(&tbl, 42, "if-range", "");
+  AssertIndex(&tbl, 43, "if-unmodified-since", "");
+  AssertIndex(&tbl, 44, "last-modified", "");
+  AssertIndex(&tbl, 45, "link", "");
+  AssertIndex(&tbl, 46, "location", "");
+  AssertIndex(&tbl, 47, "max-forwards", "");
+  AssertIndex(&tbl, 48, "proxy-authenticate", "");
+  AssertIndex(&tbl, 49, "proxy-authorization", "");
+  AssertIndex(&tbl, 50, "range", "");
+  AssertIndex(&tbl, 51, "referer", "");
+  AssertIndex(&tbl, 52, "refresh", "");
+  AssertIndex(&tbl, 53, "retry-after", "");
+  AssertIndex(&tbl, 54, "server", "");
+  AssertIndex(&tbl, 55, "set-cookie", "");
+  AssertIndex(&tbl, 56, "strict-transport-security", "");
+  AssertIndex(&tbl, 57, "transfer-encoding", "");
+  AssertIndex(&tbl, 58, "user-agent", "");
+  AssertIndex(&tbl, 59, "vary", "");
+  AssertIndex(&tbl, 60, "via", "");
+  AssertIndex(&tbl, 61, "www-authenticate", "");
 }
 
-static void test_many_additions(void) {
+TEST(HpackParserTableTest, ManyAdditions) {
   HPackTable tbl;
   int i;
 
-  LOG_TEST("test_many_additions");
-
   grpc_core::ExecCtx exec_ctx;
 
   for (i = 0; i < 100000; i++) {
     grpc_mdelem elem;
-    std::string key = absl::StrCat("K:", i);
-    std::string value = absl::StrCat("VALUE:", i);
+    std::string key = absl::StrCat("K.", i);
+    std::string value = absl::StrCat("VALUE.", i);
     elem = grpc_mdelem_from_slices(grpc_slice_from_cpp_string(key),
                                    grpc_slice_from_cpp_string(value));
-    GPR_ASSERT(tbl.Add(elem) == GRPC_ERROR_NONE);
-    GRPC_MDELEM_UNREF(elem);
-    assert_index(&tbl, 1 + grpc_core::hpack_constants::kLastStaticEntry,
-                 key.c_str(), value.c_str());
+    ASSERT_EQ(tbl.Add(HPackTable::Memento(elem)), GRPC_ERROR_NONE);
+    AssertIndex(&tbl, 1 + grpc_core::hpack_constants::kLastStaticEntry,
+                key.c_str(), value.c_str());
     if (i) {
-      std::string key = absl::StrCat("K:", i - 1);
-      std::string value = absl::StrCat("VALUE:", i - 1);
-      assert_index(&tbl, 2 + grpc_core::hpack_constants::kLastStaticEntry,
-                   key.c_str(), value.c_str());
+      std::string key = absl::StrCat("K.", i - 1);
+      std::string value = absl::StrCat("VALUE.", i - 1);
+      AssertIndex(&tbl, 2 + grpc_core::hpack_constants::kLastStaticEntry,
+                  key.c_str(), value.c_str());
     }
   }
 }
 
+}  // namespace grpc_core
+
 int main(int argc, char** argv) {
+  ::testing::InitGoogleTest(&argc, argv);
   grpc::testing::TestEnvironment env(argc, argv);
   grpc_init();
-  test_static_lookup();
-  test_many_additions();
+  int r = RUN_ALL_TESTS();
   grpc_shutdown();
-  return 0;
+  return r;
 }
index 6b052f9..7327c6d 100644 (file)
@@ -18,7 +18,7 @@
 
 #include "src/core/ext/transport/chttp2/transport/hpack_parser.h"
 
-#include <stdarg.h>
+#include <gtest/gtest.h>
 
 #include <grpc/grpc.h>
 #include <grpc/slice.h>
 #include "test/core/util/slice_splitter.h"
 #include "test/core/util/test_config.h"
 
-using MDVec = std::vector<std::pair<const char*, const char*>>;
-
-struct TestChecker {
-  MDVec* expect;
-
-  explicit TestChecker(MDVec* expect) : expect(expect) {}
+struct TestInput {
+  const char* input;
+  const char* expected_parse;
+};
 
-  grpc_error_handle operator()(grpc_mdelem md) {
-    GPR_ASSERT(!expect->empty());
-    auto e = expect->begin();
-    GPR_ASSERT(grpc_slice_str_cmp(GRPC_MDKEY(md), e->first) == 0);
-    GPR_ASSERT(grpc_slice_str_cmp(GRPC_MDVALUE(md), e->second) == 0);
-    GRPC_MDELEM_UNREF(md);
-    expect->erase(e);
-    return GRPC_ERROR_NONE;
-  }
+struct Test {
+  absl::optional<size_t> table_size;
+  std::vector<TestInput> inputs;
 };
 
-static void test_vector(grpc_core::HPackParser* parser,
-                        grpc_slice_split_mode mode, const char* hexstring,
-                        MDVec expect) {
-  grpc_slice input = parse_hexstring(hexstring);
-  grpc_slice* slices;
-  size_t nslices;
-  size_t i;
+class ParseTest : public ::testing::TestWithParam<Test> {
+ public:
+  ParseTest() {
+    grpc_init();
+    parser_ = absl::make_unique<grpc_core::HPackParser>();
+  }
 
-  parser->BeginFrame(TestChecker(&expect),
-                     grpc_core::HPackParser::Boundary::None,
-                     grpc_core::HPackParser::Priority::None);
+  ~ParseTest() override {
+    {
+      grpc_core::ExecCtx exec_ctx;
+      parser_.reset();
+    }
 
-  grpc_split_slices(mode, &input, 1, &slices, &nslices);
-  grpc_slice_unref(input);
+    grpc_shutdown();
+  }
 
-  for (i = 0; i < nslices; i++) {
-    grpc_core::ExecCtx exec_ctx;
-    auto err = parser->Parse(slices[i], i == nslices - 1);
-    if (err != GRPC_ERROR_NONE) {
-      gpr_log(GPR_ERROR, "Unexpected parse error: %s", grpc_error_string(err));
-      abort();
+  void SetUp() override {
+    if (GetParam().table_size.has_value()) {
+      parser_->hpack_table()->SetMaxBytes(GetParam().table_size.value());
+      EXPECT_EQ(parser_->hpack_table()->SetCurrentTableSize(
+                    GetParam().table_size.value()),
+                GRPC_ERROR_NONE);
     }
   }
 
-  for (i = 0; i < nslices; i++) {
-    grpc_slice_unref(slices[i]);
-  }
-  gpr_free(slices);
+  void TestVector(grpc_slice_split_mode mode, const char* hexstring,
+                  std::string expect) {
+    auto arena = grpc_core::MakeScopedArena(1024);
+    grpc_core::ExecCtx exec_ctx;
+    grpc_slice input = parse_hexstring(hexstring);
+    grpc_slice* slices;
+    size_t nslices;
+    size_t i;
 
-  GPR_ASSERT(expect.empty());
-}
+    grpc_metadata_batch b(arena.get());
 
-static void test_vectors(grpc_slice_split_mode mode) {
-  grpc_core::ExecCtx exec_ctx;
+    parser_->BeginFrame(
+        &b, 4096, grpc_core::HPackParser::Boundary::None,
+        grpc_core::HPackParser::Priority::None,
+        grpc_core::HPackParser::LogInfo{
+            1, grpc_core::HPackParser::LogInfo::kHeaders, false});
 
-  {
-    grpc_core::HPackParser parser;
-    /* D.2.1 */
-    test_vector(&parser, mode,
-                "400a 6375 7374 6f6d 2d6b 6579 0d63 7573"
-                "746f 6d2d 6865 6164 6572",
-                {std::make_pair("custom-key", "custom-header")});
-    /* D.2.2 */
-    test_vector(&parser, mode, "040c 2f73 616d 706c 652f 7061 7468",
-                {std::make_pair(":path", "/sample/path")});
-    /* D.2.3 */
-    test_vector(&parser, mode,
-                "1008 7061 7373 776f 7264 0673 6563 7265"
-                "74",
-                {std::make_pair("password", "secret")});
-    /* D.2.4 */
-    test_vector(&parser, mode, "82", {std::make_pair(":method", "GET")});
-  }
+    grpc_split_slices(mode, &input, 1, &slices, &nslices);
+    grpc_slice_unref(input);
 
-  {
-    grpc_core::HPackParser parser;
-    /* D.3.1 */
-    test_vector(
-        &parser, mode,
-        "8286 8441 0f77 7777 2e65 7861 6d70 6c65"
-        "2e63 6f6d",
-        {std::make_pair(":method", "GET"), std::make_pair(":scheme", "http"),
-         std::make_pair(":path", "/"),
-         std::make_pair(":authority", "www.example.com")});
-    /* D.3.2 */
-    test_vector(
-        &parser, mode, "8286 84be 5808 6e6f 2d63 6163 6865",
-        {std::make_pair(":method", "GET"), std::make_pair(":scheme", "http"),
-         std::make_pair(":path", "/"),
-         std::make_pair(":authority", "www.example.com"),
-         std::make_pair("cache-control", "no-cache")});
-    /* D.3.3 */
-    test_vector(&parser, mode,
-                "8287 85bf 400a 6375 7374 6f6d 2d6b 6579"
-                "0c63 7573 746f 6d2d 7661 6c75 65",
-                {
-                    std::make_pair(":method", "GET"),
-                    std::make_pair(":scheme", "https"),
-                    std::make_pair(":path", "/index.html"),
-                    std::make_pair(":authority", "www.example.com"),
-                    std::make_pair("custom-key", "custom-value"),
-                });
-  }
+    for (i = 0; i < nslices; i++) {
+      grpc_core::ExecCtx exec_ctx;
+      auto err = parser_->Parse(slices[i], i == nslices - 1);
+      if (err != GRPC_ERROR_NONE) {
+        gpr_log(GPR_ERROR, "Unexpected parse error: %s",
+                grpc_error_std_string(err).c_str());
+        abort();
+      }
+    }
 
-  {
-    grpc_core::HPackParser parser;
-    /* D.4.1 */
-    test_vector(
-        &parser, mode,
-        "8286 8441 8cf1 e3c2 e5f2 3a6b a0ab 90f4"
-        "ff",
-        {std::make_pair(":method", "GET"), std::make_pair(":scheme", "http"),
-         std::make_pair(":path", "/"),
-         std::make_pair(":authority", "www.example.com")});
-    /* D.4.2 */
-    test_vector(
-        &parser, mode, "8286 84be 5886 a8eb 1064 9cbf",
-        {std::make_pair(":method", "GET"), std::make_pair(":scheme", "http"),
-         std::make_pair(":path", "/"),
-         std::make_pair(":authority", "www.example.com"),
-         std::make_pair("cache-control", "no-cache")});
-    /* D.4.3 */
-    test_vector(
-        &parser, mode,
-        "8287 85bf 4088 25a8 49e9 5ba9 7d7f 8925"
-        "a849 e95b b8e8 b4bf",
-        {std::make_pair(":method", "GET"), std::make_pair(":scheme", "https"),
-         std::make_pair(":path", "/index.html"),
-         std::make_pair(":authority", "www.example.com"),
-         std::make_pair("custom-key", "custom-value")});
-  }
+    for (i = 0; i < nslices; i++) {
+      grpc_slice_unref(slices[i]);
+    }
+    gpr_free(slices);
 
-  {
-    grpc_core::HPackParser parser;
-    parser.hpack_table()->SetMaxBytes(256);
-    parser.hpack_table()->SetCurrentTableSize(256);
-    /* D.5.1 */
-    test_vector(&parser, mode,
-                "4803 3330 3258 0770 7269 7661 7465 611d"
-                "4d6f 6e2c 2032 3120 4f63 7420 3230 3133"
-                "2032 303a 3133 3a32 3120 474d 546e 1768"
-                "7474 7073 3a2f 2f77 7777 2e65 7861 6d70"
-                "6c65 2e63 6f6d",
-                {std::make_pair(":status", "302"),
-                 std::make_pair("cache-control", "private"),
-                 std::make_pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
-                 std::make_pair("location", "https://www.example.com")});
-    /* D.5.2 */
-    test_vector(&parser, mode, "4803 3330 37c1 c0bf",
-                {std::make_pair(":status", "307"),
-                 std::make_pair("cache-control", "private"),
-                 std::make_pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
-                 std::make_pair("location", "https://www.example.com")});
-    /* D.5.3 */
-    test_vector(
-        &parser, mode,
-        "88c1 611d 4d6f 6e2c 2032 3120 4f63 7420"
-        "3230 3133 2032 303a 3133 3a32 3220 474d"
-        "54c0 5a04 677a 6970 7738 666f 6f3d 4153"
-        "444a 4b48 514b 425a 584f 5157 454f 5049"
-        "5541 5851 5745 4f49 553b 206d 6178 2d61"
-        "6765 3d33 3630 303b 2076 6572 7369 6f6e"
-        "3d31",
-        {std::make_pair(":status", "200"),
-         std::make_pair("cache-control", "private"),
-         std::make_pair("date", "Mon, 21 Oct 2013 20:13:22 GMT"),
-         std::make_pair("location", "https://www.example.com"),
-         std::make_pair("content-encoding", "gzip"),
-         std::make_pair(
-             "set-cookie",
-             "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1")});
+    TestEncoder encoder;
+    b.Encode(&encoder);
+    EXPECT_EQ(encoder.result(), expect);
   }
 
-  {
-    grpc_core::HPackParser parser;
-    parser.hpack_table()->SetMaxBytes(256);
-    parser.hpack_table()->SetCurrentTableSize(256);
-    /* D.6.1 */
-    test_vector(&parser, mode,
-                "4882 6402 5885 aec3 771a 4b61 96d0 7abe"
-                "9410 54d4 44a8 2005 9504 0b81 66e0 82a6"
-                "2d1b ff6e 919d 29ad 1718 63c7 8f0b 97c8"
-                "e9ae 82ae 43d3",
-                {std::make_pair(":status", "302"),
-                 std::make_pair("cache-control", "private"),
-                 std::make_pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
-                 std::make_pair("location", "https://www.example.com")});
-    /* D.6.2 */
-    test_vector(&parser, mode, "4883 640e ffc1 c0bf",
-                {std::make_pair(":status", "307"),
-                 std::make_pair("cache-control", "private"),
-                 std::make_pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
-                 std::make_pair("location", "https://www.example.com")});
-    /* D.6.3 */
-    test_vector(
-        &parser, mode,
-        "88c1 6196 d07a be94 1054 d444 a820 0595"
-        "040b 8166 e084 a62d 1bff c05a 839b d9ab"
-        "77ad 94e7 821d d7f2 e6c7 b335 dfdf cd5b"
-        "3960 d5af 2708 7f36 72c1 ab27 0fb5 291f"
-        "9587 3160 65c0 03ed 4ee5 b106 3d50 07",
-        {std::make_pair(":status", "200"),
-         std::make_pair("cache-control", "private"),
-         std::make_pair("date", "Mon, 21 Oct 2013 20:13:22 GMT"),
-         std::make_pair("location", "https://www.example.com"),
-         std::make_pair("content-encoding", "gzip"),
-         std::make_pair(
-             "set-cookie",
-             "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1")});
+ private:
+  class TestEncoder {
+   public:
+    std::string result() { return out_; }
+
+    void Encode(grpc_mdelem elem) {
+      out_.append(absl::StrCat(
+          grpc_core::StringViewFromSlice(GRPC_MDKEY(elem)), ": ",
+          grpc_core::StringViewFromSlice(GRPC_MDVALUE(elem)), "\n"));
+    }
+
+    template <typename T, typename V>
+    void Encode(T, V) {
+      abort();  // not implemented
+    }
+
+   private:
+    std::string out_;
+  };
+
+  std::unique_ptr<grpc_core::HPackParser> parser_;
+};
+
+TEST_P(ParseTest, WholeSlices) {
+  for (const auto& input : GetParam().inputs) {
+    TestVector(GRPC_SLICE_SPLIT_MERGE_ALL, input.input, input.expected_parse);
   }
+}
 
-  {
-    grpc_core::HPackParser parser;
-    // Binary metadata: created using:
-    // tools/codegen/core/gen_header_frame.py
-    //    --compression inc --no_framing --hex
-    //    < test/core/transport/chttp2/binary-metadata.headers
-    test_vector(&parser, mode,
-                "40 09 61 2e 62 2e 63 2d 62 69 6e 0c 62 32 31 6e 4d 6a 41 79 "
-                "4d 51 3d 3d",
-                {std::make_pair("a.b.c-bin", "omg2021")});
+TEST_P(ParseTest, OneByteAtATime) {
+  for (const auto& input : GetParam().inputs) {
+    TestVector(GRPC_SLICE_SPLIT_ONE_BYTE, input.input, input.expected_parse);
   }
 }
 
+INSTANTIATE_TEST_SUITE_P(
+    ParseTest, ParseTest,
+    ::testing::Values(
+        Test{
+            {},
+            {
+                /* D.2.1 */
+                {"400a 6375 7374 6f6d 2d6b 6579 0d63 7573"
+                 "746f 6d2d 6865 6164 6572",
+                 "custom-key: custom-header\n"},
+                /* D.2.2 */
+                {"040c 2f73 616d 706c 652f 7061 7468", ":path: /sample/path\n"},
+                /* D.2.3 */
+                {"1008 7061 7373 776f 7264 0673 6563 7265"
+                 "74",
+                 "password: secret\n"},
+                /* D.2.4 */
+                {"82", ":method: GET\n"},
+            }},
+        Test{{},
+             {
+                 /* D.3.1 */
+                 {"8286 8441 0f77 7777 2e65 7861 6d70 6c65"
+                  "2e63 6f6d",
+                  ":method: GET\n"
+                  ":scheme: http\n"
+                  ":path: /\n"
+                  ":authority: www.example.com\n"},
+                 /* D.3.2 */
+                 {"8286 84be 5808 6e6f 2d63 6163 6865",
+                  ":method: GET\n"
+                  ":scheme: http\n"
+                  ":path: /\n"
+                  ":authority: www.example.com\n"
+                  "cache-control: no-cache\n"},
+                 /* D.3.3 */
+                 {"8287 85bf 400a 6375 7374 6f6d 2d6b 6579"
+                  "0c63 7573 746f 6d2d 7661 6c75 65",
+                  ":method: GET\n"
+                  ":scheme: https\n"
+                  ":path: /index.html\n"
+                  ":authority: www.example.com\n"
+                  "custom-key: custom-value\n"},
+             }},
+        Test{{},
+             {
+                 /* D.4.1 */
+                 {"8286 8441 8cf1 e3c2 e5f2 3a6b a0ab 90f4"
+                  "ff",
+                  ":method: GET\n"
+                  ":scheme: http\n"
+                  ":path: /\n"
+                  ":authority: www.example.com\n"},
+                 /* D.4.2 */
+                 {"8286 84be 5886 a8eb 1064 9cbf",
+                  ":method: GET\n"
+                  ":scheme: http\n"
+                  ":path: /\n"
+                  ":authority: www.example.com\n"
+                  "cache-control: no-cache\n"},
+                 /* D.4.3 */
+                 {"8287 85bf 4088 25a8 49e9 5ba9 7d7f 8925"
+                  "a849 e95b b8e8 b4bf",
+                  ":method: GET\n"
+                  ":scheme: https\n"
+                  ":path: /index.html\n"
+                  ":authority: www.example.com\n"
+                  "custom-key: custom-value\n"},
+             }},
+        Test{{256},
+             {
+                 /* D.5.1 */
+                 {"4803 3330 3258 0770 7269 7661 7465 611d"
+                  "4d6f 6e2c 2032 3120 4f63 7420 3230 3133"
+                  "2032 303a 3133 3a32 3120 474d 546e 1768"
+                  "7474 7073 3a2f 2f77 7777 2e65 7861 6d70"
+                  "6c65 2e63 6f6d",
+                  ":status: 302\n"
+                  "cache-control: private\n"
+                  "date: Mon, 21 Oct 2013 20:13:21 GMT\n"
+                  "location: https://www.example.com\n"},
+                 /* D.5.2 */
+                 {"4803 3330 37c1 c0bf",
+                  ":status: 307\n"
+                  "cache-control: private\n"
+                  "date: Mon, 21 Oct 2013 20:13:21 GMT\n"
+                  "location: https://www.example.com\n"},
+                 /* D.5.3 */
+                 {"88c1 611d 4d6f 6e2c 2032 3120 4f63 7420"
+                  "3230 3133 2032 303a 3133 3a32 3220 474d"
+                  "54c0 5a04 677a 6970 7738 666f 6f3d 4153"
+                  "444a 4b48 514b 425a 584f 5157 454f 5049"
+                  "5541 5851 5745 4f49 553b 206d 6178 2d61"
+                  "6765 3d33 3630 303b 2076 6572 7369 6f6e"
+                  "3d31",
+                  ":status: 200\n"
+                  "cache-control: private\n"
+                  "date: Mon, 21 Oct 2013 20:13:22 GMT\n"
+                  "location: https://www.example.com\n"
+                  "content-encoding: gzip\n"
+                  "set-cookie: foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; "
+                  "version=1\n"},
+             }},
+        Test{{256},
+             {
+                 /* D.6.1 */
+                 {"4882 6402 5885 aec3 771a 4b61 96d0 7abe"
+                  "9410 54d4 44a8 2005 9504 0b81 66e0 82a6"
+                  "2d1b ff6e 919d 29ad 1718 63c7 8f0b 97c8"
+                  "e9ae 82ae 43d3",
+                  ":status: 302\n"
+                  "cache-control: private\n"
+                  "date: Mon, 21 Oct 2013 20:13:21 GMT\n"
+                  "location: https://www.example.com\n"},
+                 /* D.6.2 */
+                 {"4883 640e ffc1 c0bf",
+                  ":status: 307\n"
+                  "cache-control: private\n"
+                  "date: Mon, 21 Oct 2013 20:13:21 GMT\n"
+                  "location: https://www.example.com\n"},
+                 /* D.6.3 */
+                 {"88c1 6196 d07a be94 1054 d444 a820 0595"
+                  "040b 8166 e084 a62d 1bff c05a 839b d9ab"
+                  "77ad 94e7 821d d7f2 e6c7 b335 dfdf cd5b"
+                  "3960 d5af 2708 7f36 72c1 ab27 0fb5 291f"
+                  "9587 3160 65c0 03ed 4ee5 b106 3d50 07",
+                  ":status: 200\n"
+                  "cache-control: private\n"
+                  "date: Mon, 21 Oct 2013 20:13:22 GMT\n"
+                  "location: https://www.example.com\n"
+                  "content-encoding: gzip\n"
+                  "set-cookie: foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; "
+                  "version=1\n"},
+             }},
+        Test{{},
+             {
+                 // Binary metadata: created using:
+                 // tools/codegen/core/gen_header_frame.py
+                 //    --compression inc --no_framing --hex
+                 //    < test/core/transport/chttp2/binary-metadata.headers
+                 {"40 09 61 2e 62 2e 63 2d 62 69 6e 0c 62 32 31 6e 4d 6a 41 79 "
+                  "4d 51 3d 3d",
+                  "a.b.c-bin: omg2021\n"},
+             }}));
+
 int main(int argc, char** argv) {
   grpc::testing::TestEnvironment env(argc, argv);
-  grpc_init();
-  test_vectors(GRPC_SLICE_SPLIT_MERGE_ALL);
-  test_vectors(GRPC_SLICE_SPLIT_ONE_BYTE);
-  grpc_shutdown();
-  return 0;
+  ::testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
 }
index d42a575..ebbb9f9 100644 (file)
@@ -41,7 +41,7 @@ TEST(ErrorUtilsTest, GrpcSpecialErrorNoneToAbslStatus) {
 // ---- Asymmetry of conversions of "Special" errors ----
 TEST(ErrorUtilsTest, AbslStatusToGrpcErrorDoesNotReturnSpecialVariables) {
   grpc_error_handle error =
-      absl_status_to_grpc_error(absl::CancelledError("Cancelled"));
+      absl_status_to_grpc_error(absl::CancelledError("CANCELLED"));
   ASSERT_NE(error, GRPC_ERROR_CANCELLED);
   GRPC_ERROR_UNREF(error);
 }
@@ -49,13 +49,13 @@ TEST(ErrorUtilsTest, AbslStatusToGrpcErrorDoesNotReturnSpecialVariables) {
 TEST(ErrorUtilsTest, GrpcSpecialErrorCancelledToAbslStatus) {
   absl::Status status = grpc_error_to_absl_status(GRPC_ERROR_CANCELLED);
   ASSERT_TRUE(absl::IsCancelled(status));
-  ASSERT_EQ(status.message(), "Cancelled");
+  ASSERT_EQ(status.message(), "CANCELLED");
 }
 
 TEST(ErrorUtilsTest, GrpcSpecialErrorOOMToAbslStatus) {
   absl::Status status = grpc_error_to_absl_status(GRPC_ERROR_OOM);
   ASSERT_TRUE(absl::IsResourceExhausted(status));
-  ASSERT_EQ(status.message(), "Out of memory");
+  ASSERT_EQ(status.message(), "RESOURCE_EXHAUSTED");
 }
 
 // ---- Ordinary statuses ----
@@ -67,11 +67,9 @@ TEST(ErrorUtilsTest, AbslUnavailableToGrpcError) {
   ASSERT_TRUE(grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, &code));
   ASSERT_EQ(static_cast<grpc_status_code>(code), GRPC_STATUS_UNAVAILABLE);
   // Status message checks
-  grpc_slice message;
+  std::string message;
   ASSERT_TRUE(grpc_error_get_str(error, GRPC_ERROR_STR_DESCRIPTION, &message));
-  absl::string_view str = grpc_core::StringViewFromSlice(message);
-  ASSERT_EQ(str, "Making tea");
-  grpc_slice_unref(message);
+  ASSERT_EQ(message, "Making tea");
   GRPC_ERROR_UNREF(error);
 }
 
diff --git a/test/core/transport/metadata_map_test.cc b/test/core/transport/metadata_map_test.cc
new file mode 100644 (file)
index 0000000..91e58c6
--- /dev/null
@@ -0,0 +1,95 @@
+//
+// 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 <gtest/gtest.h>
+
+#include "src/core/lib/slice/slice_internal.h"
+#include "src/core/lib/transport/metadata_batch.h"
+#include "test/core/util/test_config.h"
+
+namespace grpc_core {
+namespace testing {
+
+TEST(MetadataMapTest, Noop) {
+  auto arena = MakeScopedArena(1024);
+  MetadataMap<>(arena.get());
+}
+
+TEST(MetadataMapTest, NoopWithDeadline) {
+  auto arena = MakeScopedArena(1024);
+  MetadataMap<GrpcTimeoutMetadata>(arena.get());
+}
+
+TEST(MetadataMapTest, SimpleOps) {
+  auto arena = MakeScopedArena(1024);
+  MetadataMap<GrpcTimeoutMetadata> map(arena.get());
+  EXPECT_EQ(map.get_pointer(GrpcTimeoutMetadata()), nullptr);
+  EXPECT_EQ(map.get(GrpcTimeoutMetadata()), absl::nullopt);
+  map.Set(GrpcTimeoutMetadata(), 1234);
+  EXPECT_NE(map.get_pointer(GrpcTimeoutMetadata()), nullptr);
+  EXPECT_EQ(*map.get_pointer(GrpcTimeoutMetadata()), 1234);
+  EXPECT_EQ(map.get(GrpcTimeoutMetadata()), 1234);
+  map.Remove(GrpcTimeoutMetadata());
+  EXPECT_EQ(map.get_pointer(GrpcTimeoutMetadata()), nullptr);
+  EXPECT_EQ(map.get(GrpcTimeoutMetadata()), absl::nullopt);
+}
+
+// Target for MetadataMap::Encode.
+// Writes down some string representation of what it receives, so we can
+// EXPECT_EQ it later.
+class FakeEncoder {
+ public:
+  std::string output() { return output_; }
+
+  void Encode(grpc_mdelem md) {
+    output_ +=
+        absl::StrCat("LEGACY CALL: key=", StringViewFromSlice(GRPC_MDKEY(md)),
+                     " value=", StringViewFromSlice(GRPC_MDVALUE(md)), "\n");
+  }
+
+  void Encode(GrpcTimeoutMetadata, grpc_millis deadline) {
+    output_ += absl::StrCat("grpc-timeout: deadline=", deadline, "\n");
+  }
+
+ private:
+  std::string output_;
+};
+
+TEST(MetadataMapTest, EmptyEncodeTest) {
+  FakeEncoder encoder;
+  auto arena = MakeScopedArena(1024);
+  MetadataMap<GrpcTimeoutMetadata> map(arena.get());
+  map.Encode(&encoder);
+  EXPECT_EQ(encoder.output(), "");
+}
+
+TEST(MetadataMapTest, TimeoutEncodeTest) {
+  FakeEncoder encoder;
+  auto arena = MakeScopedArena(1024);
+  MetadataMap<GrpcTimeoutMetadata> map(arena.get());
+  map.Set(GrpcTimeoutMetadata(), 1234);
+  map.Encode(&encoder);
+  EXPECT_EQ(encoder.output(), "grpc-timeout: deadline=1234\n");
+}
+
+}  // namespace testing
+}  // namespace grpc_core
+
+int main(int argc, char** argv) {
+  testing::InitGoogleTest(&argc, argv);
+  grpc::testing::TestEnvironment env(argc, argv);
+  return RUN_ALL_TESTS();
+};
index 53ec92e..8156929 100644 (file)
@@ -33,6 +33,7 @@
 #include "src/core/ext/transport/chttp2/transport/bin_encoder.h"
 #include "src/core/ext/transport/chttp2/transport/hpack_utils.h"
 #include "src/core/lib/gpr/string.h"
+#include "src/core/lib/iomgr/error.h"
 #include "src/core/lib/iomgr/exec_ctx.h"
 #include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/transport/metadata_batch.h"
 /* a large number */
 #define MANY 10000
 
-static void test_no_op(void) {
-  gpr_log(GPR_INFO, "test_no_op");
-  grpc_init();
-  grpc_shutdown();
-}
-
 static grpc_slice maybe_intern(grpc_slice in, bool intern) {
   grpc_slice out = intern ? grpc_slice_intern(in) : grpc_slice_ref(in);
   grpc_slice_unref(in);
@@ -66,7 +61,6 @@ static void test_create_metadata(bool intern_keys, bool intern_values) {
   gpr_log(GPR_INFO, "test_create_metadata: intern_keys=%d intern_values=%d",
           intern_keys, intern_values);
 
-  grpc_init();
   grpc_core::ExecCtx exec_ctx;
   m1 = grpc_mdelem_from_slices(
       maybe_intern(grpc_slice_from_static_string("a"), intern_keys),
@@ -87,8 +81,6 @@ static void test_create_metadata(bool intern_keys, bool intern_values) {
   GRPC_MDELEM_UNREF(m1);
   GRPC_MDELEM_UNREF(m2);
   GRPC_MDELEM_UNREF(m3);
-
-  grpc_shutdown();
 }
 
 static void test_create_many_ephemeral_metadata(bool intern_keys,
@@ -101,7 +93,6 @@ static void test_create_many_ephemeral_metadata(bool intern_keys,
       "test_create_many_ephemeral_metadata: intern_keys=%d intern_values=%d",
       intern_keys, intern_values);
 
-  grpc_init();
   grpc_core::ExecCtx exec_ctx;
   /* add, and immediately delete a bunch of different elements */
   for (i = 0; i < MANY; i++) {
@@ -110,8 +101,6 @@ static void test_create_many_ephemeral_metadata(bool intern_keys,
         maybe_intern(grpc_slice_from_static_string("a"), intern_keys),
         maybe_intern(grpc_slice_from_copied_string(buffer), intern_values)));
   }
-
-  grpc_shutdown();
 }
 
 static void test_create_many_persistant_metadata(void) {
@@ -123,7 +112,6 @@ static void test_create_many_persistant_metadata(void) {
 
   gpr_log(GPR_INFO, "test_create_many_persistant_metadata");
 
-  grpc_init();
   grpc_core::ExecCtx exec_ctx;
   /* add phase */
   for (i = 0; i < MANY; i++) {
@@ -146,8 +134,6 @@ static void test_create_many_persistant_metadata(void) {
     GRPC_MDELEM_UNREF(created[i]);
   }
 
-  grpc_shutdown();
-
   gpr_free(created);
 }
 
@@ -157,7 +143,6 @@ static void test_spin_creating_the_same_thing(bool intern_keys,
           "test_spin_creating_the_same_thing: intern_keys=%d intern_values=%d",
           intern_keys, intern_values);
 
-  grpc_init();
   grpc_core::ExecCtx exec_ctx;
   grpc_mdelem a, b, c;
   GRPC_MDELEM_UNREF(
@@ -176,15 +161,12 @@ static void test_spin_creating_the_same_thing(bool intern_keys,
     GPR_ASSERT(a.payload == b.payload);
     GPR_ASSERT(a.payload == c.payload);
   }
-
-  grpc_shutdown();
 }
 
 static void test_identity_laws(bool intern_keys, bool intern_values) {
   gpr_log(GPR_INFO, "test_identity_laws: intern_keys=%d intern_values=%d",
           intern_keys, intern_values);
 
-  grpc_init();
   grpc_core::ExecCtx exec_ctx;
   grpc_mdelem a, b, c;
   a = grpc_mdelem_from_slices(
@@ -216,8 +198,6 @@ static void test_identity_laws(bool intern_keys, bool intern_values) {
   GRPC_MDELEM_UNREF(a);
   GRPC_MDELEM_UNREF(b);
   GRPC_MDELEM_UNREF(c);
-
-  grpc_shutdown();
 }
 
 static void test_things_stick_around(void) {
@@ -230,7 +210,6 @@ static void test_things_stick_around(void) {
 
   gpr_log(GPR_INFO, "test_things_stick_around");
 
-  grpc_init();
   grpc_core::ExecCtx exec_ctx;
 
   for (i = 0; i < nstrs; i++) {
@@ -263,8 +242,6 @@ static void test_things_stick_around(void) {
       grpc_slice_unref_internal(test);
     }
   }
-
-  grpc_shutdown();
   gpr_free(strs);
   gpr_free(shuf);
 }
@@ -275,7 +252,6 @@ static void test_user_data_works(void) {
   grpc_mdelem md;
   gpr_log(GPR_INFO, "test_user_data_works");
 
-  grpc_init();
   grpc_core::ExecCtx exec_ctx;
   ud1 = static_cast<int*>(gpr_malloc(sizeof(int)));
   *ud1 = 1;
@@ -288,8 +264,6 @@ static void test_user_data_works(void) {
   grpc_mdelem_set_user_data(md, gpr_free, ud2);
   GPR_ASSERT(grpc_mdelem_get_user_data(md, gpr_free) == ud1);
   GRPC_MDELEM_UNREF(md);
-
-  grpc_shutdown();
 }
 
 static void test_user_data_works_for_allocated_md(void) {
@@ -298,7 +272,6 @@ static void test_user_data_works_for_allocated_md(void) {
   grpc_mdelem md;
   gpr_log(GPR_INFO, "test_user_data_works");
 
-  grpc_init();
   grpc_core::ExecCtx exec_ctx;
   ud1 = static_cast<int*>(gpr_malloc(sizeof(int)));
   *ud1 = 1;
@@ -310,18 +283,15 @@ static void test_user_data_works_for_allocated_md(void) {
   grpc_mdelem_set_user_data(md, gpr_free, ud2);
   GPR_ASSERT(grpc_mdelem_get_user_data(md, gpr_free) == ud1);
   GRPC_MDELEM_UNREF(md);
-
-  grpc_shutdown();
 }
 
 static void test_copied_static_metadata(bool dup_key, bool dup_value) {
   gpr_log(GPR_INFO, "test_static_metadata: dup_key=%d dup_value=%d", dup_key,
           dup_value);
-  grpc_init();
   grpc_core::ExecCtx exec_ctx;
 
   for (size_t i = 0; i < GRPC_STATIC_MDELEM_COUNT; i++) {
-    grpc_mdelem p = GRPC_MAKE_MDELEM(&grpc_static_mdelem_table()[i],
+    grpc_mdelem p = GRPC_MAKE_MDELEM(&grpc_core::g_static_mdelem_table[i],
                                      GRPC_MDELEM_STORAGE_STATIC);
     grpc_mdelem q =
         grpc_mdelem_from_slices(maybe_dup(GRPC_MDKEY(p), dup_key),
@@ -335,75 +305,73 @@ static void test_copied_static_metadata(bool dup_key, bool dup_value) {
     GRPC_MDELEM_UNREF(p);
     GRPC_MDELEM_UNREF(q);
   }
-
-  grpc_shutdown();
 }
 
 static void test_grpc_metadata_batch_get_value_with_absent_key(void) {
-  grpc_init();
-  grpc_metadata_batch metadata;
-  grpc_metadata_batch_init(&metadata);
+  auto arena = grpc_core::MakeScopedArena(1024);
+  grpc_metadata_batch metadata(arena.get());
   std::string concatenated_value;
-  absl::optional<absl::string_view> value = grpc_metadata_batch_get_value(
-      &metadata, "absent_key", &concatenated_value);
+  absl::optional<absl::string_view> value =
+      metadata.GetValue("absent_key", &concatenated_value);
   GPR_ASSERT(value == absl::nullopt);
-  grpc_metadata_batch_destroy(&metadata);
-  grpc_shutdown();
 }
 
 static void test_grpc_metadata_batch_get_value_returns_one_value(void) {
-  grpc_init();
   const char* kKey = "some_key";
   const char* kValue = "some_value";
-  grpc_metadata_batch metadata;
-  grpc_metadata_batch_init(&metadata);
+  auto arena = grpc_core::MakeScopedArena(1024);
   grpc_linked_mdelem storage;
+  grpc_metadata_batch metadata(arena.get());
   storage.md = grpc_mdelem_from_slices(
       grpc_slice_intern(grpc_slice_from_static_string(kKey)),
       grpc_slice_intern(grpc_slice_from_static_string(kValue)));
-  GPR_ASSERT(grpc_metadata_batch_link_head(&metadata, &storage) ==
-             GRPC_ERROR_NONE);
+  GPR_ASSERT(metadata.LinkHead(&storage) == GRPC_ERROR_NONE);
   std::string concatenated_value;
   absl::optional<absl::string_view> value =
-      grpc_metadata_batch_get_value(&metadata, kKey, &concatenated_value);
+      metadata.GetValue(kKey, &concatenated_value);
   GPR_ASSERT(value.has_value());
   GPR_ASSERT(value.value() == kValue);
-  grpc_metadata_batch_destroy(&metadata);
-  grpc_shutdown();
 }
 
 static void test_grpc_metadata_batch_get_value_returns_multiple_values(void) {
-  grpc_init();
   const char* kKey = "some_key";
   const char* kValue1 = "value1";
   const char* kValue2 = "value2";
-  grpc_metadata_batch metadata;
-  grpc_metadata_batch_init(&metadata);
+  auto arena = grpc_core::MakeScopedArena(1024);
   grpc_linked_mdelem storage1;
+  grpc_linked_mdelem storage2;
+  grpc_metadata_batch metadata(arena.get());
   storage1.md = grpc_mdelem_from_slices(
       grpc_slice_intern(grpc_slice_from_static_string(kKey)),
       grpc_slice_intern(grpc_slice_from_static_string(kValue1)));
-  GPR_ASSERT(grpc_metadata_batch_link_tail(&metadata, &storage1) ==
-             GRPC_ERROR_NONE);
-  grpc_linked_mdelem storage2;
+  GPR_ASSERT(metadata.LinkTail(&storage1) == GRPC_ERROR_NONE);
   storage2.md = grpc_mdelem_from_slices(
       grpc_slice_intern(grpc_slice_from_static_string(kKey)),
       grpc_slice_intern(grpc_slice_from_static_string(kValue2)));
-  GPR_ASSERT(grpc_metadata_batch_link_tail(&metadata, &storage2) ==
-             GRPC_ERROR_NONE);
+  GPR_ASSERT(metadata.LinkTail(&storage2) == GRPC_ERROR_NONE);
   std::string concatenated_value;
   absl::optional<absl::string_view> value =
-      grpc_metadata_batch_get_value(&metadata, kKey, &concatenated_value);
+      metadata.GetValue(kKey, &concatenated_value);
   GPR_ASSERT(value.has_value());
   GPR_ASSERT(value.value() == absl::StrCat(kValue1, ",", kValue2));
-  grpc_metadata_batch_destroy(&metadata);
-  grpc_shutdown();
+}
+
+static void test_grpc_chttp2_incoming_metadata_replace_or_add_works(void) {
+  auto arena = grpc_core::MakeScopedArena(1024);
+  grpc_metadata_batch buffer(arena.get());
+  GRPC_LOG_IF_ERROR("incoming_buffer_add",
+                    buffer.Append(grpc_mdelem_from_slices(
+                        grpc_slice_from_static_string("a"),
+                        grpc_slice_from_static_string("b"))));
+  GRPC_LOG_IF_ERROR(
+      "incoming_buffer_replace_or_add",
+      buffer.ReplaceOrAppend(grpc_slice_from_static_string("a"),
+                             grpc_slice_malloc(1024 * 1024 * 1024)));
 }
 
 int main(int argc, char** argv) {
   grpc::testing::TestEnvironment env(argc, argv);
   grpc_init();
-  test_no_op();
   for (int k = 0; k <= 1; k++) {
     for (int v = 0; v <= 1; v++) {
       test_create_metadata(k, v);
@@ -420,6 +388,7 @@ int main(int argc, char** argv) {
   test_grpc_metadata_batch_get_value_with_absent_key();
   test_grpc_metadata_batch_get_value_returns_one_value();
   test_grpc_metadata_batch_get_value_returns_multiple_values();
+  test_grpc_chttp2_incoming_metadata_replace_or_add_works();
   grpc_shutdown();
   return 0;
 }
diff --git a/test/core/transport/parsed_metadata_test.cc b/test/core/transport/parsed_metadata_test.cc
new file mode 100644 (file)
index 0000000..d0a8c34
--- /dev/null
@@ -0,0 +1,210 @@
+//
+// 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 "src/core/lib/transport/parsed_metadata.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "src/core/lib/slice/slice_internal.h"
+#include "test/core/util/test_config.h"
+
+namespace grpc_core {
+namespace testing {
+
+struct CharTrait {
+  using MementoType = char;
+  static const char* key() { return "key"; }
+  static char test_memento() { return 'a'; }
+  static char test_value() { return 'a'; }
+  static size_t test_memento_transport_size() { return 34; }
+  static char MementoToValue(char memento) { return memento; }
+  static char ParseMemento(const grpc_slice& slice) {
+    return *GRPC_SLICE_START_PTR(slice);
+  }
+  static std::string DisplayValue(char value) { return std::string(1, value); }
+};
+
+struct Int32Trait {
+  using MementoType = int32_t;
+  static const char* key() { return "key2"; }
+  static int32_t test_memento() { return -1; }
+  static int32_t test_value() { return -1; }
+  static size_t test_memento_transport_size() { return 478; }
+  static int32_t MementoToValue(int32_t memento) { return memento; }
+  static int32_t ParseMemento(const grpc_slice& slice) {
+    int32_t out;
+    GPR_ASSERT(absl::SimpleAtoi(StringViewFromSlice(slice), &out));
+    return out;
+  }
+  static std::string DisplayValue(int32_t value) {
+    return std::to_string(value);
+  }
+};
+
+struct Int64Trait {
+  using MementoType = int64_t;
+  static const char* key() { return "key3"; }
+  static int64_t test_memento() { return 83481847284179298; }
+  static int64_t test_value() { return -83481847284179298; }
+  static size_t test_memento_transport_size() { return 87; }
+  static int64_t MementoToValue(int64_t memento) { return -memento; }
+  static int64_t ParseMemento(const grpc_slice& slice) {
+    int64_t out;
+    GPR_ASSERT(absl::SimpleAtoi(StringViewFromSlice(slice), &out));
+    return out;
+  }
+  static std::string DisplayValue(int64_t value) {
+    return std::to_string(value);
+  }
+};
+
+struct IntptrTrait {
+  using MementoType = intptr_t;
+  static const char* key() { return "key4"; }
+  static intptr_t test_memento() { return 8374298; }
+  static intptr_t test_value() { return test_memento() / 2; }
+  static size_t test_memento_transport_size() { return 800; }
+  static intptr_t MementoToValue(intptr_t memento) { return memento / 2; }
+  static intptr_t ParseMemento(const grpc_slice& slice) {
+    intptr_t out;
+    GPR_ASSERT(absl::SimpleAtoi(StringViewFromSlice(slice), &out));
+    return out;
+  }
+  static std::string DisplayValue(intptr_t value) {
+    return std::to_string(value);
+  }
+};
+
+struct StringTrait {
+  using MementoType = std::string;
+  static const char* key() { return "key5-bin"; }
+  static std::string test_memento() { return "hello"; }
+  static std::string test_value() { return "hi hello"; }
+  static size_t test_memento_transport_size() { return 599; }
+  static std::string MementoToValue(std::string memento) {
+    return "hi " + memento;
+  }
+  static std::string ParseMemento(const grpc_slice& slice) {
+    auto view = StringViewFromSlice(slice);
+    return std::string(view.begin(), view.end());
+  }
+  static std::string DisplayValue(const std::string& value) { return value; }
+};
+
+class FakeContainer {
+ public:
+  void Set(CharTrait, char x) { SetChar(x); }
+  void Set(Int32Trait, int32_t x) { SetInt32(x); }
+  void Set(Int64Trait, int64_t x) { SetInt64(x); }
+  void Set(IntptrTrait, intptr_t x) { SetIntptr(x); }
+  void Set(StringTrait, std::string x) { SetString(x); }
+
+  void Set(const ::grpc_core::ParsedMetadata<FakeContainer>& metadata) {
+    EXPECT_EQ(GRPC_ERROR_NONE, metadata.SetOnContainer(this));
+  }
+
+  MOCK_METHOD1(SetChar, void(char));
+  MOCK_METHOD1(SetInt32, void(int32_t));
+  MOCK_METHOD1(SetInt64, void(int64_t));
+  MOCK_METHOD1(SetIntptr, void(intptr_t));
+  MOCK_METHOD1(SetString, void(std::string));
+};
+
+using ParsedMetadata = ::grpc_core::ParsedMetadata<FakeContainer>;
+
+TEST(ParsedMetadataTest, Noop) { ParsedMetadata(); }
+
+TEST(ParsedMetadataTest, DebugString) {
+  ParsedMetadata parsed(CharTrait(), 'x', 36);
+  EXPECT_EQ(parsed.DebugString(), "key: x");
+}
+
+TEST(ParsedMetadataTest, IsNotBinary) {
+  ParsedMetadata parsed(CharTrait(), 'x', 36);
+  EXPECT_FALSE(parsed.is_binary_header());
+}
+
+TEST(ParsedMetadataTest, IsBinary) {
+  ParsedMetadata parsed(StringTrait(), "s", 36);
+  EXPECT_TRUE(parsed.is_binary_header());
+}
+
+TEST(ParsedMetadataTest, Set) {
+  FakeContainer c;
+  ParsedMetadata p(CharTrait(), 'x', 36);
+  EXPECT_CALL(c, SetChar('x')).Times(1);
+  c.Set(p);
+  p = ParsedMetadata(Int32Trait(), -1, 478);
+  EXPECT_CALL(c, SetInt32(-1)).Times(1);
+  c.Set(p);
+  p = ParsedMetadata(Int64Trait(), 83481847284179298, 87);
+  EXPECT_CALL(c, SetInt64(-83481847284179298)).Times(1);
+  c.Set(p);
+  p = ParsedMetadata(IntptrTrait(), 8374298, 800);
+  EXPECT_CALL(c, SetIntptr(4187149)).Times(1);
+  c.Set(p);
+  p = ParsedMetadata(StringTrait(), "hello", 599);
+  EXPECT_CALL(c, SetString("hi hello")).Times(1);
+  c.Set(p);
+}
+
+template <typename T>
+class TraitSpecializedTest : public ::testing::Test {};
+
+TYPED_TEST_SUITE_P(TraitSpecializedTest);
+
+TYPED_TEST_P(TraitSpecializedTest, Noop) {
+  ParsedMetadata(TypeParam(), TypeParam::test_memento(),
+                 TypeParam::test_memento_transport_size());
+}
+
+TYPED_TEST_P(TraitSpecializedTest, CanMove) {
+  ParsedMetadata a(TypeParam(), TypeParam::test_memento(),
+                   TypeParam::test_memento_transport_size());
+  ParsedMetadata b = std::move(a);
+  a = std::move(b);
+}
+
+TYPED_TEST_P(TraitSpecializedTest, DebugString) {
+  ParsedMetadata p(TypeParam(), TypeParam::test_memento(),
+                   TypeParam::test_memento_transport_size());
+  EXPECT_EQ(p.DebugString(),
+            absl::StrCat(TypeParam::key(), ": ",
+                         TypeParam::DisplayValue(TypeParam::test_memento())));
+}
+
+TYPED_TEST_P(TraitSpecializedTest, TransportSize) {
+  ParsedMetadata p(TypeParam(), TypeParam::test_memento(),
+                   TypeParam::test_memento_transport_size());
+  EXPECT_EQ(p.transport_size(), TypeParam::test_memento_transport_size());
+}
+
+REGISTER_TYPED_TEST_SUITE_P(TraitSpecializedTest, Noop, CanMove, DebugString,
+                            TransportSize);
+
+using InterestingTraits = ::testing::Types<CharTrait, Int32Trait, Int64Trait,
+                                           IntptrTrait, StringTrait>;
+INSTANTIATE_TYPED_TEST_SUITE_P(My, TraitSpecializedTest, InterestingTraits);
+
+}  // namespace testing
+}  // namespace grpc_core
+
+int main(int argc, char** argv) {
+  testing::InitGoogleTest(&argc, argv);
+  grpc::testing::TestEnvironment env(argc, argv);
+  return RUN_ALL_TESTS();
+};
index bf225dc..06be96d 100644 (file)
@@ -32,7 +32,7 @@ TEST(StaticMetadataTest, ReadAllStaticElements) {
   // This makes sure that all static elements are returned when
   // grpc_mdelem_from_slices is called with key pairs pregenerated.
   for (int i = 0; i < GRPC_STATIC_MDELEM_COUNT; i++) {
-    const grpc_mdelem mdelem = grpc_static_mdelem_manifested()[i];
+    const grpc_mdelem mdelem = g_static_mdelem_manifested[i];
     const grpc_mdelem mdelem2 =
         grpc_mdelem_from_slices(GRPC_MDKEY(mdelem), GRPC_MDVALUE(mdelem));
     EXPECT_EQ(mdelem.payload, mdelem2.payload);
index 6ac2d40..50f86a2 100644 (file)
@@ -14,7 +14,7 @@
 
 load("//bazel:grpc_build_system.bzl", "grpc_cc_binary", "grpc_cc_library", "grpc_cc_test", "grpc_package")
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 grpc_package(
     name = "test/core/tsi",
index 767368a..1883219 100644 (file)
@@ -14,7 +14,7 @@
 #
 load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_package")
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 grpc_package(
     name = "test/core/tsi/alts/crypt",
index c7c86fb..db47537 100644 (file)
@@ -120,7 +120,9 @@ static void gsec_test_random_encrypt_decrypt(gsec_aead_crypter* crypter,
 
   GPR_ASSERT(status == GRPC_STATUS_OK);
   GPR_ASSERT(message_length == plaintext_bytes_written);
-  GPR_ASSERT(memcmp(message, plaintext, message_length) == 0);
+  if (message_length != 0) {
+    GPR_ASSERT(memcmp(message, plaintext, message_length) == 0);
+  }
 
   /**
    * The returned plaintext will be zeroed if there was an authentication error.
@@ -142,7 +144,9 @@ static void gsec_test_random_encrypt_decrypt(gsec_aead_crypter* crypter,
           status, GRPC_STATUS_FAILED_PRECONDITION, "Checking tag failed.",
           error_message));
       GPR_ASSERT(plaintext_bytes_written == 0);
-      GPR_ASSERT(memcmp(zero_message, plaintext, plaintext_length) == 0);
+      if (plaintext_length != 0) {
+        GPR_ASSERT(memcmp(zero_message, plaintext, plaintext_length) == 0);
+      }
       gpr_free(corrupt_nonce);
       gpr_free(error_message);
     }
@@ -162,7 +166,9 @@ static void gsec_test_random_encrypt_decrypt(gsec_aead_crypter* crypter,
         status, GRPC_STATUS_FAILED_PRECONDITION, error_message,
         "Checking tag failed"));
     GPR_ASSERT(plaintext_bytes_written == 0);
-    GPR_ASSERT(memcmp(zero_message, plaintext, plaintext_length) == 0);
+    if (plaintext_length != 0) {
+      GPR_ASSERT(memcmp(zero_message, plaintext, plaintext_length) == 0);
+    }
     gpr_free(error_message);
     gpr_free(corrupt_ciphertext_and_tag);
 
@@ -176,7 +182,9 @@ static void gsec_test_random_encrypt_decrypt(gsec_aead_crypter* crypter,
         corrupt_ciphertext_and_tag, ciphertext_bytes_written, plaintext,
         plaintext_length, &plaintext_bytes_written, &error_message);
     GPR_ASSERT(plaintext_bytes_written == 0);
-    GPR_ASSERT(memcmp(zero_message, plaintext, plaintext_length) == 0);
+    if (plaintext_length != 0) {
+      GPR_ASSERT(memcmp(zero_message, plaintext, plaintext_length) == 0);
+    }
     GPR_ASSERT(gsec_test_expect_compare_code_and_substr(
         status, GRPC_STATUS_FAILED_PRECONDITION, error_message,
         "Checking tag failed"));
@@ -198,7 +206,9 @@ static void gsec_test_random_encrypt_decrypt(gsec_aead_crypter* crypter,
         status, GRPC_STATUS_FAILED_PRECONDITION, error_message,
         "Checking tag failed"));
     GPR_ASSERT(plaintext_bytes_written == 0);
-    GPR_ASSERT(memcmp(zero_message, plaintext, plaintext_length) == 0);
+    if (plaintext_length != 0) {
+      GPR_ASSERT(memcmp(zero_message, plaintext, plaintext_length) == 0);
+    }
     gpr_free(error_message);
     gpr_free(corrupt_ciphertext_and_tag);
   }
@@ -292,7 +302,9 @@ static void gsec_test_multiple_random_encrypt_decrypt(
         &(plaintext_bytes_writtens[ind]), nullptr);
     GPR_ASSERT(status == GRPC_STATUS_OK);
     GPR_ASSERT(message_length == plaintext_bytes_writtens[ind]);
-    GPR_ASSERT(memcmp(messages[ind], plaintexts[ind], message_length) == 0);
+    if (message_length != 0) {
+      GPR_ASSERT(memcmp(messages[ind], plaintexts[ind], message_length) == 0);
+    }
   }
 
   /* Slice the plaintext and encrypt with iovecs */
@@ -358,8 +370,10 @@ static void gsec_test_multiple_random_encrypt_decrypt(
                        decrypted_vec, &decrypted_length, &error_details),
                    error_details);
     GPR_ASSERT(decrypted_vec.iov_len == message_length);
-    GPR_ASSERT(memcmp(decrypted_vec.iov_base, messages[ind], message_length) ==
-               0);
+    if (message_length != 0) {
+      GPR_ASSERT(
+          memcmp(decrypted_vec.iov_base, messages[ind], message_length) == 0);
+    }
     free(decrypted);
     free(aad_vecs);
     free(ciphertext_vecs);
@@ -713,8 +727,10 @@ static void gsec_test_encrypt_decrypt_test_vector(
       test_vector->ciphertext_and_tag_length, plaintext_bytes, plaintext_length,
       &plaintext_bytes_written, nullptr);
   GPR_ASSERT(status == GRPC_STATUS_OK);
-  GPR_ASSERT(memcmp(test_vector->plaintext, plaintext_bytes,
-                    plaintext_bytes_written) == 0);
+  if (plaintext_bytes_written != 0) {
+    GPR_ASSERT(memcmp(test_vector->plaintext, plaintext_bytes,
+                      plaintext_bytes_written) == 0);
+  }
 
   gpr_free(ciphertext_and_tag_bytes);
   gpr_free(plaintext_bytes);
index 89c887f..29533fa 100644 (file)
@@ -49,7 +49,9 @@ uint32_t gsec_test_bias_random_uint32(uint32_t max_length) {
 void gsec_test_copy(const uint8_t* src, uint8_t** des, size_t source_len) {
   if (src != nullptr && des != nullptr) {
     *des = static_cast<uint8_t*>(gpr_malloc(source_len));
-    memcpy(*des, src, source_len);
+    if (*des != nullptr) {
+      memcpy(*des, src, source_len);
+    }
   } else {
     fprintf(stderr, "Either src or des buffer is nullptr in gsec_test_copy().");
     abort();
index 44f57c4..e4c8e00 100644 (file)
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 load("//bazel:grpc_build_system.bzl", "grpc_cc_binary", "grpc_cc_library", "grpc_package", "grpc_proto_library")
 
index 1e3d16d..39cc825 100644 (file)
@@ -14,7 +14,7 @@
 
 load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_package")
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 grpc_package(name = "test/core/tsi/alts/frame_protector")
 
index 0dee7c2..a8324ab 100644 (file)
@@ -22,6 +22,8 @@
 #include <stdio.h>
 #include <string.h>
 
+#include <algorithm>
+
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 
@@ -69,7 +71,8 @@ static void frame(frame_handler* handler, unsigned char* payload,
   size_t offset = 0;
   while (offset < handler->buffer_size &&
          !alts_is_frame_writer_done(handler->writer)) {
-    size_t bytes_written = GPR_MIN(write_length, handler->buffer_size - offset);
+    size_t bytes_written =
+        std::min(write_length, handler->buffer_size - offset);
     GPR_ASSERT(alts_write_frame_bytes(handler->writer, handler->buffer + offset,
                                       &bytes_written));
     offset += bytes_written;
@@ -84,7 +87,7 @@ static size_t deframe(frame_handler* handler, unsigned char* bytes,
   size_t offset = 0;
   while (offset < handler->buffer_size &&
          !alts_is_frame_reader_done(handler->reader)) {
-    size_t bytes_read = GPR_MIN(read_length, handler->buffer_size - offset);
+    size_t bytes_read = std::min(read_length, handler->buffer_size - offset);
     GPR_ASSERT(alts_read_frame_bytes(handler->reader, handler->buffer + offset,
                                      &bytes_read));
     offset += bytes_read;
index 0f8e625..29a366a 100644 (file)
@@ -14,7 +14,7 @@
 
 load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_package")
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 grpc_package(name = "test/core/tsi/alts/handshaker")
 
index 696fc8d..6f8cb64 100644 (file)
@@ -14,7 +14,7 @@
 
 load("//bazel:grpc_build_system.bzl", "grpc_cc_test", "grpc_package")
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 grpc_package(name = "test/core/tsi/alts/zero_copy_frame_protector")
 
@@ -26,7 +26,7 @@ grpc_cc_test(
         "//:alts_frame_protector",
         "//:gpr",
         "//:grpc",
-        "//:grpc_base_c",
+        "//:grpc_base",
         "//test/core/tsi/alts/crypt:alts_crypt_test_util",
         "//test/core/util:grpc_test_util",
     ],
@@ -53,7 +53,7 @@ grpc_cc_test(
         "//:alts_frame_protector",
         "//:gpr",
         "//:grpc",
-        "//:grpc_base_c",
+        "//:grpc_base",
         "//test/core/tsi/alts/crypt:alts_crypt_test_util",
         "//test/core/util:grpc_test_util",
     ],
index eeec469..c560276 100644 (file)
@@ -27,6 +27,7 @@
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
 
+#include "src/core/lib/gprpp/memory.h"
 #include "src/core/lib/iomgr/load_file.h"
 #include "src/core/lib/security/security_connector/security_connector.h"
 #include "src/core/tsi/transport_security.h"
@@ -451,14 +452,12 @@ static char* load_file(const char* dir_path, const char* file_name) {
 }
 
 static tsi_test_fixture* ssl_tsi_test_fixture_create() {
-  ssl_tsi_test_fixture* ssl_fixture =
-      static_cast<ssl_tsi_test_fixture*>(gpr_zalloc(sizeof(*ssl_fixture)));
+  ssl_tsi_test_fixture* ssl_fixture = grpc_core::Zalloc<ssl_tsi_test_fixture>();
   tsi_test_fixture_init(&ssl_fixture->base);
   ssl_fixture->base.test_unused_bytes = true;
   ssl_fixture->base.vtable = &vtable;
   /* Create ssl_key_cert_lib. */
-  ssl_key_cert_lib* key_cert_lib =
-      static_cast<ssl_key_cert_lib*>(gpr_zalloc(sizeof(*key_cert_lib)));
+  ssl_key_cert_lib* key_cert_lib = grpc_core::Zalloc<ssl_key_cert_lib>();
   key_cert_lib->use_bad_server_cert = false;
   key_cert_lib->use_bad_client_cert = false;
   key_cert_lib->use_root_store = false;
@@ -500,8 +499,7 @@ static tsi_test_fixture* ssl_tsi_test_fixture_create() {
   GPR_ASSERT(key_cert_lib->root_store != nullptr);
   ssl_fixture->key_cert_lib = key_cert_lib;
   /* Create ssl_alpn_lib. */
-  ssl_alpn_lib* alpn_lib =
-      static_cast<ssl_alpn_lib*>(gpr_zalloc(sizeof(*alpn_lib)));
+  ssl_alpn_lib* alpn_lib = grpc_core::Zalloc<ssl_alpn_lib>();
   alpn_lib->server_alpn_protocols = static_cast<const char**>(
       gpr_zalloc(sizeof(char*) * SSL_TSI_TEST_ALPN_NUM));
   alpn_lib->client_alpn_protocols = static_cast<const char**>(
diff --git a/test/core/tsi/test_creds/crl_data/15e5c67a.0 b/test/core/tsi/test_creds/crl_data/15e5c67a.0
new file mode 120000 (symlink)
index 0000000..c4afefd
--- /dev/null
@@ -0,0 +1 @@
+valid.pem
\ No newline at end of file
diff --git a/test/core/tsi/test_creds/crl_data/26fefe27.0 b/test/core/tsi/test_creds/crl_data/26fefe27.0
new file mode 120000 (symlink)
index 0000000..6b2cd06
--- /dev/null
@@ -0,0 +1 @@
+revoked.pem
\ No newline at end of file
diff --git a/test/core/tsi/test_creds/crl_data/BUILD b/test/core/tsi/test_creds/crl_data/BUILD
new file mode 100644 (file)
index 0000000..a2a5cfe
--- /dev/null
@@ -0,0 +1,24 @@
+# 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.
+
+licenses(["notice"])
+
+exports_files([
+    "ca.pem",
+    "revoked.key",
+    "revoked.pem",
+    "valid.key",
+    "valid.pem",
+    "ab06acdd.r0",
+])
diff --git a/test/core/tsi/test_creds/crl_data/README b/test/core/tsi/test_creds/crl_data/README
new file mode 100644 (file)
index 0000000..708e74a
--- /dev/null
@@ -0,0 +1,54 @@
+The test credentials have been generated with the following
+commands:
+
+The ca is self-signed:
+----------------------
+
+$ openssl req -x509 -new -newkey rsa:2048 -nodes -keyout ca.key -out ca.pem \
+  -config ca-openssl.cnf -days 3650 -extensions v3_req
+When prompted for certificate information, everything is default.
+
+valid is issued by CA:
+----------------------------------------------------------------------------
+
+$ openssl genrsa -out valid.key.rsa 2048
+$ openssl pkcs8 -topk8 -in valid.key.rsa -out valid.key -nocrypt
+$ openssl req -new -key valid.key -out valid.csr
+
+When prompted for certificate information, everything is default except the
+common name which is set to valid.
+
+$ openssl x509 -req -CA ca.pem -CAkey ca.key -CAcreateserial -in valid.csr \
+  -out valid.pem  -days 3650
+
+revoked is issued by CA:
+-----------------------
+
+$ openssl genrsa -out revoked.key.rsa 2048
+$ openssl pkcs8 -topk8 -in revoked.key.rsa -out revoked.key -nocrypt
+$ openssl req -new -key revoked.key -out revoked.csr
+
+When prompted for certificate information, everything is default except the
+common name which is set to revoked.
+
+$ openssl x509 -req -CA ca.pem -CAkey ca.key -CAcreateserial -in revoked.csr \
+  -out revoked.pem -days 3650
+
+$ openssl ca -revoke revoked.pem -keyfile ca.key -cert ca.pem -config ca-openssl.cnf
+
+Generate the CRL file:
+----------------------------------------------------------------------------
+$ openssl ca -gencrl -out current.crl -keyfile ca.key -cert ca.pem
+$ openssl rehash ./
+
+Clean up:
+---------
+$ rm *.rsa
+$ rm *.csr
+$ rm ca.srl
+
+demoCA folder:
+----------------------------------------------------------------------------
+
+The demoCA folder contains files used by the openssl CA commands to revoke 
+credentials and create CRL files.
diff --git a/test/core/tsi/test_creds/crl_data/ab06acdd.0 b/test/core/tsi/test_creds/crl_data/ab06acdd.0
new file mode 120000 (symlink)
index 0000000..e375f5a
--- /dev/null
@@ -0,0 +1 @@
+ca.pem
\ No newline at end of file
diff --git a/test/core/tsi/test_creds/crl_data/ab06acdd.r0 b/test/core/tsi/test_creds/crl_data/ab06acdd.r0
new file mode 120000 (symlink)
index 0000000..2cf6617
--- /dev/null
@@ -0,0 +1 @@
+current.crl
\ No newline at end of file
diff --git a/test/core/tsi/test_creds/crl_data/ca-openssl.cnf b/test/core/tsi/test_creds/crl_data/ca-openssl.cnf
new file mode 100644 (file)
index 0000000..631ecb2
--- /dev/null
@@ -0,0 +1,17 @@
+[req]
+distinguished_name  = req_distinguished_name
+req_extensions = v3_req
+
+[req_distinguished_name]
+countryName           = Country Name (2 letter code)
+countryName_default = AU
+stateOrProvinceName   = State or Province Name (full name)
+stateOrProvinceName_default = Some-State
+organizationName          = Organization Name (eg, company)
+organizationName_default = Internet Widgits Pty Ltd
+commonName            = Common Name (eg, YOUR name)
+commonName_default = testca
+
+[v3_req]
+basicConstraints = CA:true
+keyUsage = critical, keyCertSign, cRLSign
diff --git a/test/core/tsi/test_creds/crl_data/ca.key b/test/core/tsi/test_creds/crl_data/ca.key
new file mode 100644 (file)
index 0000000..853f98d
--- /dev/null
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDVeuZVtfjw6RmH
+gSBxri+imN9XMC/2zrP6ZLeHVI8sTxNshDSfvtL50u41y0XK9WlAqpi+KTLHZv/v
+Oymt9G+QpoVccaW/Ui8/bgmi39Fg+vdsz2ZTmEu5N7gDLgWh1MWs6MNmUM43ZRlB
+v9A6pWYOTbHbv58aJdI1LmTLk+ZSqWmz9dvyaTF0q0i0gAdSQos/mJNDDIng6+zw
+sR0N5U0Zj6PtvVJ8XJT3csvYXaPvTn/nF8szQn+06n/CDodhvEd4cRNDwm+t4U/L
+0RrxfyZ9VmbdJ7dawtCJcJyLmU86pd3ENUgSKHjWft5azL1FLUoWAK7pH9sPPeFk
+XX6En0RVAgMBAAECggEAd42SPOHh/hiswWQhJUjlSGvQd+V2lwN/a3TICzPh0nCe
+ciE/z05wnJPx75JdDaKORTbEv4oW8/DM188MMm03pYx8Fx9WMWT3LNCU+O/bNDKY
+KgmkRqB9l8aKeM1nPhAIfCMGeuA5/G/Tyyx+krlaBByixGv10BDqPfozXIcBb7yG
+eJqpoNKPmHN9+wn09S1ftk8TBNPHSwwAEb9asIr3JaB5FOAZEPiCW1vNYuZZxhTR
+ehkVFXBkR3BMa/pRtTyIkfhjmre4gq2onbdcBgpbEyNMb2x7yarJ89m+IWxbRRQW
+I3If0UnW5gKBXLdd/0hsrPwsWsBCeTmQefSws+6HKQKBgQDzJaxaGz+9KZdt0TsM
+XaaIBihGgby0EKuj4Ib0hV0Jr3BXv6UDJy6cVyjMd3830cAAjAoBfnxfmIQEmz4E
+8cc72CsKz4FWhrFXN+IBVhx1SkcCoRGb91/NcgZ0YbjoXs4ibVm6hvQW7zHMvdVX
+z7Zu4a+fmDxCzl3hhA6OZtNRfwKBgQDgw8OnSVCmwg0Zoc03yM2ybVPxmvF5qqyZ
+0pQe9ta/0XfK7A961f+ltQSXFPQm62M6IOCtvw8SrZcDxyOOpZgRl95tix+U0ZoN
+nn6UX3PtRcPFQNZDL+SAG8+lCZ7Nmxq2TnjDRSKbzEF7Bre8ksG6LKbtiT5YncFP
+qSQiWMFsKwKBgQCRuWx4fIhQ6NJ24MVQ/ffG4lnVGABusucLyo9XkW5XVawxCwzs
+vNj0nlA3aw7192HpcgS1LIeCC7hjwl8DO5y6wy3YxtCveP5kVXvAbUmVCjVQ4BPb
+tADY8pPnwIG/0sIcZAk4/5TfAfCI0uVAQZ8HCX/mWKkVKPWfKTRIKFxSJQKBgDCd
+RxFEw0P+TtUPcRKyxQLlsLVePQKCzuhKaq0z2IkOpmlmm4aHCM9vkrmW16QfX4vw
+Foid/YWdtD8l8GPnHzgW8A4jfEY0+6wcbuZqqulUIJ7mgjFwB21KFqRsq0NvW9y4
+plgd+PlXuYYBkvYfi/VXuRdBixGhtXEkdWNUbSmXAoGAVbeLCopMQ7SO1Cu5ETsN
+Pc2ei4W0qO3B5WMC58R+A3q4m9a8sxatNaBW9L+4ohlVQiFGFEsjKl07FvWuSR8l
+t4GWbULd5MW4QUuRDEcDr/cgsLdK6qWSyUoeHCoM317UXkhAufWTxXiS1ZZ4g9ZG
+2g3HdQmD+yjBtjnMqSBA6DE=
+-----END PRIVATE KEY-----
diff --git a/test/core/tsi/test_creds/crl_data/ca.pem b/test/core/tsi/test_creds/crl_data/ca.pem
new file mode 100644 (file)
index 0000000..2a70778
--- /dev/null
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDTzCCAjegAwIBAgIJANxWk51OgC+2MA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNV
+BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
+aWRnaXRzIFB0eSBMdGQxDzANBgNVBAMMBnRlc3RjYTAeFw0yMTA5MjIwNTIzNTda
+Fw0zMTA5MjAwNTIzNTdaMFYxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0
+YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxDzANBgNVBAMM
+BnRlc3RjYTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANV65lW1+PDp
+GYeBIHGuL6KY31cwL/bOs/pkt4dUjyxPE2yENJ++0vnS7jXLRcr1aUCqmL4pMsdm
+/+87Ka30b5CmhVxxpb9SLz9uCaLf0WD692zPZlOYS7k3uAMuBaHUxazow2ZQzjdl
+GUG/0DqlZg5Nsdu/nxol0jUuZMuT5lKpabP12/JpMXSrSLSAB1JCiz+Yk0MMieDr
+7PCxHQ3lTRmPo+29UnxclPdyy9hdo+9Of+cXyzNCf7Tqf8IOh2G8R3hxE0PCb63h
+T8vRGvF/Jn1WZt0nt1rC0IlwnIuZTzql3cQ1SBIoeNZ+3lrMvUUtShYArukf2w89
+4WRdfoSfRFUCAwEAAaMgMB4wDAYDVR0TBAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw
+DQYJKoZIhvcNAQELBQADggEBALmcr+Xy7g6+HYL4US/YqD289Vi+9jbUbwZuVsfY
+J3mKdExL5cYtqDGA6WCRdjDnebpGnOP2Ui+Hb32Guh2Z0upnde32WurxkbwEUx1C
+TYwBpOqmL8PRg1J60MU+9l0TK/7y40JWLYEgKVN4wdhSjL916yH6jrsDDaRsR8eh
+xzyB8FEmOQ8UbNB0J8S6G1RS2LpFna1dbq/+TBx/6GgxU7MgaQpvYKaD45ZzVaA2
+6zsOZgSHCHMYRf1iG7AKeLGACNSAIk2xiqsE8sV/k8rohIbJCQT/fqRvgYCWCAMd
+/7YXQSi+M44wvyEw+jdHrBdn3BDwCd+tmikXkmbSIV9DqvI=
+-----END CERTIFICATE-----
diff --git a/test/core/tsi/test_creds/crl_data/current.crl b/test/core/tsi/test_creds/crl_data/current.crl
new file mode 100644 (file)
index 0000000..ca65872
--- /dev/null
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBzjCBtwIBATANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJBVTETMBEGA1UE
+CAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRk
+MQ8wDQYDVQQDDAZ0ZXN0Y2EXDTIxMDkyMjA1MzYyMFoXDTIxMTAyMjA1MzYyMFow
+HDAaAgkAiySwBjJlVHwXDTIxMDkyMjA1MzYwMVqgDzANMAsGA1UdFAQEAgIQADAN
+BgkqhkiG9w0BAQsFAAOCAQEAUFDfTvhdTHaJgMVf2vCMlJRW1lB7ATjnIwirRBR4
+iQBFtGeUep2D+0ZsAICocrp840rYVxTpXbhuP1CDm8jLo7/ih9BPGps3KgJGiy5i
+k+riEeVXSWWBZl3vaZnzd0NR3pood9+Of5hK/n9DYUctzdcpyZQDiFsdtZ1Nu7qY
+a5iFFfG3jc5TdIj8RrWCQe8hfSOcl9bjgFh4bSGHg464YNK9D8Vi5IW6/YC9Y2HL
+j4snAtcWSleN15GjyQVnZw2uLYw+3QNgjBEdC4tnEktUEKlQIHbRbKV2Ol1pd5O+
+tAOrMJFe94iXzHdOgdeyIQvQo8aflOnQ4uiDYEIjOyOMKQ==
+-----END X509 CRL-----
diff --git a/test/core/tsi/test_creds/crl_data/demoCA/crlnumber b/test/core/tsi/test_creds/crl_data/demoCA/crlnumber
new file mode 100644 (file)
index 0000000..dd11724
--- /dev/null
@@ -0,0 +1 @@
+1001
diff --git a/test/core/tsi/test_creds/crl_data/demoCA/crlnumber.old b/test/core/tsi/test_creds/crl_data/demoCA/crlnumber.old
new file mode 100644 (file)
index 0000000..83b33d2
--- /dev/null
@@ -0,0 +1 @@
+1000
diff --git a/test/core/tsi/test_creds/crl_data/demoCA/index.txt b/test/core/tsi/test_creds/crl_data/demoCA/index.txt
new file mode 100644 (file)
index 0000000..e288b25
--- /dev/null
@@ -0,0 +1 @@
+R      310920052448Z   210922053601Z   8B24B0063265547C        unknown /CN=revoked
diff --git a/test/core/tsi/test_creds/crl_data/demoCA/index.txt.attr b/test/core/tsi/test_creds/crl_data/demoCA/index.txt.attr
new file mode 100644 (file)
index 0000000..8f7e63a
--- /dev/null
@@ -0,0 +1 @@
+unique_subject = yes
diff --git a/test/core/tsi/test_creds/crl_data/demoCA/index.txt.old b/test/core/tsi/test_creds/crl_data/demoCA/index.txt.old
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/test/core/tsi/test_creds/crl_data/revoked.key b/test/core/tsi/test_creds/crl_data/revoked.key
new file mode 100644 (file)
index 0000000..971c857
--- /dev/null
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQD0eLyt9JWxYZPl
+8xbz5uVWupHP7Ds7AJTl8lOpVVWN7l7VH9YItYrnySO6dNOSti3sqe3dmi+V4GTx
+HJcmaUjyPAU3BPV5fKzUlw+sEMzN9k7TB/8rYxHeYkrRguzQDpOUItZmiKvSRi0F
+jOHZqYMInEmHkszgyIJ1hOVBmfRe895Qx91HBhD/OajHGzJkZboYLcdeSM0cG1gN
+K6VRhJ/ZPdv7Pq704hCMP/I9iBnN6lG3vl5lOViL/hicpnPm6+oH6gATsomsWyWc
+V/llH3TLiLcFp7+ThQhb1PTMRD9LUZpjILqCK3f0JRZNn/ZPbtzbmOwi4SJOVflb
+lwBNtRM1AgMBAAECggEAI2w7Kpl99y3EWFVYxg52vJJb/lykWHBFIuxx4t9SfjZD
+1229fZWQgvVKEAJNhbyP+vLEXI+yxWy2M5mI7S/kOfUobEhzqR6/jC43Px9QDafa
+1AkcmBTKygZEAQePeLYj/BrwJfs3qkgwzdUUBI3jRqQeo15KAWgMPyr6bP75wagb
+0mRW07XDSkh5N2oGuMywbzVuBGtRSaSf0s+plUFkaQ172ephgYX1QT57H/KE6Bmj
+70IPrdRwReUoTBoPgDtdbgwf6YcXA3+L5iObdfBfbivrlSygkF7Knt6sDL6Y0qr3
+/zFaxMyYTsw2Yon4gv5W1wm3zAnLJ/A2yHE80MGVIQKBgQD/yPeRxpafSw22qsfY
+OO0C7cThdeMAD5dswXBvK8Ab1YGP2fUJIq7p8IxDX579311eEb+tipzzdaNZlFkT
+JA4Yhre6nFDZjqnDcvTIaCeTMiTKWWssiWoRgI889337HMjyACeoZ/tVKN1YmHQ9
+uuPzEHQgaMMwh6YdHOP9zjIMNwKBgQD0rVX6MWBfzU22KFDQfw84PyvwNcmAkWyW
+VlAe8DOKazS5faRaOz7UdaSvH/gTPAPkhv4SjicfJbx+TCy296DYzKONkDXkdDcd
+bOfI/l/nrVt3UaZQQ0Zy7gAxl6soU4bcTgQ7j4ePZnDLVBwcTS/Z55jbiAnoq9ph
+ug/SWZjd8wKBgQChJrKji2SWU6j+LzbdiW/56meiTK2J+kjC4lS+FehhIPER+pYg
+/VMKXN1iDTqUZEfk3nXPFoev86vI4mgEYTDoTugukBF4ICPg2epS4Rwd5ve67P9S
+/fhvsnmMRbl/njEUFvjlZy24B5j9GoAR7E91ciZXzOk9CBmmOe+Cloh9nQKBgQDE
+MPEN6uXCK9cyRuV2KUvE6DKNLDPk2bbeXVtlU2mghhIC4lIU4AijR6nDmrjKg4cD
+iZLUwhNwkEuyYdZA6BKbhItoicgM5XsEJz08F2xDUuhSpq/bD/a/VUPmgB0H+uHa
+aNxP/ejO/W9YOptHvkSuT1xsO4rmfFZholXpb1p6LQKBgQDTrGyvjFBmFeq3b5e/
+lDpzaVQ0G0UGKCYVf84XrUnmwQjeYgMnXKLqrNmf2mC1E3HTZjb8doa+ckuZFT+l
+nTABhJGgV5qwdpZHSOAlBThJDu55hBzZ0iNwoEWI/g2V21frU3gWXZFm7Mwl9Q6h
+V20nkOwTZC9n0HnXYkt6DnXJAw==
+-----END PRIVATE KEY-----
diff --git a/test/core/tsi/test_creds/crl_data/revoked.pem b/test/core/tsi/test_creds/crl_data/revoked.pem
new file mode 100644 (file)
index 0000000..19812aa
--- /dev/null
@@ -0,0 +1,18 @@
+-----BEGIN CERTIFICATE-----
+MIIC5DCCAcwCCQCLJLAGMmVUfDANBgkqhkiG9w0BAQUFADBWMQswCQYDVQQGEwJB
+VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0
+cyBQdHkgTHRkMQ8wDQYDVQQDDAZ0ZXN0Y2EwHhcNMjEwOTIyMDUyNDQ4WhcNMzEw
+OTIwMDUyNDQ4WjASMRAwDgYDVQQDDAdyZXZva2VkMIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEA9Hi8rfSVsWGT5fMW8+blVrqRz+w7OwCU5fJTqVVVje5e
+1R/WCLWK58kjunTTkrYt7Knt3ZovleBk8RyXJmlI8jwFNwT1eXys1JcPrBDMzfZO
+0wf/K2MR3mJK0YLs0A6TlCLWZoir0kYtBYzh2amDCJxJh5LM4MiCdYTlQZn0XvPe
+UMfdRwYQ/zmoxxsyZGW6GC3HXkjNHBtYDSulUYSf2T3b+z6u9OIQjD/yPYgZzepR
+t75eZTlYi/4YnKZz5uvqB+oAE7KJrFslnFf5ZR90y4i3Bae/k4UIW9T0zEQ/S1Ga
+YyC6git39CUWTZ/2T27c25jsIuEiTlX5W5cATbUTNQIDAQABMA0GCSqGSIb3DQEB
+BQUAA4IBAQA/lJ/OxQLVo6p2LVznvWoHSEgyPOAmGKG6LZgCcn0Hnu9SXdVzB157
+ya93woq2DlBQkU90TbdbLA8Oa9o6ml54yPErYyffO9JObABhpSxgyj+AqiclTulT
+dNP2RUAMPXEb0AELZqKyLZoyG4We7FhwIp8SdPg9l5vHPKTMTxwY8rRaclViDH2i
+9gmuWtOdopwnaHdxj7CFIeaWytRxG1OcUALFF+SaaRglqhg0LaT0UIx69wqcGeRX
+le1ZphpZCials9Qtis0rxDBQ2E8uoVk8Q8HGDm1NmNOKoktzA31qIF0x64Hggymy
+PaxUJKc2QWOo7pUTGwDjDhicVSbPkMlI
+-----END CERTIFICATE-----
diff --git a/test/core/tsi/test_creds/crl_data/valid.key b/test/core/tsi/test_creds/crl_data/valid.key
new file mode 100644 (file)
index 0000000..972d097
--- /dev/null
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC4CFzc5ggbenQz
+9L4h6nhO0SLX/bVjORCNNB5cTm01nvmgQi4f3h2YS1afg9wUGmpIQSQW+dl2fSI+
+Nyv3MqHoAzVNanT1jCNN6fK8Rnhl7lK2+qEj52u0jXlIYccOwmprkezrYVR6XtJQ
+2o+JN+CaOmZCMfTzacUiwSRO7O0eDdTFpHyt6nPMZOL13XAdahY/755l6iBfBv//
+edc9IDR0vN53uJlL29CPiTKAweYGuX/k7D94u3AWIiGYJ17e3o0rtbx9HrTTlpbD
+Ft154BrQKWBVjhNJ3CnSrSgXe9s3jjDTt2MxSkFTzJeBcJoAxRMm76zzHIOb4iO1
+M29/RJyTAgMBAAECggEBAJSoFLNPkZ74tKM/gNKOvy4Tm8zToVEMSIV3Y0r3Axq8
+VzKQIwgU+N0LhmaGMiF/EPlavVdd7b7b5+xPztD48nYjGUx2wRGUaPRIFY7mcd0M
+vX4XSFFjX8pSOXUxnoUaoLJSBwo/7eiHbeZoFmgmXeTXZcD078QsXVTspXKnygZq
+j4Kz9xbAgOSUgQqk921HWElW1klkqsnPBVh+K3dUxPraDA6ypgr7gGU6RK/mBJKX
+MNKISj5jd7FyGTgM1+7ES38b5ZOAjoGG2uG2ZjfflsoqcA8jTYaRLCw+FQDtBiOb
+Z8SDqDicN8V8BWHY/Pue/VZHMKQ/NdgJ5RR4WgKE0+kCgYEA7ruEeCDF/gSm0C3h
+vVM6k5RKOzTRKOzrwoZlBoLI0RwQz+n2A4T2KVcsEeHCNy6t6YAc987LLjGHvUMf
+v9oZNxadz2+ucP446nN1QeA0c1qKtsXiv3oJw9AXUfJgQl2qnGaBZlx1R/cY4Ju8
+8tzgX77B11sZEX5lfU7XMvKiPLUCgYEAxVf/bQFHpZEXeUnt9uoqYICpEby664I/
+w4qyClkrqqCR6Q2/2qeFI68i6QJU19pfVf4Xx1WJYZPHgF+8X0BdlrXWPRZOgaw1
+AduOq9yRvHKjzToZTIUmTNGS3byvNA02iklSnJp4z/qq8qdARIz9K4BpzYzBrJo4
+vHB/sKCfCScCgYBE1wnB4iF1uD2p9jEL+P4BJFerbvWJSZhKRZrIH9psgh1O9vYb
+2bFqBlsM5P6uDuXTWUABLT5lmZ68sqhrGCcBPaJP+LJinswmvxhm4JH/WXJ6deGG
+uVgrgMvYs32SZZQW+XAC5lJjaBtiWUZI+ewxb75RrVEzPDFjyuI/LLwfqQKBgCrh
+E/77aDXxcMhJ6ArelpahXhschwDlLDWwzT6yYWqRuSKKekVoYOWACHXYq9a6/DwT
+GdeWHmO1WIPsSWHo+mzk1cgwMJ68bEgbDMULCB+KSU0ucpDN3aSTZPYJKYiF1nP1
+up2McvO946cV8ED04Y2yOUsQaoS2fd10FEqsm+HBAoGAFMfIGHdzcKQCE2j1Boh+
+6VQahRp4iLII+Vj5h9mIhNzGHAs04g9QIZy5kUOeSkOxp9ITTl8vjNxR7eNs9yWq
+20d6is2ODE25ZjHZf8UUCM/CyL8lJjWYr8ecCpVKIlKoZgIVZhGj3MJ1a18LlrbA
+kwY8DkNvKI6LkrwthL318zA=
+-----END PRIVATE KEY-----
diff --git a/test/core/tsi/test_creds/crl_data/valid.pem b/test/core/tsi/test_creds/crl_data/valid.pem
new file mode 100644 (file)
index 0000000..0cd8486
--- /dev/null
@@ -0,0 +1,18 @@
+-----BEGIN CERTIFICATE-----
+MIIC4jCCAcoCCQCLJLAGMmVUezANBgkqhkiG9w0BAQUFADBWMQswCQYDVQQGEwJB
+VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0
+cyBQdHkgTHRkMQ8wDQYDVQQDDAZ0ZXN0Y2EwHhcNMjEwOTIyMDUyNDI1WhcNMzEw
+OTIwMDUyNDI1WjAQMQ4wDAYDVQQDDAV2YWxpZDCCASIwDQYJKoZIhvcNAQEBBQAD
+ggEPADCCAQoCggEBALgIXNzmCBt6dDP0viHqeE7RItf9tWM5EI00HlxObTWe+aBC
+Lh/eHZhLVp+D3BQaakhBJBb52XZ9Ij43K/cyoegDNU1qdPWMI03p8rxGeGXuUrb6
+oSPna7SNeUhhxw7CamuR7OthVHpe0lDaj4k34Jo6ZkIx9PNpxSLBJE7s7R4N1MWk
+fK3qc8xk4vXdcB1qFj/vnmXqIF8G//951z0gNHS83ne4mUvb0I+JMoDB5ga5f+Ts
+P3i7cBYiIZgnXt7ejSu1vH0etNOWlsMW3XngGtApYFWOE0ncKdKtKBd72zeOMNO3
+YzFKQVPMl4FwmgDFEybvrPMcg5viI7Uzb39EnJMCAwEAATANBgkqhkiG9w0BAQUF
+AAOCAQEAEcdAD923j2nFHntNoF3teOa8w8M/nlJmNDkvRWBKPP3kNvyzrMF6D2Aw
+uX6djoi6YkJ1GJ5wG/QHKjYHi1Vja1clsBbDZj4SrEtoQb4/BZ7i21LQjtqgahvJ
+liSPzGDnj2g7I46iUR3GjD+RrX6FtODcwWsMrA58wx+6Yxz8qIRv/kuni+tZ2XGV
+BAA6iKjH+TXmsGHSyX0um/qmuE/wt6b7gVKPZXIp6vIfREH6d7qAHQwbnbd5PNsw
+rrfw6i6hMl/5KpVicVd+1yXFW1VdpMqbbDdIuhao6NEXkGC2/+mWnNufnWyHpobc
+NSboe1ZNMGNgNUANNy3H9Yhppidhgg==
+-----END CERTIFICATE-----
index 307ca57..6548af3 100644 (file)
@@ -26,6 +26,7 @@
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 
+#include "src/core/lib/gprpp/memory.h"
 #include "src/core/lib/security/transport/tsi_error.h"
 
 static void notification_signal(tsi_test_fixture* fixture) {
@@ -58,8 +59,7 @@ static handshaker_args* handshaker_args_create(tsi_test_fixture* fixture,
                                                bool is_client) {
   GPR_ASSERT(fixture != nullptr);
   GPR_ASSERT(fixture->config != nullptr);
-  handshaker_args* args =
-      static_cast<handshaker_args*>(gpr_zalloc(sizeof(*args)));
+  handshaker_args* args = new handshaker_args();
   args->fixture = fixture;
   args->handshake_buffer_size = fixture->handshake_buffer_size;
   args->handshake_buffer =
@@ -72,7 +72,7 @@ static handshaker_args* handshaker_args_create(tsi_test_fixture* fixture,
 static void handshaker_args_destroy(handshaker_args* args) {
   gpr_free(args->handshake_buffer);
   GRPC_ERROR_UNREF(args->error);
-  gpr_free(args);
+  delete args;
 }
 
 static void do_handshaker_next(handshaker_args* args);
@@ -583,8 +583,7 @@ void tsi_test_frame_protector_config_destroy(
 }
 
 static tsi_test_channel* tsi_test_channel_create() {
-  tsi_test_channel* channel =
-      static_cast<tsi_test_channel*>(gpr_zalloc(sizeof(*channel)));
+  tsi_test_channel* channel = grpc_core::Zalloc<tsi_test_channel>();
   channel->client_channel =
       static_cast<uint8_t*>(gpr_zalloc(TSI_TEST_DEFAULT_CHANNEL_SIZE));
   channel->server_channel =
index aaa9b68..fd2990c 100644 (file)
@@ -14,7 +14,7 @@
 
 load("//bazel:grpc_build_system.bzl", "grpc_cc_test", "grpc_package")
 
-grpc_package(name = "test/core/client_channel")
+grpc_package(name = "test/core/uri")
 
 licenses(["notice"])
 
index be970d8..d9884d5 100644 (file)
@@ -14,7 +14,7 @@
 
 load("//bazel:grpc_build_system.bzl", "grpc_cc_binary", "grpc_cc_library", "grpc_cc_test", "grpc_package")
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 grpc_package(
     name = "test/core/util",
@@ -88,7 +88,7 @@ grpc_cc_library(
         ":grpc_suppressions",
         ":stack_tracer",
         "//:gpr",
-        "//:grpc_base_c",
+        "//:grpc_base",
         "//:grpc_common",
     ],
 )
index c91a2f6..182370a 100644 (file)
@@ -33,6 +33,7 @@
 #include <grpc/support/string_util.h>
 
 #include "src/core/lib/gpr/string.h"
+#include "src/core/lib/gprpp/memory.h"
 
 typedef enum { ARGTYPE_INT, ARGTYPE_BOOL, ARGTYPE_STRING } argtype;
 
@@ -63,7 +64,7 @@ struct gpr_cmdline {
 static int normal_state(gpr_cmdline* cl, char* str);
 
 gpr_cmdline* gpr_cmdline_create(const char* description) {
-  gpr_cmdline* cl = static_cast<gpr_cmdline*>(gpr_zalloc(sizeof(gpr_cmdline)));
+  gpr_cmdline* cl = grpc_core::Zalloc<gpr_cmdline>();
 
   cl->description = description;
   cl->state = normal_state;
index a28f3fd..f7b0b5c 100644 (file)
@@ -28,12 +28,9 @@ namespace grpc_core {
 
 class EvaluateArgsTestUtil {
  public:
-  EvaluateArgsTestUtil() { grpc_metadata_batch_init(&metadata_); }
+  EvaluateArgsTestUtil() = default;
 
-  ~EvaluateArgsTestUtil() {
-    grpc_metadata_batch_destroy(&metadata_);
-    delete channel_args_;
-  }
+  ~EvaluateArgsTestUtil() { delete channel_args_; }
 
   void AddPairToMetadata(const char* key, const char* value) {
     metadata_storage_.emplace_back();
@@ -65,8 +62,9 @@ class EvaluateArgsTestUtil {
   }
 
  private:
+  ScopedArenaPtr arena_ = MakeScopedArena(1024);
   std::list<grpc_linked_mdelem> metadata_storage_;
-  grpc_metadata_batch metadata_;
+  grpc_metadata_batch metadata_{arena_.get()};
   MockAuthorizationEndpoint endpoint_{/*local_uri=*/"", /*peer_uri=*/""};
   grpc_auth_context auth_context_{nullptr};
   EvaluateArgs::PerChannelArgs* channel_args_ = nullptr;
index d2180c2..0638baf 100644 (file)
@@ -49,7 +49,7 @@ TEST_P(FuzzerCorpusTest, RunOneExample) {
   // implementations of that function will initialize and shutdown gRPC
   // internally.
   grpc_init();
-  gpr_log(GPR_DEBUG, "Example file: %s", GetParam().c_str());
+  gpr_log(GPR_INFO, "Example file: %s", GetParam().c_str());
   grpc_slice buffer;
   squelch = false;
   leak_check = false;
index 29c9b88..ffd8832 100644 (file)
@@ -18,6 +18,8 @@
 
 #include "test/core/util/fuzzer_util.h"
 
+#include <algorithm>
+
 #include <grpc/support/alloc.h>
 
 #include "src/core/lib/gpr/useful.h"
@@ -39,7 +41,7 @@ char* grpc_fuzzer_get_next_string(input_stream* inp, bool* special) {
   char c;
   do {
     if (cap == sz) {
-      cap = GPR_MAX(3 * cap / 2, cap + 8);
+      cap = std::max(3 * cap / 2, cap + 8);
       str = static_cast<char*>(gpr_realloc(str, cap));
     }
     c = static_cast<char>(grpc_fuzzer_get_next_byte(inp));
index 99594b2..c85a8f3 100644 (file)
 # limitations under the License.
 
 load("//bazel:grpc_build_system.bzl", "grpc_cc_test")
+load("@rules_proto//proto:defs.bzl", "proto_library")
+load("@rules_cc//cc:defs.bzl", "cc_proto_library")
 
 def grpc_fuzzer(name, corpus, srcs = [], deps = [], data = [], size = "large", **kwargs):
+    CORPUS_DIR = native.package_name() + "/" + corpus
     grpc_cc_test(
         name = name,
         srcs = srcs,
-        deps = deps + ["//test/core/util:fuzzer_corpus_test"],
+        deps = deps + select({
+            "//:grpc_build_fuzzers": [],
+            "//conditions:default": ["//test/core/util:fuzzer_corpus_test"],
+        }),
         data = data + native.glob([corpus + "/**"]),
         external_deps = [
             "gtest",
         ],
         size = size,
-        args = ["--directory=" + native.package_name() + "/" + corpus],
+        args = select({
+            "//:grpc_build_fuzzers": [CORPUS_DIR],
+            "//conditions:default": ["--directory=" + CORPUS_DIR],
+        }),
+        **kwargs
+    )
+
+def grpc_proto_fuzzer(name, corpus, proto, srcs = [], deps = [], data = [], size = "large", **kwargs):
+    PROTO_LIBRARY = "_%s_proto" % name
+    CC_PROTO_LIBRARY = "_%s_cc_proto" % name
+    CORPUS_DIR = native.package_name() + "/" + corpus
+
+    proto_library(
+        name = PROTO_LIBRARY,
+        srcs = [proto],
+    )
+
+    cc_proto_library(
+        name = CC_PROTO_LIBRARY,
+        deps = [PROTO_LIBRARY],
+    )
+
+    grpc_cc_test(
+        name = name,
+        srcs = srcs,
+        deps = deps + [
+            "@com_google_libprotobuf_mutator//:libprotobuf_mutator",
+            CC_PROTO_LIBRARY,
+        ] + select({
+            "//:grpc_build_fuzzers": [],
+            "//conditions:default": ["//test/core/util:fuzzer_corpus_test"],
+        }),
+        data = data + native.glob([corpus + "/**"]),
+        external_deps = [
+            "gtest",
+        ],
+        size = size,
+        args = select({
+            "//:grpc_build_fuzzers": [CORPUS_DIR],
+            "//conditions:default": ["--directory=" + CORPUS_DIR],
+        }),
         **kwargs
     )
index f60f705..fc3e21c 100644 (file)
@@ -63,7 +63,8 @@ static size_t bucket_for_unchecked(grpc_histogram* h, double x) {
 
 /* bounds checked version of the above */
 static size_t bucket_for(grpc_histogram* h, double x) {
-  size_t bucket = bucket_for_unchecked(h, GPR_CLAMP(x, 1.0, h->max_possible));
+  size_t bucket =
+      bucket_for_unchecked(h, grpc_core::Clamp(x, 1.0, h->max_possible));
   GPR_ASSERT(bucket < h->num_buckets);
   return bucket;
 }
@@ -187,10 +188,10 @@ static double threshold_for_count_below(grpc_histogram* h, double count_below) {
        should lie */
     lower_bound = bucket_start(h, static_cast<double>(lower_idx));
     upper_bound = bucket_start(h, static_cast<double>(lower_idx + 1));
-    return GPR_CLAMP(upper_bound - (upper_bound - lower_bound) *
-                                       (count_so_far - count_below) /
-                                       h->buckets[lower_idx],
-                     h->min_seen, h->max_seen);
+    return grpc_core::Clamp(upper_bound - (upper_bound - lower_bound) *
+                                              (count_so_far - count_below) /
+                                              h->buckets[lower_idx],
+                            h->min_seen, h->max_seen);
   }
 }
 
index 1f81d03..82864d6 100644 (file)
@@ -20,6 +20,8 @@
 
 #include <string.h>
 
+#include <algorithm>
+
 #include <grpc/support/alloc.h>
 
 #include "src/core/lib/gpr/useful.h"
@@ -114,7 +116,7 @@ grpc_slice grpc_slice_merge(grpc_slice* slices, size_t nslices) {
 
   for (i = 0; i < nslices; i++) {
     if (GRPC_SLICE_LENGTH(slices[i]) + length > capacity) {
-      capacity = GPR_MAX(capacity * 2, GRPC_SLICE_LENGTH(slices[i]) + length);
+      capacity = std::max(capacity * 2, GRPC_SLICE_LENGTH(slices[i]) + length);
       out = static_cast<uint8_t*>(gpr_realloc(out, capacity));
     }
     memcpy(out + length, GRPC_SLICE_START_PTR(slices[i]),
index 186256f..6136314 100644 (file)
@@ -34,6 +34,7 @@
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 
+#include "src/core/lib/gprpp/memory.h"
 #include "test/core/util/subprocess.h"
 
 struct gpr_subprocess {
@@ -61,7 +62,7 @@ gpr_subprocess* gpr_subprocess_create(int argc, const char** argv) {
     gpr_log(GPR_ERROR, "execv '%s' failed: %s", exec_args[0], strerror(errno));
     _exit(1);
   } else {
-    r = static_cast<gpr_subprocess*>(gpr_zalloc(sizeof(gpr_subprocess)));
+    r = grpc_core::Zalloc<gpr_subprocess>();
     r->pid = pid;
     return r;
   }
index cb5e516..03b6ef0 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "src/core/ext/filters/client_channel/lb_policy.h"
 #include "src/core/ext/filters/client_channel/lb_policy_registry.h"
+#include "src/core/lib/address_utils/parse_address.h"
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/channel/channelz.h"
 #include "src/core/lib/debug/trace.h"
@@ -33,6 +34,7 @@
 #include "src/core/lib/iomgr/error.h"
 #include "src/core/lib/iomgr/pollset_set.h"
 #include "src/core/lib/json/json.h"
+#include "src/core/lib/json/json_util.h"
 #include "src/core/lib/transport/connectivity_state.h"
 
 namespace grpc_core {
@@ -138,6 +140,10 @@ class TestPickArgsLb : public ForwardingLoadBalancingPolicy {
       parent_->channel_control_helper()->RequestReresolution();
     }
 
+    absl::string_view GetAuthority() override {
+      return parent_->channel_control_helper()->GetAuthority();
+    }
+
     void AddTraceEvent(TraceSeverity severity,
                        absl::string_view message) override {
       parent_->channel_control_helper()->AddTraceEvent(severity, message);
@@ -252,6 +258,10 @@ class InterceptRecvTrailingMetadataLoadBalancingPolicy
       parent_->channel_control_helper()->RequestReresolution();
     }
 
+    absl::string_view GetAuthority() override {
+      return parent_->channel_control_helper()->GetAuthority();
+    }
+
     void AddTraceEvent(TraceSeverity severity,
                        absl::string_view message) override {
       parent_->channel_control_helper()->AddTraceEvent(severity, message);
@@ -365,6 +375,10 @@ class AddressTestLoadBalancingPolicy : public ForwardingLoadBalancingPolicy {
       parent_->channel_control_helper()->RequestReresolution();
     }
 
+    absl::string_view GetAuthority() override {
+      return parent_->channel_control_helper()->GetAuthority();
+    }
+
     void AddTraceEvent(TraceSeverity severity,
                        absl::string_view message) override {
       parent_->channel_control_helper()->AddTraceEvent(severity, message);
@@ -401,6 +415,119 @@ class AddressTestFactory : public LoadBalancingPolicyFactory {
   AddressTestCallback cb_;
 };
 
+//
+// FixedAddressLoadBalancingPolicy
+//
+
+constexpr char kFixedAddressLbPolicyName[] = "fixed_address_lb";
+
+class FixedAddressConfig : public LoadBalancingPolicy::Config {
+ public:
+  explicit FixedAddressConfig(std::string address)
+      : address_(std::move(address)) {}
+
+  const char* name() const override { return kFixedAddressLbPolicyName; }
+
+  const std::string& address() const { return address_; }
+
+ private:
+  std::string address_;
+};
+
+class FixedAddressLoadBalancingPolicy : public ForwardingLoadBalancingPolicy {
+ public:
+  explicit FixedAddressLoadBalancingPolicy(Args args)
+      : ForwardingLoadBalancingPolicy(
+            absl::make_unique<Helper>(
+                RefCountedPtr<FixedAddressLoadBalancingPolicy>(this)),
+            std::move(args),
+            /*delegate_policy_name=*/"pick_first",
+            /*initial_refcount=*/2) {}
+
+  ~FixedAddressLoadBalancingPolicy() override = default;
+
+  const char* name() const override { return kFixedAddressLbPolicyName; }
+
+  void UpdateLocked(UpdateArgs args) override {
+    auto* config = static_cast<FixedAddressConfig*>(args.config.get());
+    gpr_log(GPR_INFO, "%s: update URI: %s", kFixedAddressLbPolicyName,
+            config->address().c_str());
+    auto uri = URI::Parse(config->address());
+    args.config.reset();
+    args.addresses.clear();
+    if (uri.ok()) {
+      grpc_resolved_address address;
+      GPR_ASSERT(grpc_parse_uri(*uri, &address));
+      args.addresses.emplace_back(address, /*args=*/nullptr);
+    } else {
+      gpr_log(GPR_ERROR,
+              "%s: could not parse URI (%s), using empty address list",
+              kFixedAddressLbPolicyName, uri.status().ToString().c_str());
+    }
+    ForwardingLoadBalancingPolicy::UpdateLocked(std::move(args));
+  }
+
+ private:
+  class Helper : public ChannelControlHelper {
+   public:
+    explicit Helper(RefCountedPtr<FixedAddressLoadBalancingPolicy> parent)
+        : parent_(std::move(parent)) {}
+
+    RefCountedPtr<SubchannelInterface> CreateSubchannel(
+        ServerAddress address, const grpc_channel_args& args) override {
+      return parent_->channel_control_helper()->CreateSubchannel(
+          std::move(address), args);
+    }
+
+    void UpdateState(grpc_connectivity_state state, const absl::Status& status,
+                     std::unique_ptr<SubchannelPicker> picker) override {
+      parent_->channel_control_helper()->UpdateState(state, status,
+                                                     std::move(picker));
+    }
+
+    void RequestReresolution() override {
+      parent_->channel_control_helper()->RequestReresolution();
+    }
+
+    absl::string_view GetAuthority() override {
+      return parent_->channel_control_helper()->GetAuthority();
+    }
+
+    void AddTraceEvent(TraceSeverity severity,
+                       absl::string_view message) override {
+      parent_->channel_control_helper()->AddTraceEvent(severity, message);
+    }
+
+   private:
+    RefCountedPtr<FixedAddressLoadBalancingPolicy> parent_;
+  };
+};
+
+class FixedAddressFactory : public LoadBalancingPolicyFactory {
+ public:
+  FixedAddressFactory() = default;
+
+  OrphanablePtr<LoadBalancingPolicy> CreateLoadBalancingPolicy(
+      LoadBalancingPolicy::Args args) const override {
+    return MakeOrphanable<FixedAddressLoadBalancingPolicy>(std::move(args));
+  }
+
+  const char* name() const override { return kFixedAddressLbPolicyName; }
+
+  RefCountedPtr<LoadBalancingPolicy::Config> ParseLoadBalancingConfig(
+      const Json& json, grpc_error_handle* error) const override {
+    std::vector<grpc_error_handle> error_list;
+    std::string address;
+    ParseJsonObjectField(json.object_value(), "address", &address, &error_list);
+    if (!error_list.empty()) {
+      *error = GRPC_ERROR_CREATE_FROM_VECTOR(
+          "errors parsing fixed_address_lb config", &error_list);
+      return nullptr;
+    }
+    return MakeRefCounted<FixedAddressConfig>(std::move(address));
+  }
+};
+
 }  // namespace
 
 void RegisterTestPickArgsLoadBalancingPolicy(TestPickArgsCallback cb,
@@ -421,4 +548,9 @@ void RegisterAddressTestLoadBalancingPolicy(AddressTestCallback cb) {
       absl::make_unique<AddressTestFactory>(std::move(cb)));
 }
 
+void RegisterFixedAddressLoadBalancingPolicy() {
+  LoadBalancingPolicyRegistry::Builder::RegisterLoadBalancingPolicyFactory(
+      absl::make_unique<FixedAddressFactory>());
+}
+
 }  // namespace grpc_core
index e583abc..805f105 100644 (file)
@@ -54,6 +54,10 @@ using AddressTestCallback = std::function<void(const ServerAddress&)>;
 // address used to create a subchannel.
 void RegisterAddressTestLoadBalancingPolicy(AddressTestCallback cb);
 
+// Registers an LB policy called "fixed_address_lb" that provides a
+// single subchannel whose address is in its configuration.
+void RegisterFixedAddressLoadBalancingPolicy();
+
 }  // namespace grpc_core
 
 #endif  // GRPC_TEST_CORE_UTIL_TEST_LB_POLICIES_H
index f0e872a..49c7009 100644 (file)
@@ -182,7 +182,7 @@ size_t grpc_trickle_endpoint_trickle(grpc_endpoint* ep) {
     // gpr_log(GPR_DEBUG, "%lf elapsed --> %" PRIdPTR " bytes", elapsed, bytes);
     if (bytes > 0) {
       grpc_slice_buffer_move_first(&te->write_buffer,
-                                   GPR_MIN(bytes, te->write_buffer.length),
+                                   std::min(bytes, te->write_buffer.length),
                                    &te->writing_buffer);
       te->writing = true;
       te->last_write = now;
index ddf5afb..015f4b8 100644 (file)
@@ -21,6 +21,7 @@ enum:grpc_op_string
 signed-integer-overflow:chrono
 enum:grpc_http2_error_to_grpc_status
 enum:grpc_chttp2_cancel_stream
+enum:api_fuzzer
 # TODO(juanlishen): Remove this supression after
 # https://github.com/GoogleCloudPlatform/layer-definitions/issues/531 is
 # addressed.
index e12d115..1ef10d6 100644 (file)
@@ -70,6 +70,21 @@ grpc_cc_test(
 )
 
 grpc_cc_test(
+    name = "xds_channel_stack_modifier_test",
+    srcs = ["xds_channel_stack_modifier_test.cc"],
+    external_deps = ["gtest"],
+    language = "C++",
+    tags = ["no_test_ios"],
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//:grpc_opencensus_plugin",
+        "//:grpc_xds_channel_stack_modifier",
+        "//test/core/util:grpc_test_util",
+    ],
+)
+
+grpc_cc_test(
     name = "xds_certificate_provider_test",
     srcs = ["xds_certificate_provider_test.cc"],
     external_deps = ["gtest"],
diff --git a/test/core/xds/xds_channel_stack_modifier_test.cc b/test/core/xds/xds_channel_stack_modifier_test.cc
new file mode 100644 (file)
index 0000000..7e80414
--- /dev/null
@@ -0,0 +1,165 @@
+//
+//
+// 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 "src/core/ext/xds/xds_channel_stack_modifier.h"
+
+#include <gtest/gtest.h>
+
+#include <grpcpp/opencensus.h>
+
+#include "src/core/lib/config/core_configuration.h"
+#include "src/core/lib/surface/channel_init.h"
+#include "src/core/lib/transport/transport_impl.h"
+#include "test/core/util/test_config.h"
+
+namespace grpc_core {
+namespace testing {
+namespace {
+
+// Test that XdsChannelStackModifier can be safely copied to channel args
+// and destroyed
+TEST(XdsChannelStackModifierTest, CopyChannelArgs) {
+  grpc_init();
+  auto channel_stack_modifier = MakeRefCounted<XdsChannelStackModifier>(
+      std::vector<const grpc_channel_filter*>{});
+  grpc_arg arg = channel_stack_modifier->MakeChannelArg();
+  grpc_channel_args* args = grpc_channel_args_copy_and_add(nullptr, &arg, 1);
+  EXPECT_EQ(channel_stack_modifier,
+            XdsChannelStackModifier::GetFromChannelArgs(*args));
+  grpc_channel_args_destroy(args);
+  grpc_shutdown();
+}
+
+// Test compare on channel args with the same XdsChannelStackModifier
+TEST(XdsChannelStackModifierTest, ChannelArgsCompare) {
+  grpc_init();
+  auto channel_stack_modifier = MakeRefCounted<XdsChannelStackModifier>(
+      std::vector<const grpc_channel_filter*>{});
+  grpc_arg arg = channel_stack_modifier->MakeChannelArg();
+  grpc_channel_args* args = grpc_channel_args_copy_and_add(nullptr, &arg, 1);
+  grpc_channel_args* new_args = grpc_channel_args_copy(args);
+  EXPECT_EQ(XdsChannelStackModifier::GetFromChannelArgs(*new_args),
+            XdsChannelStackModifier::GetFromChannelArgs(*args));
+  grpc_channel_args_destroy(args);
+  grpc_channel_args_destroy(new_args);
+  grpc_shutdown();
+}
+
+constexpr char kTestFilter1[] = "test_filter_1";
+constexpr char kTestFilter2[] = "test_filter_2";
+
+// Test filters insertion
+TEST(XdsChannelStackModifierTest, XdsHttpFiltersInsertion) {
+  CoreConfiguration::Reset();
+  grpc_init();
+  // Add 2 test filters to XdsChannelStackModifier
+  const grpc_channel_filter test_filter_1 = {
+      nullptr, nullptr, 0,       nullptr, nullptr,     nullptr,
+      0,       nullptr, nullptr, nullptr, kTestFilter1};
+  const grpc_channel_filter test_filter_2 = {
+      nullptr, nullptr, 0,       nullptr, nullptr,     nullptr,
+      0,       nullptr, nullptr, nullptr, kTestFilter2};
+  auto channel_stack_modifier = MakeRefCounted<XdsChannelStackModifier>(
+      std::vector<const grpc_channel_filter*>{&test_filter_1, &test_filter_2});
+  grpc_arg arg = channel_stack_modifier->MakeChannelArg();
+  // Create a phony grpc_channel_stack_builder object
+  grpc_channel_args* args = grpc_channel_args_copy_and_add(nullptr, &arg, 1);
+  grpc_channel_stack_builder* builder = grpc_channel_stack_builder_create();
+  grpc_channel_stack_builder_set_channel_arguments(builder, args);
+  grpc_channel_args_destroy(args);
+  grpc_transport_vtable fake_transport_vtable;
+  memset(&fake_transport_vtable, 0, sizeof(grpc_transport_vtable));
+  fake_transport_vtable.name = "fake";
+  grpc_transport fake_transport = {&fake_transport_vtable};
+  grpc_channel_stack_builder_set_transport(builder, &fake_transport);
+  // Construct channel stack and verify that the test filters were successfully
+  // added
+  ASSERT_TRUE(CoreConfiguration::Get().channel_init().CreateStack(
+      builder, GRPC_SERVER_CHANNEL));
+  grpc_channel_stack_builder_iterator* it =
+      grpc_channel_stack_builder_create_iterator_at_first(builder);
+  ASSERT_TRUE(grpc_channel_stack_builder_move_next(it));
+  ASSERT_STREQ(grpc_channel_stack_builder_iterator_filter_name(it), "server");
+  ASSERT_TRUE(grpc_channel_stack_builder_move_next(it));
+  ASSERT_STREQ(grpc_channel_stack_builder_iterator_filter_name(it),
+               kTestFilter1);
+  ASSERT_TRUE(grpc_channel_stack_builder_move_next(it));
+  ASSERT_STREQ(grpc_channel_stack_builder_iterator_filter_name(it),
+               kTestFilter2);
+  grpc_channel_stack_builder_iterator_destroy(it);
+  grpc_channel_stack_builder_destroy(builder);
+  grpc_shutdown();
+}
+
+// Test filters insertion with OpenCensus plugin registered
+TEST(XdsChannelStackModifierTest, XdsHttpFiltersInsertionAfterCensus) {
+  CoreConfiguration::Reset();
+  grpc::RegisterOpenCensusPlugin();
+  grpc_init();
+  // Add 2 test filters to XdsChannelStackModifier
+  const grpc_channel_filter test_filter_1 = {
+      nullptr, nullptr, 0,       nullptr, nullptr,     nullptr,
+      0,       nullptr, nullptr, nullptr, kTestFilter1};
+  const grpc_channel_filter test_filter_2 = {
+      nullptr, nullptr, 0,       nullptr, nullptr,     nullptr,
+      0,       nullptr, nullptr, nullptr, kTestFilter2};
+  auto channel_stack_modifier = MakeRefCounted<XdsChannelStackModifier>(
+      std::vector<const grpc_channel_filter*>{&test_filter_1, &test_filter_2});
+  grpc_arg arg = channel_stack_modifier->MakeChannelArg();
+  // Create a phony grpc_channel_stack_builder object
+  grpc_channel_args* args = grpc_channel_args_copy_and_add(nullptr, &arg, 1);
+  grpc_channel_stack_builder* builder = grpc_channel_stack_builder_create();
+  grpc_channel_stack_builder_set_channel_arguments(builder, args);
+  grpc_channel_args_destroy(args);
+  grpc_transport_vtable fake_transport_vtable;
+  memset(&fake_transport_vtable, 0, sizeof(grpc_transport_vtable));
+  fake_transport_vtable.name = "fake";
+  grpc_transport fake_transport = {&fake_transport_vtable};
+  grpc_channel_stack_builder_set_transport(builder, &fake_transport);
+  // Construct channel stack and verify that the test filters were successfully
+  // added after the census filter
+  ASSERT_TRUE(CoreConfiguration::Get().channel_init().CreateStack(
+      builder, GRPC_SERVER_CHANNEL));
+  grpc_channel_stack_builder_iterator* it =
+      grpc_channel_stack_builder_create_iterator_at_first(builder);
+  ASSERT_TRUE(grpc_channel_stack_builder_move_next(it));
+  ASSERT_STREQ(grpc_channel_stack_builder_iterator_filter_name(it), "server");
+  ASSERT_TRUE(grpc_channel_stack_builder_move_next(it));
+  ASSERT_STREQ(grpc_channel_stack_builder_iterator_filter_name(it),
+               "opencensus_server");
+  ASSERT_TRUE(grpc_channel_stack_builder_move_next(it));
+  ASSERT_STREQ(grpc_channel_stack_builder_iterator_filter_name(it),
+               kTestFilter1);
+  ASSERT_TRUE(grpc_channel_stack_builder_move_next(it));
+  ASSERT_STREQ(grpc_channel_stack_builder_iterator_filter_name(it),
+               kTestFilter2);
+  grpc_channel_stack_builder_iterator_destroy(it);
+  grpc_channel_stack_builder_destroy(builder);
+  grpc_shutdown();
+}
+
+}  // namespace
+}  // namespace testing
+}  // namespace grpc_core
+
+int main(int argc, char** argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  grpc::testing::TestEnvironment env(argc, argv);
+  int ret = RUN_ALL_TESTS();
+  return ret;
+}
index c62c633..af0d86d 100644 (file)
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_package")
 
index 6a1b2ef..24c9190 100644 (file)
@@ -45,7 +45,6 @@
 #include "src/core/lib/gprpp/ref_counted_ptr.h"
 #include "src/core/lib/gprpp/thd.h"
 #include "src/core/lib/iomgr/sockaddr.h"
-#include "src/core/lib/transport/authority_override.h"
 #include "src/proto/grpc/lb/v1/load_balancer.grpc.pb.h"
 #include "src/proto/grpc/testing/echo.grpc.pb.h"
 #include "test/core/util/port.h"
@@ -228,8 +227,9 @@ class ClientChannelStressTest {
       GPR_ASSERT(lb_uri.ok());
       grpc_resolved_address address;
       GPR_ASSERT(grpc_parse_uri(*lb_uri, &address));
-      grpc_arg arg = grpc_core::CreateAuthorityOverrideChannelArg(
-          addr.balancer_name.c_str());
+      grpc_arg arg = grpc_channel_arg_string_create(
+          const_cast<char*>(GRPC_ARG_DEFAULT_AUTHORITY),
+          const_cast<char*>(addr.balancer_name.c_str()));
       grpc_channel_args* args =
           grpc_channel_args_copy_and_add(nullptr, &arg, 1);
       addresses.emplace_back(address.addr, address.len, args);
index 6daf089..147d571 100644 (file)
@@ -18,37 +18,6 @@ GRPC_LOCAL_SRC = '../../..'
   end
 end
 
-# gRPC-Core.podspec needs to be modified to be successfully used for local development. A Podfile's
-# pre_install hook lets us do that. The block passed to it runs after the podspecs are downloaded
-# and before they are installed in the user project.
-#
-# This podspec searches for the gRPC core library headers under "$(PODS_ROOT)/gRPC-Core", where
-# Cocoapods normally places the downloaded sources. When doing local development of the libraries,
-# though, Cocoapods just takes the sources from whatever directory was specified using `:path`, and
-# doesn't copy them under $(PODS_ROOT). When using static libraries, one can sometimes rely on the
-# symbolic links to the pods headers that Cocoapods creates under "$(PODS_ROOT)/Headers". But those
-# aren't created when using dynamic frameworks. So our solution is to modify the podspec on the fly
-# to point at the local directory where the sources are.
-#
-# TODO(jcanizales): Send a PR to Cocoapods to get rid of this need.
-pre_install do |installer|
-  # This is the gRPC-Core podspec object, as initialized by its podspec file.
-  grpc_core_spec = installer.pod_targets.find{|t| t.name == 'gRPC-Core'}.root_spec
-
-  # Copied from gRPC-Core.podspec, except for the adjusted src_root:
-  src_root = "$(PODS_ROOT)/../#{GRPC_LOCAL_SRC}"
-  grpc_core_spec.pod_target_xcconfig = {
-    'GRPC_SRC_ROOT' => src_root,
-    'HEADER_SEARCH_PATHS' => '"$(inherited)" "$(GRPC_SRC_ROOT)/include"',
-    'USER_HEADER_SEARCH_PATHS' => '"$(GRPC_SRC_ROOT)"',
-    # If we don't set these two settings, `include/grpc/support/time.h` and
-    # `src/core/lib/support/string.h` shadow the system `<time.h>` and `<string.h>`, breaking the
-    # build.
-    'USE_HEADERMAP' => 'NO',
-    'ALWAYS_SEARCH_USER_PATHS' => 'NO',
-  }
-end
-
 post_install do |installer|
   installer.pods_project.targets.each do |target|
     target.build_configurations.each do |config|
index b7bad5f..560f512 100644 (file)
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 load("//bazel:grpc_build_system.bzl", "grpc_cc_binary", "grpc_cc_test", "grpc_package", "grpc_sh_test")
 
index 8b21260..1e25f28 100644 (file)
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 load("//bazel:grpc_build_system.bzl", "grpc_cc_test", "grpc_package")
 
index b1e7ee1..f3c67d5 100644 (file)
@@ -53,7 +53,7 @@ bool test_mutator_mutate_fd(int fd, grpc_socket_mutator* mutator) {
 }
 
 int test_mutator_compare(grpc_socket_mutator* a, grpc_socket_mutator* b) {
-  return GPR_ICMP(a, b);
+  return grpc_core::QsortCompare(a, b);
 }
 
 void test_mutator_destroy(grpc_socket_mutator* mutator) {
index 5237fe7..e59d371 100644 (file)
@@ -48,6 +48,15 @@ grpc_cc_library(
 )
 
 grpc_cc_library(
+    name = "counted_service",
+    testonly = True,
+    hdrs = ["counted_service.h"],
+    deps = [
+        "//:grpc",
+    ],
+)
+
+grpc_cc_library(
     name = "interceptors_util",
     testonly = True,
     srcs = ["interceptors_util.cc"],
@@ -461,7 +470,7 @@ grpc_cc_test(
         "//src/proto/grpc/testing:echo_messages_proto",
         "//src/proto/grpc/testing:echo_proto",
         "//src/proto/grpc/testing/duplicate:echo_duplicate_proto",
-        "//src/proto/grpc/testing/xds:orca_load_report_for_test_proto",
+        "//src/proto/grpc/testing/xds/v3:orca_load_report_proto",
         "//test/core/util:grpc_test_util",
         "//test/core/util:test_lb_policies",
         "//test/cpp/util:test_util",
@@ -469,98 +478,68 @@ grpc_cc_test(
 )
 
 grpc_cc_test(
-    name = "service_config_end2end_test",
-    srcs = ["service_config_end2end_test.cc"],
+    name = "rls_end2end_test",
+    srcs = ["rls_end2end_test.cc"],
     external_deps = [
         "gtest",
+        "absl/types:optional",
     ],
+    tags = ["no_test_ios"],
     deps = [
+        ":counted_service",
         ":test_service_impl",
         "//:gpr",
         "//:grpc",
         "//:grpc++",
+        "//src/proto/grpc/lookup/v1:rls_proto",
         "//src/proto/grpc/testing:echo_messages_proto",
         "//src/proto/grpc/testing:echo_proto",
         "//src/proto/grpc/testing/duplicate:echo_duplicate_proto",
         "//test/core/util:grpc_test_util",
+        "//test/core/util:test_lb_policies",
+        "//test/cpp/util:test_config",
         "//test/cpp/util:test_util",
     ],
 )
 
 grpc_cc_test(
-    name = "grpclb_end2end_test",
-    srcs = ["grpclb_end2end_test.cc"],
+    name = "service_config_end2end_test",
+    srcs = ["service_config_end2end_test.cc"],
     external_deps = [
         "gtest",
     ],
-    flaky = True,  # TODO(b/150567713)
-    tags = ["no_windows"],  # TODO(jtattermusch): fix test on windows
     deps = [
         ":test_service_impl",
         "//:gpr",
         "//:grpc",
         "//:grpc++",
-        "//:grpc_resolver_fake",
-        "//src/proto/grpc/lb/v1:load_balancer_proto",
         "//src/proto/grpc/testing:echo_messages_proto",
         "//src/proto/grpc/testing:echo_proto",
         "//src/proto/grpc/testing/duplicate:echo_duplicate_proto",
         "//test/core/util:grpc_test_util",
-        "//test/cpp/util:test_config",
         "//test/cpp/util:test_util",
     ],
 )
 
 grpc_cc_test(
-    name = "xds_end2end_test",
-    size = "large",
-    srcs = ["xds_end2end_test.cc"],
-    data = [
-        "//src/core/tsi/test_creds:badclient.key",
-        "//src/core/tsi/test_creds:badclient.pem",
-        "//src/core/tsi/test_creds:ca.pem",
-        "//src/core/tsi/test_creds:client.key",
-        "//src/core/tsi/test_creds:client.pem",
-        "//src/core/tsi/test_creds:server1.key",
-        "//src/core/tsi/test_creds:server1.pem",
-    ],
+    name = "grpclb_end2end_test",
+    srcs = ["grpclb_end2end_test.cc"],
     external_deps = [
         "gtest",
     ],
-    flaky = True,  # TODO(b/144705388)
-    shard_count = 20,
-    tags = [
-        "no_test_ios",
-        "no_windows",
-    ],  # TODO(jtattermusch): fix test on windows
+    flaky = True,  # TODO(b/150567713)
+    tags = ["no_windows"],  # TODO(jtattermusch): fix test on windows
     deps = [
+        ":counted_service",
         ":test_service_impl",
         "//:gpr",
         "//:grpc",
         "//:grpc++",
         "//:grpc_resolver_fake",
-        "//:grpcpp_csds",
+        "//src/proto/grpc/lb/v1:load_balancer_proto",
         "//src/proto/grpc/testing:echo_messages_proto",
         "//src/proto/grpc/testing:echo_proto",
         "//src/proto/grpc/testing/duplicate:echo_duplicate_proto",
-        "//src/proto/grpc/testing/xds:ads_for_test_proto",
-        "//src/proto/grpc/testing/xds:cds_for_test_proto",
-        "//src/proto/grpc/testing/xds:eds_for_test_proto",
-        "//src/proto/grpc/testing/xds:lds_rds_for_test_proto",
-        "//src/proto/grpc/testing/xds:lrs_for_test_proto",
-        "//src/proto/grpc/testing/xds/v3:ads_proto",
-        "//src/proto/grpc/testing/xds/v3:aggregate_cluster_proto",
-        "//src/proto/grpc/testing/xds/v3:cluster_proto",
-        "//src/proto/grpc/testing/xds/v3:discovery_proto",
-        "//src/proto/grpc/testing/xds/v3:endpoint_proto",
-        "//src/proto/grpc/testing/xds/v3:fault_common_proto",
-        "//src/proto/grpc/testing/xds/v3:fault_proto",
-        "//src/proto/grpc/testing/xds/v3:http_connection_manager_proto",
-        "//src/proto/grpc/testing/xds/v3:listener_proto",
-        "//src/proto/grpc/testing/xds/v3:lrs_proto",
-        "//src/proto/grpc/testing/xds/v3:route_proto",
-        "//src/proto/grpc/testing/xds/v3:router_proto",
-        "//src/proto/grpc/testing/xds/v3:tls_proto",
         "//test/core/util:grpc_test_util",
         "//test/cpp/util:test_config",
         "//test/cpp/util:test_util",
@@ -859,25 +838,6 @@ grpc_cc_test(
 )
 
 grpc_cc_test(
-    name = "xds_credentials_end2end_test",
-    srcs = ["xds_credentials_end2end_test.cc"],
-    external_deps = [
-        "gtest",
-    ],
-    tags = ["no_test_ios"],
-    deps = [
-        ":test_service_impl",
-        "//:gpr",
-        "//:grpc",
-        "//:grpc++",
-        "//src/proto/grpc/testing:echo_messages_proto",
-        "//src/proto/grpc/testing:echo_proto",
-        "//test/core/util:grpc_test_util",
-        "//test/cpp/util:test_util",
-    ],
-)
-
-grpc_cc_test(
     name = "admin_services_end2end_test",
     srcs = ["admin_services_end2end_test.cc"],
     external_deps = [
index 90f633d..3892400 100644 (file)
@@ -49,7 +49,7 @@
 #include "src/core/ext/filters/client_channel/global_subchannel_pool.h"
 #include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h"
 #include "src/core/ext/filters/client_channel/server_address.h"
-#include "src/core/ext/filters/client_channel/service_config.h"
+#include "src/core/ext/service_config/service_config.h"
 #include "src/core/lib/address_utils/parse_address.h"
 #include "src/core/lib/backoff/backoff.h"
 #include "src/core/lib/channel/channel_args.h"
@@ -61,7 +61,7 @@
 #include "src/cpp/client/secure_credentials.h"
 #include "src/cpp/server/secure_server_credentials.h"
 #include "src/proto/grpc/testing/echo.grpc.pb.h"
-#include "src/proto/grpc/testing/xds/orca_load_report_for_test.pb.h"
+#include "src/proto/grpc/testing/xds/v3/orca_load_report.pb.h"
 #include "test/core/util/port.h"
 #include "test/core/util/resolve_localhost_ip46.h"
 #include "test/core/util/test_config.h"
@@ -104,7 +104,7 @@ class MyTestServiceImpl : public TestServiceImpl {
  public:
   Status Echo(ServerContext* context, const EchoRequest* request,
               EchoResponse* response) override {
-    const udpa::data::orca::v1::OrcaLoadReport* load_report = nullptr;
+    const xds::data::orca::v3::OrcaLoadReport* load_report = nullptr;
     {
       grpc::internal::MutexLock lock(&mu_);
       ++request_count_;
@@ -135,7 +135,7 @@ class MyTestServiceImpl : public TestServiceImpl {
     return clients_;
   }
 
-  void set_load_report(udpa::data::orca::v1::OrcaLoadReport* load_report) {
+  void set_load_report(xds::data::orca::v3::OrcaLoadReport* load_report) {
     grpc::internal::MutexLock lock(&mu_);
     load_report_ = load_report;
   }
@@ -148,7 +148,7 @@ class MyTestServiceImpl : public TestServiceImpl {
 
   grpc::internal::Mutex mu_;
   int request_count_ = 0;
-  const udpa::data::orca::v1::OrcaLoadReport* load_report_ = nullptr;
+  const xds::data::orca::v3::OrcaLoadReport* load_report_ = nullptr;
   grpc::internal::Mutex clients_mu_;
   std::set<std::string> clients_;
 };
@@ -1771,7 +1771,7 @@ class ClientLbInterceptTrailingMetadataTest : public ClientLbEnd2endTest {
     return trailing_metadata_;
   }
 
-  const udpa::data::orca::v1::OrcaLoadReport* backend_load_report() {
+  const xds::data::orca::v3::OrcaLoadReport* backend_load_report() {
     grpc::internal::MutexLock lock(&mu_);
     return load_report_.get();
   }
@@ -1786,7 +1786,7 @@ class ClientLbInterceptTrailingMetadataTest : public ClientLbEnd2endTest {
     self->trailing_metadata_ = args_seen.metadata;
     if (backend_metric_data != nullptr) {
       self->load_report_ =
-          absl::make_unique<udpa::data::orca::v1::OrcaLoadReport>();
+          absl::make_unique<xds::data::orca::v3::OrcaLoadReport>();
       self->load_report_->set_cpu_utilization(
           backend_metric_data->cpu_utilization);
       self->load_report_->set_mem_utilization(
@@ -1807,7 +1807,7 @@ class ClientLbInterceptTrailingMetadataTest : public ClientLbEnd2endTest {
   grpc::internal::Mutex mu_;
   int trailers_intercepted_ = 0;
   grpc_core::MetadataVector trailing_metadata_;
-  std::unique_ptr<udpa::data::orca::v1::OrcaLoadReport> load_report_;
+  std::unique_ptr<xds::data::orca::v3::OrcaLoadReport> load_report_;
 };
 
 ClientLbInterceptTrailingMetadataTest*
@@ -1885,7 +1885,7 @@ TEST_F(ClientLbInterceptTrailingMetadataTest, BackendMetricData) {
   const int kNumServers = 1;
   const int kNumRpcs = 10;
   StartServers(kNumServers);
-  udpa::data::orca::v1::OrcaLoadReport load_report;
+  xds::data::orca::v3::OrcaLoadReport load_report;
   load_report.set_cpu_utilization(0.5);
   load_report.set_mem_utilization(0.75);
   load_report.set_rps(25);
diff --git a/test/cpp/end2end/counted_service.h b/test/cpp/end2end/counted_service.h
new file mode 100644 (file)
index 0000000..4d875ac
--- /dev/null
@@ -0,0 +1,64 @@
+//
+// 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.
+//
+
+#ifndef GRPC_TEST_CPP_END2END_COUNTED_SERVICE_H
+#define GRPC_TEST_CPP_END2END_COUNTED_SERVICE_H
+
+#include "src/core/lib/gprpp/sync.h"
+
+namespace grpc {
+namespace testing {
+
+// A wrapper around an RPC service implementation that provides request and
+// response counting.
+template <typename ServiceType>
+class CountedService : public ServiceType {
+ public:
+  size_t request_count() {
+    grpc_core::MutexLock lock(&mu_);
+    return request_count_;
+  }
+
+  size_t response_count() {
+    grpc_core::MutexLock lock(&mu_);
+    return response_count_;
+  }
+
+  void IncreaseResponseCount() {
+    grpc_core::MutexLock lock(&mu_);
+    ++response_count_;
+  }
+  void IncreaseRequestCount() {
+    grpc_core::MutexLock lock(&mu_);
+    ++request_count_;
+  }
+
+  void ResetCounters() {
+    grpc_core::MutexLock lock(&mu_);
+    request_count_ = 0;
+    response_count_ = 0;
+  }
+
+ private:
+  grpc_core::Mutex mu_;
+  size_t request_count_ ABSL_GUARDED_BY(mu_) = 0;
+  size_t response_count_ ABSL_GUARDED_BY(mu_) = 0;
+};
+
+}  // namespace testing
+}  // namespace grpc
+
+#endif  // GRPC_TEST_CPP_END2END_COUNTED_SERVICE_H
index c4a287e..0d37516 100644 (file)
@@ -1383,6 +1383,24 @@ TEST_P(End2endTest, ChannelStateTimeout) {
   }
 }
 
+TEST_P(End2endTest, ChannelStateOnLameChannel) {
+  if ((GetParam().credentials_type != kInsecureCredentialsType) ||
+      GetParam().inproc) {
+    return;
+  }
+  // Channel using invalid target URI.  This creates a lame channel.
+  auto channel = grpc::CreateChannel("dns:///", InsecureChannelCredentials());
+  // Channel should immediately report TRANSIENT_FAILURE.
+  EXPECT_EQ(GRPC_CHANNEL_TRANSIENT_FAILURE, channel->GetState(true));
+  // And state will never change.
+  auto state = GRPC_CHANNEL_TRANSIENT_FAILURE;
+  for (int i = 0; i < 10; ++i) {
+    channel->WaitForStateChange(
+        state, std::chrono::system_clock::now() + std::chrono::seconds(1));
+    state = channel->GetState(false);
+  }
+}
+
 // Talking to a non-existing service.
 TEST_P(End2endTest, NonExistingService) {
   ResetChannel();
@@ -1463,8 +1481,11 @@ TEST_P(End2endTest, ExpectErrorTest) {
     EXPECT_EQ(iter->error_message(), s.error_message());
     EXPECT_EQ(iter->binary_error_details(), s.error_details());
     EXPECT_TRUE(absl::StrContains(context.debug_error_string(), "created"));
+#ifndef NDEBUG
+    // GRPC_ERROR_INT_FILE_LINE is for debug only
     EXPECT_TRUE(absl::StrContains(context.debug_error_string(), "file"));
     EXPECT_TRUE(absl::StrContains(context.debug_error_string(), "line"));
+#endif
     EXPECT_TRUE(absl::StrContains(context.debug_error_string(), "status"));
     EXPECT_TRUE(absl::StrContains(context.debug_error_string(), "13"));
   }
@@ -1630,7 +1651,7 @@ TEST_P(ProxyEnd2endTest, ClientCancelsRpc) {
   Status s = stub_->Echo(&context, request, &response);
   cancel_thread.join();
   EXPECT_EQ(StatusCode::CANCELLED, s.error_code());
-  EXPECT_EQ(s.error_message(), "Cancelled");
+  EXPECT_EQ(s.error_message(), "CANCELLED");
 }
 
 // Server cancels rpc after 1ms
index 9f0dddb..11b8115 100644 (file)
@@ -1,20 +1,18 @@
-/*
- *
- * 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.
- *
- */
+//
+// 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 <deque>
 #include <memory>
 #include <grpcpp/server_builder.h>
 
 #include "src/core/ext/filters/client_channel/backup_poller.h"
+#include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h"
 #include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_balancer_addresses.h"
 #include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h"
 #include "src/core/ext/filters/client_channel/server_address.h"
-#include "src/core/ext/filters/client_channel/service_config.h"
+#include "src/core/ext/service_config/service_config.h"
 #include "src/core/lib/address_utils/parse_address.h"
 #include "src/core/lib/gpr/env.h"
 #include "src/core/lib/gprpp/ref_counted_ptr.h"
 #include "src/core/lib/iomgr/sockaddr.h"
 #include "src/core/lib/security/credentials/fake/fake_credentials.h"
-#include "src/core/lib/transport/authority_override.h"
 #include "src/cpp/client/secure_credentials.h"
 #include "src/cpp/server/secure_server_credentials.h"
 #include "src/proto/grpc/lb/v1/load_balancer.grpc.pb.h"
@@ -60,6 +58,7 @@
 #include "test/core/util/port.h"
 #include "test/core/util/resolve_localhost_ip46.h"
 #include "test/core/util/test_config.h"
+#include "test/cpp/end2end/counted_service.h"
 #include "test/cpp/end2end/test_service_impl.h"
 #include "test/cpp/util/test_config.h"
 
@@ -97,42 +96,6 @@ constexpr char kDefaultServiceConfig[] =
     "  ]\n"
     "}";
 
-template <typename ServiceType>
-class CountedService : public ServiceType {
- public:
-  size_t request_count() {
-    grpc::internal::MutexLock lock(&mu_);
-    return request_count_;
-  }
-
-  size_t response_count() {
-    grpc::internal::MutexLock lock(&mu_);
-    return response_count_;
-  }
-
-  void IncreaseResponseCount() {
-    grpc::internal::MutexLock lock(&mu_);
-    ++response_count_;
-  }
-  void IncreaseRequestCount() {
-    grpc::internal::MutexLock lock(&mu_);
-    ++request_count_;
-  }
-
-  void ResetCounters() {
-    grpc::internal::MutexLock lock(&mu_);
-    request_count_ = 0;
-    response_count_ = 0;
-  }
-
- protected:
-  grpc::internal::Mutex mu_;
-
- private:
-  size_t request_count_ = 0;
-  size_t response_count_ = 0;
-};
-
 using BackendService = CountedService<TestServiceImpl>;
 using BalancerService = CountedService<LoadBalancer::Service>;
 
@@ -174,9 +137,8 @@ class BackendServiceImpl : public BackendService {
     clients_.insert(client);
   }
 
-  grpc::internal::Mutex mu_;
   grpc::internal::Mutex clients_mu_;
-  std::set<std::string> clients_;
+  std::set<std::string> clients_ ABSL_GUARDED_BY(&clients_mu_);
 };
 
 std::string Ip4ToPackedString(const char* ip_str) {
@@ -442,7 +404,8 @@ class GrpclbEnd2endTest : public ::testing::Test {
   void ShutdownBackend(size_t index) { backends_[index]->Shutdown(); }
 
   void ResetStub(int fallback_timeout = 0,
-                 const std::string& expected_targets = "") {
+                 const std::string& expected_targets = "",
+                 int subchannel_cache_delay_ms = 0) {
     ChannelArguments args;
     if (fallback_timeout > 0) args.SetGrpclbFallbackTimeout(fallback_timeout);
     args.SetPointer(GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR,
@@ -450,6 +413,10 @@ class GrpclbEnd2endTest : public ::testing::Test {
     if (!expected_targets.empty()) {
       args.SetString(GRPC_ARG_FAKE_SECURITY_EXPECTED_TARGETS, expected_targets);
     }
+    if (subchannel_cache_delay_ms > 0) {
+      args.SetInt(GRPC_ARG_GRPCLB_SUBCHANNEL_CACHE_INTERVAL_MS,
+                  subchannel_cache_delay_ms);
+    }
     std::ostringstream uri;
     uri << "fake:///" << kApplicationTargetName_;
     // TODO(dgq): templatize tests to run everything using both secure and
@@ -546,8 +513,9 @@ class GrpclbEnd2endTest : public ::testing::Test {
       GPR_ASSERT(lb_uri.ok());
       grpc_resolved_address address;
       GPR_ASSERT(grpc_parse_uri(*lb_uri, &address));
-      grpc_arg arg = grpc_core::CreateAuthorityOverrideChannelArg(
-          addr.balancer_name.c_str());
+      grpc_arg arg = grpc_channel_arg_string_create(
+          const_cast<char*>(GRPC_ARG_DEFAULT_AUTHORITY),
+          const_cast<char*>(addr.balancer_name.c_str()));
       grpc_channel_args* args =
           grpc_channel_args_copy_and_add(nullptr, &arg, 1);
       addresses.emplace_back(address.addr, address.len, args);
@@ -781,6 +749,52 @@ TEST_F(SingleBalancerTest, Vanilla) {
   EXPECT_EQ("grpclb", channel_->GetLoadBalancingPolicyName());
 }
 
+TEST_F(SingleBalancerTest, SubchannelCaching) {
+  ResetStub(/*fallback_timeout=*/0, /*expected_targets=*/"",
+            /*subchannel_cache_delay_ms=*/1500);
+  SetNextResolutionAllBalancers();
+  // Initially send all backends.
+  ScheduleResponseForBalancer(
+      0, BuildResponseForBackends(GetBackendPorts(), {}), 0);
+  // Then remove backends 0 and 1.
+  ScheduleResponseForBalancer(
+      0, BuildResponseForBackends(GetBackendPorts(2), {}), 1000);
+  // Now re-add backend 1.
+  ScheduleResponseForBalancer(
+      0, BuildResponseForBackends(GetBackendPorts(1), {}), 1000);
+  // Wait for all backends to come online.
+  WaitForAllBackends();
+  // Send RPCs for long enough to get all responses.
+  gpr_timespec deadline = grpc_timeout_milliseconds_to_deadline(3000);
+  do {
+    CheckRpcSendOk();
+  } while (gpr_time_cmp(gpr_now(GPR_CLOCK_MONOTONIC), deadline) < 0);
+  // Backend 0 should have received less traffic than the others.
+  // Backend 1 would have received less traffic than 2 and 3.
+  gpr_log(GPR_INFO, "BACKEND 0: %" PRIuPTR " requests",
+          backends_[0]->service_.request_count());
+  EXPECT_GT(backends_[0]->service_.request_count(), 0);
+  for (size_t i = 1; i < backends_.size(); ++i) {
+    gpr_log(GPR_INFO, "BACKEND %" PRIuPTR ": %" PRIuPTR " requests", i,
+            backends_[i]->service_.request_count());
+    EXPECT_GT(backends_[i]->service_.request_count(),
+              backends_[0]->service_.request_count())
+        << "backend " << i;
+    if (i >= 2) {
+      EXPECT_GT(backends_[i]->service_.request_count(),
+                backends_[1]->service_.request_count())
+          << "backend " << i;
+    }
+  }
+  // Backend 1 should never have lost its connection from the client.
+  EXPECT_EQ(1UL, backends_[1]->service_.clients().size());
+  balancers_[0]->service_.NotifyDoneWithServerlists();
+  // The balancer got a single request.
+  EXPECT_EQ(1U, balancers_[0]->service_.request_count());
+  // And sent 3 responses.
+  EXPECT_EQ(3U, balancers_[0]->service_.response_count());
+}
+
 TEST_F(SingleBalancerTest, ReturnServerStatus) {
   SetNextResolutionAllBalancers();
   ScheduleResponseForBalancer(
diff --git a/test/cpp/end2end/rls_end2end_test.cc b/test/cpp/end2end/rls_end2end_test.cc
new file mode 100644 (file)
index 0000000..b34a7ec
--- /dev/null
@@ -0,0 +1,1458 @@
+//
+// 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.
+//
+
+// FIXME: add tests:
+// - cache eviction via cleanup timer (based on age)
+// - RLS channel is down; wait_for_ready request is sent and RLS request fails
+//   and goes into backoff; RLS channel comes back up before backoff timer
+//   fires; request is processed at that point
+
+#include <deque>
+#include <map>
+#include <thread>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "absl/strings/str_format.h"
+#include "absl/strings/str_join.h"
+#include "absl/types/optional.h"
+
+#include <grpcpp/channel.h>
+#include <grpcpp/create_channel.h>
+#include <grpcpp/security/credentials.h>
+#include <grpcpp/server.h>
+#include <grpcpp/server_builder.h>
+#include <grpcpp/support/channel_arguments.h>
+
+#include "src/core/ext/filters/client_channel/backup_poller.h"
+#include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h"
+#include "src/core/lib/address_utils/parse_address.h"
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/gpr/env.h"
+#include "src/core/lib/gprpp/host_port.h"
+#include "src/core/lib/iomgr/sockaddr.h"
+#include "src/core/lib/security/credentials/fake/fake_credentials.h"
+#include "src/core/lib/uri/uri_parser.h"
+#include "src/cpp/client/secure_credentials.h"
+#include "src/cpp/server/secure_server_credentials.h"
+#include "src/proto/grpc/lookup/v1/rls.grpc.pb.h"
+#include "src/proto/grpc/lookup/v1/rls.pb.h"
+#include "src/proto/grpc/testing/echo.grpc.pb.h"
+#include "test/core/util/port.h"
+#include "test/core/util/resolve_localhost_ip46.h"
+#include "test/core/util/test_config.h"
+#include "test/core/util/test_lb_policies.h"
+#include "test/cpp/end2end/counted_service.h"
+#include "test/cpp/end2end/test_service_impl.h"
+#include "test/cpp/util/test_config.h"
+
+using ::grpc::lookup::v1::RouteLookupRequest;
+using ::grpc::lookup::v1::RouteLookupResponse;
+
+namespace grpc {
+namespace testing {
+namespace {
+
+const char* kServerName = "test.google.fr";
+const char* kRequestMessage = "Live long and prosper.";
+
+const char* kCallCredsMdKey = "call_cred_name";
+const char* kCallCredsMdValue = "call_cred_value";
+
+const char* kTestKey = "test_key";
+const char* kTestValue = "test_value";
+const char* kHostKey = "host_key";
+const char* kServiceKey = "service_key";
+const char* kServiceValue = "grpc.testing.EchoTestService";
+const char* kMethodKey = "method_key";
+const char* kMethodValue = "Echo";
+const char* kConstantKey = "constant_key";
+const char* kConstantValue = "constant_value";
+
+using BackendService = CountedService<TestServiceImpl>;
+using RlsService =
+    CountedService<grpc::lookup::v1::RouteLookupService::Service>;
+
+class RlsServiceImpl : public RlsService {
+ public:
+  ::grpc::Status RouteLookup(::grpc::ServerContext* context,
+                             const RouteLookupRequest* request,
+                             RouteLookupResponse* response) override {
+    gpr_log(GPR_INFO, "RLS: Received request: %s",
+            request->DebugString().c_str());
+    // RLS server should see call creds.
+    EXPECT_THAT(context->client_metadata(),
+                ::testing::Contains(
+                    ::testing::Pair(kCallCredsMdKey, kCallCredsMdValue)));
+    IncreaseRequestCount();
+    EXPECT_EQ(request->target_type(), "grpc");
+    // See if we have a configured response for this request.
+    ResponseData res;
+    {
+      grpc::internal::MutexLock lock(&mu_);
+      auto it = responses_.find(*request);
+      if (it == responses_.end()) {
+        gpr_log(GPR_INFO, "RLS: no matching request, returning INTERNAL");
+        unmatched_requests_.push_back(*request);
+        return Status(StatusCode::INTERNAL, "no response entry");
+      }
+      res = it->second;
+    }
+    // Configured response found, so use it.
+    if (res.response_delay > 0) {
+      gpr_sleep_until(
+          grpc_timeout_milliseconds_to_deadline(res.response_delay));
+    }
+    IncreaseResponseCount();
+    *response = res.response;
+    gpr_log(GPR_INFO, "RLS: returning configured response: %s",
+            response->DebugString().c_str());
+    return Status::OK;
+  }
+
+  void Start() {}
+
+  void Shutdown() {}
+
+  void SetResponse(RouteLookupRequest request, RouteLookupResponse response,
+                   grpc_millis response_delay = 0) {
+    grpc::internal::MutexLock lock(&mu_);
+    responses_[std::move(request)] = {std::move(response), response_delay};
+  }
+
+  void RemoveResponse(const RouteLookupRequest& request) {
+    grpc::internal::MutexLock lock(&mu_);
+    responses_.erase(request);
+  }
+
+  std::vector<RouteLookupRequest> GetUnmatchedRequests() {
+    grpc::internal::MutexLock lock(&mu_);
+    return std::move(unmatched_requests_);
+  }
+
+ private:
+  // Sorting thunk for RouteLookupRequest.
+  struct RlsRequestLessThan {
+    bool operator()(const RouteLookupRequest& req1,
+                    const RouteLookupRequest& req2) const {
+      std::map<absl::string_view, absl::string_view> key_map1(
+          req1.key_map().begin(), req1.key_map().end());
+      std::map<absl::string_view, absl::string_view> key_map2(
+          req2.key_map().begin(), req2.key_map().end());
+      if (key_map1 < key_map2) return true;
+      if (req1.reason() < req2.reason()) return true;
+      if (req1.stale_header_data() < req2.stale_header_data()) return true;
+      return false;
+    }
+  };
+
+  struct ResponseData {
+    RouteLookupResponse response;
+    grpc_millis response_delay;
+  };
+
+  grpc::internal::Mutex mu_;
+  std::map<RouteLookupRequest, ResponseData, RlsRequestLessThan> responses_
+      ABSL_GUARDED_BY(&mu_);
+  std::vector<RouteLookupRequest> unmatched_requests_ ABSL_GUARDED_BY(&mu_);
+};
+
+// Subclass of TestServiceImpl that increments a request counter for
+// every call to the Echo Rpc.
+class MyTestServiceImpl : public BackendService {
+ public:
+  Status Echo(ServerContext* context, const EchoRequest* request,
+              EchoResponse* response) override {
+    // Backend should see call creds.
+    EXPECT_THAT(context->client_metadata(),
+                ::testing::Contains(
+                    ::testing::Pair(kCallCredsMdKey, kCallCredsMdValue)));
+    IncreaseRequestCount();
+    auto client_metadata = context->client_metadata();
+    auto range = client_metadata.equal_range("X-Google-RLS-Data");
+    {
+      grpc::internal::MutexLock lock(&mu_);
+      for (auto it = range.first; it != range.second; ++it) {
+        rls_header_data_.insert(
+            std::string(it->second.begin(), it->second.length()));
+      }
+    }
+    IncreaseResponseCount();
+    return TestServiceImpl::Echo(context, request, response);
+  }
+
+  std::set<std::string> rls_data() {
+    grpc::internal::MutexLock lock(&mu_);
+    return std::move(rls_header_data_);
+  }
+
+  void Start() {}
+
+  void Shutdown() {}
+
+ private:
+  grpc::internal::Mutex mu_;
+  std::set<std::string> rls_header_data_ ABSL_GUARDED_BY(&mu_);
+};
+
+class FakeResolverResponseGeneratorWrapper {
+ public:
+  FakeResolverResponseGeneratorWrapper()
+      : response_generator_(grpc_core::MakeRefCounted<
+                            grpc_core::FakeResolverResponseGenerator>()) {}
+
+  void SetNextResolution(absl::string_view service_config_json) {
+    grpc_core::ExecCtx exec_ctx;
+    response_generator_->SetResponse(BuildFakeResults(service_config_json));
+  }
+
+  grpc_core::FakeResolverResponseGenerator* Get() const {
+    return response_generator_.get();
+  }
+
+ private:
+  static grpc_core::Resolver::Result BuildFakeResults(
+      absl::string_view service_config_json) {
+    grpc_core::Resolver::Result result;
+    result.service_config_error = GRPC_ERROR_NONE;
+    result.service_config = grpc_core::ServiceConfig::Create(
+        result.args, service_config_json, &result.service_config_error);
+    EXPECT_EQ(result.service_config_error, GRPC_ERROR_NONE)
+        << "JSON: " << service_config_json
+        << "Error: " << grpc_error_std_string(result.service_config_error);
+    EXPECT_NE(result.service_config, nullptr);
+    return result;
+  }
+
+  grpc_core::RefCountedPtr<grpc_core::FakeResolverResponseGenerator>
+      response_generator_;
+};
+
+class RlsEnd2endTest : public ::testing::Test {
+ protected:
+  static void SetUpTestSuite() {
+    gpr_setenv("GRPC_EXPERIMENTAL_ENABLE_RLS_LB_POLICY", "true");
+    GPR_GLOBAL_CONFIG_SET(grpc_client_channel_backup_poll_interval_ms, 1);
+    grpc_init();
+    grpc_core::RegisterFixedAddressLoadBalancingPolicy();
+  }
+
+  static void TearDownTestSuite() {
+    grpc_shutdown_blocking();
+    gpr_unsetenv("GRPC_EXPERIMENTAL_ENABLE_RLS_LB_POLICY");
+  }
+
+  void SetUp() override {
+    bool localhost_resolves_to_ipv4 = false;
+    bool localhost_resolves_to_ipv6 = false;
+    grpc_core::LocalhostResolves(&localhost_resolves_to_ipv4,
+                                 &localhost_resolves_to_ipv6);
+    ipv6_only_ = !localhost_resolves_to_ipv4 && localhost_resolves_to_ipv6;
+    rls_server_ = absl::make_unique<ServerThread<RlsServiceImpl>>("rls");
+    rls_server_->Start();
+    resolver_response_generator_ =
+        absl::make_unique<FakeResolverResponseGeneratorWrapper>();
+    ResetStub();
+  }
+
+  void TearDown() override {
+    ShutdownBackends();
+    rls_server_->Shutdown();
+  }
+
+  void ResetStub(const char* expected_authority = kServerName) {
+    ChannelArguments args;
+    args.SetPointer(GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR,
+                    resolver_response_generator_->Get());
+    args.SetString(GRPC_ARG_FAKE_SECURITY_EXPECTED_TARGETS, expected_authority);
+    grpc_channel_credentials* channel_creds =
+        grpc_fake_transport_security_credentials_create();
+    grpc_call_credentials* call_creds = grpc_md_only_test_credentials_create(
+        kCallCredsMdKey, kCallCredsMdValue, false);
+    auto creds = std::make_shared<SecureChannelCredentials>(
+        grpc_composite_channel_credentials_create(channel_creds, call_creds,
+                                                  nullptr));
+    call_creds->Unref();
+    channel_creds->Unref();
+    channel_ = ::grpc::CreateCustomChannel(
+        absl::StrCat("fake:///", kServerName).c_str(), std::move(creds), args);
+    stub_ = grpc::testing::EchoTestService::NewStub(channel_);
+  }
+
+  void ShutdownBackends() {
+    for (auto& server : backends_) {
+      server->Shutdown();
+    }
+  }
+
+  void StartBackends(size_t num_servers) {
+    backends_.clear();
+    for (size_t i = 0; i < num_servers; ++i) {
+      backends_.push_back(
+          absl::make_unique<ServerThread<MyTestServiceImpl>>("backend"));
+      backends_.back()->Start();
+    }
+  }
+
+  std::string TargetStringForPort(int port) {
+    if (ipv6_only_) return absl::StrCat("ipv6:[::1]:", port);
+    return absl::StrCat("ipv4:127.0.0.1:", port);
+  }
+
+  static RouteLookupRequest BuildRlsRequest(
+      std::map<std::string, std::string> key,
+      RouteLookupRequest::Reason reason = RouteLookupRequest::REASON_MISS,
+      const char* stale_header_data = "") {
+    RouteLookupRequest request;
+    request.set_target_type("grpc");
+    request.mutable_key_map()->insert(key.begin(), key.end());
+    request.set_reason(reason);
+    request.set_stale_header_data(stale_header_data);
+    return request;
+  }
+
+  static RouteLookupResponse BuildRlsResponse(std::vector<std::string> targets,
+                                              const char* header_data = "") {
+    RouteLookupResponse response;
+    response.mutable_targets()->Add(targets.begin(), targets.end());
+    response.set_header_data(header_data);
+    return response;
+  }
+
+  struct RpcOptions {
+    int timeout_ms = 1000;
+    bool wait_for_ready = false;
+    std::vector<std::pair<std::string, std::string>> metadata;
+
+    RpcOptions() {}
+
+    RpcOptions& set_timeout_ms(int rpc_timeout_ms) {
+      timeout_ms = rpc_timeout_ms;
+      return *this;
+    }
+
+    RpcOptions& set_wait_for_ready(bool rpc_wait_for_ready) {
+      wait_for_ready = rpc_wait_for_ready;
+      return *this;
+    }
+
+    RpcOptions& set_metadata(
+        std::vector<std::pair<std::string, std::string>> rpc_metadata) {
+      metadata = std::move(rpc_metadata);
+      return *this;
+    }
+
+    // Populates context.
+    void SetupRpc(ClientContext* context) const {
+      for (const auto& item : metadata) {
+        context->AddMetadata(item.first, item.second);
+      }
+      if (timeout_ms != 0) {
+        context->set_deadline(
+            grpc_timeout_milliseconds_to_deadline(timeout_ms));
+      }
+      if (wait_for_ready) context->set_wait_for_ready(true);
+    }
+  };
+
+  Status SendRpc(const RpcOptions& rpc_options = RpcOptions(),
+                 EchoResponse* response = nullptr) {
+    EchoResponse local_response;
+    if (response == nullptr) response = &local_response;
+    ClientContext context;
+    rpc_options.SetupRpc(&context);
+    EchoRequest request;
+    request.set_message(kRequestMessage);
+    return stub_->Echo(&context, request, response);
+  }
+
+  void CheckRpcSendOk(const grpc_core::DebugLocation& location,
+                      const RpcOptions& rpc_options = RpcOptions()) {
+    EchoResponse response;
+    Status status = SendRpc(rpc_options, &response);
+    ASSERT_TRUE(status.ok()) << location.file() << ":" << location.line()
+                             << ": RPC failed: " << status.error_code() << ": "
+                             << status.error_message();
+    EXPECT_EQ(response.message(), kRequestMessage)
+        << location.file() << ":" << location.line();
+  }
+
+  void CheckRpcSendFailure(const grpc_core::DebugLocation& location,
+                           const RpcOptions& rpc_options = RpcOptions()) {
+    Status status = SendRpc(rpc_options);
+    ASSERT_FALSE(status.ok()) << location.file() << ":" << location.line();
+  }
+
+  class ServiceConfigBuilder {
+   public:
+    explicit ServiceConfigBuilder(int rls_server_port)
+        : rls_server_port_(rls_server_port) {}
+
+    ServiceConfigBuilder& set_lookup_service_timeout(grpc_millis timeout) {
+      lookup_service_timeout_ = timeout * grpc_test_slowdown_factor();
+      return *this;
+    }
+
+    ServiceConfigBuilder& set_default_target(std::string default_target) {
+      default_target_ = std::move(default_target);
+      return *this;
+    }
+
+    ServiceConfigBuilder& set_max_age(grpc_millis max_age) {
+      max_age_ = max_age * grpc_test_slowdown_factor();
+      return *this;
+    }
+
+    ServiceConfigBuilder& set_stale_age(grpc_millis stale_age) {
+      stale_age_ = stale_age * grpc_test_slowdown_factor();
+      return *this;
+    }
+
+    ServiceConfigBuilder& set_cache_size_bytes(int64_t size) {
+      cache_size_bytes_ = size;
+      return *this;
+    }
+
+    ServiceConfigBuilder& AddKeyBuilder(absl::string_view key_builder) {
+      key_builders_.push_back(absl::StrCat("{", key_builder, "}"));
+      return *this;
+    }
+
+    std::string Build() {
+      // First build parts of routeLookupConfig.
+      std::vector<std::string> route_lookup_config_parts;
+      route_lookup_config_parts.push_back(absl::StrFormat(
+          "        \"lookupService\":\"localhost:%d\"", rls_server_port_));
+      if (lookup_service_timeout_ > 0) {
+        route_lookup_config_parts.push_back(absl::StrFormat(
+            "        \"lookupServiceTimeout\":\"%d.%09ds\"",
+            lookup_service_timeout_ / 1000, lookup_service_timeout_ % 1000));
+      }
+      if (!default_target_.empty()) {
+        route_lookup_config_parts.push_back(absl::StrFormat(
+            "        \"defaultTarget\":\"%s\"", default_target_));
+      }
+      route_lookup_config_parts.push_back(absl::StrFormat(
+          "        \"cacheSizeBytes\":%" PRId64, cache_size_bytes_));
+      if (max_age_ > 0) {
+        route_lookup_config_parts.push_back(
+            absl::StrFormat("        \"maxAge\":\"%d.%09ds\"", max_age_ / 1000,
+                            max_age_ % 1000));
+      }
+      if (stale_age_ > 0) {
+        route_lookup_config_parts.push_back(
+            absl::StrFormat("        \"staleAge\":\"%d.%09ds\"",
+                            stale_age_ / 1000, stale_age_ % 1000));
+      }
+      if (!key_builders_.empty()) {
+        route_lookup_config_parts.push_back(
+            absl::StrFormat("        \"grpcKeybuilders\":[%s]",
+                            absl::StrJoin(key_builders_, ",")));
+      }
+      // Now build parts of RLS LB policy config.
+      std::vector<std::string> rls_config_parts;
+      if (!route_lookup_config_parts.empty()) {
+        rls_config_parts.push_back(absl::StrCat(
+            "      \"routeLookupConfig\":{",
+            absl::StrJoin(route_lookup_config_parts, ","), "      }"));
+      }
+      rls_config_parts.push_back(
+          "      \"childPolicy\":[{"
+          "        \"fixed_address_lb\":{}\n"
+          "      }],\n"
+          "      \"childPolicyConfigTargetFieldName\":\"address\"\n");
+      // Put it all together.
+      return absl::StrCat(
+          "{"
+          "  \"loadBalancingConfig\":[{"
+          "    \"rls\":{",
+          absl::StrJoin(rls_config_parts, ","),
+          "    }"
+          "  }]"
+          "}");
+    }
+
+   private:
+    int rls_server_port_;
+    grpc_millis lookup_service_timeout_ = 0;
+    std::string default_target_;
+    grpc_millis max_age_ = 0;
+    grpc_millis stale_age_ = 0;
+    int64_t cache_size_bytes_ = 10485760;
+    std::vector<std::string> key_builders_;
+  };
+
+  ServiceConfigBuilder MakeServiceConfigBuilder() {
+    return ServiceConfigBuilder(rls_server_->port_);
+  }
+
+  void SetNextResolution(absl::string_view service_config_json) {
+    resolver_response_generator_->SetNextResolution(service_config_json);
+  }
+
+  template <typename T>
+  struct ServerThread {
+    template <typename... Args>
+    explicit ServerThread(const grpc::string& type, Args&&... args)
+        : port_(grpc_pick_unused_port_or_die()),
+          type_(type),
+          service_(std::forward<Args>(args)...) {}
+
+    void Start() {
+      gpr_log(GPR_INFO, "starting %s server on port %d", type_.c_str(), port_);
+      GPR_ASSERT(!running_);
+      running_ = true;
+      service_.Start();
+      grpc::internal::Mutex mu;
+      // We need to acquire the lock here in order to prevent the notify_one
+      // by ServerThread::Serve from firing before the wait below is hit.
+      grpc::internal::MutexLock lock(&mu);
+      grpc::internal::CondVar cond;
+      thread_ = absl::make_unique<std::thread>(
+          std::bind(&ServerThread::Serve, this, &mu, &cond));
+      cond.Wait(&mu);
+      gpr_log(GPR_INFO, "%s server startup complete", type_.c_str());
+    }
+
+    void Serve(grpc::internal::Mutex* mu, grpc::internal::CondVar* cond) {
+      // We need to acquire the lock here in order to prevent the notify_one
+      // below from firing before its corresponding wait is executed.
+      grpc::internal::MutexLock lock(mu);
+      ServerBuilder builder;
+      auto creds = std::make_shared<SecureServerCredentials>(
+          grpc_fake_transport_security_server_credentials_create());
+      builder.AddListeningPort(absl::StrCat("localhost:", port_),
+                               std::move(creds));
+      builder.RegisterService(&service_);
+      server_ = builder.BuildAndStart();
+      cond->Signal();
+    }
+
+    void Shutdown() {
+      if (!running_) return;
+      gpr_log(GPR_INFO, "%s about to shutdown", type_.c_str());
+      service_.Shutdown();
+      server_->Shutdown(grpc_timeout_milliseconds_to_deadline(0));
+      thread_->join();
+      gpr_log(GPR_INFO, "%s shutdown completed", type_.c_str());
+      running_ = false;
+    }
+
+    const int port_;
+    grpc::string type_;
+    T service_;
+    std::unique_ptr<Server> server_;
+    std::unique_ptr<std::thread> thread_;
+    bool running_ = false;
+  };
+
+  bool ipv6_only_;
+  std::vector<std::unique_ptr<ServerThread<MyTestServiceImpl>>> backends_;
+  std::unique_ptr<ServerThread<RlsServiceImpl>> rls_server_;
+  std::unique_ptr<FakeResolverResponseGeneratorWrapper>
+      resolver_response_generator_;
+  std::shared_ptr<grpc::Channel> channel_;
+  std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_;
+};
+
+TEST_F(RlsEnd2endTest, Basic) {
+  StartBackends(1);
+  SetNextResolution(
+      MakeServiceConfigBuilder()
+          .AddKeyBuilder(absl::StrFormat("\"names\":[{"
+                                         "  \"service\":\"%s\","
+                                         "  \"method\":\"%s\""
+                                         "}],"
+                                         "\"headers\":["
+                                         "  {"
+                                         "    \"key\":\"%s\","
+                                         "    \"names\":["
+                                         "      \"key1\""
+                                         "    ]"
+                                         "  }"
+                                         "]",
+                                         kServiceValue, kMethodValue, kTestKey))
+          .Build());
+  rls_server_->service_.SetResponse(
+      BuildRlsRequest({{kTestKey, kTestValue}}),
+      BuildRlsResponse({TargetStringForPort(backends_[0]->port_)}));
+  CheckRpcSendOk(DEBUG_LOCATION,
+                 RpcOptions().set_metadata({{"key1", kTestValue}}));
+  EXPECT_EQ(rls_server_->service_.request_count(), 1);
+  EXPECT_EQ(rls_server_->service_.response_count(), 1);
+  EXPECT_EQ(backends_[0]->service_.request_count(), 1);
+  // No RLS header seen by the backend, since the RLS response didn't set any.
+  EXPECT_THAT(backends_[0]->service_.rls_data(), ::testing::ElementsAre());
+}
+
+TEST_F(RlsEnd2endTest, DuplicateHeadersAreMerged) {
+  const char* kTestValue2 = "test_value_2";
+  StartBackends(1);
+  SetNextResolution(
+      MakeServiceConfigBuilder()
+          .AddKeyBuilder(absl::StrFormat("\"names\":[{"
+                                         "  \"service\":\"%s\","
+                                         "  \"method\":\"%s\""
+                                         "}],"
+                                         "\"headers\":["
+                                         "  {"
+                                         "    \"key\":\"%s\","
+                                         "    \"names\":["
+                                         "      \"key1\""
+                                         "    ]"
+                                         "  }"
+                                         "]",
+                                         kServiceValue, kMethodValue, kTestKey))
+          .Build());
+  rls_server_->service_.SetResponse(
+      BuildRlsRequest({{kTestKey, absl::StrCat(kTestValue, ",", kTestValue2)}}),
+      BuildRlsResponse({TargetStringForPort(backends_[0]->port_)}));
+  // Same header present twice in the request.  Values should be merged.
+  CheckRpcSendOk(
+      DEBUG_LOCATION,
+      RpcOptions().set_metadata({{"key1", kTestValue}, {"key1", kTestValue2}}));
+  EXPECT_EQ(rls_server_->service_.request_count(), 1);
+  EXPECT_EQ(rls_server_->service_.response_count(), 1);
+  EXPECT_EQ(backends_[0]->service_.request_count(), 1);
+}
+
+TEST_F(RlsEnd2endTest, SecondHeaderUsed) {
+  StartBackends(1);
+  SetNextResolution(
+      MakeServiceConfigBuilder()
+          .AddKeyBuilder(absl::StrFormat("\"names\":[{"
+                                         "  \"service\":\"%s\","
+                                         "  \"method\":\"%s\""
+                                         "}],"
+                                         "\"headers\":["
+                                         "  {"
+                                         "    \"key\":\"%s\","
+                                         "    \"names\":["
+                                         "      \"key1\", \"key2\""
+                                         "    ]"
+                                         "  }"
+                                         "]",
+                                         kServiceValue, kMethodValue, kTestKey))
+          .Build());
+  rls_server_->service_.SetResponse(
+      BuildRlsRequest({{kTestKey, kTestValue}}),
+      BuildRlsResponse({TargetStringForPort(backends_[0]->port_)}));
+  CheckRpcSendOk(DEBUG_LOCATION,
+                 RpcOptions().set_metadata({{"key2", kTestValue}}));
+  EXPECT_EQ(rls_server_->service_.request_count(), 1);
+  EXPECT_EQ(rls_server_->service_.response_count(), 1);
+  EXPECT_EQ(backends_[0]->service_.request_count(), 1);
+}
+
+TEST_F(RlsEnd2endTest, MultipleHeaderKeys) {
+  const char* kTestKey2 = "test_key_2";
+  const char* kTestValue2 = "test_value_2";
+  StartBackends(1);
+  SetNextResolution(MakeServiceConfigBuilder()
+                        .AddKeyBuilder(absl::StrFormat(
+                            "\"names\":[{"
+                            "  \"service\":\"%s\","
+                            "  \"method\":\"%s\""
+                            "}],"
+                            "\"headers\":["
+                            "  {"
+                            "    \"key\":\"%s\","
+                            "    \"names\":["
+                            "      \"key1\""
+                            "    ]"
+                            "  },"
+                            "  {"
+                            "    \"key\":\"%s\","
+                            "    \"names\":["
+                            "      \"key2\""
+                            "    ]"
+                            "  }"
+                            "]",
+                            kServiceValue, kMethodValue, kTestKey, kTestKey2))
+                        .Build());
+  rls_server_->service_.SetResponse(
+      BuildRlsRequest({
+          {kTestKey, kTestValue},
+          {kTestKey2, kTestValue2},
+      }),
+      BuildRlsResponse({TargetStringForPort(backends_[0]->port_)}));
+  CheckRpcSendOk(
+      DEBUG_LOCATION,
+      RpcOptions().set_metadata({{"key1", kTestValue}, {"key2", kTestValue2}}));
+  EXPECT_EQ(rls_server_->service_.request_count(), 1);
+  EXPECT_EQ(rls_server_->service_.response_count(), 1);
+  EXPECT_EQ(backends_[0]->service_.request_count(), 1);
+  // No RLS header seen by the backend, since the RLS response didn't set any.
+  EXPECT_THAT(backends_[0]->service_.rls_data(), ::testing::ElementsAre());
+}
+
+TEST_F(RlsEnd2endTest, NoHeaderMatch) {
+  StartBackends(1);
+  SetNextResolution(
+      MakeServiceConfigBuilder()
+          .AddKeyBuilder(absl::StrFormat("\"names\":[{"
+                                         "  \"service\":\"%s\","
+                                         "  \"method\":\"%s\""
+                                         "}],"
+                                         "\"headers\":["
+                                         "  {"
+                                         "    \"key\":\"%s\","
+                                         "    \"names\":["
+                                         "      \"key1\""
+                                         "    ]"
+                                         "  }"
+                                         "]",
+                                         kServiceValue, kMethodValue, kTestKey))
+          .Build());
+  rls_server_->service_.SetResponse(
+      BuildRlsRequest({}),
+      BuildRlsResponse({TargetStringForPort(backends_[0]->port_)}));
+  // Request does not have header "key1", so kTestKey will not be added.
+  CheckRpcSendOk(DEBUG_LOCATION);
+  EXPECT_EQ(rls_server_->service_.request_count(), 1);
+  EXPECT_EQ(rls_server_->service_.response_count(), 1);
+  EXPECT_EQ(backends_[0]->service_.request_count(), 1);
+}
+
+TEST_F(RlsEnd2endTest, WildcardMethod) {
+  StartBackends(1);
+  SetNextResolution(MakeServiceConfigBuilder()
+                        .AddKeyBuilder(absl::StrFormat("\"names\":[{"
+                                                       "  \"service\":\"%s\""
+                                                       "}],"
+                                                       "\"headers\":["
+                                                       "  {"
+                                                       "    \"key\":\"%s\","
+                                                       "    \"names\":["
+                                                       "      \"key1\""
+                                                       "    ]"
+                                                       "  }"
+                                                       "]",
+                                                       kServiceValue, kTestKey))
+                        .Build());
+  rls_server_->service_.SetResponse(
+      BuildRlsRequest({{kTestKey, kTestValue}}),
+      BuildRlsResponse({TargetStringForPort(backends_[0]->port_)}));
+  CheckRpcSendOk(DEBUG_LOCATION,
+                 RpcOptions().set_metadata({{"key1", kTestValue}}));
+  EXPECT_EQ(rls_server_->service_.request_count(), 1);
+  EXPECT_EQ(rls_server_->service_.response_count(), 1);
+  EXPECT_EQ(backends_[0]->service_.request_count(), 1);
+}
+
+TEST_F(RlsEnd2endTest, NoKeyBuilderForMethod) {
+  StartBackends(1);
+  SetNextResolution(
+      MakeServiceConfigBuilder()
+          .AddKeyBuilder(absl::StrFormat("\"names\":[{"
+                                         "  \"service\":\"%s\","
+                                         "  \"method\":\"some_other_method\""
+                                         "}],"
+                                         "\"headers\":["
+                                         "  {"
+                                         "    \"key\":\"%s\","
+                                         "    \"names\":["
+                                         "      \"key1\""
+                                         "    ]"
+                                         "  }"
+                                         "]",
+                                         kServiceValue, kTestKey))
+          .Build());
+  rls_server_->service_.SetResponse(
+      BuildRlsRequest({}),
+      BuildRlsResponse({TargetStringForPort(backends_[0]->port_)}));
+  CheckRpcSendOk(DEBUG_LOCATION);
+  EXPECT_EQ(rls_server_->service_.request_count(), 1);
+  EXPECT_EQ(rls_server_->service_.response_count(), 1);
+  EXPECT_EQ(backends_[0]->service_.request_count(), 1);
+}
+
+TEST_F(RlsEnd2endTest, HeaderData) {
+  const char* kHeaderData = "header_data";
+  StartBackends(1);
+  SetNextResolution(
+      MakeServiceConfigBuilder()
+          .AddKeyBuilder(absl::StrFormat("\"names\":[{"
+                                         "  \"service\":\"%s\","
+                                         "  \"method\":\"%s\""
+                                         "}],"
+                                         "\"headers\":["
+                                         "  {"
+                                         "    \"key\":\"%s\","
+                                         "    \"names\":["
+                                         "      \"key1\""
+                                         "    ]"
+                                         "  }"
+                                         "]",
+                                         kServiceValue, kMethodValue, kTestKey))
+          .Build());
+  rls_server_->service_.SetResponse(
+      BuildRlsRequest({{kTestKey, kTestValue}}),
+      BuildRlsResponse({TargetStringForPort(backends_[0]->port_)},
+                       kHeaderData));
+  CheckRpcSendOk(DEBUG_LOCATION,
+                 RpcOptions().set_metadata({{"key1", kTestValue}}));
+  EXPECT_EQ(rls_server_->service_.request_count(), 1);
+  EXPECT_EQ(rls_server_->service_.response_count(), 1);
+  EXPECT_EQ(backends_[0]->service_.request_count(), 1);
+  EXPECT_THAT(backends_[0]->service_.rls_data(),
+              ::testing::ElementsAre(kHeaderData));
+}
+
+TEST_F(RlsEnd2endTest, ExtraKeysAndConstantKeys) {
+  StartBackends(1);
+  SetNextResolution(
+      MakeServiceConfigBuilder()
+          .AddKeyBuilder(absl::StrFormat("\"names\":[{"
+                                         "  \"service\":\"%s\","
+                                         "  \"method\":\"%s\""
+                                         "}],"
+                                         "\"headers\":["
+                                         "  {"
+                                         "    \"key\":\"%s\","
+                                         "    \"names\":["
+                                         "      \"key1\",\"key2\",\"key3\""
+                                         "    ]"
+                                         "  }"
+                                         "],"
+                                         "\"extraKeys\":{"
+                                         "  \"host\":\"%s\","
+                                         "  \"service\":\"%s\","
+                                         "  \"method\":\"%s\""
+                                         "},"
+                                         "\"constantKeys\":{"
+                                         "  \"%s\":\"%s\""
+                                         "}",
+                                         kServiceValue, kMethodValue, kTestKey,
+                                         kHostKey, kServiceKey, kMethodKey,
+                                         kConstantKey, kConstantValue))
+          .Build());
+  rls_server_->service_.SetResponse(
+      BuildRlsRequest({
+          {kTestKey, kTestValue},
+          {kHostKey, kServerName},
+          {kServiceKey, kServiceValue},
+          {kMethodKey, kMethodValue},
+          {kConstantKey, kConstantValue},
+      }),
+      BuildRlsResponse({TargetStringForPort(backends_[0]->port_)}));
+  CheckRpcSendOk(DEBUG_LOCATION,
+                 RpcOptions().set_metadata({{"key1", kTestValue}}));
+  EXPECT_EQ(rls_server_->service_.request_count(), 1);
+  EXPECT_EQ(rls_server_->service_.response_count(), 1);
+  EXPECT_EQ(backends_[0]->service_.request_count(), 1);
+}
+
+TEST_F(RlsEnd2endTest, TwoCacheEntriesWithSameTarget) {
+  const char* kTestValue2 = "test_value2";
+  StartBackends(1);
+  SetNextResolution(
+      MakeServiceConfigBuilder()
+          .AddKeyBuilder(absl::StrFormat("\"names\":[{"
+                                         "  \"service\":\"%s\","
+                                         "  \"method\":\"%s\""
+                                         "}],"
+                                         "\"headers\":["
+                                         "  {"
+                                         "    \"key\":\"%s\","
+                                         "    \"names\":["
+                                         "      \"key1\""
+                                         "    ]"
+                                         "  }"
+                                         "]",
+                                         kServiceValue, kMethodValue, kTestKey))
+          .Build());
+  rls_server_->service_.SetResponse(
+      BuildRlsRequest({{kTestKey, kTestValue}}),
+      BuildRlsResponse({TargetStringForPort(backends_[0]->port_)}));
+  rls_server_->service_.SetResponse(
+      BuildRlsRequest({{kTestKey, kTestValue2}}),
+      BuildRlsResponse({TargetStringForPort(backends_[0]->port_)}));
+  CheckRpcSendOk(DEBUG_LOCATION,
+                 RpcOptions().set_metadata({{"key1", kTestValue}}));
+  EXPECT_EQ(rls_server_->service_.request_count(), 1);
+  EXPECT_EQ(rls_server_->service_.response_count(), 1);
+  EXPECT_EQ(backends_[0]->service_.request_count(), 1);
+  CheckRpcSendOk(DEBUG_LOCATION,
+                 RpcOptions().set_metadata({{"key1", kTestValue2}}));
+  EXPECT_EQ(rls_server_->service_.request_count(), 2);
+  EXPECT_EQ(rls_server_->service_.response_count(), 2);
+  EXPECT_EQ(backends_[0]->service_.request_count(), 2);
+}
+
+TEST_F(RlsEnd2endTest, FailedRlsRequestWithoutDefaultTarget) {
+  StartBackends(1);
+  SetNextResolution(
+      MakeServiceConfigBuilder()
+          .AddKeyBuilder(absl::StrFormat("\"names\":[{"
+                                         "  \"service\":\"%s\","
+                                         "  \"method\":\"%s\""
+                                         "}],"
+                                         "\"headers\":["
+                                         "  {"
+                                         "    \"key\":\"%s\","
+                                         "    \"names\":["
+                                         "      \"key1\""
+                                         "    ]"
+                                         "  }"
+                                         "]",
+                                         kServiceValue, kMethodValue, kTestKey))
+          .Build());
+  // Send an RPC before we give the RLS server a response.
+  // The RLS request will fail, and thus so will the data plane RPC.
+  CheckRpcSendFailure(DEBUG_LOCATION,
+                      RpcOptions().set_metadata({{"key1", kTestValue}}));
+  EXPECT_THAT(
+      rls_server_->service_.GetUnmatchedRequests(),
+      ::testing::ElementsAre(
+          // TODO(roth): Change this to use ::testing::ProtoEquals()
+          // once that becomes available in OSS.
+          ::testing::Property(
+              &RouteLookupRequest::DebugString,
+              BuildRlsRequest({{kTestKey, kTestValue}}).DebugString())));
+  // Now give the RLS server the right response.
+  rls_server_->service_.SetResponse(
+      BuildRlsRequest({{kTestKey, kTestValue}}),
+      BuildRlsResponse({TargetStringForPort(backends_[0]->port_)}));
+  // Sleep long enough for backoff to elapse, then try another RPC.
+  gpr_sleep_until(grpc_timeout_seconds_to_deadline(3));
+  CheckRpcSendOk(DEBUG_LOCATION,
+                 RpcOptions().set_metadata({{"key1", kTestValue}}));
+  EXPECT_EQ(rls_server_->service_.request_count(), 2);
+  EXPECT_EQ(rls_server_->service_.response_count(), 1);
+  EXPECT_EQ(backends_[0]->service_.request_count(), 1);
+}
+
+TEST_F(RlsEnd2endTest, FailedRlsRequestWithDefaultTarget) {
+  StartBackends(1);
+  SetNextResolution(
+      MakeServiceConfigBuilder()
+          .AddKeyBuilder(absl::StrFormat("\"names\":[{"
+                                         "  \"service\":\"%s\","
+                                         "  \"method\":\"%s\""
+                                         "}],"
+                                         "\"headers\":["
+                                         "  {"
+                                         "    \"key\":\"%s\","
+                                         "    \"names\":["
+                                         "      \"key1\""
+                                         "    ]"
+                                         "  }"
+                                         "]",
+                                         kServiceValue, kMethodValue, kTestKey))
+          .set_default_target(TargetStringForPort(backends_[0]->port_))
+          .Build());
+  // Don't give the RLS server a response, so the RLS request will fail.
+  // The data plane RPC should be sent to the default target.
+  CheckRpcSendOk(DEBUG_LOCATION,
+                 RpcOptions().set_metadata({{"key1", kTestValue}}));
+  EXPECT_THAT(
+      rls_server_->service_.GetUnmatchedRequests(),
+      ::testing::ElementsAre(
+          // TODO(roth): Change this to use ::testing::ProtoEquals()
+          // once that becomes available in OSS.
+          ::testing::Property(
+              &RouteLookupRequest::DebugString,
+              BuildRlsRequest({{kTestKey, kTestValue}}).DebugString())));
+  EXPECT_EQ(rls_server_->service_.request_count(), 1);
+  EXPECT_EQ(rls_server_->service_.response_count(), 0);
+  EXPECT_EQ(backends_[0]->service_.request_count(), 1);
+}
+
+TEST_F(RlsEnd2endTest, RlsRequestTimeout) {
+  StartBackends(2);
+  SetNextResolution(
+      MakeServiceConfigBuilder()
+          .AddKeyBuilder(absl::StrFormat("\"names\":[{"
+                                         "  \"service\":\"%s\","
+                                         "  \"method\":\"%s\""
+                                         "}],"
+                                         "\"headers\":["
+                                         "  {"
+                                         "    \"key\":\"%s\","
+                                         "    \"names\":["
+                                         "      \"key1\""
+                                         "    ]"
+                                         "  }"
+                                         "]",
+                                         kServiceValue, kMethodValue, kTestKey))
+          .set_default_target(TargetStringForPort(backends_[1]->port_))
+          .set_lookup_service_timeout(2000)
+          .Build());
+  // RLS server will send a response, but it's longer than the timeout.
+  rls_server_->service_.SetResponse(
+      BuildRlsRequest({{kTestKey, kTestValue}}),
+      BuildRlsResponse({TargetStringForPort(backends_[0]->port_)}),
+      /*response_delay=*/3000);
+  // The data plane RPC should be sent to the default target.
+  CheckRpcSendOk(DEBUG_LOCATION, RpcOptions().set_timeout_ms(4000).set_metadata(
+                                     {{"key1", kTestValue}}));
+  EXPECT_EQ(rls_server_->service_.request_count(), 1);
+  EXPECT_EQ(backends_[0]->service_.request_count(), 0);
+  EXPECT_EQ(backends_[1]->service_.request_count(), 1);
+}
+
+TEST_F(RlsEnd2endTest, UpdateConfig) {
+  StartBackends(2);
+  auto service_config_builder =
+      MakeServiceConfigBuilder()
+          .AddKeyBuilder(absl::StrFormat("\"names\":[{"
+                                         "  \"service\":\"%s\","
+                                         "  \"method\":\"%s\""
+                                         "}],"
+                                         "\"headers\":["
+                                         "  {"
+                                         "    \"key\":\"%s\","
+                                         "    \"names\":["
+                                         "      \"key1\""
+                                         "    ]"
+                                         "  }"
+                                         "]",
+                                         kServiceValue, kMethodValue, kTestKey))
+          .set_default_target(TargetStringForPort(backends_[0]->port_));
+  SetNextResolution(service_config_builder.Build());
+  // Don't give the RLS server a response, so the RLS request will fail.
+  // The data plane RPC should be sent to the default target.
+  CheckRpcSendOk(DEBUG_LOCATION,
+                 RpcOptions().set_metadata({{"key1", kTestValue}}));
+  EXPECT_THAT(
+      rls_server_->service_.GetUnmatchedRequests(),
+      ::testing::ElementsAre(
+          // TODO(roth): Change this to use ::testing::ProtoEquals()
+          // once that becomes available in OSS.
+          ::testing::Property(
+              &RouteLookupRequest::DebugString,
+              BuildRlsRequest({{kTestKey, kTestValue}}).DebugString())));
+  EXPECT_EQ(rls_server_->service_.request_count(), 1);
+  EXPECT_EQ(rls_server_->service_.response_count(), 0);
+  EXPECT_EQ(backends_[0]->service_.request_count(), 1);
+  EXPECT_EQ(backends_[1]->service_.request_count(), 0);
+  // Now update the config to point to a new default target.
+  service_config_builder.set_default_target(
+      TargetStringForPort(backends_[1]->port_));
+  SetNextResolution(service_config_builder.Build());
+  // Send another RPC, which should go to the new default target.
+  // The RLS server will *not* see another request, because the cache
+  // entry is still in backoff.
+  CheckRpcSendOk(DEBUG_LOCATION,
+                 RpcOptions().set_metadata({{"key1", kTestValue}}));
+  EXPECT_EQ(rls_server_->service_.request_count(), 1);
+  EXPECT_EQ(rls_server_->service_.response_count(), 0);
+  EXPECT_EQ(backends_[0]->service_.request_count(), 1);
+  EXPECT_EQ(backends_[1]->service_.request_count(), 1);
+}
+
+TEST_F(RlsEnd2endTest, CachedResponse) {
+  StartBackends(1);
+  SetNextResolution(
+      MakeServiceConfigBuilder()
+          .AddKeyBuilder(absl::StrFormat("\"names\":[{"
+                                         "  \"service\":\"%s\","
+                                         "  \"method\":\"%s\""
+                                         "}],"
+                                         "\"headers\":["
+                                         "  {"
+                                         "    \"key\":\"%s\","
+                                         "    \"names\":["
+                                         "      \"key1\""
+                                         "    ]"
+                                         "  }"
+                                         "]",
+                                         kServiceValue, kMethodValue, kTestKey))
+          .Build());
+  rls_server_->service_.SetResponse(
+      BuildRlsRequest({{kTestKey, kTestValue}}),
+      BuildRlsResponse({TargetStringForPort(backends_[0]->port_)}));
+  // Send two RPCs.
+  CheckRpcSendOk(DEBUG_LOCATION,
+                 RpcOptions().set_metadata({{"key1", kTestValue}}));
+  CheckRpcSendOk(DEBUG_LOCATION,
+                 RpcOptions().set_metadata({{"key1", kTestValue}}));
+  // The RLS server should have seen only one request.
+  EXPECT_EQ(rls_server_->service_.request_count(), 1);
+  EXPECT_EQ(rls_server_->service_.response_count(), 1);
+  EXPECT_EQ(backends_[0]->service_.request_count(), 2);
+}
+
+TEST_F(RlsEnd2endTest, StaleCacheEntry) {
+  StartBackends(1);
+  SetNextResolution(
+      MakeServiceConfigBuilder()
+          .AddKeyBuilder(absl::StrFormat("\"names\":[{"
+                                         "  \"service\":\"%s\","
+                                         "  \"method\":\"%s\""
+                                         "}],"
+                                         "\"headers\":["
+                                         "  {"
+                                         "    \"key\":\"%s\","
+                                         "    \"names\":["
+                                         "      \"key1\""
+                                         "    ]"
+                                         "  }"
+                                         "]",
+                                         kServiceValue, kMethodValue, kTestKey))
+          .set_max_age(5000)
+          .set_stale_age(1000)
+          .Build());
+  rls_server_->service_.SetResponse(
+      BuildRlsRequest({{kTestKey, kTestValue}}),
+      BuildRlsResponse({TargetStringForPort(backends_[0]->port_)}));
+  // Send one RPC.  RLS server gets a request, and RPC goes to backend.
+  CheckRpcSendOk(DEBUG_LOCATION,
+                 RpcOptions().set_metadata({{"key1", kTestValue}}));
+  EXPECT_EQ(rls_server_->service_.request_count(), 1);
+  EXPECT_EQ(rls_server_->service_.response_count(), 1);
+  EXPECT_EQ(backends_[0]->service_.request_count(), 1);
+  // Update RLS server to expect stale request.
+  rls_server_->service_.RemoveResponse(
+      BuildRlsRequest({{kTestKey, kTestValue}}));
+  rls_server_->service_.SetResponse(
+      BuildRlsRequest({{kTestKey, kTestValue}},
+                      RouteLookupRequest::REASON_STALE),
+      BuildRlsResponse({TargetStringForPort(backends_[0]->port_)}));
+  // Wait longer than stale age.
+  gpr_sleep_until(grpc_timeout_seconds_to_deadline(2));
+  // Send another RPC.  This should use the stale value but should
+  // dispatch a second RLS request.
+  CheckRpcSendOk(DEBUG_LOCATION,
+                 RpcOptions().set_metadata({{"key1", kTestValue}}));
+  EXPECT_EQ(backends_[0]->service_.request_count(), 2);
+  // Wait for RLS server to receive the second request.
+  gpr_sleep_until(grpc_timeout_seconds_to_deadline(2));
+  EXPECT_EQ(rls_server_->service_.request_count(), 2);
+  EXPECT_EQ(rls_server_->service_.response_count(), 2);
+}
+
+TEST_F(RlsEnd2endTest, StaleCacheEntryWithHeaderData) {
+  const char* kHeaderData = "header_data";
+  StartBackends(1);
+  SetNextResolution(
+      MakeServiceConfigBuilder()
+          .AddKeyBuilder(absl::StrFormat("\"names\":[{"
+                                         "  \"service\":\"%s\","
+                                         "  \"method\":\"%s\""
+                                         "}],"
+                                         "\"headers\":["
+                                         "  {"
+                                         "    \"key\":\"%s\","
+                                         "    \"names\":["
+                                         "      \"key1\""
+                                         "    ]"
+                                         "  }"
+                                         "]",
+                                         kServiceValue, kMethodValue, kTestKey))
+          .set_max_age(5000)
+          .set_stale_age(1000)
+          .Build());
+  rls_server_->service_.SetResponse(
+      BuildRlsRequest({{kTestKey, kTestValue}}),
+      BuildRlsResponse({TargetStringForPort(backends_[0]->port_)},
+                       kHeaderData));
+  // Send one RPC.  RLS server gets a request, and RPC goes to backend.
+  CheckRpcSendOk(DEBUG_LOCATION,
+                 RpcOptions().set_metadata({{"key1", kTestValue}}));
+  EXPECT_EQ(rls_server_->service_.request_count(), 1);
+  EXPECT_EQ(rls_server_->service_.response_count(), 1);
+  EXPECT_EQ(backends_[0]->service_.request_count(), 1);
+  // Update RLS server to expect stale request.
+  rls_server_->service_.RemoveResponse(
+      BuildRlsRequest({{kTestKey, kTestValue}}));
+  rls_server_->service_.SetResponse(
+      BuildRlsRequest({{kTestKey, kTestValue}},
+                      RouteLookupRequest::REASON_STALE, kHeaderData),
+      BuildRlsResponse({TargetStringForPort(backends_[0]->port_)},
+                       kHeaderData));
+  // Wait longer than stale age.
+  gpr_sleep_until(grpc_timeout_seconds_to_deadline(2));
+  // Send another RPC.  This should use the stale value but should
+  // dispatch a second RLS request.
+  CheckRpcSendOk(DEBUG_LOCATION,
+                 RpcOptions().set_metadata({{"key1", kTestValue}}));
+  EXPECT_EQ(backends_[0]->service_.request_count(), 2);
+  // Wait for RLS server to receive the second request.
+  gpr_sleep_until(grpc_timeout_seconds_to_deadline(2));
+  EXPECT_EQ(rls_server_->service_.request_count(), 2);
+  EXPECT_EQ(rls_server_->service_.response_count(), 2);
+}
+
+TEST_F(RlsEnd2endTest, ExpiredCacheEntry) {
+  StartBackends(1);
+  SetNextResolution(
+      MakeServiceConfigBuilder()
+          .AddKeyBuilder(absl::StrFormat("\"names\":[{"
+                                         "  \"service\":\"%s\","
+                                         "  \"method\":\"%s\""
+                                         "}],"
+                                         "\"headers\":["
+                                         "  {"
+                                         "    \"key\":\"%s\","
+                                         "    \"names\":["
+                                         "      \"key1\""
+                                         "    ]"
+                                         "  }"
+                                         "]",
+                                         kServiceValue, kMethodValue, kTestKey))
+          .set_max_age(1000)
+          .set_lookup_service_timeout(1000)
+          .Build());
+  rls_server_->service_.SetResponse(
+      BuildRlsRequest({{kTestKey, kTestValue}}),
+      BuildRlsResponse({TargetStringForPort(backends_[0]->port_)}));
+  // Send one RPC.  RLS server gets a request, and RPC goes to backend.
+  CheckRpcSendOk(DEBUG_LOCATION,
+                 RpcOptions().set_metadata({{"key1", kTestValue}}));
+  EXPECT_EQ(rls_server_->service_.request_count(), 1);
+  EXPECT_EQ(rls_server_->service_.response_count(), 1);
+  EXPECT_EQ(backends_[0]->service_.request_count(), 1);
+  // Remove response from RLS server so that the next RLS request fails.
+  rls_server_->service_.RemoveResponse(
+      BuildRlsRequest({{kTestKey, kTestValue}}));
+  // Wait for cache to be expired.
+  gpr_sleep_until(grpc_timeout_seconds_to_deadline(2));
+  // Send another RPC.  This should trigger a second RLS request, but
+  // that fails, so the RPC fails.
+  CheckRpcSendFailure(DEBUG_LOCATION,
+                      RpcOptions().set_metadata({{"key1", kTestValue}}));
+  EXPECT_EQ(rls_server_->service_.request_count(), 2);
+  EXPECT_EQ(rls_server_->service_.response_count(), 1);
+  EXPECT_EQ(backends_[0]->service_.request_count(), 1);
+}
+
+TEST_F(RlsEnd2endTest, CacheSizeLimit) {
+  const char* kTestValue2 = "test_value_2";
+  StartBackends(2);
+  SetNextResolution(
+      MakeServiceConfigBuilder()
+          .AddKeyBuilder(absl::StrFormat("\"names\":[{"
+                                         "  \"service\":\"%s\","
+                                         "  \"method\":\"%s\""
+                                         "}],"
+                                         "\"headers\":["
+                                         "  {"
+                                         "    \"key\":\"%s\","
+                                         "    \"names\":["
+                                         "      \"key1\""
+                                         "    ]"
+                                         "  }"
+                                         "]",
+                                         kServiceValue, kMethodValue,
+                                         kTestKey))
+          .set_cache_size_bytes(1)  // Not even big enough for one entry.
+          .Build());
+  // Set RLS responses for both kTestValue and kTestValue2.
+  rls_server_->service_.SetResponse(
+      BuildRlsRequest({{kTestKey, kTestValue}}),
+      BuildRlsResponse({TargetStringForPort(backends_[0]->port_)}));
+  rls_server_->service_.SetResponse(
+      BuildRlsRequest({{kTestKey, kTestValue2}}),
+      BuildRlsResponse({TargetStringForPort(backends_[1]->port_)}));
+  // Send an RPC for kTestValue.
+  // RLS server gets a request, and RPC goes to backend.
+  CheckRpcSendOk(DEBUG_LOCATION,
+                 RpcOptions().set_metadata({{"key1", kTestValue}}));
+  EXPECT_EQ(rls_server_->service_.request_count(), 1);
+  EXPECT_EQ(rls_server_->service_.response_count(), 1);
+  EXPECT_EQ(backends_[0]->service_.request_count(), 1);
+  EXPECT_EQ(backends_[1]->service_.request_count(), 0);
+  // A second RPC for kTestValue should not generate another RLS
+  // request, because the cache entry is held by min_eviction_time.
+  CheckRpcSendOk(DEBUG_LOCATION,
+                 RpcOptions().set_metadata({{"key1", kTestValue}}));
+  EXPECT_EQ(rls_server_->service_.request_count(), 1);
+  EXPECT_EQ(rls_server_->service_.response_count(), 1);
+  EXPECT_EQ(backends_[0]->service_.request_count(), 2);
+  EXPECT_EQ(backends_[1]->service_.request_count(), 0);
+  // Wait for min_eviction_time to elapse.
+  gpr_sleep_until(grpc_timeout_seconds_to_deadline(6));
+  // Send a request for kTestValue2.
+  // RLS server gets a request, and RPC goes to backend.
+  // This causes the entry for kTestValue to be evicted.
+  CheckRpcSendOk(DEBUG_LOCATION,
+                 RpcOptions().set_metadata({{"key1", kTestValue2}}));
+  EXPECT_EQ(rls_server_->service_.request_count(), 2);
+  EXPECT_EQ(rls_server_->service_.response_count(), 2);
+  EXPECT_EQ(backends_[0]->service_.request_count(), 2);
+  EXPECT_EQ(backends_[1]->service_.request_count(), 1);
+  // Send another RPC for kTestValue.
+  // This should now trigger a new RLS request.
+  CheckRpcSendOk(DEBUG_LOCATION,
+                 RpcOptions().set_metadata({{"key1", kTestValue}}));
+  EXPECT_EQ(rls_server_->service_.request_count(), 3);
+  EXPECT_EQ(rls_server_->service_.response_count(), 3);
+  EXPECT_EQ(backends_[0]->service_.request_count(), 3);
+  EXPECT_EQ(backends_[1]->service_.request_count(), 1);
+  // Another RPC for kTestValue2 should still work due to min_eviction_time.
+  CheckRpcSendOk(DEBUG_LOCATION,
+                 RpcOptions().set_metadata({{"key1", kTestValue2}}));
+  EXPECT_EQ(rls_server_->service_.request_count(), 3);
+  EXPECT_EQ(rls_server_->service_.response_count(), 3);
+  EXPECT_EQ(backends_[0]->service_.request_count(), 3);
+  EXPECT_EQ(backends_[1]->service_.request_count(), 2);
+}
+
+TEST_F(RlsEnd2endTest, MultipleTargets) {
+  StartBackends(1);
+  SetNextResolution(
+      MakeServiceConfigBuilder()
+          .AddKeyBuilder(absl::StrFormat("\"names\":[{"
+                                         "  \"service\":\"%s\","
+                                         "  \"method\":\"%s\""
+                                         "}],"
+                                         "\"headers\":["
+                                         "  {"
+                                         "    \"key\":\"%s\","
+                                         "    \"names\":["
+                                         "      \"key1\""
+                                         "    ]"
+                                         "  }"
+                                         "]",
+                                         kServiceValue, kMethodValue, kTestKey))
+          .Build());
+  rls_server_->service_.SetResponse(
+      BuildRlsRequest({{kTestKey, kTestValue}}),
+      BuildRlsResponse(
+          // First target will report TRANSIENT_FAILURE..
+          {"invalid_target", TargetStringForPort(backends_[0]->port_)}));
+  CheckRpcSendOk(DEBUG_LOCATION,
+                 RpcOptions().set_metadata({{"key1", kTestValue}}));
+  EXPECT_EQ(rls_server_->service_.request_count(), 1);
+  EXPECT_EQ(rls_server_->service_.response_count(), 1);
+  EXPECT_EQ(backends_[0]->service_.request_count(), 1);
+}
+
+TEST_F(RlsEnd2endTest, ConnectivityStateReady) {
+  StartBackends(1);
+  SetNextResolution(
+      MakeServiceConfigBuilder()
+          .AddKeyBuilder(absl::StrFormat("\"names\":[{"
+                                         "  \"service\":\"%s\","
+                                         "  \"method\":\"%s\""
+                                         "}],"
+                                         "\"headers\":["
+                                         "  {"
+                                         "    \"key\":\"%s\","
+                                         "    \"names\":["
+                                         "      \"key1\""
+                                         "    ]"
+                                         "  }"
+                                         "]",
+                                         kServiceValue, kMethodValue, kTestKey))
+          .Build());
+  EXPECT_EQ(GRPC_CHANNEL_IDLE, channel_->GetState(/*try_to_connect=*/false));
+  rls_server_->service_.SetResponse(
+      BuildRlsRequest({{kTestKey, kTestValue}}),
+      BuildRlsResponse(
+          // One target in TRANSIENT_FAILURE, the other in READY.
+          {"invalid_target", TargetStringForPort(backends_[0]->port_)}));
+  CheckRpcSendOk(DEBUG_LOCATION,
+                 RpcOptions().set_metadata({{"key1", kTestValue}}));
+  EXPECT_EQ(rls_server_->service_.request_count(), 1);
+  EXPECT_EQ(rls_server_->service_.response_count(), 1);
+  EXPECT_EQ(backends_[0]->service_.request_count(), 1);
+  EXPECT_EQ(GRPC_CHANNEL_READY, channel_->GetState(/*try_to_connect=*/false));
+}
+
+TEST_F(RlsEnd2endTest, ConnectivityStateIdle) {
+  SetNextResolution(
+      MakeServiceConfigBuilder()
+          .AddKeyBuilder(absl::StrFormat("\"names\":[{"
+                                         "  \"service\":\"%s\","
+                                         "  \"method\":\"%s\""
+                                         "}],"
+                                         "\"headers\":["
+                                         "  {"
+                                         "    \"key\":\"%s\","
+                                         "    \"names\":["
+                                         "      \"key1\""
+                                         "    ]"
+                                         "  }"
+                                         "]",
+                                         kServiceValue, kMethodValue, kTestKey))
+          .Build());
+  EXPECT_EQ(GRPC_CHANNEL_IDLE, channel_->GetState(/*try_to_connect=*/false));
+  // RLS server not given any responses, so the request will fail.
+  CheckRpcSendFailure(DEBUG_LOCATION);
+  // No child policies, so should be IDLE.
+  EXPECT_EQ(GRPC_CHANNEL_IDLE, channel_->GetState(/*try_to_connect=*/false));
+}
+
+TEST_F(RlsEnd2endTest, ConnectivityStateTransientFailure) {
+  SetNextResolution(
+      MakeServiceConfigBuilder()
+          .AddKeyBuilder(absl::StrFormat("\"names\":[{"
+                                         "  \"service\":\"%s\","
+                                         "  \"method\":\"%s\""
+                                         "}],"
+                                         "\"headers\":["
+                                         "  {"
+                                         "    \"key\":\"%s\","
+                                         "    \"names\":["
+                                         "      \"key1\""
+                                         "    ]"
+                                         "  }"
+                                         "]",
+                                         kServiceValue, kMethodValue, kTestKey))
+          .Build());
+  EXPECT_EQ(GRPC_CHANNEL_IDLE, channel_->GetState(/*try_to_connect=*/false));
+  rls_server_->service_.SetResponse(BuildRlsRequest({{kTestKey, kTestValue}}),
+                                    BuildRlsResponse({"invalid_target"}));
+  CheckRpcSendFailure(DEBUG_LOCATION,
+                      RpcOptions().set_metadata({{"key1", kTestValue}}));
+  EXPECT_EQ(rls_server_->service_.request_count(), 1);
+  EXPECT_EQ(rls_server_->service_.response_count(), 1);
+  EXPECT_EQ(GRPC_CHANNEL_TRANSIENT_FAILURE,
+            channel_->GetState(/*try_to_connect=*/false));
+}
+
+TEST_F(RlsEnd2endTest, RlsAuthorityDeathTest) {
+  GRPC_GTEST_FLAG_SET_DEATH_TEST_STYLE("threadsafe");
+  ResetStub("incorrect_authority");
+  SetNextResolution(
+      MakeServiceConfigBuilder()
+          .AddKeyBuilder(absl::StrFormat("\"names\":[{"
+                                         "  \"service\":\"%s\","
+                                         "  \"method\":\"%s\""
+                                         "}],"
+                                         "\"headers\":["
+                                         "  {"
+                                         "    \"key\":\"%s\","
+                                         "    \"names\":["
+                                         "      \"key1\""
+                                         "    ]"
+                                         "  }"
+                                         "]",
+                                         kServiceValue, kMethodValue, kTestKey))
+          .Build());
+  // Make sure that we blow up (via abort() from the security connector) when
+  // the authority for the RLS channel doesn't match expectations.
+  ASSERT_DEATH_IF_SUPPORTED(
+      {
+        CheckRpcSendOk(DEBUG_LOCATION,
+                       RpcOptions().set_metadata({{"key1", kTestValue}}));
+      },
+      "");
+}
+
+}  // namespace
+}  // namespace testing
+}  // namespace grpc
+
+int main(int argc, char** argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  grpc::testing::TestEnvironment env(argc, argv);
+  return RUN_ALL_TESTS();
+}
index 853920a..3b6fb4a 100644 (file)
@@ -28,6 +28,7 @@
 #include "src/proto/grpc/testing/echo.grpc.pb.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
+#include "test/core/util/tls_utils.h"
 #include "test/cpp/end2end/test_service_impl.h"
 
 namespace grpc {
@@ -76,6 +77,17 @@ class SdkAuthzEnd2EndTest : public ::testing::Test {
     return provider;
   }
 
+  std::shared_ptr<experimental::AuthorizationPolicyProviderInterface>
+  CreateFileWatcherAuthzPolicyProvider(const std::string& policy_path,
+                                       unsigned int refresh_interval_sec) {
+    grpc::Status status;
+    auto provider =
+        experimental::FileWatcherAuthorizationPolicyProvider::Create(
+            policy_path, refresh_interval_sec, &status);
+    EXPECT_TRUE(status.ok());
+    return provider;
+  }
+
   std::shared_ptr<Channel> BuildChannel() {
     ChannelArguments args;
     return ::grpc::CreateCustomChannel(server_address_, channel_creds_, args);
@@ -348,6 +360,397 @@ TEST_F(
   EXPECT_TRUE(resp.message().empty());
 }
 
+TEST_F(SdkAuthzEnd2EndTest,
+       FileWatcherInitAllowsRpcRequestNoMatchInDenyMatchInAllow) {
+  std::string policy =
+      "{"
+      "  \"name\": \"authz\","
+      "  \"allow_rules\": ["
+      "    {"
+      "      \"name\": \"allow_echo\","
+      "      \"request\": {"
+      "        \"paths\": ["
+      "          \"*/Echo\""
+      "        ],"
+      "        \"headers\": ["
+      "          {"
+      "            \"key\": \"key-foo\","
+      "            \"values\": [\"foo1\", \"foo2\"]"
+      "          },"
+      "          {"
+      "            \"key\": \"key-bar\","
+      "            \"values\": [\"bar1\"]"
+      "          }"
+      "        ]"
+      "      }"
+      "    }"
+      "  ],"
+      "  \"deny_rules\": ["
+      "    {"
+      "      \"name\": \"deny_clientstreamingecho\","
+      "      \"request\": {"
+      "        \"paths\": ["
+      "          \"*/ClientStreamingEcho\""
+      "        ]"
+      "      }"
+      "    }"
+      "  ]"
+      "}";
+  grpc_core::testing::TmpFile tmp_policy(policy);
+  InitServer(CreateFileWatcherAuthzPolicyProvider(tmp_policy.name(), 5));
+  auto channel = BuildChannel();
+  ClientContext context;
+  context.AddMetadata("key-foo", "foo2");
+  context.AddMetadata("key-bar", "bar1");
+  context.AddMetadata("key-baz", "baz1");
+  grpc::testing::EchoResponse resp;
+  grpc::Status status = SendRpc(channel, &context, &resp);
+  EXPECT_TRUE(status.ok());
+  EXPECT_EQ(resp.message(), kMessage);
+}
+
+TEST_F(SdkAuthzEnd2EndTest,
+       FileWatcherInitDeniesRpcRequestNoMatchInAllowAndDeny) {
+  std::string policy =
+      "{"
+      "  \"name\": \"authz\","
+      "  \"allow_rules\": ["
+      "    {"
+      "      \"name\": \"allow_foo\","
+      "      \"request\": {"
+      "        \"paths\": ["
+      "          \"*/foo\""
+      "        ]"
+      "      }"
+      "    }"
+      "  ],"
+      "  \"deny_rules\": ["
+      "    {"
+      "      \"name\": \"deny_bar\","
+      "      \"source\": {"
+      "        \"principals\": ["
+      "          \"bar\""
+      "        ]"
+      "      }"
+      "    }"
+      "  ]"
+      "}";
+  grpc_core::testing::TmpFile tmp_policy(policy);
+  InitServer(CreateFileWatcherAuthzPolicyProvider(tmp_policy.name(), 5));
+  auto channel = BuildChannel();
+  ClientContext context;
+  grpc::testing::EchoResponse resp;
+  grpc::Status status = SendRpc(channel, &context, &resp);
+  EXPECT_EQ(status.error_code(), grpc::StatusCode::PERMISSION_DENIED);
+  EXPECT_EQ(status.error_message(), "Unauthorized RPC request rejected.");
+  EXPECT_TRUE(resp.message().empty());
+}
+
+TEST_F(SdkAuthzEnd2EndTest,
+       FileWatcherInitDeniesRpcRequestMatchInDenyMatchInAllow) {
+  std::string policy =
+      "{"
+      "  \"name\": \"authz\","
+      "  \"allow_rules\": ["
+      "    {"
+      "      \"name\": \"allow_all\""
+      "    }"
+      "  ],"
+      "  \"deny_rules\": ["
+      "    {"
+      "      \"name\": \"deny_echo\","
+      "      \"request\": {"
+      "        \"paths\": ["
+      "          \"*/Echo\""
+      "        ]"
+      "      }"
+      "    }"
+      "  ]"
+      "}";
+  grpc_core::testing::TmpFile tmp_policy(policy);
+  InitServer(CreateFileWatcherAuthzPolicyProvider(tmp_policy.name(), 5));
+  auto channel = BuildChannel();
+  ClientContext context;
+  grpc::testing::EchoResponse resp;
+  grpc::Status status = SendRpc(channel, &context, &resp);
+  EXPECT_EQ(status.error_code(), grpc::StatusCode::PERMISSION_DENIED);
+  EXPECT_EQ(status.error_message(), "Unauthorized RPC request rejected.");
+  EXPECT_TRUE(resp.message().empty());
+}
+
+TEST_F(SdkAuthzEnd2EndTest,
+       FileWatcherInitDeniesRpcRequestMatchInDenyNoMatchInAllow) {
+  std::string policy =
+      "{"
+      "  \"name\": \"authz\","
+      "  \"allow_rules\": ["
+      "    {"
+      "      \"name\": \"allow_clientstreamingecho\","
+      "      \"request\": {"
+      "        \"paths\": ["
+      "          \"*/ClientStreamingEcho\""
+      "        ]"
+      "      }"
+      "    }"
+      "  ],"
+      "  \"deny_rules\": ["
+      "    {"
+      "      \"name\": \"deny_echo\","
+      "      \"request\": {"
+      "        \"paths\": ["
+      "          \"*/Echo\""
+      "        ]"
+      "      }"
+      "    }"
+      "  ]"
+      "}";
+  grpc_core::testing::TmpFile tmp_policy(policy);
+  InitServer(CreateFileWatcherAuthzPolicyProvider(tmp_policy.name(), 5));
+  auto channel = BuildChannel();
+  ClientContext context;
+  grpc::testing::EchoResponse resp;
+  grpc::Status status = SendRpc(channel, &context, &resp);
+  EXPECT_EQ(status.error_code(), grpc::StatusCode::PERMISSION_DENIED);
+  EXPECT_EQ(status.error_message(), "Unauthorized RPC request rejected.");
+  EXPECT_TRUE(resp.message().empty());
+}
+
+TEST_F(SdkAuthzEnd2EndTest,
+       FileWatcherInitAllowsRpcRequestEmptyDenyMatchInAllow) {
+  std::string policy =
+      "{"
+      "  \"name\": \"authz\","
+      "  \"allow_rules\": ["
+      "    {"
+      "      \"name\": \"allow_echo\","
+      "      \"request\": {"
+      "        \"paths\": ["
+      "          \"*/Echo\""
+      "        ],"
+      "        \"headers\": ["
+      "          {"
+      "            \"key\": \"key-foo\","
+      "            \"values\": [\"foo1\", \"foo2\"]"
+      "          },"
+      "          {"
+      "            \"key\": \"key-bar\","
+      "            \"values\": [\"bar1\"]"
+      "          }"
+      "        ]"
+      "      }"
+      "    }"
+      "  ]"
+      "}";
+  grpc_core::testing::TmpFile tmp_policy(policy);
+  InitServer(CreateFileWatcherAuthzPolicyProvider(tmp_policy.name(), 5));
+  auto channel = BuildChannel();
+  ClientContext context;
+  context.AddMetadata("key-foo", "foo2");
+  context.AddMetadata("key-bar", "bar1");
+  context.AddMetadata("key-baz", "baz1");
+  grpc::testing::EchoResponse resp;
+  grpc::Status status = SendRpc(channel, &context, &resp);
+  EXPECT_TRUE(status.ok());
+  EXPECT_EQ(resp.message(), kMessage);
+}
+
+TEST_F(SdkAuthzEnd2EndTest,
+       FileWatcherInitDeniesRpcRequestEmptyDenyNoMatchInAllow) {
+  std::string policy =
+      "{"
+      "  \"name\": \"authz\","
+      "  \"allow_rules\": ["
+      "    {"
+      "      \"name\": \"allow_echo\","
+      "      \"request\": {"
+      "        \"paths\": ["
+      "          \"*/Echo\""
+      "        ],"
+      "        \"headers\": ["
+      "          {"
+      "            \"key\": \"key-foo\","
+      "            \"values\": [\"foo1\"]"
+      "          }"
+      "        ]"
+      "      }"
+      "    }"
+      "  ]"
+      "}";
+  grpc_core::testing::TmpFile tmp_policy(policy);
+  InitServer(CreateFileWatcherAuthzPolicyProvider(tmp_policy.name(), 5));
+  auto channel = BuildChannel();
+  ClientContext context;
+  context.AddMetadata("key-bar", "bar1");
+  grpc::testing::EchoResponse resp;
+  grpc::Status status = SendRpc(channel, &context, &resp);
+  EXPECT_EQ(status.error_code(), grpc::StatusCode::PERMISSION_DENIED);
+  EXPECT_EQ(status.error_message(), "Unauthorized RPC request rejected.");
+  EXPECT_TRUE(resp.message().empty());
+}
+
+TEST_F(SdkAuthzEnd2EndTest, FileWatcherValidPolicyRefresh) {
+  std::string policy =
+      "{"
+      "  \"name\": \"authz\","
+      "  \"allow_rules\": ["
+      "    {"
+      "      \"name\": \"allow_echo\","
+      "      \"request\": {"
+      "        \"paths\": ["
+      "          \"*/Echo\""
+      "        ]"
+      "      }"
+      "    }"
+      "  ]"
+      "}";
+  grpc_core::testing::TmpFile tmp_policy(policy);
+  InitServer(CreateFileWatcherAuthzPolicyProvider(tmp_policy.name(), 1));
+  auto channel = BuildChannel();
+  ClientContext context1;
+  grpc::testing::EchoResponse resp1;
+  grpc::Status status = SendRpc(channel, &context1, &resp1);
+  EXPECT_TRUE(status.ok());
+  EXPECT_EQ(resp1.message(), kMessage);
+  // Replace the existing policy with a new authorization policy.
+  policy =
+      "{"
+      "  \"name\": \"authz\","
+      "  \"allow_rules\": ["
+      "    {"
+      "      \"name\": \"allow_foo\","
+      "      \"request\": {"
+      "        \"paths\": ["
+      "          \"*/foo\""
+      "        ]"
+      "      }"
+      "    }"
+      "  ],"
+      "  \"deny_rules\": ["
+      "    {"
+      "      \"name\": \"deny_echo\","
+      "      \"request\": {"
+      "        \"paths\": ["
+      "          \"*/Echo\""
+      "        ]"
+      "      }"
+      "    }"
+      "  ]"
+      "}";
+  tmp_policy.RewriteFile(policy);
+  // Wait 2 seconds for the provider's refresh thread to read the updated files.
+  gpr_sleep_until(grpc_timeout_seconds_to_deadline(2));
+  ClientContext context2;
+  grpc::testing::EchoResponse resp2;
+  status = SendRpc(channel, &context2, &resp2);
+  EXPECT_EQ(status.error_code(), grpc::StatusCode::PERMISSION_DENIED);
+  EXPECT_EQ(status.error_message(), "Unauthorized RPC request rejected.");
+  EXPECT_TRUE(resp2.message().empty());
+}
+
+TEST_F(SdkAuthzEnd2EndTest, FileWatcherInvalidPolicyRefreshSkipsReload) {
+  std::string policy =
+      "{"
+      "  \"name\": \"authz\","
+      "  \"allow_rules\": ["
+      "    {"
+      "      \"name\": \"allow_echo\","
+      "      \"request\": {"
+      "        \"paths\": ["
+      "          \"*/Echo\""
+      "        ]"
+      "      }"
+      "    }"
+      "  ]"
+      "}";
+  grpc_core::testing::TmpFile tmp_policy(policy);
+  InitServer(CreateFileWatcherAuthzPolicyProvider(tmp_policy.name(), 1));
+  auto channel = BuildChannel();
+  ClientContext context1;
+  grpc::testing::EchoResponse resp1;
+  grpc::Status status = SendRpc(channel, &context1, &resp1);
+  EXPECT_TRUE(status.ok());
+  EXPECT_EQ(resp1.message(), kMessage);
+  // Replaces existing policy with an invalid authorization policy.
+  policy = "{}";
+  tmp_policy.RewriteFile(policy);
+  // Wait 2 seconds for the provider's refresh thread to read the updated files.
+  gpr_sleep_until(grpc_timeout_seconds_to_deadline(2));
+  ClientContext context2;
+  grpc::testing::EchoResponse resp2;
+  status = SendRpc(channel, &context2, &resp2);
+  EXPECT_TRUE(status.ok());
+  EXPECT_EQ(resp2.message(), kMessage);
+}
+
+TEST_F(SdkAuthzEnd2EndTest, FileWatcherRecoversFromFailure) {
+  std::string policy =
+      "{"
+      "  \"name\": \"authz\","
+      "  \"allow_rules\": ["
+      "    {"
+      "      \"name\": \"allow_echo\","
+      "      \"request\": {"
+      "        \"paths\": ["
+      "          \"*/Echo\""
+      "        ]"
+      "      }"
+      "    }"
+      "  ]"
+      "}";
+  grpc_core::testing::TmpFile tmp_policy(policy);
+  InitServer(CreateFileWatcherAuthzPolicyProvider(tmp_policy.name(), 1));
+  auto channel = BuildChannel();
+  ClientContext context1;
+  grpc::testing::EchoResponse resp1;
+  grpc::Status status = SendRpc(channel, &context1, &resp1);
+  EXPECT_TRUE(status.ok());
+  EXPECT_EQ(resp1.message(), kMessage);
+  // Replaces existing policy with an invalid authorization policy.
+  policy = "{}";
+  tmp_policy.RewriteFile(policy);
+  // Wait 2 seconds for the provider's refresh thread to read the updated files.
+  gpr_sleep_until(grpc_timeout_seconds_to_deadline(2));
+  ClientContext context2;
+  grpc::testing::EchoResponse resp2;
+  status = SendRpc(channel, &context2, &resp2);
+  EXPECT_TRUE(status.ok());
+  EXPECT_EQ(resp2.message(), kMessage);
+  // Replace the existing invalid policy with a valid authorization policy.
+  policy =
+      "{"
+      "  \"name\": \"authz\","
+      "  \"allow_rules\": ["
+      "    {"
+      "      \"name\": \"allow_foo\","
+      "      \"request\": {"
+      "        \"paths\": ["
+      "          \"*/foo\""
+      "        ]"
+      "      }"
+      "    }"
+      "  ],"
+      "  \"deny_rules\": ["
+      "    {"
+      "      \"name\": \"deny_echo\","
+      "      \"request\": {"
+      "        \"paths\": ["
+      "          \"*/Echo\""
+      "        ]"
+      "      }"
+      "    }"
+      "  ]"
+      "}";
+  tmp_policy.RewriteFile(policy);
+  // Wait 2 seconds for the provider's refresh thread to read the updated files.
+  gpr_sleep_until(grpc_timeout_seconds_to_deadline(2));
+  ClientContext context3;
+  grpc::testing::EchoResponse resp3;
+  status = SendRpc(channel, &context3, &resp3);
+  EXPECT_EQ(status.error_code(), grpc::StatusCode::PERMISSION_DENIED);
+  EXPECT_EQ(status.error_message(), "Unauthorized RPC request rejected.");
+  EXPECT_TRUE(resp3.message().empty());
+}
+
 }  // namespace
 }  // namespace testing
 }  // namespace grpc
index 2b6c41a..be8fb6d 100644 (file)
@@ -377,6 +377,9 @@ class TestMultipleServiceImpl : public RpcService {
     int server_try_cancel = internal::GetIntValueFromMetadata(
         kServerTryCancelRequest, context->client_metadata(), DO_NOT_CANCEL);
 
+    int client_try_cancel = static_cast<bool>(internal::GetIntValueFromMetadata(
+        kClientTryCancelRequest, context->client_metadata(), 0));
+
     EchoRequest request;
     EchoResponse response;
 
@@ -409,6 +412,10 @@ class TestMultipleServiceImpl : public RpcService {
       }
     }
 
+    if (client_try_cancel) {
+      EXPECT_TRUE(context->IsCancelled());
+    }
+
     if (server_try_cancel_thd != nullptr) {
       server_try_cancel_thd->join();
       delete server_try_cancel_thd;
diff --git a/test/cpp/end2end/xds/BUILD b/test/cpp/end2end/xds/BUILD
new file mode 100644 (file)
index 0000000..5db4b55
--- /dev/null
@@ -0,0 +1,120 @@
+# 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.
+
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_package")
+
+licenses(["notice"])
+
+grpc_package(
+    name = "test/cpp/end2end/xds",
+    visibility = "public",
+)  # Allows external users to implement end2end tests.
+
+grpc_cc_library(
+    name = "xds_server",
+    testonly = True,
+    srcs = ["xds_server.cc"],
+    hdrs = ["xds_server.h"],
+    external_deps = [
+        "gtest",
+    ],
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//:grpc++",
+        "//src/proto/grpc/testing/xds:ads_for_test_proto",
+        "//src/proto/grpc/testing/xds:lrs_for_test_proto",
+        "//src/proto/grpc/testing/xds/v3:ads_proto",
+        "//src/proto/grpc/testing/xds/v3:cluster_proto",
+        "//src/proto/grpc/testing/xds/v3:discovery_proto",
+        "//src/proto/grpc/testing/xds/v3:endpoint_proto",
+        "//src/proto/grpc/testing/xds/v3:listener_proto",
+        "//src/proto/grpc/testing/xds/v3:lrs_proto",
+        "//src/proto/grpc/testing/xds/v3:route_proto",
+        "//test/core/util:grpc_test_util",
+        "//test/cpp/end2end:counted_service",
+    ],
+)
+
+grpc_cc_test(
+    name = "xds_end2end_test",
+    size = "large",
+    srcs = ["xds_end2end_test.cc"],
+    data = [
+        "//src/core/tsi/test_creds:badclient.key",
+        "//src/core/tsi/test_creds:badclient.pem",
+        "//src/core/tsi/test_creds:ca.pem",
+        "//src/core/tsi/test_creds:client.key",
+        "//src/core/tsi/test_creds:client.pem",
+        "//src/core/tsi/test_creds:server1.key",
+        "//src/core/tsi/test_creds:server1.pem",
+    ],
+    external_deps = [
+        "gtest",
+    ],
+    flaky = True,  # TODO(b/144705388)
+    shard_count = 50,
+    tags = [
+        "no_test_ios",
+        "no_windows",
+    ],  # TODO(jtattermusch): fix test on windows
+    deps = [
+        ":xds_server",
+        "//:gpr",
+        "//:grpc",
+        "//:grpc++",
+        "//:grpc_resolver_fake",
+        "//:grpcpp_csds",
+        "//src/proto/grpc/testing:echo_messages_proto",
+        "//src/proto/grpc/testing:echo_proto",
+        "//src/proto/grpc/testing/duplicate:echo_duplicate_proto",
+        "//src/proto/grpc/testing/xds:cds_for_test_proto",
+        "//src/proto/grpc/testing/xds:eds_for_test_proto",
+        "//src/proto/grpc/testing/xds:lds_rds_for_test_proto",
+        "//src/proto/grpc/testing/xds/v3:aggregate_cluster_proto",
+        "//src/proto/grpc/testing/xds/v3:cluster_proto",
+        "//src/proto/grpc/testing/xds/v3:endpoint_proto",
+        "//src/proto/grpc/testing/xds/v3:fault_common_proto",
+        "//src/proto/grpc/testing/xds/v3:fault_proto",
+        "//src/proto/grpc/testing/xds/v3:http_connection_manager_proto",
+        "//src/proto/grpc/testing/xds/v3:listener_proto",
+        "//src/proto/grpc/testing/xds/v3:route_proto",
+        "//src/proto/grpc/testing/xds/v3:router_proto",
+        "//src/proto/grpc/testing/xds/v3:tls_proto",
+        "//test/core/util:grpc_test_util",
+        "//test/cpp/end2end:counted_service",
+        "//test/cpp/end2end:test_service_impl",
+        "//test/cpp/util:test_config",
+        "//test/cpp/util:test_util",
+    ],
+)
+
+grpc_cc_test(
+    name = "xds_credentials_end2end_test",
+    srcs = ["xds_credentials_end2end_test.cc"],
+    external_deps = [
+        "gtest",
+    ],
+    tags = ["no_test_ios"],
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//:grpc++",
+        "//src/proto/grpc/testing:echo_messages_proto",
+        "//src/proto/grpc/testing:echo_proto",
+        "//test/core/util:grpc_test_util",
+        "//test/cpp/end2end:test_service_impl",
+        "//test/cpp/util:test_util",
+    ],
+)
diff --git a/test/cpp/end2end/xds/xds_end2end_test.cc b/test/cpp/end2end/xds/xds_end2end_test.cc
new file mode 100644 (file)
index 0000000..389c996
--- /dev/null
@@ -0,0 +1,12530 @@
+//
+// 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.
+//
+
+// TODO(roth): Split this file up into a common test framework and a set
+// of test files that use that framework.  Need to figure out the best
+// way to split up the tests.  One option would be to split it up by xDS
+// resource type; another approach would be to have all of the "core"
+// xDS functionality in one file and then move specific features to
+// their own files (e.g., mTLS security, fault injection, circuit
+// breaking, etc).
+
+#include <deque>
+#include <memory>
+#include <mutex>
+#include <numeric>
+#include <set>
+#include <sstream>
+#include <string>
+#include <thread>
+#include <vector>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "absl/functional/bind_front.h"
+#include "absl/memory/memory.h"
+#include "absl/strings/match.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/str_join.h"
+#include "absl/types/optional.h"
+
+#include <grpc/grpc.h>
+#include <grpc/grpc_security.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/time.h>
+#include <grpcpp/channel.h>
+#include <grpcpp/client_context.h>
+#include <grpcpp/create_channel.h>
+#include <grpcpp/security/tls_certificate_provider.h>
+#include <grpcpp/server.h>
+#include <grpcpp/server_builder.h>
+#include <grpcpp/xds_server_builder.h>
+
+#include "src/core/ext/filters/client_channel/backup_poller.h"
+#include "src/core/ext/filters/client_channel/lb_policy/xds/xds_channel_args.h"
+#include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h"
+#include "src/core/ext/filters/client_channel/server_address.h"
+#include "src/core/ext/xds/certificate_provider_registry.h"
+#include "src/core/ext/xds/xds_api.h"
+#include "src/core/ext/xds/xds_channel_args.h"
+#include "src/core/ext/xds/xds_client.h"
+#include "src/core/lib/address_utils/parse_address.h"
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/gpr/env.h"
+#include "src/core/lib/gpr/string.h"
+#include "src/core/lib/gpr/time_precise.h"
+#include "src/core/lib/gpr/tmpfile.h"
+#include "src/core/lib/gprpp/ref_counted_ptr.h"
+#include "src/core/lib/gprpp/sync.h"
+#include "src/core/lib/gprpp/time_util.h"
+#include "src/core/lib/iomgr/load_file.h"
+#include "src/core/lib/iomgr/sockaddr.h"
+#include "src/core/lib/security/credentials/fake/fake_credentials.h"
+#include "src/cpp/client/secure_credentials.h"
+#include "src/cpp/server/secure_server_credentials.h"
+#include "src/proto/grpc/testing/echo.grpc.pb.h"
+#include "src/proto/grpc/testing/xds/ads_for_test.grpc.pb.h"
+#include "src/proto/grpc/testing/xds/cds_for_test.grpc.pb.h"
+#include "src/proto/grpc/testing/xds/eds_for_test.grpc.pb.h"
+#include "src/proto/grpc/testing/xds/lds_rds_for_test.grpc.pb.h"
+#include "src/proto/grpc/testing/xds/lrs_for_test.grpc.pb.h"
+#include "src/proto/grpc/testing/xds/v3/ads.grpc.pb.h"
+#include "src/proto/grpc/testing/xds/v3/aggregate_cluster.grpc.pb.h"
+#include "src/proto/grpc/testing/xds/v3/cluster.grpc.pb.h"
+#include "src/proto/grpc/testing/xds/v3/discovery.grpc.pb.h"
+#include "src/proto/grpc/testing/xds/v3/endpoint.grpc.pb.h"
+#include "src/proto/grpc/testing/xds/v3/fault.grpc.pb.h"
+#include "src/proto/grpc/testing/xds/v3/http_connection_manager.grpc.pb.h"
+#include "src/proto/grpc/testing/xds/v3/listener.grpc.pb.h"
+#include "src/proto/grpc/testing/xds/v3/lrs.grpc.pb.h"
+#include "src/proto/grpc/testing/xds/v3/route.grpc.pb.h"
+#include "src/proto/grpc/testing/xds/v3/router.grpc.pb.h"
+#include "src/proto/grpc/testing/xds/v3/tls.grpc.pb.h"
+#include "test/core/util/port.h"
+#include "test/core/util/resolve_localhost_ip46.h"
+#include "test/core/util/test_config.h"
+#include "test/cpp/end2end/counted_service.h"
+#include "test/cpp/end2end/test_service_impl.h"
+#include "test/cpp/end2end/xds/xds_server.h"
+#include "test/cpp/util/test_config.h"
+
+#ifndef DISABLED_XDS_PROTO_IN_CC
+#include "src/cpp/server/csds/csds.h"
+#include "src/proto/grpc/testing/xds/v3/csds.grpc.pb.h"
+#endif  // DISABLED_XDS_PROTO_IN_CC
+
+namespace grpc {
+namespace testing {
+namespace {
+
+using std::chrono::system_clock;
+
+#ifndef DISABLED_XDS_PROTO_IN_CC
+using ::envoy::admin::v3::ClientResourceStatus;
+#endif  // DISABLED_XDS_PROTO_IN_CC
+using ::envoy::config::cluster::v3::CircuitBreakers;
+using ::envoy::config::cluster::v3::Cluster;
+using ::envoy::config::cluster::v3::CustomClusterType;
+using ::envoy::config::cluster::v3::RoutingPriority;
+using ::envoy::config::endpoint::v3::ClusterLoadAssignment;
+using ::envoy::config::endpoint::v3::HealthStatus;
+using ::envoy::config::listener::v3::FilterChainMatch;
+using ::envoy::config::listener::v3::Listener;
+using ::envoy::config::route::v3::RouteConfiguration;
+using ::envoy::extensions::clusters::aggregate::v3::ClusterConfig;
+using ::envoy::extensions::filters::http::fault::v3::HTTPFault;
+using ::envoy::extensions::filters::network::http_connection_manager::v3::
+    HttpConnectionManager;
+using ::envoy::extensions::filters::network::http_connection_manager::v3::
+    HttpFilter;
+using ::envoy::extensions::transport_sockets::tls::v3::DownstreamTlsContext;
+using ::envoy::extensions::transport_sockets::tls::v3::UpstreamTlsContext;
+using ::envoy::type::matcher::v3::StringMatcher;
+using ::envoy::type::v3::FractionalPercent;
+
+using ClientStats = LrsServiceImpl::ClientStats;
+
+constexpr char kDefaultLocalityRegion[] = "xds_default_locality_region";
+constexpr char kDefaultLocalityZone[] = "xds_default_locality_zone";
+constexpr char kLbDropType[] = "lb";
+constexpr char kThrottleDropType[] = "throttle";
+constexpr char kServerName[] = "server.example.com";
+constexpr char kDefaultRouteConfigurationName[] = "route_config_name";
+constexpr char kDefaultServerRouteConfigurationName[] =
+    "default_server_route_config_name";
+constexpr char kDefaultClusterName[] = "cluster_name";
+constexpr char kDefaultEdsServiceName[] = "eds_service_name";
+constexpr int kDefaultLocalityWeight = 3;
+constexpr int kDefaultLocalityPriority = 0;
+
+constexpr char kRequestMessage[] = "Live long and prosper.";
+constexpr char kDefaultServiceConfig[] =
+    "{\n"
+    "  \"loadBalancingConfig\":[\n"
+    "    { \"does_not_exist\":{} },\n"
+    "    { \"xds_cluster_resolver_experimental\":{\n"
+    "      \"discoveryMechanisms\": [\n"
+    "      { \"clusterName\": \"server.example.com\",\n"
+    "        \"type\": \"EDS\",\n"
+    "        \"lrsLoadReportingServerName\": \"\"\n"
+    "      } ]\n"
+    "    } }\n"
+    "  ]\n"
+    "}";
+constexpr char kDefaultServiceConfigWithoutLoadReporting[] =
+    "{\n"
+    "  \"loadBalancingConfig\":[\n"
+    "    { \"does_not_exist\":{} },\n"
+    "    { \"xds_cluster_resolver_experimental\":{\n"
+    "      \"discoveryMechanisms\": [\n"
+    "      { \"clusterName\": \"server.example.com\",\n"
+    "        \"type\": \"EDS\"\n"
+    "      } ]\n"
+    "    } }\n"
+    "  ]\n"
+    "}";
+
+constexpr char kBootstrapFileV3[] =
+    "{\n"
+    "  \"xds_servers\": [\n"
+    "    {\n"
+    "      \"server_uri\": \"fake:///xds_server\",\n"
+    "      \"channel_creds\": [\n"
+    "        {\n"
+    "          \"type\": \"fake\"\n"
+    "        }\n"
+    "      ],\n"
+    "      \"server_features\": [\"xds_v3\"]\n"
+    "    }\n"
+    "  ],\n"
+    "  \"node\": {\n"
+    "    \"id\": \"xds_end2end_test\",\n"
+    "    \"cluster\": \"test\",\n"
+    "    \"metadata\": {\n"
+    "      \"foo\": \"bar\"\n"
+    "    },\n"
+    "    \"locality\": {\n"
+    "      \"region\": \"corp\",\n"
+    "      \"zone\": \"svl\",\n"
+    "      \"sub_zone\": \"mp3\"\n"
+    "    }\n"
+    "  },\n"
+    "  \"server_listener_resource_name_template\": "
+    "\"grpc/server?xds.resource.listening_address=%s\",\n"
+    "  \"certificate_providers\": {\n"
+    "    \"fake_plugin1\": {\n"
+    "      \"plugin_name\": \"fake1\"\n"
+    "    },\n"
+    "    \"fake_plugin2\": {\n"
+    "      \"plugin_name\": \"fake2\"\n"
+    "    },\n"
+    "    \"file_plugin\": {\n"
+    "      \"plugin_name\": \"file_watcher\",\n"
+    "      \"config\": {\n"
+    "        \"certificate_file\": \"src/core/tsi/test_creds/client.pem\",\n"
+    "        \"private_key_file\": \"src/core/tsi/test_creds/client.key\",\n"
+    "        \"ca_certificate_file\": \"src/core/tsi/test_creds/ca.pem\"\n"
+    "      }"
+    "    }\n"
+    "  }\n"
+    "}\n";
+
+constexpr char kBootstrapFileV2[] =
+    "{\n"
+    "  \"xds_servers\": [\n"
+    "    {\n"
+    "      \"server_uri\": \"fake:///xds_server\",\n"
+    "      \"channel_creds\": [\n"
+    "        {\n"
+    "          \"type\": \"fake\"\n"
+    "        }\n"
+    "      ]\n"
+    "    }\n"
+    "  ],\n"
+    "  \"node\": {\n"
+    "    \"id\": \"xds_end2end_test\",\n"
+    "    \"cluster\": \"test\",\n"
+    "    \"metadata\": {\n"
+    "      \"foo\": \"bar\"\n"
+    "    },\n"
+    "    \"locality\": {\n"
+    "      \"region\": \"corp\",\n"
+    "      \"zone\": \"svl\",\n"
+    "      \"sub_zone\": \"mp3\"\n"
+    "    }\n"
+    "  }\n"
+    "}\n";
+constexpr char kCaCertPath[] = "src/core/tsi/test_creds/ca.pem";
+constexpr char kServerCertPath[] = "src/core/tsi/test_creds/server1.pem";
+constexpr char kServerKeyPath[] = "src/core/tsi/test_creds/server1.key";
+constexpr char kClientCertPath[] = "src/core/tsi/test_creds/client.pem";
+constexpr char kClientKeyPath[] = "src/core/tsi/test_creds/client.key";
+constexpr char kBadClientCertPath[] = "src/core/tsi/test_creds/badclient.pem";
+constexpr char kBadClientKeyPath[] = "src/core/tsi/test_creds/badclient.key";
+
+char* g_bootstrap_file_v3;
+char* g_bootstrap_file_v2;
+
+void WriteBootstrapFiles() {
+  char* bootstrap_file;
+  FILE* out = gpr_tmpfile("xds_bootstrap_v3", &bootstrap_file);
+  fputs(kBootstrapFileV3, out);
+  fclose(out);
+  g_bootstrap_file_v3 = bootstrap_file;
+  out = gpr_tmpfile("xds_bootstrap_v2", &bootstrap_file);
+  fputs(kBootstrapFileV2, out);
+  fclose(out);
+  g_bootstrap_file_v2 = bootstrap_file;
+}
+
+template <typename RpcService>
+class BackendServiceImpl
+    : public CountedService<TestMultipleServiceImpl<RpcService>> {
+ public:
+  BackendServiceImpl() {}
+
+  Status Echo(ServerContext* context, const EchoRequest* request,
+              EchoResponse* response) override {
+    auto peer_identity = context->auth_context()->GetPeerIdentity();
+    CountedService<TestMultipleServiceImpl<RpcService>>::IncreaseRequestCount();
+    const auto status =
+        TestMultipleServiceImpl<RpcService>::Echo(context, request, response);
+    CountedService<
+        TestMultipleServiceImpl<RpcService>>::IncreaseResponseCount();
+    {
+      grpc_core::MutexLock lock(&mu_);
+      clients_.insert(context->peer());
+      last_peer_identity_.clear();
+      for (const auto& entry : peer_identity) {
+        last_peer_identity_.emplace_back(entry.data(), entry.size());
+      }
+    }
+    return status;
+  }
+
+  Status Echo1(ServerContext* context, const EchoRequest* request,
+               EchoResponse* response) override {
+    return Echo(context, request, response);
+  }
+
+  Status Echo2(ServerContext* context, const EchoRequest* request,
+               EchoResponse* response) override {
+    return Echo(context, request, response);
+  }
+
+  void Start() {}
+  void Shutdown() {}
+
+  std::set<std::string> clients() {
+    grpc_core::MutexLock lock(&mu_);
+    return clients_;
+  }
+
+  const std::vector<std::string>& last_peer_identity() {
+    grpc_core::MutexLock lock(&mu_);
+    return last_peer_identity_;
+  }
+
+ private:
+  grpc_core::Mutex mu_;
+  std::set<std::string> clients_ ABSL_GUARDED_BY(mu_);
+  std::vector<std::string> last_peer_identity_ ABSL_GUARDED_BY(mu_);
+};
+
+class TestType {
+ public:
+  enum FilterConfigSetup {
+    // Set the fault injection filter directly from LDS
+    kHTTPConnectionManagerOriginal,
+    // Enable the fault injection filter in LDS, but override the filter config
+    // in route.
+    kRouteOverride,
+  };
+
+  enum BootstrapSource {
+    kBootstrapFromChannelArg,
+    kBootstrapFromFile,
+    kBootstrapFromEnvVar,
+  };
+
+  TestType& set_use_fake_resolver() {
+    use_fake_resolver_ = true;
+    return *this;
+  }
+
+  TestType& set_enable_load_reporting() {
+    enable_load_reporting_ = true;
+    return *this;
+  }
+
+  TestType& set_enable_rds_testing() {
+    enable_rds_testing_ = true;
+    return *this;
+  }
+
+  TestType& set_use_v2() {
+    use_v2_ = true;
+    return *this;
+  }
+
+  TestType& set_use_xds_credentials() {
+    use_xds_credentials_ = true;
+    return *this;
+  }
+
+  TestType& set_use_csds_streaming() {
+    use_csds_streaming_ = true;
+    return *this;
+  }
+
+  TestType& set_filter_config_setup(FilterConfigSetup setup) {
+    filter_config_setup_ = setup;
+    return *this;
+  }
+
+  TestType& set_bootstrap_source(BootstrapSource bootstrap_source) {
+    bootstrap_source_ = bootstrap_source;
+    return *this;
+  }
+
+  bool use_fake_resolver() const { return use_fake_resolver_; }
+  bool enable_load_reporting() const { return enable_load_reporting_; }
+  bool enable_rds_testing() const { return enable_rds_testing_; }
+  bool use_v2() const { return use_v2_; }
+  bool use_xds_credentials() const { return use_xds_credentials_; }
+  bool use_csds_streaming() const { return use_csds_streaming_; }
+  FilterConfigSetup filter_config_setup() const { return filter_config_setup_; }
+  BootstrapSource bootstrap_source() const { return bootstrap_source_; }
+
+  std::string AsString() const {
+    std::string retval = (use_fake_resolver_ ? "FakeResolver" : "XdsResolver");
+    retval += (use_v2_ ? "V2" : "V3");
+    if (enable_load_reporting_) retval += "WithLoadReporting";
+    if (enable_rds_testing_) retval += "Rds";
+    if (use_xds_credentials_) retval += "XdsCreds";
+    if (use_csds_streaming_) retval += "CsdsStreaming";
+    if (filter_config_setup_ == kRouteOverride) {
+      retval += "FilterPerRouteOverride";
+    }
+    if (bootstrap_source_ == kBootstrapFromFile) {
+      retval += "BootstrapFromFile";
+    } else if (bootstrap_source_ == kBootstrapFromEnvVar) {
+      retval += "BootstrapFromEnvVar";
+    }
+    return retval;
+  }
+
+ private:
+  bool use_fake_resolver_ = false;
+  bool enable_load_reporting_ = false;
+  bool enable_rds_testing_ = false;
+  bool use_v2_ = false;
+  bool use_xds_credentials_ = false;
+  bool use_csds_streaming_ = false;
+  FilterConfigSetup filter_config_setup_ = kHTTPConnectionManagerOriginal;
+  BootstrapSource bootstrap_source_ = kBootstrapFromChannelArg;
+};
+
+std::string ReadFile(const char* file_path) {
+  grpc_slice slice;
+  GPR_ASSERT(
+      GRPC_LOG_IF_ERROR("load_file", grpc_load_file(file_path, 0, &slice)));
+  std::string file_contents(grpc_core::StringViewFromSlice(slice));
+  grpc_slice_unref(slice);
+  return file_contents;
+}
+
+grpc_core::PemKeyCertPairList ReadTlsIdentityPair(const char* key_path,
+                                                  const char* cert_path) {
+  return grpc_core::PemKeyCertPairList{
+      grpc_core::PemKeyCertPair(ReadFile(key_path), ReadFile(cert_path))};
+}
+
+// Based on StaticDataCertificateProvider, but provides alternate certificates
+// if the certificate name is not empty.
+class FakeCertificateProvider final : public grpc_tls_certificate_provider {
+ public:
+  struct CertData {
+    std::string root_certificate;
+    grpc_core::PemKeyCertPairList identity_key_cert_pairs;
+  };
+
+  using CertDataMap = std::map<std::string /*cert_name */, CertData>;
+
+  explicit FakeCertificateProvider(CertDataMap cert_data_map)
+      : distributor_(
+            grpc_core::MakeRefCounted<grpc_tls_certificate_distributor>()),
+        cert_data_map_(std::move(cert_data_map)) {
+    distributor_->SetWatchStatusCallback([this](std::string cert_name,
+                                                bool root_being_watched,
+                                                bool identity_being_watched) {
+      if (!root_being_watched && !identity_being_watched) return;
+      auto it = cert_data_map_.find(cert_name);
+      if (it == cert_data_map_.end()) {
+        grpc_error_handle error =
+            GRPC_ERROR_CREATE_FROM_CPP_STRING(absl::StrCat(
+                "No certificates available for cert_name \"", cert_name, "\""));
+        distributor_->SetErrorForCert(cert_name, GRPC_ERROR_REF(error),
+                                      GRPC_ERROR_REF(error));
+        GRPC_ERROR_UNREF(error);
+      } else {
+        absl::optional<std::string> root_certificate;
+        absl::optional<grpc_core::PemKeyCertPairList> pem_key_cert_pairs;
+        if (root_being_watched) {
+          root_certificate = it->second.root_certificate;
+        }
+        if (identity_being_watched) {
+          pem_key_cert_pairs = it->second.identity_key_cert_pairs;
+        }
+        distributor_->SetKeyMaterials(cert_name, std::move(root_certificate),
+                                      std::move(pem_key_cert_pairs));
+      }
+    });
+  }
+
+  ~FakeCertificateProvider() override {
+    distributor_->SetWatchStatusCallback(nullptr);
+  }
+
+  grpc_core::RefCountedPtr<grpc_tls_certificate_distributor> distributor()
+      const override {
+    return distributor_;
+  }
+
+ private:
+  grpc_core::RefCountedPtr<grpc_tls_certificate_distributor> distributor_;
+  CertDataMap cert_data_map_;
+};
+
+class FakeCertificateProviderFactory
+    : public grpc_core::CertificateProviderFactory {
+ public:
+  class Config : public grpc_core::CertificateProviderFactory::Config {
+   public:
+    explicit Config(const char* name) : name_(name) {}
+
+    const char* name() const override { return name_; }
+
+    std::string ToString() const override { return "{}"; }
+
+   private:
+    const char* name_;
+  };
+
+  FakeCertificateProviderFactory(
+      const char* name, FakeCertificateProvider::CertDataMap** cert_data_map)
+      : name_(name), cert_data_map_(cert_data_map) {
+    GPR_ASSERT(cert_data_map != nullptr);
+  }
+
+  const char* name() const override { return name_; }
+
+  grpc_core::RefCountedPtr<grpc_core::CertificateProviderFactory::Config>
+  CreateCertificateProviderConfig(const grpc_core::Json& /*config_json*/,
+                                  grpc_error_handle* /*error*/) override {
+    return grpc_core::MakeRefCounted<Config>(name_);
+  }
+
+  grpc_core::RefCountedPtr<grpc_tls_certificate_provider>
+  CreateCertificateProvider(
+      grpc_core::RefCountedPtr<grpc_core::CertificateProviderFactory::Config>
+      /*config*/) override {
+    if (*cert_data_map_ == nullptr) return nullptr;
+    return grpc_core::MakeRefCounted<FakeCertificateProvider>(**cert_data_map_);
+  }
+
+ private:
+  const char* name_;
+  FakeCertificateProvider::CertDataMap** cert_data_map_;
+};
+
+// Global variables for each provider.
+FakeCertificateProvider::CertDataMap* g_fake1_cert_data_map = nullptr;
+FakeCertificateProvider::CertDataMap* g_fake2_cert_data_map = nullptr;
+
+int ServerAuthCheckSchedule(void* /* config_user_data */,
+                            grpc_tls_server_authorization_check_arg* arg) {
+  arg->success = 1;
+  arg->status = GRPC_STATUS_OK;
+  return 0; /* synchronous check */
+}
+
+std::shared_ptr<ChannelCredentials> CreateTlsFallbackCredentials() {
+  // TODO(yashykt): Switch to using C++ API once b/173823806 is fixed.
+  grpc_tls_credentials_options* options = grpc_tls_credentials_options_create();
+  grpc_tls_credentials_options_set_server_verification_option(
+      options, GRPC_TLS_SKIP_HOSTNAME_VERIFICATION);
+  grpc_tls_credentials_options_set_certificate_provider(
+      options,
+      grpc_core::MakeRefCounted<grpc_core::StaticDataCertificateProvider>(
+          ReadFile(kCaCertPath),
+          ReadTlsIdentityPair(kServerKeyPath, kServerCertPath))
+          .get());
+  grpc_tls_credentials_options_watch_root_certs(options);
+  grpc_tls_credentials_options_watch_identity_key_cert_pairs(options);
+  grpc_tls_server_authorization_check_config* check_config =
+      grpc_tls_server_authorization_check_config_create(
+          nullptr, ServerAuthCheckSchedule, nullptr, nullptr);
+  grpc_tls_credentials_options_set_server_authorization_check_config(
+      options, check_config);
+  auto channel_creds = std::make_shared<SecureChannelCredentials>(
+      grpc_tls_credentials_create(options));
+  grpc_tls_server_authorization_check_config_release(check_config);
+  return channel_creds;
+}
+
+// A No-op HTTP filter used for verifying parsing logic.
+class NoOpHttpFilter : public grpc_core::XdsHttpFilterImpl {
+ public:
+  NoOpHttpFilter(std::string name, bool supported_on_clients,
+                 bool supported_on_servers, bool is_terminal_filter)
+      : name_(std::move(name)),
+        supported_on_clients_(supported_on_clients),
+        supported_on_servers_(supported_on_servers),
+        is_terminal_filter_(is_terminal_filter) {}
+
+  void PopulateSymtab(upb_symtab* /* symtab */) const override {}
+
+  absl::StatusOr<grpc_core::XdsHttpFilterImpl::FilterConfig>
+  GenerateFilterConfig(upb_strview /* serialized_filter_config */,
+                       upb_arena* /* arena */) const override {
+    return grpc_core::XdsHttpFilterImpl::FilterConfig{name_, grpc_core::Json()};
+  }
+
+  absl::StatusOr<grpc_core::XdsHttpFilterImpl::FilterConfig>
+  GenerateFilterConfigOverride(upb_strview /*serialized_filter_config*/,
+                               upb_arena* /*arena*/) const override {
+    return grpc_core::XdsHttpFilterImpl::FilterConfig{name_, grpc_core::Json()};
+  }
+
+  const grpc_channel_filter* channel_filter() const override { return nullptr; }
+
+  absl::StatusOr<grpc_core::XdsHttpFilterImpl::ServiceConfigJsonEntry>
+  GenerateServiceConfig(
+      const FilterConfig& /*hcm_filter_config*/,
+      const FilterConfig* /*filter_config_override*/) const override {
+    return grpc_core::XdsHttpFilterImpl::ServiceConfigJsonEntry{name_, ""};
+  }
+
+  bool IsSupportedOnClients() const override { return supported_on_clients_; }
+
+  bool IsSupportedOnServers() const override { return supported_on_servers_; }
+
+  bool IsTerminalFilter() const override { return is_terminal_filter_; }
+
+ private:
+  const std::string name_;
+  const bool supported_on_clients_;
+  const bool supported_on_servers_;
+  const bool is_terminal_filter_;
+};
+
+// There is slight difference between time fetched by GPR and by C++ system
+// clock API. It's unclear if they are using the same syscall, but we do know
+// GPR round the number at millisecond-level. This creates a 1ms difference,
+// which could cause flake.
+grpc_millis NowFromCycleCounter() {
+  return grpc_timespec_to_millis_round_down(gpr_now(GPR_CLOCK_MONOTONIC));
+}
+
+// Returns the number of RPCs needed to pass error_tolerance at 99.99994%
+// chance. Rolling dices in drop/fault-injection generates a binomial
+// distribution (if our code is not horribly wrong). Let's make "n" the number
+// of samples, "p" the probability. If we have np>5 & n(1-p)>5, we can
+// approximately treat the binomial distribution as a normal distribution.
+//
+// For normal distribution, we can easily look up how many standard deviation we
+// need to reach 99.995%. Based on Wiki's table
+// https://en.wikipedia.org/wiki/68%E2%80%9395%E2%80%9399.7_rule, we need 5.00
+// sigma (standard deviation) to cover the probability area of 99.99994%. In
+// another word, for a sample with size "n" probability "p" error-tolerance "k",
+// we want the error always land within 5.00 sigma. The sigma of binominal
+// distribution and be computed as sqrt(np(1-p)). Hence, we have the equation:
+//
+//   kn <= 5.00 * sqrt(np(1-p))
+size_t ComputeIdealNumRpcs(double p, double error_tolerance) {
+  GPR_ASSERT(p >= 0 && p <= 1);
+  size_t num_rpcs =
+      ceil(p * (1 - p) * 5.00 * 5.00 / error_tolerance / error_tolerance);
+  gpr_log(GPR_INFO,
+          "Sending %" PRIuPTR " RPCs for percentage=%.3f error_tolerance=%.3f",
+          num_rpcs, p, error_tolerance);
+  return num_rpcs;
+}
+
+// Channel arg pointer vtable for storing xDS channel args in the parent
+// channel's channel args.
+void* ChannelArgsArgCopy(void* p) {
+  auto* args = static_cast<grpc_channel_args*>(p);
+  return grpc_channel_args_copy(args);
+}
+void ChannelArgsArgDestroy(void* p) {
+  auto* args = static_cast<grpc_channel_args*>(p);
+  grpc_channel_args_destroy(args);
+}
+int ChannelArgsArgCmp(void* a, void* b) {
+  auto* args_a = static_cast<grpc_channel_args*>(a);
+  auto* args_b = static_cast<grpc_channel_args*>(b);
+  return grpc_channel_args_compare(args_a, args_b);
+}
+const grpc_arg_pointer_vtable kChannelArgsArgVtable = {
+    ChannelArgsArgCopy, ChannelArgsArgDestroy, ChannelArgsArgCmp};
+
+class XdsEnd2endTest : public ::testing::TestWithParam<TestType> {
+ protected:
+  // TODO(roth): We currently set the number of backends and number of
+  // balancers on a per-test-suite basis, not a per-test-case basis.
+  // However, not every individual test case in a given test suite uses
+  // the same number of backends or balancers, so we wind up having to
+  // set the numbers for the test suite to the max number needed by any
+  // one test case in that test suite.  This results in starting more
+  // servers (and using more ports) than we actually need.  When we have
+  // time, change each test to directly start the number of backends and
+  // balancers that it needs, so that we aren't wasting resources.
+  XdsEnd2endTest(size_t num_backends, size_t num_balancers,
+                 int client_load_reporting_interval_seconds = 100,
+                 bool use_xds_enabled_server = false)
+      : num_backends_(num_backends),
+        num_balancers_(num_balancers),
+        client_load_reporting_interval_seconds_(
+            client_load_reporting_interval_seconds),
+        use_xds_enabled_server_(use_xds_enabled_server) {}
+
+  void SetUp() override {
+    bool localhost_resolves_to_ipv4 = false;
+    bool localhost_resolves_to_ipv6 = false;
+    grpc_core::LocalhostResolves(&localhost_resolves_to_ipv4,
+                                 &localhost_resolves_to_ipv6);
+    ipv6_only_ = !localhost_resolves_to_ipv4 && localhost_resolves_to_ipv6;
+    // Initialize default xDS resources.
+    // Construct LDS resource.
+    default_listener_.set_name(kServerName);
+    HttpConnectionManager http_connection_manager;
+    if (!GetParam().use_v2()) {
+      auto* filter = http_connection_manager.add_http_filters();
+      filter->set_name("router");
+      filter->mutable_typed_config()->PackFrom(
+          envoy::extensions::filters::http::router::v3::Router());
+    }
+    default_listener_.mutable_api_listener()->mutable_api_listener()->PackFrom(
+        http_connection_manager);
+    // Construct RDS resource.
+    default_route_config_.set_name(kDefaultRouteConfigurationName);
+    auto* virtual_host = default_route_config_.add_virtual_hosts();
+    virtual_host->add_domains("*");
+    auto* route = virtual_host->add_routes();
+    route->mutable_match()->set_prefix("");
+    route->mutable_route()->set_cluster(kDefaultClusterName);
+    // Construct CDS resource.
+    default_cluster_.set_name(kDefaultClusterName);
+    default_cluster_.set_type(Cluster::EDS);
+    auto* eds_config = default_cluster_.mutable_eds_cluster_config();
+    eds_config->mutable_eds_config()->mutable_ads();
+    eds_config->set_service_name(kDefaultEdsServiceName);
+    default_cluster_.set_lb_policy(Cluster::ROUND_ROBIN);
+    if (GetParam().enable_load_reporting()) {
+      default_cluster_.mutable_lrs_server()->mutable_self();
+    }
+    // Construct a default server-side RDS resource for tests to use.
+    default_server_route_config_.set_name(kDefaultServerRouteConfigurationName);
+    virtual_host = default_server_route_config_.add_virtual_hosts();
+    virtual_host->add_domains("*");
+    route = virtual_host->add_routes();
+    route->mutable_match()->set_prefix("");
+    route->mutable_non_forwarding_action();
+    // Construct a default server-side Listener resource
+    default_server_listener_.mutable_address()
+        ->mutable_socket_address()
+        ->set_address(ipv6_only_ ? "::1" : "127.0.0.1");
+    default_server_listener_.mutable_default_filter_chain()
+        ->add_filters()
+        ->mutable_typed_config()
+        ->PackFrom(http_connection_manager);
+    // Create the backends but don't start them yet. We need to create the
+    // backends to allocate the ports, so that we know what resource names to
+    // populate in the xDS servers when we start them. However, we can't start
+    // the backends until after we've started the xDS servers, because in the
+    // tests that use xDS-enabled servers, the backends will try to contact the
+    // xDS servers as soon as they start up.
+    for (size_t i = 0; i < num_backends_; ++i) {
+      backends_.emplace_back(
+          new BackendServerThread(this, use_xds_enabled_server_));
+    }
+    // Start the load balancers.
+    for (size_t i = 0; i < num_balancers_; ++i) {
+      balancers_.emplace_back(new BalancerServerThread(
+          this, GetParam().enable_load_reporting()
+                    ? client_load_reporting_interval_seconds_
+                    : 0));
+      balancers_.back()->Start();
+      // Initialize resources.
+      SetListenerAndRouteConfiguration(i, default_listener_,
+                                       default_route_config_);
+      if (use_xds_enabled_server_) {
+        for (const auto& backend : backends_) {
+          SetServerListenerNameAndRouteConfiguration(
+              i, default_server_listener_, backend->port(),
+              default_server_route_config_);
+        }
+      }
+      balancers_.back()->ads_service()->SetCdsResource(default_cluster_);
+    }
+    // Create fake resolver response generators used by client.
+    if (GetParam().use_fake_resolver()) {
+      response_generator_ =
+          grpc_core::MakeRefCounted<grpc_core::FakeResolverResponseGenerator>();
+    }
+    logical_dns_cluster_resolver_response_generator_ =
+        grpc_core::MakeRefCounted<grpc_core::FakeResolverResponseGenerator>();
+    lb_channel_response_generator_ =
+        grpc_core::MakeRefCounted<grpc_core::FakeResolverResponseGenerator>();
+    // Construct channel args for XdsClient.
+    xds_channel_args_to_add_.emplace_back(
+        grpc_core::FakeResolverResponseGenerator::MakeChannelArg(
+            lb_channel_response_generator_.get()));
+    if (xds_resource_does_not_exist_timeout_ms_ > 0) {
+      xds_channel_args_to_add_.emplace_back(grpc_channel_arg_integer_create(
+          const_cast<char*>(GRPC_ARG_XDS_RESOURCE_DOES_NOT_EXIST_TIMEOUT_MS),
+          xds_resource_does_not_exist_timeout_ms_));
+    }
+    xds_channel_args_.num_args = xds_channel_args_to_add_.size();
+    xds_channel_args_.args = xds_channel_args_to_add_.data();
+    // Initialize XdsClient state.
+    // TODO(roth): Consider changing this to dynamically generate the
+    // bootstrap config in each individual test instead of hard-coding
+    // the contents here.  That would allow us to use an ipv4: or ipv6:
+    // URI for the xDS server instead of using the fake resolver.
+    if (GetParam().bootstrap_source() == TestType::kBootstrapFromEnvVar) {
+      gpr_setenv("GRPC_XDS_BOOTSTRAP_CONFIG",
+                 GetParam().use_v2() ? kBootstrapFileV2 : kBootstrapFileV3);
+    } else if (GetParam().bootstrap_source() == TestType::kBootstrapFromFile) {
+      gpr_setenv("GRPC_XDS_BOOTSTRAP", GetParam().use_v2()
+                                           ? g_bootstrap_file_v2
+                                           : g_bootstrap_file_v3);
+    }
+    if (GetParam().bootstrap_source() != TestType::kBootstrapFromChannelArg) {
+      // If getting bootstrap from channel arg, we'll pass these args in
+      // via the parent channel args in CreateChannel() instead.
+      grpc_core::internal::SetXdsChannelArgsForTest(&xds_channel_args_);
+      // Make sure each test creates a new XdsClient instance rather than
+      // reusing the one from the previous test.  This avoids spurious failures
+      // caused when a load reporting test runs after a non-load reporting test
+      // and the XdsClient is still talking to the old LRS server, which fails
+      // because it's not expecting the client to connect.  It also
+      // ensures that each test can independently set the global channel
+      // args for the xDS channel.
+      grpc_core::internal::UnsetGlobalXdsClientForTest();
+    }
+    // Start the backends
+    for (const auto& backend : backends_) {
+      backend->Start();
+    }
+    // Create channel and stub.
+    ResetStub();
+  }
+
+  const char* DefaultEdsServiceName() const {
+    return GetParam().use_fake_resolver() ? kServerName
+                                          : kDefaultEdsServiceName;
+  }
+
+  void TearDown() override {
+    ShutdownAllBackends();
+    for (auto& balancer : balancers_) balancer->Shutdown();
+    // Clear global xDS channel args, since they will go out of scope
+    // when this test object is destroyed.
+    grpc_core::internal::SetXdsChannelArgsForTest(nullptr);
+    gpr_unsetenv("GRPC_XDS_BOOTSTRAP");
+    gpr_unsetenv("GRPC_XDS_BOOTSTRAP_CONFIG");
+  }
+
+  void StartAllBackends() {
+    for (auto& backend : backends_) backend->Start();
+  }
+
+  void StartBackend(size_t index) { backends_[index]->Start(); }
+
+  void ShutdownAllBackends() {
+    for (auto& backend : backends_) backend->Shutdown();
+  }
+
+  void ShutdownBackend(size_t index) { backends_[index]->Shutdown(); }
+
+  void ResetStub(int failover_timeout = 0) {
+    channel_ = CreateChannel(failover_timeout);
+    stub_ = grpc::testing::EchoTestService::NewStub(channel_);
+    stub1_ = grpc::testing::EchoTest1Service::NewStub(channel_);
+    stub2_ = grpc::testing::EchoTest2Service::NewStub(channel_);
+  }
+
+  std::shared_ptr<Channel> CreateChannel(
+      int failover_timeout = 0, const char* server_name = kServerName,
+      grpc_core::FakeResolverResponseGenerator* response_generator = nullptr,
+      grpc_channel_args* xds_channel_args = nullptr) {
+    ChannelArguments args;
+    if (failover_timeout > 0) {
+      args.SetInt(GRPC_ARG_PRIORITY_FAILOVER_TIMEOUT_MS, failover_timeout);
+    }
+    // If the parent channel is using the fake resolver, we inject the
+    // response generator here.
+    if (GetParam().use_fake_resolver()) {
+      if (response_generator == nullptr) {
+        response_generator = response_generator_.get();
+      }
+      args.SetPointerWithVtable(
+          GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR, response_generator,
+          &grpc_core::FakeResolverResponseGenerator::kChannelArgPointerVtable);
+    }
+    if (GetParam().bootstrap_source() == TestType::kBootstrapFromChannelArg) {
+      // We're getting the bootstrap from a channel arg, so we do the
+      // same thing for the response generator to use for the xDS
+      // channel and the xDS resource-does-not-exist timeout value.
+      args.SetString(GRPC_ARG_TEST_ONLY_DO_NOT_USE_IN_PROD_XDS_BOOTSTRAP_CONFIG,
+                     GetParam().use_v2() ? kBootstrapFileV2 : kBootstrapFileV3);
+      if (xds_channel_args == nullptr) xds_channel_args = &xds_channel_args_;
+      args.SetPointerWithVtable(
+          GRPC_ARG_TEST_ONLY_DO_NOT_USE_IN_PROD_XDS_CLIENT_CHANNEL_ARGS,
+          xds_channel_args, &kChannelArgsArgVtable);
+    }
+    args.SetPointerWithVtable(
+        GRPC_ARG_XDS_LOGICAL_DNS_CLUSTER_FAKE_RESOLVER_RESPONSE_GENERATOR,
+        logical_dns_cluster_resolver_response_generator_.get(),
+        &grpc_core::FakeResolverResponseGenerator::kChannelArgPointerVtable);
+    std::string uri = absl::StrCat(
+        GetParam().use_fake_resolver() ? "fake" : "xds", ":///", server_name);
+    std::shared_ptr<ChannelCredentials> channel_creds =
+        GetParam().use_xds_credentials()
+            ? XdsCredentials(CreateTlsFallbackCredentials())
+            : std::make_shared<SecureChannelCredentials>(
+                  grpc_fake_transport_security_credentials_create());
+    return ::grpc::CreateCustomChannel(uri, channel_creds, args);
+  }
+
+  enum RpcService {
+    SERVICE_ECHO,
+    SERVICE_ECHO1,
+    SERVICE_ECHO2,
+  };
+
+  enum RpcMethod {
+    METHOD_ECHO,
+    METHOD_ECHO1,
+    METHOD_ECHO2,
+  };
+
+  struct RpcOptions {
+    RpcService service = SERVICE_ECHO;
+    RpcMethod method = METHOD_ECHO;
+    int timeout_ms = 1000;
+    bool wait_for_ready = false;
+    bool server_fail = false;
+    std::vector<std::pair<std::string, std::string>> metadata;
+    int server_sleep_us = 0;
+    int client_cancel_after_us = 0;
+    bool skip_cancelled_check = false;
+    StatusCode server_expected_error = StatusCode::OK;
+
+    RpcOptions() {}
+
+    RpcOptions& set_rpc_service(RpcService rpc_service) {
+      service = rpc_service;
+      return *this;
+    }
+
+    RpcOptions& set_rpc_method(RpcMethod rpc_method) {
+      method = rpc_method;
+      return *this;
+    }
+
+    RpcOptions& set_timeout_ms(int rpc_timeout_ms) {
+      timeout_ms = rpc_timeout_ms;
+      return *this;
+    }
+
+    RpcOptions& set_wait_for_ready(bool rpc_wait_for_ready) {
+      wait_for_ready = rpc_wait_for_ready;
+      return *this;
+    }
+
+    RpcOptions& set_server_fail(bool rpc_server_fail) {
+      server_fail = rpc_server_fail;
+      return *this;
+    }
+
+    RpcOptions& set_skip_cancelled_check(bool rpc_skip_cancelled_check) {
+      skip_cancelled_check = rpc_skip_cancelled_check;
+      return *this;
+    }
+
+    RpcOptions& set_metadata(
+        std::vector<std::pair<std::string, std::string>> rpc_metadata) {
+      metadata = std::move(rpc_metadata);
+      return *this;
+    }
+
+    RpcOptions& set_server_sleep_us(int rpc_server_sleep_us) {
+      server_sleep_us = rpc_server_sleep_us;
+      return *this;
+    }
+
+    RpcOptions& set_client_cancel_after_us(int rpc_client_cancel_after_us) {
+      client_cancel_after_us = rpc_client_cancel_after_us;
+      return *this;
+    }
+
+    RpcOptions& set_server_expected_error(StatusCode code) {
+      server_expected_error = code;
+      return *this;
+    }
+
+    // Populates context and request.
+    void SetupRpc(ClientContext* context, EchoRequest* request) const {
+      for (const auto& item : metadata) {
+        context->AddMetadata(item.first, item.second);
+      }
+      if (timeout_ms != 0) {
+        context->set_deadline(
+            grpc_timeout_milliseconds_to_deadline(timeout_ms));
+      }
+      if (wait_for_ready) context->set_wait_for_ready(true);
+      request->set_message(kRequestMessage);
+      if (server_fail) {
+        request->mutable_param()->mutable_expected_error()->set_code(
+            GRPC_STATUS_FAILED_PRECONDITION);
+      }
+      if (server_sleep_us != 0) {
+        request->mutable_param()->set_server_sleep_us(server_sleep_us);
+      }
+      if (client_cancel_after_us != 0) {
+        request->mutable_param()->set_client_cancel_after_us(
+            client_cancel_after_us);
+      }
+      if (skip_cancelled_check) {
+        request->mutable_param()->set_skip_cancelled_check(true);
+      }
+    }
+  };
+
+  template <typename Stub>
+  Status SendRpcMethod(Stub* stub, const RpcOptions& rpc_options,
+                       ClientContext* context, EchoRequest& request,
+                       EchoResponse* response) {
+    switch (rpc_options.method) {
+      case METHOD_ECHO:
+        return (*stub)->Echo(context, request, response);
+      case METHOD_ECHO1:
+        return (*stub)->Echo1(context, request, response);
+      case METHOD_ECHO2:
+        return (*stub)->Echo2(context, request, response);
+    }
+    GPR_UNREACHABLE_CODE();
+  }
+
+  void ResetBackendCounters(size_t start_index = 0, size_t stop_index = 0) {
+    if (stop_index == 0) stop_index = backends_.size();
+    for (size_t i = start_index; i < stop_index; ++i) {
+      backends_[i]->backend_service()->ResetCounters();
+      backends_[i]->backend_service1()->ResetCounters();
+      backends_[i]->backend_service2()->ResetCounters();
+    }
+  }
+
+  bool SeenBackend(size_t backend_idx,
+                   const RpcService rpc_service = SERVICE_ECHO) {
+    switch (rpc_service) {
+      case SERVICE_ECHO:
+        if (backends_[backend_idx]->backend_service()->request_count() == 0) {
+          return false;
+        }
+        break;
+      case SERVICE_ECHO1:
+        if (backends_[backend_idx]->backend_service1()->request_count() == 0) {
+          return false;
+        }
+        break;
+      case SERVICE_ECHO2:
+        if (backends_[backend_idx]->backend_service2()->request_count() == 0) {
+          return false;
+        }
+        break;
+    }
+    return true;
+  }
+
+  bool SeenAllBackends(size_t start_index = 0, size_t stop_index = 0,
+                       const RpcService rpc_service = SERVICE_ECHO) {
+    if (stop_index == 0) stop_index = backends_.size();
+    for (size_t i = start_index; i < stop_index; ++i) {
+      if (!SeenBackend(i, rpc_service)) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  void SendRpcAndCount(
+      int* num_total, int* num_ok, int* num_failure, int* num_drops,
+      const RpcOptions& rpc_options = RpcOptions(),
+      const char* drop_error_message_prefix = "EDS-configured drop: ") {
+    const Status status = SendRpc(rpc_options);
+    if (status.ok()) {
+      ++*num_ok;
+    } else {
+      if (absl::StartsWith(status.error_message(), drop_error_message_prefix)) {
+        ++*num_drops;
+      } else {
+        ++*num_failure;
+      }
+    }
+    ++*num_total;
+  }
+
+  struct WaitForBackendOptions {
+    bool reset_counters = true;
+    bool allow_failures = false;
+
+    WaitForBackendOptions() {}
+
+    WaitForBackendOptions& set_reset_counters(bool enable) {
+      reset_counters = enable;
+      return *this;
+    }
+
+    WaitForBackendOptions& set_allow_failures(bool enable) {
+      allow_failures = enable;
+      return *this;
+    }
+  };
+
+  std::tuple<int, int, int> WaitForAllBackends(
+      size_t start_index = 0, size_t stop_index = 0,
+      const WaitForBackendOptions& wait_options = WaitForBackendOptions(),
+      const RpcOptions& rpc_options = RpcOptions()) {
+    int num_ok = 0;
+    int num_failure = 0;
+    int num_drops = 0;
+    int num_total = 0;
+    gpr_log(GPR_INFO, "========= WAITING FOR All BACKEND %lu TO %lu ==========",
+            static_cast<unsigned long>(start_index),
+            static_cast<unsigned long>(stop_index));
+    while (!SeenAllBackends(start_index, stop_index, rpc_options.service)) {
+      SendRpcAndCount(&num_total, &num_ok, &num_failure, &num_drops,
+                      rpc_options);
+    }
+    if (wait_options.reset_counters) ResetBackendCounters();
+    gpr_log(GPR_INFO,
+            "Performed %d warm up requests against the backends. "
+            "%d succeeded, %d failed, %d dropped.",
+            num_total, num_ok, num_failure, num_drops);
+    if (!wait_options.allow_failures) EXPECT_EQ(num_failure, 0);
+    return std::make_tuple(num_ok, num_failure, num_drops);
+  }
+
+  void WaitForBackend(
+      size_t backend_idx,
+      const WaitForBackendOptions& wait_options = WaitForBackendOptions(),
+      const RpcOptions& rpc_options = RpcOptions()) {
+    gpr_log(GPR_INFO, "========= WAITING FOR BACKEND %lu ==========",
+            static_cast<unsigned long>(backend_idx));
+    do {
+      Status status = SendRpc(rpc_options);
+      if (!wait_options.allow_failures) {
+        EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
+                                 << " message=" << status.error_message();
+      }
+    } while (!SeenBackend(backend_idx, rpc_options.service));
+    if (wait_options.reset_counters) ResetBackendCounters();
+    gpr_log(GPR_INFO, "========= BACKEND %lu READY ==========",
+            static_cast<unsigned long>(backend_idx));
+  }
+
+  grpc_core::ServerAddressList CreateAddressListFromPortList(
+      const std::vector<int>& ports) {
+    grpc_core::ServerAddressList addresses;
+    for (int port : ports) {
+      absl::StatusOr<grpc_core::URI> lb_uri = grpc_core::URI::Parse(
+          absl::StrCat(ipv6_only_ ? "ipv6:[::1]:" : "ipv4:127.0.0.1:", port));
+      GPR_ASSERT(lb_uri.ok());
+      grpc_resolved_address address;
+      GPR_ASSERT(grpc_parse_uri(*lb_uri, &address));
+      addresses.emplace_back(address.addr, address.len, nullptr);
+    }
+    return addresses;
+  }
+
+  std::string CreateMetadataValueThatHashesToBackendPort(int port) {
+    return absl::StrCat(ipv6_only_ ? "[::1]" : "127.0.0.1", ":", port, "_0");
+  }
+
+  std::string CreateMetadataValueThatHashesToBackend(int index) {
+    return CreateMetadataValueThatHashesToBackendPort(backends_[index]->port());
+  }
+
+  void SetNextResolution(
+      const std::vector<int>& ports,
+      grpc_core::FakeResolverResponseGenerator* response_generator = nullptr) {
+    if (!GetParam().use_fake_resolver()) return;  // Not used with xds resolver.
+    grpc_core::ExecCtx exec_ctx;
+    grpc_core::Resolver::Result result;
+    result.addresses = CreateAddressListFromPortList(ports);
+    grpc_error_handle error = GRPC_ERROR_NONE;
+    const char* service_config_json =
+        GetParam().enable_load_reporting()
+            ? kDefaultServiceConfig
+            : kDefaultServiceConfigWithoutLoadReporting;
+    result.service_config =
+        grpc_core::ServiceConfig::Create(nullptr, service_config_json, &error);
+    ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error);
+    ASSERT_NE(result.service_config.get(), nullptr);
+    if (response_generator == nullptr) {
+      response_generator = response_generator_.get();
+    }
+    response_generator->SetResponse(std::move(result));
+  }
+
+  void SetNextResolutionForLbChannelAllBalancers(
+      const char* service_config_json = nullptr,
+      const char* expected_targets = nullptr,
+      grpc_core::FakeResolverResponseGenerator* response_generator = nullptr) {
+    std::vector<int> ports;
+    for (size_t i = 0; i < balancers_.size(); ++i) {
+      ports.emplace_back(balancers_[i]->port());
+    }
+    SetNextResolutionForLbChannel(ports, service_config_json, expected_targets,
+                                  response_generator);
+  }
+
+  void SetNextResolutionForLbChannel(
+      const std::vector<int>& ports, const char* service_config_json = nullptr,
+      const char* expected_targets = nullptr,
+      grpc_core::FakeResolverResponseGenerator* response_generator = nullptr) {
+    grpc_core::ExecCtx exec_ctx;
+    grpc_core::Resolver::Result result;
+    result.addresses = CreateAddressListFromPortList(ports);
+    if (service_config_json != nullptr) {
+      grpc_error_handle error = GRPC_ERROR_NONE;
+      result.service_config = grpc_core::ServiceConfig::Create(
+          nullptr, service_config_json, &error);
+      ASSERT_NE(result.service_config.get(), nullptr);
+      ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error);
+    }
+    if (expected_targets != nullptr) {
+      grpc_arg expected_targets_arg = grpc_channel_arg_string_create(
+          const_cast<char*>(GRPC_ARG_FAKE_SECURITY_EXPECTED_TARGETS),
+          const_cast<char*>(expected_targets));
+      result.args =
+          grpc_channel_args_copy_and_add(nullptr, &expected_targets_arg, 1);
+    }
+    if (response_generator == nullptr) {
+      response_generator = lb_channel_response_generator_.get();
+    }
+    response_generator->SetResponse(std::move(result));
+  }
+
+  void SetNextReresolutionResponse(const std::vector<int>& ports) {
+    grpc_core::ExecCtx exec_ctx;
+    grpc_core::Resolver::Result result;
+    result.addresses = CreateAddressListFromPortList(ports);
+    response_generator_->SetReresolutionResponse(std::move(result));
+  }
+
+  std::vector<int> GetBackendPorts(size_t start_index = 0,
+                                   size_t stop_index = 0) const {
+    if (stop_index == 0) stop_index = backends_.size();
+    std::vector<int> backend_ports;
+    for (size_t i = start_index; i < stop_index; ++i) {
+      backend_ports.push_back(backends_[i]->port());
+    }
+    return backend_ports;
+  }
+
+  Status SendRpc(const RpcOptions& rpc_options = RpcOptions(),
+                 EchoResponse* response = nullptr) {
+    const bool local_response = (response == nullptr);
+    if (local_response) response = new EchoResponse;
+    ClientContext context;
+    EchoRequest request;
+    if (rpc_options.server_expected_error != StatusCode::OK) {
+      auto* error = request.mutable_param()->mutable_expected_error();
+      error->set_code(rpc_options.server_expected_error);
+    }
+    rpc_options.SetupRpc(&context, &request);
+    Status status;
+    switch (rpc_options.service) {
+      case SERVICE_ECHO:
+        status =
+            SendRpcMethod(&stub_, rpc_options, &context, request, response);
+        break;
+      case SERVICE_ECHO1:
+        status =
+            SendRpcMethod(&stub1_, rpc_options, &context, request, response);
+        break;
+      case SERVICE_ECHO2:
+        status =
+            SendRpcMethod(&stub2_, rpc_options, &context, request, response);
+        break;
+    }
+    if (local_response) delete response;
+    return status;
+  }
+
+  void CheckRpcSendOk(const size_t times = 1,
+                      const RpcOptions& rpc_options = RpcOptions()) {
+    for (size_t i = 0; i < times; ++i) {
+      EchoResponse response;
+      const Status status = SendRpc(rpc_options, &response);
+      EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
+                               << " message=" << status.error_message();
+      EXPECT_EQ(response.message(), kRequestMessage);
+    }
+  }
+
+  struct CheckRpcSendFailureOptions {
+    std::function<bool(size_t)> continue_predicate = [](size_t i) {
+      return i < 1;
+    };
+    RpcOptions rpc_options;
+    StatusCode expected_error_code = StatusCode::OK;
+
+    CheckRpcSendFailureOptions() {}
+
+    CheckRpcSendFailureOptions& set_times(size_t times) {
+      continue_predicate = [times](size_t i) { return i < times; };
+      return *this;
+    }
+
+    CheckRpcSendFailureOptions& set_continue_predicate(
+        std::function<bool(size_t)> pred) {
+      continue_predicate = std::move(pred);
+      return *this;
+    }
+
+    CheckRpcSendFailureOptions& set_rpc_options(const RpcOptions& options) {
+      rpc_options = options;
+      return *this;
+    }
+
+    CheckRpcSendFailureOptions& set_expected_error_code(StatusCode code) {
+      expected_error_code = code;
+      return *this;
+    }
+  };
+
+  void CheckRpcSendFailure(const CheckRpcSendFailureOptions& options =
+                               CheckRpcSendFailureOptions()) {
+    for (size_t i = 0; options.continue_predicate(i); ++i) {
+      const Status status = SendRpc(options.rpc_options);
+      EXPECT_FALSE(status.ok());
+      if (options.expected_error_code != StatusCode::OK) {
+        EXPECT_EQ(options.expected_error_code, status.error_code());
+      }
+    }
+  }
+
+  bool WaitForNack(
+      std::function<AdsServiceImpl::ResponseState::State()> get_state,
+      StatusCode expected_status = StatusCode::UNAVAILABLE) {
+    auto deadline = absl::Now() + absl::Seconds(30);
+    bool success = true;
+    CheckRpcSendFailure(CheckRpcSendFailureOptions()
+                            .set_continue_predicate([&](size_t) {
+                              if (absl::Now() >= deadline) {
+                                success = false;
+                                return false;
+                              }
+                              return get_state() !=
+                                     AdsServiceImpl::ResponseState::NACKED;
+                            })
+                            .set_expected_error_code(expected_status));
+    return success;
+  }
+
+  bool WaitForLdsNack(StatusCode expected_status = StatusCode::UNAVAILABLE) {
+    return WaitForNack(
+        [&]() {
+          return balancers_[0]->ads_service()->lds_response_state().state;
+        },
+        expected_status);
+  }
+
+  bool WaitForRdsNack() {
+    return WaitForNack(
+        [&]() { return RouteConfigurationResponseState(0).state; });
+  }
+
+  bool WaitForCdsNack() {
+    return WaitForNack([&]() {
+      return balancers_[0]->ads_service()->cds_response_state().state;
+    });
+  }
+
+  bool WaitForEdsNack() {
+    return WaitForNack([&]() {
+      return balancers_[0]->ads_service()->eds_response_state().state;
+    });
+  }
+
+  AdsServiceImpl::ResponseState RouteConfigurationResponseState(int idx) const {
+    AdsServiceImpl* ads_service = balancers_[idx]->ads_service();
+    if (GetParam().enable_rds_testing()) {
+      return ads_service->rds_response_state();
+    }
+    return ads_service->lds_response_state();
+  }
+
+  Listener PopulateServerListenerNameAndPort(const Listener& listener_template,
+                                             int port) {
+    Listener listener = listener_template;
+    listener.set_name(
+        absl::StrCat("grpc/server?xds.resource.listening_address=",
+                     ipv6_only_ ? "[::1]:" : "127.0.0.1:", port));
+    listener.mutable_address()->mutable_socket_address()->set_port_value(port);
+    return listener;
+  }
+
+  // Interface for accessing HttpConnectionManager config in Listener.
+  class HcmAccessor {
+   public:
+    virtual ~HcmAccessor() = default;
+    virtual HttpConnectionManager Unpack(const Listener& listener) const = 0;
+    virtual void Pack(const HttpConnectionManager& hcm,
+                      Listener* listener) const = 0;
+  };
+
+  // Client-side impl.
+  class ClientHcmAccessor : public HcmAccessor {
+   public:
+    HttpConnectionManager Unpack(const Listener& listener) const override {
+      HttpConnectionManager http_connection_manager;
+      listener.api_listener().api_listener().UnpackTo(&http_connection_manager);
+      return http_connection_manager;
+    }
+    void Pack(const HttpConnectionManager& hcm,
+              Listener* listener) const override {
+      auto* api_listener =
+          listener->mutable_api_listener()->mutable_api_listener();
+      api_listener->PackFrom(hcm);
+    }
+  };
+
+  // Server-side impl.
+  class ServerHcmAccessor : public HcmAccessor {
+   public:
+    HttpConnectionManager Unpack(const Listener& listener) const override {
+      HttpConnectionManager http_connection_manager;
+      listener.default_filter_chain().filters().at(0).typed_config().UnpackTo(
+          &http_connection_manager);
+      return http_connection_manager;
+    }
+    void Pack(const HttpConnectionManager& hcm,
+              Listener* listener) const override {
+      listener->mutable_default_filter_chain()
+          ->mutable_filters()
+          ->at(0)
+          .mutable_typed_config()
+          ->PackFrom(hcm);
+    }
+  };
+
+  void SetListenerAndRouteConfiguration(
+      int idx, Listener listener, const RouteConfiguration& route_config,
+      const HcmAccessor& hcm_accessor = ClientHcmAccessor()) {
+    HttpConnectionManager http_connection_manager =
+        hcm_accessor.Unpack(listener);
+    if (GetParam().enable_rds_testing()) {
+      auto* rds = http_connection_manager.mutable_rds();
+      rds->set_route_config_name(kDefaultRouteConfigurationName);
+      rds->mutable_config_source()->mutable_ads();
+      balancers_[idx]->ads_service()->SetRdsResource(route_config);
+    } else {
+      *http_connection_manager.mutable_route_config() = route_config;
+    }
+    hcm_accessor.Pack(http_connection_manager, &listener);
+    balancers_[idx]->ads_service()->SetLdsResource(listener);
+  }
+
+  void SetServerListenerNameAndRouteConfiguration(
+      int idx, Listener listener, int port,
+      const RouteConfiguration& route_config) {
+    SetListenerAndRouteConfiguration(
+        idx, PopulateServerListenerNameAndPort(listener, port), route_config,
+        ServerHcmAccessor());
+  }
+
+  void SetRouteConfiguration(int idx, const RouteConfiguration& route_config,
+                             const Listener* listener_to_copy = nullptr) {
+    if (GetParam().enable_rds_testing()) {
+      balancers_[idx]->ads_service()->SetRdsResource(route_config);
+    } else {
+      Listener listener(listener_to_copy == nullptr ? default_listener_
+                                                    : *listener_to_copy);
+      HttpConnectionManager http_connection_manager;
+      listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
+          &http_connection_manager);
+      *(http_connection_manager.mutable_route_config()) = route_config;
+      listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
+          http_connection_manager);
+      balancers_[idx]->ads_service()->SetLdsResource(listener);
+    }
+  }
+
+  struct EdsResourceArgs {
+    struct Endpoint {
+      explicit Endpoint(int port,
+                        HealthStatus health_status = HealthStatus::UNKNOWN,
+                        int lb_weight = 1)
+          : port(port), health_status(health_status), lb_weight(lb_weight) {}
+
+      int port;
+      HealthStatus health_status;
+      int lb_weight;
+    };
+
+    struct Locality {
+      Locality(std::string sub_zone, std::vector<Endpoint> endpoints,
+               int lb_weight = kDefaultLocalityWeight,
+               int priority = kDefaultLocalityPriority)
+          : sub_zone(std::move(sub_zone)),
+            endpoints(std::move(endpoints)),
+            lb_weight(lb_weight),
+            priority(priority) {}
+
+      const std::string sub_zone;
+      std::vector<Endpoint> endpoints;
+      int lb_weight;
+      int priority;
+    };
+
+    EdsResourceArgs() = default;
+    explicit EdsResourceArgs(std::vector<Locality> locality_list)
+        : locality_list(std::move(locality_list)) {}
+
+    std::vector<Locality> locality_list;
+    std::map<std::string, uint32_t> drop_categories;
+    FractionalPercent::DenominatorType drop_denominator =
+        FractionalPercent::MILLION;
+  };
+
+  EdsResourceArgs::Endpoint CreateEndpoint(
+      size_t backend_idx, HealthStatus health_status = HealthStatus::UNKNOWN,
+      int lb_weight = 1) {
+    return EdsResourceArgs::Endpoint(backends_[backend_idx]->port(),
+                                     health_status, lb_weight);
+  }
+
+  std::vector<EdsResourceArgs::Endpoint> CreateEndpointsForBackends(
+      size_t start_index = 0, size_t stop_index = 0,
+      HealthStatus health_status = HealthStatus::UNKNOWN, int lb_weight = 1) {
+    if (stop_index == 0) stop_index = backends_.size();
+    std::vector<EdsResourceArgs::Endpoint> endpoints;
+    for (size_t i = start_index; i < stop_index; ++i) {
+      endpoints.emplace_back(CreateEndpoint(i, health_status, lb_weight));
+    }
+    return endpoints;
+  }
+
+  EdsResourceArgs::Endpoint MakeNonExistantEndpoint() {
+    return EdsResourceArgs::Endpoint(grpc_pick_unused_port_or_die());
+  }
+
+  ClusterLoadAssignment BuildEdsResource(
+      const EdsResourceArgs& args,
+      const char* eds_service_name = kDefaultEdsServiceName) {
+    ClusterLoadAssignment assignment;
+    assignment.set_cluster_name(eds_service_name);
+    for (const auto& locality : args.locality_list) {
+      auto* endpoints = assignment.add_endpoints();
+      endpoints->mutable_load_balancing_weight()->set_value(locality.lb_weight);
+      endpoints->set_priority(locality.priority);
+      endpoints->mutable_locality()->set_region(kDefaultLocalityRegion);
+      endpoints->mutable_locality()->set_zone(kDefaultLocalityZone);
+      endpoints->mutable_locality()->set_sub_zone(locality.sub_zone);
+      for (size_t i = 0; i < locality.endpoints.size(); ++i) {
+        const int& port = locality.endpoints[i].port;
+        auto* lb_endpoints = endpoints->add_lb_endpoints();
+        if (locality.endpoints.size() > i &&
+            locality.endpoints[i].health_status != HealthStatus::UNKNOWN) {
+          lb_endpoints->set_health_status(locality.endpoints[i].health_status);
+        }
+        if (locality.endpoints.size() > i &&
+            locality.endpoints[i].lb_weight >= 1) {
+          lb_endpoints->mutable_load_balancing_weight()->set_value(
+              locality.endpoints[i].lb_weight);
+        }
+        auto* endpoint = lb_endpoints->mutable_endpoint();
+        auto* address = endpoint->mutable_address();
+        auto* socket_address = address->mutable_socket_address();
+        socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1");
+        socket_address->set_port_value(port);
+      }
+    }
+    if (!args.drop_categories.empty()) {
+      auto* policy = assignment.mutable_policy();
+      for (const auto& p : args.drop_categories) {
+        const std::string& name = p.first;
+        const uint32_t parts_per_million = p.second;
+        auto* drop_overload = policy->add_drop_overloads();
+        drop_overload->set_category(name);
+        auto* drop_percentage = drop_overload->mutable_drop_percentage();
+        drop_percentage->set_numerator(parts_per_million);
+        drop_percentage->set_denominator(args.drop_denominator);
+      }
+    }
+    return assignment;
+  }
+
+ public:
+  // This method could benefit test subclasses; to make it accessible
+  // via bind with a qualified name, it needs to be public.
+  void SetEdsResourceWithDelay(size_t i,
+                               const ClusterLoadAssignment& assignment,
+                               int delay_ms) {
+    GPR_ASSERT(delay_ms > 0);
+    gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(delay_ms));
+    balancers_[i]->ads_service()->SetEdsResource(assignment);
+  }
+
+ protected:
+  class XdsServingStatusNotifier
+      : public grpc::experimental::XdsServerServingStatusNotifierInterface {
+   public:
+    void OnServingStatusUpdate(std::string uri,
+                               ServingStatusUpdate update) override {
+      grpc_core::MutexLock lock(&mu_);
+      status_map[uri] = update.status;
+      cond_.Signal();
+    }
+
+    void WaitOnServingStatusChange(std::string uri,
+                                   grpc::StatusCode expected_status) {
+      grpc_core::MutexLock lock(&mu_);
+      std::map<std::string, grpc::Status>::iterator it;
+      while ((it = status_map.find(uri)) == status_map.end() ||
+             it->second.error_code() != expected_status) {
+        cond_.Wait(&mu_);
+      }
+    }
+
+   private:
+    grpc_core::Mutex mu_;
+    grpc_core::CondVar cond_;
+    std::map<std::string, grpc::Status> status_map ABSL_GUARDED_BY(mu_);
+  };
+
+  class ServerThread {
+   public:
+    explicit ServerThread(XdsEnd2endTest* test_obj,
+                          bool use_xds_enabled_server = false)
+        : test_obj_(test_obj),
+          port_(grpc_pick_unused_port_or_die()),
+          use_xds_enabled_server_(use_xds_enabled_server) {}
+    virtual ~ServerThread(){};
+
+    void Start() {
+      gpr_log(GPR_INFO, "starting %s server on port %d", Type(), port_);
+      GPR_ASSERT(!running_);
+      running_ = true;
+      StartAllServices();
+      grpc_core::Mutex mu;
+      // We need to acquire the lock here in order to prevent the notify_one
+      // by ServerThread::Serve from firing before the wait below is hit.
+      grpc_core::MutexLock lock(&mu);
+      grpc_core::CondVar cond;
+      thread_ = absl::make_unique<std::thread>(
+          std::bind(&ServerThread::Serve, this, &mu, &cond));
+      cond.Wait(&mu);
+      gpr_log(GPR_INFO, "%s server startup complete", Type());
+    }
+
+    void Serve(grpc_core::Mutex* mu, grpc_core::CondVar* cond) {
+      // We need to acquire the lock here in order to prevent the notify_one
+      // below from firing before its corresponding wait is executed.
+      grpc_core::MutexLock lock(mu);
+      std::ostringstream server_address;
+      server_address << "localhost:" << port_;
+      if (use_xds_enabled_server_) {
+        XdsServerBuilder builder;
+        if (GetParam().bootstrap_source() ==
+            TestType::kBootstrapFromChannelArg) {
+          builder.SetOption(
+              absl::make_unique<XdsChannelArgsServerBuilderOption>(test_obj_));
+        }
+        builder.set_status_notifier(&notifier_);
+        builder.AddListeningPort(server_address.str(), Credentials());
+        RegisterAllServices(&builder);
+        server_ = builder.BuildAndStart();
+      } else {
+        ServerBuilder builder;
+        builder.AddListeningPort(server_address.str(), Credentials());
+        RegisterAllServices(&builder);
+        server_ = builder.BuildAndStart();
+      }
+      cond->Signal();
+    }
+
+    void Shutdown() {
+      if (!running_) return;
+      gpr_log(GPR_INFO, "%s about to shutdown", Type());
+      ShutdownAllServices();
+      server_->Shutdown(grpc_timeout_milliseconds_to_deadline(0));
+      thread_->join();
+      gpr_log(GPR_INFO, "%s shutdown completed", Type());
+      running_ = false;
+    }
+
+    virtual std::shared_ptr<ServerCredentials> Credentials() {
+      return std::make_shared<SecureServerCredentials>(
+          grpc_fake_transport_security_server_credentials_create());
+    }
+
+    int port() const { return port_; }
+
+    bool use_xds_enabled_server() const { return use_xds_enabled_server_; }
+
+    XdsServingStatusNotifier* notifier() { return &notifier_; }
+
+   private:
+    class XdsChannelArgsServerBuilderOption
+        : public ::grpc::ServerBuilderOption {
+     public:
+      explicit XdsChannelArgsServerBuilderOption(XdsEnd2endTest* test_obj)
+          : test_obj_(test_obj) {}
+
+      void UpdateArguments(grpc::ChannelArguments* args) override {
+        args->SetString(
+            GRPC_ARG_TEST_ONLY_DO_NOT_USE_IN_PROD_XDS_BOOTSTRAP_CONFIG,
+            GetParam().use_v2() ? kBootstrapFileV2 : kBootstrapFileV3);
+        args->SetPointerWithVtable(
+            GRPC_ARG_TEST_ONLY_DO_NOT_USE_IN_PROD_XDS_CLIENT_CHANNEL_ARGS,
+            &test_obj_->xds_channel_args_, &kChannelArgsArgVtable);
+      }
+
+      void UpdatePlugins(
+          std::vector<std::unique_ptr<grpc::ServerBuilderPlugin>>* /*plugins*/)
+          override {}
+
+     private:
+      XdsEnd2endTest* test_obj_;
+    };
+
+    virtual void RegisterAllServices(ServerBuilder* builder) = 0;
+    virtual void StartAllServices() = 0;
+    virtual void ShutdownAllServices() = 0;
+
+    virtual const char* Type() = 0;
+
+    XdsEnd2endTest* test_obj_;
+    const int port_;
+    std::unique_ptr<Server> server_;
+    XdsServingStatusNotifier notifier_;
+    std::unique_ptr<std::thread> thread_;
+    bool running_ = false;
+    const bool use_xds_enabled_server_;
+  };
+
+  class BackendServerThread : public ServerThread {
+   public:
+    explicit BackendServerThread(XdsEnd2endTest* test_obj,
+                                 bool use_xds_enabled_server)
+        : ServerThread(test_obj, use_xds_enabled_server) {}
+
+    BackendServiceImpl<::grpc::testing::EchoTestService::Service>*
+    backend_service() {
+      return &backend_service_;
+    }
+    BackendServiceImpl<::grpc::testing::EchoTest1Service::Service>*
+    backend_service1() {
+      return &backend_service1_;
+    }
+    BackendServiceImpl<::grpc::testing::EchoTest2Service::Service>*
+    backend_service2() {
+      return &backend_service2_;
+    }
+
+    std::shared_ptr<ServerCredentials> Credentials() override {
+      if (GetParam().use_xds_credentials()) {
+        if (use_xds_enabled_server()) {
+          // We are testing server's use of XdsServerCredentials
+          return XdsServerCredentials(InsecureServerCredentials());
+        } else {
+          // We are testing client's use of XdsCredentials
+          std::string root_cert = ReadFile(kCaCertPath);
+          std::string identity_cert = ReadFile(kServerCertPath);
+          std::string private_key = ReadFile(kServerKeyPath);
+          std::vector<experimental::IdentityKeyCertPair>
+              identity_key_cert_pairs = {{private_key, identity_cert}};
+          auto certificate_provider = std::make_shared<
+              grpc::experimental::StaticDataCertificateProvider>(
+              root_cert, identity_key_cert_pairs);
+          grpc::experimental::TlsServerCredentialsOptions options(
+              certificate_provider);
+          options.watch_root_certs();
+          options.watch_identity_key_cert_pairs();
+          options.set_cert_request_type(
+              GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY);
+          return grpc::experimental::TlsServerCredentials(options);
+        }
+      }
+      return ServerThread::Credentials();
+    }
+
+   private:
+    void RegisterAllServices(ServerBuilder* builder) override {
+      builder->RegisterService(&backend_service_);
+      builder->RegisterService(&backend_service1_);
+      builder->RegisterService(&backend_service2_);
+    }
+
+    void StartAllServices() override {
+      backend_service_.Start();
+      backend_service1_.Start();
+      backend_service2_.Start();
+    }
+
+    void ShutdownAllServices() override {
+      backend_service_.Shutdown();
+      backend_service1_.Shutdown();
+      backend_service2_.Shutdown();
+    }
+
+    const char* Type() override { return "Backend"; }
+
+    BackendServiceImpl<::grpc::testing::EchoTestService::Service>
+        backend_service_;
+    BackendServiceImpl<::grpc::testing::EchoTest1Service::Service>
+        backend_service1_;
+    BackendServiceImpl<::grpc::testing::EchoTest2Service::Service>
+        backend_service2_;
+  };
+
+  class BalancerServerThread : public ServerThread {
+   public:
+    explicit BalancerServerThread(XdsEnd2endTest* test_obj,
+                                  int client_load_reporting_interval = 0)
+        : ServerThread(test_obj),
+          ads_service_(new AdsServiceImpl()),
+          lrs_service_(new LrsServiceImpl(client_load_reporting_interval,
+                                          {kDefaultClusterName})) {}
+
+    AdsServiceImpl* ads_service() { return ads_service_.get(); }
+    LrsServiceImpl* lrs_service() { return lrs_service_.get(); }
+
+   private:
+    void RegisterAllServices(ServerBuilder* builder) override {
+      builder->RegisterService(ads_service_->v2_rpc_service());
+      builder->RegisterService(ads_service_->v3_rpc_service());
+      builder->RegisterService(lrs_service_->v2_rpc_service());
+      builder->RegisterService(lrs_service_->v3_rpc_service());
+    }
+
+    void StartAllServices() override {
+      ads_service_->Start();
+      lrs_service_->Start();
+    }
+
+    void ShutdownAllServices() override {
+      ads_service_->Shutdown();
+      lrs_service_->Shutdown();
+    }
+
+    const char* Type() override { return "Balancer"; }
+
+    std::shared_ptr<AdsServiceImpl> ads_service_;
+    std::shared_ptr<LrsServiceImpl> lrs_service_;
+  };
+
+#ifndef DISABLED_XDS_PROTO_IN_CC
+  class AdminServerThread : public ServerThread {
+   public:
+    explicit AdminServerThread(XdsEnd2endTest* test_obj)
+        : ServerThread(test_obj) {}
+
+   private:
+    void RegisterAllServices(ServerBuilder* builder) override {
+      builder->RegisterService(&csds_service_);
+    }
+    void StartAllServices() override {}
+    void ShutdownAllServices() override {}
+
+    const char* Type() override { return "Admin"; }
+
+    grpc::xds::experimental::ClientStatusDiscoveryService csds_service_;
+  };
+#endif  // DISABLED_XDS_PROTO_IN_CC
+
+  class LongRunningRpc {
+   public:
+    void StartRpc(grpc::testing::EchoTestService::Stub* stub,
+                  const RpcOptions& rpc_options =
+                      RpcOptions().set_timeout_ms(0).set_client_cancel_after_us(
+                          1 * 1000 * 1000)) {
+      sender_thread_ = std::thread([this, stub, rpc_options]() {
+        EchoRequest request;
+        EchoResponse response;
+        rpc_options.SetupRpc(&context_, &request);
+        status_ = stub->Echo(&context_, request, &response);
+      });
+    }
+
+    void CancelRpc() {
+      context_.TryCancel();
+      if (sender_thread_.joinable()) sender_thread_.join();
+    }
+
+    Status GetStatus() {
+      if (sender_thread_.joinable()) sender_thread_.join();
+      return status_;
+    }
+
+   private:
+    std::thread sender_thread_;
+    ClientContext context_;
+    Status status_;
+  };
+
+  struct ConcurrentRpc {
+    ClientContext context;
+    Status status;
+    grpc_millis elapsed_time;
+    EchoResponse response;
+  };
+
+  std::vector<ConcurrentRpc> SendConcurrentRpcs(
+      grpc::testing::EchoTestService::Stub* stub, size_t num_rpcs,
+      const RpcOptions& rpc_options) {
+    // Variables for RPCs.
+    std::vector<ConcurrentRpc> rpcs(num_rpcs);
+    EchoRequest request;
+    // Variables for synchronization
+    absl::Mutex mu;
+    absl::CondVar cv;
+    size_t completed = 0;
+    // Set-off callback RPCs
+    for (size_t i = 0; i < num_rpcs; i++) {
+      ConcurrentRpc* rpc = &rpcs[i];
+      rpc_options.SetupRpc(&rpc->context, &request);
+      grpc_millis t0 = NowFromCycleCounter();
+      stub->async()->Echo(&rpc->context, &request, &rpc->response,
+                          [rpc, &mu, &completed, &cv, num_rpcs, t0](Status s) {
+                            rpc->status = s;
+                            rpc->elapsed_time = NowFromCycleCounter() - t0;
+                            bool done;
+                            {
+                              absl::MutexLock lock(&mu);
+                              done = (++completed) == num_rpcs;
+                            }
+                            if (done) cv.Signal();
+                          });
+    }
+    {
+      absl::MutexLock lock(&mu);
+      cv.Wait(&mu);
+    }
+    EXPECT_EQ(completed, num_rpcs);
+    return rpcs;
+  }
+
+  const size_t num_backends_;
+  const size_t num_balancers_;
+  const int client_load_reporting_interval_seconds_;
+  bool ipv6_only_ = false;
+  std::shared_ptr<Channel> channel_;
+  std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_;
+  std::unique_ptr<grpc::testing::EchoTest1Service::Stub> stub1_;
+  std::unique_ptr<grpc::testing::EchoTest2Service::Stub> stub2_;
+  std::vector<std::unique_ptr<BackendServerThread>> backends_;
+  std::vector<std::unique_ptr<BalancerServerThread>> balancers_;
+  grpc_core::RefCountedPtr<grpc_core::FakeResolverResponseGenerator>
+      response_generator_;
+  grpc_core::RefCountedPtr<grpc_core::FakeResolverResponseGenerator>
+      lb_channel_response_generator_;
+  grpc_core::RefCountedPtr<grpc_core::FakeResolverResponseGenerator>
+      logical_dns_cluster_resolver_response_generator_;
+  int xds_resource_does_not_exist_timeout_ms_ = 0;
+  absl::InlinedVector<grpc_arg, 2> xds_channel_args_to_add_;
+  grpc_channel_args xds_channel_args_;
+
+  Listener default_listener_;
+  RouteConfiguration default_route_config_;
+  Listener default_server_listener_;
+  RouteConfiguration default_server_route_config_;
+  Cluster default_cluster_;
+  bool use_xds_enabled_server_;
+  bool bootstrap_contents_from_env_var_;
+};
+
+class BasicTest : public XdsEnd2endTest {
+ public:
+  BasicTest() : XdsEnd2endTest(4, 1) {}
+};
+
+// Tests that the balancer sends the correct response to the client, and the
+// client sends RPCs to the backends using the default child policy.
+TEST_P(BasicTest, Vanilla) {
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  const size_t kNumRpcsPerAddress = 100;
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  // Make sure that trying to connect works without a call.
+  channel_->GetState(true /* try_to_connect */);
+  // We need to wait for all backends to come online.
+  WaitForAllBackends();
+  // Send kNumRpcsPerAddress RPCs per server.
+  CheckRpcSendOk(kNumRpcsPerAddress * num_backends_);
+  // Each backend should have gotten 100 requests.
+  for (size_t i = 0; i < backends_.size(); ++i) {
+    EXPECT_EQ(kNumRpcsPerAddress,
+              backends_[i]->backend_service()->request_count());
+  }
+  // Check LB policy name for the channel.
+  EXPECT_EQ(
+      (GetParam().use_fake_resolver() ? "xds_cluster_resolver_experimental"
+                                      : "xds_cluster_manager_experimental"),
+      channel_->GetLoadBalancingPolicyName());
+}
+
+TEST_P(BasicTest, IgnoresUnhealthyEndpoints) {
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  const size_t kNumRpcsPerAddress = 100;
+  auto endpoints = CreateEndpointsForBackends();
+  endpoints[0].health_status = HealthStatus::DRAINING;
+  EdsResourceArgs args({
+      {"locality0", std::move(endpoints), kDefaultLocalityWeight,
+       kDefaultLocalityPriority},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  // Make sure that trying to connect works without a call.
+  channel_->GetState(true /* try_to_connect */);
+  // We need to wait for all backends to come online.
+  WaitForAllBackends(/*start_index=*/1);
+  // Send kNumRpcsPerAddress RPCs per server.
+  CheckRpcSendOk(kNumRpcsPerAddress * (num_backends_ - 1));
+  // Each backend should have gotten 100 requests.
+  for (size_t i = 1; i < backends_.size(); ++i) {
+    EXPECT_EQ(kNumRpcsPerAddress,
+              backends_[i]->backend_service()->request_count());
+  }
+}
+
+// Tests that subchannel sharing works when the same backend is listed
+// multiple times.
+TEST_P(BasicTest, SameBackendListedMultipleTimes) {
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Same backend listed twice.
+  auto endpoints = CreateEndpointsForBackends(0, 1);
+  endpoints.push_back(endpoints.front());
+  EdsResourceArgs args({
+      {"locality0", endpoints},
+  });
+  const size_t kNumRpcsPerAddress = 10;
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  // We need to wait for the backend to come online.
+  WaitForBackend(0);
+  // Send kNumRpcsPerAddress RPCs per server.
+  CheckRpcSendOk(kNumRpcsPerAddress * endpoints.size());
+  // Backend should have gotten 20 requests.
+  EXPECT_EQ(kNumRpcsPerAddress * endpoints.size(),
+            backends_[0]->backend_service()->request_count());
+  // And they should have come from a single client port, because of
+  // subchannel sharing.
+  EXPECT_EQ(1UL, backends_[0]->backend_service()->clients().size());
+}
+
+// Tests that RPCs will be blocked until a non-empty serverlist is received.
+TEST_P(BasicTest, InitiallyEmptyServerlist) {
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  const int kServerlistDelayMs = 500 * grpc_test_slowdown_factor();
+  const int kCallDeadlineMs = kServerlistDelayMs * 2;
+  // First response is an empty serverlist, sent right away.
+  EdsResourceArgs::Locality empty_locality("locality0", {});
+  EdsResourceArgs args({
+      empty_locality,
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  // Send non-empty serverlist only after kServerlistDelayMs.
+  args = EdsResourceArgs({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  std::thread delayed_resource_setter(std::bind(
+      &BasicTest::SetEdsResourceWithDelay, this, 0,
+      BuildEdsResource(args, DefaultEdsServiceName()), kServerlistDelayMs));
+  const auto t0 = system_clock::now();
+  // Client will block: LB will initially send empty serverlist.
+  CheckRpcSendOk(
+      1, RpcOptions().set_timeout_ms(kCallDeadlineMs).set_wait_for_ready(true));
+  const auto ellapsed_ms =
+      std::chrono::duration_cast<std::chrono::milliseconds>(
+          system_clock::now() - t0);
+  // but eventually, the LB sends a serverlist update that allows the call to
+  // proceed. The call delay must be larger than the delay in sending the
+  // populated serverlist but under the call's deadline (which is enforced by
+  // the call's deadline).
+  EXPECT_GT(ellapsed_ms.count(), kServerlistDelayMs);
+  delayed_resource_setter.join();
+}
+
+// Tests that RPCs will fail with UNAVAILABLE instead of DEADLINE_EXCEEDED if
+// all the servers are unreachable.
+TEST_P(BasicTest, AllServersUnreachableFailFast) {
+  // Set Rpc timeout to 5 seconds to ensure there is enough time
+  // for communication with the xDS server to take place upon test start up.
+  const uint32_t kRpcTimeoutMs = 5000;
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  const size_t kNumUnreachableServers = 5;
+  std::vector<EdsResourceArgs::Endpoint> endpoints;
+  for (size_t i = 0; i < kNumUnreachableServers; ++i) {
+    endpoints.emplace_back(grpc_pick_unused_port_or_die());
+  }
+  EdsResourceArgs args({
+      {"locality0", endpoints},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  const Status status = SendRpc(RpcOptions().set_timeout_ms(kRpcTimeoutMs));
+  // The error shouldn't be DEADLINE_EXCEEDED because timeout is set to 5
+  // seconds, and we should disocver in that time that the target backend is
+  // down.
+  EXPECT_EQ(StatusCode::UNAVAILABLE, status.error_code());
+}
+
+// Tests that RPCs fail when the backends are down, and will succeed again
+// after the backends are restarted.
+TEST_P(BasicTest, BackendsRestart) {
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  WaitForAllBackends();
+  // Stop backends.  RPCs should fail.
+  ShutdownAllBackends();
+  // Sending multiple failed requests instead of just one to ensure that the
+  // client notices that all backends are down before we restart them. If we
+  // didn't do this, then a single RPC could fail here due to the race
+  // condition between the LB pick and the GOAWAY from the chosen backend
+  // being shut down, which would not actually prove that the client noticed
+  // that all of the backends are down. Then, when we send another request
+  // below (which we expect to succeed), if the callbacks happen in the wrong
+  // order, the same race condition could happen again due to the client not
+  // yet having noticed that the backends were all down.
+  CheckRpcSendFailure(CheckRpcSendFailureOptions().set_times(num_backends_));
+  // Restart all backends.  RPCs should start succeeding again.
+  StartAllBackends();
+  CheckRpcSendOk(1, RpcOptions().set_timeout_ms(2000).set_wait_for_ready(true));
+}
+
+TEST_P(BasicTest, IgnoresDuplicateUpdates) {
+  const size_t kNumRpcsPerAddress = 100;
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  // Wait for all backends to come online.
+  WaitForAllBackends();
+  // Send kNumRpcsPerAddress RPCs per server, but send an EDS update in
+  // between.  If the update is not ignored, this will cause the
+  // round_robin policy to see an update, which will randomly reset its
+  // position in the address list.
+  for (size_t i = 0; i < kNumRpcsPerAddress; ++i) {
+    CheckRpcSendOk(2);
+    balancers_[0]->ads_service()->SetEdsResource(
+        BuildEdsResource(args, DefaultEdsServiceName()));
+    CheckRpcSendOk(2);
+  }
+  // Each backend should have gotten the right number of requests.
+  for (size_t i = 1; i < backends_.size(); ++i) {
+    EXPECT_EQ(kNumRpcsPerAddress,
+              backends_[i]->backend_service()->request_count());
+  }
+}
+
+using XdsResolverOnlyTest = BasicTest;
+
+TEST_P(XdsResolverOnlyTest, ResourceTypeVersionPersistsAcrossStreamRestarts) {
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 1)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
+  // Wait for backends to come online.
+  WaitForAllBackends(0, 1);
+  // Stop balancer.
+  balancers_[0]->Shutdown();
+  // Tell balancer to require minimum version 1 for all resource types.
+  balancers_[0]->ads_service()->SetResourceMinVersion(kLdsTypeUrl, 1);
+  balancers_[0]->ads_service()->SetResourceMinVersion(kRdsTypeUrl, 1);
+  balancers_[0]->ads_service()->SetResourceMinVersion(kCdsTypeUrl, 1);
+  balancers_[0]->ads_service()->SetResourceMinVersion(kEdsTypeUrl, 1);
+  // Update backend, just so we can be sure that the client has
+  // reconnected to the balancer.
+  EdsResourceArgs args2({
+      {"locality0", CreateEndpointsForBackends(1, 2)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args2));
+  // Restart balancer.
+  balancers_[0]->Start();
+  // Make sure client has reconnected.
+  WaitForAllBackends(1, 2);
+}
+
+// Tests switching over from one cluster to another.
+TEST_P(XdsResolverOnlyTest, ChangeClusters) {
+  const char* kNewClusterName = "new_cluster_name";
+  const char* kNewEdsServiceName = "new_eds_service_name";
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 2)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
+  // We need to wait for all backends to come online.
+  WaitForAllBackends(0, 2);
+  // Populate new EDS resource.
+  EdsResourceArgs args2({
+      {"locality0", CreateEndpointsForBackends(2, 4)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args2, kNewEdsServiceName));
+  // Populate new CDS resource.
+  Cluster new_cluster = default_cluster_;
+  new_cluster.set_name(kNewClusterName);
+  new_cluster.mutable_eds_cluster_config()->set_service_name(
+      kNewEdsServiceName);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster);
+  // Change RDS resource to point to new cluster.
+  RouteConfiguration new_route_config = default_route_config_;
+  new_route_config.mutable_virtual_hosts(0)
+      ->mutable_routes(0)
+      ->mutable_route()
+      ->set_cluster(kNewClusterName);
+  SetListenerAndRouteConfiguration(0, default_listener_, new_route_config);
+  // Wait for all new backends to be used.
+  std::tuple<int, int, int> counts = WaitForAllBackends(2, 4);
+  // Make sure no RPCs failed in the transition.
+  EXPECT_EQ(0, std::get<1>(counts));
+}
+
+// Tests that we go into TRANSIENT_FAILURE if the Cluster disappears.
+TEST_P(XdsResolverOnlyTest, ClusterRemoved) {
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
+  // We need to wait for all backends to come online.
+  WaitForAllBackends();
+  // Unset CDS resource.
+  balancers_[0]->ads_service()->UnsetResource(kCdsTypeUrl, kDefaultClusterName);
+  // Wait for RPCs to start failing.
+  do {
+  } while (SendRpc(RpcOptions(), nullptr).ok());
+  // Make sure RPCs are still failing.
+  CheckRpcSendFailure(CheckRpcSendFailureOptions().set_times(1000));
+  // Make sure we ACK'ed the update.
+  EXPECT_EQ(balancers_[0]->ads_service()->cds_response_state().state,
+            AdsServiceImpl::ResponseState::ACKED);
+}
+
+// Tests that we restart all xDS requests when we reestablish the ADS call.
+TEST_P(XdsResolverOnlyTest, RestartsRequestsUponReconnection) {
+  // Manually configure use of RDS.
+  auto listener = default_listener_;
+  HttpConnectionManager http_connection_manager;
+  listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
+      &http_connection_manager);
+  auto* rds = http_connection_manager.mutable_rds();
+  rds->set_route_config_name(kDefaultRouteConfigurationName);
+  rds->mutable_config_source()->mutable_ads();
+  listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
+      http_connection_manager);
+  balancers_[0]->ads_service()->SetLdsResource(listener);
+  balancers_[0]->ads_service()->SetRdsResource(default_route_config_);
+  const char* kNewClusterName = "new_cluster_name";
+  const char* kNewEdsServiceName = "new_eds_service_name";
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 2)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
+  // We need to wait for all backends to come online.
+  WaitForAllBackends(0, 2);
+  // Now shut down and restart the balancer.  When the client
+  // reconnects, it should automatically restart the requests for all
+  // resource types.
+  balancers_[0]->Shutdown();
+  balancers_[0]->Start();
+  // Make sure things are still working.
+  CheckRpcSendOk(100);
+  // Populate new EDS resource.
+  EdsResourceArgs args2({
+      {"locality0", CreateEndpointsForBackends(2, 4)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args2, kNewEdsServiceName));
+  // Populate new CDS resource.
+  Cluster new_cluster = default_cluster_;
+  new_cluster.set_name(kNewClusterName);
+  new_cluster.mutable_eds_cluster_config()->set_service_name(
+      kNewEdsServiceName);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster);
+  // Change RDS resource to point to new cluster.
+  RouteConfiguration new_route_config = default_route_config_;
+  new_route_config.mutable_virtual_hosts(0)
+      ->mutable_routes(0)
+      ->mutable_route()
+      ->set_cluster(kNewClusterName);
+  balancers_[0]->ads_service()->SetRdsResource(new_route_config);
+  // Wait for all new backends to be used.
+  std::tuple<int, int, int> counts = WaitForAllBackends(2, 4);
+  // Make sure no RPCs failed in the transition.
+  EXPECT_EQ(0, std::get<1>(counts));
+}
+
+TEST_P(XdsResolverOnlyTest, DefaultRouteSpecifiesSlashPrefix) {
+  RouteConfiguration route_config = default_route_config_;
+  route_config.mutable_virtual_hosts(0)
+      ->mutable_routes(0)
+      ->mutable_match()
+      ->set_prefix("/");
+  SetListenerAndRouteConfiguration(0, default_listener_, route_config);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
+  // We need to wait for all backends to come online.
+  WaitForAllBackends();
+}
+
+TEST_P(XdsResolverOnlyTest, CircuitBreaking) {
+  constexpr size_t kMaxConcurrentRequests = 10;
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Populate new EDS resources.
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 1)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
+  // Update CDS resource to set max concurrent request.
+  CircuitBreakers circuit_breaks;
+  Cluster cluster = default_cluster_;
+  auto* threshold = cluster.mutable_circuit_breakers()->add_thresholds();
+  threshold->set_priority(RoutingPriority::DEFAULT);
+  threshold->mutable_max_requests()->set_value(kMaxConcurrentRequests);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  // Send exactly max_concurrent_requests long RPCs.
+  LongRunningRpc rpcs[kMaxConcurrentRequests];
+  for (size_t i = 0; i < kMaxConcurrentRequests; ++i) {
+    rpcs[i].StartRpc(stub_.get());
+  }
+  // Wait for all RPCs to be in flight.
+  while (backends_[0]->backend_service()->RpcsWaitingForClientCancel() <
+         kMaxConcurrentRequests) {
+    gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
+                                 gpr_time_from_micros(1 * 1000, GPR_TIMESPAN)));
+  }
+  // Sending a RPC now should fail, the error message should tell us
+  // we hit the max concurrent requests limit and got dropped.
+  Status status = SendRpc();
+  EXPECT_FALSE(status.ok());
+  EXPECT_EQ(status.error_message(), "circuit breaker drop");
+  // Cancel one RPC to allow another one through
+  rpcs[0].CancelRpc();
+  status = SendRpc();
+  EXPECT_TRUE(status.ok());
+  for (size_t i = 1; i < kMaxConcurrentRequests; ++i) {
+    rpcs[i].CancelRpc();
+  }
+  // Make sure RPCs go to the correct backend:
+  EXPECT_EQ(kMaxConcurrentRequests + 1,
+            backends_[0]->backend_service()->request_count());
+}
+
+TEST_P(XdsResolverOnlyTest, CircuitBreakingMultipleChannelsShareCallCounter) {
+  constexpr size_t kMaxConcurrentRequests = 10;
+  // Populate new EDS resources.
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 1)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
+  // Update CDS resource to set max concurrent request.
+  CircuitBreakers circuit_breaks;
+  Cluster cluster = default_cluster_;
+  auto* threshold = cluster.mutable_circuit_breakers()->add_thresholds();
+  threshold->set_priority(RoutingPriority::DEFAULT);
+  threshold->mutable_max_requests()->set_value(kMaxConcurrentRequests);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  // Create second channel.
+  auto response_generator2 =
+      grpc_core::MakeRefCounted<grpc_core::FakeResolverResponseGenerator>();
+  auto lb_response_generator2 =
+      grpc_core::MakeRefCounted<grpc_core::FakeResolverResponseGenerator>();
+  grpc_arg xds_arg = grpc_core::FakeResolverResponseGenerator::MakeChannelArg(
+      lb_response_generator2.get());
+  grpc_channel_args xds_channel_args2 = {1, &xds_arg};
+  auto channel2 = CreateChannel(
+      /*failover_timeout=*/0, /*server_name=*/kServerName,
+      response_generator2.get(), &xds_channel_args2);
+  auto stub2 = grpc::testing::EchoTestService::NewStub(channel2);
+  // Set resolution results for both channels and for the xDS channel.
+  SetNextResolution({});
+  SetNextResolution({}, response_generator2.get());
+  SetNextResolutionForLbChannelAllBalancers();
+  SetNextResolutionForLbChannelAllBalancers(nullptr, nullptr,
+                                            lb_response_generator2.get());
+  // Send exactly max_concurrent_requests long RPCs, alternating between
+  // the two channels.
+  LongRunningRpc rpcs[kMaxConcurrentRequests];
+  for (size_t i = 0; i < kMaxConcurrentRequests; ++i) {
+    rpcs[i].StartRpc(i % 2 == 0 ? stub_.get() : stub2.get());
+  }
+  // Wait for all RPCs to be in flight.
+  while (backends_[0]->backend_service()->RpcsWaitingForClientCancel() <
+         kMaxConcurrentRequests) {
+    gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
+                                 gpr_time_from_micros(1 * 1000, GPR_TIMESPAN)));
+  }
+  // Sending a RPC now should fail, the error message should tell us
+  // we hit the max concurrent requests limit and got dropped.
+  Status status = SendRpc();
+  EXPECT_FALSE(status.ok());
+  EXPECT_EQ(status.error_message(), "circuit breaker drop");
+  // Cancel one RPC to allow another one through
+  rpcs[0].CancelRpc();
+  status = SendRpc();
+  EXPECT_TRUE(status.ok());
+  for (size_t i = 1; i < kMaxConcurrentRequests; ++i) {
+    rpcs[i].CancelRpc();
+  }
+  // Make sure RPCs go to the correct backend:
+  EXPECT_EQ(kMaxConcurrentRequests + 1,
+            backends_[0]->backend_service()->request_count());
+}
+
+TEST_P(XdsResolverOnlyTest, ClusterChangeAfterAdsCallFails) {
+  const char* kNewEdsResourceName = "new_eds_resource_name";
+  // Populate EDS resources.
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 1)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
+  SetNextResolutionForLbChannelAllBalancers();
+  // Check that the channel is working.
+  CheckRpcSendOk();
+  // Stop and restart the balancer.
+  balancers_[0]->Shutdown();
+  balancers_[0]->Start();
+  // Create new EDS resource.
+  EdsResourceArgs args2({
+      {"locality0", CreateEndpointsForBackends(1, 2)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args2, kNewEdsResourceName));
+  // Change CDS resource to point to new EDS resource.
+  auto cluster = default_cluster_;
+  cluster.mutable_eds_cluster_config()->set_service_name(kNewEdsResourceName);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  // Make sure client sees the change.
+  // TODO(roth): This should not be allowing errors.  The errors are
+  // being caused by a bug that triggers in the following situation:
+  //
+  // 1. xDS call fails.
+  // 2. When xDS call is restarted, the server sends the updated CDS
+  //    resource that points to the new EDS resource name.
+  // 3. When the client receives the CDS update, it does two things:
+  //    - Sends the update to the CDS LB policy, which creates a new
+  //      xds_cluster_resolver policy using the new EDS service name.
+  //    - Notices that the CDS update no longer refers to the old EDS
+  //      service name, so removes that resource, notifying the old
+  //      xds_cluster_resolver policy that the resource no longer exists.
+  //
+  // Need to figure out a way to fix this bug, and then change this to
+  // not allow failures.
+  WaitForBackend(1, WaitForBackendOptions().set_allow_failures(true));
+}
+
+using GlobalXdsClientTest = BasicTest;
+
+TEST_P(GlobalXdsClientTest, MultipleChannelsShareXdsClient) {
+  const char* kNewServerName = "new-server.example.com";
+  Listener listener = default_listener_;
+  listener.set_name(kNewServerName);
+  SetListenerAndRouteConfiguration(0, listener, default_route_config_);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
+  WaitForAllBackends();
+  // Create second channel and tell it to connect to kNewServerName.
+  auto channel2 = CreateChannel(/*failover_timeout=*/0, kNewServerName);
+  channel2->GetState(/*try_to_connect=*/true);
+  ASSERT_TRUE(
+      channel2->WaitForConnected(grpc_timeout_milliseconds_to_deadline(100)));
+  // Make sure there's only one client connected.
+  EXPECT_EQ(1UL, balancers_[0]->ads_service()->clients().size());
+}
+
+// Tests that the NACK for multiple bad LDS resources includes both errors.
+TEST_P(GlobalXdsClientTest, MultipleBadResources) {
+  constexpr char kServerName2[] = "server.other.com";
+  constexpr char kServerName3[] = "server.another.com";
+  auto listener = default_listener_;
+  listener.clear_api_listener();
+  balancers_[0]->ads_service()->SetLdsResource(listener);
+  listener.set_name(kServerName2);
+  balancers_[0]->ads_service()->SetLdsResource(listener);
+  listener = default_listener_;
+  listener.set_name(kServerName3);
+  SetListenerAndRouteConfiguration(0, listener, default_route_config_);
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 1)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
+  SetNextResolutionForLbChannelAllBalancers();
+  CheckRpcSendFailure();
+  // Need to create a second channel to subscribe to a second LDS resource.
+  auto channel2 = CreateChannel(0, kServerName2);
+  auto stub2 = grpc::testing::EchoTestService::NewStub(channel2);
+  {
+    ClientContext context;
+    EchoRequest request;
+    request.set_message(kRequestMessage);
+    EchoResponse response;
+    grpc::Status status = stub2->Echo(&context, request, &response);
+    EXPECT_FALSE(status.ok());
+    // Wait for second NACK to be reported to xDS server.
+    auto deadline = absl::Now() + absl::Seconds(30);
+    bool timed_out = false;
+    CheckRpcSendFailure(
+        CheckRpcSendFailureOptions().set_continue_predicate([&](size_t) {
+          if (absl::Now() >= deadline) {
+            timed_out = true;
+            return false;
+          }
+          const auto response_state =
+              balancers_[0]->ads_service()->lds_response_state();
+          return response_state.state !=
+                     AdsServiceImpl::ResponseState::NACKED ||
+                 ::testing::Matches(::testing::ContainsRegex(absl::StrCat(
+                     kServerName,
+                     ": validation error.*"
+                     "Listener has neither address nor ApiListener.*",
+                     kServerName2,
+                     ": validation error.*"
+                     "Listener has neither address nor ApiListener")))(
+                     response_state.error_message);
+        }));
+    ASSERT_FALSE(timed_out);
+  }
+  // Now start a new channel with a third server name, this one with a
+  // valid resource.
+  auto channel3 = CreateChannel(0, kServerName3);
+  auto stub3 = grpc::testing::EchoTestService::NewStub(channel3);
+  {
+    ClientContext context;
+    EchoRequest request;
+    request.set_message(kRequestMessage);
+    EchoResponse response;
+    grpc::Status status = stub3->Echo(&context, request, &response);
+    EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
+                             << " message=" << status.error_message();
+  }
+}
+
+// Tests that we don't trigger does-not-exist callbacks for a resource
+// that was previously valid but is updated to be invalid.
+TEST_P(GlobalXdsClientTest, InvalidListenerStillExistsIfPreviouslyCached) {
+  // Set up valid resources and check that the channel works.
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 1)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
+  SetNextResolutionForLbChannelAllBalancers();
+  CheckRpcSendOk();
+  // Now send an update changing the Listener to be invalid.
+  auto listener = default_listener_;
+  listener.clear_api_listener();
+  balancers_[0]->ads_service()->SetLdsResource(listener);
+  // Wait for xDS server to see NACK.
+  auto deadline = absl::Now() + absl::Seconds(30);
+  do {
+    CheckRpcSendOk();
+    ASSERT_LT(absl::Now(), deadline);
+  } while (balancers_[0]->ads_service()->lds_response_state().state !=
+           AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(balancers_[0]->ads_service()->lds_response_state().error_message,
+              ::testing::ContainsRegex(absl::StrCat(
+                  kServerName,
+                  ": validation error.*"
+                  "Listener has neither address nor ApiListener")));
+  // Check one more time, just to make sure it still works after NACK.
+  CheckRpcSendOk();
+}
+
+class XdsResolverLoadReportingOnlyTest : public XdsEnd2endTest {
+ public:
+  XdsResolverLoadReportingOnlyTest() : XdsEnd2endTest(4, 1, 3) {}
+};
+
+// Tests load reporting when switching over from one cluster to another.
+TEST_P(XdsResolverLoadReportingOnlyTest, ChangeClusters) {
+  const char* kNewClusterName = "new_cluster_name";
+  const char* kNewEdsServiceName = "new_eds_service_name";
+  balancers_[0]->lrs_service()->set_cluster_names(
+      {kDefaultClusterName, kNewClusterName});
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // cluster kDefaultClusterName -> locality0 -> backends 0 and 1
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 2)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
+  // cluster kNewClusterName -> locality1 -> backends 2 and 3
+  EdsResourceArgs args2({
+      {"locality1", CreateEndpointsForBackends(2, 4)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args2, kNewEdsServiceName));
+  // CDS resource for kNewClusterName.
+  Cluster new_cluster = default_cluster_;
+  new_cluster.set_name(kNewClusterName);
+  new_cluster.mutable_eds_cluster_config()->set_service_name(
+      kNewEdsServiceName);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster);
+  // Wait for all backends to come online.
+  int num_ok = 0;
+  int num_failure = 0;
+  int num_drops = 0;
+  std::tie(num_ok, num_failure, num_drops) = WaitForAllBackends(0, 2);
+  // The load report received at the balancer should be correct.
+  std::vector<ClientStats> load_report =
+      balancers_[0]->lrs_service()->WaitForLoadReport();
+  EXPECT_THAT(
+      load_report,
+      ::testing::ElementsAre(::testing::AllOf(
+          ::testing::Property(&ClientStats::cluster_name, kDefaultClusterName),
+          ::testing::Property(
+              &ClientStats::locality_stats,
+              ::testing::ElementsAre(::testing::Pair(
+                  "locality0",
+                  ::testing::AllOf(
+                      ::testing::Field(&ClientStats::LocalityStats::
+                                           total_successful_requests,
+                                       num_ok),
+                      ::testing::Field(&ClientStats::LocalityStats::
+                                           total_requests_in_progress,
+                                       0UL),
+                      ::testing::Field(
+                          &ClientStats::LocalityStats::total_error_requests,
+                          num_failure),
+                      ::testing::Field(
+                          &ClientStats::LocalityStats::total_issued_requests,
+                          num_failure + num_ok))))),
+          ::testing::Property(&ClientStats::total_dropped_requests,
+                              num_drops))));
+  // Change RDS resource to point to new cluster.
+  RouteConfiguration new_route_config = default_route_config_;
+  new_route_config.mutable_virtual_hosts(0)
+      ->mutable_routes(0)
+      ->mutable_route()
+      ->set_cluster(kNewClusterName);
+  SetListenerAndRouteConfiguration(0, default_listener_, new_route_config);
+  // Wait for all new backends to be used.
+  std::tie(num_ok, num_failure, num_drops) = WaitForAllBackends(2, 4);
+  // The load report received at the balancer should be correct.
+  load_report = balancers_[0]->lrs_service()->WaitForLoadReport();
+  EXPECT_THAT(
+      load_report,
+      ::testing::ElementsAre(
+          ::testing::AllOf(
+              ::testing::Property(&ClientStats::cluster_name,
+                                  kDefaultClusterName),
+              ::testing::Property(
+                  &ClientStats::locality_stats,
+                  ::testing::ElementsAre(::testing::Pair(
+                      "locality0",
+                      ::testing::AllOf(
+                          ::testing::Field(&ClientStats::LocalityStats::
+                                               total_successful_requests,
+                                           ::testing::Lt(num_ok)),
+                          ::testing::Field(&ClientStats::LocalityStats::
+                                               total_requests_in_progress,
+                                           0UL),
+                          ::testing::Field(
+                              &ClientStats::LocalityStats::total_error_requests,
+                              ::testing::Le(num_failure)),
+                          ::testing::Field(
+                              &ClientStats::LocalityStats::
+                                  total_issued_requests,
+                              ::testing::Le(num_failure + num_ok)))))),
+              ::testing::Property(&ClientStats::total_dropped_requests,
+                                  num_drops)),
+          ::testing::AllOf(
+              ::testing::Property(&ClientStats::cluster_name, kNewClusterName),
+              ::testing::Property(
+                  &ClientStats::locality_stats,
+                  ::testing::ElementsAre(::testing::Pair(
+                      "locality1",
+                      ::testing::AllOf(
+                          ::testing::Field(&ClientStats::LocalityStats::
+                                               total_successful_requests,
+                                           ::testing::Le(num_ok)),
+                          ::testing::Field(&ClientStats::LocalityStats::
+                                               total_requests_in_progress,
+                                           0UL),
+                          ::testing::Field(
+                              &ClientStats::LocalityStats::total_error_requests,
+                              ::testing::Le(num_failure)),
+                          ::testing::Field(
+                              &ClientStats::LocalityStats::
+                                  total_issued_requests,
+                              ::testing::Le(num_failure + num_ok)))))),
+              ::testing::Property(&ClientStats::total_dropped_requests,
+                                  num_drops))));
+  int total_ok = 0;
+  int total_failure = 0;
+  for (const ClientStats& client_stats : load_report) {
+    total_ok += client_stats.total_successful_requests();
+    total_failure += client_stats.total_error_requests();
+  }
+  EXPECT_EQ(total_ok, num_ok);
+  EXPECT_EQ(total_failure, num_failure);
+  // The LRS service got a single request, and sent a single response.
+  EXPECT_EQ(1U, balancers_[0]->lrs_service()->request_count());
+  EXPECT_EQ(1U, balancers_[0]->lrs_service()->response_count());
+}
+
+using SecureNamingTest = BasicTest;
+
+// Tests that secure naming check passes if target name is expected.
+TEST_P(SecureNamingTest, TargetNameIsExpected) {
+  SetNextResolution({});
+  SetNextResolutionForLbChannel({balancers_[0]->port()}, nullptr, "xds_server");
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  CheckRpcSendOk();
+}
+
+// Tests that secure naming check fails if target name is unexpected.
+TEST_P(SecureNamingTest, TargetNameIsUnexpected) {
+  GRPC_GTEST_FLAG_SET_DEATH_TEST_STYLE("threadsafe");
+  SetNextResolution({});
+  SetNextResolutionForLbChannel({balancers_[0]->port()}, nullptr,
+                                "incorrect_server_name");
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  // Make sure that we blow up (via abort() from the security connector) when
+  // the name from the balancer doesn't match expectations.
+  ASSERT_DEATH_IF_SUPPORTED({ CheckRpcSendOk(); }, "");
+}
+
+using LdsTest = BasicTest;
+
+// Tests that LDS client should send a NACK if there is no API listener in the
+// Listener in the LDS response.
+TEST_P(LdsTest, NoApiListener) {
+  auto listener = default_listener_;
+  listener.clear_api_listener();
+  balancers_[0]->ads_service()->SetLdsResource(listener);
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForLdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->lds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(
+      response_state.error_message,
+      ::testing::HasSubstr("Listener has neither address nor ApiListener"));
+}
+
+// Tests that LDS client should send a NACK if the route_specifier in the
+// http_connection_manager is neither inlined route_config nor RDS.
+TEST_P(LdsTest, WrongRouteSpecifier) {
+  auto listener = default_listener_;
+  HttpConnectionManager http_connection_manager;
+  listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
+      &http_connection_manager);
+  http_connection_manager.mutable_scoped_routes();
+  listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
+      http_connection_manager);
+  balancers_[0]->ads_service()->SetLdsResource(listener);
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForLdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->lds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(
+      response_state.error_message,
+      ::testing::HasSubstr(
+          "HttpConnectionManager neither has inlined route_config nor RDS."));
+}
+
+// Tests that LDS client should send a NACK if the rds message in the
+// http_connection_manager is missing the config_source field.
+TEST_P(LdsTest, RdsMissingConfigSource) {
+  auto listener = default_listener_;
+  HttpConnectionManager http_connection_manager;
+  listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
+      &http_connection_manager);
+  http_connection_manager.mutable_rds()->set_route_config_name(
+      kDefaultRouteConfigurationName);
+  listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
+      http_connection_manager);
+  balancers_[0]->ads_service()->SetLdsResource(listener);
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForLdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->lds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr(
+                  "HttpConnectionManager missing config_source for RDS."));
+}
+
+// Tests that LDS client should send a NACK if the rds message in the
+// http_connection_manager has a config_source field that does not specify
+// ADS.
+TEST_P(LdsTest, RdsConfigSourceDoesNotSpecifyAds) {
+  auto listener = default_listener_;
+  HttpConnectionManager http_connection_manager;
+  listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
+      &http_connection_manager);
+  auto* rds = http_connection_manager.mutable_rds();
+  rds->set_route_config_name(kDefaultRouteConfigurationName);
+  rds->mutable_config_source()->mutable_self();
+  listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
+      http_connection_manager);
+  balancers_[0]->ads_service()->SetLdsResource(listener);
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForLdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->lds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr("HttpConnectionManager ConfigSource for "
+                                   "RDS does not specify ADS."));
+}
+
+// Tests that we NACK non-terminal filters at the end of the list.
+TEST_P(LdsTest, NacksNonTerminalHttpFilterAtEndOfList) {
+  SetNextResolutionForLbChannelAllBalancers();
+  auto listener = default_listener_;
+  HttpConnectionManager http_connection_manager;
+  listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
+      &http_connection_manager);
+  auto* filter = http_connection_manager.mutable_http_filters(0);
+  filter->set_name("unknown");
+  filter->mutable_typed_config()->set_type_url(
+      "grpc.testing.client_only_http_filter");
+  listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
+      http_connection_manager);
+  SetListenerAndRouteConfiguration(0, listener, default_route_config_);
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForLdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->lds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr(
+                  "non-terminal filter for config type grpc.testing"
+                  ".client_only_http_filter is the last filter in the chain"));
+}
+
+// Test that we NACK terminal filters that are not at the end of the list.
+TEST_P(LdsTest, NacksTerminalFilterBeforeEndOfList) {
+  SetNextResolutionForLbChannelAllBalancers();
+  auto listener = default_listener_;
+  HttpConnectionManager http_connection_manager;
+  listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
+      &http_connection_manager);
+  // The default_listener_ has a terminal router filter by default. Add an
+  // additional filter.
+  auto* filter = http_connection_manager.add_http_filters();
+  filter->set_name("grpc.testing.terminal_http_filter");
+  filter->mutable_typed_config()->set_type_url(
+      "grpc.testing.terminal_http_filter");
+  listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
+      http_connection_manager);
+  SetListenerAndRouteConfiguration(0, listener, default_route_config_);
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForLdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->lds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(
+      response_state.error_message,
+      ::testing::HasSubstr(
+          "terminal filter for config type envoy.extensions.filters.http"
+          ".router.v3.Router must be the last filter in the chain"));
+}
+
+// Test that we NACK empty filter names.
+TEST_P(LdsTest, RejectsEmptyHttpFilterName) {
+  auto listener = default_listener_;
+  HttpConnectionManager http_connection_manager;
+  listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
+      &http_connection_manager);
+  *http_connection_manager.add_http_filters() =
+      http_connection_manager.http_filters(0);
+  auto* filter = http_connection_manager.mutable_http_filters(0);
+  filter->Clear();
+  filter->mutable_typed_config()->PackFrom(Listener());
+  listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
+      http_connection_manager);
+  SetListenerAndRouteConfiguration(0, listener, default_route_config_);
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForLdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->lds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr("empty filter name at index 0"));
+}
+
+// Test that we NACK duplicate HTTP filter names.
+TEST_P(LdsTest, RejectsDuplicateHttpFilterName) {
+  auto listener = default_listener_;
+  HttpConnectionManager http_connection_manager;
+  listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
+      &http_connection_manager);
+  *http_connection_manager.add_http_filters() =
+      http_connection_manager.http_filters(0);
+  http_connection_manager.mutable_http_filters(0)
+      ->mutable_typed_config()
+      ->PackFrom(HTTPFault());
+  listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
+      http_connection_manager);
+  SetListenerAndRouteConfiguration(0, listener, default_route_config_);
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForLdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->lds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr("duplicate HTTP filter name: router"));
+}
+
+// Test that we NACK unknown filter types.
+TEST_P(LdsTest, RejectsUnknownHttpFilterType) {
+  auto listener = default_listener_;
+  HttpConnectionManager http_connection_manager;
+  listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
+      &http_connection_manager);
+  *http_connection_manager.add_http_filters() =
+      http_connection_manager.http_filters(0);
+  auto* filter = http_connection_manager.mutable_http_filters(0);
+  filter->set_name("unknown");
+  filter->mutable_typed_config()->PackFrom(Listener());
+  listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
+      http_connection_manager);
+  SetListenerAndRouteConfiguration(0, listener, default_route_config_);
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForLdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->lds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr("no filter registered for config type "
+                                   "envoy.config.listener.v3.Listener"));
+}
+
+// Test that we ignore optional unknown filter types.
+TEST_P(LdsTest, IgnoresOptionalUnknownHttpFilterType) {
+  auto listener = default_listener_;
+  HttpConnectionManager http_connection_manager;
+  listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
+      &http_connection_manager);
+  *http_connection_manager.add_http_filters() =
+      http_connection_manager.http_filters(0);
+  auto* filter = http_connection_manager.mutable_http_filters(0);
+  filter->set_name("unknown");
+  filter->mutable_typed_config()->PackFrom(Listener());
+  filter->set_is_optional(true);
+  listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
+      http_connection_manager);
+  SetListenerAndRouteConfiguration(0, listener, default_route_config_);
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  SetNextResolutionForLbChannelAllBalancers();
+  WaitForAllBackends();
+  EXPECT_EQ(balancers_[0]->ads_service()->lds_response_state().state,
+            AdsServiceImpl::ResponseState::ACKED);
+}
+
+// Test that we NACK filters without configs.
+TEST_P(LdsTest, RejectsHttpFilterWithoutConfig) {
+  auto listener = default_listener_;
+  HttpConnectionManager http_connection_manager;
+  listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
+      &http_connection_manager);
+  *http_connection_manager.add_http_filters() =
+      http_connection_manager.http_filters(0);
+  auto* filter = http_connection_manager.mutable_http_filters(0);
+  filter->Clear();
+  filter->set_name("unknown");
+  listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
+      http_connection_manager);
+  SetListenerAndRouteConfiguration(0, listener, default_route_config_);
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForLdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->lds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr(
+                  "no filter config specified for filter name unknown"));
+}
+
+// Test that we ignore optional filters without configs.
+TEST_P(LdsTest, IgnoresOptionalHttpFilterWithoutConfig) {
+  auto listener = default_listener_;
+  HttpConnectionManager http_connection_manager;
+  listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
+      &http_connection_manager);
+  *http_connection_manager.add_http_filters() =
+      http_connection_manager.http_filters(0);
+  auto* filter = http_connection_manager.mutable_http_filters(0);
+  filter->Clear();
+  filter->set_name("unknown");
+  filter->set_is_optional(true);
+  listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
+      http_connection_manager);
+  SetListenerAndRouteConfiguration(0, listener, default_route_config_);
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  SetNextResolutionForLbChannelAllBalancers();
+  WaitForAllBackends();
+  EXPECT_EQ(balancers_[0]->ads_service()->lds_response_state().state,
+            AdsServiceImpl::ResponseState::ACKED);
+}
+
+// Test that we NACK unparseable filter configs.
+TEST_P(LdsTest, RejectsUnparseableHttpFilterType) {
+  auto listener = default_listener_;
+  HttpConnectionManager http_connection_manager;
+  listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
+      &http_connection_manager);
+  *http_connection_manager.add_http_filters() =
+      http_connection_manager.http_filters(0);
+  auto* filter = http_connection_manager.mutable_http_filters(0);
+  filter->set_name("unknown");
+  filter->mutable_typed_config()->PackFrom(listener);
+  filter->mutable_typed_config()->set_type_url(
+      "type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault");
+  listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
+      http_connection_manager);
+  SetListenerAndRouteConfiguration(0, listener, default_route_config_);
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForLdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->lds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(
+      response_state.error_message,
+      ::testing::HasSubstr(
+          "filter config for type "
+          "envoy.extensions.filters.http.fault.v3.HTTPFault failed to parse"));
+}
+
+// Test that we NACK HTTP filters unsupported on client-side.
+TEST_P(LdsTest, RejectsHttpFiltersNotSupportedOnClients) {
+  auto listener = default_listener_;
+  HttpConnectionManager http_connection_manager;
+  listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
+      &http_connection_manager);
+  *http_connection_manager.add_http_filters() =
+      http_connection_manager.http_filters(0);
+  auto* filter = http_connection_manager.mutable_http_filters(0);
+  filter->set_name("grpc.testing.server_only_http_filter");
+  filter->mutable_typed_config()->set_type_url(
+      "grpc.testing.server_only_http_filter");
+  listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
+      http_connection_manager);
+  SetListenerAndRouteConfiguration(0, listener, default_route_config_);
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForLdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->lds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(
+      response_state.error_message,
+      ::testing::HasSubstr("Filter grpc.testing.server_only_http_filter is not "
+                           "supported on clients"));
+}
+
+// Test that we ignore optional HTTP filters unsupported on client-side.
+TEST_P(LdsTest, IgnoresOptionalHttpFiltersNotSupportedOnClients) {
+  auto listener = default_listener_;
+  HttpConnectionManager http_connection_manager;
+  listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
+      &http_connection_manager);
+  *http_connection_manager.add_http_filters() =
+      http_connection_manager.http_filters(0);
+  auto* filter = http_connection_manager.mutable_http_filters(0);
+  filter->set_name("grpc.testing.server_only_http_filter");
+  filter->mutable_typed_config()->set_type_url(
+      "grpc.testing.server_only_http_filter");
+  filter->set_is_optional(true);
+  listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
+      http_connection_manager);
+  SetListenerAndRouteConfiguration(0, listener, default_route_config_);
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 1)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  SetNextResolutionForLbChannelAllBalancers();
+  WaitForBackend(0);
+  EXPECT_EQ(balancers_[0]->ads_service()->lds_response_state().state,
+            AdsServiceImpl::ResponseState::ACKED);
+}
+
+using LdsV2Test = LdsTest;
+
+// Tests that we ignore the HTTP filter list in v2.
+// TODO(roth): The test framework is not set up to allow us to test
+// the server sending v2 resources when the client requests v3, so this
+// just tests a pure v2 setup.  When we have time, fix this.
+TEST_P(LdsV2Test, IgnoresHttpFilters) {
+  auto listener = default_listener_;
+  HttpConnectionManager http_connection_manager;
+  listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
+      &http_connection_manager);
+  auto* filter = http_connection_manager.add_http_filters();
+  filter->set_name("unknown");
+  filter->mutable_typed_config()->PackFrom(Listener());
+  listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
+      http_connection_manager);
+  SetListenerAndRouteConfiguration(0, listener, default_route_config_);
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 1)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  SetNextResolutionForLbChannelAllBalancers();
+  CheckRpcSendOk();
+}
+
+using LdsRdsTest = BasicTest;
+
+// Tests that LDS client should send an ACK upon correct LDS response (with
+// inlined RDS result).
+TEST_P(LdsRdsTest, Vanilla) {
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  (void)SendRpc();
+  EXPECT_EQ(RouteConfigurationResponseState(0).state,
+            AdsServiceImpl::ResponseState::ACKED);
+  // Make sure we actually used the RPC service for the right version of xDS.
+  EXPECT_EQ(balancers_[0]->ads_service()->seen_v2_client(),
+            GetParam().use_v2());
+  EXPECT_NE(balancers_[0]->ads_service()->seen_v3_client(),
+            GetParam().use_v2());
+}
+
+// Tests that we go into TRANSIENT_FAILURE if the Listener is removed.
+TEST_P(LdsRdsTest, ListenerRemoved) {
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
+  // We need to wait for all backends to come online.
+  WaitForAllBackends();
+  // Unset LDS resource.
+  balancers_[0]->ads_service()->UnsetResource(kLdsTypeUrl, kServerName);
+  // Wait for RPCs to start failing.
+  do {
+  } while (SendRpc(RpcOptions(), nullptr).ok());
+  // Make sure RPCs are still failing.
+  CheckRpcSendFailure(CheckRpcSendFailureOptions().set_times(1000));
+  // Make sure we ACK'ed the update.
+  EXPECT_EQ(balancers_[0]->ads_service()->lds_response_state().state,
+            AdsServiceImpl::ResponseState::ACKED);
+}
+
+// Tests that LDS client ACKs but fails if matching domain can't be found in
+// the LDS response.
+TEST_P(LdsRdsTest, NoMatchedDomain) {
+  RouteConfiguration route_config = default_route_config_;
+  route_config.mutable_virtual_hosts(0)->clear_domains();
+  route_config.mutable_virtual_hosts(0)->add_domains("unmatched_domain");
+  SetRouteConfiguration(0, route_config);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  CheckRpcSendFailure();
+  // Do a bit of polling, to allow the ACK to get to the ADS server.
+  channel_->WaitForConnected(grpc_timeout_milliseconds_to_deadline(100));
+  const auto response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::ACKED);
+}
+
+// Tests that LDS client should choose the virtual host with matching domain
+// if multiple virtual hosts exist in the LDS response.
+TEST_P(LdsRdsTest, ChooseMatchedDomain) {
+  RouteConfiguration route_config = default_route_config_;
+  *(route_config.add_virtual_hosts()) = route_config.virtual_hosts(0);
+  route_config.mutable_virtual_hosts(0)->clear_domains();
+  route_config.mutable_virtual_hosts(0)->add_domains("unmatched_domain");
+  SetRouteConfiguration(0, route_config);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  (void)SendRpc();
+  EXPECT_EQ(RouteConfigurationResponseState(0).state,
+            AdsServiceImpl::ResponseState::ACKED);
+}
+
+// Tests that LDS client should choose the last route in the virtual host if
+// multiple routes exist in the LDS response.
+TEST_P(LdsRdsTest, ChooseLastRoute) {
+  RouteConfiguration route_config = default_route_config_;
+  *(route_config.mutable_virtual_hosts(0)->add_routes()) =
+      route_config.virtual_hosts(0).routes(0);
+  route_config.mutable_virtual_hosts(0)
+      ->mutable_routes(0)
+      ->mutable_route()
+      ->mutable_cluster_header();
+  SetRouteConfiguration(0, route_config);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  (void)SendRpc();
+  EXPECT_EQ(RouteConfigurationResponseState(0).state,
+            AdsServiceImpl::ResponseState::ACKED);
+}
+
+// Tests that LDS client should ignore route which has query_parameters.
+TEST_P(LdsRdsTest, RouteMatchHasQueryParameters) {
+  RouteConfiguration route_config = default_route_config_;
+  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/");
+  route1->mutable_match()->add_query_parameters();
+  SetRouteConfiguration(0, route_config);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
+  const auto response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr("No valid routes specified."));
+}
+
+// Tests that LDS client should send a ACK if route match has a prefix
+// that is either empty or a single slash
+TEST_P(LdsRdsTest, RouteMatchHasValidPrefixEmptyOrSingleSlash) {
+  RouteConfiguration route_config = default_route_config_;
+  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  route1->mutable_match()->set_prefix("");
+  auto* default_route = route_config.mutable_virtual_hosts(0)->add_routes();
+  default_route->mutable_match()->set_prefix("/");
+  default_route->mutable_route()->set_cluster(kDefaultClusterName);
+  SetRouteConfiguration(0, route_config);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  (void)SendRpc();
+  const auto response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::ACKED);
+}
+
+// Tests that LDS client should ignore route which has a path
+// prefix string does not start with "/".
+TEST_P(LdsRdsTest, RouteMatchHasInvalidPrefixNoLeadingSlash) {
+  RouteConfiguration route_config = default_route_config_;
+  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  route1->mutable_match()->set_prefix("grpc.testing.EchoTest1Service/");
+  SetRouteConfiguration(0, route_config);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
+  const auto response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr("No valid routes specified."));
+}
+
+// Tests that LDS client should ignore route which has a prefix
+// string with more than 2 slashes.
+TEST_P(LdsRdsTest, RouteMatchHasInvalidPrefixExtraContent) {
+  RouteConfiguration route_config = default_route_config_;
+  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/Echo1/");
+  SetRouteConfiguration(0, route_config);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
+  const auto response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr("No valid routes specified."));
+}
+
+// Tests that LDS client should ignore route which has a prefix
+// string "//".
+TEST_P(LdsRdsTest, RouteMatchHasInvalidPrefixDoubleSlash) {
+  RouteConfiguration route_config = default_route_config_;
+  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  route1->mutable_match()->set_prefix("//");
+  SetRouteConfiguration(0, route_config);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
+  const auto response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr("No valid routes specified."));
+}
+
+// Tests that LDS client should ignore route which has path
+// but it's empty.
+TEST_P(LdsRdsTest, RouteMatchHasInvalidPathEmptyPath) {
+  RouteConfiguration route_config = default_route_config_;
+  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  route1->mutable_match()->set_path("");
+  SetRouteConfiguration(0, route_config);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
+  const auto response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr("No valid routes specified."));
+}
+
+// Tests that LDS client should ignore route which has path
+// string does not start with "/".
+TEST_P(LdsRdsTest, RouteMatchHasInvalidPathNoLeadingSlash) {
+  RouteConfiguration route_config = default_route_config_;
+  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  route1->mutable_match()->set_path("grpc.testing.EchoTest1Service/Echo1");
+  SetRouteConfiguration(0, route_config);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
+  const auto response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr("No valid routes specified."));
+}
+
+// Tests that LDS client should ignore route which has path
+// string that has too many slashes; for example, ends with "/".
+TEST_P(LdsRdsTest, RouteMatchHasInvalidPathTooManySlashes) {
+  RouteConfiguration route_config = default_route_config_;
+  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  route1->mutable_match()->set_path("/grpc.testing.EchoTest1Service/Echo1/");
+  SetRouteConfiguration(0, route_config);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
+  const auto response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr("No valid routes specified."));
+}
+
+// Tests that LDS client should ignore route which has path
+// string that has only 1 slash: missing "/" between service and method.
+TEST_P(LdsRdsTest, RouteMatchHasInvalidPathOnlyOneSlash) {
+  RouteConfiguration route_config = default_route_config_;
+  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  route1->mutable_match()->set_path("/grpc.testing.EchoTest1Service.Echo1");
+  SetRouteConfiguration(0, route_config);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
+  const auto response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr("No valid routes specified."));
+}
+
+// Tests that LDS client should ignore route which has path
+// string that is missing service.
+TEST_P(LdsRdsTest, RouteMatchHasInvalidPathMissingService) {
+  RouteConfiguration route_config = default_route_config_;
+  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  route1->mutable_match()->set_path("//Echo1");
+  SetRouteConfiguration(0, route_config);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
+  const auto response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr("No valid routes specified."));
+}
+
+// Tests that LDS client should ignore route which has path
+// string that is missing method.
+TEST_P(LdsRdsTest, RouteMatchHasInvalidPathMissingMethod) {
+  RouteConfiguration route_config = default_route_config_;
+  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  route1->mutable_match()->set_path("/grpc.testing.EchoTest1Service/");
+  SetRouteConfiguration(0, route_config);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
+  const auto response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr("No valid routes specified."));
+}
+
+// Test that LDS client should reject route which has invalid path regex.
+TEST_P(LdsRdsTest, RouteMatchHasInvalidPathRegex) {
+  const char* kNewCluster1Name = "new_cluster_1";
+  RouteConfiguration route_config = default_route_config_;
+  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  route1->mutable_match()->mutable_safe_regex()->set_regex("a[z-a]");
+  route1->mutable_route()->set_cluster(kNewCluster1Name);
+  SetRouteConfiguration(0, route_config);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
+  const auto response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr(
+                  "path matcher: Invalid regex string specified in matcher."));
+}
+
+// Tests that LDS client should fail RPCs with UNAVAILABLE status code if the
+// matching route has an action other than RouteAction.
+TEST_P(LdsRdsTest, MatchingRouteHasNoRouteAction) {
+  RouteConfiguration route_config = default_route_config_;
+  // Set a route with an inappropriate route action
+  auto* vhost = route_config.mutable_virtual_hosts(0);
+  vhost->mutable_routes(0)->mutable_redirect();
+  // Add another route to make sure that the resolver code actually tries to
+  // match to a route instead of using a shorthand logic to error out.
+  auto* route = vhost->add_routes();
+  route->mutable_match()->set_prefix("");
+  route->mutable_route()->set_cluster(kDefaultClusterName);
+  SetRouteConfiguration(0, route_config);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  CheckRpcSendFailure(CheckRpcSendFailureOptions().set_expected_error_code(
+      StatusCode::UNAVAILABLE));
+}
+
+TEST_P(LdsRdsTest, RouteActionClusterHasEmptyClusterName) {
+  RouteConfiguration route_config = default_route_config_;
+  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/");
+  route1->mutable_route()->set_cluster("");
+  auto* default_route = route_config.mutable_virtual_hosts(0)->add_routes();
+  default_route->mutable_match()->set_prefix("");
+  default_route->mutable_route()->set_cluster(kDefaultClusterName);
+  SetRouteConfiguration(0, route_config);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
+  const auto response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(
+      response_state.error_message,
+      ::testing::HasSubstr("RouteAction cluster contains empty cluster name."));
+}
+
+TEST_P(LdsRdsTest, RouteActionWeightedTargetHasIncorrectTotalWeightSet) {
+  const size_t kWeight75 = 75;
+  const char* kNewCluster1Name = "new_cluster_1";
+  RouteConfiguration route_config = default_route_config_;
+  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/");
+  auto* weighted_cluster1 =
+      route1->mutable_route()->mutable_weighted_clusters()->add_clusters();
+  weighted_cluster1->set_name(kNewCluster1Name);
+  weighted_cluster1->mutable_weight()->set_value(kWeight75);
+  route1->mutable_route()
+      ->mutable_weighted_clusters()
+      ->mutable_total_weight()
+      ->set_value(kWeight75 + 1);
+  auto* default_route = route_config.mutable_virtual_hosts(0)->add_routes();
+  default_route->mutable_match()->set_prefix("");
+  default_route->mutable_route()->set_cluster(kDefaultClusterName);
+  SetRouteConfiguration(0, route_config);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
+  const auto response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr(
+                  "RouteAction weighted_cluster has incorrect total weight"));
+}
+
+TEST_P(LdsRdsTest, RouteActionWeightedClusterHasZeroTotalWeight) {
+  const char* kNewCluster1Name = "new_cluster_1";
+  RouteConfiguration route_config = default_route_config_;
+  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/");
+  auto* weighted_cluster1 =
+      route1->mutable_route()->mutable_weighted_clusters()->add_clusters();
+  weighted_cluster1->set_name(kNewCluster1Name);
+  weighted_cluster1->mutable_weight()->set_value(0);
+  route1->mutable_route()
+      ->mutable_weighted_clusters()
+      ->mutable_total_weight()
+      ->set_value(0);
+  auto* default_route = route_config.mutable_virtual_hosts(0)->add_routes();
+  default_route->mutable_match()->set_prefix("");
+  default_route->mutable_route()->set_cluster(kDefaultClusterName);
+  SetRouteConfiguration(0, route_config);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
+  const auto response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(
+      response_state.error_message,
+      ::testing::HasSubstr(
+          "RouteAction weighted_cluster has no valid clusters specified."));
+}
+
+TEST_P(LdsRdsTest, RouteActionWeightedTargetClusterHasEmptyClusterName) {
+  const size_t kWeight75 = 75;
+  RouteConfiguration route_config = default_route_config_;
+  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/");
+  auto* weighted_cluster1 =
+      route1->mutable_route()->mutable_weighted_clusters()->add_clusters();
+  weighted_cluster1->set_name("");
+  weighted_cluster1->mutable_weight()->set_value(kWeight75);
+  route1->mutable_route()
+      ->mutable_weighted_clusters()
+      ->mutable_total_weight()
+      ->set_value(kWeight75);
+  auto* default_route = route_config.mutable_virtual_hosts(0)->add_routes();
+  default_route->mutable_match()->set_prefix("");
+  default_route->mutable_route()->set_cluster(kDefaultClusterName);
+  SetRouteConfiguration(0, route_config);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
+  const auto response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr("RouteAction weighted_cluster cluster "
+                                   "contains empty cluster name."));
+}
+
+TEST_P(LdsRdsTest, RouteActionWeightedTargetClusterHasNoWeight) {
+  const size_t kWeight75 = 75;
+  const char* kNewCluster1Name = "new_cluster_1";
+  RouteConfiguration route_config = default_route_config_;
+  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/");
+  auto* weighted_cluster1 =
+      route1->mutable_route()->mutable_weighted_clusters()->add_clusters();
+  weighted_cluster1->set_name(kNewCluster1Name);
+  route1->mutable_route()
+      ->mutable_weighted_clusters()
+      ->mutable_total_weight()
+      ->set_value(kWeight75);
+  auto* default_route = route_config.mutable_virtual_hosts(0)->add_routes();
+  default_route->mutable_match()->set_prefix("");
+  default_route->mutable_route()->set_cluster(kDefaultClusterName);
+  SetRouteConfiguration(0, route_config);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
+  const auto response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr(
+                  "RouteAction weighted_cluster cluster missing weight"));
+}
+
+TEST_P(LdsRdsTest, RouteHeaderMatchInvalidRegex) {
+  const char* kNewCluster1Name = "new_cluster_1";
+  RouteConfiguration route_config = default_route_config_;
+  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/");
+  auto* header_matcher1 = route1->mutable_match()->add_headers();
+  header_matcher1->set_name("header1");
+  header_matcher1->mutable_safe_regex_match()->set_regex("a[z-a]");
+  route1->mutable_route()->set_cluster(kNewCluster1Name);
+  SetRouteConfiguration(0, route_config);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
+  const auto response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(
+      response_state.error_message,
+      ::testing::HasSubstr(
+          "header matcher: Invalid regex string specified in matcher."));
+}
+
+TEST_P(LdsRdsTest, RouteHeaderMatchInvalidRange) {
+  const char* kNewCluster1Name = "new_cluster_1";
+  RouteConfiguration route_config = default_route_config_;
+  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/");
+  auto* header_matcher1 = route1->mutable_match()->add_headers();
+  header_matcher1->set_name("header1");
+  header_matcher1->mutable_range_match()->set_start(1001);
+  header_matcher1->mutable_range_match()->set_end(1000);
+  route1->mutable_route()->set_cluster(kNewCluster1Name);
+  SetRouteConfiguration(0, route_config);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
+  const auto response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(
+      response_state.error_message,
+      ::testing::HasSubstr(
+          "header matcher: Invalid range specifier specified: end cannot be "
+          "smaller than start."));
+}
+
+// Tests that LDS client should choose the default route (with no matching
+// specified) after unable to find a match with previous routes.
+TEST_P(LdsRdsTest, XdsRoutingPathMatching) {
+  const char* kNewCluster1Name = "new_cluster_1";
+  const char* kNewEdsService1Name = "new_eds_service_name_1";
+  const char* kNewCluster2Name = "new_cluster_2";
+  const char* kNewEdsService2Name = "new_eds_service_name_2";
+  const size_t kNumEcho1Rpcs = 10;
+  const size_t kNumEcho2Rpcs = 20;
+  const size_t kNumEchoRpcs = 30;
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Populate new EDS resources.
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 2)},
+  });
+  EdsResourceArgs args1({
+      {"locality0", CreateEndpointsForBackends(2, 3)},
+  });
+  EdsResourceArgs args2({
+      {"locality0", CreateEndpointsForBackends(3, 4)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args1, kNewEdsService1Name));
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args2, kNewEdsService2Name));
+  // Populate new CDS resources.
+  Cluster new_cluster1 = default_cluster_;
+  new_cluster1.set_name(kNewCluster1Name);
+  new_cluster1.mutable_eds_cluster_config()->set_service_name(
+      kNewEdsService1Name);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster1);
+  Cluster new_cluster2 = default_cluster_;
+  new_cluster2.set_name(kNewCluster2Name);
+  new_cluster2.mutable_eds_cluster_config()->set_service_name(
+      kNewEdsService2Name);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster2);
+  // Populating Route Configurations for LDS.
+  RouteConfiguration new_route_config = default_route_config_;
+  auto* route1 = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  route1->mutable_match()->set_path("/grpc.testing.EchoTest1Service/Echo1");
+  route1->mutable_route()->set_cluster(kNewCluster1Name);
+  auto* route2 = new_route_config.mutable_virtual_hosts(0)->add_routes();
+  route2->mutable_match()->set_path("/grpc.testing.EchoTest2Service/Echo2");
+  route2->mutable_route()->set_cluster(kNewCluster2Name);
+  auto* route3 = new_route_config.mutable_virtual_hosts(0)->add_routes();
+  route3->mutable_match()->set_path("/grpc.testing.EchoTest3Service/Echo3");
+  route3->mutable_route()->set_cluster(kDefaultClusterName);
+  auto* default_route = new_route_config.mutable_virtual_hosts(0)->add_routes();
+  default_route->mutable_match()->set_prefix("");
+  default_route->mutable_route()->set_cluster(kDefaultClusterName);
+  SetRouteConfiguration(0, new_route_config);
+  WaitForAllBackends(0, 2);
+  CheckRpcSendOk(kNumEchoRpcs, RpcOptions().set_wait_for_ready(true));
+  CheckRpcSendOk(kNumEcho1Rpcs, RpcOptions()
+                                    .set_rpc_service(SERVICE_ECHO1)
+                                    .set_rpc_method(METHOD_ECHO1)
+                                    .set_wait_for_ready(true));
+  CheckRpcSendOk(kNumEcho2Rpcs, RpcOptions()
+                                    .set_rpc_service(SERVICE_ECHO2)
+                                    .set_rpc_method(METHOD_ECHO2)
+                                    .set_wait_for_ready(true));
+  // Make sure RPCs all go to the correct backend.
+  for (size_t i = 0; i < 2; ++i) {
+    EXPECT_EQ(kNumEchoRpcs / 2,
+              backends_[i]->backend_service()->request_count());
+    EXPECT_EQ(0, backends_[i]->backend_service1()->request_count());
+    EXPECT_EQ(0, backends_[i]->backend_service2()->request_count());
+  }
+  EXPECT_EQ(0, backends_[2]->backend_service()->request_count());
+  EXPECT_EQ(kNumEcho1Rpcs, backends_[2]->backend_service1()->request_count());
+  EXPECT_EQ(0, backends_[2]->backend_service2()->request_count());
+  EXPECT_EQ(0, backends_[3]->backend_service()->request_count());
+  EXPECT_EQ(0, backends_[3]->backend_service1()->request_count());
+  EXPECT_EQ(kNumEcho2Rpcs, backends_[3]->backend_service2()->request_count());
+}
+
+TEST_P(LdsRdsTest, XdsRoutingPathMatchingCaseInsensitive) {
+  const char* kNewCluster1Name = "new_cluster_1";
+  const char* kNewEdsService1Name = "new_eds_service_name_1";
+  const char* kNewCluster2Name = "new_cluster_2";
+  const char* kNewEdsService2Name = "new_eds_service_name_2";
+  const size_t kNumEcho1Rpcs = 10;
+  const size_t kNumEchoRpcs = 30;
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Populate new EDS resources.
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 1)},
+  });
+  EdsResourceArgs args1({
+      {"locality0", CreateEndpointsForBackends(1, 2)},
+  });
+  EdsResourceArgs args2({
+      {"locality0", CreateEndpointsForBackends(2, 3)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args1, kNewEdsService1Name));
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args2, kNewEdsService2Name));
+  // Populate new CDS resources.
+  Cluster new_cluster1 = default_cluster_;
+  new_cluster1.set_name(kNewCluster1Name);
+  new_cluster1.mutable_eds_cluster_config()->set_service_name(
+      kNewEdsService1Name);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster1);
+  Cluster new_cluster2 = default_cluster_;
+  new_cluster2.set_name(kNewCluster2Name);
+  new_cluster2.mutable_eds_cluster_config()->set_service_name(
+      kNewEdsService2Name);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster2);
+  // Populating Route Configurations for LDS.
+  RouteConfiguration new_route_config = default_route_config_;
+  // First route will not match, since it's case-sensitive.
+  // Second route will match with same path.
+  auto* route1 = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  route1->mutable_match()->set_path("/GrPc.TeStInG.EcHoTeSt1SErViCe/EcHo1");
+  route1->mutable_route()->set_cluster(kNewCluster1Name);
+  auto* route2 = new_route_config.mutable_virtual_hosts(0)->add_routes();
+  route2->mutable_match()->set_path("/GrPc.TeStInG.EcHoTeSt1SErViCe/EcHo1");
+  route2->mutable_match()->mutable_case_sensitive()->set_value(false);
+  route2->mutable_route()->set_cluster(kNewCluster2Name);
+  auto* default_route = new_route_config.mutable_virtual_hosts(0)->add_routes();
+  default_route->mutable_match()->set_prefix("");
+  default_route->mutable_route()->set_cluster(kDefaultClusterName);
+  SetRouteConfiguration(0, new_route_config);
+  CheckRpcSendOk(kNumEchoRpcs, RpcOptions().set_wait_for_ready(true));
+  CheckRpcSendOk(kNumEcho1Rpcs, RpcOptions()
+                                    .set_rpc_service(SERVICE_ECHO1)
+                                    .set_rpc_method(METHOD_ECHO1)
+                                    .set_wait_for_ready(true));
+  // Make sure RPCs all go to the correct backend.
+  EXPECT_EQ(kNumEchoRpcs, backends_[0]->backend_service()->request_count());
+  EXPECT_EQ(0, backends_[0]->backend_service1()->request_count());
+  EXPECT_EQ(0, backends_[1]->backend_service()->request_count());
+  EXPECT_EQ(0, backends_[1]->backend_service1()->request_count());
+  EXPECT_EQ(0, backends_[2]->backend_service()->request_count());
+  EXPECT_EQ(kNumEcho1Rpcs, backends_[2]->backend_service1()->request_count());
+}
+
+TEST_P(LdsRdsTest, XdsRoutingPrefixMatching) {
+  const char* kNewCluster1Name = "new_cluster_1";
+  const char* kNewEdsService1Name = "new_eds_service_name_1";
+  const char* kNewCluster2Name = "new_cluster_2";
+  const char* kNewEdsService2Name = "new_eds_service_name_2";
+  const size_t kNumEcho1Rpcs = 10;
+  const size_t kNumEcho2Rpcs = 20;
+  const size_t kNumEchoRpcs = 30;
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Populate new EDS resources.
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 2)},
+  });
+  EdsResourceArgs args1({
+      {"locality0", CreateEndpointsForBackends(2, 3)},
+  });
+  EdsResourceArgs args2({
+      {"locality0", CreateEndpointsForBackends(3, 4)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args1, kNewEdsService1Name));
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args2, kNewEdsService2Name));
+  // Populate new CDS resources.
+  Cluster new_cluster1 = default_cluster_;
+  new_cluster1.set_name(kNewCluster1Name);
+  new_cluster1.mutable_eds_cluster_config()->set_service_name(
+      kNewEdsService1Name);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster1);
+  Cluster new_cluster2 = default_cluster_;
+  new_cluster2.set_name(kNewCluster2Name);
+  new_cluster2.mutable_eds_cluster_config()->set_service_name(
+      kNewEdsService2Name);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster2);
+  // Populating Route Configurations for LDS.
+  RouteConfiguration new_route_config = default_route_config_;
+  auto* route1 = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/");
+  route1->mutable_route()->set_cluster(kNewCluster1Name);
+  auto* route2 = new_route_config.mutable_virtual_hosts(0)->add_routes();
+  route2->mutable_match()->set_prefix("/grpc.testing.EchoTest2Service/");
+  route2->mutable_route()->set_cluster(kNewCluster2Name);
+  auto* default_route = new_route_config.mutable_virtual_hosts(0)->add_routes();
+  default_route->mutable_match()->set_prefix("");
+  default_route->mutable_route()->set_cluster(kDefaultClusterName);
+  SetRouteConfiguration(0, new_route_config);
+  WaitForAllBackends(0, 2);
+  CheckRpcSendOk(kNumEchoRpcs, RpcOptions().set_wait_for_ready(true));
+  CheckRpcSendOk(
+      kNumEcho1Rpcs,
+      RpcOptions().set_rpc_service(SERVICE_ECHO1).set_wait_for_ready(true));
+  CheckRpcSendOk(
+      kNumEcho2Rpcs,
+      RpcOptions().set_rpc_service(SERVICE_ECHO2).set_wait_for_ready(true));
+  // Make sure RPCs all go to the correct backend.
+  for (size_t i = 0; i < 2; ++i) {
+    EXPECT_EQ(kNumEchoRpcs / 2,
+              backends_[i]->backend_service()->request_count());
+    EXPECT_EQ(0, backends_[i]->backend_service1()->request_count());
+    EXPECT_EQ(0, backends_[i]->backend_service2()->request_count());
+  }
+  EXPECT_EQ(0, backends_[2]->backend_service()->request_count());
+  EXPECT_EQ(kNumEcho1Rpcs, backends_[2]->backend_service1()->request_count());
+  EXPECT_EQ(0, backends_[2]->backend_service2()->request_count());
+  EXPECT_EQ(0, backends_[3]->backend_service()->request_count());
+  EXPECT_EQ(0, backends_[3]->backend_service1()->request_count());
+  EXPECT_EQ(kNumEcho2Rpcs, backends_[3]->backend_service2()->request_count());
+}
+
+TEST_P(LdsRdsTest, XdsRoutingPrefixMatchingCaseInsensitive) {
+  const char* kNewCluster1Name = "new_cluster_1";
+  const char* kNewEdsService1Name = "new_eds_service_name_1";
+  const char* kNewCluster2Name = "new_cluster_2";
+  const char* kNewEdsService2Name = "new_eds_service_name_2";
+  const size_t kNumEcho1Rpcs = 10;
+  const size_t kNumEchoRpcs = 30;
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Populate new EDS resources.
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 1)},
+  });
+  EdsResourceArgs args1({
+      {"locality0", CreateEndpointsForBackends(1, 2)},
+  });
+  EdsResourceArgs args2({
+      {"locality0", CreateEndpointsForBackends(2, 3)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args1, kNewEdsService1Name));
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args2, kNewEdsService2Name));
+  // Populate new CDS resources.
+  Cluster new_cluster1 = default_cluster_;
+  new_cluster1.set_name(kNewCluster1Name);
+  new_cluster1.mutable_eds_cluster_config()->set_service_name(
+      kNewEdsService1Name);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster1);
+  Cluster new_cluster2 = default_cluster_;
+  new_cluster2.set_name(kNewCluster2Name);
+  new_cluster2.mutable_eds_cluster_config()->set_service_name(
+      kNewEdsService2Name);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster2);
+  // Populating Route Configurations for LDS.
+  RouteConfiguration new_route_config = default_route_config_;
+  // First route will not match, since it's case-sensitive.
+  // Second route will match with same path.
+  auto* route1 = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  route1->mutable_match()->set_prefix("/GrPc.TeStInG.EcHoTeSt1SErViCe");
+  route1->mutable_route()->set_cluster(kNewCluster1Name);
+  auto* route2 = new_route_config.mutable_virtual_hosts(0)->add_routes();
+  route2->mutable_match()->set_prefix("/GrPc.TeStInG.EcHoTeSt1SErViCe");
+  route2->mutable_match()->mutable_case_sensitive()->set_value(false);
+  route2->mutable_route()->set_cluster(kNewCluster2Name);
+  auto* default_route = new_route_config.mutable_virtual_hosts(0)->add_routes();
+  default_route->mutable_match()->set_prefix("");
+  default_route->mutable_route()->set_cluster(kDefaultClusterName);
+  SetRouteConfiguration(0, new_route_config);
+  CheckRpcSendOk(kNumEchoRpcs, RpcOptions().set_wait_for_ready(true));
+  CheckRpcSendOk(kNumEcho1Rpcs, RpcOptions()
+                                    .set_rpc_service(SERVICE_ECHO1)
+                                    .set_rpc_method(METHOD_ECHO1)
+                                    .set_wait_for_ready(true));
+  // Make sure RPCs all go to the correct backend.
+  EXPECT_EQ(kNumEchoRpcs, backends_[0]->backend_service()->request_count());
+  EXPECT_EQ(0, backends_[0]->backend_service1()->request_count());
+  EXPECT_EQ(0, backends_[1]->backend_service()->request_count());
+  EXPECT_EQ(0, backends_[1]->backend_service1()->request_count());
+  EXPECT_EQ(0, backends_[2]->backend_service()->request_count());
+  EXPECT_EQ(kNumEcho1Rpcs, backends_[2]->backend_service1()->request_count());
+}
+
+TEST_P(LdsRdsTest, XdsRoutingPathRegexMatching) {
+  const char* kNewCluster1Name = "new_cluster_1";
+  const char* kNewEdsService1Name = "new_eds_service_name_1";
+  const char* kNewCluster2Name = "new_cluster_2";
+  const char* kNewEdsService2Name = "new_eds_service_name_2";
+  const size_t kNumEcho1Rpcs = 10;
+  const size_t kNumEcho2Rpcs = 20;
+  const size_t kNumEchoRpcs = 30;
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Populate new EDS resources.
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 2)},
+  });
+  EdsResourceArgs args1({
+      {"locality0", CreateEndpointsForBackends(2, 3)},
+  });
+  EdsResourceArgs args2({
+      {"locality0", CreateEndpointsForBackends(3, 4)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args1, kNewEdsService1Name));
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args2, kNewEdsService2Name));
+  // Populate new CDS resources.
+  Cluster new_cluster1 = default_cluster_;
+  new_cluster1.set_name(kNewCluster1Name);
+  new_cluster1.mutable_eds_cluster_config()->set_service_name(
+      kNewEdsService1Name);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster1);
+  Cluster new_cluster2 = default_cluster_;
+  new_cluster2.set_name(kNewCluster2Name);
+  new_cluster2.mutable_eds_cluster_config()->set_service_name(
+      kNewEdsService2Name);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster2);
+  // Populating Route Configurations for LDS.
+  RouteConfiguration new_route_config = default_route_config_;
+  auto* route1 = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  // Will match "/grpc.testing.EchoTest1Service/"
+  route1->mutable_match()->mutable_safe_regex()->set_regex(".*1.*");
+  route1->mutable_route()->set_cluster(kNewCluster1Name);
+  auto* route2 = new_route_config.mutable_virtual_hosts(0)->add_routes();
+  // Will match "/grpc.testing.EchoTest2Service/"
+  route2->mutable_match()->mutable_safe_regex()->set_regex(".*2.*");
+  route2->mutable_route()->set_cluster(kNewCluster2Name);
+  auto* default_route = new_route_config.mutable_virtual_hosts(0)->add_routes();
+  default_route->mutable_match()->set_prefix("");
+  default_route->mutable_route()->set_cluster(kDefaultClusterName);
+  SetRouteConfiguration(0, new_route_config);
+  WaitForAllBackends(0, 2);
+  CheckRpcSendOk(kNumEchoRpcs, RpcOptions().set_wait_for_ready(true));
+  CheckRpcSendOk(
+      kNumEcho1Rpcs,
+      RpcOptions().set_rpc_service(SERVICE_ECHO1).set_wait_for_ready(true));
+  CheckRpcSendOk(
+      kNumEcho2Rpcs,
+      RpcOptions().set_rpc_service(SERVICE_ECHO2).set_wait_for_ready(true));
+  // Make sure RPCs all go to the correct backend.
+  for (size_t i = 0; i < 2; ++i) {
+    EXPECT_EQ(kNumEchoRpcs / 2,
+              backends_[i]->backend_service()->request_count());
+    EXPECT_EQ(0, backends_[i]->backend_service1()->request_count());
+    EXPECT_EQ(0, backends_[i]->backend_service2()->request_count());
+  }
+  EXPECT_EQ(0, backends_[2]->backend_service()->request_count());
+  EXPECT_EQ(kNumEcho1Rpcs, backends_[2]->backend_service1()->request_count());
+  EXPECT_EQ(0, backends_[2]->backend_service2()->request_count());
+  EXPECT_EQ(0, backends_[3]->backend_service()->request_count());
+  EXPECT_EQ(0, backends_[3]->backend_service1()->request_count());
+  EXPECT_EQ(kNumEcho2Rpcs, backends_[3]->backend_service2()->request_count());
+}
+
+TEST_P(LdsRdsTest, XdsRoutingWeightedCluster) {
+  const char* kNewCluster1Name = "new_cluster_1";
+  const char* kNewEdsService1Name = "new_eds_service_name_1";
+  const char* kNewCluster2Name = "new_cluster_2";
+  const char* kNewEdsService2Name = "new_eds_service_name_2";
+  const char* kNotUsedClusterName = "not_used_cluster";
+  const size_t kNumEchoRpcs = 10;  // RPCs that will go to a fixed backend.
+  const size_t kWeight75 = 75;
+  const size_t kWeight25 = 25;
+  const double kErrorTolerance = 0.05;
+  const double kWeight75Percent = static_cast<double>(kWeight75) / 100;
+  const double kWeight25Percent = static_cast<double>(kWeight25) / 100;
+  const size_t kNumEcho1Rpcs =
+      ComputeIdealNumRpcs(kWeight75Percent, kErrorTolerance);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Populate new EDS resources.
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 1)},
+  });
+  EdsResourceArgs args1({
+      {"locality0", CreateEndpointsForBackends(1, 2)},
+  });
+  EdsResourceArgs args2({
+      {"locality0", CreateEndpointsForBackends(2, 3)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args1, kNewEdsService1Name));
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args2, kNewEdsService2Name));
+  // Populate new CDS resources.
+  Cluster new_cluster1 = default_cluster_;
+  new_cluster1.set_name(kNewCluster1Name);
+  new_cluster1.mutable_eds_cluster_config()->set_service_name(
+      kNewEdsService1Name);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster1);
+  Cluster new_cluster2 = default_cluster_;
+  new_cluster2.set_name(kNewCluster2Name);
+  new_cluster2.mutable_eds_cluster_config()->set_service_name(
+      kNewEdsService2Name);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster2);
+  // Populating Route Configurations for LDS.
+  RouteConfiguration new_route_config = default_route_config_;
+  auto* route1 = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/");
+  auto* weighted_cluster1 =
+      route1->mutable_route()->mutable_weighted_clusters()->add_clusters();
+  weighted_cluster1->set_name(kNewCluster1Name);
+  weighted_cluster1->mutable_weight()->set_value(kWeight75);
+  auto* weighted_cluster2 =
+      route1->mutable_route()->mutable_weighted_clusters()->add_clusters();
+  weighted_cluster2->set_name(kNewCluster2Name);
+  weighted_cluster2->mutable_weight()->set_value(kWeight25);
+  // Cluster with weight 0 will not be used.
+  auto* weighted_cluster3 =
+      route1->mutable_route()->mutable_weighted_clusters()->add_clusters();
+  weighted_cluster3->set_name(kNotUsedClusterName);
+  weighted_cluster3->mutable_weight()->set_value(0);
+  route1->mutable_route()
+      ->mutable_weighted_clusters()
+      ->mutable_total_weight()
+      ->set_value(kWeight75 + kWeight25);
+  auto* default_route = new_route_config.mutable_virtual_hosts(0)->add_routes();
+  default_route->mutable_match()->set_prefix("");
+  default_route->mutable_route()->set_cluster(kDefaultClusterName);
+  SetRouteConfiguration(0, new_route_config);
+  WaitForAllBackends(0, 1);
+  WaitForAllBackends(1, 3, WaitForBackendOptions(),
+                     RpcOptions().set_rpc_service(SERVICE_ECHO1));
+  CheckRpcSendOk(kNumEchoRpcs);
+  CheckRpcSendOk(kNumEcho1Rpcs, RpcOptions().set_rpc_service(SERVICE_ECHO1));
+  // Make sure RPCs all go to the correct backend.
+  EXPECT_EQ(kNumEchoRpcs, backends_[0]->backend_service()->request_count());
+  EXPECT_EQ(0, backends_[0]->backend_service1()->request_count());
+  EXPECT_EQ(0, backends_[1]->backend_service()->request_count());
+  const int weight_75_request_count =
+      backends_[1]->backend_service1()->request_count();
+  EXPECT_EQ(0, backends_[2]->backend_service()->request_count());
+  const int weight_25_request_count =
+      backends_[2]->backend_service1()->request_count();
+  gpr_log(GPR_INFO, "target_75 received %d rpcs and target_25 received %d rpcs",
+          weight_75_request_count, weight_25_request_count);
+  EXPECT_THAT(static_cast<double>(weight_75_request_count) / kNumEcho1Rpcs,
+              ::testing::DoubleNear(kWeight75Percent, kErrorTolerance));
+  EXPECT_THAT(static_cast<double>(weight_25_request_count) / kNumEcho1Rpcs,
+              ::testing::DoubleNear(kWeight25Percent, kErrorTolerance));
+}
+
+TEST_P(LdsRdsTest, RouteActionWeightedTargetDefaultRoute) {
+  const char* kNewCluster1Name = "new_cluster_1";
+  const char* kNewEdsService1Name = "new_eds_service_name_1";
+  const char* kNewCluster2Name = "new_cluster_2";
+  const char* kNewEdsService2Name = "new_eds_service_name_2";
+  const size_t kWeight75 = 75;
+  const size_t kWeight25 = 25;
+  const double kErrorTolerance = 0.05;
+  const double kWeight75Percent = static_cast<double>(kWeight75) / 100;
+  const double kWeight25Percent = static_cast<double>(kWeight25) / 100;
+  const size_t kNumEchoRpcs =
+      ComputeIdealNumRpcs(kWeight75Percent, kErrorTolerance);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Populate new EDS resources.
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 1)},
+  });
+  EdsResourceArgs args1({
+      {"locality0", CreateEndpointsForBackends(1, 2)},
+  });
+  EdsResourceArgs args2({
+      {"locality0", CreateEndpointsForBackends(2, 3)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args1, kNewEdsService1Name));
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args2, kNewEdsService2Name));
+  // Populate new CDS resources.
+  Cluster new_cluster1 = default_cluster_;
+  new_cluster1.set_name(kNewCluster1Name);
+  new_cluster1.mutable_eds_cluster_config()->set_service_name(
+      kNewEdsService1Name);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster1);
+  Cluster new_cluster2 = default_cluster_;
+  new_cluster2.set_name(kNewCluster2Name);
+  new_cluster2.mutable_eds_cluster_config()->set_service_name(
+      kNewEdsService2Name);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster2);
+  // Populating Route Configurations for LDS.
+  RouteConfiguration new_route_config = default_route_config_;
+  auto* route1 = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  route1->mutable_match()->set_prefix("");
+  auto* weighted_cluster1 =
+      route1->mutable_route()->mutable_weighted_clusters()->add_clusters();
+  weighted_cluster1->set_name(kNewCluster1Name);
+  weighted_cluster1->mutable_weight()->set_value(kWeight75);
+  auto* weighted_cluster2 =
+      route1->mutable_route()->mutable_weighted_clusters()->add_clusters();
+  weighted_cluster2->set_name(kNewCluster2Name);
+  weighted_cluster2->mutable_weight()->set_value(kWeight25);
+  route1->mutable_route()
+      ->mutable_weighted_clusters()
+      ->mutable_total_weight()
+      ->set_value(kWeight75 + kWeight25);
+  SetRouteConfiguration(0, new_route_config);
+  WaitForAllBackends(1, 3);
+  CheckRpcSendOk(kNumEchoRpcs);
+  // Make sure RPCs all go to the correct backend.
+  EXPECT_EQ(0, backends_[0]->backend_service()->request_count());
+  const int weight_75_request_count =
+      backends_[1]->backend_service()->request_count();
+  const int weight_25_request_count =
+      backends_[2]->backend_service()->request_count();
+  gpr_log(GPR_INFO, "target_75 received %d rpcs and target_25 received %d rpcs",
+          weight_75_request_count, weight_25_request_count);
+  EXPECT_THAT(static_cast<double>(weight_75_request_count) / kNumEchoRpcs,
+              ::testing::DoubleNear(kWeight75Percent, kErrorTolerance));
+  EXPECT_THAT(static_cast<double>(weight_25_request_count) / kNumEchoRpcs,
+              ::testing::DoubleNear(kWeight25Percent, kErrorTolerance));
+}
+
+TEST_P(LdsRdsTest, XdsRoutingWeightedClusterUpdateWeights) {
+  const char* kNewCluster1Name = "new_cluster_1";
+  const char* kNewEdsService1Name = "new_eds_service_name_1";
+  const char* kNewCluster2Name = "new_cluster_2";
+  const char* kNewEdsService2Name = "new_eds_service_name_2";
+  const char* kNewCluster3Name = "new_cluster_3";
+  const char* kNewEdsService3Name = "new_eds_service_name_3";
+  const size_t kNumEchoRpcs = 10;
+  const size_t kWeight75 = 75;
+  const size_t kWeight25 = 25;
+  const size_t kWeight50 = 50;
+  const double kErrorTolerance = 0.05;
+  const double kWeight75Percent = static_cast<double>(kWeight75) / 100;
+  const double kWeight25Percent = static_cast<double>(kWeight25) / 100;
+  const double kWeight50Percent = static_cast<double>(kWeight50) / 100;
+  const size_t kNumEcho1Rpcs7525 =
+      ComputeIdealNumRpcs(kWeight75Percent, kErrorTolerance);
+  const size_t kNumEcho1Rpcs5050 =
+      ComputeIdealNumRpcs(kWeight50Percent, kErrorTolerance);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Populate new EDS resources.
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 1)},
+  });
+  EdsResourceArgs args1({
+      {"locality0", CreateEndpointsForBackends(1, 2)},
+  });
+  EdsResourceArgs args2({
+      {"locality0", CreateEndpointsForBackends(2, 3)},
+  });
+  EdsResourceArgs args3({
+      {"locality0", CreateEndpointsForBackends(3, 4)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args1, kNewEdsService1Name));
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args2, kNewEdsService2Name));
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args3, kNewEdsService3Name));
+  // Populate new CDS resources.
+  Cluster new_cluster1 = default_cluster_;
+  new_cluster1.set_name(kNewCluster1Name);
+  new_cluster1.mutable_eds_cluster_config()->set_service_name(
+      kNewEdsService1Name);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster1);
+  Cluster new_cluster2 = default_cluster_;
+  new_cluster2.set_name(kNewCluster2Name);
+  new_cluster2.mutable_eds_cluster_config()->set_service_name(
+      kNewEdsService2Name);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster2);
+  Cluster new_cluster3 = default_cluster_;
+  new_cluster3.set_name(kNewCluster3Name);
+  new_cluster3.mutable_eds_cluster_config()->set_service_name(
+      kNewEdsService3Name);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster3);
+  // Populating Route Configurations.
+  RouteConfiguration new_route_config = default_route_config_;
+  auto* route1 = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/");
+  auto* weighted_cluster1 =
+      route1->mutable_route()->mutable_weighted_clusters()->add_clusters();
+  weighted_cluster1->set_name(kNewCluster1Name);
+  weighted_cluster1->mutable_weight()->set_value(kWeight75);
+  auto* weighted_cluster2 =
+      route1->mutable_route()->mutable_weighted_clusters()->add_clusters();
+  weighted_cluster2->set_name(kNewCluster2Name);
+  weighted_cluster2->mutable_weight()->set_value(kWeight25);
+  route1->mutable_route()
+      ->mutable_weighted_clusters()
+      ->mutable_total_weight()
+      ->set_value(kWeight75 + kWeight25);
+  auto* default_route = new_route_config.mutable_virtual_hosts(0)->add_routes();
+  default_route->mutable_match()->set_prefix("");
+  default_route->mutable_route()->set_cluster(kDefaultClusterName);
+  SetRouteConfiguration(0, new_route_config);
+  WaitForAllBackends(0, 1);
+  WaitForAllBackends(1, 3, WaitForBackendOptions(),
+                     RpcOptions().set_rpc_service(SERVICE_ECHO1));
+  CheckRpcSendOk(kNumEchoRpcs);
+  CheckRpcSendOk(kNumEcho1Rpcs7525,
+                 RpcOptions().set_rpc_service(SERVICE_ECHO1));
+  // Make sure RPCs all go to the correct backend.
+  EXPECT_EQ(kNumEchoRpcs, backends_[0]->backend_service()->request_count());
+  EXPECT_EQ(0, backends_[0]->backend_service1()->request_count());
+  EXPECT_EQ(0, backends_[1]->backend_service()->request_count());
+  const int weight_75_request_count =
+      backends_[1]->backend_service1()->request_count();
+  EXPECT_EQ(0, backends_[1]->backend_service2()->request_count());
+  EXPECT_EQ(0, backends_[2]->backend_service()->request_count());
+  const int weight_25_request_count =
+      backends_[2]->backend_service1()->request_count();
+  EXPECT_EQ(0, backends_[3]->backend_service()->request_count());
+  EXPECT_EQ(0, backends_[3]->backend_service1()->request_count());
+  gpr_log(GPR_INFO, "target_75 received %d rpcs and target_25 received %d rpcs",
+          weight_75_request_count, weight_25_request_count);
+  EXPECT_THAT(static_cast<double>(weight_75_request_count) / kNumEcho1Rpcs7525,
+              ::testing::DoubleNear(kWeight75Percent, kErrorTolerance));
+  EXPECT_THAT(static_cast<double>(weight_25_request_count) / kNumEcho1Rpcs7525,
+              ::testing::DoubleNear(kWeight25Percent, kErrorTolerance));
+  // Change Route Configurations: same clusters different weights.
+  weighted_cluster1->mutable_weight()->set_value(kWeight50);
+  weighted_cluster2->mutable_weight()->set_value(kWeight50);
+  // Change default route to a new cluster to help to identify when new
+  // polices are seen by the client.
+  default_route->mutable_route()->set_cluster(kNewCluster3Name);
+  SetRouteConfiguration(0, new_route_config);
+  ResetBackendCounters();
+  WaitForAllBackends(3, 4);
+  CheckRpcSendOk(kNumEchoRpcs);
+  CheckRpcSendOk(kNumEcho1Rpcs5050,
+                 RpcOptions().set_rpc_service(SERVICE_ECHO1));
+  // Make sure RPCs all go to the correct backend.
+  EXPECT_EQ(0, backends_[0]->backend_service()->request_count());
+  EXPECT_EQ(0, backends_[0]->backend_service1()->request_count());
+  EXPECT_EQ(0, backends_[1]->backend_service()->request_count());
+  const int weight_50_request_count_1 =
+      backends_[1]->backend_service1()->request_count();
+  EXPECT_EQ(0, backends_[2]->backend_service()->request_count());
+  const int weight_50_request_count_2 =
+      backends_[2]->backend_service1()->request_count();
+  EXPECT_EQ(kNumEchoRpcs, backends_[3]->backend_service()->request_count());
+  EXPECT_EQ(0, backends_[3]->backend_service1()->request_count());
+  EXPECT_THAT(
+      static_cast<double>(weight_50_request_count_1) / kNumEcho1Rpcs5050,
+      ::testing::DoubleNear(kWeight50Percent, kErrorTolerance));
+  EXPECT_THAT(
+      static_cast<double>(weight_50_request_count_2) / kNumEcho1Rpcs5050,
+      ::testing::DoubleNear(kWeight50Percent, kErrorTolerance));
+}
+
+TEST_P(LdsRdsTest, XdsRoutingWeightedClusterUpdateClusters) {
+  const char* kNewCluster1Name = "new_cluster_1";
+  const char* kNewEdsService1Name = "new_eds_service_name_1";
+  const char* kNewCluster2Name = "new_cluster_2";
+  const char* kNewEdsService2Name = "new_eds_service_name_2";
+  const char* kNewCluster3Name = "new_cluster_3";
+  const char* kNewEdsService3Name = "new_eds_service_name_3";
+  const size_t kNumEchoRpcs = 10;
+  const size_t kWeight75 = 75;
+  const size_t kWeight25 = 25;
+  const size_t kWeight50 = 50;
+  const double kErrorTolerance = 0.05;
+  const double kWeight75Percent = static_cast<double>(kWeight75) / 100;
+  const double kWeight25Percent = static_cast<double>(kWeight25) / 100;
+  const double kWeight50Percent = static_cast<double>(kWeight50) / 100;
+  const size_t kNumEcho1Rpcs7525 =
+      ComputeIdealNumRpcs(kWeight75Percent, kErrorTolerance);
+  const size_t kNumEcho1Rpcs5050 =
+      ComputeIdealNumRpcs(kWeight50Percent, kErrorTolerance);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Populate new EDS resources.
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 1)},
+  });
+  EdsResourceArgs args1({
+      {"locality0", CreateEndpointsForBackends(1, 2)},
+  });
+  EdsResourceArgs args2({
+      {"locality0", CreateEndpointsForBackends(2, 3)},
+  });
+  EdsResourceArgs args3({
+      {"locality0", CreateEndpointsForBackends(3, 4)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args1, kNewEdsService1Name));
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args2, kNewEdsService2Name));
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args3, kNewEdsService3Name));
+  // Populate new CDS resources.
+  Cluster new_cluster1 = default_cluster_;
+  new_cluster1.set_name(kNewCluster1Name);
+  new_cluster1.mutable_eds_cluster_config()->set_service_name(
+      kNewEdsService1Name);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster1);
+  Cluster new_cluster2 = default_cluster_;
+  new_cluster2.set_name(kNewCluster2Name);
+  new_cluster2.mutable_eds_cluster_config()->set_service_name(
+      kNewEdsService2Name);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster2);
+  Cluster new_cluster3 = default_cluster_;
+  new_cluster3.set_name(kNewCluster3Name);
+  new_cluster3.mutable_eds_cluster_config()->set_service_name(
+      kNewEdsService3Name);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster3);
+  // Populating Route Configurations.
+  RouteConfiguration new_route_config = default_route_config_;
+  auto* route1 = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/");
+  auto* weighted_cluster1 =
+      route1->mutable_route()->mutable_weighted_clusters()->add_clusters();
+  weighted_cluster1->set_name(kNewCluster1Name);
+  weighted_cluster1->mutable_weight()->set_value(kWeight75);
+  auto* weighted_cluster2 =
+      route1->mutable_route()->mutable_weighted_clusters()->add_clusters();
+  weighted_cluster2->set_name(kDefaultClusterName);
+  weighted_cluster2->mutable_weight()->set_value(kWeight25);
+  route1->mutable_route()
+      ->mutable_weighted_clusters()
+      ->mutable_total_weight()
+      ->set_value(kWeight75 + kWeight25);
+  auto* default_route = new_route_config.mutable_virtual_hosts(0)->add_routes();
+  default_route->mutable_match()->set_prefix("");
+  default_route->mutable_route()->set_cluster(kDefaultClusterName);
+  SetRouteConfiguration(0, new_route_config);
+  WaitForBackend(0);
+  WaitForBackend(1, WaitForBackendOptions(),
+                 RpcOptions().set_rpc_service(SERVICE_ECHO1));
+  CheckRpcSendOk(kNumEchoRpcs);
+  CheckRpcSendOk(kNumEcho1Rpcs7525,
+                 RpcOptions().set_rpc_service(SERVICE_ECHO1));
+  // Make sure RPCs all go to the correct backend.
+  EXPECT_EQ(kNumEchoRpcs, backends_[0]->backend_service()->request_count());
+  int weight_25_request_count =
+      backends_[0]->backend_service1()->request_count();
+  EXPECT_EQ(0, backends_[1]->backend_service()->request_count());
+  int weight_75_request_count =
+      backends_[1]->backend_service1()->request_count();
+  EXPECT_EQ(0, backends_[2]->backend_service()->request_count());
+  EXPECT_EQ(0, backends_[2]->backend_service1()->request_count());
+  EXPECT_EQ(0, backends_[3]->backend_service()->request_count());
+  EXPECT_EQ(0, backends_[3]->backend_service1()->request_count());
+  gpr_log(GPR_INFO, "target_75 received %d rpcs and target_25 received %d rpcs",
+          weight_75_request_count, weight_25_request_count);
+  EXPECT_THAT(static_cast<double>(weight_75_request_count) / kNumEcho1Rpcs7525,
+              ::testing::DoubleNear(kWeight75Percent, kErrorTolerance));
+  EXPECT_THAT(static_cast<double>(weight_25_request_count) / kNumEcho1Rpcs7525,
+              ::testing::DoubleNear(kWeight25Percent, kErrorTolerance));
+  // Change Route Configurations: new set of clusters with different weights.
+  weighted_cluster1->mutable_weight()->set_value(kWeight50);
+  weighted_cluster2->set_name(kNewCluster2Name);
+  weighted_cluster2->mutable_weight()->set_value(kWeight50);
+  SetRouteConfiguration(0, new_route_config);
+  ResetBackendCounters();
+  WaitForBackend(2, WaitForBackendOptions(),
+                 RpcOptions().set_rpc_service(SERVICE_ECHO1));
+  CheckRpcSendOk(kNumEchoRpcs);
+  CheckRpcSendOk(kNumEcho1Rpcs5050,
+                 RpcOptions().set_rpc_service(SERVICE_ECHO1));
+  // Make sure RPCs all go to the correct backend.
+  EXPECT_EQ(kNumEchoRpcs, backends_[0]->backend_service()->request_count());
+  EXPECT_EQ(0, backends_[0]->backend_service1()->request_count());
+  EXPECT_EQ(0, backends_[1]->backend_service()->request_count());
+  const int weight_50_request_count_1 =
+      backends_[1]->backend_service1()->request_count();
+  EXPECT_EQ(0, backends_[2]->backend_service()->request_count());
+  const int weight_50_request_count_2 =
+      backends_[2]->backend_service1()->request_count();
+  EXPECT_EQ(0, backends_[3]->backend_service()->request_count());
+  EXPECT_EQ(0, backends_[3]->backend_service1()->request_count());
+  EXPECT_THAT(
+      static_cast<double>(weight_50_request_count_1) / kNumEcho1Rpcs5050,
+      ::testing::DoubleNear(kWeight50Percent, kErrorTolerance));
+  EXPECT_THAT(
+      static_cast<double>(weight_50_request_count_2) / kNumEcho1Rpcs5050,
+      ::testing::DoubleNear(kWeight50Percent, kErrorTolerance));
+  // Change Route Configurations.
+  weighted_cluster1->mutable_weight()->set_value(kWeight75);
+  weighted_cluster2->set_name(kNewCluster3Name);
+  weighted_cluster2->mutable_weight()->set_value(kWeight25);
+  SetRouteConfiguration(0, new_route_config);
+  ResetBackendCounters();
+  WaitForBackend(3, WaitForBackendOptions(),
+                 RpcOptions().set_rpc_service(SERVICE_ECHO1));
+  CheckRpcSendOk(kNumEchoRpcs);
+  CheckRpcSendOk(kNumEcho1Rpcs7525,
+                 RpcOptions().set_rpc_service(SERVICE_ECHO1));
+  // Make sure RPCs all go to the correct backend.
+  EXPECT_EQ(kNumEchoRpcs, backends_[0]->backend_service()->request_count());
+  EXPECT_EQ(0, backends_[0]->backend_service1()->request_count());
+  EXPECT_EQ(0, backends_[1]->backend_service()->request_count());
+  weight_75_request_count = backends_[1]->backend_service1()->request_count();
+  EXPECT_EQ(0, backends_[2]->backend_service()->request_count());
+  EXPECT_EQ(0, backends_[2]->backend_service1()->request_count());
+  EXPECT_EQ(0, backends_[3]->backend_service()->request_count());
+  weight_25_request_count = backends_[3]->backend_service1()->request_count();
+  gpr_log(GPR_INFO, "target_75 received %d rpcs and target_25 received %d rpcs",
+          weight_75_request_count, weight_25_request_count);
+  EXPECT_THAT(static_cast<double>(weight_75_request_count) / kNumEcho1Rpcs7525,
+              ::testing::DoubleNear(kWeight75Percent, kErrorTolerance));
+  EXPECT_THAT(static_cast<double>(weight_25_request_count) / kNumEcho1Rpcs7525,
+              ::testing::DoubleNear(kWeight25Percent, kErrorTolerance));
+}
+
+TEST_P(LdsRdsTest, XdsRoutingClusterUpdateClusters) {
+  const char* kNewClusterName = "new_cluster";
+  const char* kNewEdsServiceName = "new_eds_service_name";
+  const size_t kNumEchoRpcs = 5;
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Populate new EDS resources.
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 1)},
+  });
+  EdsResourceArgs args1({
+      {"locality0", CreateEndpointsForBackends(1, 2)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args1, kNewEdsServiceName));
+  // Populate new CDS resources.
+  Cluster new_cluster = default_cluster_;
+  new_cluster.set_name(kNewClusterName);
+  new_cluster.mutable_eds_cluster_config()->set_service_name(
+      kNewEdsServiceName);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster);
+  // Send Route Configuration.
+  RouteConfiguration new_route_config = default_route_config_;
+  SetRouteConfiguration(0, new_route_config);
+  WaitForAllBackends(0, 1);
+  CheckRpcSendOk(kNumEchoRpcs);
+  // Make sure RPCs all go to the correct backend.
+  EXPECT_EQ(kNumEchoRpcs, backends_[0]->backend_service()->request_count());
+  // Change Route Configurations: new default cluster.
+  auto* default_route =
+      new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  default_route->mutable_route()->set_cluster(kNewClusterName);
+  SetRouteConfiguration(0, new_route_config);
+  WaitForAllBackends(1, 2);
+  CheckRpcSendOk(kNumEchoRpcs);
+  // Make sure RPCs all go to the correct backend.
+  EXPECT_EQ(kNumEchoRpcs, backends_[1]->backend_service()->request_count());
+}
+
+TEST_P(LdsRdsTest, XdsRoutingClusterUpdateClustersWithPickingDelays) {
+  const char* kNewClusterName = "new_cluster";
+  const char* kNewEdsServiceName = "new_eds_service_name";
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Populate new EDS resources.
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 1)},
+  });
+  EdsResourceArgs args1({
+      {"locality0", CreateEndpointsForBackends(1, 2)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args1, kNewEdsServiceName));
+  // Populate new CDS resources.
+  Cluster new_cluster = default_cluster_;
+  new_cluster.set_name(kNewClusterName);
+  new_cluster.mutable_eds_cluster_config()->set_service_name(
+      kNewEdsServiceName);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster);
+  // Bring down the current backend: 0, this will delay route picking time,
+  // resulting in un-committed RPCs.
+  ShutdownBackend(0);
+  // Send a RouteConfiguration with a default route that points to
+  // backend 0.
+  RouteConfiguration new_route_config = default_route_config_;
+  SetRouteConfiguration(0, new_route_config);
+  // Send exactly one RPC with no deadline and with wait_for_ready=true.
+  // This RPC will not complete until after backend 0 is started.
+  std::thread sending_rpc([this]() {
+    CheckRpcSendOk(1, RpcOptions().set_wait_for_ready(true).set_timeout_ms(0));
+  });
+  // Send a non-wait_for_ready RPC which should fail, this will tell us
+  // that the client has received the update and attempted to connect.
+  const Status status = SendRpc(RpcOptions().set_timeout_ms(0));
+  EXPECT_FALSE(status.ok());
+  // Send a update RouteConfiguration to use backend 1.
+  auto* default_route =
+      new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  default_route->mutable_route()->set_cluster(kNewClusterName);
+  SetRouteConfiguration(0, new_route_config);
+  // Wait for RPCs to go to the new backend: 1, this ensures that the client
+  // has processed the update.
+  WaitForBackend(
+      1, WaitForBackendOptions().set_reset_counters(false).set_allow_failures(
+             true));
+  // Bring up the previous backend: 0, this will allow the delayed RPC to
+  // finally call on_call_committed upon completion.
+  StartBackend(0);
+  sending_rpc.join();
+  // Make sure RPCs go to the correct backend:
+  EXPECT_EQ(1, backends_[0]->backend_service()->request_count());
+  EXPECT_EQ(1, backends_[1]->backend_service()->request_count());
+}
+
+TEST_P(LdsRdsTest, XdsRoutingApplyXdsTimeout) {
+  const int64_t kTimeoutMillis = 500;
+  const int64_t kTimeoutNano = kTimeoutMillis * 1000000;
+  const int64_t kTimeoutGrpcTimeoutHeaderMaxSecond = 1;
+  const int64_t kTimeoutMaxStreamDurationSecond = 2;
+  const int64_t kTimeoutHttpMaxStreamDurationSecond = 3;
+  const int64_t kTimeoutApplicationSecond = 4;
+  const char* kNewCluster1Name = "new_cluster_1";
+  const char* kNewEdsService1Name = "new_eds_service_name_1";
+  const char* kNewCluster2Name = "new_cluster_2";
+  const char* kNewEdsService2Name = "new_eds_service_name_2";
+  const char* kNewCluster3Name = "new_cluster_3";
+  const char* kNewEdsService3Name = "new_eds_service_name_3";
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Populate new EDS resources.
+  EdsResourceArgs args({{"locality0", {MakeNonExistantEndpoint()}}});
+  EdsResourceArgs args1({{"locality0", {MakeNonExistantEndpoint()}}});
+  EdsResourceArgs args2({{"locality0", {MakeNonExistantEndpoint()}}});
+  EdsResourceArgs args3({{"locality0", {MakeNonExistantEndpoint()}}});
+  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args1, kNewEdsService1Name));
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args2, kNewEdsService2Name));
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args3, kNewEdsService3Name));
+  // Populate new CDS resources.
+  Cluster new_cluster1 = default_cluster_;
+  new_cluster1.set_name(kNewCluster1Name);
+  new_cluster1.mutable_eds_cluster_config()->set_service_name(
+      kNewEdsService1Name);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster1);
+  Cluster new_cluster2 = default_cluster_;
+  new_cluster2.set_name(kNewCluster2Name);
+  new_cluster2.mutable_eds_cluster_config()->set_service_name(
+      kNewEdsService2Name);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster2);
+  Cluster new_cluster3 = default_cluster_;
+  new_cluster3.set_name(kNewCluster3Name);
+  new_cluster3.mutable_eds_cluster_config()->set_service_name(
+      kNewEdsService3Name);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster3);
+  // Construct listener.
+  auto listener = default_listener_;
+  HttpConnectionManager http_connection_manager;
+  listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
+      &http_connection_manager);
+  // Set up HTTP max_stream_duration of 3.5 seconds
+  auto* duration =
+      http_connection_manager.mutable_common_http_protocol_options()
+          ->mutable_max_stream_duration();
+  duration->set_seconds(kTimeoutHttpMaxStreamDurationSecond);
+  duration->set_nanos(kTimeoutNano);
+  listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
+      http_connection_manager);
+  // Construct route config.
+  RouteConfiguration new_route_config = default_route_config_;
+  // route 1: Set max_stream_duration of 2.5 seconds, Set
+  // grpc_timeout_header_max of 1.5
+  auto* route1 = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  route1->mutable_match()->set_path("/grpc.testing.EchoTest1Service/Echo1");
+  route1->mutable_route()->set_cluster(kNewCluster1Name);
+  auto* max_stream_duration =
+      route1->mutable_route()->mutable_max_stream_duration();
+  duration = max_stream_duration->mutable_max_stream_duration();
+  duration->set_seconds(kTimeoutMaxStreamDurationSecond);
+  duration->set_nanos(kTimeoutNano);
+  duration = max_stream_duration->mutable_grpc_timeout_header_max();
+  duration->set_seconds(kTimeoutGrpcTimeoutHeaderMaxSecond);
+  duration->set_nanos(kTimeoutNano);
+  // route 2: Set max_stream_duration of 2.5 seconds
+  auto* route2 = new_route_config.mutable_virtual_hosts(0)->add_routes();
+  route2->mutable_match()->set_path("/grpc.testing.EchoTest2Service/Echo2");
+  route2->mutable_route()->set_cluster(kNewCluster2Name);
+  max_stream_duration = route2->mutable_route()->mutable_max_stream_duration();
+  duration = max_stream_duration->mutable_max_stream_duration();
+  duration->set_seconds(kTimeoutMaxStreamDurationSecond);
+  duration->set_nanos(kTimeoutNano);
+  // route 3: No timeout values in route configuration
+  auto* route3 = new_route_config.mutable_virtual_hosts(0)->add_routes();
+  route3->mutable_match()->set_path("/grpc.testing.EchoTestService/Echo");
+  route3->mutable_route()->set_cluster(kNewCluster3Name);
+  // Set listener and route config.
+  SetListenerAndRouteConfiguration(0, std::move(listener), new_route_config);
+  // Test grpc_timeout_header_max of 1.5 seconds applied
+  grpc_millis t0 = NowFromCycleCounter();
+  grpc_millis t1 =
+      t0 + kTimeoutGrpcTimeoutHeaderMaxSecond * 1000 + kTimeoutMillis;
+  grpc_millis t2 = t0 + kTimeoutMaxStreamDurationSecond * 1000 + kTimeoutMillis;
+  CheckRpcSendFailure(
+      CheckRpcSendFailureOptions()
+          .set_rpc_options(
+              RpcOptions()
+                  .set_rpc_service(SERVICE_ECHO1)
+                  .set_rpc_method(METHOD_ECHO1)
+                  .set_wait_for_ready(true)
+                  .set_timeout_ms(kTimeoutApplicationSecond * 1000))
+          .set_expected_error_code(StatusCode::DEADLINE_EXCEEDED));
+  t0 = NowFromCycleCounter();
+  EXPECT_GE(t0, t1);
+  EXPECT_LT(t0, t2);
+  // Test max_stream_duration of 2.5 seconds applied
+  t0 = NowFromCycleCounter();
+  t1 = t0 + kTimeoutMaxStreamDurationSecond * 1000 + kTimeoutMillis;
+  t2 = t0 + kTimeoutHttpMaxStreamDurationSecond * 1000 + kTimeoutMillis;
+  CheckRpcSendFailure(
+      CheckRpcSendFailureOptions()
+          .set_rpc_options(
+              RpcOptions()
+                  .set_rpc_service(SERVICE_ECHO2)
+                  .set_rpc_method(METHOD_ECHO2)
+                  .set_wait_for_ready(true)
+                  .set_timeout_ms(kTimeoutApplicationSecond * 1000))
+          .set_expected_error_code(StatusCode::DEADLINE_EXCEEDED));
+  t0 = NowFromCycleCounter();
+  EXPECT_GE(t0, t1);
+  EXPECT_LT(t0, t2);
+  // Test http_stream_duration of 3.5 seconds applied
+  t0 = NowFromCycleCounter();
+  t1 = t0 + kTimeoutHttpMaxStreamDurationSecond * 1000 + kTimeoutMillis;
+  t2 = t0 + kTimeoutApplicationSecond * 1000 + kTimeoutMillis;
+  CheckRpcSendFailure(
+      CheckRpcSendFailureOptions()
+          .set_rpc_options(RpcOptions().set_wait_for_ready(true).set_timeout_ms(
+              kTimeoutApplicationSecond * 1000))
+          .set_expected_error_code(StatusCode::DEADLINE_EXCEEDED));
+  t0 = NowFromCycleCounter();
+  EXPECT_GE(t0, t1);
+  EXPECT_LT(t0, t2);
+}
+
+TEST_P(LdsRdsTest, XdsRoutingApplyApplicationTimeoutWhenXdsTimeoutExplicit0) {
+  const int64_t kTimeoutNano = 500000000;
+  const int64_t kTimeoutMaxStreamDurationSecond = 2;
+  const int64_t kTimeoutHttpMaxStreamDurationSecond = 3;
+  const int64_t kTimeoutApplicationSecond = 4;
+  const char* kNewCluster1Name = "new_cluster_1";
+  const char* kNewEdsService1Name = "new_eds_service_name_1";
+  const char* kNewCluster2Name = "new_cluster_2";
+  const char* kNewEdsService2Name = "new_eds_service_name_2";
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Populate new EDS resources.
+  EdsResourceArgs args({{"locality0", {MakeNonExistantEndpoint()}}});
+  EdsResourceArgs args1({{"locality0", {MakeNonExistantEndpoint()}}});
+  EdsResourceArgs args2({{"locality0", {MakeNonExistantEndpoint()}}});
+  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args1, kNewEdsService1Name));
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args2, kNewEdsService2Name));
+  // Populate new CDS resources.
+  Cluster new_cluster1 = default_cluster_;
+  new_cluster1.set_name(kNewCluster1Name);
+  new_cluster1.mutable_eds_cluster_config()->set_service_name(
+      kNewEdsService1Name);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster1);
+  Cluster new_cluster2 = default_cluster_;
+  new_cluster2.set_name(kNewCluster2Name);
+  new_cluster2.mutable_eds_cluster_config()->set_service_name(
+      kNewEdsService2Name);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster2);
+  // Construct listener.
+  auto listener = default_listener_;
+  HttpConnectionManager http_connection_manager;
+  listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
+      &http_connection_manager);
+  // Set up HTTP max_stream_duration of 3.5 seconds
+  auto* duration =
+      http_connection_manager.mutable_common_http_protocol_options()
+          ->mutable_max_stream_duration();
+  duration->set_seconds(kTimeoutHttpMaxStreamDurationSecond);
+  duration->set_nanos(kTimeoutNano);
+  listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
+      http_connection_manager);
+  // Construct route config.
+  RouteConfiguration new_route_config = default_route_config_;
+  // route 1: Set max_stream_duration of 2.5 seconds, Set
+  // grpc_timeout_header_max of 0
+  auto* route1 = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  route1->mutable_match()->set_path("/grpc.testing.EchoTest1Service/Echo1");
+  route1->mutable_route()->set_cluster(kNewCluster1Name);
+  auto* max_stream_duration =
+      route1->mutable_route()->mutable_max_stream_duration();
+  duration = max_stream_duration->mutable_max_stream_duration();
+  duration->set_seconds(kTimeoutMaxStreamDurationSecond);
+  duration->set_nanos(kTimeoutNano);
+  duration = max_stream_duration->mutable_grpc_timeout_header_max();
+  duration->set_seconds(0);
+  duration->set_nanos(0);
+  // route 2: Set max_stream_duration to 0
+  auto* route2 = new_route_config.mutable_virtual_hosts(0)->add_routes();
+  route2->mutable_match()->set_path("/grpc.testing.EchoTest2Service/Echo2");
+  route2->mutable_route()->set_cluster(kNewCluster2Name);
+  max_stream_duration = route2->mutable_route()->mutable_max_stream_duration();
+  duration = max_stream_duration->mutable_max_stream_duration();
+  duration->set_seconds(0);
+  duration->set_nanos(0);
+  // Set listener and route config.
+  SetListenerAndRouteConfiguration(0, std::move(listener), new_route_config);
+  // Test application timeout is applied for route 1
+  auto t0 = system_clock::now();
+  CheckRpcSendFailure(
+      CheckRpcSendFailureOptions()
+          .set_rpc_options(
+              RpcOptions()
+                  .set_rpc_service(SERVICE_ECHO1)
+                  .set_rpc_method(METHOD_ECHO1)
+                  .set_wait_for_ready(true)
+                  .set_timeout_ms(kTimeoutApplicationSecond * 1000))
+          .set_expected_error_code(StatusCode::DEADLINE_EXCEEDED));
+  auto ellapsed_nano_seconds =
+      std::chrono::duration_cast<std::chrono::nanoseconds>(system_clock::now() -
+                                                           t0);
+  EXPECT_GT(ellapsed_nano_seconds.count(),
+            kTimeoutApplicationSecond * 1000000000);
+  // Test application timeout is applied for route 2
+  t0 = system_clock::now();
+  CheckRpcSendFailure(
+      CheckRpcSendFailureOptions()
+          .set_rpc_options(
+              RpcOptions()
+                  .set_rpc_service(SERVICE_ECHO2)
+                  .set_rpc_method(METHOD_ECHO2)
+                  .set_wait_for_ready(true)
+                  .set_timeout_ms(kTimeoutApplicationSecond * 1000))
+          .set_expected_error_code(StatusCode::DEADLINE_EXCEEDED));
+  ellapsed_nano_seconds = std::chrono::duration_cast<std::chrono::nanoseconds>(
+      system_clock::now() - t0);
+  EXPECT_GT(ellapsed_nano_seconds.count(),
+            kTimeoutApplicationSecond * 1000000000);
+}
+
+TEST_P(LdsRdsTest, XdsRoutingApplyApplicationTimeoutWhenHttpTimeoutExplicit0) {
+  const int64_t kTimeoutApplicationSecond = 4;
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Populate new EDS resources.
+  EdsResourceArgs args({{"locality0", {MakeNonExistantEndpoint()}}});
+  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
+  auto listener = default_listener_;
+  HttpConnectionManager http_connection_manager;
+  listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
+      &http_connection_manager);
+  // Set up HTTP max_stream_duration to be explicit 0
+  auto* duration =
+      http_connection_manager.mutable_common_http_protocol_options()
+          ->mutable_max_stream_duration();
+  duration->set_seconds(0);
+  duration->set_nanos(0);
+  listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
+      http_connection_manager);
+  // Set listener and route config.
+  SetListenerAndRouteConfiguration(0, std::move(listener),
+                                   default_route_config_);
+  // Test application timeout is applied for route 1
+  auto t0 = system_clock::now();
+  CheckRpcSendFailure(
+      CheckRpcSendFailureOptions()
+          .set_rpc_options(RpcOptions().set_wait_for_ready(true).set_timeout_ms(
+              kTimeoutApplicationSecond * 1000))
+          .set_expected_error_code(StatusCode::DEADLINE_EXCEEDED));
+  auto ellapsed_nano_seconds =
+      std::chrono::duration_cast<std::chrono::nanoseconds>(system_clock::now() -
+                                                           t0);
+  EXPECT_GT(ellapsed_nano_seconds.count(),
+            kTimeoutApplicationSecond * 1000000000);
+}
+
+// Test to ensure application-specified deadline won't be affected when
+// the xDS config does not specify a timeout.
+TEST_P(LdsRdsTest, XdsRoutingWithOnlyApplicationTimeout) {
+  const int64_t kTimeoutApplicationSecond = 4;
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Populate new EDS resources.
+  EdsResourceArgs args({{"locality0", {MakeNonExistantEndpoint()}}});
+  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
+  auto t0 = system_clock::now();
+  CheckRpcSendFailure(
+      CheckRpcSendFailureOptions()
+          .set_rpc_options(RpcOptions().set_wait_for_ready(true).set_timeout_ms(
+              kTimeoutApplicationSecond * 1000))
+          .set_expected_error_code(StatusCode::DEADLINE_EXCEEDED));
+  auto ellapsed_nano_seconds =
+      std::chrono::duration_cast<std::chrono::nanoseconds>(system_clock::now() -
+                                                           t0);
+  EXPECT_GT(ellapsed_nano_seconds.count(),
+            kTimeoutApplicationSecond * 1000000000);
+}
+
+TEST_P(LdsRdsTest, XdsRetryPolicyNumRetries) {
+  const size_t kNumRetries = 3;
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Populate new EDS resources.
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 1)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
+  // Construct route config to set retry policy.
+  RouteConfiguration new_route_config = default_route_config_;
+  auto* route1 = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  auto* retry_policy = route1->mutable_route()->mutable_retry_policy();
+  retry_policy->set_retry_on(
+      "5xx,cancelled,deadline-exceeded,internal,resource-exhausted,"
+      "unavailable");
+  retry_policy->mutable_num_retries()->set_value(kNumRetries);
+  SetRouteConfiguration(0, new_route_config);
+  // Ensure we retried the correct number of times on all supported status.
+  CheckRpcSendFailure(
+      CheckRpcSendFailureOptions()
+          .set_rpc_options(
+              RpcOptions().set_server_expected_error(StatusCode::CANCELLED))
+          .set_expected_error_code(StatusCode::CANCELLED));
+  EXPECT_EQ(kNumRetries + 1, backends_[0]->backend_service()->request_count());
+  ResetBackendCounters();
+  CheckRpcSendFailure(
+      CheckRpcSendFailureOptions()
+          .set_rpc_options(RpcOptions().set_server_expected_error(
+              StatusCode::DEADLINE_EXCEEDED))
+          .set_expected_error_code(StatusCode::DEADLINE_EXCEEDED));
+  EXPECT_EQ(kNumRetries + 1, backends_[0]->backend_service()->request_count());
+  ResetBackendCounters();
+  CheckRpcSendFailure(
+      CheckRpcSendFailureOptions()
+          .set_rpc_options(
+              RpcOptions().set_server_expected_error(StatusCode::INTERNAL))
+          .set_expected_error_code(StatusCode::INTERNAL));
+  EXPECT_EQ(kNumRetries + 1, backends_[0]->backend_service()->request_count());
+  ResetBackendCounters();
+  CheckRpcSendFailure(
+      CheckRpcSendFailureOptions()
+          .set_rpc_options(RpcOptions().set_server_expected_error(
+              StatusCode::RESOURCE_EXHAUSTED))
+          .set_expected_error_code(StatusCode::RESOURCE_EXHAUSTED));
+  EXPECT_EQ(kNumRetries + 1, backends_[0]->backend_service()->request_count());
+  ResetBackendCounters();
+  CheckRpcSendFailure(
+      CheckRpcSendFailureOptions()
+          .set_rpc_options(
+              RpcOptions().set_server_expected_error(StatusCode::UNAVAILABLE))
+          .set_expected_error_code(StatusCode::UNAVAILABLE));
+  EXPECT_EQ(kNumRetries + 1, backends_[0]->backend_service()->request_count());
+  ResetBackendCounters();
+  // Ensure we don't retry on an unsupported status.
+  CheckRpcSendFailure(
+      CheckRpcSendFailureOptions()
+          .set_rpc_options(RpcOptions().set_server_expected_error(
+              StatusCode::UNAUTHENTICATED))
+          .set_expected_error_code(StatusCode::UNAUTHENTICATED));
+  EXPECT_EQ(1, backends_[0]->backend_service()->request_count());
+}
+
+TEST_P(LdsRdsTest, XdsRetryPolicyAtVirtualHostLevel) {
+  const size_t kNumRetries = 3;
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Populate new EDS resources.
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 1)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
+  // Construct route config to set retry policy.
+  RouteConfiguration new_route_config = default_route_config_;
+  auto* retry_policy =
+      new_route_config.mutable_virtual_hosts(0)->mutable_retry_policy();
+  retry_policy->set_retry_on(
+      "cancelled,deadline-exceeded,internal,resource-exhausted,unavailable");
+  retry_policy->mutable_num_retries()->set_value(kNumRetries);
+  SetRouteConfiguration(0, new_route_config);
+  // Ensure we retried the correct number of times on a supported status.
+  CheckRpcSendFailure(
+      CheckRpcSendFailureOptions()
+          .set_rpc_options(RpcOptions().set_server_expected_error(
+              StatusCode::DEADLINE_EXCEEDED))
+          .set_expected_error_code(StatusCode::DEADLINE_EXCEEDED));
+  EXPECT_EQ(kNumRetries + 1, backends_[0]->backend_service()->request_count());
+}
+
+TEST_P(LdsRdsTest, XdsRetryPolicyLongBackOff) {
+  // Set num retries to 3, but due to longer back off, we expect only 1 retry
+  // will take place.
+  const size_t kNumRetries = 3;
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Populate new EDS resources.
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 1)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
+  // Construct route config to set retry policy.
+  RouteConfiguration new_route_config = default_route_config_;
+  auto* route1 = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  auto* retry_policy = route1->mutable_route()->mutable_retry_policy();
+  retry_policy->set_retry_on(
+      "5xx,cancelled,deadline-exceeded,internal,resource-exhausted,"
+      "unavailable");
+  retry_policy->mutable_num_retries()->set_value(kNumRetries);
+  auto base_interval =
+      retry_policy->mutable_retry_back_off()->mutable_base_interval();
+  // Set backoff to 1 second, 1/2 of rpc timeout of 2 second.
+  base_interval->set_seconds(1 * grpc_test_slowdown_factor());
+  base_interval->set_nanos(0);
+  SetRouteConfiguration(0, new_route_config);
+  // No need to set max interval and just let it be the default of 10x of base.
+  // We expect 1 retry before the RPC times out with DEADLINE_EXCEEDED.
+  CheckRpcSendFailure(
+      CheckRpcSendFailureOptions()
+          .set_rpc_options(
+              RpcOptions().set_timeout_ms(2500).set_server_expected_error(
+                  StatusCode::CANCELLED))
+          .set_expected_error_code(StatusCode::DEADLINE_EXCEEDED));
+  EXPECT_EQ(1 + 1, backends_[0]->backend_service()->request_count());
+}
+
+TEST_P(LdsRdsTest, XdsRetryPolicyMaxBackOff) {
+  // Set num retries to 3, but due to longer back off, we expect only 2 retry
+  // will take place, while the 2nd one will obey the max backoff.
+  const size_t kNumRetries = 3;
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Populate new EDS resources.
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 1)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
+  // Construct route config to set retry policy.
+  RouteConfiguration new_route_config = default_route_config_;
+  auto* route1 = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  auto* retry_policy = route1->mutable_route()->mutable_retry_policy();
+  retry_policy->set_retry_on(
+      "5xx,cancelled,deadline-exceeded,internal,resource-exhausted,"
+      "unavailable");
+  retry_policy->mutable_num_retries()->set_value(kNumRetries);
+  auto base_interval =
+      retry_policy->mutable_retry_back_off()->mutable_base_interval();
+  // Set backoff to 1 second.
+  base_interval->set_seconds(1 * grpc_test_slowdown_factor());
+  base_interval->set_nanos(0);
+  auto max_interval =
+      retry_policy->mutable_retry_back_off()->mutable_max_interval();
+  // Set max interval to be the same as base, so 2 retries will take 2 seconds
+  // and both retries will take place before the 2.5 seconds rpc timeout.
+  // Tested to ensure if max is not set, this test will be the same as
+  // XdsRetryPolicyLongBackOff and we will only see 1 retry in that case.
+  max_interval->set_seconds(1 * grpc_test_slowdown_factor());
+  max_interval->set_nanos(0);
+  SetRouteConfiguration(0, new_route_config);
+  // We expect 2 retry before the RPC times out with DEADLINE_EXCEEDED.
+  CheckRpcSendFailure(
+      CheckRpcSendFailureOptions()
+          .set_rpc_options(
+              RpcOptions().set_timeout_ms(2500).set_server_expected_error(
+                  StatusCode::CANCELLED))
+          .set_expected_error_code(StatusCode::DEADLINE_EXCEEDED));
+  EXPECT_EQ(2 + 1, backends_[0]->backend_service()->request_count());
+}
+
+TEST_P(LdsRdsTest, XdsRetryPolicyUnsupportedStatusCode) {
+  const size_t kNumRetries = 3;
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Populate new EDS resources.
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 1)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
+  // Construct route config to set retry policy.
+  RouteConfiguration new_route_config = default_route_config_;
+  auto* route1 = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  auto* retry_policy = route1->mutable_route()->mutable_retry_policy();
+  retry_policy->set_retry_on("5xx");
+  retry_policy->mutable_num_retries()->set_value(kNumRetries);
+  SetRouteConfiguration(0, new_route_config);
+  // We expect no retry.
+  CheckRpcSendFailure(
+      CheckRpcSendFailureOptions()
+          .set_rpc_options(RpcOptions().set_server_expected_error(
+              StatusCode::DEADLINE_EXCEEDED))
+          .set_expected_error_code(StatusCode::DEADLINE_EXCEEDED));
+  EXPECT_EQ(1, backends_[0]->backend_service()->request_count());
+}
+
+TEST_P(LdsRdsTest,
+       XdsRetryPolicyUnsupportedStatusCodeWithVirtualHostLevelRetry) {
+  const size_t kNumRetries = 3;
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Populate new EDS resources.
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 1)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
+  // Construct route config to set retry policy with no supported retry_on
+  // statuses.
+  RouteConfiguration new_route_config = default_route_config_;
+  auto* route1 = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  auto* retry_policy = route1->mutable_route()->mutable_retry_policy();
+  retry_policy->set_retry_on("5xx");
+  retry_policy->mutable_num_retries()->set_value(kNumRetries);
+  // Construct a virtual host level retry policy with supported statuses.
+  auto* virtual_host_retry_policy =
+      new_route_config.mutable_virtual_hosts(0)->mutable_retry_policy();
+  virtual_host_retry_policy->set_retry_on(
+      "cancelled,deadline-exceeded,internal,resource-exhausted,unavailable");
+  virtual_host_retry_policy->mutable_num_retries()->set_value(kNumRetries);
+  SetRouteConfiguration(0, new_route_config);
+  // We expect no retry.
+  CheckRpcSendFailure(
+      CheckRpcSendFailureOptions()
+          .set_rpc_options(RpcOptions().set_server_expected_error(
+              StatusCode::DEADLINE_EXCEEDED))
+          .set_expected_error_code(StatusCode::DEADLINE_EXCEEDED));
+  EXPECT_EQ(1, backends_[0]->backend_service()->request_count());
+}
+
+TEST_P(LdsRdsTest, XdsRetryPolicyInvalidNumRetriesZero) {
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Populate new EDS resources.
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 1)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
+  // Construct route config to set retry policy.
+  RouteConfiguration new_route_config = default_route_config_;
+  auto* route1 = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  auto* retry_policy = route1->mutable_route()->mutable_retry_policy();
+  retry_policy->set_retry_on("deadline-exceeded");
+  // Setting num_retries to zero is not valid.
+  retry_policy->mutable_num_retries()->set_value(0);
+  SetRouteConfiguration(0, new_route_config);
+  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
+  const auto response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(
+      response_state.error_message,
+      ::testing::HasSubstr(
+          "RouteAction RetryPolicy num_retries set to invalid value 0."));
+}
+
+TEST_P(LdsRdsTest, XdsRetryPolicyRetryBackOffMissingBaseInterval) {
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Populate new EDS resources.
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 1)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
+  // Construct route config to set retry policy.
+  RouteConfiguration new_route_config = default_route_config_;
+  auto* route1 = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  auto* retry_policy = route1->mutable_route()->mutable_retry_policy();
+  retry_policy->set_retry_on("deadline-exceeded");
+  retry_policy->mutable_num_retries()->set_value(1);
+  // RetryBackoff is there but base interval is missing.
+  auto max_interval =
+      retry_policy->mutable_retry_back_off()->mutable_max_interval();
+  max_interval->set_seconds(0);
+  max_interval->set_nanos(250000000);
+  SetRouteConfiguration(0, new_route_config);
+  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
+  const auto response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(
+      response_state.error_message,
+      ::testing::HasSubstr(
+          "RouteAction RetryPolicy RetryBackoff missing base interval."));
+}
+
+TEST_P(LdsRdsTest, XdsRoutingHeadersMatching) {
+  const char* kNewClusterName = "new_cluster";
+  const char* kNewEdsServiceName = "new_eds_service_name";
+  const size_t kNumEcho1Rpcs = 100;
+  const size_t kNumEchoRpcs = 5;
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Populate new EDS resources.
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 1)},
+  });
+  EdsResourceArgs args1({
+      {"locality0", CreateEndpointsForBackends(1, 2)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args1, kNewEdsServiceName));
+  // Populate new CDS resources.
+  Cluster new_cluster = default_cluster_;
+  new_cluster.set_name(kNewClusterName);
+  new_cluster.mutable_eds_cluster_config()->set_service_name(
+      kNewEdsServiceName);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster);
+  // Populating Route Configurations for LDS.
+  RouteConfiguration route_config = default_route_config_;
+  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/");
+  auto* header_matcher1 = route1->mutable_match()->add_headers();
+  header_matcher1->set_name("header1");
+  header_matcher1->set_exact_match("POST,PUT,GET");
+  auto* header_matcher2 = route1->mutable_match()->add_headers();
+  header_matcher2->set_name("header2");
+  header_matcher2->mutable_safe_regex_match()->set_regex("[a-z]*");
+  auto* header_matcher3 = route1->mutable_match()->add_headers();
+  header_matcher3->set_name("header3");
+  header_matcher3->mutable_range_match()->set_start(1);
+  header_matcher3->mutable_range_match()->set_end(1000);
+  auto* header_matcher4 = route1->mutable_match()->add_headers();
+  header_matcher4->set_name("header4");
+  header_matcher4->set_present_match(false);
+  auto* header_matcher5 = route1->mutable_match()->add_headers();
+  header_matcher5->set_name("header5");
+  header_matcher5->set_present_match(true);
+  auto* header_matcher6 = route1->mutable_match()->add_headers();
+  header_matcher6->set_name("header6");
+  header_matcher6->set_prefix_match("/grpc");
+  auto* header_matcher7 = route1->mutable_match()->add_headers();
+  header_matcher7->set_name("header7");
+  header_matcher7->set_suffix_match(".cc");
+  header_matcher7->set_invert_match(true);
+  route1->mutable_route()->set_cluster(kNewClusterName);
+  auto* default_route = route_config.mutable_virtual_hosts(0)->add_routes();
+  default_route->mutable_match()->set_prefix("");
+  default_route->mutable_route()->set_cluster(kDefaultClusterName);
+  SetRouteConfiguration(0, route_config);
+  std::vector<std::pair<std::string, std::string>> metadata = {
+      {"header1", "POST"},
+      {"header2", "blah"},
+      {"header3", "1"},
+      {"header5", "anything"},
+      {"header6", "/grpc.testing.EchoTest1Service/"},
+      {"header1", "PUT"},
+      {"header7", "grpc.java"},
+      {"header1", "GET"},
+  };
+  const auto header_match_rpc_options = RpcOptions()
+                                            .set_rpc_service(SERVICE_ECHO1)
+                                            .set_rpc_method(METHOD_ECHO1)
+                                            .set_metadata(std::move(metadata));
+  // Make sure all backends are up.
+  WaitForBackend(0);
+  WaitForBackend(1, WaitForBackendOptions(), header_match_rpc_options);
+  // Send RPCs.
+  CheckRpcSendOk(kNumEchoRpcs);
+  CheckRpcSendOk(kNumEcho1Rpcs, header_match_rpc_options);
+  EXPECT_EQ(kNumEchoRpcs, backends_[0]->backend_service()->request_count());
+  EXPECT_EQ(0, backends_[0]->backend_service1()->request_count());
+  EXPECT_EQ(0, backends_[0]->backend_service2()->request_count());
+  EXPECT_EQ(0, backends_[1]->backend_service()->request_count());
+  EXPECT_EQ(kNumEcho1Rpcs, backends_[1]->backend_service1()->request_count());
+  EXPECT_EQ(0, backends_[1]->backend_service2()->request_count());
+  const auto response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::ACKED);
+}
+
+TEST_P(LdsRdsTest, XdsRoutingHeadersMatchingSpecialHeaderContentType) {
+  const char* kNewClusterName = "new_cluster";
+  const char* kNewEdsServiceName = "new_eds_service_name";
+  const size_t kNumEchoRpcs = 100;
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Populate new EDS resources.
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 1)},
+  });
+  EdsResourceArgs args1({
+      {"locality0", CreateEndpointsForBackends(1, 2)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args1, kNewEdsServiceName));
+  // Populate new CDS resources.
+  Cluster new_cluster = default_cluster_;
+  new_cluster.set_name(kNewClusterName);
+  new_cluster.mutable_eds_cluster_config()->set_service_name(
+      kNewEdsServiceName);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster);
+  // Populating Route Configurations for LDS.
+  RouteConfiguration route_config = default_route_config_;
+  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  route1->mutable_match()->set_prefix("");
+  auto* header_matcher1 = route1->mutable_match()->add_headers();
+  header_matcher1->set_name("content-type");
+  header_matcher1->set_exact_match("notapplication/grpc");
+  route1->mutable_route()->set_cluster(kNewClusterName);
+  auto* default_route = route_config.mutable_virtual_hosts(0)->add_routes();
+  default_route->mutable_match()->set_prefix("");
+  auto* header_matcher2 = default_route->mutable_match()->add_headers();
+  header_matcher2->set_name("content-type");
+  header_matcher2->set_exact_match("application/grpc");
+  default_route->mutable_route()->set_cluster(kDefaultClusterName);
+  SetRouteConfiguration(0, route_config);
+  // Make sure the backend is up.
+  WaitForAllBackends(0, 1);
+  // Send RPCs.
+  CheckRpcSendOk(kNumEchoRpcs);
+  EXPECT_EQ(kNumEchoRpcs, backends_[0]->backend_service()->request_count());
+  EXPECT_EQ(0, backends_[1]->backend_service()->request_count());
+  const auto response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::ACKED);
+}
+
+TEST_P(LdsRdsTest, XdsRoutingHeadersMatchingSpecialCasesToIgnore) {
+  const char* kNewCluster1Name = "new_cluster_1";
+  const char* kNewEdsService1Name = "new_eds_service_name_1";
+  const size_t kNumEchoRpcs = 100;
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Populate new EDS resources.
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 1)},
+  });
+  EdsResourceArgs args1({
+      {"locality0", CreateEndpointsForBackends(1, 2)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args1, kNewEdsService1Name));
+  // Populate new CDS resources.
+  Cluster new_cluster1 = default_cluster_;
+  new_cluster1.set_name(kNewCluster1Name);
+  new_cluster1.mutable_eds_cluster_config()->set_service_name(
+      kNewEdsService1Name);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster1);
+  // Populating Route Configurations for LDS.
+  RouteConfiguration route_config = default_route_config_;
+  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  route1->mutable_match()->set_prefix("");
+  auto* header_matcher1 = route1->mutable_match()->add_headers();
+  header_matcher1->set_name("grpc-foo-bin");
+  header_matcher1->set_present_match(true);
+  route1->mutable_route()->set_cluster(kNewCluster1Name);
+  auto* default_route = route_config.mutable_virtual_hosts(0)->add_routes();
+  default_route->mutable_match()->set_prefix("");
+  default_route->mutable_route()->set_cluster(kDefaultClusterName);
+  SetRouteConfiguration(0, route_config);
+  // Send headers which will mismatch each route
+  std::vector<std::pair<std::string, std::string>> metadata = {
+      {"grpc-foo-bin", "grpc-foo-bin"},
+  };
+  WaitForAllBackends(0, 1);
+  CheckRpcSendOk(kNumEchoRpcs, RpcOptions().set_metadata(metadata));
+  // Verify that only the default backend got RPCs since all previous routes
+  // were mismatched.
+  EXPECT_EQ(kNumEchoRpcs, backends_[0]->backend_service()->request_count());
+  EXPECT_EQ(0, backends_[1]->backend_service()->request_count());
+  const auto response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::ACKED);
+}
+
+TEST_P(LdsRdsTest, XdsRoutingRuntimeFractionMatching) {
+  const char* kNewClusterName = "new_cluster";
+  const char* kNewEdsServiceName = "new_eds_service_name";
+  const double kErrorTolerance = 0.05;
+  const size_t kRouteMatchNumerator = 25;
+  const double kRouteMatchPercent =
+      static_cast<double>(kRouteMatchNumerator) / 100;
+  const size_t kNumRpcs =
+      ComputeIdealNumRpcs(kRouteMatchPercent, kErrorTolerance);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Populate new EDS resources.
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 1)},
+  });
+  EdsResourceArgs args1({
+      {"locality0", CreateEndpointsForBackends(1, 2)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args1, kNewEdsServiceName));
+  // Populate new CDS resources.
+  Cluster new_cluster = default_cluster_;
+  new_cluster.set_name(kNewClusterName);
+  new_cluster.mutable_eds_cluster_config()->set_service_name(
+      kNewEdsServiceName);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster);
+  // Populating Route Configurations for LDS.
+  RouteConfiguration route_config = default_route_config_;
+  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  route1->mutable_match()
+      ->mutable_runtime_fraction()
+      ->mutable_default_value()
+      ->set_numerator(kRouteMatchNumerator);
+  route1->mutable_route()->set_cluster(kNewClusterName);
+  auto* default_route = route_config.mutable_virtual_hosts(0)->add_routes();
+  default_route->mutable_match()->set_prefix("");
+  default_route->mutable_route()->set_cluster(kDefaultClusterName);
+  SetRouteConfiguration(0, route_config);
+  WaitForAllBackends(0, 2);
+  CheckRpcSendOk(kNumRpcs);
+  const int default_backend_count =
+      backends_[0]->backend_service()->request_count();
+  const int matched_backend_count =
+      backends_[1]->backend_service()->request_count();
+  EXPECT_THAT(static_cast<double>(default_backend_count) / kNumRpcs,
+              ::testing::DoubleNear(1 - kRouteMatchPercent, kErrorTolerance));
+  EXPECT_THAT(static_cast<double>(matched_backend_count) / kNumRpcs,
+              ::testing::DoubleNear(kRouteMatchPercent, kErrorTolerance));
+  const auto response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::ACKED);
+}
+
+TEST_P(LdsRdsTest, XdsRoutingHeadersMatchingUnmatchCases) {
+  const char* kNewCluster1Name = "new_cluster_1";
+  const char* kNewEdsService1Name = "new_eds_service_name_1";
+  const char* kNewCluster2Name = "new_cluster_2";
+  const char* kNewEdsService2Name = "new_eds_service_name_2";
+  const char* kNewCluster3Name = "new_cluster_3";
+  const char* kNewEdsService3Name = "new_eds_service_name_3";
+  const size_t kNumEcho1Rpcs = 100;
+  const size_t kNumEchoRpcs = 5;
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Populate new EDS resources.
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 1)},
+  });
+  EdsResourceArgs args1({
+      {"locality0", CreateEndpointsForBackends(1, 2)},
+  });
+  EdsResourceArgs args2({
+      {"locality0", CreateEndpointsForBackends(2, 3)},
+  });
+  EdsResourceArgs args3({
+      {"locality0", CreateEndpointsForBackends(3, 4)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args1, kNewEdsService1Name));
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args2, kNewEdsService2Name));
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args3, kNewEdsService3Name));
+  // Populate new CDS resources.
+  Cluster new_cluster1 = default_cluster_;
+  new_cluster1.set_name(kNewCluster1Name);
+  new_cluster1.mutable_eds_cluster_config()->set_service_name(
+      kNewEdsService1Name);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster1);
+  Cluster new_cluster2 = default_cluster_;
+  new_cluster2.set_name(kNewCluster2Name);
+  new_cluster2.mutable_eds_cluster_config()->set_service_name(
+      kNewEdsService2Name);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster2);
+  Cluster new_cluster3 = default_cluster_;
+  new_cluster3.set_name(kNewCluster3Name);
+  new_cluster3.mutable_eds_cluster_config()->set_service_name(
+      kNewEdsService3Name);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster3);
+  // Populating Route Configurations for LDS.
+  RouteConfiguration route_config = default_route_config_;
+  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/");
+  auto* header_matcher1 = route1->mutable_match()->add_headers();
+  header_matcher1->set_name("header1");
+  header_matcher1->set_exact_match("POST");
+  route1->mutable_route()->set_cluster(kNewCluster1Name);
+  auto route2 = route_config.mutable_virtual_hosts(0)->add_routes();
+  route2->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/");
+  auto* header_matcher2 = route2->mutable_match()->add_headers();
+  header_matcher2->set_name("header2");
+  header_matcher2->mutable_range_match()->set_start(1);
+  header_matcher2->mutable_range_match()->set_end(1000);
+  route2->mutable_route()->set_cluster(kNewCluster2Name);
+  auto route3 = route_config.mutable_virtual_hosts(0)->add_routes();
+  route3->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/");
+  auto* header_matcher3 = route3->mutable_match()->add_headers();
+  header_matcher3->set_name("header3");
+  header_matcher3->mutable_safe_regex_match()->set_regex("[a-z]*");
+  route3->mutable_route()->set_cluster(kNewCluster3Name);
+  auto* default_route = route_config.mutable_virtual_hosts(0)->add_routes();
+  default_route->mutable_match()->set_prefix("");
+  default_route->mutable_route()->set_cluster(kDefaultClusterName);
+  SetRouteConfiguration(0, route_config);
+  // Send headers which will mismatch each route
+  std::vector<std::pair<std::string, std::string>> metadata = {
+      {"header1", "POST"},
+      {"header2", "1000"},
+      {"header3", "123"},
+      {"header1", "GET"},
+  };
+  WaitForAllBackends(0, 1);
+  CheckRpcSendOk(kNumEchoRpcs, RpcOptions().set_metadata(metadata));
+  CheckRpcSendOk(kNumEcho1Rpcs, RpcOptions()
+                                    .set_rpc_service(SERVICE_ECHO1)
+                                    .set_rpc_method(METHOD_ECHO1)
+                                    .set_metadata(metadata));
+  // Verify that only the default backend got RPCs since all previous routes
+  // were mismatched.
+  for (size_t i = 1; i < 4; ++i) {
+    EXPECT_EQ(0, backends_[i]->backend_service()->request_count());
+    EXPECT_EQ(0, backends_[i]->backend_service1()->request_count());
+    EXPECT_EQ(0, backends_[i]->backend_service2()->request_count());
+  }
+  EXPECT_EQ(kNumEchoRpcs, backends_[0]->backend_service()->request_count());
+  EXPECT_EQ(kNumEcho1Rpcs, backends_[0]->backend_service1()->request_count());
+  EXPECT_EQ(0, backends_[0]->backend_service2()->request_count());
+  const auto response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::ACKED);
+}
+
+TEST_P(LdsRdsTest, XdsRoutingChangeRoutesWithoutChangingClusters) {
+  const char* kNewClusterName = "new_cluster";
+  const char* kNewEdsServiceName = "new_eds_service_name";
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Populate new EDS resources.
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 1)},
+  });
+  EdsResourceArgs args1({
+      {"locality0", CreateEndpointsForBackends(1, 2)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args1, kNewEdsServiceName));
+  // Populate new CDS resources.
+  Cluster new_cluster = default_cluster_;
+  new_cluster.set_name(kNewClusterName);
+  new_cluster.mutable_eds_cluster_config()->set_service_name(
+      kNewEdsServiceName);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster);
+  // Populating Route Configurations for LDS.
+  RouteConfiguration route_config = default_route_config_;
+  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/");
+  route1->mutable_route()->set_cluster(kNewClusterName);
+  auto* default_route = route_config.mutable_virtual_hosts(0)->add_routes();
+  default_route->mutable_match()->set_prefix("");
+  default_route->mutable_route()->set_cluster(kDefaultClusterName);
+  SetRouteConfiguration(0, route_config);
+  // Make sure all backends are up and that requests for each RPC
+  // service go to the right backends.
+  WaitForBackend(0, WaitForBackendOptions().set_reset_counters(false));
+  WaitForBackend(1, WaitForBackendOptions().set_reset_counters(false),
+                 RpcOptions().set_rpc_service(SERVICE_ECHO1));
+  WaitForBackend(0, WaitForBackendOptions().set_reset_counters(false),
+                 RpcOptions().set_rpc_service(SERVICE_ECHO2));
+  // Requests for services Echo and Echo2 should have gone to backend 0.
+  EXPECT_EQ(1, backends_[0]->backend_service()->request_count());
+  EXPECT_EQ(0, backends_[0]->backend_service1()->request_count());
+  EXPECT_EQ(1, backends_[0]->backend_service2()->request_count());
+  // Requests for service Echo1 should have gone to backend 1.
+  EXPECT_EQ(0, backends_[1]->backend_service()->request_count());
+  EXPECT_EQ(1, backends_[1]->backend_service1()->request_count());
+  EXPECT_EQ(0, backends_[1]->backend_service2()->request_count());
+  // Now send an update that changes the first route to match a
+  // different RPC service, and wait for the client to make the change.
+  route1->mutable_match()->set_prefix("/grpc.testing.EchoTest2Service/");
+  SetRouteConfiguration(0, route_config);
+  WaitForBackend(1, WaitForBackendOptions(),
+                 RpcOptions().set_rpc_service(SERVICE_ECHO2));
+  // Now repeat the earlier test, making sure all traffic goes to the
+  // right place.
+  WaitForBackend(0, WaitForBackendOptions().set_reset_counters(false));
+  WaitForBackend(0, WaitForBackendOptions().set_reset_counters(false),
+                 RpcOptions().set_rpc_service(SERVICE_ECHO1));
+  WaitForBackend(1, WaitForBackendOptions().set_reset_counters(false),
+                 RpcOptions().set_rpc_service(SERVICE_ECHO2));
+  // Requests for services Echo and Echo1 should have gone to backend 0.
+  EXPECT_EQ(1, backends_[0]->backend_service()->request_count());
+  EXPECT_EQ(1, backends_[0]->backend_service1()->request_count());
+  EXPECT_EQ(0, backends_[0]->backend_service2()->request_count());
+  // Requests for service Echo2 should have gone to backend 1.
+  EXPECT_EQ(0, backends_[1]->backend_service()->request_count());
+  EXPECT_EQ(0, backends_[1]->backend_service1()->request_count());
+  EXPECT_EQ(1, backends_[1]->backend_service2()->request_count());
+}
+
+// Test that we NACK unknown filter types in VirtualHost.
+TEST_P(LdsRdsTest, RejectsUnknownHttpFilterTypeInVirtualHost) {
+  if (GetParam().use_v2()) return;  // Filters supported in v3 only.
+  RouteConfiguration route_config = default_route_config_;
+  auto* per_filter_config =
+      route_config.mutable_virtual_hosts(0)->mutable_typed_per_filter_config();
+  (*per_filter_config)["unknown"].PackFrom(Listener());
+  SetListenerAndRouteConfiguration(0, default_listener_, route_config);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
+  const auto response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr("no filter registered for config type "
+                                   "envoy.config.listener.v3.Listener"));
+}
+
+// Test that we ignore optional unknown filter types in VirtualHost.
+TEST_P(LdsRdsTest, IgnoresOptionalUnknownHttpFilterTypeInVirtualHost) {
+  if (GetParam().use_v2()) return;  // Filters supported in v3 only.
+  RouteConfiguration route_config = default_route_config_;
+  auto* per_filter_config =
+      route_config.mutable_virtual_hosts(0)->mutable_typed_per_filter_config();
+  ::envoy::config::route::v3::FilterConfig filter_config;
+  filter_config.mutable_config()->PackFrom(Listener());
+  filter_config.set_is_optional(true);
+  (*per_filter_config)["unknown"].PackFrom(filter_config);
+  SetListenerAndRouteConfiguration(0, default_listener_, route_config);
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  WaitForAllBackends();
+  EXPECT_EQ(RouteConfigurationResponseState(0).state,
+            AdsServiceImpl::ResponseState::ACKED);
+}
+
+// Test that we NACK filters without configs in VirtualHost.
+TEST_P(LdsRdsTest, RejectsHttpFilterWithoutConfigInVirtualHost) {
+  if (GetParam().use_v2()) return;  // Filters supported in v3 only.
+  RouteConfiguration route_config = default_route_config_;
+  auto* per_filter_config =
+      route_config.mutable_virtual_hosts(0)->mutable_typed_per_filter_config();
+  (*per_filter_config)["unknown"];
+  SetListenerAndRouteConfiguration(0, default_listener_, route_config);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
+  const auto response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr(
+                  "no filter config specified for filter name unknown"));
+}
+
+// Test that we NACK filters without configs in FilterConfig in VirtualHost.
+TEST_P(LdsRdsTest, RejectsHttpFilterWithoutConfigInFilterConfigInVirtualHost) {
+  if (GetParam().use_v2()) return;  // Filters supported in v3 only.
+  RouteConfiguration route_config = default_route_config_;
+  auto* per_filter_config =
+      route_config.mutable_virtual_hosts(0)->mutable_typed_per_filter_config();
+  (*per_filter_config)["unknown"].PackFrom(
+      ::envoy::config::route::v3::FilterConfig());
+  SetListenerAndRouteConfiguration(0, default_listener_, route_config);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
+  const auto response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr(
+                  "no filter config specified for filter name unknown"));
+}
+
+// Test that we ignore optional filters without configs in VirtualHost.
+TEST_P(LdsRdsTest, IgnoresOptionalHttpFilterWithoutConfigInVirtualHost) {
+  if (GetParam().use_v2()) return;  // Filters supported in v3 only.
+  RouteConfiguration route_config = default_route_config_;
+  auto* per_filter_config =
+      route_config.mutable_virtual_hosts(0)->mutable_typed_per_filter_config();
+  ::envoy::config::route::v3::FilterConfig filter_config;
+  filter_config.set_is_optional(true);
+  (*per_filter_config)["unknown"].PackFrom(filter_config);
+  SetListenerAndRouteConfiguration(0, default_listener_, route_config);
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  WaitForAllBackends();
+  EXPECT_EQ(RouteConfigurationResponseState(0).state,
+            AdsServiceImpl::ResponseState::ACKED);
+}
+
+// Test that we NACK unparseable filter types in VirtualHost.
+TEST_P(LdsRdsTest, RejectsUnparseableHttpFilterTypeInVirtualHost) {
+  if (GetParam().use_v2()) return;  // Filters supported in v3 only.
+  RouteConfiguration route_config = default_route_config_;
+  auto* per_filter_config =
+      route_config.mutable_virtual_hosts(0)->mutable_typed_per_filter_config();
+  (*per_filter_config)["unknown"].PackFrom(
+      envoy::extensions::filters::http::router::v3::Router());
+  SetListenerAndRouteConfiguration(0, default_listener_, route_config);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
+  const auto response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(
+      response_state.error_message,
+      ::testing::HasSubstr("router filter does not support config override"));
+}
+
+// Test that we NACK unknown filter types in Route.
+TEST_P(LdsRdsTest, RejectsUnknownHttpFilterTypeInRoute) {
+  if (GetParam().use_v2()) return;  // Filters supported in v3 only.
+  RouteConfiguration route_config = default_route_config_;
+  auto* per_filter_config = route_config.mutable_virtual_hosts(0)
+                                ->mutable_routes(0)
+                                ->mutable_typed_per_filter_config();
+  (*per_filter_config)["unknown"].PackFrom(Listener());
+  SetListenerAndRouteConfiguration(0, default_listener_, route_config);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
+  const auto response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr("no filter registered for config type "
+                                   "envoy.config.listener.v3.Listener"));
+}
+
+// Test that we ignore optional unknown filter types in Route.
+TEST_P(LdsRdsTest, IgnoresOptionalUnknownHttpFilterTypeInRoute) {
+  if (GetParam().use_v2()) return;  // Filters supported in v3 only.
+  RouteConfiguration route_config = default_route_config_;
+  auto* per_filter_config = route_config.mutable_virtual_hosts(0)
+                                ->mutable_routes(0)
+                                ->mutable_typed_per_filter_config();
+  ::envoy::config::route::v3::FilterConfig filter_config;
+  filter_config.mutable_config()->PackFrom(Listener());
+  filter_config.set_is_optional(true);
+  (*per_filter_config)["unknown"].PackFrom(filter_config);
+  SetListenerAndRouteConfiguration(0, default_listener_, route_config);
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  WaitForAllBackends();
+  EXPECT_EQ(RouteConfigurationResponseState(0).state,
+            AdsServiceImpl::ResponseState::ACKED);
+}
+
+// Test that we NACK filters without configs in Route.
+TEST_P(LdsRdsTest, RejectsHttpFilterWithoutConfigInRoute) {
+  if (GetParam().use_v2()) return;  // Filters supported in v3 only.
+  RouteConfiguration route_config = default_route_config_;
+  auto* per_filter_config = route_config.mutable_virtual_hosts(0)
+                                ->mutable_routes(0)
+                                ->mutable_typed_per_filter_config();
+  (*per_filter_config)["unknown"];
+  SetListenerAndRouteConfiguration(0, default_listener_, route_config);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
+  const auto response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr(
+                  "no filter config specified for filter name unknown"));
+}
+
+// Test that we NACK filters without configs in FilterConfig in Route.
+TEST_P(LdsRdsTest, RejectsHttpFilterWithoutConfigInFilterConfigInRoute) {
+  if (GetParam().use_v2()) return;  // Filters supported in v3 only.
+  RouteConfiguration route_config = default_route_config_;
+  auto* per_filter_config = route_config.mutable_virtual_hosts(0)
+                                ->mutable_routes(0)
+                                ->mutable_typed_per_filter_config();
+  (*per_filter_config)["unknown"].PackFrom(
+      ::envoy::config::route::v3::FilterConfig());
+  SetListenerAndRouteConfiguration(0, default_listener_, route_config);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
+  const auto response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr(
+                  "no filter config specified for filter name unknown"));
+}
+
+// Test that we ignore optional filters without configs in Route.
+TEST_P(LdsRdsTest, IgnoresOptionalHttpFilterWithoutConfigInRoute) {
+  if (GetParam().use_v2()) return;  // Filters supported in v3 only.
+  RouteConfiguration route_config = default_route_config_;
+  auto* per_filter_config = route_config.mutable_virtual_hosts(0)
+                                ->mutable_routes(0)
+                                ->mutable_typed_per_filter_config();
+  ::envoy::config::route::v3::FilterConfig filter_config;
+  filter_config.set_is_optional(true);
+  (*per_filter_config)["unknown"].PackFrom(filter_config);
+  SetListenerAndRouteConfiguration(0, default_listener_, route_config);
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  WaitForAllBackends();
+  EXPECT_EQ(RouteConfigurationResponseState(0).state,
+            AdsServiceImpl::ResponseState::ACKED);
+}
+
+// Test that we NACK unparseable filter types in Route.
+TEST_P(LdsRdsTest, RejectsUnparseableHttpFilterTypeInRoute) {
+  if (GetParam().use_v2()) return;  // Filters supported in v3 only.
+  RouteConfiguration route_config = default_route_config_;
+  auto* per_filter_config = route_config.mutable_virtual_hosts(0)
+                                ->mutable_routes(0)
+                                ->mutable_typed_per_filter_config();
+  (*per_filter_config)["unknown"].PackFrom(
+      envoy::extensions::filters::http::router::v3::Router());
+  SetListenerAndRouteConfiguration(0, default_listener_, route_config);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
+  const auto response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(
+      response_state.error_message,
+      ::testing::HasSubstr("router filter does not support config override"));
+}
+
+// Test that we NACK unknown filter types in ClusterWeight.
+TEST_P(LdsRdsTest, RejectsUnknownHttpFilterTypeInClusterWeight) {
+  if (GetParam().use_v2()) return;  // Filters supported in v3 only.
+  RouteConfiguration route_config = default_route_config_;
+  auto* cluster_weight = route_config.mutable_virtual_hosts(0)
+                             ->mutable_routes(0)
+                             ->mutable_route()
+                             ->mutable_weighted_clusters()
+                             ->add_clusters();
+  cluster_weight->set_name(kDefaultClusterName);
+  cluster_weight->mutable_weight()->set_value(100);
+  auto* per_filter_config = cluster_weight->mutable_typed_per_filter_config();
+  (*per_filter_config)["unknown"].PackFrom(Listener());
+  SetListenerAndRouteConfiguration(0, default_listener_, route_config);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
+  const auto response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr("no filter registered for config type "
+                                   "envoy.config.listener.v3.Listener"));
+}
+
+// Test that we ignore optional unknown filter types in ClusterWeight.
+TEST_P(LdsRdsTest, IgnoresOptionalUnknownHttpFilterTypeInClusterWeight) {
+  if (GetParam().use_v2()) return;  // Filters supported in v3 only.
+  RouteConfiguration route_config = default_route_config_;
+  auto* cluster_weight = route_config.mutable_virtual_hosts(0)
+                             ->mutable_routes(0)
+                             ->mutable_route()
+                             ->mutable_weighted_clusters()
+                             ->add_clusters();
+  cluster_weight->set_name(kDefaultClusterName);
+  cluster_weight->mutable_weight()->set_value(100);
+  auto* per_filter_config = cluster_weight->mutable_typed_per_filter_config();
+  ::envoy::config::route::v3::FilterConfig filter_config;
+  filter_config.mutable_config()->PackFrom(Listener());
+  filter_config.set_is_optional(true);
+  (*per_filter_config)["unknown"].PackFrom(filter_config);
+  SetListenerAndRouteConfiguration(0, default_listener_, route_config);
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  WaitForAllBackends();
+  EXPECT_EQ(RouteConfigurationResponseState(0).state,
+            AdsServiceImpl::ResponseState::ACKED);
+}
+
+// Test that we NACK filters without configs in ClusterWeight.
+TEST_P(LdsRdsTest, RejectsHttpFilterWithoutConfigInClusterWeight) {
+  if (GetParam().use_v2()) return;  // Filters supported in v3 only.
+  RouteConfiguration route_config = default_route_config_;
+  auto* cluster_weight = route_config.mutable_virtual_hosts(0)
+                             ->mutable_routes(0)
+                             ->mutable_route()
+                             ->mutable_weighted_clusters()
+                             ->add_clusters();
+  cluster_weight->set_name(kDefaultClusterName);
+  cluster_weight->mutable_weight()->set_value(100);
+  auto* per_filter_config = cluster_weight->mutable_typed_per_filter_config();
+  (*per_filter_config)["unknown"];
+  SetListenerAndRouteConfiguration(0, default_listener_, route_config);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
+  const auto response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr(
+                  "no filter config specified for filter name unknown"));
+}
+
+// Test that we NACK filters without configs in FilterConfig in ClusterWeight.
+TEST_P(LdsRdsTest,
+       RejectsHttpFilterWithoutConfigInFilterConfigInClusterWeight) {
+  if (GetParam().use_v2()) return;  // Filters supported in v3 only.
+  RouteConfiguration route_config = default_route_config_;
+  auto* cluster_weight = route_config.mutable_virtual_hosts(0)
+                             ->mutable_routes(0)
+                             ->mutable_route()
+                             ->mutable_weighted_clusters()
+                             ->add_clusters();
+  cluster_weight->set_name(kDefaultClusterName);
+  cluster_weight->mutable_weight()->set_value(100);
+  auto* per_filter_config = cluster_weight->mutable_typed_per_filter_config();
+  (*per_filter_config)["unknown"].PackFrom(
+      ::envoy::config::route::v3::FilterConfig());
+  SetListenerAndRouteConfiguration(0, default_listener_, route_config);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
+  const auto response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr(
+                  "no filter config specified for filter name unknown"));
+}
+
+// Test that we ignore optional filters without configs in ClusterWeight.
+TEST_P(LdsRdsTest, IgnoresOptionalHttpFilterWithoutConfigInClusterWeight) {
+  if (GetParam().use_v2()) return;  // Filters supported in v3 only.
+  RouteConfiguration route_config = default_route_config_;
+  auto* cluster_weight = route_config.mutable_virtual_hosts(0)
+                             ->mutable_routes(0)
+                             ->mutable_route()
+                             ->mutable_weighted_clusters()
+                             ->add_clusters();
+  cluster_weight->set_name(kDefaultClusterName);
+  cluster_weight->mutable_weight()->set_value(100);
+  auto* per_filter_config = cluster_weight->mutable_typed_per_filter_config();
+  ::envoy::config::route::v3::FilterConfig filter_config;
+  filter_config.set_is_optional(true);
+  (*per_filter_config)["unknown"].PackFrom(filter_config);
+  SetListenerAndRouteConfiguration(0, default_listener_, route_config);
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  WaitForAllBackends();
+  EXPECT_EQ(RouteConfigurationResponseState(0).state,
+            AdsServiceImpl::ResponseState::ACKED);
+}
+
+// Test that we NACK unparseable filter types in ClusterWeight.
+TEST_P(LdsRdsTest, RejectsUnparseableHttpFilterTypeInClusterWeight) {
+  if (GetParam().use_v2()) return;  // Filters supported in v3 only.
+  RouteConfiguration route_config = default_route_config_;
+  auto* cluster_weight = route_config.mutable_virtual_hosts(0)
+                             ->mutable_routes(0)
+                             ->mutable_route()
+                             ->mutable_weighted_clusters()
+                             ->add_clusters();
+  cluster_weight->set_name(kDefaultClusterName);
+  cluster_weight->mutable_weight()->set_value(100);
+  auto* per_filter_config = cluster_weight->mutable_typed_per_filter_config();
+  (*per_filter_config)["unknown"].PackFrom(
+      envoy::extensions::filters::http::router::v3::Router());
+  SetListenerAndRouteConfiguration(0, default_listener_, route_config);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
+  const auto response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(
+      response_state.error_message,
+      ::testing::HasSubstr("router filter does not support config override"));
+}
+
+using CdsTest = BasicTest;
+
+// Tests that CDS client should send an ACK upon correct CDS response.
+TEST_P(CdsTest, Vanilla) {
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  (void)SendRpc();
+  EXPECT_EQ(balancers_[0]->ads_service()->cds_response_state().state,
+            AdsServiceImpl::ResponseState::ACKED);
+}
+
+TEST_P(CdsTest, LogicalDNSClusterType) {
+  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER",
+             "true");
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Create Logical DNS Cluster
+  auto cluster = default_cluster_;
+  cluster.set_type(Cluster::LOGICAL_DNS);
+  auto* address = cluster.mutable_load_assignment()
+                      ->add_endpoints()
+                      ->add_lb_endpoints()
+                      ->mutable_endpoint()
+                      ->mutable_address()
+                      ->mutable_socket_address();
+  address->set_address(kServerName);
+  address->set_port_value(443);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  // Set Logical DNS result
+  {
+    grpc_core::ExecCtx exec_ctx;
+    grpc_core::Resolver::Result result;
+    result.addresses = CreateAddressListFromPortList(GetBackendPorts(1, 2));
+    logical_dns_cluster_resolver_response_generator_->SetResponse(
+        std::move(result));
+  }
+  // Wait for traffic to go to backend 1.
+  WaitForBackend(1);
+  gpr_unsetenv(
+      "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER");
+}
+
+TEST_P(CdsTest, LogicalDNSClusterTypeMissingLoadAssignment) {
+  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER",
+             "true");
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Create Logical DNS Cluster
+  auto cluster = default_cluster_;
+  cluster.set_type(Cluster::LOGICAL_DNS);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->cds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr(
+                  "load_assignment not present for LOGICAL_DNS cluster"));
+  gpr_unsetenv(
+      "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER");
+}
+
+TEST_P(CdsTest, LogicalDNSClusterTypeMissingLocalities) {
+  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER",
+             "true");
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Create Logical DNS Cluster
+  auto cluster = default_cluster_;
+  cluster.set_type(Cluster::LOGICAL_DNS);
+  cluster.mutable_load_assignment();
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->cds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(
+      response_state.error_message,
+      ::testing::HasSubstr("load_assignment for LOGICAL_DNS cluster must have "
+                           "exactly one locality, found 0"));
+  gpr_unsetenv(
+      "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER");
+}
+
+TEST_P(CdsTest, LogicalDNSClusterTypeMultipleLocalities) {
+  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER",
+             "true");
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Create Logical DNS Cluster
+  auto cluster = default_cluster_;
+  cluster.set_type(Cluster::LOGICAL_DNS);
+  auto* load_assignment = cluster.mutable_load_assignment();
+  load_assignment->add_endpoints();
+  load_assignment->add_endpoints();
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->cds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(
+      response_state.error_message,
+      ::testing::HasSubstr("load_assignment for LOGICAL_DNS cluster must have "
+                           "exactly one locality, found 2"));
+  gpr_unsetenv(
+      "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER");
+}
+
+TEST_P(CdsTest, LogicalDNSClusterTypeMissingEndpoints) {
+  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER",
+             "true");
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Create Logical DNS Cluster
+  auto cluster = default_cluster_;
+  cluster.set_type(Cluster::LOGICAL_DNS);
+  cluster.mutable_load_assignment()->add_endpoints();
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->cds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr(
+                  "locality for LOGICAL_DNS cluster must have exactly one "
+                  "endpoint, found 0"));
+  gpr_unsetenv(
+      "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER");
+}
+
+TEST_P(CdsTest, LogicalDNSClusterTypeMultipleEndpoints) {
+  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER",
+             "true");
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Create Logical DNS Cluster
+  auto cluster = default_cluster_;
+  cluster.set_type(Cluster::LOGICAL_DNS);
+  auto* locality = cluster.mutable_load_assignment()->add_endpoints();
+  locality->add_lb_endpoints();
+  locality->add_lb_endpoints();
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->cds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr(
+                  "locality for LOGICAL_DNS cluster must have exactly one "
+                  "endpoint, found 2"));
+  gpr_unsetenv(
+      "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER");
+}
+
+TEST_P(CdsTest, LogicalDNSClusterTypeEmptyEndpoint) {
+  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER",
+             "true");
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Create Logical DNS Cluster
+  auto cluster = default_cluster_;
+  cluster.set_type(Cluster::LOGICAL_DNS);
+  cluster.mutable_load_assignment()->add_endpoints()->add_lb_endpoints();
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->cds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr("LbEndpoint endpoint field not set"));
+  gpr_unsetenv(
+      "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER");
+}
+
+TEST_P(CdsTest, LogicalDNSClusterTypeEndpointMissingAddress) {
+  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER",
+             "true");
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Create Logical DNS Cluster
+  auto cluster = default_cluster_;
+  cluster.set_type(Cluster::LOGICAL_DNS);
+  cluster.mutable_load_assignment()
+      ->add_endpoints()
+      ->add_lb_endpoints()
+      ->mutable_endpoint();
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->cds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr("Endpoint address field not set"));
+  gpr_unsetenv(
+      "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER");
+}
+
+TEST_P(CdsTest, LogicalDNSClusterTypeAddressMissingSocketAddress) {
+  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER",
+             "true");
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Create Logical DNS Cluster
+  auto cluster = default_cluster_;
+  cluster.set_type(Cluster::LOGICAL_DNS);
+  cluster.mutable_load_assignment()
+      ->add_endpoints()
+      ->add_lb_endpoints()
+      ->mutable_endpoint()
+      ->mutable_address();
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->cds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr("Address socket_address field not set"));
+  gpr_unsetenv(
+      "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER");
+}
+
+TEST_P(CdsTest, LogicalDNSClusterTypeSocketAddressHasResolverName) {
+  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER",
+             "true");
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Create Logical DNS Cluster
+  auto cluster = default_cluster_;
+  cluster.set_type(Cluster::LOGICAL_DNS);
+  cluster.mutable_load_assignment()
+      ->add_endpoints()
+      ->add_lb_endpoints()
+      ->mutable_endpoint()
+      ->mutable_address()
+      ->mutable_socket_address()
+      ->set_resolver_name("foo");
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->cds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr("LOGICAL_DNS clusters must NOT have a "
+                                   "custom resolver name set"));
+  gpr_unsetenv(
+      "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER");
+}
+
+TEST_P(CdsTest, LogicalDNSClusterTypeSocketAddressMissingAddress) {
+  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER",
+             "true");
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Create Logical DNS Cluster
+  auto cluster = default_cluster_;
+  cluster.set_type(Cluster::LOGICAL_DNS);
+  cluster.mutable_load_assignment()
+      ->add_endpoints()
+      ->add_lb_endpoints()
+      ->mutable_endpoint()
+      ->mutable_address()
+      ->mutable_socket_address();
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->cds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr("SocketAddress address field not set"));
+  gpr_unsetenv(
+      "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER");
+}
+
+TEST_P(CdsTest, LogicalDNSClusterTypeSocketAddressMissingPort) {
+  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER",
+             "true");
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Create Logical DNS Cluster
+  auto cluster = default_cluster_;
+  cluster.set_type(Cluster::LOGICAL_DNS);
+  cluster.mutable_load_assignment()
+      ->add_endpoints()
+      ->add_lb_endpoints()
+      ->mutable_endpoint()
+      ->mutable_address()
+      ->mutable_socket_address()
+      ->set_address(kServerName);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->cds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr("SocketAddress port_value field not set"));
+  gpr_unsetenv(
+      "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER");
+}
+
+TEST_P(CdsTest, AggregateClusterType) {
+  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER",
+             "true");
+  const char* kNewCluster1Name = "new_cluster_1";
+  const char* kNewEdsService1Name = "new_eds_service_name_1";
+  const char* kNewCluster2Name = "new_cluster_2";
+  const char* kNewEdsService2Name = "new_eds_service_name_2";
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Populate new EDS resources.
+  EdsResourceArgs args1({
+      {"locality0", CreateEndpointsForBackends(1, 2)},
+  });
+  EdsResourceArgs args2({
+      {"locality0", CreateEndpointsForBackends(2, 3)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args1, kNewEdsService1Name));
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args2, kNewEdsService2Name));
+  // Populate new CDS resources.
+  Cluster new_cluster1 = default_cluster_;
+  new_cluster1.set_name(kNewCluster1Name);
+  new_cluster1.mutable_eds_cluster_config()->set_service_name(
+      kNewEdsService1Name);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster1);
+  Cluster new_cluster2 = default_cluster_;
+  new_cluster2.set_name(kNewCluster2Name);
+  new_cluster2.mutable_eds_cluster_config()->set_service_name(
+      kNewEdsService2Name);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster2);
+  // Create Aggregate Cluster
+  auto cluster = default_cluster_;
+  CustomClusterType* custom_cluster = cluster.mutable_cluster_type();
+  custom_cluster->set_name("envoy.clusters.aggregate");
+  ClusterConfig cluster_config;
+  cluster_config.add_clusters(kNewCluster1Name);
+  cluster_config.add_clusters(kNewCluster2Name);
+  custom_cluster->mutable_typed_config()->PackFrom(cluster_config);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  // Wait for traffic to go to backend 1.
+  WaitForBackend(1);
+  // Shutdown backend 1 and wait for all traffic to go to backend 2.
+  ShutdownBackend(1);
+  WaitForBackend(2, WaitForBackendOptions().set_allow_failures(true));
+  EXPECT_EQ(balancers_[0]->ads_service()->cds_response_state().state,
+            AdsServiceImpl::ResponseState::ACKED);
+  // Bring backend 1 back and ensure all traffic go back to it.
+  StartBackend(1);
+  WaitForBackend(1);
+  gpr_unsetenv(
+      "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER");
+}
+
+TEST_P(CdsTest, AggregateClusterEdsToLogicalDns) {
+  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER",
+             "true");
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  const char* kNewCluster1Name = "new_cluster_1";
+  const char* kNewEdsService1Name = "new_eds_service_name_1";
+  const char* kLogicalDNSClusterName = "logical_dns_cluster";
+  // Populate new EDS resources.
+  EdsResourceArgs args1({
+      {"locality0", CreateEndpointsForBackends(1, 2)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args1, kNewEdsService1Name));
+  // Populate new CDS resources.
+  Cluster new_cluster1 = default_cluster_;
+  new_cluster1.set_name(kNewCluster1Name);
+  new_cluster1.mutable_eds_cluster_config()->set_service_name(
+      kNewEdsService1Name);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster1);
+  // Create Logical DNS Cluster
+  auto logical_dns_cluster = default_cluster_;
+  logical_dns_cluster.set_name(kLogicalDNSClusterName);
+  logical_dns_cluster.set_type(Cluster::LOGICAL_DNS);
+  auto* address = logical_dns_cluster.mutable_load_assignment()
+                      ->add_endpoints()
+                      ->add_lb_endpoints()
+                      ->mutable_endpoint()
+                      ->mutable_address()
+                      ->mutable_socket_address();
+  address->set_address(kServerName);
+  address->set_port_value(443);
+  balancers_[0]->ads_service()->SetCdsResource(logical_dns_cluster);
+  // Create Aggregate Cluster
+  auto cluster = default_cluster_;
+  CustomClusterType* custom_cluster = cluster.mutable_cluster_type();
+  custom_cluster->set_name("envoy.clusters.aggregate");
+  ClusterConfig cluster_config;
+  cluster_config.add_clusters(kNewCluster1Name);
+  cluster_config.add_clusters(kLogicalDNSClusterName);
+  custom_cluster->mutable_typed_config()->PackFrom(cluster_config);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  // Set Logical DNS result
+  {
+    grpc_core::ExecCtx exec_ctx;
+    grpc_core::Resolver::Result result;
+    result.addresses = CreateAddressListFromPortList(GetBackendPorts(2, 3));
+    logical_dns_cluster_resolver_response_generator_->SetResponse(
+        std::move(result));
+  }
+  // Wait for traffic to go to backend 1.
+  WaitForBackend(1);
+  // Shutdown backend 1 and wait for all traffic to go to backend 2.
+  ShutdownBackend(1);
+  WaitForBackend(2, WaitForBackendOptions().set_allow_failures(true));
+  EXPECT_EQ(balancers_[0]->ads_service()->cds_response_state().state,
+            AdsServiceImpl::ResponseState::ACKED);
+  // Bring backend 1 back and ensure all traffic go back to it.
+  StartBackend(1);
+  WaitForBackend(1);
+  gpr_unsetenv(
+      "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER");
+}
+
+TEST_P(CdsTest, AggregateClusterLogicalDnsToEds) {
+  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER",
+             "true");
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  const char* kNewCluster2Name = "new_cluster_2";
+  const char* kNewEdsService2Name = "new_eds_service_name_2";
+  const char* kLogicalDNSClusterName = "logical_dns_cluster";
+  // Populate new EDS resources.
+  EdsResourceArgs args2({
+      {"locality0", CreateEndpointsForBackends(2, 3)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args2, kNewEdsService2Name));
+  // Populate new CDS resources.
+  Cluster new_cluster2 = default_cluster_;
+  new_cluster2.set_name(kNewCluster2Name);
+  new_cluster2.mutable_eds_cluster_config()->set_service_name(
+      kNewEdsService2Name);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster2);
+  // Create Logical DNS Cluster
+  auto logical_dns_cluster = default_cluster_;
+  logical_dns_cluster.set_name(kLogicalDNSClusterName);
+  logical_dns_cluster.set_type(Cluster::LOGICAL_DNS);
+  auto* address = logical_dns_cluster.mutable_load_assignment()
+                      ->add_endpoints()
+                      ->add_lb_endpoints()
+                      ->mutable_endpoint()
+                      ->mutable_address()
+                      ->mutable_socket_address();
+  address->set_address(kServerName);
+  address->set_port_value(443);
+  balancers_[0]->ads_service()->SetCdsResource(logical_dns_cluster);
+  // Create Aggregate Cluster
+  auto cluster = default_cluster_;
+  CustomClusterType* custom_cluster = cluster.mutable_cluster_type();
+  custom_cluster->set_name("envoy.clusters.aggregate");
+  ClusterConfig cluster_config;
+  cluster_config.add_clusters(kLogicalDNSClusterName);
+  cluster_config.add_clusters(kNewCluster2Name);
+  custom_cluster->mutable_typed_config()->PackFrom(cluster_config);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  // Set Logical DNS result
+  {
+    grpc_core::ExecCtx exec_ctx;
+    grpc_core::Resolver::Result result;
+    result.addresses = CreateAddressListFromPortList(GetBackendPorts(1, 2));
+    logical_dns_cluster_resolver_response_generator_->SetResponse(
+        std::move(result));
+  }
+  // Wait for traffic to go to backend 1.
+  WaitForBackend(1);
+  // Shutdown backend 1 and wait for all traffic to go to backend 2.
+  ShutdownBackend(1);
+  WaitForBackend(2, WaitForBackendOptions().set_allow_failures(true));
+  EXPECT_EQ(balancers_[0]->ads_service()->cds_response_state().state,
+            AdsServiceImpl::ResponseState::ACKED);
+  // Bring backend 1 back and ensure all traffic go back to it.
+  StartBackend(1);
+  WaitForBackend(1);
+  gpr_unsetenv(
+      "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER");
+}
+
+// Test that CDS client should send a NACK if cluster type is Logical DNS but
+// the feature is not yet supported.
+TEST_P(CdsTest, LogicalDNSClusterTypeDisabled) {
+  auto cluster = default_cluster_;
+  cluster.set_type(Cluster::LOGICAL_DNS);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->cds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr("DiscoveryType is not valid."));
+}
+
+// Test that CDS client should send a NACK if cluster type is AGGREGATE but
+// the feature is not yet supported.
+TEST_P(CdsTest, AggregateClusterTypeDisabled) {
+  auto cluster = default_cluster_;
+  CustomClusterType* custom_cluster = cluster.mutable_cluster_type();
+  custom_cluster->set_name("envoy.clusters.aggregate");
+  ClusterConfig cluster_config;
+  cluster_config.add_clusters("cluster1");
+  cluster_config.add_clusters("cluster2");
+  custom_cluster->mutable_typed_config()->PackFrom(cluster_config);
+  cluster.set_type(Cluster::LOGICAL_DNS);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->cds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr("DiscoveryType is not valid."));
+}
+
+// Tests that CDS client should send a NACK if the cluster type in CDS
+// response is unsupported.
+TEST_P(CdsTest, UnsupportedClusterType) {
+  auto cluster = default_cluster_;
+  cluster.set_type(Cluster::STATIC);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->cds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr("DiscoveryType is not valid."));
+}
+
+// Tests that the NACK for multiple bad resources includes both errors.
+TEST_P(CdsTest, MultipleBadResources) {
+  constexpr char kClusterName2[] = "cluster_name_2";
+  constexpr char kClusterName3[] = "cluster_name_3";
+  // Add cluster with unsupported type.
+  auto cluster = default_cluster_;
+  cluster.set_name(kClusterName2);
+  cluster.set_type(Cluster::STATIC);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  // Add second cluster with the same error.
+  cluster.set_name(kClusterName3);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  // Change RouteConfig to point to all clusters.
+  RouteConfiguration route_config = default_route_config_;
+  route_config.mutable_virtual_hosts(0)->clear_routes();
+  // First route: default cluster, selected based on header.
+  auto* route = route_config.mutable_virtual_hosts(0)->add_routes();
+  route->mutable_match()->set_prefix("");
+  auto* header_matcher = route->mutable_match()->add_headers();
+  header_matcher->set_name("cluster");
+  header_matcher->set_exact_match(kDefaultClusterName);
+  route->mutable_route()->set_cluster(kDefaultClusterName);
+  // Second route: cluster 2, selected based on header.
+  route = route_config.mutable_virtual_hosts(0)->add_routes();
+  route->mutable_match()->set_prefix("");
+  header_matcher = route->mutable_match()->add_headers();
+  header_matcher->set_name("cluster");
+  header_matcher->set_exact_match(kClusterName2);
+  route->mutable_route()->set_cluster(kClusterName2);
+  // Third route: cluster 3, used by default.
+  route = route_config.mutable_virtual_hosts(0)->add_routes();
+  route->mutable_match()->set_prefix("");
+  route->mutable_route()->set_cluster(kClusterName3);
+  SetRouteConfiguration(0, route_config);
+  // Add EDS resource.
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 1)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
+  // Send RPC.
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->cds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(
+      response_state.error_message,
+      ::testing::ContainsRegex(absl::StrCat(kClusterName2,
+                                            ": validation error.*"
+                                            "DiscoveryType is not valid.*",
+                                            kClusterName3,
+                                            ": validation error.*"
+                                            "DiscoveryType is not valid")));
+  // RPCs for default cluster should succeed.
+  std::vector<std::pair<std::string, std::string>> metadata_default_cluster = {
+      {"cluster", kDefaultClusterName},
+  };
+  CheckRpcSendOk(
+      1, RpcOptions().set_metadata(std::move(metadata_default_cluster)));
+  // RPCs for cluster 2 should fail.
+  std::vector<std::pair<std::string, std::string>> metadata_cluster_2 = {
+      {"cluster", kClusterName2},
+  };
+  CheckRpcSendFailure(CheckRpcSendFailureOptions().set_rpc_options(
+      RpcOptions().set_metadata(std::move(metadata_cluster_2))));
+}
+
+// Tests that we don't trigger does-not-exist callbacks for a resource
+// that was previously valid but is updated to be invalid.
+TEST_P(CdsTest, InvalidClusterStillExistsIfPreviouslyCached) {
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 1)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Check that everything works.
+  CheckRpcSendOk();
+  // Now send an update changing the Cluster to be invalid.
+  auto cluster = default_cluster_;
+  cluster.set_type(Cluster::STATIC);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  // Wait for xDS server to see NACK.
+  auto deadline = absl::Now() + absl::Seconds(30);
+  do {
+    CheckRpcSendOk();
+    ASSERT_LT(absl::Now(), deadline);
+  } while (balancers_[0]->ads_service()->cds_response_state().state !=
+           AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(balancers_[0]->ads_service()->cds_response_state().error_message,
+              ::testing::ContainsRegex(absl::StrCat(
+                  kDefaultClusterName,
+                  ": validation error.*DiscoveryType is not valid")));
+  // Check one more time, just to make sure it still works after NACK.
+  CheckRpcSendOk();
+}
+
+// Tests that CDS client should send a NACK if the eds_config in CDS response
+// is other than ADS.
+TEST_P(CdsTest, WrongEdsConfig) {
+  auto cluster = default_cluster_;
+  cluster.mutable_eds_cluster_config()->mutable_eds_config()->mutable_self();
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->cds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr("EDS ConfigSource is not ADS."));
+}
+
+// Tests that CDS client should send a NACK if the lb_policy in CDS response
+// is other than ROUND_ROBIN.
+TEST_P(CdsTest, WrongLbPolicy) {
+  auto cluster = default_cluster_;
+  cluster.set_lb_policy(Cluster::LEAST_REQUEST);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->cds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr("LB policy is not supported."));
+}
+
+// Tests that CDS client should send a NACK if the lrs_server in CDS response
+// is other than SELF.
+TEST_P(CdsTest, WrongLrsServer) {
+  auto cluster = default_cluster_;
+  cluster.mutable_lrs_server()->mutable_ads();
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->cds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr("LRS ConfigSource is not self."));
+}
+
+// Tests that ring hash policy that hashes using channel id ensures all RPCs
+// to go 1 particular backend.
+TEST_P(CdsTest, RingHashChannelIdHashing) {
+  auto cluster = default_cluster_;
+  cluster.set_lb_policy(Cluster::RING_HASH);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  auto new_route_config = default_route_config_;
+  auto* route = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  auto* hash_policy = route->mutable_route()->add_hash_policy();
+  hash_policy->mutable_filter_state()->set_key("io.grpc.channel_id");
+  SetListenerAndRouteConfiguration(0, default_listener_, new_route_config);
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  SetNextResolutionForLbChannelAllBalancers();
+  CheckRpcSendOk(100);
+  bool found = false;
+  for (size_t i = 0; i < backends_.size(); ++i) {
+    if (backends_[i]->backend_service()->request_count() > 0) {
+      EXPECT_EQ(backends_[i]->backend_service()->request_count(), 100)
+          << "backend " << i;
+      EXPECT_FALSE(found) << "backend " << i;
+      found = true;
+    }
+  }
+  EXPECT_TRUE(found);
+}
+
+// Tests that ring hash policy that hashes using a header value can spread
+// RPCs across all the backends.
+TEST_P(CdsTest, RingHashHeaderHashing) {
+  auto cluster = default_cluster_;
+  cluster.set_lb_policy(Cluster::RING_HASH);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  auto new_route_config = default_route_config_;
+  auto* route = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  auto* hash_policy = route->mutable_route()->add_hash_policy();
+  hash_policy->mutable_header()->set_header_name("address_hash");
+  SetListenerAndRouteConfiguration(0, default_listener_, new_route_config);
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  SetNextResolutionForLbChannelAllBalancers();
+  // Note each type of RPC will contains a header value that will always be
+  // hashed to a specific backend as the header value matches the value used
+  // to create the entry in the ring.
+  std::vector<std::pair<std::string, std::string>> metadata = {
+      {"address_hash", CreateMetadataValueThatHashesToBackend(0)}};
+  std::vector<std::pair<std::string, std::string>> metadata1 = {
+      {"address_hash", CreateMetadataValueThatHashesToBackend(1)}};
+  std::vector<std::pair<std::string, std::string>> metadata2 = {
+      {"address_hash", CreateMetadataValueThatHashesToBackend(2)}};
+  std::vector<std::pair<std::string, std::string>> metadata3 = {
+      {"address_hash", CreateMetadataValueThatHashesToBackend(3)}};
+  const auto rpc_options = RpcOptions().set_metadata(std::move(metadata));
+  const auto rpc_options1 = RpcOptions().set_metadata(std::move(metadata1));
+  const auto rpc_options2 = RpcOptions().set_metadata(std::move(metadata2));
+  const auto rpc_options3 = RpcOptions().set_metadata(std::move(metadata3));
+  WaitForBackend(0, WaitForBackendOptions(), rpc_options);
+  WaitForBackend(1, WaitForBackendOptions(), rpc_options1);
+  WaitForBackend(2, WaitForBackendOptions(), rpc_options2);
+  WaitForBackend(3, WaitForBackendOptions(), rpc_options3);
+  CheckRpcSendOk(100, rpc_options);
+  CheckRpcSendOk(100, rpc_options1);
+  CheckRpcSendOk(100, rpc_options2);
+  CheckRpcSendOk(100, rpc_options3);
+  for (size_t i = 0; i < backends_.size(); ++i) {
+    EXPECT_EQ(100, backends_[i]->backend_service()->request_count());
+  }
+}
+
+// Tests that ring hash policy that hashes using a header value and regex
+// rewrite to aggregate RPCs to 1 backend.
+TEST_P(CdsTest, RingHashHeaderHashingWithRegexRewrite) {
+  auto cluster = default_cluster_;
+  cluster.set_lb_policy(Cluster::RING_HASH);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  auto new_route_config = default_route_config_;
+  auto* route = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  auto* hash_policy = route->mutable_route()->add_hash_policy();
+  hash_policy->mutable_header()->set_header_name("address_hash");
+  hash_policy->mutable_header()
+      ->mutable_regex_rewrite()
+      ->mutable_pattern()
+      ->set_regex("[0-9]+");
+  hash_policy->mutable_header()->mutable_regex_rewrite()->set_substitution(
+      "foo");
+  SetListenerAndRouteConfiguration(0, default_listener_, new_route_config);
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  SetNextResolutionForLbChannelAllBalancers();
+  std::vector<std::pair<std::string, std::string>> metadata = {
+      {"address_hash", CreateMetadataValueThatHashesToBackend(0)}};
+  std::vector<std::pair<std::string, std::string>> metadata1 = {
+      {"address_hash", CreateMetadataValueThatHashesToBackend(1)}};
+  std::vector<std::pair<std::string, std::string>> metadata2 = {
+      {"address_hash", CreateMetadataValueThatHashesToBackend(2)}};
+  std::vector<std::pair<std::string, std::string>> metadata3 = {
+      {"address_hash", CreateMetadataValueThatHashesToBackend(3)}};
+  const auto rpc_options = RpcOptions().set_metadata(std::move(metadata));
+  const auto rpc_options1 = RpcOptions().set_metadata(std::move(metadata1));
+  const auto rpc_options2 = RpcOptions().set_metadata(std::move(metadata2));
+  const auto rpc_options3 = RpcOptions().set_metadata(std::move(metadata3));
+  CheckRpcSendOk(100, rpc_options);
+  CheckRpcSendOk(100, rpc_options1);
+  CheckRpcSendOk(100, rpc_options2);
+  CheckRpcSendOk(100, rpc_options3);
+  bool found = false;
+  for (size_t i = 0; i < backends_.size(); ++i) {
+    if (backends_[i]->backend_service()->request_count() > 0) {
+      EXPECT_EQ(backends_[i]->backend_service()->request_count(), 400)
+          << "backend " << i;
+      EXPECT_FALSE(found) << "backend " << i;
+      found = true;
+    }
+  }
+  EXPECT_TRUE(found);
+}
+
+// Tests that ring hash policy that hashes using a random value.
+TEST_P(CdsTest, RingHashNoHashPolicy) {
+  const double kDistribution50Percent = 0.5;
+  const double kErrorTolerance = 0.05;
+  const uint32_t kRpcTimeoutMs = 10000;
+  const size_t kNumRpcs =
+      ComputeIdealNumRpcs(kDistribution50Percent, kErrorTolerance);
+  auto cluster = default_cluster_;
+  // Increasing min ring size for random distribution.
+  cluster.mutable_ring_hash_lb_config()->mutable_minimum_ring_size()->set_value(
+      100000);
+  cluster.set_lb_policy(Cluster::RING_HASH);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  EdsResourceArgs args({{"locality0", CreateEndpointsForBackends(0, 2)}});
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  SetNextResolutionForLbChannelAllBalancers();
+  // TODO(donnadionne): remove extended timeout after ring creation
+  // optimization.
+  WaitForAllBackends(0, 2, WaitForBackendOptions(),
+                     RpcOptions().set_timeout_ms(kRpcTimeoutMs));
+  CheckRpcSendOk(kNumRpcs);
+  const int request_count_1 = backends_[0]->backend_service()->request_count();
+  const int request_count_2 = backends_[1]->backend_service()->request_count();
+  EXPECT_THAT(static_cast<double>(request_count_1) / kNumRpcs,
+              ::testing::DoubleNear(kDistribution50Percent, kErrorTolerance));
+  EXPECT_THAT(static_cast<double>(request_count_2) / kNumRpcs,
+              ::testing::DoubleNear(kDistribution50Percent, kErrorTolerance));
+}
+
+// Test that ring hash policy evaluation will continue past the terminal
+// policy if no results are produced yet.
+TEST_P(CdsTest, RingHashContinuesPastTerminalPolicyThatDoesNotProduceResult) {
+  auto cluster = default_cluster_;
+  cluster.set_lb_policy(Cluster::RING_HASH);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  auto new_route_config = default_route_config_;
+  auto* route = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  auto* hash_policy = route->mutable_route()->add_hash_policy();
+  hash_policy->mutable_header()->set_header_name("header_not_present");
+  hash_policy->set_terminal(true);
+  auto* hash_policy2 = route->mutable_route()->add_hash_policy();
+  hash_policy2->mutable_header()->set_header_name("address_hash");
+  SetListenerAndRouteConfiguration(0, default_listener_, new_route_config);
+  EdsResourceArgs args({{"locality0", CreateEndpointsForBackends(0, 2)}});
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  SetNextResolutionForLbChannelAllBalancers();
+  std::vector<std::pair<std::string, std::string>> metadata = {
+      {"address_hash", CreateMetadataValueThatHashesToBackend(0)}};
+  const auto rpc_options = RpcOptions().set_metadata(std::move(metadata));
+  CheckRpcSendOk(100, rpc_options);
+  EXPECT_EQ(backends_[0]->backend_service()->request_count(), 100);
+  EXPECT_EQ(backends_[1]->backend_service()->request_count(), 0);
+}
+
+// Test random hash is used when header hashing specified a header field that
+// the RPC did not have.
+TEST_P(CdsTest, RingHashOnHeaderThatIsNotPresent) {
+  const double kDistribution50Percent = 0.5;
+  const double kErrorTolerance = 0.05;
+  const uint32_t kRpcTimeoutMs = 10000;
+  const size_t kNumRpcs =
+      ComputeIdealNumRpcs(kDistribution50Percent, kErrorTolerance);
+  auto cluster = default_cluster_;
+  // Increasing min ring size for random distribution.
+  cluster.mutable_ring_hash_lb_config()->mutable_minimum_ring_size()->set_value(
+      100000);
+  cluster.set_lb_policy(Cluster::RING_HASH);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  auto new_route_config = default_route_config_;
+  auto* route = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  auto* hash_policy = route->mutable_route()->add_hash_policy();
+  hash_policy->mutable_header()->set_header_name("header_not_present");
+  SetListenerAndRouteConfiguration(0, default_listener_, new_route_config);
+  EdsResourceArgs args({{"locality0", CreateEndpointsForBackends(0, 2)}});
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  SetNextResolutionForLbChannelAllBalancers();
+  std::vector<std::pair<std::string, std::string>> metadata = {
+      {"unmatched_header", absl::StrFormat("%" PRIu32, rand())},
+  };
+  const auto rpc_options = RpcOptions().set_metadata(std::move(metadata));
+  // TODO(donnadionne): remove extended timeout after ring creation
+  // optimization.
+  WaitForAllBackends(0, 2, WaitForBackendOptions(),
+                     RpcOptions().set_timeout_ms(kRpcTimeoutMs));
+  CheckRpcSendOk(kNumRpcs, rpc_options);
+  const int request_count_1 = backends_[0]->backend_service()->request_count();
+  const int request_count_2 = backends_[1]->backend_service()->request_count();
+  EXPECT_THAT(static_cast<double>(request_count_1) / kNumRpcs,
+              ::testing::DoubleNear(kDistribution50Percent, kErrorTolerance));
+  EXPECT_THAT(static_cast<double>(request_count_2) / kNumRpcs,
+              ::testing::DoubleNear(kDistribution50Percent, kErrorTolerance));
+}
+
+// Test random hash is used when only unsupported hash policies are
+// configured.
+TEST_P(CdsTest, RingHashUnsupportedHashPolicyDefaultToRandomHashing) {
+  const double kDistribution50Percent = 0.5;
+  const double kErrorTolerance = 0.05;
+  const uint32_t kRpcTimeoutMs = 10000;
+  const size_t kNumRpcs =
+      ComputeIdealNumRpcs(kDistribution50Percent, kErrorTolerance);
+  auto cluster = default_cluster_;
+  // Increasing min ring size for random distribution.
+  cluster.mutable_ring_hash_lb_config()->mutable_minimum_ring_size()->set_value(
+      100000);
+  cluster.set_lb_policy(Cluster::RING_HASH);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  auto new_route_config = default_route_config_;
+  auto* route = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  auto* hash_policy_unsupported_1 = route->mutable_route()->add_hash_policy();
+  hash_policy_unsupported_1->mutable_cookie()->set_name("cookie");
+  auto* hash_policy_unsupported_2 = route->mutable_route()->add_hash_policy();
+  hash_policy_unsupported_2->mutable_connection_properties()->set_source_ip(
+      true);
+  auto* hash_policy_unsupported_3 = route->mutable_route()->add_hash_policy();
+  hash_policy_unsupported_3->mutable_query_parameter()->set_name(
+      "query_parameter");
+  SetListenerAndRouteConfiguration(0, default_listener_, new_route_config);
+  EdsResourceArgs args({{"locality0", CreateEndpointsForBackends(0, 2)}});
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  SetNextResolutionForLbChannelAllBalancers();
+  // TODO(donnadionne): remove extended timeout after ring creation
+  // optimization.
+  WaitForAllBackends(0, 2, WaitForBackendOptions(),
+                     RpcOptions().set_timeout_ms(kRpcTimeoutMs));
+  CheckRpcSendOk(kNumRpcs);
+  const int request_count_1 = backends_[0]->backend_service()->request_count();
+  const int request_count_2 = backends_[1]->backend_service()->request_count();
+  EXPECT_THAT(static_cast<double>(request_count_1) / kNumRpcs,
+              ::testing::DoubleNear(kDistribution50Percent, kErrorTolerance));
+  EXPECT_THAT(static_cast<double>(request_count_2) / kNumRpcs,
+              ::testing::DoubleNear(kDistribution50Percent, kErrorTolerance));
+}
+
+// Tests that ring hash policy that hashes using a random value can spread
+// RPCs across all the backends according to locality weight.
+TEST_P(CdsTest, RingHashRandomHashingDistributionAccordingToEndpointWeight) {
+  const size_t kWeight1 = 1;
+  const size_t kWeight2 = 2;
+  const size_t kWeightTotal = kWeight1 + kWeight2;
+  const double kWeight33Percent = static_cast<double>(kWeight1) / kWeightTotal;
+  const double kWeight66Percent = static_cast<double>(kWeight2) / kWeightTotal;
+  const double kErrorTolerance = 0.05;
+  const uint32_t kRpcTimeoutMs = 10000;
+  const size_t kNumRpcs =
+      ComputeIdealNumRpcs(kWeight33Percent, kErrorTolerance);
+  auto cluster = default_cluster_;
+  // Increasing min ring size for random distribution.
+  cluster.mutable_ring_hash_lb_config()->mutable_minimum_ring_size()->set_value(
+      100000);
+  cluster.set_lb_policy(Cluster::RING_HASH);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  EdsResourceArgs args({{"locality0",
+                         {CreateEndpoint(0, HealthStatus::UNKNOWN, 1),
+                          CreateEndpoint(1, HealthStatus::UNKNOWN, 2)}}});
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  SetNextResolutionForLbChannelAllBalancers();
+  // TODO(donnadionne): remove extended timeout after ring creation
+  // optimization.
+  WaitForAllBackends(0, 2, WaitForBackendOptions(),
+                     RpcOptions().set_timeout_ms(kRpcTimeoutMs));
+  CheckRpcSendOk(kNumRpcs);
+  const int weight_33_request_count =
+      backends_[0]->backend_service()->request_count();
+  const int weight_66_request_count =
+      backends_[1]->backend_service()->request_count();
+  EXPECT_THAT(static_cast<double>(weight_33_request_count) / kNumRpcs,
+              ::testing::DoubleNear(kWeight33Percent, kErrorTolerance));
+  EXPECT_THAT(static_cast<double>(weight_66_request_count) / kNumRpcs,
+              ::testing::DoubleNear(kWeight66Percent, kErrorTolerance));
+}
+
+// Tests that ring hash policy that hashes using a random value can spread
+// RPCs across all the backends according to locality weight.
+TEST_P(CdsTest,
+       RingHashRandomHashingDistributionAccordingToLocalityAndEndpointWeight) {
+  const size_t kWeight1 = 1 * 1;
+  const size_t kWeight2 = 2 * 2;
+  const size_t kWeightTotal = kWeight1 + kWeight2;
+  const double kWeight20Percent = static_cast<double>(kWeight1) / kWeightTotal;
+  const double kWeight80Percent = static_cast<double>(kWeight2) / kWeightTotal;
+  const double kErrorTolerance = 0.05;
+  const uint32_t kRpcTimeoutMs = 10000;
+  const size_t kNumRpcs =
+      ComputeIdealNumRpcs(kWeight20Percent, kErrorTolerance);
+  auto cluster = default_cluster_;
+  // Increasing min ring size for random distribution.
+  cluster.mutable_ring_hash_lb_config()->mutable_minimum_ring_size()->set_value(
+      100000);
+  cluster.set_lb_policy(Cluster::RING_HASH);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  EdsResourceArgs args(
+      {{"locality0", {CreateEndpoint(0, HealthStatus::UNKNOWN, 1)}, 1},
+       {"locality1", {CreateEndpoint(1, HealthStatus::UNKNOWN, 2)}, 2}});
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  SetNextResolutionForLbChannelAllBalancers();
+  // TODO(donnadionne): remove extended timeout after ring creation
+  // optimization.
+  WaitForAllBackends(0, 2, WaitForBackendOptions(),
+                     RpcOptions().set_timeout_ms(kRpcTimeoutMs));
+  CheckRpcSendOk(kNumRpcs);
+  const int weight_20_request_count =
+      backends_[0]->backend_service()->request_count();
+  const int weight_80_request_count =
+      backends_[1]->backend_service()->request_count();
+  EXPECT_THAT(static_cast<double>(weight_20_request_count) / kNumRpcs,
+              ::testing::DoubleNear(kWeight20Percent, kErrorTolerance));
+  EXPECT_THAT(static_cast<double>(weight_80_request_count) / kNumRpcs,
+              ::testing::DoubleNear(kWeight80Percent, kErrorTolerance));
+}
+
+// Tests round robin is not implacted by the endpoint weight, and that the
+// localities in a locality map are picked according to their weights.
+TEST_P(CdsTest, RingHashEndpointWeightDoesNotImpactWeightedRoundRobin) {
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  const int kLocalityWeight0 = 2;
+  const int kLocalityWeight1 = 8;
+  const int kTotalLocalityWeight = kLocalityWeight0 + kLocalityWeight1;
+  const double kLocalityWeightRate0 =
+      static_cast<double>(kLocalityWeight0) / kTotalLocalityWeight;
+  const double kLocalityWeightRate1 =
+      static_cast<double>(kLocalityWeight1) / kTotalLocalityWeight;
+  const double kErrorTolerance = 0.05;
+  const size_t kNumRpcs =
+      ComputeIdealNumRpcs(kLocalityWeightRate0, kErrorTolerance);
+  // ADS response contains 2 localities, each of which contains 1 backend.
+  EdsResourceArgs args({
+      {"locality0",
+       {CreateEndpoint(0, HealthStatus::UNKNOWN, 8)},
+       kLocalityWeight0},
+      {"locality1",
+       {CreateEndpoint(1, HealthStatus::UNKNOWN, 2)},
+       kLocalityWeight1},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  // Wait for both backends to be ready.
+  WaitForAllBackends(0, 2);
+  // Send kNumRpcs RPCs.
+  CheckRpcSendOk(kNumRpcs);
+  // The locality picking rates should be roughly equal to the expectation.
+  const double locality_picked_rate_0 =
+      static_cast<double>(backends_[0]->backend_service()->request_count()) /
+      kNumRpcs;
+  const double locality_picked_rate_1 =
+      static_cast<double>(backends_[1]->backend_service()->request_count()) /
+      kNumRpcs;
+  EXPECT_THAT(locality_picked_rate_0,
+              ::testing::DoubleNear(kLocalityWeightRate0, kErrorTolerance));
+  EXPECT_THAT(locality_picked_rate_1,
+              ::testing::DoubleNear(kLocalityWeightRate1, kErrorTolerance));
+}
+
+// Tests that ring hash policy that hashes using a fixed string ensures all
+// RPCs to go 1 particular backend; and that subsequent hashing policies are
+// ignored due to the setting of terminal.
+TEST_P(CdsTest, RingHashFixedHashingTerminalPolicy) {
+  auto cluster = default_cluster_;
+  cluster.set_lb_policy(Cluster::RING_HASH);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  auto new_route_config = default_route_config_;
+  auto* route = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  auto* hash_policy = route->mutable_route()->add_hash_policy();
+  hash_policy->mutable_header()->set_header_name("fixed_string");
+  hash_policy->set_terminal(true);
+  auto* hash_policy_to_be_ignored = route->mutable_route()->add_hash_policy();
+  hash_policy_to_be_ignored->mutable_header()->set_header_name("random_string");
+  SetListenerAndRouteConfiguration(0, default_listener_, new_route_config);
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  SetNextResolutionForLbChannelAllBalancers();
+  std::vector<std::pair<std::string, std::string>> metadata = {
+      {"fixed_string", "fixed_value"},
+      {"random_string", absl::StrFormat("%" PRIu32, rand())},
+  };
+  const auto rpc_options = RpcOptions().set_metadata(std::move(metadata));
+  CheckRpcSendOk(100, rpc_options);
+  bool found = false;
+  for (size_t i = 0; i < backends_.size(); ++i) {
+    if (backends_[i]->backend_service()->request_count() > 0) {
+      EXPECT_EQ(backends_[i]->backend_service()->request_count(), 100)
+          << "backend " << i;
+      EXPECT_FALSE(found) << "backend " << i;
+      found = true;
+    }
+  }
+  EXPECT_TRUE(found);
+}
+
+// Test that the channel will go from idle to ready via connecting;
+// (tho it is not possible to catch the connecting state before moving to
+// ready)
+TEST_P(CdsTest, RingHashIdleToReady) {
+  auto cluster = default_cluster_;
+  cluster.set_lb_policy(Cluster::RING_HASH);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  auto new_route_config = default_route_config_;
+  auto* route = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  auto* hash_policy = route->mutable_route()->add_hash_policy();
+  hash_policy->mutable_filter_state()->set_key("io.grpc.channel_id");
+  SetListenerAndRouteConfiguration(0, default_listener_, new_route_config);
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  SetNextResolutionForLbChannelAllBalancers();
+  EXPECT_EQ(GRPC_CHANNEL_IDLE, channel_->GetState(false));
+  CheckRpcSendOk();
+  EXPECT_EQ(GRPC_CHANNEL_READY, channel_->GetState(false));
+}
+
+// Test that when the first pick is down leading to a transient failure, we
+// will move on to the next ring hash entry.
+TEST_P(CdsTest, RingHashTransientFailureCheckNextOne) {
+  auto cluster = default_cluster_;
+  cluster.set_lb_policy(Cluster::RING_HASH);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  auto new_route_config = default_route_config_;
+  auto* route = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  auto* hash_policy = route->mutable_route()->add_hash_policy();
+  hash_policy->mutable_header()->set_header_name("address_hash");
+  SetListenerAndRouteConfiguration(0, default_listener_, new_route_config);
+  std::vector<EdsResourceArgs::Endpoint> endpoints;
+  const int unused_port = grpc_pick_unused_port_or_die();
+  endpoints.emplace_back(unused_port);
+  endpoints.emplace_back(backends_[1]->port());
+  EdsResourceArgs args({
+      {"locality0", std::move(endpoints)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  SetNextResolutionForLbChannelAllBalancers();
+  std::vector<std::pair<std::string, std::string>> metadata = {
+      {"address_hash",
+       CreateMetadataValueThatHashesToBackendPort(unused_port)}};
+  const auto rpc_options = RpcOptions().set_metadata(std::move(metadata));
+  WaitForBackend(1, WaitForBackendOptions(), rpc_options);
+  CheckRpcSendOk(100, rpc_options);
+  EXPECT_EQ(0, backends_[0]->backend_service()->request_count());
+  EXPECT_EQ(100, backends_[1]->backend_service()->request_count());
+}
+
+// Test that when a backend goes down, we will move on to the next subchannel
+// (with a lower priority).  When the backend comes back up, traffic will move
+// back.
+TEST_P(CdsTest, RingHashSwitchToLowerPrioirtyAndThenBack) {
+  auto cluster = default_cluster_;
+  cluster.set_lb_policy(Cluster::RING_HASH);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  auto new_route_config = default_route_config_;
+  auto* route = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  auto* hash_policy = route->mutable_route()->add_hash_policy();
+  hash_policy->mutable_header()->set_header_name("address_hash");
+  SetListenerAndRouteConfiguration(0, default_listener_, new_route_config);
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 1), kDefaultLocalityWeight,
+       0},
+      {"locality1", CreateEndpointsForBackends(1, 2), kDefaultLocalityWeight,
+       1},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  SetNextResolutionForLbChannelAllBalancers();
+  std::vector<std::pair<std::string, std::string>> metadata = {
+      {"address_hash", CreateMetadataValueThatHashesToBackend(0)}};
+  const auto rpc_options = RpcOptions().set_metadata(std::move(metadata));
+  WaitForBackend(0, WaitForBackendOptions(), rpc_options);
+  ShutdownBackend(0);
+  WaitForBackend(1, WaitForBackendOptions().set_allow_failures(true),
+                 rpc_options);
+  StartBackend(0);
+  WaitForBackend(0, WaitForBackendOptions(), rpc_options);
+  CheckRpcSendOk(100, rpc_options);
+  EXPECT_EQ(100, backends_[0]->backend_service()->request_count());
+  EXPECT_EQ(0, backends_[1]->backend_service()->request_count());
+}
+
+// Test that when all backends are down, we will keep reattempting.
+TEST_P(CdsTest, RingHashAllFailReattempt) {
+  const uint32_t kConnectionTimeoutMilliseconds = 5000;
+  auto cluster = default_cluster_;
+  cluster.set_lb_policy(Cluster::RING_HASH);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  auto new_route_config = default_route_config_;
+  auto* route = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  auto* hash_policy = route->mutable_route()->add_hash_policy();
+  hash_policy->mutable_header()->set_header_name("address_hash");
+  SetListenerAndRouteConfiguration(0, default_listener_, new_route_config);
+  std::vector<EdsResourceArgs::Endpoint> endpoints;
+  endpoints.emplace_back(grpc_pick_unused_port_or_die());
+  endpoints.emplace_back(backends_[1]->port());
+  EdsResourceArgs args({
+      {"locality0", std::move(endpoints)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  SetNextResolutionForLbChannelAllBalancers();
+  std::vector<std::pair<std::string, std::string>> metadata = {
+      {"address_hash", CreateMetadataValueThatHashesToBackend(0)}};
+  EXPECT_EQ(GRPC_CHANNEL_IDLE, channel_->GetState(false));
+  ShutdownBackend(1);
+  CheckRpcSendFailure(CheckRpcSendFailureOptions().set_rpc_options(
+      RpcOptions().set_metadata(std::move(metadata))));
+  StartBackend(1);
+  // Ensure we are actively connecting without any traffic.
+  EXPECT_TRUE(channel_->WaitForConnected(
+      grpc_timeout_milliseconds_to_deadline(kConnectionTimeoutMilliseconds)));
+}
+
+// Test that when all backends are down and then up, we may pick a TF backend
+// and we will then jump to ready backend.
+TEST_P(CdsTest, RingHashTransientFailureSkipToAvailableReady) {
+  const uint32_t kConnectionTimeoutMilliseconds = 5000;
+  auto cluster = default_cluster_;
+  cluster.set_lb_policy(Cluster::RING_HASH);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  auto new_route_config = default_route_config_;
+  auto* route = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  auto* hash_policy = route->mutable_route()->add_hash_policy();
+  hash_policy->mutable_header()->set_header_name("address_hash");
+  SetListenerAndRouteConfiguration(0, default_listener_, new_route_config);
+  std::vector<EdsResourceArgs::Endpoint> endpoints;
+  // Make sure we include some unused ports to fill the ring.
+  endpoints.emplace_back(backends_[0]->port());
+  endpoints.emplace_back(backends_[1]->port());
+  endpoints.emplace_back(grpc_pick_unused_port_or_die());
+  endpoints.emplace_back(grpc_pick_unused_port_or_die());
+  EdsResourceArgs args({
+      {"locality0", std::move(endpoints)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  SetNextResolutionForLbChannelAllBalancers();
+  std::vector<std::pair<std::string, std::string>> metadata = {
+      {"address_hash", CreateMetadataValueThatHashesToBackend(0)}};
+  const auto rpc_options = RpcOptions().set_metadata(std::move(metadata));
+  EXPECT_EQ(GRPC_CHANNEL_IDLE, channel_->GetState(false));
+  ShutdownBackend(0);
+  ShutdownBackend(1);
+  CheckRpcSendFailure(
+      CheckRpcSendFailureOptions().set_rpc_options(rpc_options));
+  EXPECT_EQ(GRPC_CHANNEL_TRANSIENT_FAILURE, channel_->GetState(false));
+  // Bring up 0, should be picked as the RPC is hashed to it.
+  StartBackend(0);
+  EXPECT_TRUE(channel_->WaitForConnected(
+      grpc_timeout_milliseconds_to_deadline(kConnectionTimeoutMilliseconds)));
+  WaitForBackend(0, WaitForBackendOptions(), rpc_options);
+  // Bring down 0 and bring up 1.
+  // Note the RPC contains a header value that will always be hashed to
+  // backend 0. So by purposely bring down backend 0 and bring up another
+  // backend, this will ensure Picker's first choice of backend 0 will fail
+  // and it will
+  // 1. reattempt backend 0 and
+  // 2. go through the remaining subchannels to find one in READY.
+  // Since the the entries in the ring is pretty distributed and we have
+  // unused ports to fill the ring, it is almost guaranteed that the Picker
+  // will go through some non-READY entries and skip them as per design.
+  ShutdownBackend(0);
+  CheckRpcSendFailure(
+      CheckRpcSendFailureOptions().set_rpc_options(rpc_options));
+  StartBackend(1);
+  EXPECT_TRUE(channel_->WaitForConnected(
+      grpc_timeout_milliseconds_to_deadline(kConnectionTimeoutMilliseconds)));
+  WaitForBackend(1, WaitForBackendOptions(), rpc_options);
+}
+
+// Test unspported hash policy types are all ignored before a supported
+// policy.
+TEST_P(CdsTest, RingHashUnsupportedHashPolicyUntilChannelIdHashing) {
+  auto cluster = default_cluster_;
+  cluster.set_lb_policy(Cluster::RING_HASH);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  auto new_route_config = default_route_config_;
+  auto* route = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  auto* hash_policy_unsupported_1 = route->mutable_route()->add_hash_policy();
+  hash_policy_unsupported_1->mutable_cookie()->set_name("cookie");
+  auto* hash_policy_unsupported_2 = route->mutable_route()->add_hash_policy();
+  hash_policy_unsupported_2->mutable_connection_properties()->set_source_ip(
+      true);
+  auto* hash_policy_unsupported_3 = route->mutable_route()->add_hash_policy();
+  hash_policy_unsupported_3->mutable_query_parameter()->set_name(
+      "query_parameter");
+  auto* hash_policy = route->mutable_route()->add_hash_policy();
+  hash_policy->mutable_filter_state()->set_key("io.grpc.channel_id");
+  SetListenerAndRouteConfiguration(0, default_listener_, new_route_config);
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  SetNextResolutionForLbChannelAllBalancers();
+  CheckRpcSendOk(100);
+  bool found = false;
+  for (size_t i = 0; i < backends_.size(); ++i) {
+    if (backends_[i]->backend_service()->request_count() > 0) {
+      EXPECT_EQ(backends_[i]->backend_service()->request_count(), 100)
+          << "backend " << i;
+      EXPECT_FALSE(found) << "backend " << i;
+      found = true;
+    }
+  }
+  EXPECT_TRUE(found);
+}
+
+// Test we nack when ring hash policy has invalid hash function (something
+// other than XX_HASH.
+TEST_P(CdsTest, RingHashPolicyHasInvalidHashFunction) {
+  auto cluster = default_cluster_;
+  cluster.set_lb_policy(Cluster::RING_HASH);
+  cluster.mutable_ring_hash_lb_config()->set_hash_function(
+      Cluster::RingHashLbConfig::MURMUR_HASH_2);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  auto new_route_config = default_route_config_;
+  auto* route = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  auto* hash_policy = route->mutable_route()->add_hash_policy();
+  hash_policy->mutable_filter_state()->set_key("io.grpc.channel_id");
+  SetListenerAndRouteConfiguration(0, default_listener_, new_route_config);
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->cds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(
+      response_state.error_message,
+      ::testing::HasSubstr("ring hash lb config has invalid hash function."));
+}
+
+// Test we nack when ring hash policy has invalid ring size.
+TEST_P(CdsTest, RingHashPolicyHasInvalidMinimumRingSize) {
+  auto cluster = default_cluster_;
+  cluster.set_lb_policy(Cluster::RING_HASH);
+  cluster.mutable_ring_hash_lb_config()->mutable_minimum_ring_size()->set_value(
+      0);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  auto new_route_config = default_route_config_;
+  auto* route = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  auto* hash_policy = route->mutable_route()->add_hash_policy();
+  hash_policy->mutable_filter_state()->set_key("io.grpc.channel_id");
+  SetListenerAndRouteConfiguration(0, default_listener_, new_route_config);
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->cds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr(
+                  "min_ring_size is not in the range of 1 to 8388608."));
+}
+
+// Test we nack when ring hash policy has invalid ring size.
+TEST_P(CdsTest, RingHashPolicyHasInvalidMaxmumRingSize) {
+  auto cluster = default_cluster_;
+  cluster.set_lb_policy(Cluster::RING_HASH);
+  cluster.mutable_ring_hash_lb_config()->mutable_maximum_ring_size()->set_value(
+      8388609);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  auto new_route_config = default_route_config_;
+  auto* route = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  auto* hash_policy = route->mutable_route()->add_hash_policy();
+  hash_policy->mutable_filter_state()->set_key("io.grpc.channel_id");
+  SetListenerAndRouteConfiguration(0, default_listener_, new_route_config);
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->cds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr(
+                  "max_ring_size is not in the range of 1 to 8388608."));
+}
+
+// Test we nack when ring hash policy has invalid ring size.
+TEST_P(CdsTest, RingHashPolicyHasInvalidRingSizeMinGreaterThanMax) {
+  auto cluster = default_cluster_;
+  cluster.set_lb_policy(Cluster::RING_HASH);
+  cluster.mutable_ring_hash_lb_config()->mutable_maximum_ring_size()->set_value(
+      5000);
+  cluster.mutable_ring_hash_lb_config()->mutable_minimum_ring_size()->set_value(
+      5001);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  auto new_route_config = default_route_config_;
+  auto* route = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  auto* hash_policy = route->mutable_route()->add_hash_policy();
+  hash_policy->mutable_filter_state()->set_key("io.grpc.channel_id");
+  SetListenerAndRouteConfiguration(0, default_listener_, new_route_config);
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  SetNextResolutionForLbChannelAllBalancers();
+  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->cds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr(
+                  "min_ring_size cannot be greater than max_ring_size."));
+}
+
+class XdsSecurityTest : public BasicTest {
+ protected:
+  void SetUp() override {
+    BasicTest::SetUp();
+    root_cert_ = ReadFile(kCaCertPath);
+    bad_root_cert_ = ReadFile(kBadClientCertPath);
+    identity_pair_ = ReadTlsIdentityPair(kClientKeyPath, kClientCertPath);
+    // TODO(yashykt): Use different client certs here instead of reusing
+    // server certs after https://github.com/grpc/grpc/pull/24876 is merged
+    fallback_identity_pair_ =
+        ReadTlsIdentityPair(kServerKeyPath, kServerCertPath);
+    bad_identity_pair_ =
+        ReadTlsIdentityPair(kBadClientKeyPath, kBadClientCertPath);
+    server_san_exact_.set_exact("*.test.google.fr");
+    server_san_prefix_.set_prefix("waterzooi.test.google");
+    server_san_suffix_.set_suffix("google.fr");
+    server_san_contains_.set_contains("google");
+    server_san_regex_.mutable_safe_regex()->mutable_google_re2();
+    server_san_regex_.mutable_safe_regex()->set_regex(
+        "(foo|waterzooi).test.google.(fr|be)");
+    bad_san_1_.set_exact("192.168.1.4");
+    bad_san_2_.set_exact("foo.test.google.in");
+    authenticated_identity_ = {"testclient"};
+    fallback_authenticated_identity_ = {"*.test.google.fr",
+                                        "waterzooi.test.google.be",
+                                        "*.test.youtube.com", "192.168.1.3"};
+    EdsResourceArgs args({
+        {"locality0", CreateEndpointsForBackends(0, 1)},
+    });
+    balancers_[0]->ads_service()->SetEdsResource(
+        BuildEdsResource(args, DefaultEdsServiceName()));
+    SetNextResolutionForLbChannelAllBalancers();
+  }
+
+  void TearDown() override {
+    g_fake1_cert_data_map = nullptr;
+    g_fake2_cert_data_map = nullptr;
+    BasicTest::TearDown();
+  }
+
+  // Sends CDS updates with the new security configuration and verifies that
+  // after propagation, this new configuration is used for connections. If \a
+  // identity_instance_name and \a root_instance_name are both empty,
+  // connections are expected to use fallback credentials.
+  void UpdateAndVerifyXdsSecurityConfiguration(
+      absl::string_view root_instance_name,
+      absl::string_view root_certificate_name,
+      absl::string_view identity_instance_name,
+      absl::string_view identity_certificate_name,
+      const std::vector<StringMatcher>& san_matchers,
+      const std::vector<std::string>& expected_authenticated_identity,
+      bool test_expects_failure = false) {
+    auto cluster = default_cluster_;
+    if (!identity_instance_name.empty() || !root_instance_name.empty()) {
+      auto* transport_socket = cluster.mutable_transport_socket();
+      transport_socket->set_name("envoy.transport_sockets.tls");
+      UpstreamTlsContext upstream_tls_context;
+      if (!identity_instance_name.empty()) {
+        upstream_tls_context.mutable_common_tls_context()
+            ->mutable_tls_certificate_provider_instance()
+            ->set_instance_name(std::string(identity_instance_name));
+        upstream_tls_context.mutable_common_tls_context()
+            ->mutable_tls_certificate_provider_instance()
+            ->set_certificate_name(std::string(identity_certificate_name));
+      }
+      if (!root_instance_name.empty()) {
+        upstream_tls_context.mutable_common_tls_context()
+            ->mutable_validation_context()
+            ->mutable_ca_certificate_provider_instance()
+            ->set_instance_name(std::string(root_instance_name));
+        upstream_tls_context.mutable_common_tls_context()
+            ->mutable_validation_context()
+            ->mutable_ca_certificate_provider_instance()
+            ->set_certificate_name(std::string(root_certificate_name));
+      }
+      if (!san_matchers.empty()) {
+        auto* validation_context =
+            upstream_tls_context.mutable_common_tls_context()
+                ->mutable_validation_context();
+        for (const auto& san_matcher : san_matchers) {
+          *validation_context->add_match_subject_alt_names() = san_matcher;
+        }
+      }
+      transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context);
+    }
+    balancers_[0]->ads_service()->SetCdsResource(cluster);
+    // The updates might take time to have an effect, so use a retry loop.
+    constexpr int kRetryCount = 100;
+    int num_tries = 0;
+    for (; num_tries < kRetryCount; num_tries++) {
+      // Give some time for the updates to propagate.
+      gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(100));
+      if (test_expects_failure) {
+        // Restart the servers to force a reconnection so that previously
+        // connected subchannels are not used for the RPC.
+        ShutdownBackend(0);
+        StartBackend(0);
+        if (SendRpc().ok()) {
+          gpr_log(GPR_ERROR, "RPC succeeded. Failure expected. Trying again.");
+          continue;
+        }
+      } else {
+        WaitForBackend(0, WaitForBackendOptions().set_allow_failures(true));
+        Status status = SendRpc();
+        if (!status.ok()) {
+          gpr_log(GPR_ERROR, "RPC failed. code=%d message=%s Trying again.",
+                  status.error_code(), status.error_message().c_str());
+          continue;
+        }
+        if (backends_[0]->backend_service()->last_peer_identity() !=
+            expected_authenticated_identity) {
+          gpr_log(
+              GPR_ERROR,
+              "Expected client identity does not match. (actual) %s vs "
+              "(expected) %s Trying again.",
+              absl::StrJoin(
+                  backends_[0]->backend_service()->last_peer_identity(), ",")
+                  .c_str(),
+              absl::StrJoin(expected_authenticated_identity, ",").c_str());
+          continue;
+        }
+      }
+      break;
+    }
+    EXPECT_LT(num_tries, kRetryCount);
+  }
+
+  std::string root_cert_;
+  std::string bad_root_cert_;
+  grpc_core::PemKeyCertPairList identity_pair_;
+  grpc_core::PemKeyCertPairList fallback_identity_pair_;
+  grpc_core::PemKeyCertPairList bad_identity_pair_;
+  StringMatcher server_san_exact_;
+  StringMatcher server_san_prefix_;
+  StringMatcher server_san_suffix_;
+  StringMatcher server_san_contains_;
+  StringMatcher server_san_regex_;
+  StringMatcher bad_san_1_;
+  StringMatcher bad_san_2_;
+  std::vector<std::string> authenticated_identity_;
+  std::vector<std::string> fallback_authenticated_identity_;
+};
+
+TEST_P(XdsSecurityTest, UnknownTransportSocket) {
+  auto cluster = default_cluster_;
+  auto* transport_socket = cluster.mutable_transport_socket();
+  transport_socket->set_name("unknown_transport_socket");
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->cds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr(
+                  "Unrecognized transport socket: unknown_transport_socket"));
+}
+
+TEST_P(XdsSecurityTest,
+       TLSConfigurationWithoutValidationContextCertificateProviderInstance) {
+  auto cluster = default_cluster_;
+  auto* transport_socket = cluster.mutable_transport_socket();
+  transport_socket->set_name("envoy.transport_sockets.tls");
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->cds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr("TLS configuration provided but no "
+                                   "ca_certificate_provider_instance found."));
+}
+
+TEST_P(
+    XdsSecurityTest,
+    MatchSubjectAltNamesProvidedWithoutValidationContextCertificateProviderInstance) {
+  auto cluster = default_cluster_;
+  auto* transport_socket = cluster.mutable_transport_socket();
+  transport_socket->set_name("envoy.transport_sockets.tls");
+  UpstreamTlsContext upstream_tls_context;
+  auto* validation_context = upstream_tls_context.mutable_common_tls_context()
+                                 ->mutable_validation_context();
+  *validation_context->add_match_subject_alt_names() = server_san_exact_;
+  transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->cds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr("TLS configuration provided but no "
+                                   "ca_certificate_provider_instance found."));
+}
+
+TEST_P(
+    XdsSecurityTest,
+    TlsCertificateProviderInstanceWithoutValidationContextCertificateProviderInstance) {
+  auto cluster = default_cluster_;
+  auto* transport_socket = cluster.mutable_transport_socket();
+  transport_socket->set_name("envoy.transport_sockets.tls");
+  UpstreamTlsContext upstream_tls_context;
+  upstream_tls_context.mutable_common_tls_context()
+      ->mutable_tls_certificate_provider_instance()
+      ->set_instance_name(std::string("fake_plugin1"));
+  transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->cds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr("TLS configuration provided but no "
+                                   "ca_certificate_provider_instance found."));
+}
+
+TEST_P(XdsSecurityTest, RegexSanMatcherDoesNotAllowIgnoreCase) {
+  auto cluster = default_cluster_;
+  auto* transport_socket = cluster.mutable_transport_socket();
+  transport_socket->set_name("envoy.transport_sockets.tls");
+  UpstreamTlsContext upstream_tls_context;
+  upstream_tls_context.mutable_common_tls_context()
+      ->mutable_validation_context()
+      ->mutable_ca_certificate_provider_instance()
+      ->set_instance_name(std::string("fake_plugin1"));
+  auto* validation_context = upstream_tls_context.mutable_common_tls_context()
+                                 ->mutable_validation_context();
+  StringMatcher matcher;
+  matcher.mutable_safe_regex()->mutable_google_re2();
+  matcher.mutable_safe_regex()->set_regex(
+      "(foo|waterzooi).test.google.(fr|be)");
+  matcher.set_ignore_case(true);
+  *validation_context->add_match_subject_alt_names() = matcher;
+  transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->cds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr(
+                  "StringMatcher: ignore_case has no effect for SAFE_REGEX."));
+}
+
+TEST_P(XdsSecurityTest, UnknownRootCertificateProvider) {
+  auto cluster = default_cluster_;
+  auto* transport_socket = cluster.mutable_transport_socket();
+  transport_socket->set_name("envoy.transport_sockets.tls");
+  UpstreamTlsContext upstream_tls_context;
+  upstream_tls_context.mutable_common_tls_context()
+      ->mutable_validation_context()
+      ->mutable_ca_certificate_provider_instance()
+      ->set_instance_name("unknown");
+  transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->cds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr(
+                  "Unrecognized certificate provider instance name: unknown"));
+}
+
+TEST_P(XdsSecurityTest, UnknownIdentityCertificateProvider) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  auto cluster = default_cluster_;
+  auto* transport_socket = cluster.mutable_transport_socket();
+  transport_socket->set_name("envoy.transport_sockets.tls");
+  UpstreamTlsContext upstream_tls_context;
+  upstream_tls_context.mutable_common_tls_context()
+      ->mutable_tls_certificate_provider_instance()
+      ->set_instance_name("unknown");
+  upstream_tls_context.mutable_common_tls_context()
+      ->mutable_validation_context()
+      ->mutable_ca_certificate_provider_instance()
+      ->set_instance_name("fake_plugin1");
+  transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->cds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr(
+                  "Unrecognized certificate provider instance name: unknown"));
+  g_fake1_cert_data_map = nullptr;
+}
+
+TEST_P(XdsSecurityTest,
+       NacksCertificateValidationContextWithVerifyCertificateSpki) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  auto cluster = default_cluster_;
+  auto* transport_socket = cluster.mutable_transport_socket();
+  transport_socket->set_name("envoy.transport_sockets.tls");
+  UpstreamTlsContext upstream_tls_context;
+  upstream_tls_context.mutable_common_tls_context()
+      ->mutable_validation_context()
+      ->mutable_ca_certificate_provider_instance()
+      ->set_instance_name("fake_plugin1");
+  upstream_tls_context.mutable_common_tls_context()
+      ->mutable_validation_context()
+      ->add_verify_certificate_spki("spki");
+  transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->cds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(
+      response_state.error_message,
+      ::testing::HasSubstr(
+          "CertificateValidationContext: verify_certificate_spki unsupported"));
+}
+
+TEST_P(XdsSecurityTest,
+       NacksCertificateValidationContextWithVerifyCertificateHash) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  auto cluster = default_cluster_;
+  auto* transport_socket = cluster.mutable_transport_socket();
+  transport_socket->set_name("envoy.transport_sockets.tls");
+  UpstreamTlsContext upstream_tls_context;
+  upstream_tls_context.mutable_common_tls_context()
+      ->mutable_validation_context()
+      ->mutable_ca_certificate_provider_instance()
+      ->set_instance_name("fake_plugin1");
+  upstream_tls_context.mutable_common_tls_context()
+      ->mutable_validation_context()
+      ->add_verify_certificate_hash("hash");
+  transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->cds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(
+      response_state.error_message,
+      ::testing::HasSubstr(
+          "CertificateValidationContext: verify_certificate_hash unsupported"));
+}
+
+TEST_P(XdsSecurityTest,
+       NacksCertificateValidationContextWithRequireSignedCertificateTimes) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  auto cluster = default_cluster_;
+  auto* transport_socket = cluster.mutable_transport_socket();
+  transport_socket->set_name("envoy.transport_sockets.tls");
+  UpstreamTlsContext upstream_tls_context;
+  upstream_tls_context.mutable_common_tls_context()
+      ->mutable_validation_context()
+      ->mutable_ca_certificate_provider_instance()
+      ->set_instance_name("fake_plugin1");
+  upstream_tls_context.mutable_common_tls_context()
+      ->mutable_validation_context()
+      ->mutable_require_signed_certificate_timestamp()
+      ->set_value(true);
+  transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->cds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(
+      response_state.error_message,
+      ::testing::HasSubstr("CertificateValidationContext: "
+                           "require_signed_certificate_timestamp unsupported"));
+}
+
+TEST_P(XdsSecurityTest, NacksCertificateValidationContextWithCrl) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  auto cluster = default_cluster_;
+  auto* transport_socket = cluster.mutable_transport_socket();
+  transport_socket->set_name("envoy.transport_sockets.tls");
+  UpstreamTlsContext upstream_tls_context;
+  upstream_tls_context.mutable_common_tls_context()
+      ->mutable_validation_context()
+      ->mutable_ca_certificate_provider_instance()
+      ->set_instance_name("fake_plugin1");
+  upstream_tls_context.mutable_common_tls_context()
+      ->mutable_validation_context()
+      ->mutable_crl();
+  transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->cds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(
+      response_state.error_message,
+      ::testing::HasSubstr("CertificateValidationContext: crl unsupported"));
+}
+
+TEST_P(XdsSecurityTest,
+       NacksCertificateValidationContextWithCustomValidatorConfig) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  auto cluster = default_cluster_;
+  auto* transport_socket = cluster.mutable_transport_socket();
+  transport_socket->set_name("envoy.transport_sockets.tls");
+  UpstreamTlsContext upstream_tls_context;
+  upstream_tls_context.mutable_common_tls_context()
+      ->mutable_validation_context()
+      ->mutable_ca_certificate_provider_instance()
+      ->set_instance_name("fake_plugin1");
+  upstream_tls_context.mutable_common_tls_context()
+      ->mutable_validation_context()
+      ->mutable_custom_validator_config();
+  transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->cds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(
+      response_state.error_message,
+      ::testing::HasSubstr(
+          "CertificateValidationContext: custom_validator_config unsupported"));
+}
+
+TEST_P(XdsSecurityTest, NacksValidationContextSdsSecretConfig) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  auto cluster = default_cluster_;
+  auto* transport_socket = cluster.mutable_transport_socket();
+  transport_socket->set_name("envoy.transport_sockets.tls");
+  UpstreamTlsContext upstream_tls_context;
+  upstream_tls_context.mutable_common_tls_context()
+      ->mutable_validation_context_sds_secret_config();
+  transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->cds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(
+      response_state.error_message,
+      ::testing::HasSubstr("validation_context_sds_secret_config unsupported"));
+}
+
+TEST_P(XdsSecurityTest, NacksTlsParams) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  auto cluster = default_cluster_;
+  auto* transport_socket = cluster.mutable_transport_socket();
+  transport_socket->set_name("envoy.transport_sockets.tls");
+  UpstreamTlsContext upstream_tls_context;
+  upstream_tls_context.mutable_common_tls_context()
+      ->mutable_validation_context()
+      ->mutable_ca_certificate_provider_instance()
+      ->set_instance_name("fake_plugin1");
+  upstream_tls_context.mutable_common_tls_context()->mutable_tls_params();
+  transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->cds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr("tls_params unsupported"));
+}
+
+TEST_P(XdsSecurityTest, NacksCustomHandshaker) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  auto cluster = default_cluster_;
+  auto* transport_socket = cluster.mutable_transport_socket();
+  transport_socket->set_name("envoy.transport_sockets.tls");
+  UpstreamTlsContext upstream_tls_context;
+  upstream_tls_context.mutable_common_tls_context()
+      ->mutable_validation_context()
+      ->mutable_ca_certificate_provider_instance()
+      ->set_instance_name("fake_plugin1");
+  upstream_tls_context.mutable_common_tls_context()
+      ->mutable_custom_handshaker();
+  transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->cds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr("custom_handshaker unsupported"));
+}
+
+TEST_P(XdsSecurityTest, NacksTlsCertificates) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  auto cluster = default_cluster_;
+  auto* transport_socket = cluster.mutable_transport_socket();
+  transport_socket->set_name("envoy.transport_sockets.tls");
+  UpstreamTlsContext upstream_tls_context;
+  upstream_tls_context.mutable_common_tls_context()
+      ->mutable_validation_context()
+      ->mutable_ca_certificate_provider_instance()
+      ->set_instance_name("fake_plugin1");
+  upstream_tls_context.mutable_common_tls_context()->add_tls_certificates();
+  transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->cds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr("tls_certificates unsupported"));
+}
+
+TEST_P(XdsSecurityTest, NacksTlsCertificateSdsSecretConfigs) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  auto cluster = default_cluster_;
+  auto* transport_socket = cluster.mutable_transport_socket();
+  transport_socket->set_name("envoy.transport_sockets.tls");
+  UpstreamTlsContext upstream_tls_context;
+  upstream_tls_context.mutable_common_tls_context()
+      ->mutable_validation_context()
+      ->mutable_ca_certificate_provider_instance()
+      ->set_instance_name("fake_plugin1");
+  upstream_tls_context.mutable_common_tls_context()
+      ->add_tls_certificate_sds_secret_configs();
+  transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->cds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(
+      response_state.error_message,
+      ::testing::HasSubstr("tls_certificate_sds_secret_configs unsupported"));
+}
+
+TEST_P(XdsSecurityTest, TestTlsConfigurationInCombinedValidationContext) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  auto cluster = default_cluster_;
+  auto* transport_socket = cluster.mutable_transport_socket();
+  transport_socket->set_name("envoy.transport_sockets.tls");
+  UpstreamTlsContext upstream_tls_context;
+  upstream_tls_context.mutable_common_tls_context()
+      ->mutable_combined_validation_context()
+      ->mutable_default_validation_context()
+      ->mutable_ca_certificate_provider_instance()
+      ->set_instance_name("fake_plugin1");
+  transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  WaitForBackend(0, WaitForBackendOptions().set_allow_failures(true));
+  Status status = SendRpc();
+  EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
+                           << " message=" << status.error_message();
+}
+
+// TODO(yashykt): Remove this test once we stop supporting old fields
+TEST_P(XdsSecurityTest,
+       TestTlsConfigurationInValidationContextCertificateProviderInstance) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  auto cluster = default_cluster_;
+  auto* transport_socket = cluster.mutable_transport_socket();
+  transport_socket->set_name("envoy.transport_sockets.tls");
+  UpstreamTlsContext upstream_tls_context;
+  upstream_tls_context.mutable_common_tls_context()
+      ->mutable_combined_validation_context()
+      ->mutable_validation_context_certificate_provider_instance()
+      ->set_instance_name("fake_plugin1");
+  transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  WaitForBackend(0, WaitForBackendOptions().set_allow_failures(true));
+  Status status = SendRpc();
+  EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
+                           << " message=" << status.error_message();
+}
+
+TEST_P(XdsSecurityTest, TestMtlsConfigurationWithNoSanMatchers) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "fake_plugin1",
+                                          "", {}, authenticated_identity_);
+  g_fake1_cert_data_map = nullptr;
+}
+
+TEST_P(XdsSecurityTest, TestMtlsConfigurationWithExactSanMatcher) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "fake_plugin1",
+                                          "", {server_san_exact_},
+                                          authenticated_identity_);
+  g_fake1_cert_data_map = nullptr;
+}
+
+TEST_P(XdsSecurityTest, TestMtlsConfigurationWithPrefixSanMatcher) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "fake_plugin1",
+                                          "", {server_san_prefix_},
+                                          authenticated_identity_);
+  g_fake1_cert_data_map = nullptr;
+}
+
+TEST_P(XdsSecurityTest, TestMtlsConfigurationWithSuffixSanMatcher) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "fake_plugin1",
+                                          "", {server_san_suffix_},
+                                          authenticated_identity_);
+  g_fake1_cert_data_map = nullptr;
+}
+
+TEST_P(XdsSecurityTest, TestMtlsConfigurationWithContainsSanMatcher) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "fake_plugin1",
+                                          "", {server_san_contains_},
+                                          authenticated_identity_);
+  g_fake1_cert_data_map = nullptr;
+}
+
+TEST_P(XdsSecurityTest, TestMtlsConfigurationWithRegexSanMatcher) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "fake_plugin1",
+                                          "", {server_san_regex_},
+                                          authenticated_identity_);
+  g_fake1_cert_data_map = nullptr;
+}
+
+TEST_P(XdsSecurityTest, TestMtlsConfigurationWithSanMatchersUpdate) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  UpdateAndVerifyXdsSecurityConfiguration(
+      "fake_plugin1", "", "fake_plugin1", "",
+      {server_san_exact_, server_san_prefix_}, authenticated_identity_);
+  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "fake_plugin1",
+                                          "", {bad_san_1_, bad_san_2_}, {},
+                                          true /* failure */);
+  UpdateAndVerifyXdsSecurityConfiguration(
+      "fake_plugin1", "", "fake_plugin1", "",
+      {server_san_prefix_, server_san_regex_}, authenticated_identity_);
+  g_fake1_cert_data_map = nullptr;
+}
+
+TEST_P(XdsSecurityTest, TestMtlsConfigurationWithRootPluginUpdate) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  FakeCertificateProvider::CertDataMap fake2_cert_map = {
+      {"", {bad_root_cert_, bad_identity_pair_}}};
+  g_fake2_cert_data_map = &fake2_cert_map;
+  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "fake_plugin1",
+                                          "", {server_san_exact_},
+                                          authenticated_identity_);
+  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin2" /* bad root */, "",
+                                          "fake_plugin1", "", {}, {},
+                                          true /* failure */);
+  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "fake_plugin1",
+                                          "", {server_san_exact_},
+                                          authenticated_identity_);
+  g_fake1_cert_data_map = nullptr;
+  g_fake2_cert_data_map = nullptr;
+}
+
+TEST_P(XdsSecurityTest, TestMtlsConfigurationWithIdentityPluginUpdate) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  FakeCertificateProvider::CertDataMap fake2_cert_map = {
+      {"", {root_cert_, fallback_identity_pair_}}};
+  g_fake2_cert_data_map = &fake2_cert_map;
+  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "fake_plugin1",
+                                          "", {server_san_exact_},
+                                          authenticated_identity_);
+  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "fake_plugin2",
+                                          "", {server_san_exact_},
+                                          fallback_authenticated_identity_);
+  g_fake1_cert_data_map = nullptr;
+  g_fake2_cert_data_map = nullptr;
+}
+
+TEST_P(XdsSecurityTest, TestMtlsConfigurationWithBothPluginsUpdated) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  FakeCertificateProvider::CertDataMap fake2_cert_map = {
+      {"", {bad_root_cert_, bad_identity_pair_}},
+      {"good", {root_cert_, fallback_identity_pair_}}};
+  g_fake2_cert_data_map = &fake2_cert_map;
+  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin2", "", "fake_plugin2",
+                                          "", {}, {}, true /* failure */);
+  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "fake_plugin1",
+                                          "", {server_san_prefix_},
+                                          authenticated_identity_);
+  UpdateAndVerifyXdsSecurityConfiguration(
+      "fake_plugin2", "good", "fake_plugin2", "good", {server_san_prefix_},
+      fallback_authenticated_identity_);
+  g_fake1_cert_data_map = nullptr;
+  g_fake2_cert_data_map = nullptr;
+}
+
+TEST_P(XdsSecurityTest, TestMtlsConfigurationWithRootCertificateNameUpdate) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}},
+      {"bad", {bad_root_cert_, bad_identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "fake_plugin1",
+                                          "", {server_san_regex_},
+                                          authenticated_identity_);
+  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "bad", "fake_plugin1",
+                                          "", {server_san_regex_}, {},
+                                          true /* failure */);
+  g_fake1_cert_data_map = nullptr;
+}
+
+TEST_P(XdsSecurityTest,
+       TestMtlsConfigurationWithIdentityCertificateNameUpdate) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}},
+      {"bad", {bad_root_cert_, bad_identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "fake_plugin1",
+                                          "", {server_san_exact_},
+                                          authenticated_identity_);
+  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "fake_plugin1",
+                                          "bad", {server_san_exact_}, {},
+                                          true /* failure */);
+  g_fake1_cert_data_map = nullptr;
+}
+
+TEST_P(XdsSecurityTest,
+       TestMtlsConfigurationWithIdentityCertificateNameUpdateGoodCerts) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}},
+      {"good", {root_cert_, fallback_identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "fake_plugin1",
+                                          "", {server_san_exact_},
+                                          authenticated_identity_);
+  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "fake_plugin1",
+                                          "good", {server_san_exact_},
+                                          fallback_authenticated_identity_);
+  g_fake1_cert_data_map = nullptr;
+}
+
+TEST_P(XdsSecurityTest, TestMtlsConfigurationWithBothCertificateNamesUpdated) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}},
+      {"bad", {bad_root_cert_, bad_identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "bad", "fake_plugin1",
+                                          "bad", {server_san_prefix_}, {},
+                                          true /* failure */);
+  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "fake_plugin1",
+                                          "", {server_san_prefix_},
+                                          authenticated_identity_);
+  g_fake1_cert_data_map = nullptr;
+}
+
+TEST_P(XdsSecurityTest, TestTlsConfigurationWithNoSanMatchers) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "", "", {},
+                                          {} /* unauthenticated */);
+  g_fake1_cert_data_map = nullptr;
+}
+
+TEST_P(XdsSecurityTest, TestTlsConfigurationWithSanMatchers) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  UpdateAndVerifyXdsSecurityConfiguration(
+      "fake_plugin1", "", "", "",
+      {server_san_exact_, server_san_prefix_, server_san_regex_},
+      {} /* unauthenticated */);
+  g_fake1_cert_data_map = nullptr;
+}
+
+TEST_P(XdsSecurityTest, TestTlsConfigurationWithSanMatchersUpdate) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  UpdateAndVerifyXdsSecurityConfiguration(
+      "fake_plugin1", "", "", "", {server_san_exact_, server_san_prefix_},
+      {} /* unauthenticated */);
+  UpdateAndVerifyXdsSecurityConfiguration(
+      "fake_plugin1", "", "", "", {bad_san_1_, bad_san_2_},
+      {} /* unauthenticated */, true /* failure */);
+  UpdateAndVerifyXdsSecurityConfiguration(
+      "fake_plugin1", "", "", "", {server_san_prefix_, server_san_regex_},
+      {} /* unauthenticated */);
+  g_fake1_cert_data_map = nullptr;
+}
+
+TEST_P(XdsSecurityTest, TestTlsConfigurationWithRootCertificateNameUpdate) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}},
+      {"bad", {bad_root_cert_, bad_identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "", "",
+                                          {server_san_exact_},
+                                          {} /* unauthenticated */);
+  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "bad", "", "",
+                                          {server_san_exact_}, {},
+                                          true /* failure */);
+  g_fake1_cert_data_map = nullptr;
+}
+
+TEST_P(XdsSecurityTest, TestTlsConfigurationWithRootPluginUpdate) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  FakeCertificateProvider::CertDataMap fake2_cert_map = {
+      {"", {bad_root_cert_, bad_identity_pair_}}};
+  g_fake2_cert_data_map = &fake2_cert_map;
+  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "", "",
+                                          {server_san_exact_},
+                                          {} /* unauthenticated */);
+  UpdateAndVerifyXdsSecurityConfiguration(
+      "fake_plugin2", "", "", "", {server_san_exact_}, {}, true /* failure */);
+  g_fake1_cert_data_map = nullptr;
+  g_fake2_cert_data_map = nullptr;
+}
+
+TEST_P(XdsSecurityTest, TestFallbackConfiguration) {
+  UpdateAndVerifyXdsSecurityConfiguration("", "", "", "", {},
+                                          fallback_authenticated_identity_);
+  g_fake1_cert_data_map = nullptr;
+}
+
+TEST_P(XdsSecurityTest, TestMtlsToTls) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "fake_plugin1",
+                                          "", {server_san_exact_},
+                                          authenticated_identity_);
+  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "", "",
+                                          {server_san_exact_},
+                                          {} /* unauthenticated */);
+  g_fake1_cert_data_map = nullptr;
+}
+
+TEST_P(XdsSecurityTest, TestMtlsToFallback) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "fake_plugin1",
+                                          "", {server_san_exact_},
+                                          authenticated_identity_);
+  UpdateAndVerifyXdsSecurityConfiguration("", "", "", "", {},
+                                          fallback_authenticated_identity_);
+  g_fake1_cert_data_map = nullptr;
+}
+
+TEST_P(XdsSecurityTest, TestTlsToMtls) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "", "",
+                                          {server_san_exact_},
+                                          {} /* unauthenticated */);
+  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "fake_plugin1",
+                                          "", {server_san_exact_},
+                                          authenticated_identity_);
+  g_fake1_cert_data_map = nullptr;
+}
+
+TEST_P(XdsSecurityTest, TestTlsToFallback) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "", "",
+                                          {server_san_exact_},
+                                          {} /* unauthenticated */);
+  UpdateAndVerifyXdsSecurityConfiguration("", "", "", "", {},
+                                          fallback_authenticated_identity_);
+  g_fake1_cert_data_map = nullptr;
+}
+
+TEST_P(XdsSecurityTest, TestFallbackToMtls) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  UpdateAndVerifyXdsSecurityConfiguration("", "", "", "", {},
+                                          fallback_authenticated_identity_);
+  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "fake_plugin1",
+                                          "", {server_san_exact_},
+                                          authenticated_identity_);
+  g_fake1_cert_data_map = nullptr;
+}
+
+TEST_P(XdsSecurityTest, TestFallbackToTls) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  UpdateAndVerifyXdsSecurityConfiguration("", "", "", "", {},
+                                          fallback_authenticated_identity_);
+  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "", "",
+                                          {server_san_exact_},
+                                          {} /* unauthenticated */);
+  g_fake1_cert_data_map = nullptr;
+}
+
+TEST_P(XdsSecurityTest, TestFileWatcherCertificateProvider) {
+  UpdateAndVerifyXdsSecurityConfiguration("file_plugin", "", "file_plugin", "",
+                                          {server_san_exact_},
+                                          authenticated_identity_);
+}
+
+class XdsEnabledServerTest : public XdsEnd2endTest {
+ protected:
+  XdsEnabledServerTest()
+      : XdsEnd2endTest(1, 1, 100, true /* use_xds_enabled_server */) {}
+
+  void SetUp() override {
+    XdsEnd2endTest::SetUp();
+    EdsResourceArgs args({
+        {"locality0", CreateEndpointsForBackends(0, 1)},
+    });
+    balancers_[0]->ads_service()->SetEdsResource(
+        BuildEdsResource(args, DefaultEdsServiceName()));
+    SetNextResolution({});
+    SetNextResolutionForLbChannelAllBalancers();
+  }
+};
+
+TEST_P(XdsEnabledServerTest, Basic) { WaitForBackend(0); }
+
+TEST_P(XdsEnabledServerTest, BadLdsUpdateNoApiListenerNorAddress) {
+  Listener listener = default_server_listener_;
+  listener.clear_address();
+  listener.set_name(
+      absl::StrCat("grpc/server?xds.resource.listening_address=",
+                   ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()));
+  balancers_[0]->ads_service()->SetLdsResource(listener);
+  ASSERT_TRUE(WaitForLdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->lds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(
+      response_state.error_message,
+      ::testing::HasSubstr("Listener has neither address nor ApiListener"));
+}
+
+TEST_P(XdsEnabledServerTest, BadLdsUpdateBothApiListenerAndAddress) {
+  Listener listener = default_server_listener_;
+  listener.mutable_api_listener();
+  SetServerListenerNameAndRouteConfiguration(0, listener, backends_[0]->port(),
+                                             default_server_route_config_);
+  ASSERT_TRUE(WaitForLdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->lds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(
+      response_state.error_message,
+      ::testing::HasSubstr("Listener has both address and ApiListener"));
+}
+
+TEST_P(XdsEnabledServerTest, UnsupportedL4Filter) {
+  Listener listener = default_server_listener_;
+  listener.mutable_default_filter_chain()->clear_filters();
+  listener.mutable_default_filter_chain()->add_filters()->mutable_typed_config()->PackFrom(default_listener_ /* any proto object other than HttpConnectionManager */);
+  balancers_[0]->ads_service()->SetLdsResource(
+      PopulateServerListenerNameAndPort(listener, backends_[0]->port()));
+  ASSERT_TRUE(WaitForLdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->lds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr("Unsupported filter type"));
+}
+
+TEST_P(XdsEnabledServerTest, NacksEmptyHttpFilterList) {
+  Listener listener = default_server_listener_;
+  HttpConnectionManager http_connection_manager =
+      ServerHcmAccessor().Unpack(listener);
+  http_connection_manager.clear_http_filters();
+  ServerHcmAccessor().Pack(http_connection_manager, &listener);
+  SetServerListenerNameAndRouteConfiguration(0, listener, backends_[0]->port(),
+                                             default_server_route_config_);
+  ASSERT_TRUE(WaitForLdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->lds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr("Expected at least one HTTP filter"));
+}
+
+TEST_P(XdsEnabledServerTest, UnsupportedHttpFilter) {
+  Listener listener = default_server_listener_;
+  HttpConnectionManager http_connection_manager =
+      ServerHcmAccessor().Unpack(listener);
+  http_connection_manager.clear_http_filters();
+  auto* http_filter = http_connection_manager.add_http_filters();
+  http_filter->set_name("grpc.testing.unsupported_http_filter");
+  http_filter->mutable_typed_config()->set_type_url(
+      "grpc.testing.unsupported_http_filter");
+  http_filter = http_connection_manager.add_http_filters();
+  http_filter->set_name("router");
+  http_filter->mutable_typed_config()->PackFrom(
+      envoy::extensions::filters::http::router::v3::Router());
+  ServerHcmAccessor().Pack(http_connection_manager, &listener);
+  SetServerListenerNameAndRouteConfiguration(0, listener, backends_[0]->port(),
+                                             default_server_route_config_);
+  ASSERT_TRUE(WaitForLdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->lds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr("no filter registered for config type "
+                                   "grpc.testing.unsupported_http_filter"));
+}
+
+TEST_P(XdsEnabledServerTest, HttpFilterNotSupportedOnServer) {
+  Listener listener = default_server_listener_;
+  HttpConnectionManager http_connection_manager =
+      ServerHcmAccessor().Unpack(listener);
+  http_connection_manager.clear_http_filters();
+  auto* http_filter = http_connection_manager.add_http_filters();
+  http_filter->set_name("grpc.testing.client_only_http_filter");
+  http_filter->mutable_typed_config()->set_type_url(
+      "grpc.testing.client_only_http_filter");
+  http_filter = http_connection_manager.add_http_filters();
+  http_filter->set_name("router");
+  http_filter->mutable_typed_config()->PackFrom(
+      envoy::extensions::filters::http::router::v3::Router());
+  ServerHcmAccessor().Pack(http_connection_manager, &listener);
+  SetServerListenerNameAndRouteConfiguration(0, listener, backends_[0]->port(),
+                                             default_server_route_config_);
+  ASSERT_TRUE(WaitForLdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->lds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(
+      response_state.error_message,
+      ::testing::HasSubstr("Filter grpc.testing.client_only_http_filter is not "
+                           "supported on servers"));
+}
+
+TEST_P(XdsEnabledServerTest,
+       HttpFilterNotSupportedOnServerIgnoredWhenOptional) {
+  Listener listener = default_server_listener_;
+  HttpConnectionManager http_connection_manager =
+      ServerHcmAccessor().Unpack(listener);
+  http_connection_manager.clear_http_filters();
+  auto* http_filter = http_connection_manager.add_http_filters();
+  http_filter->set_name("grpc.testing.client_only_http_filter");
+  http_filter->mutable_typed_config()->set_type_url(
+      "grpc.testing.client_only_http_filter");
+  http_filter->set_is_optional(true);
+  http_filter = http_connection_manager.add_http_filters();
+  http_filter->set_name("router");
+  http_filter->mutable_typed_config()->PackFrom(
+      envoy::extensions::filters::http::router::v3::Router());
+  ServerHcmAccessor().Pack(http_connection_manager, &listener);
+  SetServerListenerNameAndRouteConfiguration(0, listener, backends_[0]->port(),
+                                             default_server_route_config_);
+  WaitForBackend(0);
+  const auto response_state =
+      balancers_[0]->ads_service()->lds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::ACKED);
+}
+
+// Verify that a mismatch of listening address results in "not serving"
+// status.
+TEST_P(XdsEnabledServerTest, ListenerAddressMismatch) {
+  Listener listener = default_server_listener_;
+  // Set a different listening address in the LDS update
+  listener.mutable_address()->mutable_socket_address()->set_address(
+      "192.168.1.1");
+  SetServerListenerNameAndRouteConfiguration(0, listener, backends_[0]->port(),
+                                             default_server_route_config_);
+  backends_[0]->notifier()->WaitOnServingStatusChange(
+      absl::StrCat(ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()),
+      grpc::StatusCode::FAILED_PRECONDITION);
+}
+
+TEST_P(XdsEnabledServerTest, UseOriginalDstNotSupported) {
+  Listener listener = default_server_listener_;
+  listener.mutable_use_original_dst()->set_value(true);
+  SetServerListenerNameAndRouteConfiguration(0, listener, backends_[0]->port(),
+                                             default_server_route_config_);
+  ASSERT_TRUE(WaitForLdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->lds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(
+      response_state.error_message,
+      ::testing::HasSubstr("Field \'use_original_dst\' is not supported."));
+}
+
+class XdsServerSecurityTest : public XdsEnd2endTest {
+ protected:
+  XdsServerSecurityTest()
+      : XdsEnd2endTest(1, 1, 100, true /* use_xds_enabled_server */) {}
+
+  void SetUp() override {
+    XdsEnd2endTest::SetUp();
+    root_cert_ = ReadFile(kCaCertPath);
+    bad_root_cert_ = ReadFile(kBadClientCertPath);
+    identity_pair_ = ReadTlsIdentityPair(kServerKeyPath, kServerCertPath);
+    bad_identity_pair_ =
+        ReadTlsIdentityPair(kBadClientKeyPath, kBadClientCertPath);
+    identity_pair_2_ = ReadTlsIdentityPair(kClientKeyPath, kClientCertPath);
+    server_authenticated_identity_ = {"*.test.google.fr",
+                                      "waterzooi.test.google.be",
+                                      "*.test.youtube.com", "192.168.1.3"};
+    server_authenticated_identity_2_ = {"testclient"};
+    client_authenticated_identity_ = {"*.test.google.fr",
+                                      "waterzooi.test.google.be",
+                                      "*.test.youtube.com", "192.168.1.3"};
+    EdsResourceArgs args({
+        {"locality0", CreateEndpointsForBackends(0, 1)},
+    });
+    balancers_[0]->ads_service()->SetEdsResource(
+        BuildEdsResource(args, DefaultEdsServiceName()));
+    SetNextResolution({});
+    SetNextResolutionForLbChannelAllBalancers();
+  }
+
+  void TearDown() override {
+    g_fake1_cert_data_map = nullptr;
+    g_fake2_cert_data_map = nullptr;
+    XdsEnd2endTest::TearDown();
+  }
+
+  void SetLdsUpdate(absl::string_view root_instance_name,
+                    absl::string_view root_certificate_name,
+                    absl::string_view identity_instance_name,
+                    absl::string_view identity_certificate_name,
+                    bool require_client_certificates) {
+    Listener listener = default_server_listener_;
+    auto* filter_chain = listener.mutable_default_filter_chain();
+    if (!identity_instance_name.empty()) {
+      auto* transport_socket = filter_chain->mutable_transport_socket();
+      transport_socket->set_name("envoy.transport_sockets.tls");
+      DownstreamTlsContext downstream_tls_context;
+      downstream_tls_context.mutable_common_tls_context()
+          ->mutable_tls_certificate_provider_instance()
+          ->set_instance_name(std::string(identity_instance_name));
+      downstream_tls_context.mutable_common_tls_context()
+          ->mutable_tls_certificate_provider_instance()
+          ->set_certificate_name(std::string(identity_certificate_name));
+      if (!root_instance_name.empty()) {
+        downstream_tls_context.mutable_common_tls_context()
+            ->mutable_validation_context()
+            ->mutable_ca_certificate_provider_instance()
+            ->set_instance_name(std::string(root_instance_name));
+        downstream_tls_context.mutable_common_tls_context()
+            ->mutable_validation_context()
+            ->mutable_ca_certificate_provider_instance()
+            ->set_certificate_name(std::string(root_certificate_name));
+        downstream_tls_context.mutable_require_client_certificate()->set_value(
+            require_client_certificates);
+      }
+      transport_socket->mutable_typed_config()->PackFrom(
+          downstream_tls_context);
+    }
+    SetServerListenerNameAndRouteConfiguration(
+        0, listener, backends_[0]->port(), default_server_route_config_);
+  }
+
+  std::shared_ptr<grpc::Channel> CreateMtlsChannel() {
+    ChannelArguments args;
+    // Override target name for host name check
+    args.SetString(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG,
+                   ipv6_only_ ? "::1" : "127.0.0.1");
+    args.SetInt(GRPC_ARG_USE_LOCAL_SUBCHANNEL_POOL, 1);
+    std::string uri = absl::StrCat(
+        ipv6_only_ ? "ipv6:[::1]:" : "ipv4:127.0.0.1:", backends_[0]->port());
+    // TODO(yashykt): Switch to using C++ API once b/173823806 is fixed.
+    grpc_tls_credentials_options* options =
+        grpc_tls_credentials_options_create();
+    grpc_tls_credentials_options_set_server_verification_option(
+        options, GRPC_TLS_SKIP_HOSTNAME_VERIFICATION);
+    grpc_tls_credentials_options_set_certificate_provider(
+        options,
+        grpc_core::MakeRefCounted<grpc_core::StaticDataCertificateProvider>(
+            ReadFile(kCaCertPath),
+            ReadTlsIdentityPair(kServerKeyPath, kServerCertPath))
+            .get());
+    grpc_tls_credentials_options_watch_root_certs(options);
+    grpc_tls_credentials_options_watch_identity_key_cert_pairs(options);
+    grpc_tls_server_authorization_check_config* check_config =
+        grpc_tls_server_authorization_check_config_create(
+            nullptr, ServerAuthCheckSchedule, nullptr, nullptr);
+    grpc_tls_credentials_options_set_server_authorization_check_config(
+        options, check_config);
+    auto channel_creds = std::make_shared<SecureChannelCredentials>(
+        grpc_tls_credentials_create(options));
+    grpc_tls_server_authorization_check_config_release(check_config);
+    return CreateCustomChannel(uri, channel_creds, args);
+  }
+
+  std::shared_ptr<grpc::Channel> CreateTlsChannel() {
+    ChannelArguments args;
+    // Override target name for host name check
+    args.SetString(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG,
+                   ipv6_only_ ? "::1" : "127.0.0.1");
+    args.SetInt(GRPC_ARG_USE_LOCAL_SUBCHANNEL_POOL, 1);
+    std::string uri = absl::StrCat(
+        ipv6_only_ ? "ipv6:[::1]:" : "ipv4:127.0.0.1:", backends_[0]->port());
+    // TODO(yashykt): Switch to using C++ API once b/173823806 is fixed.
+    grpc_tls_credentials_options* options =
+        grpc_tls_credentials_options_create();
+    grpc_tls_credentials_options_set_server_verification_option(
+        options, GRPC_TLS_SKIP_HOSTNAME_VERIFICATION);
+    grpc_tls_credentials_options_set_certificate_provider(
+        options,
+        grpc_core::MakeRefCounted<grpc_core::StaticDataCertificateProvider>(
+            ReadFile(kCaCertPath),
+            ReadTlsIdentityPair(kServerKeyPath, kServerCertPath))
+            .get());
+    grpc_tls_credentials_options_watch_root_certs(options);
+    grpc_tls_server_authorization_check_config* check_config =
+        grpc_tls_server_authorization_check_config_create(
+            nullptr, ServerAuthCheckSchedule, nullptr, nullptr);
+    grpc_tls_credentials_options_set_server_authorization_check_config(
+        options, check_config);
+    auto channel_creds = std::make_shared<SecureChannelCredentials>(
+        grpc_tls_credentials_create(options));
+    grpc_tls_server_authorization_check_config_release(check_config);
+    return CreateCustomChannel(uri, channel_creds, args);
+  }
+
+  std::shared_ptr<grpc::Channel> CreateInsecureChannel() {
+    ChannelArguments args;
+    // Override target name for host name check
+    args.SetString(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG,
+                   ipv6_only_ ? "::1" : "127.0.0.1");
+    args.SetInt(GRPC_ARG_USE_LOCAL_SUBCHANNEL_POOL, 1);
+    std::string uri = absl::StrCat(
+        ipv6_only_ ? "ipv6:[::1]:" : "ipv4:127.0.0.1:", backends_[0]->port());
+    return CreateCustomChannel(uri, InsecureChannelCredentials(), args);
+  }
+
+  void SendRpc(std::function<std::shared_ptr<grpc::Channel>()> channel_creator,
+               std::vector<std::string> expected_server_identity,
+               std::vector<std::string> expected_client_identity,
+               bool test_expects_failure = false) {
+    gpr_log(GPR_INFO, "Sending RPC");
+    int num_tries = 0;
+    constexpr int kRetryCount = 100;
+    for (; num_tries < kRetryCount; num_tries++) {
+      auto channel = channel_creator();
+      auto stub = grpc::testing::EchoTestService::NewStub(channel);
+      ClientContext context;
+      context.set_wait_for_ready(true);
+      context.set_deadline(grpc_timeout_milliseconds_to_deadline(2000));
+      EchoRequest request;
+      request.set_message(kRequestMessage);
+      EchoResponse response;
+      Status status = stub->Echo(&context, request, &response);
+      if (test_expects_failure) {
+        if (status.ok()) {
+          gpr_log(GPR_ERROR, "RPC succeeded. Failure expected. Trying again.");
+          continue;
+        }
+      } else {
+        if (!status.ok()) {
+          gpr_log(GPR_ERROR, "RPC failed. code=%d message=%s Trying again.",
+                  status.error_code(), status.error_message().c_str());
+          continue;
+        }
+        EXPECT_EQ(response.message(), kRequestMessage);
+        std::vector<std::string> peer_identity;
+        for (const auto& entry : context.auth_context()->GetPeerIdentity()) {
+          peer_identity.emplace_back(
+              std::string(entry.data(), entry.size()).c_str());
+        }
+        if (peer_identity != expected_server_identity) {
+          gpr_log(GPR_ERROR,
+                  "Expected server identity does not match. (actual) %s vs "
+                  "(expected) %s Trying again.",
+                  absl::StrJoin(peer_identity, ",").c_str(),
+                  absl::StrJoin(expected_server_identity, ",").c_str());
+          continue;
+        }
+        if (backends_[0]->backend_service()->last_peer_identity() !=
+            expected_client_identity) {
+          gpr_log(
+              GPR_ERROR,
+              "Expected client identity does not match. (actual) %s vs "
+              "(expected) %s Trying again.",
+              absl::StrJoin(
+                  backends_[0]->backend_service()->last_peer_identity(), ",")
+                  .c_str(),
+              absl::StrJoin(expected_client_identity, ",").c_str());
+          continue;
+        }
+      }
+      break;
+    }
+    EXPECT_LT(num_tries, kRetryCount);
+  }
+
+  std::string root_cert_;
+  std::string bad_root_cert_;
+  grpc_core::PemKeyCertPairList identity_pair_;
+  grpc_core::PemKeyCertPairList bad_identity_pair_;
+  grpc_core::PemKeyCertPairList identity_pair_2_;
+  std::vector<std::string> server_authenticated_identity_;
+  std::vector<std::string> server_authenticated_identity_2_;
+  std::vector<std::string> client_authenticated_identity_;
+};
+
+TEST_P(XdsServerSecurityTest, UnknownTransportSocket) {
+  Listener listener = default_server_listener_;
+  auto* filter_chain = listener.mutable_default_filter_chain();
+  auto* transport_socket = filter_chain->mutable_transport_socket();
+  transport_socket->set_name("unknown_transport_socket");
+  SetServerListenerNameAndRouteConfiguration(0, listener, backends_[0]->port(),
+                                             default_server_route_config_);
+  ASSERT_TRUE(WaitForLdsNack(StatusCode::DEADLINE_EXCEEDED))
+      << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->lds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr(
+                  "Unrecognized transport socket: unknown_transport_socket"));
+}
+
+TEST_P(XdsServerSecurityTest, NacksRequireSNI) {
+  Listener listener = default_server_listener_;
+  auto* filter_chain = listener.mutable_default_filter_chain();
+  auto* transport_socket = filter_chain->mutable_transport_socket();
+  transport_socket->set_name("envoy.transport_sockets.tls");
+  DownstreamTlsContext downstream_tls_context;
+  downstream_tls_context.mutable_common_tls_context()
+      ->mutable_tls_certificate_provider_instance()
+      ->set_instance_name("fake_plugin1");
+  downstream_tls_context.mutable_require_sni()->set_value(true);
+  transport_socket->mutable_typed_config()->PackFrom(downstream_tls_context);
+  SetServerListenerNameAndRouteConfiguration(0, listener, backends_[0]->port(),
+                                             default_server_route_config_);
+  ASSERT_TRUE(WaitForLdsNack(StatusCode::DEADLINE_EXCEEDED))
+      << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->lds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr("require_sni: unsupported"));
+}
+
+TEST_P(XdsServerSecurityTest, NacksOcspStaplePolicyOtherThanLenientStapling) {
+  Listener listener = default_server_listener_;
+  auto* filter_chain = listener.mutable_default_filter_chain();
+  auto* transport_socket = filter_chain->mutable_transport_socket();
+  transport_socket->set_name("envoy.transport_sockets.tls");
+  DownstreamTlsContext downstream_tls_context;
+  downstream_tls_context.mutable_common_tls_context()
+      ->mutable_tls_certificate_provider_instance()
+      ->set_instance_name("fake_plugin1");
+  downstream_tls_context.set_ocsp_staple_policy(
+      envoy::extensions::transport_sockets::tls::v3::
+          DownstreamTlsContext_OcspStaplePolicy_STRICT_STAPLING);
+  transport_socket->mutable_typed_config()->PackFrom(downstream_tls_context);
+  SetServerListenerNameAndRouteConfiguration(0, listener, backends_[0]->port(),
+                                             default_server_route_config_);
+  ASSERT_TRUE(WaitForLdsNack(StatusCode::DEADLINE_EXCEEDED))
+      << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->lds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr(
+                  "ocsp_staple_policy: Only LENIENT_STAPLING supported"));
+}
+
+TEST_P(
+    XdsServerSecurityTest,
+    NacksRequiringClientCertificateWithoutValidationCertificateProviderInstance) {
+  Listener listener = default_server_listener_;
+  auto* filter_chain = listener.mutable_default_filter_chain();
+  auto* transport_socket = filter_chain->mutable_transport_socket();
+  transport_socket->set_name("envoy.transport_sockets.tls");
+  DownstreamTlsContext downstream_tls_context;
+  downstream_tls_context.mutable_common_tls_context()
+      ->mutable_tls_certificate_provider_instance()
+      ->set_instance_name("fake_plugin1");
+  downstream_tls_context.mutable_require_client_certificate()->set_value(true);
+  transport_socket->mutable_typed_config()->PackFrom(downstream_tls_context);
+  SetServerListenerNameAndRouteConfiguration(0, listener, backends_[0]->port(),
+                                             default_server_route_config_);
+  ASSERT_TRUE(WaitForLdsNack(StatusCode::DEADLINE_EXCEEDED))
+      << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->lds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr(
+                  "TLS configuration requires client certificates but no "
+                  "certificate provider instance specified for validation."));
+}
+
+TEST_P(XdsServerSecurityTest,
+       NacksTlsConfigurationWithoutIdentityProviderInstance) {
+  Listener listener = default_server_listener_;
+  auto* filter_chain = listener.mutable_default_filter_chain();
+  auto* transport_socket = filter_chain->mutable_transport_socket();
+  transport_socket->set_name("envoy.transport_sockets.tls");
+  DownstreamTlsContext downstream_tls_context;
+  transport_socket->mutable_typed_config()->PackFrom(downstream_tls_context);
+  SetServerListenerNameAndRouteConfiguration(0, listener, backends_[0]->port(),
+                                             default_server_route_config_);
+  ASSERT_TRUE(WaitForLdsNack(StatusCode::DEADLINE_EXCEEDED))
+      << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->lds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr("TLS configuration provided but no "
+                                   "tls_certificate_provider_instance found."));
+}
+
+TEST_P(XdsServerSecurityTest, NacksMatchSubjectAltNames) {
+  Listener listener = default_server_listener_;
+  auto* filter_chain = listener.mutable_default_filter_chain();
+  auto* transport_socket = filter_chain->mutable_transport_socket();
+  transport_socket->set_name("envoy.transport_sockets.tls");
+  DownstreamTlsContext downstream_tls_context;
+  downstream_tls_context.mutable_common_tls_context()
+      ->mutable_tls_certificate_provider_instance()
+      ->set_instance_name("fake_plugin1");
+  downstream_tls_context.mutable_common_tls_context()
+      ->mutable_validation_context()
+      ->add_match_subject_alt_names()
+      ->set_exact("*.test.google.fr");
+  transport_socket->mutable_typed_config()->PackFrom(downstream_tls_context);
+  SetServerListenerNameAndRouteConfiguration(0, listener, backends_[0]->port(),
+                                             default_server_route_config_);
+  ASSERT_TRUE(WaitForLdsNack(StatusCode::DEADLINE_EXCEEDED))
+      << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->lds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(
+      response_state.error_message,
+      ::testing::HasSubstr("match_subject_alt_names not supported on servers"));
+}
+
+TEST_P(XdsServerSecurityTest, UnknownIdentityCertificateProvider) {
+  SetLdsUpdate("", "", "unknown", "", false);
+  SendRpc([this]() { return CreateTlsChannel(); }, {}, {},
+          true /* test_expects_failure */);
+  ASSERT_TRUE(WaitForLdsNack(StatusCode::DEADLINE_EXCEEDED))
+      << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->lds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr(
+                  "Unrecognized certificate provider instance name: unknown"));
+}
+
+TEST_P(XdsServerSecurityTest, UnknownRootCertificateProvider) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  SetLdsUpdate("unknown", "", "fake_plugin1", "", false);
+  ASSERT_TRUE(WaitForLdsNack(StatusCode::DEADLINE_EXCEEDED))
+      << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->lds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr(
+                  "Unrecognized certificate provider instance name: unknown"));
+}
+
+TEST_P(XdsServerSecurityTest,
+       TestDeprecateTlsCertificateCertificateProviderInstanceField) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  Listener listener = default_server_listener_;
+  auto* filter_chain = listener.mutable_default_filter_chain();
+  filter_chain->mutable_filters()->at(0).mutable_typed_config()->PackFrom(
+      ServerHcmAccessor().Unpack(listener));
+  auto* transport_socket = filter_chain->mutable_transport_socket();
+  transport_socket->set_name("envoy.transport_sockets.tls");
+  DownstreamTlsContext downstream_tls_context;
+  downstream_tls_context.mutable_common_tls_context()
+      ->mutable_tls_certificate_certificate_provider_instance()
+      ->set_instance_name("fake_plugin1");
+  transport_socket->mutable_typed_config()->PackFrom(downstream_tls_context);
+  SetServerListenerNameAndRouteConfiguration(0, listener, backends_[0]->port(),
+                                             default_server_route_config_);
+  SendRpc([this]() { return CreateTlsChannel(); },
+          server_authenticated_identity_, {});
+}
+
+TEST_P(XdsServerSecurityTest, CertificatesNotAvailable) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map;
+  g_fake1_cert_data_map = &fake1_cert_map;
+  SetLdsUpdate("fake_plugin1", "", "fake_plugin1", "", true);
+  SendRpc([this]() { return CreateMtlsChannel(); }, {}, {},
+          true /* test_expects_failure */);
+}
+
+TEST_P(XdsServerSecurityTest, TestMtls) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  SetLdsUpdate("fake_plugin1", "", "fake_plugin1", "", true);
+  SendRpc([this]() { return CreateMtlsChannel(); },
+          server_authenticated_identity_, client_authenticated_identity_);
+}
+
+TEST_P(XdsServerSecurityTest, TestMtlsWithRootPluginUpdate) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  FakeCertificateProvider::CertDataMap fake2_cert_map = {
+      {"", {bad_root_cert_, bad_identity_pair_}}};
+  g_fake2_cert_data_map = &fake2_cert_map;
+  SetLdsUpdate("fake_plugin1", "", "fake_plugin1", "", true);
+  SendRpc([this]() { return CreateMtlsChannel(); },
+          server_authenticated_identity_, client_authenticated_identity_);
+  SetLdsUpdate("fake_plugin2", "", "fake_plugin1", "", true);
+  SendRpc([this]() { return CreateMtlsChannel(); }, {}, {},
+          true /* test_expects_failure */);
+}
+
+TEST_P(XdsServerSecurityTest, TestMtlsWithIdentityPluginUpdate) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  FakeCertificateProvider::CertDataMap fake2_cert_map = {
+      {"", {root_cert_, identity_pair_2_}}};
+  g_fake2_cert_data_map = &fake2_cert_map;
+  SetLdsUpdate("fake_plugin1", "", "fake_plugin1", "", true);
+  SendRpc([this]() { return CreateMtlsChannel(); },
+          server_authenticated_identity_, client_authenticated_identity_);
+  SetLdsUpdate("fake_plugin1", "", "fake_plugin2", "", true);
+  SendRpc([this]() { return CreateMtlsChannel(); },
+          server_authenticated_identity_2_, client_authenticated_identity_);
+}
+
+TEST_P(XdsServerSecurityTest, TestMtlsWithBothPluginsUpdated) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  FakeCertificateProvider::CertDataMap fake2_cert_map = {
+      {"good", {root_cert_, identity_pair_2_}},
+      {"", {bad_root_cert_, bad_identity_pair_}}};
+  g_fake2_cert_data_map = &fake2_cert_map;
+  SetLdsUpdate("fake_plugin2", "", "fake_plugin2", "", true);
+  SendRpc([this]() { return CreateMtlsChannel(); }, {}, {},
+          true /* test_expects_failure */);
+  SetLdsUpdate("fake_plugin1", "", "fake_plugin1", "", true);
+  SendRpc([this]() { return CreateMtlsChannel(); },
+          server_authenticated_identity_, client_authenticated_identity_);
+  SetLdsUpdate("fake_plugin2", "good", "fake_plugin2", "good", true);
+  SendRpc([this]() { return CreateMtlsChannel(); },
+          server_authenticated_identity_2_, client_authenticated_identity_);
+}
+
+TEST_P(XdsServerSecurityTest, TestMtlsWithRootCertificateNameUpdate) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}},
+      {"bad", {bad_root_cert_, bad_identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  SetLdsUpdate("fake_plugin1", "", "fake_plugin1", "", true);
+  SendRpc([this]() { return CreateMtlsChannel(); },
+          server_authenticated_identity_, client_authenticated_identity_);
+  SetLdsUpdate("fake_plugin1", "bad", "fake_plugin1", "", true);
+  SendRpc([this]() { return CreateMtlsChannel(); }, {}, {},
+          true /* test_expects_failure */);
+}
+
+TEST_P(XdsServerSecurityTest, TestMtlsWithIdentityCertificateNameUpdate) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}},
+      {"good", {root_cert_, identity_pair_2_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  SetLdsUpdate("fake_plugin1", "", "fake_plugin1", "", true);
+  SendRpc([this]() { return CreateMtlsChannel(); },
+          server_authenticated_identity_, client_authenticated_identity_);
+  SetLdsUpdate("fake_plugin1", "", "fake_plugin1", "good", true);
+  SendRpc([this]() { return CreateMtlsChannel(); },
+          server_authenticated_identity_2_, client_authenticated_identity_);
+}
+
+TEST_P(XdsServerSecurityTest, TestMtlsWithBothCertificateNamesUpdated) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}},
+      {"good", {root_cert_, identity_pair_2_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  SetLdsUpdate("fake_plugin1", "", "fake_plugin1", "", true);
+  SendRpc([this]() { return CreateMtlsChannel(); },
+          server_authenticated_identity_, client_authenticated_identity_);
+  SetLdsUpdate("fake_plugin1", "good", "fake_plugin1", "good", true);
+  SendRpc([this]() { return CreateMtlsChannel(); },
+          server_authenticated_identity_2_, client_authenticated_identity_);
+}
+
+TEST_P(XdsServerSecurityTest, TestMtlsNotRequiringButProvidingClientCerts) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  SetLdsUpdate("fake_plugin1", "", "fake_plugin1", "", false);
+  SendRpc([this]() { return CreateMtlsChannel(); },
+          server_authenticated_identity_, client_authenticated_identity_);
+}
+
+TEST_P(XdsServerSecurityTest, TestMtlsNotRequiringAndNotProvidingClientCerts) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  SetLdsUpdate("fake_plugin1", "", "fake_plugin1", "", false);
+  SendRpc([this]() { return CreateTlsChannel(); },
+          server_authenticated_identity_, {});
+}
+
+TEST_P(XdsServerSecurityTest, TestTls) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  SetLdsUpdate("", "", "fake_plugin1", "", false);
+  SendRpc([this]() { return CreateTlsChannel(); },
+          server_authenticated_identity_, {});
+}
+
+TEST_P(XdsServerSecurityTest, TestTlsWithIdentityPluginUpdate) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  FakeCertificateProvider::CertDataMap fake2_cert_map = {
+      {"", {root_cert_, identity_pair_2_}}};
+  g_fake2_cert_data_map = &fake2_cert_map;
+  SetLdsUpdate("", "", "fake_plugin1", "", false);
+  SendRpc([this]() { return CreateTlsChannel(); },
+          server_authenticated_identity_, {});
+  SetLdsUpdate("", "", "fake_plugin2", "", false);
+  SendRpc([this]() { return CreateTlsChannel(); },
+          server_authenticated_identity_2_, {});
+}
+
+TEST_P(XdsServerSecurityTest, TestTlsWithIdentityCertificateNameUpdate) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}},
+      {"good", {root_cert_, identity_pair_2_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  SetLdsUpdate("", "", "fake_plugin1", "", false);
+  SendRpc([this]() { return CreateTlsChannel(); },
+          server_authenticated_identity_, {});
+  SetLdsUpdate("", "", "fake_plugin1", "good", false);
+  SendRpc([this]() { return CreateTlsChannel(); },
+          server_authenticated_identity_2_, {});
+}
+
+TEST_P(XdsServerSecurityTest, TestFallback) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  SetLdsUpdate("", "", "", "", false);
+  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {});
+}
+
+TEST_P(XdsServerSecurityTest, TestMtlsToTls) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  SetLdsUpdate("fake_plugin1", "", "fake_plugin1", "", true);
+  SendRpc([this]() { return CreateTlsChannel(); }, {}, {},
+          true /* test_expects_failure */);
+  SetLdsUpdate("", "", "fake_plugin1", "", false);
+  SendRpc([this]() { return CreateTlsChannel(); },
+          server_authenticated_identity_, {});
+}
+
+TEST_P(XdsServerSecurityTest, TestTlsToMtls) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  SetLdsUpdate("", "", "fake_plugin1", "", false);
+  SendRpc([this]() { return CreateTlsChannel(); },
+          server_authenticated_identity_, {});
+  SetLdsUpdate("fake_plugin1", "", "fake_plugin1", "", true);
+  SendRpc([this]() { return CreateTlsChannel(); }, {}, {},
+          true /* test_expects_failure */);
+}
+
+TEST_P(XdsServerSecurityTest, TestMtlsToFallback) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  SetLdsUpdate("fake_plugin1", "", "fake_plugin1", "", false);
+  SendRpc([this]() { return CreateMtlsChannel(); },
+          server_authenticated_identity_, client_authenticated_identity_);
+  SetLdsUpdate("", "", "", "", false);
+  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {});
+}
+
+TEST_P(XdsServerSecurityTest, TestFallbackToMtls) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  SetLdsUpdate("", "", "", "", false);
+  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {});
+  SetLdsUpdate("fake_plugin1", "", "fake_plugin1", "", true);
+  SendRpc([this]() { return CreateMtlsChannel(); },
+          server_authenticated_identity_, client_authenticated_identity_);
+}
+
+TEST_P(XdsServerSecurityTest, TestTlsToFallback) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  SetLdsUpdate("", "", "fake_plugin1", "", false);
+  SendRpc([this]() { return CreateTlsChannel(); },
+          server_authenticated_identity_, {});
+  SetLdsUpdate("", "", "", "", false);
+  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {});
+}
+
+TEST_P(XdsServerSecurityTest, TestFallbackToTls) {
+  FakeCertificateProvider::CertDataMap fake1_cert_map = {
+      {"", {root_cert_, identity_pair_}}};
+  g_fake1_cert_data_map = &fake1_cert_map;
+  SetLdsUpdate("", "", "", "", false);
+  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {});
+  SetLdsUpdate("", "", "fake_plugin1", "", false);
+  SendRpc([this]() { return CreateTlsChannel(); },
+          server_authenticated_identity_, {});
+}
+
+class XdsEnabledServerStatusNotificationTest : public XdsServerSecurityTest {
+ protected:
+  void SetValidLdsUpdate() { SetLdsUpdate("", "", "", "", false); }
+
+  void SetInvalidLdsUpdate() {
+    Listener listener = default_server_listener_;
+    listener.clear_address();
+    listener.set_name(absl::StrCat(
+        "grpc/server?xds.resource.listening_address=",
+        ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()));
+    balancers_[0]->ads_service()->SetLdsResource(listener);
+  }
+
+  void UnsetLdsUpdate() {
+    balancers_[0]->ads_service()->UnsetResource(
+        kLdsTypeUrl, absl::StrCat("grpc/server?xds.resource.listening_address=",
+                                  ipv6_only_ ? "[::1]:" : "127.0.0.1:",
+                                  backends_[0]->port()));
+  }
+};
+
+TEST_P(XdsEnabledServerStatusNotificationTest, ServingStatus) {
+  SetValidLdsUpdate();
+  backends_[0]->notifier()->WaitOnServingStatusChange(
+      absl::StrCat(ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()),
+      grpc::StatusCode::OK);
+  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {});
+}
+
+TEST_P(XdsEnabledServerStatusNotificationTest, NotServingStatus) {
+  SetInvalidLdsUpdate();
+  backends_[0]->notifier()->WaitOnServingStatusChange(
+      absl::StrCat(ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()),
+      grpc::StatusCode::UNAVAILABLE);
+  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {},
+          true /* test_expects_failure */);
+}
+
+TEST_P(XdsEnabledServerStatusNotificationTest, ErrorUpdateWhenAlreadyServing) {
+  SetValidLdsUpdate();
+  backends_[0]->notifier()->WaitOnServingStatusChange(
+      absl::StrCat(ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()),
+      grpc::StatusCode::OK);
+  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {});
+  // Invalid update does not lead to a change in the serving status.
+  SetInvalidLdsUpdate();
+  do {
+    SendRpc([this]() { return CreateInsecureChannel(); }, {}, {});
+  } while (balancers_[0]->ads_service()->lds_response_state().state ==
+           AdsServiceImpl::ResponseState::SENT);
+  backends_[0]->notifier()->WaitOnServingStatusChange(
+      absl::StrCat(ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()),
+      grpc::StatusCode::OK);
+  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {});
+}
+
+TEST_P(XdsEnabledServerStatusNotificationTest,
+       NotServingStatusToServingStatusTransition) {
+  SetInvalidLdsUpdate();
+  backends_[0]->notifier()->WaitOnServingStatusChange(
+      absl::StrCat(ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()),
+      grpc::StatusCode::UNAVAILABLE);
+  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {},
+          true /* test_expects_failure */);
+  // Send a valid LDS update to change to serving status
+  SetValidLdsUpdate();
+  backends_[0]->notifier()->WaitOnServingStatusChange(
+      absl::StrCat(ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()),
+      grpc::StatusCode::OK);
+  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {});
+}
+
+// This test verifies that the resource getting deleted when already serving
+// results in future connections being dropped.
+TEST_P(XdsEnabledServerStatusNotificationTest,
+       ServingStatusToNonServingStatusTransition) {
+  SetValidLdsUpdate();
+  backends_[0]->notifier()->WaitOnServingStatusChange(
+      absl::StrCat(ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()),
+      grpc::StatusCode::OK);
+  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {});
+  // Deleting the resource should result in a non-serving status.
+  UnsetLdsUpdate();
+  backends_[0]->notifier()->WaitOnServingStatusChange(
+      absl::StrCat(ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()),
+      grpc::StatusCode::NOT_FOUND);
+  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {},
+          true /* test_expects_failure */);
+}
+
+TEST_P(XdsEnabledServerStatusNotificationTest, RepeatedServingStatusChanges) {
+  for (int i = 0; i < 5; i++) {
+    // Send a valid LDS update to get the server to start listening
+    SetValidLdsUpdate();
+    backends_[0]->notifier()->WaitOnServingStatusChange(
+        absl::StrCat(ipv6_only_ ? "[::1]:" : "127.0.0.1:",
+                     backends_[0]->port()),
+        grpc::StatusCode::OK);
+    SendRpc([this]() { return CreateInsecureChannel(); }, {}, {});
+    // Deleting the resource will make the server start rejecting connections
+    UnsetLdsUpdate();
+    backends_[0]->notifier()->WaitOnServingStatusChange(
+        absl::StrCat(ipv6_only_ ? "[::1]:" : "127.0.0.1:",
+                     backends_[0]->port()),
+        grpc::StatusCode::NOT_FOUND);
+    SendRpc([this]() { return CreateInsecureChannel(); }, {}, {},
+            true /* test_expects_failure */);
+  }
+}
+
+TEST_P(XdsEnabledServerStatusNotificationTest, ExistingRpcsOnResourceDeletion) {
+  // Send a valid LDS update to get the server to start listening
+  SetValidLdsUpdate();
+  backends_[0]->notifier()->WaitOnServingStatusChange(
+      absl::StrCat(ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()),
+      grpc::StatusCode::OK);
+  constexpr int kNumChannels = 10;
+  struct StreamingRpc {
+    std::shared_ptr<Channel> channel;
+    std::unique_ptr<grpc::testing::EchoTestService::Stub> stub;
+    ClientContext context;
+    std::unique_ptr<ClientReaderWriter<EchoRequest, EchoResponse>> stream;
+  } streaming_rpcs[kNumChannels];
+  EchoRequest request;
+  EchoResponse response;
+  request.set_message("Hello");
+  for (int i = 0; i < kNumChannels; i++) {
+    streaming_rpcs[i].channel = CreateInsecureChannel();
+    streaming_rpcs[i].stub =
+        grpc::testing::EchoTestService::NewStub(streaming_rpcs[i].channel);
+    streaming_rpcs[i].context.set_wait_for_ready(true);
+    streaming_rpcs[i].stream =
+        streaming_rpcs[i].stub->BidiStream(&streaming_rpcs[i].context);
+    EXPECT_TRUE(streaming_rpcs[i].stream->Write(request));
+    streaming_rpcs[i].stream->Read(&response);
+    EXPECT_EQ(request.message(), response.message());
+  }
+  // Deleting the resource will make the server start rejecting connections
+  UnsetLdsUpdate();
+  backends_[0]->notifier()->WaitOnServingStatusChange(
+      absl::StrCat(ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()),
+      grpc::StatusCode::NOT_FOUND);
+  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {},
+          true /* test_expects_failure */);
+  for (int i = 0; i < kNumChannels; i++) {
+    EXPECT_TRUE(streaming_rpcs[i].stream->Write(request));
+    streaming_rpcs[i].stream->Read(&response);
+    EXPECT_EQ(request.message(), response.message());
+    EXPECT_TRUE(streaming_rpcs[i].stream->WritesDone());
+    auto status = streaming_rpcs[i].stream->Finish();
+    EXPECT_TRUE(status.ok())
+        << status.error_message() << ", " << status.error_details() << ", "
+        << streaming_rpcs[i].context.debug_error_string();
+    // New RPCs on the existing channels should fail.
+    ClientContext new_context;
+    new_context.set_deadline(grpc_timeout_milliseconds_to_deadline(1000));
+    EXPECT_FALSE(
+        streaming_rpcs[i].stub->Echo(&new_context, request, &response).ok());
+  }
+}
+
+using XdsServerFilterChainMatchTest = XdsServerSecurityTest;
+
+TEST_P(XdsServerFilterChainMatchTest,
+       DefaultFilterChainUsedWhenNoFilterChainMentioned) {
+  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {});
+}
+
+TEST_P(XdsServerFilterChainMatchTest,
+       DefaultFilterChainUsedWhenOtherFilterChainsDontMatch) {
+  Listener listener = default_server_listener_;
+  // Add a filter chain that will never get matched
+  auto* filter_chain = listener.add_filter_chains();
+  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
+      ServerHcmAccessor().Unpack(listener));
+  filter_chain->mutable_filter_chain_match()
+      ->mutable_destination_port()
+      ->set_value(8080);
+  SetServerListenerNameAndRouteConfiguration(0, listener, backends_[0]->port(),
+                                             default_server_route_config_);
+  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {});
+}
+
+TEST_P(XdsServerFilterChainMatchTest,
+       FilterChainsWithDestinationPortDontMatch) {
+  Listener listener = default_server_listener_;
+  // Add filter chain with destination port that should never get matched
+  auto* filter_chain = listener.add_filter_chains();
+  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
+      ServerHcmAccessor().Unpack(listener));
+  filter_chain->mutable_filter_chain_match()
+      ->mutable_destination_port()
+      ->set_value(8080);
+  listener.clear_default_filter_chain();
+  balancers_[0]->ads_service()->SetLdsResource(
+      PopulateServerListenerNameAndPort(listener, backends_[0]->port()));
+  // RPC should fail since no matching filter chain was found and no default
+  // filter chain is configured.
+  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {},
+          true /* test_expects_failure */);
+}
+
+TEST_P(XdsServerFilterChainMatchTest, FilterChainsWithServerNamesDontMatch) {
+  Listener listener = default_server_listener_;
+  // Add filter chain with server name that should never get matched
+  auto* filter_chain = listener.add_filter_chains();
+  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
+      ServerHcmAccessor().Unpack(listener));
+  filter_chain->mutable_filter_chain_match()->add_server_names("server_name");
+  listener.clear_default_filter_chain();
+  balancers_[0]->ads_service()->SetLdsResource(
+      PopulateServerListenerNameAndPort(listener, backends_[0]->port()));
+  // RPC should fail since no matching filter chain was found and no default
+  // filter chain is configured.
+  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {},
+          true /* test_expects_failure */);
+}
+
+TEST_P(XdsServerFilterChainMatchTest,
+       FilterChainsWithTransportProtocolsOtherThanRawBufferDontMatch) {
+  Listener listener = default_server_listener_;
+  // Add filter chain with transport protocol "tls" that should never match
+  auto* filter_chain = listener.add_filter_chains();
+  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
+      ServerHcmAccessor().Unpack(listener));
+  filter_chain->mutable_filter_chain_match()->set_transport_protocol("tls");
+  listener.clear_default_filter_chain();
+  balancers_[0]->ads_service()->SetLdsResource(
+      PopulateServerListenerNameAndPort(listener, backends_[0]->port()));
+  // RPC should fail since no matching filter chain was found and no default
+  // filter chain is configured.
+  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {},
+          true /* test_expects_failure */);
+}
+
+TEST_P(XdsServerFilterChainMatchTest,
+       FilterChainsWithApplicationProtocolsDontMatch) {
+  Listener listener = default_server_listener_;
+  // Add filter chain with application protocol that should never get matched
+  auto* filter_chain = listener.add_filter_chains();
+  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
+      ServerHcmAccessor().Unpack(listener));
+  filter_chain->mutable_filter_chain_match()->add_application_protocols("h2");
+  listener.clear_default_filter_chain();
+  balancers_[0]->ads_service()->SetLdsResource(
+      PopulateServerListenerNameAndPort(listener, backends_[0]->port()));
+  // RPC should fail since no matching filter chain was found and no default
+  // filter chain is configured.
+  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {},
+          true /* test_expects_failure */);
+}
+
+TEST_P(XdsServerFilterChainMatchTest,
+       FilterChainsWithTransportProtocolRawBufferIsPreferred) {
+  Listener listener = default_server_listener_;
+  // Add filter chain with "raw_buffer" transport protocol
+  auto* filter_chain = listener.add_filter_chains();
+  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
+      ServerHcmAccessor().Unpack(listener));
+  filter_chain->mutable_filter_chain_match()->set_transport_protocol(
+      "raw_buffer");
+  // Add another filter chain with no transport protocol set but application
+  // protocol set (fails match)
+  filter_chain = listener.add_filter_chains();
+  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
+      ServerHcmAccessor().Unpack(listener));
+  filter_chain->mutable_filter_chain_match()->add_application_protocols("h2");
+  listener.clear_default_filter_chain();
+  balancers_[0]->ads_service()->SetLdsResource(
+      PopulateServerListenerNameAndPort(listener, backends_[0]->port()));
+  // A successful RPC proves that filter chains that mention "raw_buffer" as
+  // the transport protocol are chosen as the best match in the round.
+  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {});
+}
+
+TEST_P(XdsServerFilterChainMatchTest,
+       FilterChainsWithMoreSpecificDestinationPrefixRangesArePreferred) {
+  Listener listener = default_server_listener_;
+  // Add filter chain with prefix range (length 4 and 16) but with server name
+  // mentioned. (Prefix range is matched first.)
+  auto* filter_chain = listener.add_filter_chains();
+  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
+      ServerHcmAccessor().Unpack(listener));
+  auto* prefix_range =
+      filter_chain->mutable_filter_chain_match()->add_prefix_ranges();
+  prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1");
+  prefix_range->mutable_prefix_len()->set_value(4);
+  prefix_range =
+      filter_chain->mutable_filter_chain_match()->add_prefix_ranges();
+  prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1");
+  prefix_range->mutable_prefix_len()->set_value(16);
+  filter_chain->mutable_filter_chain_match()->add_server_names("server_name");
+  // Add filter chain with two prefix ranges (length 8 and 24). Since 24 is
+  // the highest match, it should be chosen.
+  filter_chain = listener.add_filter_chains();
+  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
+      ServerHcmAccessor().Unpack(listener));
+  prefix_range =
+      filter_chain->mutable_filter_chain_match()->add_prefix_ranges();
+  prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1");
+  prefix_range->mutable_prefix_len()->set_value(8);
+  prefix_range =
+      filter_chain->mutable_filter_chain_match()->add_prefix_ranges();
+  prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1");
+  prefix_range->mutable_prefix_len()->set_value(24);
+  // Add another filter chain with a non-matching prefix range (with length
+  // 30)
+  filter_chain = listener.add_filter_chains();
+  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
+      ServerHcmAccessor().Unpack(listener));
+  prefix_range =
+      filter_chain->mutable_filter_chain_match()->add_prefix_ranges();
+  prefix_range->set_address_prefix("192.168.1.1");
+  prefix_range->mutable_prefix_len()->set_value(30);
+  filter_chain->mutable_filter_chain_match()->add_server_names("server_name");
+  // Add another filter chain with no prefix range mentioned
+  filter_chain = listener.add_filter_chains();
+  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
+      ServerHcmAccessor().Unpack(listener));
+  filter_chain->mutable_filter_chain_match()->add_server_names("server_name");
+  listener.clear_default_filter_chain();
+  balancers_[0]->ads_service()->SetLdsResource(
+      PopulateServerListenerNameAndPort(listener, backends_[0]->port()));
+  // A successful RPC proves that the filter chain with the longest matching
+  // prefix range was the best match.
+  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {});
+}
+
+TEST_P(XdsServerFilterChainMatchTest,
+       FilterChainsThatMentionSourceTypeArePreferred) {
+  Listener listener = default_server_listener_;
+  // Add filter chain with the local source type (best match)
+  auto* filter_chain = listener.add_filter_chains();
+  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
+      ServerHcmAccessor().Unpack(listener));
+  filter_chain->mutable_filter_chain_match()->set_source_type(
+      FilterChainMatch::SAME_IP_OR_LOOPBACK);
+  // Add filter chain with the external source type but bad source port.
+  // Note that backends_[0]->port() will never be a match for the source port
+  // because it is already being used by a backend.
+  filter_chain = listener.add_filter_chains();
+  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
+      ServerHcmAccessor().Unpack(listener));
+  filter_chain->mutable_filter_chain_match()->set_source_type(
+      FilterChainMatch::EXTERNAL);
+  filter_chain->mutable_filter_chain_match()->add_source_ports(
+      backends_[0]->port());
+  // Add filter chain with the default source type (ANY) but bad source port.
+  filter_chain = listener.add_filter_chains();
+  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
+      ServerHcmAccessor().Unpack(listener));
+  filter_chain->mutable_filter_chain_match()->add_source_ports(
+      backends_[0]->port());
+  listener.clear_default_filter_chain();
+  balancers_[0]->ads_service()->SetLdsResource(
+      PopulateServerListenerNameAndPort(listener, backends_[0]->port()));
+  // A successful RPC proves that the filter chain with the longest matching
+  // prefix range was the best match.
+  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {});
+}
+
+TEST_P(XdsServerFilterChainMatchTest,
+       FilterChainsWithMoreSpecificSourcePrefixRangesArePreferred) {
+  Listener listener = default_server_listener_;
+  // Add filter chain with source prefix range (length 16) but with a bad
+  // source port mentioned. (Prefix range is matched first.) Note that
+  // backends_[0]->port() will never be a match for the source port because it
+  // is already being used by a backend.
+  auto* filter_chain = listener.add_filter_chains();
+  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
+      ServerHcmAccessor().Unpack(listener));
+  auto* source_prefix_range =
+      filter_chain->mutable_filter_chain_match()->add_source_prefix_ranges();
+  source_prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1");
+  source_prefix_range->mutable_prefix_len()->set_value(4);
+  source_prefix_range =
+      filter_chain->mutable_filter_chain_match()->add_source_prefix_ranges();
+  source_prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1");
+  source_prefix_range->mutable_prefix_len()->set_value(16);
+  filter_chain->mutable_filter_chain_match()->add_source_ports(
+      backends_[0]->port());
+  // Add filter chain with two source prefix ranges (length 8 and 24). Since
+  // 24 is the highest match, it should be chosen.
+  filter_chain = listener.add_filter_chains();
+  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
+      ServerHcmAccessor().Unpack(listener));
+  source_prefix_range =
+      filter_chain->mutable_filter_chain_match()->add_source_prefix_ranges();
+  source_prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1");
+  source_prefix_range->mutable_prefix_len()->set_value(8);
+  source_prefix_range =
+      filter_chain->mutable_filter_chain_match()->add_source_prefix_ranges();
+  source_prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1");
+  source_prefix_range->mutable_prefix_len()->set_value(24);
+  // Add another filter chain with a non-matching source prefix range (with
+  // length 30) and bad source port
+  filter_chain = listener.add_filter_chains();
+  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
+      ServerHcmAccessor().Unpack(listener));
+  source_prefix_range =
+      filter_chain->mutable_filter_chain_match()->add_source_prefix_ranges();
+  source_prefix_range->set_address_prefix("192.168.1.1");
+  source_prefix_range->mutable_prefix_len()->set_value(30);
+  filter_chain->mutable_filter_chain_match()->add_source_ports(
+      backends_[0]->port());
+  // Add another filter chain with no source prefix range mentioned and bad
+  // source port
+  filter_chain = listener.add_filter_chains();
+  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
+      ServerHcmAccessor().Unpack(listener));
+  filter_chain->mutable_filter_chain_match()->add_source_ports(
+      backends_[0]->port());
+  listener.clear_default_filter_chain();
+  balancers_[0]->ads_service()->SetLdsResource(
+      PopulateServerListenerNameAndPort(listener, backends_[0]->port()));
+  // A successful RPC proves that the filter chain with the longest matching
+  // source prefix range was the best match.
+  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {});
+}
+
+TEST_P(XdsServerFilterChainMatchTest,
+       FilterChainsWithMoreSpecificSourcePortArePreferred) {
+  Listener listener = default_server_listener_;
+  auto* filter_chain = listener.add_filter_chains();
+  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
+      ServerHcmAccessor().Unpack(listener));
+  // Since we don't know which port will be used by the channel, just add all
+  // ports except for 0.
+  for (int i = 1; i < 65536; i++) {
+    filter_chain->mutable_filter_chain_match()->add_source_ports(i);
+  }
+  // Add another filter chain with no source port mentioned with a bad
+  // DownstreamTlsContext configuration.
+  filter_chain = listener.add_filter_chains();
+  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
+      ServerHcmAccessor().Unpack(listener));
+  auto* transport_socket = filter_chain->mutable_transport_socket();
+  transport_socket->set_name("envoy.transport_sockets.tls");
+  DownstreamTlsContext downstream_tls_context;
+  downstream_tls_context.mutable_common_tls_context()
+      ->mutable_tls_certificate_provider_instance()
+      ->set_instance_name("fake_plugin1");
+  transport_socket->mutable_typed_config()->PackFrom(downstream_tls_context);
+  listener.clear_default_filter_chain();
+  balancers_[0]->ads_service()->SetLdsResource(
+      PopulateServerListenerNameAndPort(listener, backends_[0]->port()));
+  // A successful RPC proves that the filter chain with matching source port
+  // was chosen.
+  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {});
+}
+
+TEST_P(XdsServerFilterChainMatchTest, DuplicateMatchNacked) {
+  Listener listener = default_server_listener_;
+  // Add filter chain
+  auto* filter_chain = listener.add_filter_chains();
+  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
+      ServerHcmAccessor().Unpack(listener));
+  // Add a duplicate filter chain
+  filter_chain = listener.add_filter_chains();
+  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
+      ServerHcmAccessor().Unpack(listener));
+  SetServerListenerNameAndRouteConfiguration(0, listener, backends_[0]->port(),
+                                             default_server_route_config_);
+  ASSERT_TRUE(WaitForLdsNack(StatusCode::DEADLINE_EXCEEDED))
+      << "timed out waiting for NACK";
+  EXPECT_THAT(
+      balancers_[0]->ads_service()->lds_response_state().error_message,
+      ::testing::HasSubstr(
+          "Duplicate matching rules detected when adding filter chain: {}"));
+}
+
+TEST_P(XdsServerFilterChainMatchTest, DuplicateMatchOnPrefixRangesNacked) {
+  Listener listener = default_server_listener_;
+  // Add filter chain with prefix range
+  auto* filter_chain = listener.add_filter_chains();
+  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
+      ServerHcmAccessor().Unpack(listener));
+  auto* prefix_range =
+      filter_chain->mutable_filter_chain_match()->add_prefix_ranges();
+  prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1");
+  prefix_range->mutable_prefix_len()->set_value(16);
+  prefix_range =
+      filter_chain->mutable_filter_chain_match()->add_prefix_ranges();
+  prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1");
+  prefix_range->mutable_prefix_len()->set_value(24);
+  // Add a filter chain with a duplicate prefix range entry
+  filter_chain = listener.add_filter_chains();
+  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
+      ServerHcmAccessor().Unpack(listener));
+  prefix_range =
+      filter_chain->mutable_filter_chain_match()->add_prefix_ranges();
+  prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1");
+  prefix_range->mutable_prefix_len()->set_value(16);
+  prefix_range =
+      filter_chain->mutable_filter_chain_match()->add_prefix_ranges();
+  prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1");
+  prefix_range->mutable_prefix_len()->set_value(32);
+  SetServerListenerNameAndRouteConfiguration(0, listener, backends_[0]->port(),
+                                             default_server_route_config_);
+  ASSERT_TRUE(WaitForLdsNack(StatusCode::DEADLINE_EXCEEDED))
+      << "timed out waiting for NACK";
+  if (ipv6_only_) {
+    EXPECT_THAT(
+        balancers_[0]->ads_service()->lds_response_state().error_message,
+        ::testing::HasSubstr(
+            "Duplicate matching rules detected when adding filter chain: "
+            "{prefix_ranges={{address_prefix=[::]:0, prefix_len=16}, "
+            "{address_prefix=[::]:0, prefix_len=32}}}"));
+  } else {
+    EXPECT_THAT(
+        balancers_[0]->ads_service()->lds_response_state().error_message,
+        ::testing::HasSubstr(
+            "Duplicate matching rules detected when adding filter chain: "
+            "{prefix_ranges={{address_prefix=127.0.0.0:0, prefix_len=16}, "
+            "{address_prefix=127.0.0.1:0, prefix_len=32}}}"));
+  }
+}
+
+TEST_P(XdsServerFilterChainMatchTest, DuplicateMatchOnTransportProtocolNacked) {
+  Listener listener = default_server_listener_;
+  // Add filter chain with "raw_buffer" transport protocol
+  auto* filter_chain = listener.add_filter_chains();
+  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
+      ServerHcmAccessor().Unpack(listener));
+  filter_chain->mutable_filter_chain_match()->set_transport_protocol(
+      "raw_buffer");
+  // Add a duplicate filter chain with the same "raw_buffer" transport
+  // protocol entry
+  filter_chain = listener.add_filter_chains();
+  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
+      ServerHcmAccessor().Unpack(listener));
+  filter_chain->mutable_filter_chain_match()->set_transport_protocol(
+      "raw_buffer");
+  SetServerListenerNameAndRouteConfiguration(0, listener, backends_[0]->port(),
+                                             default_server_route_config_);
+  ASSERT_TRUE(WaitForLdsNack(StatusCode::DEADLINE_EXCEEDED))
+      << "timed out waiting for NACK";
+  EXPECT_THAT(
+      balancers_[0]->ads_service()->lds_response_state().error_message,
+      ::testing::HasSubstr("Duplicate matching rules detected when adding "
+                           "filter chain: {transport_protocol=raw_buffer}"));
+}
+
+TEST_P(XdsServerFilterChainMatchTest, DuplicateMatchOnLocalSourceTypeNacked) {
+  Listener listener = default_server_listener_;
+  // Add filter chain with the local source type
+  auto* filter_chain = listener.add_filter_chains();
+  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
+      ServerHcmAccessor().Unpack(listener));
+  filter_chain->mutable_filter_chain_match()->set_source_type(
+      FilterChainMatch::SAME_IP_OR_LOOPBACK);
+  // Add a duplicate filter chain with the same local source type entry
+  filter_chain = listener.add_filter_chains();
+  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
+      ServerHcmAccessor().Unpack(listener));
+  filter_chain->mutable_filter_chain_match()->set_source_type(
+      FilterChainMatch::SAME_IP_OR_LOOPBACK);
+  SetServerListenerNameAndRouteConfiguration(0, listener, backends_[0]->port(),
+                                             default_server_route_config_);
+  ASSERT_TRUE(WaitForLdsNack(StatusCode::DEADLINE_EXCEEDED))
+      << "timed out waiting for NACK";
+  EXPECT_THAT(
+      balancers_[0]->ads_service()->lds_response_state().error_message,
+      ::testing::HasSubstr("Duplicate matching rules detected when adding "
+                           "filter chain: {source_type=SAME_IP_OR_LOOPBACK}"));
+}
+
+TEST_P(XdsServerFilterChainMatchTest,
+       DuplicateMatchOnExternalSourceTypeNacked) {
+  Listener listener = default_server_listener_;
+  // Add filter chain with the external source type
+  auto* filter_chain = listener.add_filter_chains();
+  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
+      ServerHcmAccessor().Unpack(listener));
+  filter_chain->mutable_filter_chain_match()->set_source_type(
+      FilterChainMatch::EXTERNAL);
+  // Add a duplicate filter chain with the same external source type entry
+  filter_chain = listener.add_filter_chains();
+  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
+      ServerHcmAccessor().Unpack(listener));
+  filter_chain->mutable_filter_chain_match()->set_source_type(
+      FilterChainMatch::EXTERNAL);
+  SetServerListenerNameAndRouteConfiguration(0, listener, backends_[0]->port(),
+                                             default_server_route_config_);
+  ASSERT_TRUE(WaitForLdsNack(StatusCode::DEADLINE_EXCEEDED))
+      << "timed out waiting for NACK";
+  EXPECT_THAT(
+      balancers_[0]->ads_service()->lds_response_state().error_message,
+      ::testing::HasSubstr("Duplicate matching rules detected when adding "
+                           "filter chain: {source_type=EXTERNAL}"));
+}
+
+TEST_P(XdsServerFilterChainMatchTest,
+       DuplicateMatchOnSourcePrefixRangesNacked) {
+  Listener listener = default_server_listener_;
+  // Add filter chain with source prefix range
+  auto* filter_chain = listener.add_filter_chains();
+  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
+      ServerHcmAccessor().Unpack(listener));
+  auto* prefix_range =
+      filter_chain->mutable_filter_chain_match()->add_source_prefix_ranges();
+  prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1");
+  prefix_range->mutable_prefix_len()->set_value(16);
+  prefix_range =
+      filter_chain->mutable_filter_chain_match()->add_source_prefix_ranges();
+  prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1");
+  prefix_range->mutable_prefix_len()->set_value(24);
+  // Add a filter chain with a duplicate source prefix range entry
+  filter_chain = listener.add_filter_chains();
+  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
+      ServerHcmAccessor().Unpack(listener));
+  prefix_range =
+      filter_chain->mutable_filter_chain_match()->add_source_prefix_ranges();
+  prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1");
+  prefix_range->mutable_prefix_len()->set_value(16);
+  prefix_range =
+      filter_chain->mutable_filter_chain_match()->add_source_prefix_ranges();
+  prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1");
+  prefix_range->mutable_prefix_len()->set_value(32);
+  SetServerListenerNameAndRouteConfiguration(0, listener, backends_[0]->port(),
+                                             default_server_route_config_);
+  ASSERT_TRUE(WaitForLdsNack(StatusCode::DEADLINE_EXCEEDED))
+      << "timed out waiting for NACK";
+  if (ipv6_only_) {
+    EXPECT_THAT(
+        balancers_[0]->ads_service()->lds_response_state().error_message,
+        ::testing::HasSubstr(
+            "Duplicate matching rules detected when adding filter chain: "
+            "{source_prefix_ranges={{address_prefix=[::]:0, prefix_len=16}, "
+            "{address_prefix=[::]:0, prefix_len=32}}}"));
+  } else {
+    EXPECT_THAT(
+        balancers_[0]->ads_service()->lds_response_state().error_message,
+        ::testing::HasSubstr(
+            "Duplicate matching rules detected when adding filter chain: "
+            "{source_prefix_ranges={{address_prefix=127.0.0.0:0, "
+            "prefix_len=16}, "
+            "{address_prefix=127.0.0.1:0, prefix_len=32}}}"));
+  }
+}
+
+TEST_P(XdsServerFilterChainMatchTest, DuplicateMatchOnSourcePortNacked) {
+  Listener listener = default_server_listener_;
+  // Add filter chain with the external source type
+  auto* filter_chain = listener.add_filter_chains();
+  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
+      ServerHcmAccessor().Unpack(listener));
+  filter_chain->mutable_filter_chain_match()->add_source_ports(8080);
+  // Add a duplicate filter chain with the same source port entry
+  filter_chain = listener.add_filter_chains();
+  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
+      ServerHcmAccessor().Unpack(listener));
+  filter_chain->mutable_filter_chain_match()->add_source_ports(8080);
+  SetServerListenerNameAndRouteConfiguration(0, listener, backends_[0]->port(),
+                                             default_server_route_config_);
+  ASSERT_TRUE(WaitForLdsNack(StatusCode::DEADLINE_EXCEEDED))
+      << "timed out waiting for NACK";
+  EXPECT_THAT(
+      balancers_[0]->ads_service()->lds_response_state().error_message,
+      ::testing::HasSubstr("Duplicate matching rules detected when adding "
+                           "filter chain: {source_ports={8080}}"));
+}
+
+class XdsServerRdsTest : public XdsServerSecurityTest {
+ protected:
+  static void SetUpTestSuite() {
+    gpr_setenv("GRPC_XDS_EXPERIMENTAL_RBAC", "true");
+  }
+
+  static void TearDownTestSuite() {
+    gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_RBAC");
+  }
+};
+
+TEST_P(XdsServerRdsTest, NacksInvalidDomainPattern) {
+  RouteConfiguration route_config = default_server_route_config_;
+  route_config.mutable_virtual_hosts()->at(0).add_domains("");
+  SetServerListenerNameAndRouteConfiguration(
+      0, default_server_listener_, backends_[0]->port(), route_config);
+  ASSERT_TRUE(WaitForLdsNack(StatusCode::DEADLINE_EXCEEDED))
+      << "timed out waiting for NACK";
+  EXPECT_THAT(balancers_[0]->ads_service()->lds_response_state().error_message,
+              ::testing::HasSubstr("Invalid domain pattern \"\""));
+}
+
+TEST_P(XdsServerRdsTest, NacksEmptyDomainsList) {
+  RouteConfiguration route_config = default_server_route_config_;
+  route_config.mutable_virtual_hosts()->at(0).clear_domains();
+  SetServerListenerNameAndRouteConfiguration(
+      0, default_server_listener_, backends_[0]->port(), route_config);
+  ASSERT_TRUE(WaitForLdsNack(StatusCode::DEADLINE_EXCEEDED))
+      << "timed out waiting for NACK";
+  EXPECT_THAT(balancers_[0]->ads_service()->lds_response_state().error_message,
+              ::testing::HasSubstr("VirtualHost has no domains"));
+}
+
+TEST_P(XdsServerRdsTest, NacksEmptyRoutesList) {
+  RouteConfiguration route_config = default_server_route_config_;
+  route_config.mutable_virtual_hosts()->at(0).clear_routes();
+  SetServerListenerNameAndRouteConfiguration(
+      0, default_server_listener_, backends_[0]->port(), route_config);
+  ASSERT_TRUE(WaitForLdsNack(StatusCode::DEADLINE_EXCEEDED))
+      << "timed out waiting for NACK";
+  EXPECT_THAT(balancers_[0]->ads_service()->lds_response_state().error_message,
+              ::testing::HasSubstr("No route found in the virtual host"));
+}
+
+TEST_P(XdsServerRdsTest, NacksEmptyMatch) {
+  RouteConfiguration route_config = default_server_route_config_;
+  route_config.mutable_virtual_hosts()
+      ->at(0)
+      .mutable_routes()
+      ->at(0)
+      .clear_match();
+  SetServerListenerNameAndRouteConfiguration(
+      0, default_server_listener_, backends_[0]->port(), route_config);
+  ASSERT_TRUE(WaitForLdsNack(StatusCode::DEADLINE_EXCEEDED))
+      << "timed out waiting for NACK";
+  EXPECT_THAT(balancers_[0]->ads_service()->lds_response_state().error_message,
+              ::testing::HasSubstr("Match can't be null"));
+}
+
+using EdsTest = BasicTest;
+
+// Tests that EDS client should send a NACK if the EDS update contains
+// sparse priorities.
+TEST_P(EdsTest, NacksSparsePriorityList) {
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(), kDefaultLocalityWeight, 1},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
+  ASSERT_TRUE(WaitForEdsNack()) << "timed out waiting for NACK";
+  const auto response_state =
+      balancers_[0]->ads_service()->eds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_THAT(response_state.error_message,
+              ::testing::HasSubstr("sparse priority list"));
+}
+
+// In most of our tests, we use different names for different resource
+// types, to make sure that there are no cut-and-paste errors in the code
+// that cause us to look at data for the wrong resource type.  So we add
+// this test to make sure that the EDS resource name defaults to the
+// cluster name if not specified in the CDS resource.
+TEST_P(EdsTest, EdsServiceNameDefaultsToClusterName) {
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, kDefaultClusterName));
+  Cluster cluster = default_cluster_;
+  cluster.mutable_eds_cluster_config()->clear_service_name();
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  CheckRpcSendOk();
+}
+
+class TimeoutTest : public BasicTest {
+ protected:
+  void SetUp() override {
+    xds_resource_does_not_exist_timeout_ms_ = 500;
+    BasicTest::SetUp();
+  }
+};
+
+// Tests that LDS client times out when no response received.
+TEST_P(TimeoutTest, Lds) {
+  balancers_[0]->ads_service()->IgnoreResourceType(kLdsTypeUrl);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  CheckRpcSendFailure();
+}
+
+TEST_P(TimeoutTest, Rds) {
+  balancers_[0]->ads_service()->IgnoreResourceType(kRdsTypeUrl);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  CheckRpcSendFailure();
+}
+
+// Tests that CDS client times out when no response received.
+TEST_P(TimeoutTest, Cds) {
+  balancers_[0]->ads_service()->IgnoreResourceType(kCdsTypeUrl);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  CheckRpcSendFailure();
+}
+
+TEST_P(TimeoutTest, Eds) {
+  balancers_[0]->ads_service()->IgnoreResourceType(kEdsTypeUrl);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  CheckRpcSendFailure();
+}
+
+using LocalityMapTest = BasicTest;
+
+// Tests that the localities in a locality map are picked according to their
+// weights.
+TEST_P(LocalityMapTest, WeightedRoundRobin) {
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  const int kLocalityWeight0 = 2;
+  const int kLocalityWeight1 = 8;
+  const int kTotalLocalityWeight = kLocalityWeight0 + kLocalityWeight1;
+  const double kLocalityWeightRate0 =
+      static_cast<double>(kLocalityWeight0) / kTotalLocalityWeight;
+  const double kLocalityWeightRate1 =
+      static_cast<double>(kLocalityWeight1) / kTotalLocalityWeight;
+  const double kErrorTolerance = 0.05;
+  const size_t kNumRpcs =
+      ComputeIdealNumRpcs(kLocalityWeightRate0, kErrorTolerance);
+  // ADS response contains 2 localities, each of which contains 1 backend.
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 1), kLocalityWeight0},
+      {"locality1", CreateEndpointsForBackends(1, 2), kLocalityWeight1},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  // Wait for both backends to be ready.
+  WaitForAllBackends(0, 2);
+  // Send kNumRpcs RPCs.
+  CheckRpcSendOk(kNumRpcs);
+  // The locality picking rates should be roughly equal to the expectation.
+  const double locality_picked_rate_0 =
+      static_cast<double>(backends_[0]->backend_service()->request_count()) /
+      kNumRpcs;
+  const double locality_picked_rate_1 =
+      static_cast<double>(backends_[1]->backend_service()->request_count()) /
+      kNumRpcs;
+  EXPECT_THAT(locality_picked_rate_0,
+              ::testing::DoubleNear(kLocalityWeightRate0, kErrorTolerance));
+  EXPECT_THAT(locality_picked_rate_1,
+              ::testing::DoubleNear(kLocalityWeightRate1, kErrorTolerance));
+}
+
+// Tests that we correctly handle a locality containing no endpoints.
+TEST_P(LocalityMapTest, LocalityContainingNoEndpoints) {
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  const size_t kNumRpcs = 5000;
+  // EDS response contains 2 localities, one with no endpoints.
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+      {"locality1", {}},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  // Wait for both backends to be ready.
+  WaitForAllBackends();
+  // Send kNumRpcs RPCs.
+  CheckRpcSendOk(kNumRpcs);
+  // All traffic should go to the reachable locality.
+  EXPECT_EQ(backends_[0]->backend_service()->request_count(),
+            kNumRpcs / backends_.size());
+  EXPECT_EQ(backends_[1]->backend_service()->request_count(),
+            kNumRpcs / backends_.size());
+  EXPECT_EQ(backends_[2]->backend_service()->request_count(),
+            kNumRpcs / backends_.size());
+  EXPECT_EQ(backends_[3]->backend_service()->request_count(),
+            kNumRpcs / backends_.size());
+}
+
+// EDS update with no localities.
+TEST_P(LocalityMapTest, NoLocalities) {
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource({}, DefaultEdsServiceName()));
+  Status status = SendRpc();
+  EXPECT_FALSE(status.ok());
+  EXPECT_EQ(status.error_code(), StatusCode::UNAVAILABLE);
+}
+
+// Tests that the locality map can work properly even when it contains a large
+// number of localities.
+TEST_P(LocalityMapTest, StressTest) {
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  const size_t kNumLocalities = 100;
+  const uint32_t kRpcTimeoutMs = 5000;
+  // The first ADS response contains kNumLocalities localities, each of which
+  // contains backend 0.
+  EdsResourceArgs args;
+  for (size_t i = 0; i < kNumLocalities; ++i) {
+    std::string name = absl::StrCat("locality", i);
+    EdsResourceArgs::Locality locality(name, CreateEndpointsForBackends(0, 1));
+    args.locality_list.emplace_back(std::move(locality));
+  }
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  // The second ADS response contains 1 locality, which contains backend 1.
+  args = EdsResourceArgs({
+      {"locality0", CreateEndpointsForBackends(1, 2)},
+  });
+  std::thread delayed_resource_setter(
+      std::bind(&BasicTest::SetEdsResourceWithDelay, this, 0,
+                BuildEdsResource(args, DefaultEdsServiceName()), 60 * 1000));
+  // Wait until backend 0 is ready, before which kNumLocalities localities are
+  // received and handled by the xds policy.
+  WaitForBackend(0, WaitForBackendOptions().set_reset_counters(false),
+                 RpcOptions().set_timeout_ms(kRpcTimeoutMs));
+  EXPECT_EQ(0U, backends_[1]->backend_service()->request_count());
+  // Wait until backend 1 is ready, before which kNumLocalities localities are
+  // removed by the xds policy.
+  WaitForBackend(1);
+  delayed_resource_setter.join();
+}
+
+// Tests that the localities in a locality map are picked correctly after
+// update (addition, modification, deletion).
+TEST_P(LocalityMapTest, UpdateMap) {
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  const size_t kNumRpcs = 3000;
+  // The locality weight for the first 3 localities.
+  const std::vector<int> kLocalityWeights0 = {2, 3, 4};
+  const double kTotalLocalityWeight0 =
+      std::accumulate(kLocalityWeights0.begin(), kLocalityWeights0.end(), 0);
+  std::vector<double> locality_weight_rate_0;
+  locality_weight_rate_0.reserve(kLocalityWeights0.size());
+  for (int weight : kLocalityWeights0) {
+    locality_weight_rate_0.push_back(weight / kTotalLocalityWeight0);
+  }
+  // Delete the first locality, keep the second locality, change the third
+  // locality's weight from 4 to 2, and add a new locality with weight 6.
+  const std::vector<int> kLocalityWeights1 = {3, 2, 6};
+  const double kTotalLocalityWeight1 =
+      std::accumulate(kLocalityWeights1.begin(), kLocalityWeights1.end(), 0);
+  std::vector<double> locality_weight_rate_1 = {
+      0 /* placeholder for locality 0 */};
+  for (int weight : kLocalityWeights1) {
+    locality_weight_rate_1.push_back(weight / kTotalLocalityWeight1);
+  }
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 1), 2},
+      {"locality1", CreateEndpointsForBackends(1, 2), 3},
+      {"locality2", CreateEndpointsForBackends(2, 3), 4},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  // Wait for the first 3 backends to be ready.
+  WaitForAllBackends(0, 3);
+  gpr_log(GPR_INFO, "========= BEFORE FIRST BATCH ==========");
+  // Send kNumRpcs RPCs.
+  CheckRpcSendOk(kNumRpcs);
+  gpr_log(GPR_INFO, "========= DONE WITH FIRST BATCH ==========");
+  // The picking rates of the first 3 backends should be roughly equal to the
+  // expectation.
+  std::vector<double> locality_picked_rates;
+  for (size_t i = 0; i < 3; ++i) {
+    locality_picked_rates.push_back(
+        static_cast<double>(backends_[i]->backend_service()->request_count()) /
+        kNumRpcs);
+  }
+  const double kErrorTolerance = 0.2;
+  for (size_t i = 0; i < 3; ++i) {
+    gpr_log(GPR_INFO, "Locality %" PRIuPTR " rate %f", i,
+            locality_picked_rates[i]);
+    EXPECT_THAT(
+        locality_picked_rates[i],
+        ::testing::AllOf(
+            ::testing::Ge(locality_weight_rate_0[i] * (1 - kErrorTolerance)),
+            ::testing::Le(locality_weight_rate_0[i] * (1 + kErrorTolerance))));
+  }
+  args = EdsResourceArgs({
+      {"locality1", CreateEndpointsForBackends(1, 2), 3},
+      {"locality2", CreateEndpointsForBackends(2, 3), 2},
+      {"locality3", CreateEndpointsForBackends(3, 4), 6},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  // Backend 3 hasn't received any request.
+  EXPECT_EQ(0U, backends_[3]->backend_service()->request_count());
+  // Wait until the locality update has been processed, as signaled by backend
+  // 3 receiving a request.
+  WaitForAllBackends(3, 4);
+  gpr_log(GPR_INFO, "========= BEFORE SECOND BATCH ==========");
+  // Send kNumRpcs RPCs.
+  CheckRpcSendOk(kNumRpcs);
+  gpr_log(GPR_INFO, "========= DONE WITH SECOND BATCH ==========");
+  // Backend 0 no longer receives any request.
+  EXPECT_EQ(0U, backends_[0]->backend_service()->request_count());
+  // The picking rates of the last 3 backends should be roughly equal to the
+  // expectation.
+  locality_picked_rates = {0 /* placeholder for backend 0 */};
+  for (size_t i = 1; i < 4; ++i) {
+    locality_picked_rates.push_back(
+        static_cast<double>(backends_[i]->backend_service()->request_count()) /
+        kNumRpcs);
+  }
+  for (size_t i = 1; i < 4; ++i) {
+    gpr_log(GPR_INFO, "Locality %" PRIuPTR " rate %f", i,
+            locality_picked_rates[i]);
+    EXPECT_THAT(
+        locality_picked_rates[i],
+        ::testing::AllOf(
+            ::testing::Ge(locality_weight_rate_1[i] * (1 - kErrorTolerance)),
+            ::testing::Le(locality_weight_rate_1[i] * (1 + kErrorTolerance))));
+  }
+}
+
+// Tests that we don't fail RPCs when replacing all of the localities in
+// a given priority.
+TEST_P(LocalityMapTest, ReplaceAllLocalitiesInPriority) {
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 1)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  args = EdsResourceArgs({
+      {"locality1", CreateEndpointsForBackends(1, 2)},
+  });
+  std::thread delayed_resource_setter(
+      std::bind(&BasicTest::SetEdsResourceWithDelay, this, 0,
+                BuildEdsResource(args, DefaultEdsServiceName()), 5000));
+  // Wait for the first backend to be ready.
+  WaitForBackend(0);
+  // Keep sending RPCs until we switch over to backend 1, which tells us
+  // that we received the update.  No RPCs should fail during this
+  // transition.
+  WaitForBackend(1);
+  delayed_resource_setter.join();
+}
+
+class FailoverTest : public BasicTest {
+ public:
+  void SetUp() override {
+    BasicTest::SetUp();
+    ResetStub(500);
+  }
+};
+
+// Localities with the highest priority are used when multiple priority exist.
+TEST_P(FailoverTest, ChooseHighestPriority) {
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 1), kDefaultLocalityWeight,
+       1},
+      {"locality1", CreateEndpointsForBackends(1, 2), kDefaultLocalityWeight,
+       2},
+      {"locality2", CreateEndpointsForBackends(2, 3), kDefaultLocalityWeight,
+       3},
+      {"locality3", CreateEndpointsForBackends(3, 4), kDefaultLocalityWeight,
+       0},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  WaitForBackend(3, WaitForBackendOptions().set_reset_counters(false));
+  for (size_t i = 0; i < 3; ++i) {
+    EXPECT_EQ(0U, backends_[i]->backend_service()->request_count());
+  }
+}
+
+// Does not choose priority with no endpoints.
+TEST_P(FailoverTest, DoesNotUsePriorityWithNoEndpoints) {
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 1), kDefaultLocalityWeight,
+       1},
+      {"locality1", CreateEndpointsForBackends(1, 2), kDefaultLocalityWeight,
+       2},
+      {"locality2", CreateEndpointsForBackends(2, 3), kDefaultLocalityWeight,
+       3},
+      {"locality3", {}, kDefaultLocalityWeight, 0},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  WaitForBackend(0, WaitForBackendOptions().set_reset_counters(false));
+  for (size_t i = 1; i < 3; ++i) {
+    EXPECT_EQ(0U, backends_[i]->backend_service()->request_count());
+  }
+}
+
+// Does not choose locality with no endpoints.
+TEST_P(FailoverTest, DoesNotUseLocalityWithNoEndpoints) {
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  EdsResourceArgs args({
+      {"locality0", {}, kDefaultLocalityWeight, 0},
+      {"locality1", CreateEndpointsForBackends(), kDefaultLocalityWeight, 0},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  // Wait for all backends to be used.
+  std::tuple<int, int, int> counts = WaitForAllBackends();
+  // Make sure no RPCs failed in the transition.
+  EXPECT_EQ(0, std::get<1>(counts));
+}
+
+// If the higher priority localities are not reachable, failover to the
+// highest priority among the rest.
+TEST_P(FailoverTest, Failover) {
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 1), kDefaultLocalityWeight,
+       1},
+      {"locality1", CreateEndpointsForBackends(1, 2), kDefaultLocalityWeight,
+       2},
+      {"locality2", CreateEndpointsForBackends(2, 3), kDefaultLocalityWeight,
+       3},
+      {"locality3", CreateEndpointsForBackends(3, 4), kDefaultLocalityWeight,
+       0},
+  });
+  ShutdownBackend(3);
+  ShutdownBackend(0);
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  WaitForBackend(1, WaitForBackendOptions().set_reset_counters(false));
+  for (size_t i = 0; i < 4; ++i) {
+    if (i == 1) continue;
+    EXPECT_EQ(0U, backends_[i]->backend_service()->request_count());
+  }
+}
+
+// If a locality with higher priority than the current one becomes ready,
+// switch to it.
+TEST_P(FailoverTest, SwitchBackToHigherPriority) {
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  const size_t kNumRpcs = 100;
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 1), kDefaultLocalityWeight,
+       1},
+      {"locality1", CreateEndpointsForBackends(1, 2), kDefaultLocalityWeight,
+       2},
+      {"locality2", CreateEndpointsForBackends(2, 3), kDefaultLocalityWeight,
+       3},
+      {"locality3", CreateEndpointsForBackends(3, 4), kDefaultLocalityWeight,
+       0},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  WaitForBackend(3);
+  ShutdownBackend(3);
+  ShutdownBackend(0);
+  WaitForBackend(
+      1, WaitForBackendOptions().set_reset_counters(false).set_allow_failures(
+             true));
+  for (size_t i = 0; i < 4; ++i) {
+    if (i == 1) continue;
+    EXPECT_EQ(0U, backends_[i]->backend_service()->request_count());
+  }
+  StartBackend(0);
+  WaitForBackend(0);
+  CheckRpcSendOk(kNumRpcs);
+  EXPECT_EQ(kNumRpcs, backends_[0]->backend_service()->request_count());
+}
+
+// The first update only contains unavailable priorities. The second update
+// contains available priorities.
+TEST_P(FailoverTest, UpdateInitialUnavailable) {
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 1), kDefaultLocalityWeight,
+       0},
+      {"locality1", CreateEndpointsForBackends(1, 2), kDefaultLocalityWeight,
+       1},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  args = EdsResourceArgs({
+      {"locality0", CreateEndpointsForBackends(0, 1), kDefaultLocalityWeight,
+       0},
+      {"locality1", CreateEndpointsForBackends(1, 2), kDefaultLocalityWeight,
+       1},
+      {"locality2", CreateEndpointsForBackends(2, 3), kDefaultLocalityWeight,
+       2},
+      {"locality3", CreateEndpointsForBackends(3, 4), kDefaultLocalityWeight,
+       3},
+  });
+  ShutdownBackend(0);
+  ShutdownBackend(1);
+  std::thread delayed_resource_setter(
+      std::bind(&BasicTest::SetEdsResourceWithDelay, this, 0,
+                BuildEdsResource(args, DefaultEdsServiceName()), 1000));
+  gpr_timespec deadline = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
+                                       gpr_time_from_millis(500, GPR_TIMESPAN));
+  // Send 0.5 second worth of RPCs.
+  do {
+    CheckRpcSendFailure();
+  } while (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), deadline) < 0);
+  WaitForBackend(
+      2, WaitForBackendOptions().set_reset_counters(false).set_allow_failures(
+             true));
+  for (size_t i = 0; i < 4; ++i) {
+    if (i == 2) continue;
+    EXPECT_EQ(0U, backends_[i]->backend_service()->request_count());
+  }
+  delayed_resource_setter.join();
+}
+
+// Tests that after the localities' priorities are updated, we still choose
+// the highest READY priority with the updated localities.
+TEST_P(FailoverTest, UpdatePriority) {
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  const size_t kNumRpcs = 100;
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 1), kDefaultLocalityWeight,
+       1},
+      {"locality1", CreateEndpointsForBackends(1, 2), kDefaultLocalityWeight,
+       2},
+      {"locality2", CreateEndpointsForBackends(2, 3), kDefaultLocalityWeight,
+       3},
+      {"locality3", CreateEndpointsForBackends(3, 4), kDefaultLocalityWeight,
+       0},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  args = EdsResourceArgs({
+      {"locality0", CreateEndpointsForBackends(0, 1), kDefaultLocalityWeight,
+       2},
+      {"locality1", CreateEndpointsForBackends(1, 2), kDefaultLocalityWeight,
+       0},
+      {"locality2", CreateEndpointsForBackends(2, 3), kDefaultLocalityWeight,
+       1},
+      {"locality3", CreateEndpointsForBackends(3, 4), kDefaultLocalityWeight,
+       3},
+  });
+  std::thread delayed_resource_setter(
+      std::bind(&BasicTest::SetEdsResourceWithDelay, this, 0,
+                BuildEdsResource(args, DefaultEdsServiceName()), 1000));
+  WaitForBackend(3, WaitForBackendOptions().set_reset_counters(false));
+  for (size_t i = 0; i < 3; ++i) {
+    EXPECT_EQ(0U, backends_[i]->backend_service()->request_count());
+  }
+  WaitForBackend(1);
+  CheckRpcSendOk(kNumRpcs);
+  EXPECT_EQ(kNumRpcs, backends_[1]->backend_service()->request_count());
+  delayed_resource_setter.join();
+}
+
+// Moves all localities in the current priority to a higher priority.
+TEST_P(FailoverTest, MoveAllLocalitiesInCurrentPriorityToHigherPriority) {
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // First update:
+  // - Priority 0 is locality 0, containing backend 0, which is down.
+  // - Priority 1 is locality 1, containing backends 1 and 2, which are up.
+  ShutdownBackend(0);
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, 1), kDefaultLocalityWeight,
+       0},
+      {"locality1", CreateEndpointsForBackends(1, 3), kDefaultLocalityWeight,
+       1},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  // Second update:
+  // - Priority 0 contains both localities 0 and 1.
+  // - Priority 1 is not present.
+  // - We add backend 3 to locality 1, just so we have a way to know
+  //   when the update has been seen by the client.
+  args = EdsResourceArgs({
+      {"locality0", CreateEndpointsForBackends(0, 1), kDefaultLocalityWeight,
+       0},
+      {"locality1", CreateEndpointsForBackends(1, 4), kDefaultLocalityWeight,
+       0},
+  });
+  std::thread delayed_resource_setter(
+      std::bind(&BasicTest::SetEdsResourceWithDelay, this, 0,
+                BuildEdsResource(args, DefaultEdsServiceName()), 1000));
+  // When we get the first update, all backends in priority 0 are down,
+  // so we will create priority 1.  Backends 1 and 2 should have traffic,
+  // but backend 3 should not.
+  WaitForAllBackends(1, 3, WaitForBackendOptions().set_reset_counters(false));
+  EXPECT_EQ(0UL, backends_[3]->backend_service()->request_count());
+  // When backend 3 gets traffic, we know the second update has been seen.
+  WaitForBackend(3);
+  // The ADS service of balancer 0 got at least 1 response.
+  EXPECT_GT(balancers_[0]->ads_service()->eds_response_state().state,
+            AdsServiceImpl::ResponseState::NOT_SENT);
+  delayed_resource_setter.join();
+}
+
+using DropTest = BasicTest;
+
+// Tests that RPCs are dropped according to the drop config.
+TEST_P(DropTest, Vanilla) {
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  const uint32_t kDropPerMillionForLb = 100000;
+  const uint32_t kDropPerMillionForThrottle = 200000;
+  const double kDropRateForLb = kDropPerMillionForLb / 1000000.0;
+  const double kDropRateForThrottle = kDropPerMillionForThrottle / 1000000.0;
+  const double kDropRateForLbAndThrottle =
+      kDropRateForLb + (1 - kDropRateForLb) * kDropRateForThrottle;
+  const double kErrorTolerance = 0.05;
+  const size_t kNumRpcs =
+      ComputeIdealNumRpcs(kDropRateForLbAndThrottle, kErrorTolerance);
+  // The ADS response contains two drop categories.
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  args.drop_categories = {{kLbDropType, kDropPerMillionForLb},
+                          {kThrottleDropType, kDropPerMillionForThrottle}};
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  WaitForAllBackends();
+  // Send kNumRpcs RPCs and count the drops.
+  size_t num_drops = 0;
+  for (size_t i = 0; i < kNumRpcs; ++i) {
+    EchoResponse response;
+    const Status status = SendRpc(RpcOptions(), &response);
+    if (!status.ok() &&
+        absl::StartsWith(status.error_message(), "EDS-configured drop: ")) {
+      ++num_drops;
+    } else {
+      EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
+                               << " message=" << status.error_message();
+      EXPECT_EQ(response.message(), kRequestMessage);
+    }
+  }
+  // The drop rate should be roughly equal to the expectation.
+  const double seen_drop_rate = static_cast<double>(num_drops) / kNumRpcs;
+  EXPECT_THAT(seen_drop_rate, ::testing::DoubleNear(kDropRateForLbAndThrottle,
+                                                    kErrorTolerance));
+}
+
+// Tests that drop config is converted correctly from per hundred.
+TEST_P(DropTest, DropPerHundred) {
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  const uint32_t kDropPerHundredForLb = 10;
+  const double kDropRateForLb = kDropPerHundredForLb / 100.0;
+  const double kErrorTolerance = 0.05;
+  const size_t kNumRpcs = ComputeIdealNumRpcs(kDropRateForLb, kErrorTolerance);
+  // The ADS response contains one drop category.
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  args.drop_categories = {{kLbDropType, kDropPerHundredForLb}};
+  args.drop_denominator = FractionalPercent::HUNDRED;
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  WaitForAllBackends();
+  // Send kNumRpcs RPCs and count the drops.
+  size_t num_drops = 0;
+  for (size_t i = 0; i < kNumRpcs; ++i) {
+    EchoResponse response;
+    const Status status = SendRpc(RpcOptions(), &response);
+    if (!status.ok() &&
+        absl::StartsWith(status.error_message(), "EDS-configured drop: ")) {
+      ++num_drops;
+    } else {
+      EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
+                               << " message=" << status.error_message();
+      EXPECT_EQ(response.message(), kRequestMessage);
+    }
+  }
+  // The drop rate should be roughly equal to the expectation.
+  const double seen_drop_rate = static_cast<double>(num_drops) / kNumRpcs;
+  EXPECT_THAT(seen_drop_rate,
+              ::testing::DoubleNear(kDropRateForLb, kErrorTolerance));
+}
+
+// Tests that drop config is converted correctly from per ten thousand.
+TEST_P(DropTest, DropPerTenThousand) {
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  const uint32_t kDropPerTenThousandForLb = 1000;
+  const double kDropRateForLb = kDropPerTenThousandForLb / 10000.0;
+  const double kErrorTolerance = 0.05;
+  const size_t kNumRpcs = ComputeIdealNumRpcs(kDropRateForLb, kErrorTolerance);
+  // The ADS response contains one drop category.
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  args.drop_categories = {{kLbDropType, kDropPerTenThousandForLb}};
+  args.drop_denominator = FractionalPercent::TEN_THOUSAND;
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  WaitForAllBackends();
+  // Send kNumRpcs RPCs and count the drops.
+  size_t num_drops = 0;
+  for (size_t i = 0; i < kNumRpcs; ++i) {
+    EchoResponse response;
+    const Status status = SendRpc(RpcOptions(), &response);
+    if (!status.ok() &&
+        absl::StartsWith(status.error_message(), "EDS-configured drop: ")) {
+      ++num_drops;
+    } else {
+      EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
+                               << " message=" << status.error_message();
+      EXPECT_EQ(response.message(), kRequestMessage);
+    }
+  }
+  // The drop rate should be roughly equal to the expectation.
+  const double seen_drop_rate = static_cast<double>(num_drops) / kNumRpcs;
+  EXPECT_THAT(seen_drop_rate,
+              ::testing::DoubleNear(kDropRateForLb, kErrorTolerance));
+}
+
+// Tests that drop is working correctly after update.
+TEST_P(DropTest, Update) {
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  const uint32_t kDropPerMillionForLb = 100000;
+  const uint32_t kDropPerMillionForThrottle = 200000;
+  const double kErrorTolerance = 0.05;
+  const double kDropRateForLb = kDropPerMillionForLb / 1000000.0;
+  const double kDropRateForThrottle = kDropPerMillionForThrottle / 1000000.0;
+  const double kDropRateForLbAndThrottle =
+      kDropRateForLb + (1 - kDropRateForLb) * kDropRateForThrottle;
+  const size_t kNumRpcsLbOnly =
+      ComputeIdealNumRpcs(kDropRateForLb, kErrorTolerance);
+  const size_t kNumRpcsBoth =
+      ComputeIdealNumRpcs(kDropRateForLbAndThrottle, kErrorTolerance);
+  // The first ADS response contains one drop category.
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  args.drop_categories = {{kLbDropType, kDropPerMillionForLb}};
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  WaitForAllBackends();
+  // Send kNumRpcsLbOnly RPCs and count the drops.
+  size_t num_drops = 0;
+  gpr_log(GPR_INFO, "========= BEFORE FIRST BATCH ==========");
+  for (size_t i = 0; i < kNumRpcsLbOnly; ++i) {
+    EchoResponse response;
+    const Status status = SendRpc(RpcOptions(), &response);
+    if (!status.ok() &&
+        absl::StartsWith(status.error_message(), "EDS-configured drop: ")) {
+      ++num_drops;
+    } else {
+      EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
+                               << " message=" << status.error_message();
+      EXPECT_EQ(response.message(), kRequestMessage);
+    }
+  }
+  gpr_log(GPR_INFO, "========= DONE WITH FIRST BATCH ==========");
+  // The drop rate should be roughly equal to the expectation.
+  double seen_drop_rate = static_cast<double>(num_drops) / kNumRpcsLbOnly;
+  gpr_log(GPR_INFO, "First batch drop rate %f", seen_drop_rate);
+  EXPECT_THAT(seen_drop_rate,
+              ::testing::DoubleNear(kDropRateForLb, kErrorTolerance));
+  // The second ADS response contains two drop categories, send an update EDS
+  // response.
+  args.drop_categories = {{kLbDropType, kDropPerMillionForLb},
+                          {kThrottleDropType, kDropPerMillionForThrottle}};
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  // Wait until the drop rate increases to the middle of the two configs,
+  // which implies that the update has been in effect.
+  const double kDropRateThreshold =
+      (kDropRateForLb + kDropRateForLbAndThrottle) / 2;
+  size_t num_rpcs = kNumRpcsBoth;
+  while (seen_drop_rate < kDropRateThreshold) {
+    EchoResponse response;
+    const Status status = SendRpc(RpcOptions(), &response);
+    ++num_rpcs;
+    if (!status.ok() &&
+        absl::StartsWith(status.error_message(), "EDS-configured drop: ")) {
+      ++num_drops;
+    } else {
+      EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
+                               << " message=" << status.error_message();
+      EXPECT_EQ(response.message(), kRequestMessage);
+    }
+    seen_drop_rate = static_cast<double>(num_drops) / num_rpcs;
+  }
+  // Send kNumRpcsBoth RPCs and count the drops.
+  num_drops = 0;
+  gpr_log(GPR_INFO, "========= BEFORE SECOND BATCH ==========");
+  for (size_t i = 0; i < kNumRpcsBoth; ++i) {
+    EchoResponse response;
+    const Status status = SendRpc(RpcOptions(), &response);
+    if (!status.ok() &&
+        absl::StartsWith(status.error_message(), "EDS-configured drop: ")) {
+      ++num_drops;
+    } else {
+      EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
+                               << " message=" << status.error_message();
+      EXPECT_EQ(response.message(), kRequestMessage);
+    }
+  }
+  gpr_log(GPR_INFO, "========= DONE WITH SECOND BATCH ==========");
+  // The new drop rate should be roughly equal to the expectation.
+  seen_drop_rate = static_cast<double>(num_drops) / kNumRpcsBoth;
+  gpr_log(GPR_INFO, "Second batch drop rate %f", seen_drop_rate);
+  EXPECT_THAT(seen_drop_rate, ::testing::DoubleNear(kDropRateForLbAndThrottle,
+                                                    kErrorTolerance));
+}
+
+// Tests that all the RPCs are dropped if any drop category drops 100%.
+TEST_P(DropTest, DropAll) {
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  const size_t kNumRpcs = 1000;
+  const uint32_t kDropPerMillionForLb = 100000;
+  const uint32_t kDropPerMillionForThrottle = 1000000;
+  // The ADS response contains two drop categories.
+  EdsResourceArgs args;
+  args.drop_categories = {{kLbDropType, kDropPerMillionForLb},
+                          {kThrottleDropType, kDropPerMillionForThrottle}};
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  // Send kNumRpcs RPCs and all of them are dropped.
+  for (size_t i = 0; i < kNumRpcs; ++i) {
+    EchoResponse response;
+    const Status status = SendRpc(RpcOptions(), &response);
+    EXPECT_EQ(status.error_code(), StatusCode::UNAVAILABLE);
+    EXPECT_THAT(status.error_message(),
+                ::testing::StartsWith("EDS-configured drop: "));
+  }
+}
+
+class BalancerUpdateTest : public XdsEnd2endTest {
+ public:
+  BalancerUpdateTest() : XdsEnd2endTest(4, 3) {}
+};
+
+// Tests that the old LB call is still used after the balancer address update
+// as long as that call is still alive.
+TEST_P(BalancerUpdateTest, UpdateBalancersButKeepUsingOriginalBalancer) {
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  EdsResourceArgs args({{"locality0", CreateEndpointsForBackends(0, 1)}});
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  args = EdsResourceArgs({{"locality0", CreateEndpointsForBackends(1, 2)}});
+  balancers_[1]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  // Wait until the first backend is ready.
+  WaitForBackend(0);
+  // Send 10 requests.
+  gpr_log(GPR_INFO, "========= BEFORE FIRST BATCH ==========");
+  CheckRpcSendOk(10);
+  gpr_log(GPR_INFO, "========= DONE WITH FIRST BATCH ==========");
+  // All 10 requests should have gone to the first backend.
+  EXPECT_EQ(10U, backends_[0]->backend_service()->request_count());
+  // The ADS service of balancer 0 sent at least 1 response.
+  EXPECT_GT(balancers_[0]->ads_service()->eds_response_state().state,
+            AdsServiceImpl::ResponseState::NOT_SENT);
+  EXPECT_EQ(balancers_[1]->ads_service()->eds_response_state().state,
+            AdsServiceImpl::ResponseState::NOT_SENT)
+      << "Error Message:"
+      << balancers_[1]->ads_service()->eds_response_state().error_message;
+  EXPECT_EQ(balancers_[2]->ads_service()->eds_response_state().state,
+            AdsServiceImpl::ResponseState::NOT_SENT)
+      << "Error Message:"
+      << balancers_[2]->ads_service()->eds_response_state().error_message;
+  gpr_log(GPR_INFO, "========= ABOUT TO UPDATE 1 ==========");
+  SetNextResolutionForLbChannel({balancers_[1]->port()});
+  gpr_log(GPR_INFO, "========= UPDATE 1 DONE ==========");
+  EXPECT_EQ(0U, backends_[1]->backend_service()->request_count());
+  gpr_timespec deadline = gpr_time_add(
+      gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_millis(10000, GPR_TIMESPAN));
+  // Send 10 seconds worth of RPCs
+  do {
+    CheckRpcSendOk();
+  } while (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), deadline) < 0);
+  // The current LB call is still working, so xds continued using it to the
+  // first balancer, which doesn't assign the second backend.
+  EXPECT_EQ(0U, backends_[1]->backend_service()->request_count());
+  // The ADS service of balancer 0 sent at least 1 response.
+  EXPECT_GT(balancers_[0]->ads_service()->eds_response_state().state,
+            AdsServiceImpl::ResponseState::NOT_SENT);
+  EXPECT_EQ(balancers_[1]->ads_service()->eds_response_state().state,
+            AdsServiceImpl::ResponseState::NOT_SENT)
+      << "Error Message:"
+      << balancers_[1]->ads_service()->eds_response_state().error_message;
+  EXPECT_EQ(balancers_[2]->ads_service()->eds_response_state().state,
+            AdsServiceImpl::ResponseState::NOT_SENT)
+      << "Error Message:"
+      << balancers_[2]->ads_service()->eds_response_state().error_message;
+}
+
+// Tests that the old LB call is still used after multiple balancer address
+// updates as long as that call is still alive. Send an update with the same
+// set of LBs as the one in SetUp() in order to verify that the LB channel
+// inside xds keeps the initial connection (which by definition is also
+// present in the update).
+TEST_P(BalancerUpdateTest, Repeated) {
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  EdsResourceArgs args({{"locality0", CreateEndpointsForBackends(0, 1)}});
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  args = EdsResourceArgs({{"locality0", CreateEndpointsForBackends(1, 2)}});
+  balancers_[1]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  // Wait until the first backend is ready.
+  WaitForBackend(0);
+  // Send 10 requests.
+  gpr_log(GPR_INFO, "========= BEFORE FIRST BATCH ==========");
+  CheckRpcSendOk(10);
+  gpr_log(GPR_INFO, "========= DONE WITH FIRST BATCH ==========");
+  // All 10 requests should have gone to the first backend.
+  EXPECT_EQ(10U, backends_[0]->backend_service()->request_count());
+  // The ADS service of balancer 0 sent at least 1 response.
+  EXPECT_GT(balancers_[0]->ads_service()->eds_response_state().state,
+            AdsServiceImpl::ResponseState::NOT_SENT);
+  EXPECT_EQ(balancers_[1]->ads_service()->eds_response_state().state,
+            AdsServiceImpl::ResponseState::NOT_SENT)
+      << "Error Message:"
+      << balancers_[1]->ads_service()->eds_response_state().error_message;
+  EXPECT_EQ(balancers_[2]->ads_service()->eds_response_state().state,
+            AdsServiceImpl::ResponseState::NOT_SENT)
+      << "Error Message:"
+      << balancers_[2]->ads_service()->eds_response_state().error_message;
+  std::vector<int> ports;
+  ports.emplace_back(balancers_[0]->port());
+  ports.emplace_back(balancers_[1]->port());
+  ports.emplace_back(balancers_[2]->port());
+  gpr_log(GPR_INFO, "========= ABOUT TO UPDATE 1 ==========");
+  SetNextResolutionForLbChannel(ports);
+  gpr_log(GPR_INFO, "========= UPDATE 1 DONE ==========");
+  EXPECT_EQ(0U, backends_[1]->backend_service()->request_count());
+  gpr_timespec deadline = gpr_time_add(
+      gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_millis(10000, GPR_TIMESPAN));
+  // Send 10 seconds worth of RPCs
+  do {
+    CheckRpcSendOk();
+  } while (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), deadline) < 0);
+  // xds continued using the original LB call to the first balancer, which
+  // doesn't assign the second backend.
+  EXPECT_EQ(0U, backends_[1]->backend_service()->request_count());
+  ports.clear();
+  ports.emplace_back(balancers_[0]->port());
+  ports.emplace_back(balancers_[1]->port());
+  gpr_log(GPR_INFO, "========= ABOUT TO UPDATE 2 ==========");
+  SetNextResolutionForLbChannel(ports);
+  gpr_log(GPR_INFO, "========= UPDATE 2 DONE ==========");
+  EXPECT_EQ(0U, backends_[1]->backend_service()->request_count());
+  deadline = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
+                          gpr_time_from_millis(10000, GPR_TIMESPAN));
+  // Send 10 seconds worth of RPCs
+  do {
+    CheckRpcSendOk();
+  } while (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), deadline) < 0);
+  // xds continued using the original LB call to the first balancer, which
+  // doesn't assign the second backend.
+  EXPECT_EQ(0U, backends_[1]->backend_service()->request_count());
+}
+
+// Tests that if the balancer is down, the RPCs will still be sent to the
+// backends according to the last balancer response, until a new balancer is
+// reachable.
+TEST_P(BalancerUpdateTest, DeadUpdate) {
+  SetNextResolution({});
+  SetNextResolutionForLbChannel({balancers_[0]->port()});
+  EdsResourceArgs args({{"locality0", CreateEndpointsForBackends(0, 1)}});
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  args = EdsResourceArgs({{"locality0", CreateEndpointsForBackends(1, 2)}});
+  balancers_[1]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  // Start servers and send 10 RPCs per server.
+  gpr_log(GPR_INFO, "========= BEFORE FIRST BATCH ==========");
+  CheckRpcSendOk(10);
+  gpr_log(GPR_INFO, "========= DONE WITH FIRST BATCH ==========");
+  // All 10 requests should have gone to the first backend.
+  EXPECT_EQ(10U, backends_[0]->backend_service()->request_count());
+  // The ADS service of balancer 0 sent at least 1 response.
+  EXPECT_GT(balancers_[0]->ads_service()->eds_response_state().state,
+            AdsServiceImpl::ResponseState::NOT_SENT);
+  EXPECT_EQ(balancers_[1]->ads_service()->eds_response_state().state,
+            AdsServiceImpl::ResponseState::NOT_SENT)
+      << "Error Message:"
+      << balancers_[1]->ads_service()->eds_response_state().error_message;
+  EXPECT_EQ(balancers_[2]->ads_service()->eds_response_state().state,
+            AdsServiceImpl::ResponseState::NOT_SENT)
+      << "Error Message:"
+      << balancers_[2]->ads_service()->eds_response_state().error_message;
+  // Kill balancer 0
+  gpr_log(GPR_INFO, "********** ABOUT TO KILL BALANCER 0 *************");
+  balancers_[0]->Shutdown();
+  gpr_log(GPR_INFO, "********** KILLED BALANCER 0 *************");
+  // This is serviced by the existing child policy.
+  gpr_log(GPR_INFO, "========= BEFORE SECOND BATCH ==========");
+  CheckRpcSendOk(10);
+  gpr_log(GPR_INFO, "========= DONE WITH SECOND BATCH ==========");
+  // All 10 requests should again have gone to the first backend.
+  EXPECT_EQ(20U, backends_[0]->backend_service()->request_count());
+  EXPECT_EQ(0U, backends_[1]->backend_service()->request_count());
+  // The ADS service of no balancers sent anything
+  EXPECT_EQ(balancers_[0]->ads_service()->eds_response_state().state,
+            AdsServiceImpl::ResponseState::NOT_SENT)
+      << "Error Message:"
+      << balancers_[0]->ads_service()->eds_response_state().error_message;
+  EXPECT_EQ(balancers_[1]->ads_service()->eds_response_state().state,
+            AdsServiceImpl::ResponseState::NOT_SENT)
+      << "Error Message:"
+      << balancers_[1]->ads_service()->eds_response_state().error_message;
+  EXPECT_EQ(balancers_[2]->ads_service()->eds_response_state().state,
+            AdsServiceImpl::ResponseState::NOT_SENT)
+      << "Error Message:"
+      << balancers_[2]->ads_service()->eds_response_state().error_message;
+  gpr_log(GPR_INFO, "========= ABOUT TO UPDATE 1 ==========");
+  SetNextResolutionForLbChannel({balancers_[1]->port()});
+  gpr_log(GPR_INFO, "========= UPDATE 1 DONE ==========");
+  // Wait until update has been processed, as signaled by the second backend
+  // receiving a request. In the meantime, the client continues to be serviced
+  // (by the first backend) without interruption.
+  EXPECT_EQ(0U, backends_[1]->backend_service()->request_count());
+  WaitForBackend(1);
+  // This is serviced by the updated RR policy
+  backends_[1]->backend_service()->ResetCounters();
+  gpr_log(GPR_INFO, "========= BEFORE THIRD BATCH ==========");
+  CheckRpcSendOk(10);
+  gpr_log(GPR_INFO, "========= DONE WITH THIRD BATCH ==========");
+  // All 10 requests should have gone to the second backend.
+  EXPECT_EQ(10U, backends_[1]->backend_service()->request_count());
+  // The ADS service of balancer 1 sent at least 1 response.
+  EXPECT_EQ(balancers_[0]->ads_service()->eds_response_state().state,
+            AdsServiceImpl::ResponseState::NOT_SENT)
+      << "Error Message:"
+      << balancers_[0]->ads_service()->eds_response_state().error_message;
+  EXPECT_GT(balancers_[1]->ads_service()->eds_response_state().state,
+            AdsServiceImpl::ResponseState::NOT_SENT);
+  EXPECT_EQ(balancers_[2]->ads_service()->eds_response_state().state,
+            AdsServiceImpl::ResponseState::NOT_SENT)
+      << "Error Message:"
+      << balancers_[2]->ads_service()->eds_response_state().error_message;
+}
+
+class ClientLoadReportingTest : public XdsEnd2endTest {
+ public:
+  ClientLoadReportingTest() : XdsEnd2endTest(4, 1, 3) {}
+};
+
+// Tests that the load report received at the balancer is correct.
+TEST_P(ClientLoadReportingTest, Vanilla) {
+  if (GetParam().use_fake_resolver()) {
+    balancers_[0]->lrs_service()->set_cluster_names({kServerName});
+  }
+  SetNextResolution({});
+  SetNextResolutionForLbChannel({balancers_[0]->port()});
+  const size_t kNumRpcsPerAddress = 10;
+  const size_t kNumFailuresPerAddress = 3;
+  // TODO(juanlishen): Partition the backends after multiple localities is
+  // tested.
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  // Wait until all backends are ready.
+  int num_ok = 0;
+  int num_failure = 0;
+  int num_drops = 0;
+  std::tie(num_ok, num_failure, num_drops) = WaitForAllBackends();
+  // Send kNumRpcsPerAddress RPCs per server.
+  CheckRpcSendOk(kNumRpcsPerAddress * num_backends_);
+  CheckRpcSendFailure(CheckRpcSendFailureOptions()
+                          .set_times(kNumFailuresPerAddress * num_backends_)
+                          .set_rpc_options(RpcOptions().set_server_fail(true)));
+  // Check that each backend got the right number of requests.
+  for (size_t i = 0; i < backends_.size(); ++i) {
+    EXPECT_EQ(kNumRpcsPerAddress + kNumFailuresPerAddress,
+              backends_[i]->backend_service()->request_count());
+  }
+  // The load report received at the balancer should be correct.
+  std::vector<ClientStats> load_report =
+      balancers_[0]->lrs_service()->WaitForLoadReport();
+  ASSERT_EQ(load_report.size(), 1UL);
+  ClientStats& client_stats = load_report.front();
+  EXPECT_EQ(kNumRpcsPerAddress * num_backends_ + num_ok,
+            client_stats.total_successful_requests());
+  EXPECT_EQ(0U, client_stats.total_requests_in_progress());
+  EXPECT_EQ((kNumRpcsPerAddress + kNumFailuresPerAddress) * num_backends_ +
+                num_ok + num_failure,
+            client_stats.total_issued_requests());
+  EXPECT_EQ(kNumFailuresPerAddress * num_backends_ + num_failure,
+            client_stats.total_error_requests());
+  EXPECT_EQ(0U, client_stats.total_dropped_requests());
+  // The LRS service got a single request, and sent a single response.
+  EXPECT_EQ(1U, balancers_[0]->lrs_service()->request_count());
+  EXPECT_EQ(1U, balancers_[0]->lrs_service()->response_count());
+}
+
+// Tests send_all_clusters.
+TEST_P(ClientLoadReportingTest, SendAllClusters) {
+  balancers_[0]->lrs_service()->set_send_all_clusters(true);
+  SetNextResolution({});
+  SetNextResolutionForLbChannel({balancers_[0]->port()});
+  const size_t kNumRpcsPerAddress = 10;
+  const size_t kNumFailuresPerAddress = 3;
+  // TODO(juanlishen): Partition the backends after multiple localities is
+  // tested.
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  // Wait until all backends are ready.
+  int num_ok = 0;
+  int num_failure = 0;
+  int num_drops = 0;
+  std::tie(num_ok, num_failure, num_drops) = WaitForAllBackends();
+  // Send kNumRpcsPerAddress RPCs per server.
+  CheckRpcSendOk(kNumRpcsPerAddress * num_backends_);
+  CheckRpcSendFailure(CheckRpcSendFailureOptions()
+                          .set_times(kNumFailuresPerAddress * num_backends_)
+                          .set_rpc_options(RpcOptions().set_server_fail(true)));
+  // Check that each backend got the right number of requests.
+  for (size_t i = 0; i < backends_.size(); ++i) {
+    EXPECT_EQ(kNumRpcsPerAddress + kNumFailuresPerAddress,
+              backends_[i]->backend_service()->request_count());
+  }
+  // The load report received at the balancer should be correct.
+  std::vector<ClientStats> load_report =
+      balancers_[0]->lrs_service()->WaitForLoadReport();
+  ASSERT_EQ(load_report.size(), 1UL);
+  ClientStats& client_stats = load_report.front();
+  EXPECT_EQ(kNumRpcsPerAddress * num_backends_ + num_ok,
+            client_stats.total_successful_requests());
+  EXPECT_EQ(0U, client_stats.total_requests_in_progress());
+  EXPECT_EQ((kNumRpcsPerAddress + kNumFailuresPerAddress) * num_backends_ +
+                num_ok + num_failure,
+            client_stats.total_issued_requests());
+  EXPECT_EQ(kNumFailuresPerAddress * num_backends_ + num_failure,
+            client_stats.total_error_requests());
+  EXPECT_EQ(0U, client_stats.total_dropped_requests());
+  // The LRS service got a single request, and sent a single response.
+  EXPECT_EQ(1U, balancers_[0]->lrs_service()->request_count());
+  EXPECT_EQ(1U, balancers_[0]->lrs_service()->response_count());
+}
+
+// Tests that we don't include stats for clusters that are not requested
+// by the LRS server.
+TEST_P(ClientLoadReportingTest, HonorsClustersRequestedByLrsServer) {
+  balancers_[0]->lrs_service()->set_cluster_names({"bogus"});
+  SetNextResolution({});
+  SetNextResolutionForLbChannel({balancers_[0]->port()});
+  const size_t kNumRpcsPerAddress = 100;
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  // Wait until all backends are ready.
+  int num_ok = 0;
+  int num_failure = 0;
+  int num_drops = 0;
+  std::tie(num_ok, num_failure, num_drops) = WaitForAllBackends();
+  // Send kNumRpcsPerAddress RPCs per server.
+  CheckRpcSendOk(kNumRpcsPerAddress * num_backends_);
+  // Each backend should have gotten 100 requests.
+  for (size_t i = 0; i < backends_.size(); ++i) {
+    EXPECT_EQ(kNumRpcsPerAddress,
+              backends_[i]->backend_service()->request_count());
+  }
+  // The LRS service got a single request, and sent a single response.
+  EXPECT_EQ(1U, balancers_[0]->lrs_service()->request_count());
+  EXPECT_EQ(1U, balancers_[0]->lrs_service()->response_count());
+  // The load report received at the balancer should be correct.
+  std::vector<ClientStats> load_report =
+      balancers_[0]->lrs_service()->WaitForLoadReport();
+  ASSERT_EQ(load_report.size(), 0UL);
+}
+
+// Tests that if the balancer restarts, the client load report contains the
+// stats before and after the restart correctly.
+TEST_P(ClientLoadReportingTest, BalancerRestart) {
+  if (GetParam().use_fake_resolver()) {
+    balancers_[0]->lrs_service()->set_cluster_names({kServerName});
+  }
+  SetNextResolution({});
+  SetNextResolutionForLbChannel({balancers_[0]->port()});
+  const size_t kNumBackendsFirstPass = backends_.size() / 2;
+  const size_t kNumBackendsSecondPass =
+      backends_.size() - kNumBackendsFirstPass;
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends(0, kNumBackendsFirstPass)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  // Wait until all backends returned by the balancer are ready.
+  int num_ok = 0;
+  int num_failure = 0;
+  int num_drops = 0;
+  std::tie(num_ok, num_failure, num_drops) =
+      WaitForAllBackends(/* start_index */ 0,
+                         /* stop_index */ kNumBackendsFirstPass);
+  std::vector<ClientStats> load_report =
+      balancers_[0]->lrs_service()->WaitForLoadReport();
+  ASSERT_EQ(load_report.size(), 1UL);
+  ClientStats client_stats = std::move(load_report.front());
+  EXPECT_EQ(static_cast<size_t>(num_ok),
+            client_stats.total_successful_requests());
+  EXPECT_EQ(0U, client_stats.total_requests_in_progress());
+  EXPECT_EQ(0U, client_stats.total_error_requests());
+  EXPECT_EQ(0U, client_stats.total_dropped_requests());
+  // Shut down the balancer.
+  balancers_[0]->Shutdown();
+  // We should continue using the last EDS response we received from the
+  // balancer before it was shut down.
+  // Note: We need to use WaitForAllBackends() here instead of just
+  // CheckRpcSendOk(kNumBackendsFirstPass), because when the balancer
+  // shuts down, the XdsClient will generate an error to the
+  // ServiceConfigWatcher, which will cause the xds resolver to send a
+  // no-op update to the LB policy.  When this update gets down to the
+  // round_robin child policy for the locality, it will generate a new
+  // subchannel list, which resets the start index randomly.  So we need
+  // to be a little more permissive here to avoid spurious failures.
+  ResetBackendCounters();
+  int num_started = std::get<0>(WaitForAllBackends(
+      /* start_index */ 0, /* stop_index */ kNumBackendsFirstPass));
+  // Now restart the balancer, this time pointing to the new backends.
+  balancers_[0]->Start();
+  args = EdsResourceArgs({
+      {"locality0", CreateEndpointsForBackends(kNumBackendsFirstPass)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  // Wait for queries to start going to one of the new backends.
+  // This tells us that we're now using the new serverlist.
+  std::tie(num_ok, num_failure, num_drops) =
+      WaitForAllBackends(/* start_index */ kNumBackendsFirstPass);
+  num_started += num_ok + num_failure + num_drops;
+  // Send one RPC per backend.
+  CheckRpcSendOk(kNumBackendsSecondPass);
+  num_started += kNumBackendsSecondPass;
+  // Check client stats.
+  load_report = balancers_[0]->lrs_service()->WaitForLoadReport();
+  ASSERT_EQ(load_report.size(), 1UL);
+  client_stats = std::move(load_report.front());
+  EXPECT_EQ(num_started, client_stats.total_successful_requests());
+  EXPECT_EQ(0U, client_stats.total_requests_in_progress());
+  EXPECT_EQ(0U, client_stats.total_error_requests());
+  EXPECT_EQ(0U, client_stats.total_dropped_requests());
+}
+
+class ClientLoadReportingWithDropTest : public XdsEnd2endTest {
+ public:
+  ClientLoadReportingWithDropTest() : XdsEnd2endTest(4, 1, 20) {}
+};
+
+// Tests that the drop stats are correctly reported by client load reporting.
+TEST_P(ClientLoadReportingWithDropTest, Vanilla) {
+  if (GetParam().use_fake_resolver()) {
+    balancers_[0]->lrs_service()->set_cluster_names({kServerName});
+  }
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  const uint32_t kDropPerMillionForLb = 100000;
+  const uint32_t kDropPerMillionForThrottle = 200000;
+  const double kErrorTolerance = 0.05;
+  const double kDropRateForLb = kDropPerMillionForLb / 1000000.0;
+  const double kDropRateForThrottle = kDropPerMillionForThrottle / 1000000.0;
+  const double kDropRateForLbAndThrottle =
+      kDropRateForLb + (1 - kDropRateForLb) * kDropRateForThrottle;
+  const size_t kNumRpcs =
+      ComputeIdealNumRpcs(kDropRateForLbAndThrottle, kErrorTolerance);
+  // The ADS response contains two drop categories.
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  args.drop_categories = {{kLbDropType, kDropPerMillionForLb},
+                          {kThrottleDropType, kDropPerMillionForThrottle}};
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  int num_ok = 0;
+  int num_failure = 0;
+  int num_drops = 0;
+  std::tie(num_ok, num_failure, num_drops) = WaitForAllBackends();
+  const size_t num_warmup = num_ok + num_failure + num_drops;
+  // Send kNumRpcs RPCs and count the drops.
+  for (size_t i = 0; i < kNumRpcs; ++i) {
+    EchoResponse response;
+    const Status status = SendRpc(RpcOptions(), &response);
+    if (!status.ok() &&
+        absl::StartsWith(status.error_message(), "EDS-configured drop: ")) {
+      ++num_drops;
+    } else {
+      EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
+                               << " message=" << status.error_message();
+      EXPECT_EQ(response.message(), kRequestMessage);
+    }
+  }
+  // The drop rate should be roughly equal to the expectation.
+  const double seen_drop_rate = static_cast<double>(num_drops) / kNumRpcs;
+  EXPECT_THAT(seen_drop_rate, ::testing::DoubleNear(kDropRateForLbAndThrottle,
+                                                    kErrorTolerance));
+  // Check client stats.
+  const size_t total_rpc = num_warmup + kNumRpcs;
+  ClientStats client_stats;
+  do {
+    std::vector<ClientStats> load_reports =
+        balancers_[0]->lrs_service()->WaitForLoadReport();
+    for (const auto& load_report : load_reports) {
+      client_stats += load_report;
+    }
+  } while (client_stats.total_issued_requests() +
+               client_stats.total_dropped_requests() <
+           total_rpc);
+  EXPECT_EQ(num_drops, client_stats.total_dropped_requests());
+  EXPECT_THAT(static_cast<double>(client_stats.dropped_requests(kLbDropType)) /
+                  total_rpc,
+              ::testing::DoubleNear(kDropRateForLb, kErrorTolerance));
+  EXPECT_THAT(
+      static_cast<double>(client_stats.dropped_requests(kThrottleDropType)) /
+          (total_rpc * (1 - kDropRateForLb)),
+      ::testing::DoubleNear(kDropRateForThrottle, kErrorTolerance));
+}
+
+class FaultInjectionTest : public XdsEnd2endTest {
+ public:
+  FaultInjectionTest() : XdsEnd2endTest(1, 1) {}
+
+  // Builds a Listener with Fault Injection filter config. If the http_fault
+  // is nullptr, then assign an empty filter config. This filter config is
+  // required to enable the fault injection features.
+  static Listener BuildListenerWithFaultInjection(
+      const HTTPFault& http_fault = HTTPFault()) {
+    HttpConnectionManager http_connection_manager;
+    Listener listener;
+    listener.set_name(kServerName);
+    HttpFilter* fault_filter = http_connection_manager.add_http_filters();
+    fault_filter->set_name("envoy.fault");
+    fault_filter->mutable_typed_config()->PackFrom(http_fault);
+    HttpFilter* router_filter = http_connection_manager.add_http_filters();
+    router_filter->set_name("router");
+    router_filter->mutable_typed_config()->PackFrom(
+        envoy::extensions::filters::http::router::v3::Router());
+    listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
+        http_connection_manager);
+    return listener;
+  }
+
+  RouteConfiguration BuildRouteConfigurationWithFaultInjection(
+      const HTTPFault& http_fault) {
+    // Package as Any
+    google::protobuf::Any filter_config;
+    filter_config.PackFrom(http_fault);
+    // Plug into the RouteConfiguration
+    RouteConfiguration new_route_config = default_route_config_;
+    auto* config_map = new_route_config.mutable_virtual_hosts(0)
+                           ->mutable_routes(0)
+                           ->mutable_typed_per_filter_config();
+    (*config_map)["envoy.fault"] = std::move(filter_config);
+    return new_route_config;
+  }
+
+  void SetFilterConfig(HTTPFault& http_fault) {
+    switch (GetParam().filter_config_setup()) {
+      case TestType::FilterConfigSetup::kRouteOverride: {
+        Listener listener = BuildListenerWithFaultInjection();
+        RouteConfiguration route =
+            BuildRouteConfigurationWithFaultInjection(http_fault);
+        SetListenerAndRouteConfiguration(0, listener, route);
+        break;
+      }
+      case TestType::FilterConfigSetup::kHTTPConnectionManagerOriginal: {
+        Listener listener = BuildListenerWithFaultInjection(http_fault);
+        SetListenerAndRouteConfiguration(0, listener, default_route_config_);
+      }
+    };
+  }
+};
+
+// Test to ensure the most basic fault injection config works.
+TEST_P(FaultInjectionTest, XdsFaultInjectionAlwaysAbort) {
+  const uint32_t kAbortPercentagePerHundred = 100;
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Construct the fault injection filter config
+  HTTPFault http_fault;
+  auto* abort_percentage = http_fault.mutable_abort()->mutable_percentage();
+  abort_percentage->set_numerator(kAbortPercentagePerHundred);
+  abort_percentage->set_denominator(FractionalPercent::HUNDRED);
+  http_fault.mutable_abort()->set_grpc_status(
+      static_cast<uint32_t>(StatusCode::ABORTED));
+  // Config fault injection via different setup
+  SetFilterConfig(http_fault);
+  // Fire several RPCs, and expect all of them to be aborted.
+  CheckRpcSendFailure(
+      CheckRpcSendFailureOptions()
+          .set_times(5)
+          .set_rpc_options(RpcOptions().set_wait_for_ready(true))
+          .set_expected_error_code(StatusCode::ABORTED));
+}
+
+// Without the listener config, the fault injection won't be enabled.
+TEST_P(FaultInjectionTest, XdsFaultInjectionWithoutListenerFilter) {
+  const uint32_t kAbortPercentagePerHundred = 100;
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Create an EDS resource
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  // Construct the fault injection filter config
+  HTTPFault http_fault;
+  auto* abort_percentage = http_fault.mutable_abort()->mutable_percentage();
+  abort_percentage->set_numerator(kAbortPercentagePerHundred);
+  abort_percentage->set_denominator(FractionalPercent::HUNDRED);
+  http_fault.mutable_abort()->set_grpc_status(
+      static_cast<uint32_t>(StatusCode::ABORTED));
+  // Turn on fault injection
+  RouteConfiguration route =
+      BuildRouteConfigurationWithFaultInjection(http_fault);
+  SetListenerAndRouteConfiguration(0, default_listener_, route);
+  // Fire several RPCs, and expect all of them to be pass.
+  CheckRpcSendOk(5, RpcOptions().set_wait_for_ready(true));
+}
+
+TEST_P(FaultInjectionTest, XdsFaultInjectionPercentageAbort) {
+  const uint32_t kAbortPercentagePerHundred = 50;
+  const double kAbortRate = kAbortPercentagePerHundred / 100.0;
+  const double kErrorTolerance = 0.05;
+  const size_t kNumRpcs = ComputeIdealNumRpcs(kAbortRate, kErrorTolerance);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Create an EDS resource
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  // Construct the fault injection filter config
+  HTTPFault http_fault;
+  auto* abort_percentage = http_fault.mutable_abort()->mutable_percentage();
+  abort_percentage->set_numerator(kAbortPercentagePerHundred);
+  abort_percentage->set_denominator(FractionalPercent::HUNDRED);
+  http_fault.mutable_abort()->set_grpc_status(
+      static_cast<uint32_t>(StatusCode::ABORTED));
+  // Config fault injection via different setup
+  SetFilterConfig(http_fault);
+  // Send kNumRpcs RPCs and count the aborts.
+  int num_total = 0, num_ok = 0, num_failure = 0, num_aborted = 0;
+  for (size_t i = 0; i < kNumRpcs; ++i) {
+    SendRpcAndCount(&num_total, &num_ok, &num_failure, &num_aborted,
+                    RpcOptions(), "Fault injected");
+  }
+  EXPECT_EQ(kNumRpcs, num_total);
+  EXPECT_EQ(0, num_failure);
+  // The abort rate should be roughly equal to the expectation.
+  const double seen_abort_rate = static_cast<double>(num_aborted) / kNumRpcs;
+  EXPECT_THAT(seen_abort_rate,
+              ::testing::DoubleNear(kAbortRate, kErrorTolerance));
+}
+
+TEST_P(FaultInjectionTest, XdsFaultInjectionPercentageAbortViaHeaders) {
+  const uint32_t kAbortPercentageCap = 100;
+  const uint32_t kAbortPercentage = 50;
+  const double kAbortRate = kAbortPercentage / 100.0;
+  const double kErrorTolerance = 0.05;
+  const size_t kNumRpcs = ComputeIdealNumRpcs(kAbortRate, kErrorTolerance);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Create an EDS resource
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  // Construct the fault injection filter config
+  HTTPFault http_fault;
+  http_fault.mutable_abort()->mutable_header_abort();
+  http_fault.mutable_abort()->mutable_percentage()->set_numerator(
+      kAbortPercentageCap);
+  // Config fault injection via different setup
+  SetFilterConfig(http_fault);
+  // Send kNumRpcs RPCs and count the aborts.
+  std::vector<std::pair<std::string, std::string>> metadata = {
+      {"x-envoy-fault-abort-grpc-request", "10"},
+      {"x-envoy-fault-abort-percentage", std::to_string(kAbortPercentage)},
+  };
+  int num_total = 0, num_ok = 0, num_failure = 0, num_aborted = 0;
+  RpcOptions options = RpcOptions().set_metadata(metadata);
+  for (size_t i = 0; i < kNumRpcs; ++i) {
+    SendRpcAndCount(&num_total, &num_ok, &num_failure, &num_aborted, options,
+                    "Fault injected");
+  }
+  EXPECT_EQ(kNumRpcs, num_total);
+  EXPECT_EQ(0, num_failure);
+  // The abort rate should be roughly equal to the expectation.
+  const double seen_abort_rate = static_cast<double>(num_aborted) / kNumRpcs;
+  EXPECT_THAT(seen_abort_rate,
+              ::testing::DoubleNear(kAbortRate, kErrorTolerance));
+}
+
+TEST_P(FaultInjectionTest, XdsFaultInjectionPercentageDelay) {
+  const uint32_t kRpcTimeoutMilliseconds = grpc_test_slowdown_factor() * 3000;
+  const uint32_t kFixedDelaySeconds = 100;
+  const uint32_t kDelayPercentagePerHundred = 50;
+  const double kDelayRate = kDelayPercentagePerHundred / 100.0;
+  const double kErrorTolerance = 0.05;
+  const size_t kNumRpcs = ComputeIdealNumRpcs(kDelayRate, kErrorTolerance);
+  const size_t kMaxConcurrentRequests = kNumRpcs;
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Create an EDS resource
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  // Loosen the max concurrent request limit
+  Cluster cluster = default_cluster_;
+  auto* threshold = cluster.mutable_circuit_breakers()->add_thresholds();
+  threshold->set_priority(RoutingPriority::DEFAULT);
+  threshold->mutable_max_requests()->set_value(kMaxConcurrentRequests);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  // Construct the fault injection filter config
+  HTTPFault http_fault;
+  auto* delay_percentage = http_fault.mutable_delay()->mutable_percentage();
+  delay_percentage->set_numerator(kDelayPercentagePerHundred);
+  delay_percentage->set_denominator(FractionalPercent::HUNDRED);
+  auto* fixed_delay = http_fault.mutable_delay()->mutable_fixed_delay();
+  fixed_delay->set_seconds(kFixedDelaySeconds);
+  // Config fault injection via different setup
+  SetFilterConfig(http_fault);
+  // Send kNumRpcs RPCs and count the delays.
+  RpcOptions rpc_options = RpcOptions()
+                               .set_timeout_ms(kRpcTimeoutMilliseconds)
+                               .set_skip_cancelled_check(true);
+  std::vector<ConcurrentRpc> rpcs =
+      SendConcurrentRpcs(stub_.get(), kNumRpcs, rpc_options);
+  size_t num_delayed = 0;
+  for (auto& rpc : rpcs) {
+    if (rpc.status.error_code() == StatusCode::OK) continue;
+    EXPECT_EQ(StatusCode::DEADLINE_EXCEEDED, rpc.status.error_code());
+    ++num_delayed;
+  }
+  // The delay rate should be roughly equal to the expectation.
+  const double seen_delay_rate = static_cast<double>(num_delayed) / kNumRpcs;
+  EXPECT_THAT(seen_delay_rate,
+              ::testing::DoubleNear(kDelayRate, kErrorTolerance));
+}
+
+TEST_P(FaultInjectionTest, XdsFaultInjectionPercentageDelayViaHeaders) {
+  const uint32_t kFixedDelayMilliseconds = 100000;
+  const uint32_t kRpcTimeoutMilliseconds = grpc_test_slowdown_factor() * 3000;
+  const uint32_t kDelayPercentageCap = 100;
+  const uint32_t kDelayPercentage = 50;
+  const double kDelayRate = kDelayPercentage / 100.0;
+  const double kErrorTolerance = 0.05;
+  const size_t kNumRpcs = ComputeIdealNumRpcs(kDelayRate, kErrorTolerance);
+  const size_t kMaxConcurrentRequests = kNumRpcs;
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Create an EDS resource
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  // Loosen the max concurrent request limit
+  Cluster cluster = default_cluster_;
+  auto* threshold = cluster.mutable_circuit_breakers()->add_thresholds();
+  threshold->set_priority(RoutingPriority::DEFAULT);
+  threshold->mutable_max_requests()->set_value(kMaxConcurrentRequests);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  // Construct the fault injection filter config
+  HTTPFault http_fault;
+  http_fault.mutable_delay()->mutable_header_delay();
+  http_fault.mutable_delay()->mutable_percentage()->set_numerator(
+      kDelayPercentageCap);
+  // Config fault injection via different setup
+  SetFilterConfig(http_fault);
+  // Send kNumRpcs RPCs and count the delays.
+  std::vector<std::pair<std::string, std::string>> metadata = {
+      {"x-envoy-fault-delay-request", std::to_string(kFixedDelayMilliseconds)},
+      {"x-envoy-fault-delay-request-percentage",
+       std::to_string(kDelayPercentage)},
+  };
+  RpcOptions rpc_options = RpcOptions()
+                               .set_metadata(metadata)
+                               .set_timeout_ms(kRpcTimeoutMilliseconds)
+                               .set_skip_cancelled_check(true);
+  std::vector<ConcurrentRpc> rpcs =
+      SendConcurrentRpcs(stub_.get(), kNumRpcs, rpc_options);
+  size_t num_delayed = 0;
+  for (auto& rpc : rpcs) {
+    if (rpc.status.error_code() == StatusCode::OK) continue;
+    EXPECT_EQ(StatusCode::DEADLINE_EXCEEDED, rpc.status.error_code());
+    ++num_delayed;
+  }
+  // The delay rate should be roughly equal to the expectation.
+  const double seen_delay_rate = static_cast<double>(num_delayed) / kNumRpcs;
+  EXPECT_THAT(seen_delay_rate,
+              ::testing::DoubleNear(kDelayRate, kErrorTolerance));
+}
+
+TEST_P(FaultInjectionTest, XdsFaultInjectionAbortAfterDelayForStreamCall) {
+  const uint32_t kFixedDelaySeconds = 1;
+  const uint32_t kRpcTimeoutMilliseconds = 100 * 1000;  // 100s should not reach
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Create an EDS resource
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  // Construct the fault injection filter config
+  HTTPFault http_fault;
+  auto* abort_percentage = http_fault.mutable_abort()->mutable_percentage();
+  abort_percentage->set_numerator(100);  // Always inject ABORT!
+  abort_percentage->set_denominator(FractionalPercent::HUNDRED);
+  http_fault.mutable_abort()->set_grpc_status(
+      static_cast<uint32_t>(StatusCode::ABORTED));
+  auto* delay_percentage = http_fault.mutable_delay()->mutable_percentage();
+  delay_percentage->set_numerator(100);  // Always inject DELAY!
+  delay_percentage->set_denominator(FractionalPercent::HUNDRED);
+  auto* fixed_delay = http_fault.mutable_delay()->mutable_fixed_delay();
+  fixed_delay->set_seconds(kFixedDelaySeconds);
+  // Config fault injection via different setup
+  SetFilterConfig(http_fault);
+  // Send a stream RPC and check its status code
+  ClientContext context;
+  context.set_deadline(
+      grpc_timeout_milliseconds_to_deadline(kRpcTimeoutMilliseconds));
+  auto stream = stub_->BidiStream(&context);
+  stream->WritesDone();
+  auto status = stream->Finish();
+  EXPECT_EQ(StatusCode::ABORTED, status.error_code())
+      << status.error_message() << ", " << status.error_details() << ", "
+      << context.debug_error_string();
+}
+
+TEST_P(FaultInjectionTest, XdsFaultInjectionAlwaysDelayPercentageAbort) {
+  const uint32_t kAbortPercentagePerHundred = 50;
+  const double kAbortRate = kAbortPercentagePerHundred / 100.0;
+  const uint32_t kFixedDelaySeconds = 1;
+  const uint32_t kRpcTimeoutMilliseconds = 100 * 1000;  // 100s should not reach
+  const uint32_t kConnectionTimeoutMilliseconds =
+      10 * 1000;  // 10s should not reach
+  const double kErrorTolerance = 0.05;
+  const size_t kNumRpcs = ComputeIdealNumRpcs(kAbortRate, kErrorTolerance);
+  const size_t kMaxConcurrentRequests = kNumRpcs;
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Create an EDS resource
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  // Loosen the max concurrent request limit
+  Cluster cluster = default_cluster_;
+  auto* threshold = cluster.mutable_circuit_breakers()->add_thresholds();
+  threshold->set_priority(RoutingPriority::DEFAULT);
+  threshold->mutable_max_requests()->set_value(kMaxConcurrentRequests);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  // Construct the fault injection filter config
+  HTTPFault http_fault;
+  auto* abort_percentage = http_fault.mutable_abort()->mutable_percentage();
+  abort_percentage->set_numerator(kAbortPercentagePerHundred);
+  abort_percentage->set_denominator(FractionalPercent::HUNDRED);
+  http_fault.mutable_abort()->set_grpc_status(
+      static_cast<uint32_t>(StatusCode::ABORTED));
+  auto* delay_percentage = http_fault.mutable_delay()->mutable_percentage();
+  delay_percentage->set_numerator(1000000);  // Always inject DELAY!
+  delay_percentage->set_denominator(FractionalPercent::MILLION);
+  auto* fixed_delay = http_fault.mutable_delay()->mutable_fixed_delay();
+  fixed_delay->set_seconds(kFixedDelaySeconds);
+  // Config fault injection via different setup
+  SetFilterConfig(http_fault);
+  // Allow the channel to connect to one backends, so the herd of queued RPCs
+  // won't be executed on the same ExecCtx object and using the cached Now()
+  // value, which causes millisecond level delay error.
+  channel_->WaitForConnected(
+      grpc_timeout_milliseconds_to_deadline(kConnectionTimeoutMilliseconds));
+  // Send kNumRpcs RPCs and count the aborts.
+  int num_aborted = 0;
+  RpcOptions rpc_options = RpcOptions().set_timeout_ms(kRpcTimeoutMilliseconds);
+  std::vector<ConcurrentRpc> rpcs =
+      SendConcurrentRpcs(stub_.get(), kNumRpcs, rpc_options);
+  for (auto& rpc : rpcs) {
+    EXPECT_GE(rpc.elapsed_time, kFixedDelaySeconds * 1000);
+    if (rpc.status.error_code() == StatusCode::OK) continue;
+    EXPECT_EQ("Fault injected", rpc.status.error_message());
+    ++num_aborted;
+  }
+  // The abort rate should be roughly equal to the expectation.
+  const double seen_abort_rate = static_cast<double>(num_aborted) / kNumRpcs;
+  EXPECT_THAT(seen_abort_rate,
+              ::testing::DoubleNear(kAbortRate, kErrorTolerance));
+}
+
+// This test and the above test apply different denominators to delay and
+// abort. This ensures that we are using the right denominator for each
+// injected fault in our code.
+TEST_P(FaultInjectionTest,
+       XdsFaultInjectionAlwaysDelayPercentageAbortSwitchDenominator) {
+  const uint32_t kAbortPercentagePerMillion = 500000;
+  const double kAbortRate = kAbortPercentagePerMillion / 1000000.0;
+  const uint32_t kFixedDelaySeconds = 1;                // 1s
+  const uint32_t kRpcTimeoutMilliseconds = 100 * 1000;  // 100s should not reach
+  const uint32_t kConnectionTimeoutMilliseconds =
+      10 * 1000;  // 10s should not reach
+  const double kErrorTolerance = 0.05;
+  const size_t kNumRpcs = ComputeIdealNumRpcs(kAbortRate, kErrorTolerance);
+  const size_t kMaxConcurrentRequests = kNumRpcs;
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Create an EDS resource
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  // Loosen the max concurrent request limit
+  Cluster cluster = default_cluster_;
+  auto* threshold = cluster.mutable_circuit_breakers()->add_thresholds();
+  threshold->set_priority(RoutingPriority::DEFAULT);
+  threshold->mutable_max_requests()->set_value(kMaxConcurrentRequests);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  // Construct the fault injection filter config
+  HTTPFault http_fault;
+  auto* abort_percentage = http_fault.mutable_abort()->mutable_percentage();
+  abort_percentage->set_numerator(kAbortPercentagePerMillion);
+  abort_percentage->set_denominator(FractionalPercent::MILLION);
+  http_fault.mutable_abort()->set_grpc_status(
+      static_cast<uint32_t>(StatusCode::ABORTED));
+  auto* delay_percentage = http_fault.mutable_delay()->mutable_percentage();
+  delay_percentage->set_numerator(100);  // Always inject DELAY!
+  delay_percentage->set_denominator(FractionalPercent::HUNDRED);
+  auto* fixed_delay = http_fault.mutable_delay()->mutable_fixed_delay();
+  fixed_delay->set_seconds(kFixedDelaySeconds);
+  // Config fault injection via different setup
+  SetFilterConfig(http_fault);
+  // Allow the channel to connect to one backends, so the herd of queued RPCs
+  // won't be executed on the same ExecCtx object and using the cached Now()
+  // value, which causes millisecond level delay error.
+  channel_->WaitForConnected(
+      grpc_timeout_milliseconds_to_deadline(kConnectionTimeoutMilliseconds));
+  // Send kNumRpcs RPCs and count the aborts.
+  int num_aborted = 0;
+  RpcOptions rpc_options = RpcOptions().set_timeout_ms(kRpcTimeoutMilliseconds);
+  std::vector<ConcurrentRpc> rpcs =
+      SendConcurrentRpcs(stub_.get(), kNumRpcs, rpc_options);
+  for (auto& rpc : rpcs) {
+    EXPECT_GE(rpc.elapsed_time, kFixedDelaySeconds * 1000);
+    if (rpc.status.error_code() == StatusCode::OK) continue;
+    EXPECT_EQ("Fault injected", rpc.status.error_message());
+    ++num_aborted;
+  }
+  // The abort rate should be roughly equal to the expectation.
+  const double seen_abort_rate = static_cast<double>(num_aborted) / kNumRpcs;
+  EXPECT_THAT(seen_abort_rate,
+              ::testing::DoubleNear(kAbortRate, kErrorTolerance));
+}
+
+TEST_P(FaultInjectionTest, XdsFaultInjectionMaxFault) {
+  const uint32_t kMaxFault = 10;
+  const uint32_t kNumRpcs = 30;  // kNumRpcs should be bigger than kMaxFault
+  const uint32_t kRpcTimeoutMs = 4000;     // 4 seconds
+  const uint32_t kLongDelaySeconds = 100;  // 100 seconds
+  const uint32_t kAlwaysDelayPercentage = 100;
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Create an EDS resource
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  // Construct the fault injection filter config
+  HTTPFault http_fault;
+  auto* delay_percentage = http_fault.mutable_delay()->mutable_percentage();
+  delay_percentage->set_numerator(
+      kAlwaysDelayPercentage);  // Always inject DELAY!
+  delay_percentage->set_denominator(FractionalPercent::HUNDRED);
+  auto* fixed_delay = http_fault.mutable_delay()->mutable_fixed_delay();
+  fixed_delay->set_seconds(kLongDelaySeconds);
+  http_fault.mutable_max_active_faults()->set_value(kMaxFault);
+  // Config fault injection via different setup
+  SetFilterConfig(http_fault);
+  // Sends a batch of long running RPCs with long timeout to consume all
+  // active faults quota.
+  int num_delayed = 0;
+  RpcOptions rpc_options = RpcOptions().set_timeout_ms(kRpcTimeoutMs);
+  std::vector<ConcurrentRpc> rpcs =
+      SendConcurrentRpcs(stub_.get(), kNumRpcs, rpc_options);
+  for (auto& rpc : rpcs) {
+    if (rpc.status.error_code() == StatusCode::OK) continue;
+    EXPECT_EQ(StatusCode::DEADLINE_EXCEEDED, rpc.status.error_code());
+    ++num_delayed;
+  }
+  // Only kMaxFault number of RPC should be fault injected..
+  EXPECT_EQ(kMaxFault, num_delayed);
+}
+
+TEST_P(FaultInjectionTest, XdsFaultInjectionBidiStreamDelayOk) {
+  // kRpcTimeoutMilliseconds is 10s should never be reached.
+  const uint32_t kRpcTimeoutMilliseconds = grpc_test_slowdown_factor() * 10000;
+  const uint32_t kFixedDelaySeconds = 1;
+  const uint32_t kDelayPercentagePerHundred = 100;
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Create an EDS resource
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  // Construct the fault injection filter config
+  HTTPFault http_fault;
+  auto* delay_percentage = http_fault.mutable_delay()->mutable_percentage();
+  delay_percentage->set_numerator(kDelayPercentagePerHundred);
+  delay_percentage->set_denominator(FractionalPercent::HUNDRED);
+  auto* fixed_delay = http_fault.mutable_delay()->mutable_fixed_delay();
+  fixed_delay->set_seconds(kFixedDelaySeconds);
+  // Config fault injection via different setup
+  SetFilterConfig(http_fault);
+  ClientContext context;
+  context.set_deadline(
+      grpc_timeout_milliseconds_to_deadline(kRpcTimeoutMilliseconds));
+  auto stream = stub_->BidiStream(&context);
+  stream->WritesDone();
+  auto status = stream->Finish();
+  EXPECT_TRUE(status.ok()) << status.error_message() << ", "
+                           << status.error_details() << ", "
+                           << context.debug_error_string();
+}
+
+// This case catches a bug in the retry code that was triggered by a bad
+// interaction with the FI code.  See https://github.com/grpc/grpc/pull/27217
+// for description.
+TEST_P(FaultInjectionTest, XdsFaultInjectionBidiStreamDelayError) {
+  const uint32_t kRpcTimeoutMilliseconds = grpc_test_slowdown_factor() * 500;
+  const uint32_t kFixedDelaySeconds = 100;
+  const uint32_t kDelayPercentagePerHundred = 100;
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Create an EDS resource
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  // Construct the fault injection filter config
+  HTTPFault http_fault;
+  auto* delay_percentage = http_fault.mutable_delay()->mutable_percentage();
+  delay_percentage->set_numerator(kDelayPercentagePerHundred);
+  delay_percentage->set_denominator(FractionalPercent::HUNDRED);
+  auto* fixed_delay = http_fault.mutable_delay()->mutable_fixed_delay();
+  fixed_delay->set_seconds(kFixedDelaySeconds);
+  // Config fault injection via different setup
+  SetFilterConfig(http_fault);
+  ClientContext context;
+  context.set_deadline(
+      grpc_timeout_milliseconds_to_deadline(kRpcTimeoutMilliseconds));
+  auto stream = stub_->BidiStream(&context);
+  stream->WritesDone();
+  auto status = stream->Finish();
+  EXPECT_EQ(StatusCode::DEADLINE_EXCEEDED, status.error_code())
+      << status.error_message() << ", " << status.error_details() << ", "
+      << context.debug_error_string();
+}
+
+class BootstrapSourceTest : public XdsEnd2endTest {
+ public:
+  BootstrapSourceTest() : XdsEnd2endTest(4, 1) {}
+};
+
+TEST_P(BootstrapSourceTest, Vanilla) {
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  EdsResourceArgs args({
+      {"locality0", CreateEndpointsForBackends()},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  WaitForAllBackends();
+}
+
+#ifndef DISABLED_XDS_PROTO_IN_CC
+class ClientStatusDiscoveryServiceTest : public XdsEnd2endTest {
+ public:
+  ClientStatusDiscoveryServiceTest() : XdsEnd2endTest(1, 1) {}
+
+  void SetUp() override {
+    XdsEnd2endTest::SetUp();
+    admin_server_thread_ = absl::make_unique<AdminServerThread>(this);
+    admin_server_thread_->Start();
+    std::string admin_server_address = absl::StrCat(
+        ipv6_only_ ? "[::1]:" : "127.0.0.1:", admin_server_thread_->port());
+    admin_channel_ = grpc::CreateChannel(
+        admin_server_address,
+        std::make_shared<SecureChannelCredentials>(
+            grpc_fake_transport_security_credentials_create()));
+    csds_stub_ =
+        envoy::service::status::v3::ClientStatusDiscoveryService::NewStub(
+            admin_channel_);
+    if (GetParam().use_csds_streaming()) {
+      stream_ = csds_stub_->StreamClientStatus(&stream_context_);
+    }
+  }
+
+  void TearDown() override {
+    if (stream_ != nullptr) {
+      EXPECT_TRUE(stream_->WritesDone());
+      Status status = stream_->Finish();
+      EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
+                               << " message=" << status.error_message();
+    }
+    admin_server_thread_->Shutdown();
+    XdsEnd2endTest::TearDown();
+  }
+
+  envoy::service::status::v3::ClientStatusResponse FetchCsdsResponse() {
+    envoy::service::status::v3::ClientStatusResponse response;
+    if (!GetParam().use_csds_streaming()) {
+      // Fetch through unary pulls
+      ClientContext context;
+      Status status = csds_stub_->FetchClientStatus(
+          &context, envoy::service::status::v3::ClientStatusRequest(),
+          &response);
+      EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
+                               << " message=" << status.error_message();
+    } else {
+      // Fetch through streaming pulls
+      EXPECT_TRUE(
+          stream_->Write(envoy::service::status::v3::ClientStatusRequest()));
+      EXPECT_TRUE(stream_->Read(&response));
+    }
+    return response;
+  }
+
+ private:
+  std::unique_ptr<AdminServerThread> admin_server_thread_;
+  std::shared_ptr<Channel> admin_channel_;
+  std::unique_ptr<
+      envoy::service::status::v3::ClientStatusDiscoveryService::Stub>
+      csds_stub_;
+  ClientContext stream_context_;
+  std::unique_ptr<
+      ClientReaderWriter<envoy::service::status::v3::ClientStatusRequest,
+                         envoy::service::status::v3::ClientStatusResponse>>
+      stream_;
+};
+
+MATCHER_P4(EqNode, id, user_agent_name, user_agent_version, client_features,
+           "equals Node") {
+  bool ok = true;
+  ok &= ::testing::ExplainMatchResult(id, arg.id(), result_listener);
+  ok &= ::testing::ExplainMatchResult(user_agent_name, arg.user_agent_name(),
+                                      result_listener);
+  ok &= ::testing::ExplainMatchResult(
+      user_agent_version, arg.user_agent_version(), result_listener);
+  ok &= ::testing::ExplainMatchResult(client_features, arg.client_features(),
+                                      result_listener);
+  return ok;
+}
+
+MATCHER_P6(EqGenericXdsConfig, type_url, name, version_info, xds_config,
+           client_status, error_state, "equals GenericXdsConfig") {
+  bool ok = true;
+  ok &=
+      ::testing::ExplainMatchResult(type_url, arg.type_url(), result_listener);
+  ok &= ::testing::ExplainMatchResult(name, arg.name(), result_listener);
+  ok &= ::testing::ExplainMatchResult(version_info, arg.version_info(),
+                                      result_listener);
+  ok &= ::testing::ExplainMatchResult(xds_config, arg.xds_config(),
+                                      result_listener);
+  ok &= ::testing::ExplainMatchResult(client_status, arg.client_status(),
+                                      result_listener);
+  ok &= ::testing::ExplainMatchResult(error_state, arg.error_state(),
+                                      result_listener);
+  return ok;
+}
+
+MATCHER_P2(EqListener, name, api_listener, "equals Listener") {
+  bool ok = true;
+  ok &= ::testing::ExplainMatchResult(name, arg.name(), result_listener);
+  ok &= ::testing::ExplainMatchResult(
+      api_listener, arg.api_listener().api_listener(), result_listener);
+  return ok;
+}
+
+MATCHER_P(EqHttpConnectionManagerNotRds, route_config,
+          "equals HttpConnectionManager") {
+  bool ok = true;
+  ok &= ::testing::ExplainMatchResult(route_config, arg.route_config(),
+                                      result_listener);
+  return ok;
+}
+
+MATCHER_P(EqRouteConfigurationName, name, "equals RouteConfiguration") {
+  bool ok = true;
+  ok &= ::testing::ExplainMatchResult(name, arg.name(), result_listener);
+  return ok;
+}
+
+MATCHER_P2(EqRouteConfiguration, name, cluster_name,
+           "equals RouteConfiguration") {
+  bool ok = true;
+  ok &= ::testing::ExplainMatchResult(name, arg.name(), result_listener);
+  ok &= ::testing::ExplainMatchResult(
+      ::testing::ElementsAre(::testing::Property(
+          &envoy::config::route::v3::VirtualHost::routes,
+          ::testing::ElementsAre(::testing::Property(
+              &envoy::config::route::v3::Route::route,
+              ::testing::Property(
+                  &envoy::config::route::v3::RouteAction::cluster,
+                  cluster_name))))),
+      arg.virtual_hosts(), result_listener);
+  return ok;
+}
+
+MATCHER_P(EqCluster, name, "equals Cluster") {
+  bool ok = true;
+  ok &= ::testing::ExplainMatchResult(name, arg.name(), result_listener);
+  return ok;
+}
+
+MATCHER_P(EqEndpoint, port, "equals Endpoint") {
+  bool ok = true;
+  ok &= ::testing::ExplainMatchResult(
+      port, arg.address().socket_address().port_value(), result_listener);
+  return ok;
+}
+
+MATCHER_P2(EqLocalityLbEndpoints, port, weight, "equals LocalityLbEndpoints") {
+  bool ok = true;
+  ok &= ::testing::ExplainMatchResult(
+      ::testing::ElementsAre(::testing::Property(
+          &envoy::config::endpoint::v3::LbEndpoint::endpoint,
+          EqEndpoint(port))),
+      arg.lb_endpoints(), result_listener);
+  ok &= ::testing::ExplainMatchResult(
+      weight, arg.load_balancing_weight().value(), result_listener);
+  return ok;
+}
+
+MATCHER_P(EqClusterLoadAssignmentName, cluster_name,
+          "equals ClusterLoadAssignment") {
+  bool ok = true;
+  ok &= ::testing::ExplainMatchResult(cluster_name, arg.cluster_name(),
+                                      result_listener);
+  return ok;
+}
+
+MATCHER_P3(EqClusterLoadAssignment, cluster_name, port, weight,
+           "equals ClusterLoadAssignment") {
+  bool ok = true;
+  ok &= ::testing::ExplainMatchResult(cluster_name, arg.cluster_name(),
+                                      result_listener);
+  ok &= ::testing::ExplainMatchResult(
+      ::testing::ElementsAre(EqLocalityLbEndpoints(port, weight)),
+      arg.endpoints(), result_listener);
+  return ok;
+}
+
+MATCHER_P2(EqUpdateFailureState, details, version_info,
+           "equals UpdateFailureState") {
+  bool ok = true;
+  ok &= ::testing::ExplainMatchResult(details, arg.details(), result_listener);
+  ok &= ::testing::ExplainMatchResult(version_info, arg.version_info(),
+                                      result_listener);
+  return ok;
+}
+
+MATCHER_P(UnpackListener, matcher, "is a Listener") {
+  Listener config;
+  if (!::testing::ExplainMatchResult(true, arg.UnpackTo(&config),
+                                     result_listener)) {
+    return false;
+  }
+  return ::testing::ExplainMatchResult(matcher, config, result_listener);
+}
+
+MATCHER_P(UnpackRouteConfiguration, matcher, "is a RouteConfiguration") {
+  RouteConfiguration config;
+  if (!::testing::ExplainMatchResult(true, arg.UnpackTo(&config),
+                                     result_listener)) {
+    return false;
+  }
+  return ::testing::ExplainMatchResult(matcher, config, result_listener);
+}
+
+MATCHER_P(UnpackHttpConnectionManager, matcher, "is a HttpConnectionManager") {
+  HttpConnectionManager config;
+  if (!::testing::ExplainMatchResult(true, arg.UnpackTo(&config),
+                                     result_listener)) {
+    return false;
+  }
+  return ::testing::ExplainMatchResult(matcher, config, result_listener);
+}
+
+MATCHER_P(UnpackCluster, matcher, "is a Cluster") {
+  Cluster config;
+  if (!::testing::ExplainMatchResult(true, arg.UnpackTo(&config),
+                                     result_listener)) {
+    return false;
+  }
+  return ::testing::ExplainMatchResult(matcher, config, result_listener);
+}
+
+MATCHER_P(UnpackClusterLoadAssignment, matcher, "is a ClusterLoadAssignment") {
+  ClusterLoadAssignment config;
+  if (!::testing::ExplainMatchResult(true, arg.UnpackTo(&config),
+                                     result_listener)) {
+    return false;
+  }
+  return ::testing::ExplainMatchResult(matcher, config, result_listener);
+}
+
+MATCHER(IsRdsEnabledHCM, "is a RDS enabled HttpConnectionManager") {
+  return ::testing::ExplainMatchResult(
+      UnpackHttpConnectionManager(
+          ::testing::Property(&HttpConnectionManager::has_rds, true)),
+      arg, result_listener);
+}
+
+MATCHER_P2(EqNoRdsHCM, route_configuration_name, cluster_name,
+           "equals RDS disabled HttpConnectionManager") {
+  return ::testing::ExplainMatchResult(
+      UnpackHttpConnectionManager(EqHttpConnectionManagerNotRds(
+          EqRouteConfiguration(route_configuration_name, cluster_name))),
+      arg, result_listener);
+}
+
+TEST_P(ClientStatusDiscoveryServiceTest, XdsConfigDumpVanilla) {
+  const size_t kNumRpcs = 5;
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  EdsResourceArgs args({{"locality0", CreateEndpointsForBackends(0, 1)}});
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  // Send several RPCs to ensure the xDS setup works
+  CheckRpcSendOk(kNumRpcs);
+  // Fetches the client config
+  auto csds_response = FetchCsdsResponse();
+  gpr_log(GPR_INFO, "xDS config dump: %s", csds_response.DebugString().c_str());
+  EXPECT_EQ(1, csds_response.config_size());
+  const auto& client_config = csds_response.config(0);
+  // Validate the Node information
+  EXPECT_THAT(client_config.node(),
+              EqNode("xds_end2end_test", ::testing::HasSubstr("C-core"),
+                     ::testing::HasSubstr(grpc_version_string()),
+                     ::testing::ElementsAre(
+                         "envoy.lb.does_not_support_overprovisioning")));
+  // Listener matcher depends on whether RDS is enabled.
+  ::testing::Matcher<google::protobuf::Any> api_listener_matcher;
+  if (GetParam().enable_rds_testing()) {
+    api_listener_matcher = IsRdsEnabledHCM();
+  } else {
+    api_listener_matcher =
+        EqNoRdsHCM(kDefaultRouteConfigurationName, kDefaultClusterName);
+  }
+  // Construct list of all matchers.
+  std::vector<::testing::Matcher<
+      envoy::service::status::v3::ClientConfig_GenericXdsConfig>>
+      matchers = {
+          // Listener
+          EqGenericXdsConfig(
+              kLdsTypeUrl, kServerName, /*version_info=*/"1",
+              UnpackListener(EqListener(kServerName, api_listener_matcher)),
+              ClientResourceStatus::ACKED, /*error_state=*/::testing::_),
+          // Cluster
+          EqGenericXdsConfig(
+              kCdsTypeUrl, kDefaultClusterName, /*version_info=*/"1",
+              UnpackCluster(EqCluster(kDefaultClusterName)),
+              ClientResourceStatus::ACKED, /*error_state=*/::testing::_),
+          // ClusterLoadAssignment
+          EqGenericXdsConfig(
+              kEdsTypeUrl, kDefaultEdsServiceName, /*version_info=*/"1",
+              UnpackClusterLoadAssignment(EqClusterLoadAssignment(
+                  kDefaultEdsServiceName, backends_[0]->port(),
+                  kDefaultLocalityWeight)),
+              ClientResourceStatus::ACKED, /*error_state=*/::testing::_),
+      };
+  // If RDS is enabled, add matcher for RDS resource.
+  if (GetParam().enable_rds_testing()) {
+    matchers.push_back(EqGenericXdsConfig(
+        kRdsTypeUrl, kDefaultRouteConfigurationName, /*version_info=*/"1",
+        UnpackRouteConfiguration(EqRouteConfiguration(
+            kDefaultRouteConfigurationName, kDefaultClusterName)),
+        ClientResourceStatus::ACKED, /*error_state=*/::testing::_));
+  }
+  // Validate the dumped xDS configs
+  EXPECT_THAT(client_config.generic_xds_configs(),
+              ::testing::UnorderedElementsAreArray(matchers))
+      << "Actual: " << client_config.DebugString();
+}
+
+TEST_P(ClientStatusDiscoveryServiceTest, XdsConfigDumpEmpty) {
+  // The CSDS service should not fail if XdsClient is not initialized or there
+  // is no working xDS configs.
+  FetchCsdsResponse();
+}
+
+TEST_P(ClientStatusDiscoveryServiceTest, XdsConfigDumpListenerError) {
+  int kFetchConfigRetries = 3;
+  int kFetchIntervalMilliseconds = 200;
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  EdsResourceArgs args({{"locality0", CreateEndpointsForBackends(0, 1)}});
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  // Ensure the xDS resolver has working configs.
+  CheckRpcSendOk();
+  // Bad Listener should be rejected.
+  Listener listener;
+  listener.set_name(kServerName);
+  balancers_[0]->ads_service()->SetLdsResource(listener);
+  // The old xDS configs should still be effective.
+  CheckRpcSendOk();
+  ::testing::Matcher<google::protobuf::Any> api_listener_matcher;
+  if (GetParam().enable_rds_testing()) {
+    api_listener_matcher = IsRdsEnabledHCM();
+  } else {
+    api_listener_matcher =
+        EqNoRdsHCM(kDefaultRouteConfigurationName, kDefaultClusterName);
+  }
+  for (int i = 0; i < kFetchConfigRetries; ++i) {
+    auto csds_response = FetchCsdsResponse();
+    // Check if error state is propagated
+    bool ok = ::testing::Value(
+        csds_response.config(0).generic_xds_configs(),
+        ::testing::Contains(EqGenericXdsConfig(
+            kLdsTypeUrl, kServerName, /*version_info=*/"1",
+            UnpackListener(EqListener(kServerName, api_listener_matcher)),
+            ClientResourceStatus::NACKED,
+            EqUpdateFailureState(
+                ::testing::HasSubstr(
+                    "Listener has neither address nor ApiListener"),
+                "2"))));
+    if (ok) return;  // TEST PASSED!
+    gpr_sleep_until(
+        grpc_timeout_milliseconds_to_deadline(kFetchIntervalMilliseconds));
+  }
+  FAIL() << "error_state not seen in CSDS responses";
+}
+
+TEST_P(ClientStatusDiscoveryServiceTest, XdsConfigDumpRouteError) {
+  int kFetchConfigRetries = 3;
+  int kFetchIntervalMilliseconds = 200;
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  EdsResourceArgs args({{"locality0", CreateEndpointsForBackends(0, 1)}});
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  // Ensure the xDS resolver has working configs.
+  CheckRpcSendOk();
+  // Bad route config will be rejected.
+  RouteConfiguration route_config;
+  route_config.set_name(kDefaultRouteConfigurationName);
+  route_config.add_virtual_hosts();
+  SetRouteConfiguration(0, route_config);
+  // The old xDS configs should still be effective.
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  CheckRpcSendOk();
+  for (int i = 0; i < kFetchConfigRetries; ++i) {
+    auto csds_response = FetchCsdsResponse();
+    bool ok = false;
+    if (GetParam().enable_rds_testing()) {
+      ok = ::testing::Value(
+          csds_response.config(0).generic_xds_configs(),
+          ::testing::Contains(EqGenericXdsConfig(
+              kRdsTypeUrl, kDefaultRouteConfigurationName, /*version_info=*/"1",
+              UnpackRouteConfiguration(EqRouteConfiguration(
+                  kDefaultRouteConfigurationName, kDefaultClusterName)),
+              ClientResourceStatus::NACKED,
+              EqUpdateFailureState(
+                  ::testing::HasSubstr("VirtualHost has no domains"), "2"))));
+    } else {
+      ok = ::testing::Value(
+          csds_response.config(0).generic_xds_configs(),
+          ::testing::Contains(EqGenericXdsConfig(
+              kLdsTypeUrl, kServerName, /*version_info=*/"1",
+              UnpackListener(EqListener(
+                  kServerName, EqNoRdsHCM(kDefaultRouteConfigurationName,
+                                          kDefaultClusterName))),
+              ClientResourceStatus::NACKED,
+              EqUpdateFailureState(
+                  ::testing::HasSubstr("VirtualHost has no domains"), "2"))));
+    }
+    if (ok) return;  // TEST PASSED!
+    gpr_sleep_until(
+        grpc_timeout_milliseconds_to_deadline(kFetchIntervalMilliseconds));
+  }
+  FAIL() << "error_state not seen in CSDS responses";
+}
+
+TEST_P(ClientStatusDiscoveryServiceTest, XdsConfigDumpClusterError) {
+  int kFetchConfigRetries = 3;
+  int kFetchIntervalMilliseconds = 200;
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  EdsResourceArgs args({{"locality0", CreateEndpointsForBackends(0, 1)}});
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  // Ensure the xDS resolver has working configs.
+  CheckRpcSendOk();
+  // Listener without any route, will be rejected.
+  Cluster cluster;
+  cluster.set_name(kDefaultClusterName);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
+  // The old xDS configs should still be effective.
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  CheckRpcSendOk();
+  for (int i = 0; i < kFetchConfigRetries; ++i) {
+    auto csds_response = FetchCsdsResponse();
+    // Check if error state is propagated
+    bool ok = ::testing::Value(
+        csds_response.config(0).generic_xds_configs(),
+        ::testing::Contains(EqGenericXdsConfig(
+            kCdsTypeUrl, kDefaultClusterName, /*version_info=*/"1",
+            UnpackCluster(EqCluster(kDefaultClusterName)),
+            ClientResourceStatus::NACKED,
+            EqUpdateFailureState(
+                ::testing::HasSubstr("DiscoveryType not found"), "2"))));
+    if (ok) return;  // TEST PASSED!
+    gpr_sleep_until(
+        grpc_timeout_milliseconds_to_deadline(kFetchIntervalMilliseconds));
+  }
+  FAIL() << "error_state not seen in CSDS responses";
+}
+
+TEST_P(ClientStatusDiscoveryServiceTest, XdsConfigDumpEndpointError) {
+  int kFetchConfigRetries = 3;
+  int kFetchIntervalMilliseconds = 200;
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  EdsResourceArgs args({{"locality0", CreateEndpointsForBackends(0, 1)}});
+  balancers_[0]->ads_service()->SetEdsResource(
+      BuildEdsResource(args, DefaultEdsServiceName()));
+  // Ensure the xDS resolver has working configs.
+  CheckRpcSendOk();
+  // Bad endpoint config will be rejected.
+  ClusterLoadAssignment cluster_load_assignment;
+  cluster_load_assignment.set_cluster_name(kDefaultEdsServiceName);
+  auto* endpoints = cluster_load_assignment.add_endpoints();
+  endpoints->mutable_load_balancing_weight()->set_value(1);
+  auto* endpoint = endpoints->add_lb_endpoints()->mutable_endpoint();
+  endpoint->mutable_address()->mutable_socket_address()->set_port_value(1 << 1);
+  balancers_[0]->ads_service()->SetEdsResource(cluster_load_assignment);
+  // The old xDS configs should still be effective.
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  CheckRpcSendOk();
+  for (int i = 0; i < kFetchConfigRetries; ++i) {
+    auto csds_response = FetchCsdsResponse();
+    // Check if error state is propagated
+    bool ok = ::testing::Value(
+        csds_response.config(0).generic_xds_configs(),
+        ::testing::Contains(EqGenericXdsConfig(
+            kEdsTypeUrl, kDefaultEdsServiceName, /*version_info=*/"1",
+            UnpackClusterLoadAssignment(EqClusterLoadAssignment(
+                kDefaultEdsServiceName, backends_[0]->port(),
+                kDefaultLocalityWeight)),
+            ClientResourceStatus::NACKED,
+            EqUpdateFailureState(::testing::HasSubstr("Empty locality"),
+                                 "2"))));
+    if (ok) return;  // TEST PASSED!
+    gpr_sleep_until(
+        grpc_timeout_milliseconds_to_deadline(kFetchIntervalMilliseconds));
+  }
+  FAIL() << "error_state not seen in CSDS responses";
+}
+
+TEST_P(ClientStatusDiscoveryServiceTest, XdsConfigDumpListenerRequested) {
+  int kTimeoutMillisecond = 1000;
+  balancers_[0]->ads_service()->UnsetResource(kLdsTypeUrl, kServerName);
+  CheckRpcSendFailure(
+      CheckRpcSendFailureOptions()
+          .set_rpc_options(RpcOptions().set_timeout_ms(kTimeoutMillisecond))
+          .set_expected_error_code(StatusCode::DEADLINE_EXCEEDED));
+  auto csds_response = FetchCsdsResponse();
+  EXPECT_THAT(
+      csds_response.config(0).generic_xds_configs(),
+      ::testing::Contains(EqGenericXdsConfig(
+          kLdsTypeUrl, kServerName, /*version_info=*/::testing::_, ::testing::_,
+          ClientResourceStatus::REQUESTED, /*error_state=*/::testing::_)));
+}
+
+TEST_P(ClientStatusDiscoveryServiceTest, XdsConfigDumpClusterRequested) {
+  int kTimeoutMillisecond = 1000;
+  std::string kClusterName1 = "cluster-1";
+  std::string kClusterName2 = "cluster-2";
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Create a route config requesting two non-existing clusters
+  RouteConfiguration route_config;
+  route_config.set_name(kDefaultRouteConfigurationName);
+  auto* vh = route_config.add_virtual_hosts();
+  // The VirtualHost must match the domain name, otherwise will cause resolver
+  // transient failure.
+  vh->add_domains("*");
+  auto* routes1 = vh->add_routes();
+  routes1->mutable_match()->set_prefix("");
+  routes1->mutable_route()->set_cluster(kClusterName1);
+  auto* routes2 = vh->add_routes();
+  routes2->mutable_match()->set_prefix("");
+  routes2->mutable_route()->set_cluster(kClusterName2);
+  SetRouteConfiguration(0, route_config);
+  // Try to get the configs plumb through
+  CheckRpcSendFailure(
+      CheckRpcSendFailureOptions()
+          .set_rpc_options(RpcOptions().set_timeout_ms(kTimeoutMillisecond))
+          .set_expected_error_code(StatusCode::DEADLINE_EXCEEDED));
+  auto csds_response = FetchCsdsResponse();
+  EXPECT_THAT(csds_response.config(0).generic_xds_configs(),
+              ::testing::AllOf(
+                  ::testing::Contains(EqGenericXdsConfig(
+                      kCdsTypeUrl, kClusterName1, /*version_info=*/::testing::_,
+                      ::testing::_, ClientResourceStatus::REQUESTED,
+                      /*error_state=*/::testing::_)),
+                  ::testing::Contains(EqGenericXdsConfig(
+                      kCdsTypeUrl, kClusterName2, /*version_info=*/::testing::_,
+                      ::testing::_, ClientResourceStatus::REQUESTED,
+                      /*error_state=*/::testing::_))));
+}
+
+class CsdsShortAdsTimeoutTest : public ClientStatusDiscoveryServiceTest {
+  void SetUp() override {
+    // Shorten the ADS subscription timeout to speed up the test run.
+    xds_resource_does_not_exist_timeout_ms_ = 2000;
+    ClientStatusDiscoveryServiceTest::SetUp();
+  }
+};
+
+TEST_P(CsdsShortAdsTimeoutTest, XdsConfigDumpListenerDoesNotExist) {
+  int kTimeoutMillisecond = 1000000;  // 1000s wait for the transient failure.
+  balancers_[0]->ads_service()->UnsetResource(kLdsTypeUrl, kServerName);
+  CheckRpcSendFailure(
+      CheckRpcSendFailureOptions()
+          .set_rpc_options(RpcOptions().set_timeout_ms(kTimeoutMillisecond))
+          .set_expected_error_code(grpc::UNAVAILABLE));
+  auto csds_response = FetchCsdsResponse();
+  EXPECT_THAT(
+      csds_response.config(0).generic_xds_configs(),
+      ::testing::Contains(EqGenericXdsConfig(
+          kLdsTypeUrl, kServerName, /*version_info=*/::testing::_, ::testing::_,
+          ClientResourceStatus::DOES_NOT_EXIST, /*error_state=*/::testing::_)));
+}
+
+TEST_P(CsdsShortAdsTimeoutTest, XdsConfigDumpRouteConfigDoesNotExist) {
+  if (!GetParam().enable_rds_testing()) return;
+  int kTimeoutMillisecond = 1000000;  // 1000s wait for the transient failure.
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  balancers_[0]->ads_service()->UnsetResource(kRdsTypeUrl,
+                                              kDefaultRouteConfigurationName);
+  CheckRpcSendFailure(
+      CheckRpcSendFailureOptions()
+          .set_rpc_options(RpcOptions().set_timeout_ms(kTimeoutMillisecond))
+          .set_expected_error_code(grpc::UNAVAILABLE));
+  auto csds_response = FetchCsdsResponse();
+  EXPECT_THAT(
+      csds_response.config(0).generic_xds_configs(),
+      ::testing::Contains(EqGenericXdsConfig(
+          kRdsTypeUrl, kDefaultRouteConfigurationName,
+          /*version_info=*/::testing::_, ::testing::_,
+          ClientResourceStatus::DOES_NOT_EXIST, /*error_state=*/::testing::_)));
+}
+
+TEST_P(CsdsShortAdsTimeoutTest, XdsConfigDumpClusterDoesNotExist) {
+  int kTimeoutMillisecond = 1000000;  // 1000s wait for the transient failure.
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  balancers_[0]->ads_service()->UnsetResource(kCdsTypeUrl, kDefaultClusterName);
+  CheckRpcSendFailure(
+      CheckRpcSendFailureOptions()
+          .set_rpc_options(RpcOptions().set_timeout_ms(kTimeoutMillisecond))
+          .set_expected_error_code(grpc::UNAVAILABLE));
+  auto csds_response = FetchCsdsResponse();
+  EXPECT_THAT(
+      csds_response.config(0).generic_xds_configs(),
+      ::testing::Contains(EqGenericXdsConfig(
+          kCdsTypeUrl, kDefaultClusterName, /*version_info=*/::testing::_,
+          ::testing::_, ClientResourceStatus::DOES_NOT_EXIST,
+          /*error_state=*/::testing::_)));
+}
+
+TEST_P(CsdsShortAdsTimeoutTest, XdsConfigDumpEndpointDoesNotExist) {
+  int kTimeoutMillisecond = 1000000;  // 1000s wait for the transient failure.
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  balancers_[0]->ads_service()->UnsetResource(kEdsTypeUrl,
+                                              kDefaultEdsServiceName);
+  CheckRpcSendFailure(
+      CheckRpcSendFailureOptions()
+          .set_rpc_options(RpcOptions().set_timeout_ms(kTimeoutMillisecond))
+          .set_expected_error_code(grpc::UNAVAILABLE));
+  auto csds_response = FetchCsdsResponse();
+  EXPECT_THAT(csds_response.config(0).generic_xds_configs(),
+              ::testing::Contains(EqGenericXdsConfig(
+                  kEdsTypeUrl, kDefaultEdsServiceName,
+                  /*version_info=*/::testing::_, ::testing::_,
+                  ClientResourceStatus::DOES_NOT_EXIST,
+                  /*error_state=*/::testing::_)));
+}
+
+#endif  // DISABLED_XDS_PROTO_IN_CC
+
+std::string TestTypeName(const ::testing::TestParamInfo<TestType>& info) {
+  return info.param.AsString();
+}
+
+// Run with all combinations of xds/fake resolver and enabling load reporting.
+INSTANTIATE_TEST_SUITE_P(
+    XdsTest, BasicTest,
+    ::testing::Values(
+        TestType(), TestType().set_enable_load_reporting(),
+        TestType().set_use_fake_resolver(),
+        TestType().set_use_fake_resolver().set_enable_load_reporting()),
+    &TestTypeName);
+
+// Run with both fake resolver and xds resolver.
+// Don't run with load reporting or v2 or RDS, since they are irrelevant to
+// the tests.
+INSTANTIATE_TEST_SUITE_P(XdsTest, SecureNamingTest,
+                         ::testing::Values(TestType(),
+                                           TestType().set_use_fake_resolver()),
+                         &TestTypeName);
+
+// LDS depends on XdsResolver.
+INSTANTIATE_TEST_SUITE_P(XdsTest, LdsTest, ::testing::Values(TestType()),
+                         &TestTypeName);
+INSTANTIATE_TEST_SUITE_P(XdsTest, LdsV2Test,
+                         ::testing::Values(TestType().set_use_v2()),
+                         &TestTypeName);
+
+// LDS/RDS commmon tests depend on XdsResolver.
+INSTANTIATE_TEST_SUITE_P(
+    XdsTest, LdsRdsTest,
+    ::testing::Values(TestType(), TestType().set_enable_rds_testing(),
+                      // Also test with xDS v2.
+                      TestType().set_enable_rds_testing().set_use_v2()),
+    &TestTypeName);
+
+// CDS depends on XdsResolver.
+INSTANTIATE_TEST_SUITE_P(
+    XdsTest, CdsTest,
+    ::testing::Values(TestType(), TestType().set_enable_load_reporting()),
+    &TestTypeName);
+
+// CDS depends on XdsResolver.
+// Security depends on v3.
+// Not enabling load reporting or RDS, since those are irrelevant to these
+// tests.
+INSTANTIATE_TEST_SUITE_P(
+    XdsTest, XdsSecurityTest,
+    ::testing::Values(TestType().set_use_xds_credentials()), &TestTypeName);
+
+// We are only testing the server here.
+// Run with bootstrap from env var, so that we use a global XdsClient
+// instance.  Otherwise, we would need to use a separate fake resolver
+// result generator on the client and server sides.
+INSTANTIATE_TEST_SUITE_P(XdsTest, XdsEnabledServerTest,
+                         ::testing::Values(TestType().set_bootstrap_source(
+                             TestType::kBootstrapFromEnvVar)),
+                         &TestTypeName);
+
+// We are only testing the server here.
+INSTANTIATE_TEST_SUITE_P(XdsTest, XdsServerSecurityTest,
+                         ::testing::Values(TestType()
+                                               .set_use_fake_resolver()
+                                               .set_use_xds_credentials()),
+                         &TestTypeName);
+
+// We are only testing the server here.
+INSTANTIATE_TEST_SUITE_P(XdsTest, XdsEnabledServerStatusNotificationTest,
+                         ::testing::Values(TestType()
+                                               .set_use_fake_resolver()
+                                               .set_use_xds_credentials()),
+                         &TestTypeName);
+
+// We are only testing the server here.
+INSTANTIATE_TEST_SUITE_P(XdsTest, XdsServerFilterChainMatchTest,
+                         ::testing::Values(TestType()
+                                               .set_use_fake_resolver()
+                                               .set_use_xds_credentials()),
+                         &TestTypeName);
+
+// We are only testing the server here.
+// TODO(yashykt): Also add a test type with set_enable_rds_testing() once we
+// start fetching non-inline resources.
+INSTANTIATE_TEST_SUITE_P(XdsTest, XdsServerRdsTest,
+                         ::testing::Values(TestType()
+                                               .set_use_fake_resolver()
+                                               .set_use_xds_credentials()),
+                         &TestTypeName);
+
+// EDS could be tested with or without XdsResolver, but the tests would
+// be the same either way, so we test it only with XdsResolver.
+INSTANTIATE_TEST_SUITE_P(
+    XdsTest, EdsTest,
+    ::testing::Values(TestType(), TestType().set_enable_load_reporting()),
+    &TestTypeName);
+
+// Test initial resource timeouts for each resource type.
+// Do this only for XdsResolver with RDS enabled, so that we can test
+// all resource types.
+// Run with V3 only, since the functionality is no different in V2.
+INSTANTIATE_TEST_SUITE_P(XdsTest, TimeoutTest,
+                         ::testing::Values(TestType().set_enable_rds_testing()),
+                         &TestTypeName);
+
+// XdsResolverOnlyTest depends on XdsResolver.
+INSTANTIATE_TEST_SUITE_P(
+    XdsTest, XdsResolverOnlyTest,
+    ::testing::Values(TestType(), TestType().set_enable_load_reporting()),
+    &TestTypeName);
+
+// Runs with bootstrap from env var, so that there's a global XdsClient.
+INSTANTIATE_TEST_SUITE_P(
+    XdsTest, GlobalXdsClientTest,
+    ::testing::Values(
+        TestType().set_bootstrap_source(TestType::kBootstrapFromEnvVar),
+        TestType()
+            .set_bootstrap_source(TestType::kBootstrapFromEnvVar)
+            .set_enable_load_reporting()),
+    &TestTypeName);
+
+// XdsResolverLoadReprtingOnlyTest depends on XdsResolver and load reporting.
+INSTANTIATE_TEST_SUITE_P(
+    XdsTest, XdsResolverLoadReportingOnlyTest,
+    ::testing::Values(TestType().set_enable_load_reporting()), &TestTypeName);
+
+INSTANTIATE_TEST_SUITE_P(
+    XdsTest, LocalityMapTest,
+    ::testing::Values(
+        TestType(), TestType().set_enable_load_reporting(),
+        TestType().set_use_fake_resolver(),
+        TestType().set_use_fake_resolver().set_enable_load_reporting()),
+    &TestTypeName);
+
+INSTANTIATE_TEST_SUITE_P(
+    XdsTest, FailoverTest,
+    ::testing::Values(
+        TestType(), TestType().set_enable_load_reporting(),
+        TestType().set_use_fake_resolver(),
+        TestType().set_use_fake_resolver().set_enable_load_reporting()),
+    &TestTypeName);
+
+INSTANTIATE_TEST_SUITE_P(
+    XdsTest, DropTest,
+    ::testing::Values(
+        TestType(), TestType().set_enable_load_reporting(),
+        TestType().set_use_fake_resolver(),
+        TestType().set_use_fake_resolver().set_enable_load_reporting()),
+    &TestTypeName);
+
+INSTANTIATE_TEST_SUITE_P(
+    XdsTest, BalancerUpdateTest,
+    ::testing::Values(
+        TestType().set_use_fake_resolver(),
+        TestType().set_use_fake_resolver().set_enable_load_reporting(),
+        TestType().set_enable_load_reporting()),
+    &TestTypeName);
+
+// Load reporting tests are not run with load reporting disabled.
+INSTANTIATE_TEST_SUITE_P(
+    XdsTest, ClientLoadReportingTest,
+    ::testing::Values(
+        TestType().set_enable_load_reporting(),
+        TestType().set_enable_load_reporting().set_use_fake_resolver()),
+    &TestTypeName);
+
+// Load reporting tests are not run with load reporting disabled.
+INSTANTIATE_TEST_SUITE_P(
+    XdsTest, ClientLoadReportingWithDropTest,
+    ::testing::Values(
+        TestType().set_enable_load_reporting(),
+        TestType().set_enable_load_reporting().set_use_fake_resolver()),
+    &TestTypeName);
+
+INSTANTIATE_TEST_SUITE_P(
+    XdsTest, FaultInjectionTest,
+    ::testing::Values(
+        TestType(), TestType().set_enable_rds_testing(),
+        TestType().set_filter_config_setup(
+            TestType::FilterConfigSetup::kRouteOverride),
+        TestType().set_enable_rds_testing().set_filter_config_setup(
+            TestType::FilterConfigSetup::kRouteOverride)),
+    &TestTypeName);
+
+INSTANTIATE_TEST_SUITE_P(
+    XdsTest, BootstrapSourceTest,
+    ::testing::Values(
+        TestType().set_bootstrap_source(TestType::kBootstrapFromEnvVar),
+        TestType().set_bootstrap_source(TestType::kBootstrapFromFile)),
+    &TestTypeName);
+
+#ifndef DISABLED_XDS_PROTO_IN_CC
+// Run CSDS tests with RDS enabled and disabled.
+// These need to run with the bootstrap from an env var instead of from
+// a channel arg, since there needs to be a global XdsClient instance.
+INSTANTIATE_TEST_SUITE_P(
+    XdsTest, ClientStatusDiscoveryServiceTest,
+    ::testing::Values(
+        TestType().set_bootstrap_source(TestType::kBootstrapFromEnvVar),
+        TestType()
+            .set_bootstrap_source(TestType::kBootstrapFromEnvVar)
+            .set_enable_rds_testing(),
+        TestType()
+            .set_bootstrap_source(TestType::kBootstrapFromEnvVar)
+            .set_use_csds_streaming(),
+        TestType()
+            .set_bootstrap_source(TestType::kBootstrapFromEnvVar)
+            .set_enable_rds_testing()
+            .set_use_csds_streaming()),
+    &TestTypeName);
+INSTANTIATE_TEST_SUITE_P(
+    XdsTest, CsdsShortAdsTimeoutTest,
+    ::testing::Values(
+        TestType().set_bootstrap_source(TestType::kBootstrapFromEnvVar),
+        TestType()
+            .set_bootstrap_source(TestType::kBootstrapFromEnvVar)
+            .set_enable_rds_testing(),
+        TestType()
+            .set_bootstrap_source(TestType::kBootstrapFromEnvVar)
+            .set_use_csds_streaming(),
+        TestType()
+            .set_bootstrap_source(TestType::kBootstrapFromEnvVar)
+            .set_enable_rds_testing()
+            .set_use_csds_streaming()),
+    &TestTypeName);
+#endif  // DISABLED_XDS_PROTO_IN_CC
+
+}  // namespace
+}  // namespace testing
+}  // namespace grpc
+
+int main(int argc, char** argv) {
+  grpc::testing::TestEnvironment env(argc, argv);
+  ::testing::InitGoogleTest(&argc, argv);
+  grpc::testing::WriteBootstrapFiles();
+  // Make the backup poller poll very frequently in order to pick up
+  // updates from all the subchannels's FDs.
+  GPR_GLOBAL_CONFIG_SET(grpc_client_channel_backup_poll_interval_ms, 1);
+#if TARGET_OS_IPHONE
+  // Workaround Apple CFStream bug
+  gpr_setenv("grpc_cfstream", "0");
+#endif
+  grpc_core::CertificateProviderRegistry::RegisterCertificateProviderFactory(
+      absl::make_unique<grpc::testing::FakeCertificateProviderFactory>(
+          "fake1", &grpc::testing::g_fake1_cert_data_map));
+  grpc_core::CertificateProviderRegistry::RegisterCertificateProviderFactory(
+      absl::make_unique<grpc::testing::FakeCertificateProviderFactory>(
+          "fake2", &grpc::testing::g_fake2_cert_data_map));
+  grpc_init();
+  grpc_core::XdsHttpFilterRegistry::RegisterFilter(
+      absl::make_unique<grpc::testing::NoOpHttpFilter>(
+          "grpc.testing.client_only_http_filter",
+          /* supported_on_clients = */ true, /* supported_on_servers = */ false,
+          /* is_terminal_filter */ false),
+      {"grpc.testing.client_only_http_filter"});
+  grpc_core::XdsHttpFilterRegistry::RegisterFilter(
+      absl::make_unique<grpc::testing::NoOpHttpFilter>(
+          "grpc.testing.server_only_http_filter",
+          /* supported_on_clients = */ false, /* supported_on_servers = */ true,
+          /* is_terminal_filter */ false),
+      {"grpc.testing.server_only_http_filter"});
+  grpc_core::XdsHttpFilterRegistry::RegisterFilter(
+      absl::make_unique<grpc::testing::NoOpHttpFilter>(
+          "grpc.testing.terminal_http_filter",
+          /* supported_on_clients = */ true, /* supported_on_servers = */ true,
+          /* is_terminal_filter */ true),
+      {"grpc.testing.terminal_http_filter"});
+  const auto result = RUN_ALL_TESTS();
+  grpc_shutdown();
+  return result;
+}
diff --git a/test/cpp/end2end/xds/xds_server.cc b/test/cpp/end2end/xds/xds_server.cc
new file mode 100644 (file)
index 0000000..f9ac5a1
--- /dev/null
@@ -0,0 +1,257 @@
+//
+// 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 "test/cpp/end2end/xds/xds_server.h"
+
+#include <deque>
+#include <set>
+#include <string>
+#include <thread>
+#include <vector>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "absl/types/optional.h"
+
+#include <grpc/support/log.h>
+
+#include "src/core/lib/address_utils/parse_address.h"
+#include "src/core/lib/gprpp/sync.h"
+#include "src/proto/grpc/testing/xds/ads_for_test.grpc.pb.h"
+#include "src/proto/grpc/testing/xds/lrs_for_test.grpc.pb.h"
+#include "src/proto/grpc/testing/xds/v3/ads.grpc.pb.h"
+#include "src/proto/grpc/testing/xds/v3/discovery.grpc.pb.h"
+#include "src/proto/grpc/testing/xds/v3/lrs.grpc.pb.h"
+
+namespace grpc {
+namespace testing {
+
+//
+// AdsServiceImpl
+//
+
+void AdsServiceImpl::SetResource(google::protobuf::Any resource,
+                                 const std::string& type_url,
+                                 const std::string& name) {
+  grpc_core::MutexLock lock(&ads_mu_);
+  ResourceTypeState& resource_type_state = resource_map_[type_url];
+  ++resource_type_state.resource_type_version;
+  ResourceState& resource_state = resource_type_state.resource_name_map[name];
+  resource_state.resource_type_version =
+      resource_type_state.resource_type_version;
+  resource_state.resource = std::move(resource);
+  gpr_log(GPR_INFO,
+          "ADS[%p]: Updating %s resource %s; resource_type_version now %u",
+          this, type_url.c_str(), name.c_str(),
+          resource_type_state.resource_type_version);
+  for (SubscriptionState* subscription : resource_state.subscriptions) {
+    subscription->update_queue->emplace_back(type_url, name);
+  }
+}
+
+void AdsServiceImpl::UnsetResource(const std::string& type_url,
+                                   const std::string& name) {
+  grpc_core::MutexLock lock(&ads_mu_);
+  ResourceTypeState& resource_type_state = resource_map_[type_url];
+  ++resource_type_state.resource_type_version;
+  ResourceState& resource_state = resource_type_state.resource_name_map[name];
+  resource_state.resource_type_version =
+      resource_type_state.resource_type_version;
+  resource_state.resource.reset();
+  gpr_log(GPR_INFO,
+          "ADS[%p]: Unsetting %s resource %s; resource_type_version now %u",
+          this, type_url.c_str(), name.c_str(),
+          resource_type_state.resource_type_version);
+  for (SubscriptionState* subscription : resource_state.subscriptions) {
+    subscription->update_queue->emplace_back(type_url, name);
+  }
+}
+
+// Checks whether the client needs to receive a newer version of
+// the resource.
+bool AdsServiceImpl::ClientNeedsResourceUpdate(
+    const ResourceTypeState& resource_type_state,
+    const ResourceState& resource_state, int client_resource_type_version) {
+  return client_resource_type_version <
+             resource_type_state.resource_type_version &&
+         resource_state.resource_type_version <=
+             resource_type_state.resource_type_version;
+}
+
+// Subscribes to a resource if not already subscribed:
+// 1. Sets the update_queue field in subscription_state.
+// 2. Adds subscription_state to resource_state->subscriptions.
+bool AdsServiceImpl::MaybeSubscribe(const std::string& resource_type,
+                                    const std::string& resource_name,
+                                    SubscriptionState* subscription_state,
+                                    ResourceState* resource_state,
+                                    UpdateQueue* update_queue) {
+  // The update_queue will be null if we were not previously subscribed.
+  if (subscription_state->update_queue != nullptr) return false;
+  subscription_state->update_queue = update_queue;
+  resource_state->subscriptions.emplace(subscription_state);
+  gpr_log(GPR_INFO, "ADS[%p]: subscribe to resource type %s name %s state %p",
+          this, resource_type.c_str(), resource_name.c_str(),
+          &subscription_state);
+  return true;
+}
+
+// Removes subscriptions for resources no longer present in the
+// current request.
+void AdsServiceImpl::ProcessUnsubscriptions(
+    const std::string& resource_type,
+    const std::set<std::string>& resources_in_current_request,
+    SubscriptionNameMap* subscription_name_map,
+    ResourceNameMap* resource_name_map) {
+  for (auto it = subscription_name_map->begin();
+       it != subscription_name_map->end();) {
+    const std::string& resource_name = it->first;
+    SubscriptionState& subscription_state = it->second;
+    if (resources_in_current_request.find(resource_name) !=
+        resources_in_current_request.end()) {
+      ++it;
+      continue;
+    }
+    gpr_log(GPR_INFO, "ADS[%p]: Unsubscribe to type=%s name=%s state=%p", this,
+            resource_type.c_str(), resource_name.c_str(), &subscription_state);
+    auto resource_it = resource_name_map->find(resource_name);
+    GPR_ASSERT(resource_it != resource_name_map->end());
+    auto& resource_state = resource_it->second;
+    resource_state.subscriptions.erase(&subscription_state);
+    if (resource_state.subscriptions.empty() &&
+        !resource_state.resource.has_value()) {
+      resource_name_map->erase(resource_it);
+    }
+    it = subscription_name_map->erase(it);
+  }
+}
+
+void AdsServiceImpl::Start() {
+  grpc_core::MutexLock lock(&ads_mu_);
+  ads_done_ = false;
+}
+
+void AdsServiceImpl::Shutdown() {
+  {
+    grpc_core::MutexLock lock(&ads_mu_);
+    if (!ads_done_) {
+      ads_done_ = true;
+      ads_cond_.SignalAll();
+    }
+    resource_type_response_state_.clear();
+  }
+  gpr_log(GPR_INFO, "ADS[%p]: shut down", this);
+}
+
+//
+// LrsServiceImpl::ClientStats
+//
+
+uint64_t LrsServiceImpl::ClientStats::total_successful_requests() const {
+  uint64_t sum = 0;
+  for (auto& p : locality_stats_) {
+    sum += p.second.total_successful_requests;
+  }
+  return sum;
+}
+
+uint64_t LrsServiceImpl::ClientStats::total_requests_in_progress() const {
+  uint64_t sum = 0;
+  for (auto& p : locality_stats_) {
+    sum += p.second.total_requests_in_progress;
+  }
+  return sum;
+}
+
+uint64_t LrsServiceImpl::ClientStats::total_error_requests() const {
+  uint64_t sum = 0;
+  for (auto& p : locality_stats_) {
+    sum += p.second.total_error_requests;
+  }
+  return sum;
+}
+
+uint64_t LrsServiceImpl::ClientStats::total_issued_requests() const {
+  uint64_t sum = 0;
+  for (auto& p : locality_stats_) {
+    sum += p.second.total_issued_requests;
+  }
+  return sum;
+}
+
+uint64_t LrsServiceImpl::ClientStats::dropped_requests(
+    const std::string& category) const {
+  auto iter = dropped_requests_.find(category);
+  GPR_ASSERT(iter != dropped_requests_.end());
+  return iter->second;
+}
+
+LrsServiceImpl::ClientStats& LrsServiceImpl::ClientStats::operator+=(
+    const ClientStats& other) {
+  for (const auto& p : other.locality_stats_) {
+    locality_stats_[p.first] += p.second;
+  }
+  total_dropped_requests_ += other.total_dropped_requests_;
+  for (const auto& p : other.dropped_requests_) {
+    dropped_requests_[p.first] += p.second;
+  }
+  return *this;
+}
+
+//
+// LrsServiceImpl
+//
+
+void LrsServiceImpl::Start() {
+  {
+    grpc_core::MutexLock lock(&lrs_mu_);
+    lrs_done_ = false;
+  }
+  {
+    grpc_core::MutexLock lock(&load_report_mu_);
+    result_queue_.clear();
+  }
+}
+
+void LrsServiceImpl::Shutdown() {
+  {
+    grpc_core::MutexLock lock(&lrs_mu_);
+    if (!lrs_done_) {
+      lrs_done_ = true;
+      lrs_cv_.SignalAll();
+    }
+  }
+  gpr_log(GPR_INFO, "LRS[%p]: shut down", this);
+}
+
+std::vector<LrsServiceImpl::ClientStats> LrsServiceImpl::WaitForLoadReport() {
+  grpc_core::MutexLock lock(&load_report_mu_);
+  grpc_core::CondVar cv;
+  if (result_queue_.empty()) {
+    load_report_cond_ = &cv;
+    while (result_queue_.empty()) {
+      cv.Wait(&load_report_mu_);
+    }
+    load_report_cond_ = nullptr;
+  }
+  std::vector<ClientStats> result = std::move(result_queue_.front());
+  result_queue_.pop_front();
+  return result;
+}
+
+}  // namespace testing
+}  // namespace grpc
diff --git a/test/cpp/end2end/xds/xds_server.h b/test/cpp/end2end/xds/xds_server.h
new file mode 100644 (file)
index 0000000..32e0835
--- /dev/null
@@ -0,0 +1,877 @@
+//
+// 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.
+//
+
+#ifndef GRPC_TEST_CPP_END2END_XDS_XDS_SERVER_H
+#define GRPC_TEST_CPP_END2END_XDS_XDS_SERVER_H
+
+#include <deque>
+#include <set>
+#include <string>
+#include <thread>
+#include <vector>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "absl/types/optional.h"
+
+#include <grpc/support/log.h>
+
+#include "src/core/lib/address_utils/parse_address.h"
+#include "src/core/lib/gprpp/sync.h"
+#include "src/proto/grpc/testing/xds/ads_for_test.grpc.pb.h"
+#include "src/proto/grpc/testing/xds/lrs_for_test.grpc.pb.h"
+#include "src/proto/grpc/testing/xds/v3/ads.grpc.pb.h"
+#include "src/proto/grpc/testing/xds/v3/cluster.grpc.pb.h"
+#include "src/proto/grpc/testing/xds/v3/discovery.grpc.pb.h"
+#include "src/proto/grpc/testing/xds/v3/endpoint.grpc.pb.h"
+#include "src/proto/grpc/testing/xds/v3/listener.grpc.pb.h"
+#include "src/proto/grpc/testing/xds/v3/lrs.grpc.pb.h"
+#include "src/proto/grpc/testing/xds/v3/route.grpc.pb.h"
+#include "test/core/util/test_config.h"
+#include "test/cpp/end2end/counted_service.h"
+
+namespace grpc {
+namespace testing {
+
+constexpr char kLdsTypeUrl[] =
+    "type.googleapis.com/envoy.config.listener.v3.Listener";
+constexpr char kRdsTypeUrl[] =
+    "type.googleapis.com/envoy.config.route.v3.RouteConfiguration";
+constexpr char kCdsTypeUrl[] =
+    "type.googleapis.com/envoy.config.cluster.v3.Cluster";
+constexpr char kEdsTypeUrl[] =
+    "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment";
+
+constexpr char kLdsV2TypeUrl[] = "type.googleapis.com/envoy.api.v2.Listener";
+constexpr char kRdsV2TypeUrl[] =
+    "type.googleapis.com/envoy.api.v2.RouteConfiguration";
+constexpr char kCdsV2TypeUrl[] = "type.googleapis.com/envoy.api.v2.Cluster";
+constexpr char kEdsV2TypeUrl[] =
+    "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment";
+
+// An ADS service implementation.
+class AdsServiceImpl : public std::enable_shared_from_this<AdsServiceImpl> {
+ public:
+  // State for a given xDS resource type.
+  struct ResponseState {
+    enum State {
+      NOT_SENT,  // No response sent yet.
+      SENT,      // Response was sent, but no ACK/NACK received.
+      ACKED,     // ACK received.
+      NACKED,    // NACK received; error_message will contain the error.
+    };
+    State state = NOT_SENT;
+    std::string error_message;
+  };
+
+  AdsServiceImpl()
+      : v2_rpc_service_(this, /*is_v2=*/true),
+        v3_rpc_service_(this, /*is_v2=*/false) {}
+
+  bool seen_v2_client() const { return seen_v2_client_; }
+  bool seen_v3_client() const { return seen_v3_client_; }
+
+  ::envoy::service::discovery::v2::AggregatedDiscoveryService::Service*
+  v2_rpc_service() {
+    return &v2_rpc_service_;
+  }
+
+  ::envoy::service::discovery::v3::AggregatedDiscoveryService::Service*
+  v3_rpc_service() {
+    return &v3_rpc_service_;
+  }
+
+  // Sets a resource to a particular value, overwriting any previous value.
+  void SetResource(google::protobuf::Any resource, const std::string& type_url,
+                   const std::string& name);
+
+  // Removes a resource from the server's state.
+  void UnsetResource(const std::string& type_url, const std::string& name);
+
+  void SetLdsResource(const ::envoy::config::listener::v3::Listener& listener) {
+    google::protobuf::Any resource;
+    resource.PackFrom(listener);
+    SetResource(std::move(resource), kLdsTypeUrl, listener.name());
+  }
+
+  void SetRdsResource(
+      const ::envoy::config::route::v3::RouteConfiguration& route) {
+    google::protobuf::Any resource;
+    resource.PackFrom(route);
+    SetResource(std::move(resource), kRdsTypeUrl, route.name());
+  }
+
+  void SetCdsResource(const ::envoy::config::cluster::v3::Cluster& cluster) {
+    google::protobuf::Any resource;
+    resource.PackFrom(cluster);
+    SetResource(std::move(resource), kCdsTypeUrl, cluster.name());
+  }
+
+  void SetEdsResource(
+      const ::envoy::config::endpoint::v3::ClusterLoadAssignment& assignment) {
+    google::protobuf::Any resource;
+    resource.PackFrom(assignment);
+    SetResource(std::move(resource), kEdsTypeUrl, assignment.cluster_name());
+  }
+
+  // Tells the server to ignore requests from the client for a given
+  // resource type.
+  void IgnoreResourceType(const std::string& type_url) {
+    grpc_core::MutexLock lock(&ads_mu_);
+    resource_types_to_ignore_.emplace(type_url);
+  }
+
+  // Sets the minimum version that the server will accept for a given
+  // resource type.  Will cause a gmock expectation failure if we see a
+  // lower version.
+  void SetResourceMinVersion(const std::string& type_url, int version) {
+    grpc_core::MutexLock lock(&ads_mu_);
+    resource_type_min_versions_[type_url] = version;
+  }
+
+  // Get the latest response state for each resource type.
+  ResponseState GetResponseState(const std::string& type_url) {
+    grpc_core::MutexLock lock(&ads_mu_);
+    return resource_type_response_state_[type_url];
+  }
+  ResponseState lds_response_state() { return GetResponseState(kLdsTypeUrl); }
+  ResponseState rds_response_state() { return GetResponseState(kRdsTypeUrl); }
+  ResponseState cds_response_state() { return GetResponseState(kCdsTypeUrl); }
+  ResponseState eds_response_state() { return GetResponseState(kEdsTypeUrl); }
+
+  // Starts the service.
+  void Start();
+
+  // Shuts down the service.
+  void Shutdown();
+
+  // Returns the peer names of clients currently connected to the service.
+  std::set<std::string> clients() {
+    grpc_core::MutexLock lock(&clients_mu_);
+    return clients_;
+  }
+
+ private:
+  // A queue of resource type/name pairs that have changed since the client
+  // subscribed to them.
+  using UpdateQueue = std::deque<
+      std::pair<std::string /* type url */, std::string /* resource name */>>;
+
+  // A struct representing a client's subscription to a particular resource.
+  struct SubscriptionState {
+    // The queue upon which to place updates when the resource is updated.
+    UpdateQueue* update_queue;
+  };
+
+  // A struct representing the a client's subscription to all the resources.
+  using SubscriptionNameMap =
+      std::map<std::string /* resource_name */, SubscriptionState>;
+  using SubscriptionMap =
+      std::map<std::string /* type_url */, SubscriptionNameMap>;
+
+  // Sent state for a given resource type.
+  struct SentState {
+    int nonce = 0;
+    int resource_type_version = 0;
+  };
+
+  // A struct representing the current state for an individual resource.
+  struct ResourceState {
+    // The resource itself, if present.
+    absl::optional<google::protobuf::Any> resource;
+    // The resource type version that this resource was last updated in.
+    int resource_type_version = 0;
+    // A list of subscriptions to this resource.
+    std::set<SubscriptionState*> subscriptions;
+  };
+
+  // The current state for all individual resources of a given type.
+  using ResourceNameMap =
+      std::map<std::string /* resource_name */, ResourceState>;
+
+  struct ResourceTypeState {
+    int resource_type_version = 0;
+    ResourceNameMap resource_name_map;
+  };
+
+  using ResourceMap = std::map<std::string /* type_url */, ResourceTypeState>;
+
+  // Templated RPC service implementation, works for both v2 and v3.
+  template <class RpcApi, class DiscoveryRequest, class DiscoveryResponse>
+  class RpcService : public RpcApi::Service {
+   public:
+    using Stream = ServerReaderWriter<DiscoveryResponse, DiscoveryRequest>;
+
+    RpcService(AdsServiceImpl* parent, bool is_v2)
+        : parent_(parent), is_v2_(is_v2) {}
+
+    Status StreamAggregatedResources(ServerContext* context,
+                                     Stream* stream) override {
+      gpr_log(GPR_INFO, "ADS[%p]: StreamAggregatedResources starts", this);
+      parent_->AddClient(context->peer());
+      if (is_v2_) {
+        parent_->seen_v2_client_ = true;
+      } else {
+        parent_->seen_v3_client_ = true;
+      }
+      // Take a reference of the AdsServiceImpl object, which will go
+      // out of scope when this request handler returns.  This ensures
+      // that the parent won't be destroyed until this stream is complete.
+      std::shared_ptr<AdsServiceImpl> ads_service_impl =
+          parent_->shared_from_this();
+      // Resources (type/name pairs) that have changed since the client
+      // subscribed to them.
+      UpdateQueue update_queue;
+      // Resources that the client will be subscribed to keyed by resource type
+      // url.
+      SubscriptionMap subscription_map;
+      // Sent state for each resource type.
+      std::map<std::string /*type_url*/, SentState> sent_state_map;
+      // Spawn a thread to read requests from the stream.
+      // Requests will be delivered to this thread in a queue.
+      std::deque<DiscoveryRequest> requests;
+      bool stream_closed = false;
+      std::thread reader(std::bind(&RpcService::BlockingRead, this, stream,
+                                   &requests, &stream_closed));
+      // Main loop to process requests and updates.
+      while (true) {
+        // Boolean to keep track if the loop received any work to do: a
+        // request or an update; regardless whether a response was actually
+        // sent out.
+        bool did_work = false;
+        // Look for new requests and and decide what to handle.
+        absl::optional<DiscoveryResponse> response;
+        {
+          grpc_core::MutexLock lock(&parent_->ads_mu_);
+          // If the stream has been closed or our parent is being shut
+          // down, stop immediately.
+          if (stream_closed || parent_->ads_done_) break;
+          // Otherwise, see if there's a request to read from the queue.
+          if (!requests.empty()) {
+            DiscoveryRequest request = std::move(requests.front());
+            requests.pop_front();
+            did_work = true;
+            gpr_log(GPR_INFO,
+                    "ADS[%p]: Received request for type %s with content %s",
+                    this, request.type_url().c_str(),
+                    request.DebugString().c_str());
+            const std::string v3_resource_type =
+                TypeUrlToV3(request.type_url());
+            SentState& sent_state = sent_state_map[v3_resource_type];
+            // Process request.
+            ProcessRequest(request, v3_resource_type, &update_queue,
+                           &subscription_map, &sent_state, &response);
+          }
+        }
+        if (response.has_value()) {
+          gpr_log(GPR_INFO, "ADS[%p]: Sending response: %s", this,
+                  response->DebugString().c_str());
+          stream->Write(response.value());
+        }
+        response.reset();
+        // Look for updates and decide what to handle.
+        {
+          grpc_core::MutexLock lock(&parent_->ads_mu_);
+          if (!update_queue.empty()) {
+            const std::string resource_type =
+                std::move(update_queue.front().first);
+            const std::string resource_name =
+                std::move(update_queue.front().second);
+            update_queue.pop_front();
+            did_work = true;
+            SentState& sent_state = sent_state_map[resource_type];
+            ProcessUpdate(resource_type, resource_name, &subscription_map,
+                          &sent_state, &response);
+          }
+        }
+        if (response.has_value()) {
+          gpr_log(GPR_INFO, "ADS[%p]: Sending update response: %s", this,
+                  response->DebugString().c_str());
+          stream->Write(response.value());
+        }
+        {
+          grpc_core::MutexLock lock(&parent_->ads_mu_);
+          if (parent_->ads_done_) {
+            break;
+          }
+        }
+        // If we didn't find anything to do, delay before the next loop
+        // iteration; otherwise, check whether we should exit and then
+        // immediately continue.
+        gpr_sleep_until(
+            grpc_timeout_milliseconds_to_deadline(did_work ? 0 : 10));
+      }
+      // Done with main loop.  Clean up before returning.
+      // Join reader thread.
+      reader.join();
+      // Clean up any subscriptions that were still active when the call
+      // finished.
+      {
+        grpc_core::MutexLock lock(&parent_->ads_mu_);
+        for (auto& p : subscription_map) {
+          const std::string& type_url = p.first;
+          SubscriptionNameMap& subscription_name_map = p.second;
+          for (auto& q : subscription_name_map) {
+            const std::string& resource_name = q.first;
+            SubscriptionState& subscription_state = q.second;
+            ResourceNameMap& resource_name_map =
+                parent_->resource_map_[type_url].resource_name_map;
+            ResourceState& resource_state = resource_name_map[resource_name];
+            resource_state.subscriptions.erase(&subscription_state);
+          }
+        }
+      }
+      gpr_log(GPR_INFO, "ADS[%p]: StreamAggregatedResources done", this);
+      parent_->RemoveClient(context->peer());
+      return Status::OK;
+    }
+
+   private:
+    // NB: clang's annotalysis is confused by the use of inner template
+    // classes here and *ignores* the exclusive lock annotation on some
+    // functions. See https://bugs.llvm.org/show_bug.cgi?id=51368.
+    //
+    // This class is used for a dual purpose:
+    // - it convinces clang that the lock is held in a given scope
+    // - when used in a function that is annotated to require the inner lock it
+    //   will cause compilation to fail if the upstream bug is fixed!
+    //
+    // If you arrive here because of a compilation failure, that might mean the
+    // clang bug is fixed! Please report that on the ticket.
+    //
+    // Since the buggy compiler will still need to be supported, consider
+    // wrapping this class in a compiler version #if and replace its usage
+    // with a macro whose expansion is conditional on the compiler version. In
+    // time (years? decades?) this code can be deleted altogether.
+    class ABSL_SCOPED_LOCKABLE NoopMutexLock {
+     public:
+      explicit NoopMutexLock(grpc_core::Mutex& mu)
+          ABSL_EXCLUSIVE_LOCK_FUNCTION(mu) {}
+      ~NoopMutexLock() ABSL_UNLOCK_FUNCTION() {}
+    };
+    // Processes a response read from the client.
+    // Populates response if needed.
+    void ProcessRequest(const DiscoveryRequest& request,
+                        const std::string& v3_resource_type,
+                        UpdateQueue* update_queue,
+                        SubscriptionMap* subscription_map,
+                        SentState* sent_state,
+                        absl::optional<DiscoveryResponse>* response)
+        ABSL_EXCLUSIVE_LOCKS_REQUIRED(parent_->ads_mu_) {
+      NoopMutexLock mu(parent_->ads_mu_);
+      // Check the nonce sent by the client, if any.
+      // (This will be absent on the first request on a stream.)
+      if (request.response_nonce().empty()) {
+        int client_resource_type_version = 0;
+        if (!request.version_info().empty()) {
+          GPR_ASSERT(absl::SimpleAtoi(request.version_info(),
+                                      &client_resource_type_version));
+        }
+        EXPECT_GE(client_resource_type_version,
+                  parent_->resource_type_min_versions_[v3_resource_type])
+            << "resource_type: " << v3_resource_type;
+      } else {
+        int client_nonce;
+        GPR_ASSERT(absl::SimpleAtoi(request.response_nonce(), &client_nonce));
+        // Ignore requests with stale nonces.
+        if (client_nonce < sent_state->nonce) return;
+        // Check for ACK or NACK.
+        auto it = parent_->resource_type_response_state_.find(v3_resource_type);
+        if (it != parent_->resource_type_response_state_.end()) {
+          if (!request.has_error_detail()) {
+            it->second.state = ResponseState::ACKED;
+            it->second.error_message.clear();
+            gpr_log(GPR_INFO,
+                    "ADS[%p]: client ACKed resource_type=%s version=%s", this,
+                    request.type_url().c_str(), request.version_info().c_str());
+          } else {
+            it->second.state = ResponseState::NACKED;
+            EXPECT_EQ(request.error_detail().code(),
+                      GRPC_STATUS_INVALID_ARGUMENT);
+            it->second.error_message = request.error_detail().message();
+            gpr_log(GPR_INFO,
+                    "ADS[%p]: client NACKed resource_type=%s version=%s: %s",
+                    this, request.type_url().c_str(),
+                    request.version_info().c_str(),
+                    it->second.error_message.c_str());
+          }
+        }
+      }
+      // Ignore resource types as requested by tests.
+      if (parent_->resource_types_to_ignore_.find(v3_resource_type) !=
+          parent_->resource_types_to_ignore_.end()) {
+        return;
+      }
+      // Look at all the resource names in the request.
+      auto& subscription_name_map = (*subscription_map)[v3_resource_type];
+      auto& resource_type_state = parent_->resource_map_[v3_resource_type];
+      auto& resource_name_map = resource_type_state.resource_name_map;
+      std::set<std::string> resources_in_current_request;
+      std::set<std::string> resources_added_to_response;
+      for (const std::string& resource_name : request.resource_names()) {
+        resources_in_current_request.emplace(resource_name);
+        auto& subscription_state = subscription_name_map[resource_name];
+        auto& resource_state = resource_name_map[resource_name];
+        // Subscribe if needed.
+        // Send the resource in the response if either (a) this is
+        // a new subscription or (b) there is an updated version of
+        // this resource to send.
+        if (parent_->MaybeSubscribe(v3_resource_type, resource_name,
+                                    &subscription_state, &resource_state,
+                                    update_queue) ||
+            ClientNeedsResourceUpdate(resource_type_state, resource_state,
+                                      sent_state->resource_type_version)) {
+          gpr_log(GPR_INFO, "ADS[%p]: Sending update for type=%s name=%s", this,
+                  request.type_url().c_str(), resource_name.c_str());
+          resources_added_to_response.emplace(resource_name);
+          if (!response->has_value()) response->emplace();
+          if (resource_state.resource.has_value()) {
+            auto* resource = (*response)->add_resources();
+            resource->CopyFrom(resource_state.resource.value());
+            if (is_v2_) {
+              resource->set_type_url(request.type_url());
+            }
+          }
+        } else {
+          gpr_log(GPR_INFO,
+                  "ADS[%p]: client does not need update for type=%s name=%s",
+                  this, request.type_url().c_str(), resource_name.c_str());
+        }
+      }
+      // Process unsubscriptions for any resource no longer
+      // present in the request's resource list.
+      parent_->ProcessUnsubscriptions(
+          v3_resource_type, resources_in_current_request,
+          &subscription_name_map, &resource_name_map);
+      // Construct response if needed.
+      if (!resources_added_to_response.empty()) {
+        CompleteBuildingDiscoveryResponse(
+            v3_resource_type, request.type_url(),
+            resource_type_state.resource_type_version, subscription_name_map,
+            resources_added_to_response, sent_state, &response->value());
+      }
+    }
+
+    // Processes a resource update from the test.
+    // Populates response if needed.
+    void ProcessUpdate(const std::string& resource_type,
+                       const std::string& resource_name,
+                       SubscriptionMap* subscription_map, SentState* sent_state,
+                       absl::optional<DiscoveryResponse>* response)
+        ABSL_EXCLUSIVE_LOCKS_REQUIRED(parent_->ads_mu_) {
+      NoopMutexLock mu(parent_->ads_mu_);
+      const std::string v2_resource_type = TypeUrlToV2(resource_type);
+      gpr_log(GPR_INFO, "ADS[%p]: Received update for type=%s name=%s", this,
+              resource_type.c_str(), resource_name.c_str());
+      auto& subscription_name_map = (*subscription_map)[resource_type];
+      auto& resource_type_state = parent_->resource_map_[resource_type];
+      auto& resource_name_map = resource_type_state.resource_name_map;
+      auto it = subscription_name_map.find(resource_name);
+      if (it != subscription_name_map.end()) {
+        ResourceState& resource_state = resource_name_map[resource_name];
+        if (ClientNeedsResourceUpdate(resource_type_state, resource_state,
+                                      sent_state->resource_type_version)) {
+          gpr_log(GPR_INFO, "ADS[%p]: Sending update for type=%s name=%s", this,
+                  resource_type.c_str(), resource_name.c_str());
+          response->emplace();
+          if (resource_state.resource.has_value()) {
+            auto* resource = (*response)->add_resources();
+            resource->CopyFrom(resource_state.resource.value());
+            if (is_v2_) {
+              resource->set_type_url(v2_resource_type);
+            }
+          }
+          CompleteBuildingDiscoveryResponse(
+              resource_type, v2_resource_type,
+              resource_type_state.resource_type_version, subscription_name_map,
+              {resource_name}, sent_state, &response->value());
+        }
+      }
+    }
+
+    // Starting a thread to do blocking read on the stream until cancel.
+    void BlockingRead(Stream* stream, std::deque<DiscoveryRequest>* requests,
+                      bool* stream_closed) {
+      DiscoveryRequest request;
+      bool seen_first_request = false;
+      while (stream->Read(&request)) {
+        if (!seen_first_request) {
+          EXPECT_TRUE(request.has_node());
+          ASSERT_FALSE(request.node().client_features().empty());
+          EXPECT_EQ(request.node().client_features(0),
+                    "envoy.lb.does_not_support_overprovisioning");
+          CheckBuildVersion(request);
+          seen_first_request = true;
+        }
+        {
+          grpc_core::MutexLock lock(&parent_->ads_mu_);
+          requests->emplace_back(std::move(request));
+        }
+      }
+      gpr_log(GPR_INFO, "ADS[%p]: Null read, stream closed", this);
+      grpc_core::MutexLock lock(&parent_->ads_mu_);
+      *stream_closed = true;
+    }
+
+    // Completing the building a DiscoveryResponse by adding common information
+    // for all resources and by adding all subscribed resources for LDS and CDS.
+    void CompleteBuildingDiscoveryResponse(
+        const std::string& resource_type, const std::string& v2_resource_type,
+        const int version, const SubscriptionNameMap& subscription_name_map,
+        const std::set<std::string>& resources_added_to_response,
+        SentState* sent_state, DiscoveryResponse* response)
+        ABSL_EXCLUSIVE_LOCKS_REQUIRED(parent_->ads_mu_) {
+      NoopMutexLock mu(parent_->ads_mu_);
+      auto& response_state =
+          parent_->resource_type_response_state_[resource_type];
+      if (response_state.state == ResponseState::NOT_SENT) {
+        response_state.state = ResponseState::SENT;
+      }
+      response->set_type_url(is_v2_ ? v2_resource_type : resource_type);
+      response->set_version_info(std::to_string(version));
+      response->set_nonce(std::to_string(++sent_state->nonce));
+      if (resource_type == kLdsTypeUrl || resource_type == kCdsTypeUrl) {
+        // For LDS and CDS we must send back all subscribed resources
+        // (even the unchanged ones)
+        for (const auto& p : subscription_name_map) {
+          const std::string& resource_name = p.first;
+          if (resources_added_to_response.find(resource_name) ==
+              resources_added_to_response.end()) {
+            ResourceNameMap& resource_name_map =
+                parent_->resource_map_[resource_type].resource_name_map;
+            const ResourceState& resource_state =
+                resource_name_map[resource_name];
+            if (resource_state.resource.has_value()) {
+              auto* resource = response->add_resources();
+              resource->CopyFrom(resource_state.resource.value());
+              if (is_v2_) {
+                resource->set_type_url(v2_resource_type);
+              }
+            }
+          }
+        }
+      }
+      sent_state->resource_type_version = version;
+    }
+
+    static std::string TypeUrlToV2(const std::string& resource_type) {
+      if (resource_type == kLdsTypeUrl) return kLdsV2TypeUrl;
+      if (resource_type == kRdsTypeUrl) return kRdsV2TypeUrl;
+      if (resource_type == kCdsTypeUrl) return kCdsV2TypeUrl;
+      if (resource_type == kEdsTypeUrl) return kEdsV2TypeUrl;
+      return resource_type;
+    }
+
+    static std::string TypeUrlToV3(const std::string& resource_type) {
+      if (resource_type == kLdsV2TypeUrl) return kLdsTypeUrl;
+      if (resource_type == kRdsV2TypeUrl) return kRdsTypeUrl;
+      if (resource_type == kCdsV2TypeUrl) return kCdsTypeUrl;
+      if (resource_type == kEdsV2TypeUrl) return kEdsTypeUrl;
+      return resource_type;
+    }
+
+    static void CheckBuildVersion(
+        const ::envoy::api::v2::DiscoveryRequest& request) {
+      EXPECT_FALSE(request.node().build_version().empty());
+    }
+
+    static void CheckBuildVersion(
+        const ::envoy::service::discovery::v3::DiscoveryRequest& /*request*/) {}
+
+    AdsServiceImpl* parent_;
+    const bool is_v2_;
+  };
+
+  // Checks whether the client needs to receive a newer version of
+  // the resource.
+  static bool ClientNeedsResourceUpdate(
+      const ResourceTypeState& resource_type_state,
+      const ResourceState& resource_state, int client_resource_type_version);
+
+  // Subscribes to a resource if not already subscribed:
+  // 1. Sets the update_queue field in subscription_state.
+  // 2. Adds subscription_state to resource_state->subscriptions.
+  bool MaybeSubscribe(const std::string& resource_type,
+                      const std::string& resource_name,
+                      SubscriptionState* subscription_state,
+                      ResourceState* resource_state, UpdateQueue* update_queue);
+
+  // Removes subscriptions for resources no longer present in the
+  // current request.
+  void ProcessUnsubscriptions(
+      const std::string& resource_type,
+      const std::set<std::string>& resources_in_current_request,
+      SubscriptionNameMap* subscription_name_map,
+      ResourceNameMap* resource_name_map);
+
+  void AddClient(const std::string& client) {
+    grpc_core::MutexLock lock(&clients_mu_);
+    clients_.insert(client);
+  }
+
+  void RemoveClient(const std::string& client) {
+    grpc_core::MutexLock lock(&clients_mu_);
+    clients_.erase(client);
+  }
+
+  RpcService<::envoy::service::discovery::v2::AggregatedDiscoveryService,
+             ::envoy::api::v2::DiscoveryRequest,
+             ::envoy::api::v2::DiscoveryResponse>
+      v2_rpc_service_;
+  RpcService<::envoy::service::discovery::v3::AggregatedDiscoveryService,
+             ::envoy::service::discovery::v3::DiscoveryRequest,
+             ::envoy::service::discovery::v3::DiscoveryResponse>
+      v3_rpc_service_;
+
+  std::atomic_bool seen_v2_client_{false};
+  std::atomic_bool seen_v3_client_{false};
+
+  grpc_core::CondVar ads_cond_;
+  grpc_core::Mutex ads_mu_;
+  bool ads_done_ ABSL_GUARDED_BY(ads_mu_) = false;
+  std::map<std::string /* type_url */, ResponseState>
+      resource_type_response_state_ ABSL_GUARDED_BY(ads_mu_);
+  std::set<std::string /*resource_type*/> resource_types_to_ignore_
+      ABSL_GUARDED_BY(ads_mu_);
+  std::map<std::string /*resource_type*/, int> resource_type_min_versions_
+      ABSL_GUARDED_BY(ads_mu_);
+  // An instance data member containing the current state of all resources.
+  // Note that an entry will exist whenever either of the following is true:
+  // - The resource exists (i.e., has been created by SetResource() and has not
+  //   yet been destroyed by UnsetResource()).
+  // - There is at least one subscription for the resource.
+  ResourceMap resource_map_ ABSL_GUARDED_BY(ads_mu_);
+
+  grpc_core::Mutex clients_mu_;
+  std::set<std::string> clients_ ABSL_GUARDED_BY(clients_mu_);
+};
+
+// An LRS service implementation.
+class LrsServiceImpl : public std::enable_shared_from_this<LrsServiceImpl> {
+ public:
+  // Stats reported by client.
+  class ClientStats {
+   public:
+    // Stats for a given locality.
+    struct LocalityStats {
+      LocalityStats() {}
+
+      // Converts from proto message class.
+      template <class UpstreamLocalityStats>
+      explicit LocalityStats(
+          const UpstreamLocalityStats& upstream_locality_stats)
+          : total_successful_requests(
+                upstream_locality_stats.total_successful_requests()),
+            total_requests_in_progress(
+                upstream_locality_stats.total_requests_in_progress()),
+            total_error_requests(
+                upstream_locality_stats.total_error_requests()),
+            total_issued_requests(
+                upstream_locality_stats.total_issued_requests()) {}
+
+      LocalityStats& operator+=(const LocalityStats& other) {
+        total_successful_requests += other.total_successful_requests;
+        total_requests_in_progress += other.total_requests_in_progress;
+        total_error_requests += other.total_error_requests;
+        total_issued_requests += other.total_issued_requests;
+        return *this;
+      }
+
+      uint64_t total_successful_requests = 0;
+      uint64_t total_requests_in_progress = 0;
+      uint64_t total_error_requests = 0;
+      uint64_t total_issued_requests = 0;
+    };
+
+    ClientStats() {}
+
+    // Converts from proto message class.
+    template <class ClusterStats>
+    explicit ClientStats(const ClusterStats& cluster_stats)
+        : cluster_name_(cluster_stats.cluster_name()),
+          total_dropped_requests_(cluster_stats.total_dropped_requests()) {
+      for (const auto& input_locality_stats :
+           cluster_stats.upstream_locality_stats()) {
+        locality_stats_.emplace(input_locality_stats.locality().sub_zone(),
+                                LocalityStats(input_locality_stats));
+      }
+      for (const auto& input_dropped_requests :
+           cluster_stats.dropped_requests()) {
+        dropped_requests_.emplace(input_dropped_requests.category(),
+                                  input_dropped_requests.dropped_count());
+      }
+    }
+
+    const std::string& cluster_name() const { return cluster_name_; }
+
+    const std::map<std::string, LocalityStats>& locality_stats() const {
+      return locality_stats_;
+    }
+
+    uint64_t total_successful_requests() const;
+    uint64_t total_requests_in_progress() const;
+    uint64_t total_error_requests() const;
+    uint64_t total_issued_requests() const;
+
+    uint64_t total_dropped_requests() const { return total_dropped_requests_; }
+
+    uint64_t dropped_requests(const std::string& category) const;
+
+    ClientStats& operator+=(const ClientStats& other);
+
+   private:
+    std::string cluster_name_;
+    std::map<std::string, LocalityStats> locality_stats_;
+    uint64_t total_dropped_requests_ = 0;
+    std::map<std::string, uint64_t> dropped_requests_;
+  };
+
+  LrsServiceImpl(int client_load_reporting_interval_seconds,
+                 std::set<std::string> cluster_names)
+      : v2_rpc_service_(this),
+        v3_rpc_service_(this),
+        client_load_reporting_interval_seconds_(
+            client_load_reporting_interval_seconds),
+        cluster_names_(std::move(cluster_names)) {}
+
+  ::envoy::service::load_stats::v2::LoadReportingService::Service*
+  v2_rpc_service() {
+    return &v2_rpc_service_;
+  }
+
+  ::envoy::service::load_stats::v3::LoadReportingService::Service*
+  v3_rpc_service() {
+    return &v3_rpc_service_;
+  }
+
+  size_t request_count() {
+    return v2_rpc_service_.request_count() + v3_rpc_service_.request_count();
+  }
+
+  size_t response_count() {
+    return v2_rpc_service_.response_count() + v3_rpc_service_.response_count();
+  }
+
+  // Must be called before the LRS call is started.
+  void set_send_all_clusters(bool send_all_clusters) {
+    send_all_clusters_ = send_all_clusters;
+  }
+  void set_cluster_names(const std::set<std::string>& cluster_names) {
+    cluster_names_ = cluster_names;
+  }
+
+  void Start() ABSL_LOCKS_EXCLUDED(lrs_mu_, load_report_mu_);
+
+  void Shutdown();
+
+  std::vector<ClientStats> WaitForLoadReport();
+
+ private:
+  // Templated RPC service implementation, works for both v2 and v3.
+  template <class RpcApi, class LoadStatsRequest, class LoadStatsResponse>
+  class RpcService : public CountedService<typename RpcApi::Service> {
+   public:
+    using Stream = ServerReaderWriter<LoadStatsResponse, LoadStatsRequest>;
+
+    explicit RpcService(LrsServiceImpl* parent) : parent_(parent) {}
+
+    Status StreamLoadStats(ServerContext* /*context*/,
+                           Stream* stream) override {
+      gpr_log(GPR_INFO, "LRS[%p]: StreamLoadStats starts", this);
+      EXPECT_GT(parent_->client_load_reporting_interval_seconds_, 0);
+      // Take a reference of the LrsServiceImpl object, reference will go
+      // out of scope after this method exits.
+      std::shared_ptr<LrsServiceImpl> lrs_service_impl =
+          parent_->shared_from_this();
+      // Read initial request.
+      LoadStatsRequest request;
+      if (stream->Read(&request)) {
+        CountedService<typename RpcApi::Service>::IncreaseRequestCount();
+        // Verify client features.
+        EXPECT_THAT(
+            request.node().client_features(),
+            ::testing::Contains("envoy.lrs.supports_send_all_clusters"));
+        // Send initial response.
+        LoadStatsResponse response;
+        if (parent_->send_all_clusters_) {
+          response.set_send_all_clusters(true);
+        } else {
+          for (const std::string& cluster_name : parent_->cluster_names_) {
+            response.add_clusters(cluster_name);
+          }
+        }
+        response.mutable_load_reporting_interval()->set_seconds(
+            parent_->client_load_reporting_interval_seconds_);
+        stream->Write(response);
+        CountedService<typename RpcApi::Service>::IncreaseResponseCount();
+        // Wait for report.
+        request.Clear();
+        while (stream->Read(&request)) {
+          gpr_log(GPR_INFO, "LRS[%p]: received client load report message: %s",
+                  this, request.DebugString().c_str());
+          std::vector<ClientStats> stats;
+          for (const auto& cluster_stats : request.cluster_stats()) {
+            stats.emplace_back(cluster_stats);
+          }
+          grpc_core::MutexLock lock(&parent_->load_report_mu_);
+          parent_->result_queue_.emplace_back(std::move(stats));
+          if (parent_->load_report_cond_ != nullptr) {
+            parent_->load_report_cond_->Signal();
+          }
+        }
+        // Wait until notified done.
+        grpc_core::MutexLock lock(&parent_->lrs_mu_);
+        while (!parent_->lrs_done_) {
+          parent_->lrs_cv_.Wait(&parent_->lrs_mu_);
+        }
+      }
+      gpr_log(GPR_INFO, "LRS[%p]: StreamLoadStats done", this);
+      return Status::OK;
+    }
+
+   private:
+    LrsServiceImpl* parent_;
+  };
+
+  RpcService<::envoy::service::load_stats::v2::LoadReportingService,
+             ::envoy::service::load_stats::v2::LoadStatsRequest,
+             ::envoy::service::load_stats::v2::LoadStatsResponse>
+      v2_rpc_service_;
+  RpcService<::envoy::service::load_stats::v3::LoadReportingService,
+             ::envoy::service::load_stats::v3::LoadStatsRequest,
+             ::envoy::service::load_stats::v3::LoadStatsResponse>
+      v3_rpc_service_;
+
+  const int client_load_reporting_interval_seconds_;
+  bool send_all_clusters_ = false;
+  std::set<std::string> cluster_names_;
+
+  grpc_core::CondVar lrs_cv_;
+  grpc_core::Mutex lrs_mu_;
+  bool lrs_done_ ABSL_GUARDED_BY(lrs_mu_) = false;
+
+  grpc_core::Mutex load_report_mu_;
+  grpc_core::CondVar* load_report_cond_ ABSL_GUARDED_BY(load_report_mu_) =
+      nullptr;
+  std::deque<std::vector<ClientStats>> result_queue_
+      ABSL_GUARDED_BY(load_report_mu_);
+};
+
+}  // namespace testing
+}  // namespace grpc
+
+#endif  // GRPC_TEST_CPP_END2END_XDS_XDS_SERVER_H
diff --git a/test/cpp/end2end/xds_end2end_test.cc b/test/cpp/end2end/xds_end2end_test.cc
deleted file mode 100644 (file)
index 8f48005..0000000
+++ /dev/null
@@ -1,13630 +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 <deque>
-#include <memory>
-#include <mutex>
-#include <numeric>
-#include <set>
-#include <sstream>
-#include <string>
-#include <thread>
-#include <vector>
-
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-#include "absl/functional/bind_front.h"
-#include "absl/memory/memory.h"
-#include "absl/strings/match.h"
-#include "absl/strings/str_cat.h"
-#include "absl/strings/str_format.h"
-#include "absl/strings/str_join.h"
-#include "absl/types/optional.h"
-
-#include <grpc/grpc.h>
-#include <grpc/grpc_security.h>
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/time.h>
-#include <grpcpp/channel.h>
-#include <grpcpp/client_context.h>
-#include <grpcpp/create_channel.h>
-#include <grpcpp/security/tls_certificate_provider.h>
-#include <grpcpp/server.h>
-#include <grpcpp/server_builder.h>
-#include <grpcpp/xds_server_builder.h>
-
-#include "src/core/ext/filters/client_channel/backup_poller.h"
-#include "src/core/ext/filters/client_channel/lb_policy/xds/xds_channel_args.h"
-#include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h"
-#include "src/core/ext/filters/client_channel/server_address.h"
-#include "src/core/ext/xds/certificate_provider_registry.h"
-#include "src/core/ext/xds/xds_api.h"
-#include "src/core/ext/xds/xds_channel_args.h"
-#include "src/core/ext/xds/xds_client.h"
-#include "src/core/lib/address_utils/parse_address.h"
-#include "src/core/lib/channel/channel_args.h"
-#include "src/core/lib/gpr/env.h"
-#include "src/core/lib/gpr/string.h"
-#include "src/core/lib/gpr/time_precise.h"
-#include "src/core/lib/gpr/tmpfile.h"
-#include "src/core/lib/gprpp/ref_counted_ptr.h"
-#include "src/core/lib/gprpp/sync.h"
-#include "src/core/lib/gprpp/time_util.h"
-#include "src/core/lib/iomgr/load_file.h"
-#include "src/core/lib/iomgr/sockaddr.h"
-#include "src/core/lib/security/credentials/fake/fake_credentials.h"
-#include "src/cpp/client/secure_credentials.h"
-#include "src/cpp/server/secure_server_credentials.h"
-#include "src/proto/grpc/testing/echo.grpc.pb.h"
-#include "src/proto/grpc/testing/xds/ads_for_test.grpc.pb.h"
-#include "src/proto/grpc/testing/xds/cds_for_test.grpc.pb.h"
-#include "src/proto/grpc/testing/xds/eds_for_test.grpc.pb.h"
-#include "src/proto/grpc/testing/xds/lds_rds_for_test.grpc.pb.h"
-#include "src/proto/grpc/testing/xds/lrs_for_test.grpc.pb.h"
-#include "src/proto/grpc/testing/xds/v3/ads.grpc.pb.h"
-#include "src/proto/grpc/testing/xds/v3/aggregate_cluster.grpc.pb.h"
-#include "src/proto/grpc/testing/xds/v3/cluster.grpc.pb.h"
-#include "src/proto/grpc/testing/xds/v3/discovery.grpc.pb.h"
-#include "src/proto/grpc/testing/xds/v3/endpoint.grpc.pb.h"
-#include "src/proto/grpc/testing/xds/v3/fault.grpc.pb.h"
-#include "src/proto/grpc/testing/xds/v3/http_connection_manager.grpc.pb.h"
-#include "src/proto/grpc/testing/xds/v3/listener.grpc.pb.h"
-#include "src/proto/grpc/testing/xds/v3/lrs.grpc.pb.h"
-#include "src/proto/grpc/testing/xds/v3/route.grpc.pb.h"
-#include "src/proto/grpc/testing/xds/v3/router.grpc.pb.h"
-#include "src/proto/grpc/testing/xds/v3/tls.grpc.pb.h"
-#include "test/core/util/port.h"
-#include "test/core/util/resolve_localhost_ip46.h"
-#include "test/core/util/test_config.h"
-#include "test/cpp/end2end/test_service_impl.h"
-#include "test/cpp/util/test_config.h"
-
-#ifndef DISABLED_XDS_PROTO_IN_CC
-#include "src/cpp/server/csds/csds.h"
-#include "src/proto/grpc/testing/xds/v3/csds.grpc.pb.h"
-#endif  // DISABLED_XDS_PROTO_IN_CC
-
-namespace grpc {
-namespace testing {
-namespace {
-
-using std::chrono::system_clock;
-
-#ifndef DISABLED_XDS_PROTO_IN_CC
-using ::envoy::admin::v3::ClientResourceStatus;
-#endif  // DISABLED_XDS_PROTO_IN_CC
-using ::envoy::config::cluster::v3::CircuitBreakers;
-using ::envoy::config::cluster::v3::Cluster;
-using ::envoy::config::cluster::v3::CustomClusterType;
-using ::envoy::config::cluster::v3::RoutingPriority;
-using ::envoy::config::endpoint::v3::ClusterLoadAssignment;
-using ::envoy::config::endpoint::v3::HealthStatus;
-using ::envoy::config::listener::v3::FilterChainMatch;
-using ::envoy::config::listener::v3::Listener;
-using ::envoy::config::route::v3::RouteConfiguration;
-using ::envoy::extensions::clusters::aggregate::v3::ClusterConfig;
-using ::envoy::extensions::filters::http::fault::v3::HTTPFault;
-using ::envoy::extensions::filters::network::http_connection_manager::v3::
-    HttpConnectionManager;
-using ::envoy::extensions::filters::network::http_connection_manager::v3::
-    HttpFilter;
-using ::envoy::extensions::transport_sockets::tls::v3::DownstreamTlsContext;
-using ::envoy::extensions::transport_sockets::tls::v3::UpstreamTlsContext;
-using ::envoy::type::matcher::v3::StringMatcher;
-using ::envoy::type::v3::FractionalPercent;
-
-constexpr char kLdsTypeUrl[] =
-    "type.googleapis.com/envoy.config.listener.v3.Listener";
-constexpr char kRdsTypeUrl[] =
-    "type.googleapis.com/envoy.config.route.v3.RouteConfiguration";
-constexpr char kCdsTypeUrl[] =
-    "type.googleapis.com/envoy.config.cluster.v3.Cluster";
-constexpr char kEdsTypeUrl[] =
-    "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment";
-
-constexpr char kLdsV2TypeUrl[] = "type.googleapis.com/envoy.api.v2.Listener";
-constexpr char kRdsV2TypeUrl[] =
-    "type.googleapis.com/envoy.api.v2.RouteConfiguration";
-constexpr char kCdsV2TypeUrl[] = "type.googleapis.com/envoy.api.v2.Cluster";
-constexpr char kEdsV2TypeUrl[] =
-    "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment";
-
-constexpr char kDefaultLocalityRegion[] = "xds_default_locality_region";
-constexpr char kDefaultLocalityZone[] = "xds_default_locality_zone";
-constexpr char kLbDropType[] = "lb";
-constexpr char kThrottleDropType[] = "throttle";
-constexpr char kServerName[] = "server.example.com";
-constexpr char kDefaultRouteConfigurationName[] = "route_config_name";
-constexpr char kDefaultClusterName[] = "cluster_name";
-constexpr char kDefaultEdsServiceName[] = "eds_service_name";
-constexpr int kDefaultLocalityWeight = 3;
-constexpr int kDefaultLocalityPriority = 0;
-
-constexpr char kRequestMessage[] = "Live long and prosper.";
-constexpr char kDefaultServiceConfig[] =
-    "{\n"
-    "  \"loadBalancingConfig\":[\n"
-    "    { \"does_not_exist\":{} },\n"
-    "    { \"xds_cluster_resolver_experimental\":{\n"
-    "      \"discoveryMechanisms\": [\n"
-    "      { \"clusterName\": \"server.example.com\",\n"
-    "        \"type\": \"EDS\",\n"
-    "        \"lrsLoadReportingServerName\": \"\"\n"
-    "      } ]\n"
-    "    } }\n"
-    "  ]\n"
-    "}";
-constexpr char kDefaultServiceConfigWithoutLoadReporting[] =
-    "{\n"
-    "  \"loadBalancingConfig\":[\n"
-    "    { \"does_not_exist\":{} },\n"
-    "    { \"xds_cluster_resolver_experimental\":{\n"
-    "      \"discoveryMechanisms\": [\n"
-    "      { \"clusterName\": \"server.example.com\",\n"
-    "        \"type\": \"EDS\"\n"
-    "      } ]\n"
-    "    } }\n"
-    "  ]\n"
-    "}";
-
-constexpr char kBootstrapFileV3[] =
-    "{\n"
-    "  \"xds_servers\": [\n"
-    "    {\n"
-    "      \"server_uri\": \"fake:///xds_server\",\n"
-    "      \"channel_creds\": [\n"
-    "        {\n"
-    "          \"type\": \"fake\"\n"
-    "        }\n"
-    "      ],\n"
-    "      \"server_features\": [\"xds_v3\"]\n"
-    "    }\n"
-    "  ],\n"
-    "  \"node\": {\n"
-    "    \"id\": \"xds_end2end_test\",\n"
-    "    \"cluster\": \"test\",\n"
-    "    \"metadata\": {\n"
-    "      \"foo\": \"bar\"\n"
-    "    },\n"
-    "    \"locality\": {\n"
-    "      \"region\": \"corp\",\n"
-    "      \"zone\": \"svl\",\n"
-    "      \"sub_zone\": \"mp3\"\n"
-    "    }\n"
-    "  },\n"
-    "  \"server_listener_resource_name_template\": "
-    "\"grpc/server?xds.resource.listening_address=%s\",\n"
-    "  \"certificate_providers\": {\n"
-    "    \"fake_plugin1\": {\n"
-    "      \"plugin_name\": \"fake1\"\n"
-    "    },\n"
-    "    \"fake_plugin2\": {\n"
-    "      \"plugin_name\": \"fake2\"\n"
-    "    },\n"
-    "    \"file_plugin\": {\n"
-    "      \"plugin_name\": \"file_watcher\",\n"
-    "      \"config\": {\n"
-    "        \"certificate_file\": \"src/core/tsi/test_creds/client.pem\",\n"
-    "        \"private_key_file\": \"src/core/tsi/test_creds/client.key\",\n"
-    "        \"ca_certificate_file\": \"src/core/tsi/test_creds/ca.pem\"\n"
-    "      }"
-    "    }\n"
-    "  }\n"
-    "}\n";
-
-constexpr char kBootstrapFileV2[] =
-    "{\n"
-    "  \"xds_servers\": [\n"
-    "    {\n"
-    "      \"server_uri\": \"fake:///xds_server\",\n"
-    "      \"channel_creds\": [\n"
-    "        {\n"
-    "          \"type\": \"fake\"\n"
-    "        }\n"
-    "      ]\n"
-    "    }\n"
-    "  ],\n"
-    "  \"node\": {\n"
-    "    \"id\": \"xds_end2end_test\",\n"
-    "    \"cluster\": \"test\",\n"
-    "    \"metadata\": {\n"
-    "      \"foo\": \"bar\"\n"
-    "    },\n"
-    "    \"locality\": {\n"
-    "      \"region\": \"corp\",\n"
-    "      \"zone\": \"svl\",\n"
-    "      \"sub_zone\": \"mp3\"\n"
-    "    }\n"
-    "  }\n"
-    "}\n";
-constexpr char kCaCertPath[] = "src/core/tsi/test_creds/ca.pem";
-constexpr char kServerCertPath[] = "src/core/tsi/test_creds/server1.pem";
-constexpr char kServerKeyPath[] = "src/core/tsi/test_creds/server1.key";
-constexpr char kClientCertPath[] = "src/core/tsi/test_creds/client.pem";
-constexpr char kClientKeyPath[] = "src/core/tsi/test_creds/client.key";
-constexpr char kBadClientCertPath[] = "src/core/tsi/test_creds/badclient.pem";
-constexpr char kBadClientKeyPath[] = "src/core/tsi/test_creds/badclient.key";
-
-char* g_bootstrap_file_v3;
-char* g_bootstrap_file_v2;
-
-void WriteBootstrapFiles() {
-  char* bootstrap_file;
-  FILE* out = gpr_tmpfile("xds_bootstrap_v3", &bootstrap_file);
-  fputs(kBootstrapFileV3, out);
-  fclose(out);
-  g_bootstrap_file_v3 = bootstrap_file;
-  out = gpr_tmpfile("xds_bootstrap_v2", &bootstrap_file);
-  fputs(kBootstrapFileV2, out);
-  fclose(out);
-  g_bootstrap_file_v2 = bootstrap_file;
-}
-
-template <typename ServiceType>
-class CountedService : public ServiceType {
- public:
-  size_t request_count() {
-    grpc_core::MutexLock lock(&mu_);
-    return request_count_;
-  }
-
-  size_t response_count() {
-    grpc_core::MutexLock lock(&mu_);
-    return response_count_;
-  }
-
-  void IncreaseResponseCount() {
-    grpc_core::MutexLock lock(&mu_);
-    ++response_count_;
-  }
-  void IncreaseRequestCount() {
-    grpc_core::MutexLock lock(&mu_);
-    ++request_count_;
-  }
-
-  void ResetCounters() {
-    grpc_core::MutexLock lock(&mu_);
-    request_count_ = 0;
-    response_count_ = 0;
-  }
-
- private:
-  grpc_core::Mutex mu_;
-  size_t request_count_ ABSL_GUARDED_BY(mu_) = 0;
-  size_t response_count_ ABSL_GUARDED_BY(mu_) = 0;
-};
-
-template <typename RpcService>
-class BackendServiceImpl
-    : public CountedService<TestMultipleServiceImpl<RpcService>> {
- public:
-  BackendServiceImpl() {}
-
-  Status Echo(ServerContext* context, const EchoRequest* request,
-              EchoResponse* response) override {
-    auto peer_identity = context->auth_context()->GetPeerIdentity();
-    CountedService<TestMultipleServiceImpl<RpcService>>::IncreaseRequestCount();
-    const auto status =
-        TestMultipleServiceImpl<RpcService>::Echo(context, request, response);
-    CountedService<
-        TestMultipleServiceImpl<RpcService>>::IncreaseResponseCount();
-    {
-      grpc_core::MutexLock lock(&mu_);
-      clients_.insert(context->peer());
-      last_peer_identity_.clear();
-      for (const auto& entry : peer_identity) {
-        last_peer_identity_.emplace_back(entry.data(), entry.size());
-      }
-    }
-    return status;
-  }
-
-  Status Echo1(ServerContext* context, const EchoRequest* request,
-               EchoResponse* response) override {
-    return Echo(context, request, response);
-  }
-
-  Status Echo2(ServerContext* context, const EchoRequest* request,
-               EchoResponse* response) override {
-    return Echo(context, request, response);
-  }
-
-  void Start() {}
-  void Shutdown() {}
-
-  std::set<std::string> clients() {
-    grpc_core::MutexLock lock(&mu_);
-    return clients_;
-  }
-
-  const std::vector<std::string>& last_peer_identity() {
-    grpc_core::MutexLock lock(&mu_);
-    return last_peer_identity_;
-  }
-
- private:
-  grpc_core::Mutex mu_;
-  std::set<std::string> clients_ ABSL_GUARDED_BY(mu_);
-  std::vector<std::string> last_peer_identity_ ABSL_GUARDED_BY(mu_);
-};
-
-class ClientStats {
- public:
-  struct LocalityStats {
-    LocalityStats() {}
-
-    // Converts from proto message class.
-    template <class UpstreamLocalityStats>
-    explicit LocalityStats(const UpstreamLocalityStats& upstream_locality_stats)
-        : total_successful_requests(
-              upstream_locality_stats.total_successful_requests()),
-          total_requests_in_progress(
-              upstream_locality_stats.total_requests_in_progress()),
-          total_error_requests(upstream_locality_stats.total_error_requests()),
-          total_issued_requests(
-              upstream_locality_stats.total_issued_requests()) {}
-
-    LocalityStats& operator+=(const LocalityStats& other) {
-      total_successful_requests += other.total_successful_requests;
-      total_requests_in_progress += other.total_requests_in_progress;
-      total_error_requests += other.total_error_requests;
-      total_issued_requests += other.total_issued_requests;
-      return *this;
-    }
-
-    uint64_t total_successful_requests = 0;
-    uint64_t total_requests_in_progress = 0;
-    uint64_t total_error_requests = 0;
-    uint64_t total_issued_requests = 0;
-  };
-
-  ClientStats() {}
-
-  // Converts from proto message class.
-  template <class ClusterStats>
-  explicit ClientStats(const ClusterStats& cluster_stats)
-      : cluster_name_(cluster_stats.cluster_name()),
-        total_dropped_requests_(cluster_stats.total_dropped_requests()) {
-    for (const auto& input_locality_stats :
-         cluster_stats.upstream_locality_stats()) {
-      locality_stats_.emplace(input_locality_stats.locality().sub_zone(),
-                              LocalityStats(input_locality_stats));
-    }
-    for (const auto& input_dropped_requests :
-         cluster_stats.dropped_requests()) {
-      dropped_requests_.emplace(input_dropped_requests.category(),
-                                input_dropped_requests.dropped_count());
-    }
-  }
-
-  const std::string& cluster_name() const { return cluster_name_; }
-
-  const std::map<std::string, LocalityStats>& locality_stats() const {
-    return locality_stats_;
-  }
-  uint64_t total_successful_requests() const {
-    uint64_t sum = 0;
-    for (auto& p : locality_stats_) {
-      sum += p.second.total_successful_requests;
-    }
-    return sum;
-  }
-  uint64_t total_requests_in_progress() const {
-    uint64_t sum = 0;
-    for (auto& p : locality_stats_) {
-      sum += p.second.total_requests_in_progress;
-    }
-    return sum;
-  }
-  uint64_t total_error_requests() const {
-    uint64_t sum = 0;
-    for (auto& p : locality_stats_) {
-      sum += p.second.total_error_requests;
-    }
-    return sum;
-  }
-  uint64_t total_issued_requests() const {
-    uint64_t sum = 0;
-    for (auto& p : locality_stats_) {
-      sum += p.second.total_issued_requests;
-    }
-    return sum;
-  }
-
-  uint64_t total_dropped_requests() const { return total_dropped_requests_; }
-
-  uint64_t dropped_requests(const std::string& category) const {
-    auto iter = dropped_requests_.find(category);
-    GPR_ASSERT(iter != dropped_requests_.end());
-    return iter->second;
-  }
-
-  ClientStats& operator+=(const ClientStats& other) {
-    for (const auto& p : other.locality_stats_) {
-      locality_stats_[p.first] += p.second;
-    }
-    total_dropped_requests_ += other.total_dropped_requests_;
-    for (const auto& p : other.dropped_requests_) {
-      dropped_requests_[p.first] += p.second;
-    }
-    return *this;
-  }
-
- private:
-  std::string cluster_name_;
-  std::map<std::string, LocalityStats> locality_stats_;
-  uint64_t total_dropped_requests_ = 0;
-  std::map<std::string, uint64_t> dropped_requests_;
-};
-
-class AdsServiceImpl : public std::enable_shared_from_this<AdsServiceImpl> {
- public:
-  struct ResponseState {
-    enum State { NOT_SENT, SENT, ACKED, NACKED };
-    State state = NOT_SENT;
-    std::string error_message;
-  };
-
-  struct EdsResourceArgs {
-    struct Endpoint {
-      explicit Endpoint(int port,
-                        HealthStatus health_status = HealthStatus::UNKNOWN,
-                        int lb_weight = 1)
-          : port(port), health_status(health_status), lb_weight(lb_weight) {}
-
-      int port;
-      HealthStatus health_status;
-      int lb_weight;
-    };
-
-    struct Locality {
-      Locality(std::string sub_zone, std::vector<Endpoint> endpoints,
-               int lb_weight = kDefaultLocalityWeight,
-               int priority = kDefaultLocalityPriority)
-          : sub_zone(std::move(sub_zone)),
-            endpoints(std::move(endpoints)),
-            lb_weight(lb_weight),
-            priority(priority) {}
-
-      const std::string sub_zone;
-      std::vector<Endpoint> endpoints;
-      int lb_weight;
-      int priority;
-    };
-
-    EdsResourceArgs() = default;
-    explicit EdsResourceArgs(std::vector<Locality> locality_list)
-        : locality_list(std::move(locality_list)) {}
-
-    std::vector<Locality> locality_list;
-    std::map<std::string, uint32_t> drop_categories;
-    FractionalPercent::DenominatorType drop_denominator =
-        FractionalPercent::MILLION;
-  };
-
-  AdsServiceImpl()
-      : v2_rpc_service_(this, /*is_v2=*/true),
-        v3_rpc_service_(this, /*is_v2=*/false) {}
-
-  bool seen_v2_client() const { return seen_v2_client_; }
-  bool seen_v3_client() const { return seen_v3_client_; }
-
-  ::envoy::service::discovery::v2::AggregatedDiscoveryService::Service*
-  v2_rpc_service() {
-    return &v2_rpc_service_;
-  }
-
-  ::envoy::service::discovery::v3::AggregatedDiscoveryService::Service*
-  v3_rpc_service() {
-    return &v3_rpc_service_;
-  }
-
-  ResponseState lds_response_state() {
-    grpc_core::MutexLock lock(&ads_mu_);
-    return resource_type_response_state_[kLdsTypeUrl];
-  }
-
-  ResponseState rds_response_state() {
-    grpc_core::MutexLock lock(&ads_mu_);
-    return resource_type_response_state_[kRdsTypeUrl];
-  }
-
-  ResponseState cds_response_state() {
-    grpc_core::MutexLock lock(&ads_mu_);
-    return resource_type_response_state_[kCdsTypeUrl];
-  }
-
-  ResponseState eds_response_state() {
-    grpc_core::MutexLock lock(&ads_mu_);
-    return resource_type_response_state_[kEdsTypeUrl];
-  }
-
-  void SetResourceIgnore(const std::string& type_url) {
-    grpc_core::MutexLock lock(&ads_mu_);
-    resource_types_to_ignore_.emplace(type_url);
-  }
-
-  void SetResourceMinVersion(const std::string& type_url, int version) {
-    grpc_core::MutexLock lock(&ads_mu_);
-    resource_type_min_versions_[type_url] = version;
-  }
-
-  void UnsetResource(const std::string& type_url, const std::string& name) {
-    grpc_core::MutexLock lock(&ads_mu_);
-    ResourceTypeState& resource_type_state = resource_map_[type_url];
-    ++resource_type_state.resource_type_version;
-    ResourceState& resource_state = resource_type_state.resource_name_map[name];
-    resource_state.resource_type_version =
-        resource_type_state.resource_type_version;
-    resource_state.resource.reset();
-    gpr_log(GPR_INFO,
-            "ADS[%p]: Unsetting %s resource %s; resource_type_version now %u",
-            this, type_url.c_str(), name.c_str(),
-            resource_type_state.resource_type_version);
-    for (SubscriptionState* subscription : resource_state.subscriptions) {
-      subscription->update_queue->emplace_back(type_url, name);
-    }
-  }
-
-  void SetResource(google::protobuf::Any resource, const std::string& type_url,
-                   const std::string& name) {
-    grpc_core::MutexLock lock(&ads_mu_);
-    ResourceTypeState& resource_type_state = resource_map_[type_url];
-    ++resource_type_state.resource_type_version;
-    ResourceState& resource_state = resource_type_state.resource_name_map[name];
-    resource_state.resource_type_version =
-        resource_type_state.resource_type_version;
-    resource_state.resource = std::move(resource);
-    gpr_log(GPR_INFO,
-            "ADS[%p]: Updating %s resource %s; resource_type_version now %u",
-            this, type_url.c_str(), name.c_str(),
-            resource_type_state.resource_type_version);
-    for (SubscriptionState* subscription : resource_state.subscriptions) {
-      subscription->update_queue->emplace_back(type_url, name);
-    }
-  }
-
-  void SetLdsResource(const Listener& listener) {
-    google::protobuf::Any resource;
-    resource.PackFrom(listener);
-    SetResource(std::move(resource), kLdsTypeUrl, listener.name());
-  }
-
-  void SetRdsResource(const RouteConfiguration& route) {
-    google::protobuf::Any resource;
-    resource.PackFrom(route);
-    SetResource(std::move(resource), kRdsTypeUrl, route.name());
-  }
-
-  void SetCdsResource(const Cluster& cluster) {
-    google::protobuf::Any resource;
-    resource.PackFrom(cluster);
-    SetResource(std::move(resource), kCdsTypeUrl, cluster.name());
-  }
-
-  void SetEdsResource(const ClusterLoadAssignment& assignment) {
-    google::protobuf::Any resource;
-    resource.PackFrom(assignment);
-    SetResource(std::move(resource), kEdsTypeUrl, assignment.cluster_name());
-  }
-
-  void Start() {
-    grpc_core::MutexLock lock(&ads_mu_);
-    ads_done_ = false;
-  }
-
-  void Shutdown() {
-    {
-      grpc_core::MutexLock lock(&ads_mu_);
-      NotifyDoneWithAdsCallLocked();
-      resource_type_response_state_.clear();
-    }
-    gpr_log(GPR_INFO, "ADS[%p]: shut down", this);
-  }
-
-  void NotifyDoneWithAdsCall() {
-    grpc_core::MutexLock lock(&ads_mu_);
-    NotifyDoneWithAdsCallLocked();
-  }
-
-  void NotifyDoneWithAdsCallLocked() ABSL_EXCLUSIVE_LOCKS_REQUIRED(ads_mu_) {
-    if (!ads_done_) {
-      ads_done_ = true;
-      ads_cond_.SignalAll();
-    }
-  }
-
-  std::set<std::string> clients() {
-    grpc_core::MutexLock lock(&clients_mu_);
-    return clients_;
-  }
-
- private:
-  // A queue of resource type/name pairs that have changed since the client
-  // subscribed to them.
-  using UpdateQueue = std::deque<
-      std::pair<std::string /* type url */, std::string /* resource name */>>;
-
-  // A struct representing a client's subscription to a particular resource.
-  struct SubscriptionState {
-    // The queue upon which to place updates when the resource is updated.
-    UpdateQueue* update_queue;
-  };
-
-  // A struct representing the a client's subscription to all the resources.
-  using SubscriptionNameMap =
-      std::map<std::string /* resource_name */, SubscriptionState>;
-  using SubscriptionMap =
-      std::map<std::string /* type_url */, SubscriptionNameMap>;
-
-  // Sent state for a given resource type.
-  struct SentState {
-    int nonce = 0;
-    int resource_type_version = 0;
-  };
-
-  // A struct representing the current state for an individual resource.
-  struct ResourceState {
-    // The resource itself, if present.
-    absl::optional<google::protobuf::Any> resource;
-    // The resource type version that this resource was last updated in.
-    int resource_type_version = 0;
-    // A list of subscriptions to this resource.
-    std::set<SubscriptionState*> subscriptions;
-  };
-
-  // The current state for all individual resources of a given type.
-  using ResourceNameMap =
-      std::map<std::string /* resource_name */, ResourceState>;
-
-  struct ResourceTypeState {
-    int resource_type_version = 0;
-    ResourceNameMap resource_name_map;
-  };
-
-  using ResourceMap = std::map<std::string /* type_url */, ResourceTypeState>;
-
-  template <class RpcApi, class DiscoveryRequest, class DiscoveryResponse>
-  class RpcService : public RpcApi::Service {
-   public:
-    using Stream = ServerReaderWriter<DiscoveryResponse, DiscoveryRequest>;
-
-    RpcService(AdsServiceImpl* parent, bool is_v2)
-        : parent_(parent), is_v2_(is_v2) {}
-
-    Status StreamAggregatedResources(ServerContext* context,
-                                     Stream* stream) override {
-      gpr_log(GPR_INFO, "ADS[%p]: StreamAggregatedResources starts", this);
-      parent_->AddClient(context->peer());
-      if (is_v2_) {
-        parent_->seen_v2_client_ = true;
-      } else {
-        parent_->seen_v3_client_ = true;
-      }
-      // Take a reference of the AdsServiceImpl object, which will go
-      // out of scope when this request handler returns.  This ensures
-      // that the parent won't be destroyed until this stream is complete.
-      std::shared_ptr<AdsServiceImpl> ads_service_impl =
-          parent_->shared_from_this();
-      // Resources (type/name pairs) that have changed since the client
-      // subscribed to them.
-      UpdateQueue update_queue;
-      // Resources that the client will be subscribed to keyed by resource type
-      // url.
-      SubscriptionMap subscription_map;
-      // Sent state for each resource type.
-      std::map<std::string /*type_url*/, SentState> sent_state_map;
-      // Spawn a thread to read requests from the stream.
-      // Requests will be delivered to this thread in a queue.
-      std::deque<DiscoveryRequest> requests;
-      bool stream_closed = false;
-      std::thread reader(std::bind(&RpcService::BlockingRead, this, stream,
-                                   &requests, &stream_closed));
-      // Main loop to process requests and updates.
-      while (true) {
-        // Boolean to keep track if the loop received any work to do: a
-        // request or an update; regardless whether a response was actually
-        // sent out.
-        bool did_work = false;
-        // Look for new requests and and decide what to handle.
-        absl::optional<DiscoveryResponse> response;
-        {
-          grpc_core::MutexLock lock(&parent_->ads_mu_);
-          // If the stream has been closed or our parent is being shut
-          // down, stop immediately.
-          if (stream_closed || parent_->ads_done_) break;
-          // Otherwise, see if there's a request to read from the queue.
-          if (!requests.empty()) {
-            DiscoveryRequest request = std::move(requests.front());
-            requests.pop_front();
-            did_work = true;
-            gpr_log(GPR_INFO,
-                    "ADS[%p]: Received request for type %s with content %s",
-                    this, request.type_url().c_str(),
-                    request.DebugString().c_str());
-            const std::string v3_resource_type =
-                TypeUrlToV3(request.type_url());
-            SentState& sent_state = sent_state_map[v3_resource_type];
-            // Process request.
-            ProcessRequest(request, v3_resource_type, &update_queue,
-                           &subscription_map, &sent_state, &response);
-          }
-        }
-        if (response.has_value()) {
-          gpr_log(GPR_INFO, "ADS[%p]: Sending response: %s", this,
-                  response->DebugString().c_str());
-          stream->Write(response.value());
-        }
-        response.reset();
-        // Look for updates and decide what to handle.
-        {
-          grpc_core::MutexLock lock(&parent_->ads_mu_);
-          if (!update_queue.empty()) {
-            const std::string resource_type =
-                std::move(update_queue.front().first);
-            const std::string resource_name =
-                std::move(update_queue.front().second);
-            update_queue.pop_front();
-            did_work = true;
-            SentState& sent_state = sent_state_map[resource_type];
-            ProcessUpdate(resource_type, resource_name, &subscription_map,
-                          &sent_state, &response);
-          }
-        }
-        if (response.has_value()) {
-          gpr_log(GPR_INFO, "ADS[%p]: Sending update response: %s", this,
-                  response->DebugString().c_str());
-          stream->Write(response.value());
-        }
-        {
-          grpc_core::MutexLock lock(&parent_->ads_mu_);
-          if (parent_->ads_done_) {
-            break;
-          }
-        }
-        // If we didn't find anything to do, delay before the next loop
-        // iteration; otherwise, check whether we should exit and then
-        // immediately continue.
-        gpr_sleep_until(
-            grpc_timeout_milliseconds_to_deadline(did_work ? 0 : 10));
-      }
-      // Done with main loop.  Clean up before returning.
-      // Join reader thread.
-      reader.join();
-      // Clean up any subscriptions that were still active when the call
-      // finished.
-      {
-        grpc_core::MutexLock lock(&parent_->ads_mu_);
-        for (auto& p : subscription_map) {
-          const std::string& type_url = p.first;
-          SubscriptionNameMap& subscription_name_map = p.second;
-          for (auto& q : subscription_name_map) {
-            const std::string& resource_name = q.first;
-            SubscriptionState& subscription_state = q.second;
-            ResourceNameMap& resource_name_map =
-                parent_->resource_map_[type_url].resource_name_map;
-            ResourceState& resource_state = resource_name_map[resource_name];
-            resource_state.subscriptions.erase(&subscription_state);
-          }
-        }
-      }
-      gpr_log(GPR_INFO, "ADS[%p]: StreamAggregatedResources done", this);
-      parent_->RemoveClient(context->peer());
-      return Status::OK;
-    }
-
-   private:
-    // NB: clang's annotalysis is confused by the use of inner template
-    // classes here and *ignores* the exclusive lock annotation on some
-    // functions. See https://bugs.llvm.org/show_bug.cgi?id=51368.
-    //
-    // This class is used for a dual purpose:
-    // - it convinces clang that the lock is held in a given scope
-    // - when used in a function that is annotated to require the inner lock it
-    //   will cause compilation to fail if the upstream bug is fixed!
-    //
-    // If you arrive here because of a compilation failure, that might mean the
-    // clang bug is fixed! Please report that on the ticket.
-    //
-    // Since the buggy compiler will still need to be supported, consider
-    // wrapping this class in a compiler version #if and replace its usage
-    // with a macro whose expansion is conditional on the compiler version. In
-    // time (years? decades?) this code can be deleted altogether.
-    class ABSL_SCOPED_LOCKABLE NoopMutexLock {
-     public:
-      explicit NoopMutexLock(grpc_core::Mutex& mu)
-          ABSL_EXCLUSIVE_LOCK_FUNCTION(mu) {}
-      ~NoopMutexLock() ABSL_UNLOCK_FUNCTION() {}
-    };
-    // Processes a response read from the client.
-    // Populates response if needed.
-    void ProcessRequest(const DiscoveryRequest& request,
-                        const std::string& v3_resource_type,
-                        UpdateQueue* update_queue,
-                        SubscriptionMap* subscription_map,
-                        SentState* sent_state,
-                        absl::optional<DiscoveryResponse>* response)
-        ABSL_EXCLUSIVE_LOCKS_REQUIRED(parent_->ads_mu_) {
-      NoopMutexLock mu(parent_->ads_mu_);
-      // Check the nonce sent by the client, if any.
-      // (This will be absent on the first request on a stream.)
-      if (request.response_nonce().empty()) {
-        int client_resource_type_version = 0;
-        if (!request.version_info().empty()) {
-          GPR_ASSERT(absl::SimpleAtoi(request.version_info(),
-                                      &client_resource_type_version));
-        }
-        EXPECT_GE(client_resource_type_version,
-                  parent_->resource_type_min_versions_[v3_resource_type])
-            << "resource_type: " << v3_resource_type;
-      } else {
-        int client_nonce;
-        GPR_ASSERT(absl::SimpleAtoi(request.response_nonce(), &client_nonce));
-        // Ignore requests with stale nonces.
-        if (client_nonce < sent_state->nonce) return;
-        // Check for ACK or NACK.
-        auto it = parent_->resource_type_response_state_.find(v3_resource_type);
-        if (it != parent_->resource_type_response_state_.end()) {
-          if (!request.has_error_detail()) {
-            it->second.state = ResponseState::ACKED;
-            it->second.error_message.clear();
-            gpr_log(GPR_INFO,
-                    "ADS[%p]: client ACKed resource_type=%s version=%s", this,
-                    request.type_url().c_str(), request.version_info().c_str());
-          } else {
-            it->second.state = ResponseState::NACKED;
-            EXPECT_EQ(request.error_detail().code(),
-                      GRPC_STATUS_INVALID_ARGUMENT);
-            it->second.error_message = request.error_detail().message();
-            gpr_log(GPR_INFO,
-                    "ADS[%p]: client NACKed resource_type=%s version=%s: %s",
-                    this, request.type_url().c_str(),
-                    request.version_info().c_str(),
-                    it->second.error_message.c_str());
-          }
-        }
-      }
-      // Ignore resource types as requested by tests.
-      if (parent_->resource_types_to_ignore_.find(v3_resource_type) !=
-          parent_->resource_types_to_ignore_.end()) {
-        return;
-      }
-      // Look at all the resource names in the request.
-      auto& subscription_name_map = (*subscription_map)[v3_resource_type];
-      auto& resource_type_state = parent_->resource_map_[v3_resource_type];
-      auto& resource_name_map = resource_type_state.resource_name_map;
-      std::set<std::string> resources_in_current_request;
-      std::set<std::string> resources_added_to_response;
-      for (const std::string& resource_name : request.resource_names()) {
-        resources_in_current_request.emplace(resource_name);
-        auto& subscription_state = subscription_name_map[resource_name];
-        auto& resource_state = resource_name_map[resource_name];
-        // Subscribe if needed.
-        // Send the resource in the response if either (a) this is
-        // a new subscription or (b) there is an updated version of
-        // this resource to send.
-        if (parent_->MaybeSubscribe(v3_resource_type, resource_name,
-                                    &subscription_state, &resource_state,
-                                    update_queue) ||
-            ClientNeedsResourceUpdate(resource_type_state, resource_state,
-                                      sent_state->resource_type_version)) {
-          gpr_log(GPR_INFO, "ADS[%p]: Sending update for type=%s name=%s", this,
-                  request.type_url().c_str(), resource_name.c_str());
-          resources_added_to_response.emplace(resource_name);
-          if (!response->has_value()) response->emplace();
-          if (resource_state.resource.has_value()) {
-            auto* resource = (*response)->add_resources();
-            resource->CopyFrom(resource_state.resource.value());
-            if (is_v2_) {
-              resource->set_type_url(request.type_url());
-            }
-          }
-        } else {
-          gpr_log(GPR_INFO,
-                  "ADS[%p]: client does not need update for type=%s name=%s",
-                  this, request.type_url().c_str(), resource_name.c_str());
-        }
-      }
-      // Process unsubscriptions for any resource no longer
-      // present in the request's resource list.
-      parent_->ProcessUnsubscriptions(
-          v3_resource_type, resources_in_current_request,
-          &subscription_name_map, &resource_name_map);
-      // Construct response if needed.
-      if (!resources_added_to_response.empty()) {
-        CompleteBuildingDiscoveryResponse(
-            v3_resource_type, request.type_url(),
-            resource_type_state.resource_type_version, subscription_name_map,
-            resources_added_to_response, sent_state, &response->value());
-      }
-    }
-
-    // Processes a resource update from the test.
-    // Populates response if needed.
-    void ProcessUpdate(const std::string& resource_type,
-                       const std::string& resource_name,
-                       SubscriptionMap* subscription_map, SentState* sent_state,
-                       absl::optional<DiscoveryResponse>* response)
-        ABSL_EXCLUSIVE_LOCKS_REQUIRED(parent_->ads_mu_) {
-      NoopMutexLock mu(parent_->ads_mu_);
-      const std::string v2_resource_type = TypeUrlToV2(resource_type);
-      gpr_log(GPR_INFO, "ADS[%p]: Received update for type=%s name=%s", this,
-              resource_type.c_str(), resource_name.c_str());
-      auto& subscription_name_map = (*subscription_map)[resource_type];
-      auto& resource_type_state = parent_->resource_map_[resource_type];
-      auto& resource_name_map = resource_type_state.resource_name_map;
-      auto it = subscription_name_map.find(resource_name);
-      if (it != subscription_name_map.end()) {
-        ResourceState& resource_state = resource_name_map[resource_name];
-        if (ClientNeedsResourceUpdate(resource_type_state, resource_state,
-                                      sent_state->resource_type_version)) {
-          gpr_log(GPR_INFO, "ADS[%p]: Sending update for type=%s name=%s", this,
-                  resource_type.c_str(), resource_name.c_str());
-          response->emplace();
-          if (resource_state.resource.has_value()) {
-            auto* resource = (*response)->add_resources();
-            resource->CopyFrom(resource_state.resource.value());
-            if (is_v2_) {
-              resource->set_type_url(v2_resource_type);
-            }
-          }
-          CompleteBuildingDiscoveryResponse(
-              resource_type, v2_resource_type,
-              resource_type_state.resource_type_version, subscription_name_map,
-              {resource_name}, sent_state, &response->value());
-        }
-      }
-    }
-
-    // Starting a thread to do blocking read on the stream until cancel.
-    void BlockingRead(Stream* stream, std::deque<DiscoveryRequest>* requests,
-                      bool* stream_closed) {
-      DiscoveryRequest request;
-      bool seen_first_request = false;
-      while (stream->Read(&request)) {
-        if (!seen_first_request) {
-          EXPECT_TRUE(request.has_node());
-          ASSERT_FALSE(request.node().client_features().empty());
-          EXPECT_EQ(request.node().client_features(0),
-                    "envoy.lb.does_not_support_overprovisioning");
-          CheckBuildVersion(request);
-          seen_first_request = true;
-        }
-        {
-          grpc_core::MutexLock lock(&parent_->ads_mu_);
-          requests->emplace_back(std::move(request));
-        }
-      }
-      gpr_log(GPR_INFO, "ADS[%p]: Null read, stream closed", this);
-      grpc_core::MutexLock lock(&parent_->ads_mu_);
-      *stream_closed = true;
-    }
-
-    // Completing the building a DiscoveryResponse by adding common information
-    // for all resources and by adding all subscribed resources for LDS and CDS.
-    void CompleteBuildingDiscoveryResponse(
-        const std::string& resource_type, const std::string& v2_resource_type,
-        const int version, const SubscriptionNameMap& subscription_name_map,
-        const std::set<std::string>& resources_added_to_response,
-        SentState* sent_state, DiscoveryResponse* response)
-        ABSL_EXCLUSIVE_LOCKS_REQUIRED(parent_->ads_mu_) {
-      NoopMutexLock mu(parent_->ads_mu_);
-      auto& response_state =
-          parent_->resource_type_response_state_[resource_type];
-      if (response_state.state == ResponseState::NOT_SENT) {
-        response_state.state = ResponseState::SENT;
-      }
-      response->set_type_url(is_v2_ ? v2_resource_type : resource_type);
-      response->set_version_info(std::to_string(version));
-      response->set_nonce(std::to_string(++sent_state->nonce));
-      if (resource_type == kLdsTypeUrl || resource_type == kCdsTypeUrl) {
-        // For LDS and CDS we must send back all subscribed resources
-        // (even the unchanged ones)
-        for (const auto& p : subscription_name_map) {
-          const std::string& resource_name = p.first;
-          if (resources_added_to_response.find(resource_name) ==
-              resources_added_to_response.end()) {
-            ResourceNameMap& resource_name_map =
-                parent_->resource_map_[resource_type].resource_name_map;
-            const ResourceState& resource_state =
-                resource_name_map[resource_name];
-            if (resource_state.resource.has_value()) {
-              auto* resource = response->add_resources();
-              resource->CopyFrom(resource_state.resource.value());
-              if (is_v2_) {
-                resource->set_type_url(v2_resource_type);
-              }
-            }
-          }
-        }
-      }
-      sent_state->resource_type_version = version;
-    }
-
-    static std::string TypeUrlToV2(const std::string& resource_type) {
-      if (resource_type == kLdsTypeUrl) return kLdsV2TypeUrl;
-      if (resource_type == kRdsTypeUrl) return kRdsV2TypeUrl;
-      if (resource_type == kCdsTypeUrl) return kCdsV2TypeUrl;
-      if (resource_type == kEdsTypeUrl) return kEdsV2TypeUrl;
-      return resource_type;
-    }
-
-    static std::string TypeUrlToV3(const std::string& resource_type) {
-      if (resource_type == kLdsV2TypeUrl) return kLdsTypeUrl;
-      if (resource_type == kRdsV2TypeUrl) return kRdsTypeUrl;
-      if (resource_type == kCdsV2TypeUrl) return kCdsTypeUrl;
-      if (resource_type == kEdsV2TypeUrl) return kEdsTypeUrl;
-      return resource_type;
-    }
-
-    static void CheckBuildVersion(
-        const ::envoy::api::v2::DiscoveryRequest& request) {
-      EXPECT_FALSE(request.node().build_version().empty());
-    }
-
-    static void CheckBuildVersion(
-        const ::envoy::service::discovery::v3::DiscoveryRequest& /*request*/) {}
-
-    AdsServiceImpl* parent_;
-    const bool is_v2_;
-  };
-
-  // Checks whether the client needs to receive a newer version of
-  // the resource.
-  static bool ClientNeedsResourceUpdate(
-      const ResourceTypeState& resource_type_state,
-      const ResourceState& resource_state, int client_resource_type_version) {
-    return client_resource_type_version <
-               resource_type_state.resource_type_version &&
-           resource_state.resource_type_version <=
-               resource_type_state.resource_type_version;
-  }
-
-  // Subscribes to a resource if not already subscribed:
-  // 1. Sets the update_queue field in subscription_state.
-  // 2. Adds subscription_state to resource_state->subscriptions.
-  bool MaybeSubscribe(const std::string& resource_type,
-                      const std::string& resource_name,
-                      SubscriptionState* subscription_state,
-                      ResourceState* resource_state,
-                      UpdateQueue* update_queue) {
-    // The update_queue will be null if we were not previously subscribed.
-    if (subscription_state->update_queue != nullptr) return false;
-    subscription_state->update_queue = update_queue;
-    resource_state->subscriptions.emplace(subscription_state);
-    gpr_log(GPR_INFO, "ADS[%p]: subscribe to resource type %s name %s state %p",
-            this, resource_type.c_str(), resource_name.c_str(),
-            &subscription_state);
-    return true;
-  }
-
-  // Removes subscriptions for resources no longer present in the
-  // current request.
-  void ProcessUnsubscriptions(
-      const std::string& resource_type,
-      const std::set<std::string>& resources_in_current_request,
-      SubscriptionNameMap* subscription_name_map,
-      ResourceNameMap* resource_name_map) {
-    for (auto it = subscription_name_map->begin();
-         it != subscription_name_map->end();) {
-      const std::string& resource_name = it->first;
-      SubscriptionState& subscription_state = it->second;
-      if (resources_in_current_request.find(resource_name) !=
-          resources_in_current_request.end()) {
-        ++it;
-        continue;
-      }
-      gpr_log(GPR_INFO, "ADS[%p]: Unsubscribe to type=%s name=%s state=%p",
-              this, resource_type.c_str(), resource_name.c_str(),
-              &subscription_state);
-      auto resource_it = resource_name_map->find(resource_name);
-      GPR_ASSERT(resource_it != resource_name_map->end());
-      auto& resource_state = resource_it->second;
-      resource_state.subscriptions.erase(&subscription_state);
-      if (resource_state.subscriptions.empty() &&
-          !resource_state.resource.has_value()) {
-        resource_name_map->erase(resource_it);
-      }
-      it = subscription_name_map->erase(it);
-    }
-  }
-
-  void AddClient(const std::string& client) {
-    grpc_core::MutexLock lock(&clients_mu_);
-    clients_.insert(client);
-  }
-
-  void RemoveClient(const std::string& client) {
-    grpc_core::MutexLock lock(&clients_mu_);
-    clients_.erase(client);
-  }
-
-  RpcService<::envoy::service::discovery::v2::AggregatedDiscoveryService,
-             ::envoy::api::v2::DiscoveryRequest,
-             ::envoy::api::v2::DiscoveryResponse>
-      v2_rpc_service_;
-  RpcService<::envoy::service::discovery::v3::AggregatedDiscoveryService,
-             ::envoy::service::discovery::v3::DiscoveryRequest,
-             ::envoy::service::discovery::v3::DiscoveryResponse>
-      v3_rpc_service_;
-
-  std::atomic_bool seen_v2_client_{false};
-  std::atomic_bool seen_v3_client_{false};
-
-  grpc_core::CondVar ads_cond_;
-  grpc_core::Mutex ads_mu_;
-  bool ads_done_ ABSL_GUARDED_BY(ads_mu_) = false;
-  std::map<std::string /* type_url */, ResponseState>
-      resource_type_response_state_ ABSL_GUARDED_BY(ads_mu_);
-  std::set<std::string /*resource_type*/> resource_types_to_ignore_
-      ABSL_GUARDED_BY(ads_mu_);
-  std::map<std::string /*resource_type*/, int> resource_type_min_versions_
-      ABSL_GUARDED_BY(ads_mu_);
-  // An instance data member containing the current state of all resources.
-  // Note that an entry will exist whenever either of the following is true:
-  // - The resource exists (i.e., has been created by SetResource() and has not
-  //   yet been destroyed by UnsetResource()).
-  // - There is at least one subscription for the resource.
-  ResourceMap resource_map_ ABSL_GUARDED_BY(ads_mu_);
-
-  grpc_core::Mutex clients_mu_;
-  std::set<std::string> clients_ ABSL_GUARDED_BY(clients_mu_);
-};
-
-class LrsServiceImpl : public std::enable_shared_from_this<LrsServiceImpl> {
- public:
-  explicit LrsServiceImpl(int client_load_reporting_interval_seconds)
-      : v2_rpc_service_(this),
-        v3_rpc_service_(this),
-        client_load_reporting_interval_seconds_(
-            client_load_reporting_interval_seconds),
-        cluster_names_({kDefaultClusterName}) {}
-
-  ::envoy::service::load_stats::v2::LoadReportingService::Service*
-  v2_rpc_service() {
-    return &v2_rpc_service_;
-  }
-
-  ::envoy::service::load_stats::v3::LoadReportingService::Service*
-  v3_rpc_service() {
-    return &v3_rpc_service_;
-  }
-
-  size_t request_count() {
-    return v2_rpc_service_.request_count() + v3_rpc_service_.request_count();
-  }
-
-  size_t response_count() {
-    return v2_rpc_service_.response_count() + v3_rpc_service_.response_count();
-  }
-
-  // Must be called before the LRS call is started.
-  void set_send_all_clusters(bool send_all_clusters) {
-    send_all_clusters_ = send_all_clusters;
-  }
-  void set_cluster_names(const std::set<std::string>& cluster_names) {
-    cluster_names_ = cluster_names;
-  }
-
-  void Start() ABSL_LOCKS_EXCLUDED(lrs_mu_, load_report_mu_) {
-    {
-      grpc_core::MutexLock lock(&lrs_mu_);
-      lrs_done_ = false;
-    }
-    {
-      grpc_core::MutexLock lock(&load_report_mu_);
-      result_queue_.clear();
-    }
-  }
-
-  void Shutdown() {
-    {
-      grpc_core::MutexLock lock(&lrs_mu_);
-      NotifyDoneWithLrsCallLocked();
-    }
-    gpr_log(GPR_INFO, "LRS[%p]: shut down", this);
-  }
-
-  std::vector<ClientStats> WaitForLoadReport() {
-    grpc_core::MutexLock lock(&load_report_mu_);
-    grpc_core::CondVar cv;
-    if (result_queue_.empty()) {
-      load_report_cond_ = &cv;
-      while (result_queue_.empty()) {
-        cv.Wait(&load_report_mu_);
-      }
-      load_report_cond_ = nullptr;
-    }
-    std::vector<ClientStats> result = std::move(result_queue_.front());
-    result_queue_.pop_front();
-    return result;
-  }
-
-  void NotifyDoneWithLrsCall() {
-    grpc_core::MutexLock lock(&lrs_mu_);
-    NotifyDoneWithLrsCallLocked();
-  }
-
- private:
-  template <class RpcApi, class LoadStatsRequest, class LoadStatsResponse>
-  class RpcService : public CountedService<typename RpcApi::Service> {
-   public:
-    using Stream = ServerReaderWriter<LoadStatsResponse, LoadStatsRequest>;
-
-    explicit RpcService(LrsServiceImpl* parent) : parent_(parent) {}
-
-    Status StreamLoadStats(ServerContext* /*context*/,
-                           Stream* stream) override {
-      gpr_log(GPR_INFO, "LRS[%p]: StreamLoadStats starts", this);
-      EXPECT_GT(parent_->client_load_reporting_interval_seconds_, 0);
-      // Take a reference of the LrsServiceImpl object, reference will go
-      // out of scope after this method exits.
-      std::shared_ptr<LrsServiceImpl> lrs_service_impl =
-          parent_->shared_from_this();
-      // Read initial request.
-      LoadStatsRequest request;
-      if (stream->Read(&request)) {
-        CountedService<typename RpcApi::Service>::IncreaseRequestCount();
-        // Verify client features.
-        EXPECT_THAT(
-            request.node().client_features(),
-            ::testing::Contains("envoy.lrs.supports_send_all_clusters"));
-        // Send initial response.
-        LoadStatsResponse response;
-        if (parent_->send_all_clusters_) {
-          response.set_send_all_clusters(true);
-        } else {
-          for (const std::string& cluster_name : parent_->cluster_names_) {
-            response.add_clusters(cluster_name);
-          }
-        }
-        response.mutable_load_reporting_interval()->set_seconds(
-            parent_->client_load_reporting_interval_seconds_);
-        stream->Write(response);
-        CountedService<typename RpcApi::Service>::IncreaseResponseCount();
-        // Wait for report.
-        request.Clear();
-        while (stream->Read(&request)) {
-          gpr_log(GPR_INFO, "LRS[%p]: received client load report message: %s",
-                  this, request.DebugString().c_str());
-          std::vector<ClientStats> stats;
-          for (const auto& cluster_stats : request.cluster_stats()) {
-            stats.emplace_back(cluster_stats);
-          }
-          grpc_core::MutexLock lock(&parent_->load_report_mu_);
-          parent_->result_queue_.emplace_back(std::move(stats));
-          if (parent_->load_report_cond_ != nullptr) {
-            parent_->load_report_cond_->Signal();
-          }
-        }
-        // Wait until notified done.
-        grpc_core::MutexLock lock(&parent_->lrs_mu_);
-        while (!parent_->lrs_done_) {
-          parent_->lrs_cv_.Wait(&parent_->lrs_mu_);
-        }
-      }
-      gpr_log(GPR_INFO, "LRS[%p]: StreamLoadStats done", this);
-      return Status::OK;
-    }
-
-   private:
-    LrsServiceImpl* parent_;
-  };
-
-  void NotifyDoneWithLrsCallLocked() ABSL_EXCLUSIVE_LOCKS_REQUIRED(lrs_mu_) {
-    if (!lrs_done_) {
-      lrs_done_ = true;
-      lrs_cv_.SignalAll();
-    }
-  }
-
-  RpcService<::envoy::service::load_stats::v2::LoadReportingService,
-             ::envoy::service::load_stats::v2::LoadStatsRequest,
-             ::envoy::service::load_stats::v2::LoadStatsResponse>
-      v2_rpc_service_;
-  RpcService<::envoy::service::load_stats::v3::LoadReportingService,
-             ::envoy::service::load_stats::v3::LoadStatsRequest,
-             ::envoy::service::load_stats::v3::LoadStatsResponse>
-      v3_rpc_service_;
-
-  const int client_load_reporting_interval_seconds_;
-  bool send_all_clusters_ = false;
-  std::set<std::string> cluster_names_;
-
-  grpc_core::CondVar lrs_cv_;
-  grpc_core::Mutex lrs_mu_;
-  bool lrs_done_ ABSL_GUARDED_BY(lrs_mu_) = false;
-
-  grpc_core::Mutex load_report_mu_;
-  grpc_core::CondVar* load_report_cond_ ABSL_GUARDED_BY(load_report_mu_) =
-      nullptr;
-  std::deque<std::vector<ClientStats>> result_queue_
-      ABSL_GUARDED_BY(load_report_mu_);
-};
-
-class TestType {
- public:
-  enum FilterConfigSetup {
-    // Set the fault injection filter directly from LDS
-    kHTTPConnectionManagerOriginal,
-    // Enable the fault injection filter in LDS, but override the filter config
-    // in route.
-    kRouteOverride,
-  };
-
-  enum BootstrapSource {
-    kBootstrapFromChannelArg,
-    kBootstrapFromFile,
-    kBootstrapFromEnvVar,
-  };
-
-  TestType& set_use_fake_resolver() {
-    use_fake_resolver_ = true;
-    return *this;
-  }
-
-  TestType& set_enable_load_reporting() {
-    enable_load_reporting_ = true;
-    return *this;
-  }
-
-  TestType& set_enable_rds_testing() {
-    enable_rds_testing_ = true;
-    return *this;
-  }
-
-  TestType& set_use_v2() {
-    use_v2_ = true;
-    return *this;
-  }
-
-  TestType& set_use_xds_credentials() {
-    use_xds_credentials_ = true;
-    return *this;
-  }
-
-  TestType& set_use_csds_streaming() {
-    use_csds_streaming_ = true;
-    return *this;
-  }
-
-  TestType& set_filter_config_setup(FilterConfigSetup setup) {
-    filter_config_setup_ = setup;
-    return *this;
-  }
-
-  TestType& set_bootstrap_source(BootstrapSource bootstrap_source) {
-    bootstrap_source_ = bootstrap_source;
-    return *this;
-  }
-
-  bool use_fake_resolver() const { return use_fake_resolver_; }
-  bool enable_load_reporting() const { return enable_load_reporting_; }
-  bool enable_rds_testing() const { return enable_rds_testing_; }
-  bool use_v2() const { return use_v2_; }
-  bool use_xds_credentials() const { return use_xds_credentials_; }
-  bool use_csds_streaming() const { return use_csds_streaming_; }
-  FilterConfigSetup filter_config_setup() const { return filter_config_setup_; }
-  BootstrapSource bootstrap_source() const { return bootstrap_source_; }
-
-  std::string AsString() const {
-    std::string retval = (use_fake_resolver_ ? "FakeResolver" : "XdsResolver");
-    retval += (use_v2_ ? "V2" : "V3");
-    if (enable_load_reporting_) retval += "WithLoadReporting";
-    if (enable_rds_testing_) retval += "Rds";
-    if (use_xds_credentials_) retval += "XdsCreds";
-    if (use_csds_streaming_) retval += "CsdsStreaming";
-    if (filter_config_setup_ == kRouteOverride) {
-      retval += "FilterPerRouteOverride";
-    }
-    if (bootstrap_source_ == kBootstrapFromFile) {
-      retval += "BootstrapFromFile";
-    } else if (bootstrap_source_ == kBootstrapFromEnvVar) {
-      retval += "BootstrapFromEnvVar";
-    }
-    return retval;
-  }
-
- private:
-  bool use_fake_resolver_ = false;
-  bool enable_load_reporting_ = false;
-  bool enable_rds_testing_ = false;
-  bool use_v2_ = false;
-  bool use_xds_credentials_ = false;
-  bool use_csds_streaming_ = false;
-  FilterConfigSetup filter_config_setup_ = kHTTPConnectionManagerOriginal;
-  BootstrapSource bootstrap_source_ = kBootstrapFromChannelArg;
-};
-
-std::string ReadFile(const char* file_path) {
-  grpc_slice slice;
-  GPR_ASSERT(
-      GRPC_LOG_IF_ERROR("load_file", grpc_load_file(file_path, 0, &slice)));
-  std::string file_contents(grpc_core::StringViewFromSlice(slice));
-  grpc_slice_unref(slice);
-  return file_contents;
-}
-
-grpc_core::PemKeyCertPairList ReadTlsIdentityPair(const char* key_path,
-                                                  const char* cert_path) {
-  return grpc_core::PemKeyCertPairList{
-      grpc_core::PemKeyCertPair(ReadFile(key_path), ReadFile(cert_path))};
-}
-
-// Based on StaticDataCertificateProvider, but provides alternate certificates
-// if the certificate name is not empty.
-class FakeCertificateProvider final : public grpc_tls_certificate_provider {
- public:
-  struct CertData {
-    std::string root_certificate;
-    grpc_core::PemKeyCertPairList identity_key_cert_pairs;
-  };
-
-  using CertDataMap = std::map<std::string /*cert_name */, CertData>;
-
-  explicit FakeCertificateProvider(CertDataMap cert_data_map)
-      : distributor_(
-            grpc_core::MakeRefCounted<grpc_tls_certificate_distributor>()),
-        cert_data_map_(std::move(cert_data_map)) {
-    distributor_->SetWatchStatusCallback([this](std::string cert_name,
-                                                bool root_being_watched,
-                                                bool identity_being_watched) {
-      if (!root_being_watched && !identity_being_watched) return;
-      auto it = cert_data_map_.find(cert_name);
-      if (it == cert_data_map_.end()) {
-        grpc_error_handle error =
-            GRPC_ERROR_CREATE_FROM_CPP_STRING(absl::StrCat(
-                "No certificates available for cert_name \"", cert_name, "\""));
-        distributor_->SetErrorForCert(cert_name, GRPC_ERROR_REF(error),
-                                      GRPC_ERROR_REF(error));
-        GRPC_ERROR_UNREF(error);
-      } else {
-        absl::optional<std::string> root_certificate;
-        absl::optional<grpc_core::PemKeyCertPairList> pem_key_cert_pairs;
-        if (root_being_watched) {
-          root_certificate = it->second.root_certificate;
-        }
-        if (identity_being_watched) {
-          pem_key_cert_pairs = it->second.identity_key_cert_pairs;
-        }
-        distributor_->SetKeyMaterials(cert_name, std::move(root_certificate),
-                                      std::move(pem_key_cert_pairs));
-      }
-    });
-  }
-
-  ~FakeCertificateProvider() override {
-    distributor_->SetWatchStatusCallback(nullptr);
-  }
-
-  grpc_core::RefCountedPtr<grpc_tls_certificate_distributor> distributor()
-      const override {
-    return distributor_;
-  }
-
- private:
-  grpc_core::RefCountedPtr<grpc_tls_certificate_distributor> distributor_;
-  CertDataMap cert_data_map_;
-};
-
-class FakeCertificateProviderFactory
-    : public grpc_core::CertificateProviderFactory {
- public:
-  class Config : public grpc_core::CertificateProviderFactory::Config {
-   public:
-    explicit Config(const char* name) : name_(name) {}
-
-    const char* name() const override { return name_; }
-
-    std::string ToString() const override { return "{}"; }
-
-   private:
-    const char* name_;
-  };
-
-  FakeCertificateProviderFactory(
-      const char* name, FakeCertificateProvider::CertDataMap** cert_data_map)
-      : name_(name), cert_data_map_(cert_data_map) {
-    GPR_ASSERT(cert_data_map != nullptr);
-  }
-
-  const char* name() const override { return name_; }
-
-  grpc_core::RefCountedPtr<grpc_core::CertificateProviderFactory::Config>
-  CreateCertificateProviderConfig(const grpc_core::Json& /*config_json*/,
-                                  grpc_error_handle* /*error*/) override {
-    return grpc_core::MakeRefCounted<Config>(name_);
-  }
-
-  grpc_core::RefCountedPtr<grpc_tls_certificate_provider>
-  CreateCertificateProvider(
-      grpc_core::RefCountedPtr<grpc_core::CertificateProviderFactory::Config>
-      /*config*/) override {
-    if (*cert_data_map_ == nullptr) return nullptr;
-    return grpc_core::MakeRefCounted<FakeCertificateProvider>(**cert_data_map_);
-  }
-
- private:
-  const char* name_;
-  FakeCertificateProvider::CertDataMap** cert_data_map_;
-};
-
-// Global variables for each provider.
-FakeCertificateProvider::CertDataMap* g_fake1_cert_data_map = nullptr;
-FakeCertificateProvider::CertDataMap* g_fake2_cert_data_map = nullptr;
-
-int ServerAuthCheckSchedule(void* /* config_user_data */,
-                            grpc_tls_server_authorization_check_arg* arg) {
-  arg->success = 1;
-  arg->status = GRPC_STATUS_OK;
-  return 0; /* synchronous check */
-}
-
-std::shared_ptr<ChannelCredentials> CreateTlsFallbackCredentials() {
-  // TODO(yashykt): Switch to using C++ API once b/173823806 is fixed.
-  grpc_tls_credentials_options* options = grpc_tls_credentials_options_create();
-  grpc_tls_credentials_options_set_server_verification_option(
-      options, GRPC_TLS_SKIP_HOSTNAME_VERIFICATION);
-  grpc_tls_credentials_options_set_certificate_provider(
-      options,
-      grpc_core::MakeRefCounted<grpc_core::StaticDataCertificateProvider>(
-          ReadFile(kCaCertPath),
-          ReadTlsIdentityPair(kServerKeyPath, kServerCertPath))
-          .get());
-  grpc_tls_credentials_options_watch_root_certs(options);
-  grpc_tls_credentials_options_watch_identity_key_cert_pairs(options);
-  grpc_tls_server_authorization_check_config* check_config =
-      grpc_tls_server_authorization_check_config_create(
-          nullptr, ServerAuthCheckSchedule, nullptr, nullptr);
-  grpc_tls_credentials_options_set_server_authorization_check_config(
-      options, check_config);
-  auto channel_creds = std::make_shared<SecureChannelCredentials>(
-      grpc_tls_credentials_create(options));
-  grpc_tls_server_authorization_check_config_release(check_config);
-  return channel_creds;
-}
-
-// A No-op HTTP filter used for verifying parsing logic.
-class NoOpHttpFilter : public grpc_core::XdsHttpFilterImpl {
- public:
-  NoOpHttpFilter(std::string name, bool supported_on_clients,
-                 bool supported_on_servers)
-      : name_(std::move(name)),
-        supported_on_clients_(supported_on_clients),
-        supported_on_servers_(supported_on_servers) {}
-
-  void PopulateSymtab(upb_symtab* /* symtab */) const override {}
-
-  absl::StatusOr<grpc_core::XdsHttpFilterImpl::FilterConfig>
-  GenerateFilterConfig(upb_strview /* serialized_filter_config */,
-                       upb_arena* /* arena */) const override {
-    return grpc_core::XdsHttpFilterImpl::FilterConfig{name_, grpc_core::Json()};
-  }
-
-  absl::StatusOr<grpc_core::XdsHttpFilterImpl::FilterConfig>
-  GenerateFilterConfigOverride(upb_strview /*serialized_filter_config*/,
-                               upb_arena* /*arena*/) const override {
-    return grpc_core::XdsHttpFilterImpl::FilterConfig{name_, grpc_core::Json()};
-  }
-
-  const grpc_channel_filter* channel_filter() const override { return nullptr; }
-
-  absl::StatusOr<grpc_core::XdsHttpFilterImpl::ServiceConfigJsonEntry>
-  GenerateServiceConfig(
-      const FilterConfig& /*hcm_filter_config*/,
-      const FilterConfig* /*filter_config_override*/) const override {
-    return grpc_core::XdsHttpFilterImpl::ServiceConfigJsonEntry{name_, ""};
-  }
-
-  bool IsSupportedOnClients() const override { return supported_on_clients_; }
-
-  bool IsSupportedOnServers() const override { return supported_on_servers_; }
-
- private:
-  const std::string name_;
-  const bool supported_on_clients_;
-  const bool supported_on_servers_;
-};
-
-// There is slight difference between time fetched by GPR and by C++ system
-// clock API. It's unclear if they are using the same syscall, but we do know
-// GPR round the number at millisecond-level. This creates a 1ms difference,
-// which could cause flake.
-grpc_millis NowFromCycleCounter() {
-  gpr_cycle_counter now = gpr_get_cycle_counter();
-  return grpc_cycle_counter_to_millis_round_up(now);
-}
-
-// Returns the number of RPCs needed to pass error_tolerance at 99.99994%
-// chance. Rolling dices in drop/fault-injection generates a binomial
-// distribution (if our code is not horribly wrong). Let's make "n" the number
-// of samples, "p" the probability. If we have np>5 & n(1-p)>5, we can
-// approximately treat the binomial distribution as a normal distribution.
-//
-// For normal distribution, we can easily look up how many standard deviation we
-// need to reach 99.995%. Based on Wiki's table
-// https://en.wikipedia.org/wiki/68%E2%80%9395%E2%80%9399.7_rule, we need 5.00
-// sigma (standard deviation) to cover the probability area of 99.99994%. In
-// another word, for a sample with size "n" probability "p" error-tolerance "k",
-// we want the error always land within 5.00 sigma. The sigma of binominal
-// distribution and be computed as sqrt(np(1-p)). Hence, we have the equation:
-//
-//   kn <= 5.00 * sqrt(np(1-p))
-size_t ComputeIdealNumRpcs(double p, double error_tolerance) {
-  GPR_ASSERT(p >= 0 && p <= 1);
-  size_t num_rpcs =
-      ceil(p * (1 - p) * 5.00 * 5.00 / error_tolerance / error_tolerance);
-  gpr_log(GPR_INFO,
-          "Sending %" PRIuPTR " RPCs for percentage=%.3f error_tolerance=%.3f",
-          num_rpcs, p, error_tolerance);
-  return num_rpcs;
-}
-
-// Channel arg pointer vtable for storing xDS channel args in the parent
-// channel's channel args.
-void* ChannelArgsArgCopy(void* p) {
-  auto* args = static_cast<grpc_channel_args*>(p);
-  return grpc_channel_args_copy(args);
-}
-void ChannelArgsArgDestroy(void* p) {
-  auto* args = static_cast<grpc_channel_args*>(p);
-  grpc_channel_args_destroy(args);
-}
-int ChannelArgsArgCmp(void* a, void* b) {
-  auto* args_a = static_cast<grpc_channel_args*>(a);
-  auto* args_b = static_cast<grpc_channel_args*>(b);
-  return grpc_channel_args_compare(args_a, args_b);
-}
-const grpc_arg_pointer_vtable kChannelArgsArgVtable = {
-    ChannelArgsArgCopy, ChannelArgsArgDestroy, ChannelArgsArgCmp};
-
-class XdsEnd2endTest : public ::testing::TestWithParam<TestType> {
- protected:
-  // TODO(roth): We currently set the number of backends and number of
-  // balancers on a per-test-suite basis, not a per-test-case basis.
-  // However, not every individual test case in a given test suite uses
-  // the same number of backends or balancers, so we wind up having to
-  // set the numbers for the test suite to the max number needed by any
-  // one test case in that test suite.  This results in starting more
-  // servers (and using more ports) than we actually need.  When we have
-  // time, change each test to directly start the number of backends and
-  // balancers that it needs, so that we aren't wasting resources.
-  XdsEnd2endTest(size_t num_backends, size_t num_balancers,
-                 int client_load_reporting_interval_seconds = 100,
-                 bool use_xds_enabled_server = false)
-      : num_backends_(num_backends),
-        num_balancers_(num_balancers),
-        client_load_reporting_interval_seconds_(
-            client_load_reporting_interval_seconds),
-        use_xds_enabled_server_(use_xds_enabled_server) {}
-
-  void SetUp() override {
-    bool localhost_resolves_to_ipv4 = false;
-    bool localhost_resolves_to_ipv6 = false;
-    grpc_core::LocalhostResolves(&localhost_resolves_to_ipv4,
-                                 &localhost_resolves_to_ipv6);
-    ipv6_only_ = !localhost_resolves_to_ipv4 && localhost_resolves_to_ipv6;
-    // Initialize default xDS resources.
-    // Construct LDS resource.
-    default_listener_.set_name(kServerName);
-    HttpConnectionManager http_connection_manager;
-    if (!GetParam().use_v2()) {
-      auto* filter = http_connection_manager.add_http_filters();
-      filter->set_name("router");
-      filter->mutable_typed_config()->PackFrom(
-          envoy::extensions::filters::http::router::v3::Router());
-    }
-    default_listener_.mutable_api_listener()->mutable_api_listener()->PackFrom(
-        http_connection_manager);
-    // Construct RDS resource.
-    default_route_config_.set_name(kDefaultRouteConfigurationName);
-    auto* virtual_host = default_route_config_.add_virtual_hosts();
-    virtual_host->add_domains("*");
-    auto* route = virtual_host->add_routes();
-    route->mutable_match()->set_prefix("");
-    route->mutable_route()->set_cluster(kDefaultClusterName);
-    // Construct CDS resource.
-    default_cluster_.set_name(kDefaultClusterName);
-    default_cluster_.set_type(Cluster::EDS);
-    auto* eds_config = default_cluster_.mutable_eds_cluster_config();
-    eds_config->mutable_eds_config()->mutable_ads();
-    eds_config->set_service_name(kDefaultEdsServiceName);
-    default_cluster_.set_lb_policy(Cluster::ROUND_ROBIN);
-    if (GetParam().enable_load_reporting()) {
-      default_cluster_.mutable_lrs_server()->mutable_self();
-    }
-    // Start the load balancers.
-    for (size_t i = 0; i < num_balancers_; ++i) {
-      balancers_.emplace_back(new BalancerServerThread(
-          this, GetParam().enable_load_reporting()
-                    ? client_load_reporting_interval_seconds_
-                    : 0));
-      balancers_.back()->Start();
-      // Initialize resources.
-      SetListenerAndRouteConfiguration(i, default_listener_,
-                                       default_route_config_);
-      balancers_.back()->ads_service()->SetCdsResource(default_cluster_);
-    }
-    // Create fake resolver response generators used by client.
-    if (GetParam().use_fake_resolver()) {
-      response_generator_ =
-          grpc_core::MakeRefCounted<grpc_core::FakeResolverResponseGenerator>();
-    }
-    logical_dns_cluster_resolver_response_generator_ =
-        grpc_core::MakeRefCounted<grpc_core::FakeResolverResponseGenerator>();
-    lb_channel_response_generator_ =
-        grpc_core::MakeRefCounted<grpc_core::FakeResolverResponseGenerator>();
-    // Construct channel args for XdsClient.
-    xds_channel_args_to_add_.emplace_back(
-        grpc_core::FakeResolverResponseGenerator::MakeChannelArg(
-            lb_channel_response_generator_.get()));
-    if (xds_resource_does_not_exist_timeout_ms_ > 0) {
-      xds_channel_args_to_add_.emplace_back(grpc_channel_arg_integer_create(
-          const_cast<char*>(GRPC_ARG_XDS_RESOURCE_DOES_NOT_EXIST_TIMEOUT_MS),
-          xds_resource_does_not_exist_timeout_ms_));
-    }
-    xds_channel_args_.num_args = xds_channel_args_to_add_.size();
-    xds_channel_args_.args = xds_channel_args_to_add_.data();
-    // Initialize XdsClient state.
-    // TODO(roth): Consider changing this to dynamically generate the
-    // bootstrap config in each individual test instead of hard-coding
-    // the contents here.  That would allow us to use an ipv4: or ipv6:
-    // URI for the xDS server instead of using the fake resolver.
-    if (GetParam().bootstrap_source() == TestType::kBootstrapFromEnvVar) {
-      gpr_setenv("GRPC_XDS_BOOTSTRAP_CONFIG",
-                 GetParam().use_v2() ? kBootstrapFileV2 : kBootstrapFileV3);
-    } else if (GetParam().bootstrap_source() == TestType::kBootstrapFromFile) {
-      gpr_setenv("GRPC_XDS_BOOTSTRAP", GetParam().use_v2()
-                                           ? g_bootstrap_file_v2
-                                           : g_bootstrap_file_v3);
-    }
-    if (GetParam().bootstrap_source() != TestType::kBootstrapFromChannelArg) {
-      // If getting bootstrap from channel arg, we'll pass these args in
-      // via the parent channel args in CreateChannel() instead.
-      grpc_core::internal::SetXdsChannelArgsForTest(&xds_channel_args_);
-      // Make sure each test creates a new XdsClient instance rather than
-      // reusing the one from the previous test.  This avoids spurious failures
-      // caused when a load reporting test runs after a non-load reporting test
-      // and the XdsClient is still talking to the old LRS server, which fails
-      // because it's not expecting the client to connect.  It also
-      // ensures that each test can independently set the global channel
-      // args for the xDS channel.
-      grpc_core::internal::UnsetGlobalXdsClientForTest();
-    }
-    // Start the backends.
-    for (size_t i = 0; i < num_backends_; ++i) {
-      backends_.emplace_back(
-          new BackendServerThread(this, use_xds_enabled_server_));
-      backends_.back()->Start();
-    }
-    // Create channel and stub.
-    ResetStub();
-  }
-
-  const char* DefaultEdsServiceName() const {
-    return GetParam().use_fake_resolver() ? kServerName
-                                          : kDefaultEdsServiceName;
-  }
-
-  void TearDown() override {
-    ShutdownAllBackends();
-    for (auto& balancer : balancers_) balancer->Shutdown();
-    // Clear global xDS channel args, since they will go out of scope
-    // when this test object is destroyed.
-    grpc_core::internal::SetXdsChannelArgsForTest(nullptr);
-    gpr_unsetenv("GRPC_XDS_BOOTSTRAP");
-    gpr_unsetenv("GRPC_XDS_BOOTSTRAP_CONFIG");
-  }
-
-  void StartAllBackends() {
-    for (auto& backend : backends_) backend->Start();
-  }
-
-  void StartBackend(size_t index) { backends_[index]->Start(); }
-
-  void ShutdownAllBackends() {
-    for (auto& backend : backends_) backend->Shutdown();
-  }
-
-  void ShutdownBackend(size_t index) { backends_[index]->Shutdown(); }
-
-  void ResetStub(int failover_timeout = 0) {
-    channel_ = CreateChannel(failover_timeout);
-    stub_ = grpc::testing::EchoTestService::NewStub(channel_);
-    stub1_ = grpc::testing::EchoTest1Service::NewStub(channel_);
-    stub2_ = grpc::testing::EchoTest2Service::NewStub(channel_);
-  }
-
-  std::shared_ptr<Channel> CreateChannel(
-      int failover_timeout = 0, const char* server_name = kServerName,
-      grpc_core::FakeResolverResponseGenerator* response_generator = nullptr,
-      grpc_channel_args* xds_channel_args = nullptr) {
-    ChannelArguments args;
-    if (failover_timeout > 0) {
-      args.SetInt(GRPC_ARG_PRIORITY_FAILOVER_TIMEOUT_MS, failover_timeout);
-    }
-    // If the parent channel is using the fake resolver, we inject the
-    // response generator here.
-    if (GetParam().use_fake_resolver()) {
-      if (response_generator == nullptr) {
-        response_generator = response_generator_.get();
-      }
-      args.SetPointerWithVtable(
-          GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR, response_generator,
-          &grpc_core::FakeResolverResponseGenerator::kChannelArgPointerVtable);
-    }
-    if (GetParam().bootstrap_source() == TestType::kBootstrapFromChannelArg) {
-      // We're getting the bootstrap from a channel arg, so we do the
-      // same thing for the response generator to use for the xDS
-      // channel and the xDS resource-does-not-exist timeout value.
-      args.SetString(GRPC_ARG_TEST_ONLY_DO_NOT_USE_IN_PROD_XDS_BOOTSTRAP_CONFIG,
-                     GetParam().use_v2() ? kBootstrapFileV2 : kBootstrapFileV3);
-      if (xds_channel_args == nullptr) xds_channel_args = &xds_channel_args_;
-      args.SetPointerWithVtable(
-          GRPC_ARG_TEST_ONLY_DO_NOT_USE_IN_PROD_XDS_CLIENT_CHANNEL_ARGS,
-          xds_channel_args, &kChannelArgsArgVtable);
-    }
-    args.SetPointerWithVtable(
-        GRPC_ARG_XDS_LOGICAL_DNS_CLUSTER_FAKE_RESOLVER_RESPONSE_GENERATOR,
-        logical_dns_cluster_resolver_response_generator_.get(),
-        &grpc_core::FakeResolverResponseGenerator::kChannelArgPointerVtable);
-    std::string uri = absl::StrCat(
-        GetParam().use_fake_resolver() ? "fake" : "xds", ":///", server_name);
-    std::shared_ptr<ChannelCredentials> channel_creds =
-        GetParam().use_xds_credentials()
-            ? XdsCredentials(CreateTlsFallbackCredentials())
-            : std::make_shared<SecureChannelCredentials>(
-                  grpc_fake_transport_security_credentials_create());
-    return ::grpc::CreateCustomChannel(uri, channel_creds, args);
-  }
-
-  enum RpcService {
-    SERVICE_ECHO,
-    SERVICE_ECHO1,
-    SERVICE_ECHO2,
-  };
-
-  enum RpcMethod {
-    METHOD_ECHO,
-    METHOD_ECHO1,
-    METHOD_ECHO2,
-  };
-
-  struct RpcOptions {
-    RpcService service = SERVICE_ECHO;
-    RpcMethod method = METHOD_ECHO;
-    int timeout_ms = 1000;
-    bool wait_for_ready = false;
-    bool server_fail = false;
-    std::vector<std::pair<std::string, std::string>> metadata;
-    int server_sleep_us = 0;
-    int client_cancel_after_us = 0;
-    bool skip_cancelled_check = false;
-    StatusCode server_expected_error = StatusCode::OK;
-
-    RpcOptions() {}
-
-    RpcOptions& set_rpc_service(RpcService rpc_service) {
-      service = rpc_service;
-      return *this;
-    }
-
-    RpcOptions& set_rpc_method(RpcMethod rpc_method) {
-      method = rpc_method;
-      return *this;
-    }
-
-    RpcOptions& set_timeout_ms(int rpc_timeout_ms) {
-      timeout_ms = rpc_timeout_ms;
-      return *this;
-    }
-
-    RpcOptions& set_wait_for_ready(bool rpc_wait_for_ready) {
-      wait_for_ready = rpc_wait_for_ready;
-      return *this;
-    }
-
-    RpcOptions& set_server_fail(bool rpc_server_fail) {
-      server_fail = rpc_server_fail;
-      return *this;
-    }
-
-    RpcOptions& set_skip_cancelled_check(bool rpc_skip_cancelled_check) {
-      skip_cancelled_check = rpc_skip_cancelled_check;
-      return *this;
-    }
-
-    RpcOptions& set_metadata(
-        std::vector<std::pair<std::string, std::string>> rpc_metadata) {
-      metadata = std::move(rpc_metadata);
-      return *this;
-    }
-
-    RpcOptions& set_server_sleep_us(int rpc_server_sleep_us) {
-      server_sleep_us = rpc_server_sleep_us;
-      return *this;
-    }
-
-    RpcOptions& set_client_cancel_after_us(int rpc_client_cancel_after_us) {
-      client_cancel_after_us = rpc_client_cancel_after_us;
-      return *this;
-    }
-
-    RpcOptions& set_server_expected_error(StatusCode code) {
-      server_expected_error = code;
-      return *this;
-    }
-
-    // Populates context and request.
-    void SetupRpc(ClientContext* context, EchoRequest* request) const {
-      for (const auto& item : metadata) {
-        context->AddMetadata(item.first, item.second);
-      }
-      if (timeout_ms != 0) {
-        context->set_deadline(
-            grpc_timeout_milliseconds_to_deadline(timeout_ms));
-      }
-      if (wait_for_ready) context->set_wait_for_ready(true);
-      request->set_message(kRequestMessage);
-      if (server_fail) {
-        request->mutable_param()->mutable_expected_error()->set_code(
-            GRPC_STATUS_FAILED_PRECONDITION);
-      }
-      if (server_sleep_us != 0) {
-        request->mutable_param()->set_server_sleep_us(server_sleep_us);
-      }
-      if (client_cancel_after_us != 0) {
-        request->mutable_param()->set_client_cancel_after_us(
-            client_cancel_after_us);
-      }
-      if (skip_cancelled_check) {
-        request->mutable_param()->set_skip_cancelled_check(true);
-      }
-    }
-  };
-
-  template <typename Stub>
-  Status SendRpcMethod(Stub* stub, const RpcOptions& rpc_options,
-                       ClientContext* context, EchoRequest& request,
-                       EchoResponse* response) {
-    switch (rpc_options.method) {
-      case METHOD_ECHO:
-        return (*stub)->Echo(context, request, response);
-      case METHOD_ECHO1:
-        return (*stub)->Echo1(context, request, response);
-      case METHOD_ECHO2:
-        return (*stub)->Echo2(context, request, response);
-    }
-    GPR_UNREACHABLE_CODE();
-  }
-
-  void ResetBackendCounters(size_t start_index = 0, size_t stop_index = 0) {
-    if (stop_index == 0) stop_index = backends_.size();
-    for (size_t i = start_index; i < stop_index; ++i) {
-      backends_[i]->backend_service()->ResetCounters();
-      backends_[i]->backend_service1()->ResetCounters();
-      backends_[i]->backend_service2()->ResetCounters();
-    }
-  }
-
-  bool SeenBackend(size_t backend_idx,
-                   const RpcService rpc_service = SERVICE_ECHO) {
-    switch (rpc_service) {
-      case SERVICE_ECHO:
-        if (backends_[backend_idx]->backend_service()->request_count() == 0) {
-          return false;
-        }
-        break;
-      case SERVICE_ECHO1:
-        if (backends_[backend_idx]->backend_service1()->request_count() == 0) {
-          return false;
-        }
-        break;
-      case SERVICE_ECHO2:
-        if (backends_[backend_idx]->backend_service2()->request_count() == 0) {
-          return false;
-        }
-        break;
-    }
-    return true;
-  }
-
-  bool SeenAllBackends(size_t start_index = 0, size_t stop_index = 0,
-                       const RpcService rpc_service = SERVICE_ECHO) {
-    if (stop_index == 0) stop_index = backends_.size();
-    for (size_t i = start_index; i < stop_index; ++i) {
-      if (!SeenBackend(i, rpc_service)) {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  void SendRpcAndCount(
-      int* num_total, int* num_ok, int* num_failure, int* num_drops,
-      const RpcOptions& rpc_options = RpcOptions(),
-      const char* drop_error_message_prefix = "EDS-configured drop: ") {
-    const Status status = SendRpc(rpc_options);
-    if (status.ok()) {
-      ++*num_ok;
-    } else {
-      if (absl::StartsWith(status.error_message(), drop_error_message_prefix)) {
-        ++*num_drops;
-      } else {
-        ++*num_failure;
-      }
-    }
-    ++*num_total;
-  }
-
-  struct WaitForBackendOptions {
-    bool reset_counters = true;
-    bool allow_failures = false;
-
-    WaitForBackendOptions() {}
-
-    WaitForBackendOptions& set_reset_counters(bool enable) {
-      reset_counters = enable;
-      return *this;
-    }
-
-    WaitForBackendOptions& set_allow_failures(bool enable) {
-      allow_failures = enable;
-      return *this;
-    }
-  };
-
-  std::tuple<int, int, int> WaitForAllBackends(
-      size_t start_index = 0, size_t stop_index = 0,
-      const WaitForBackendOptions& wait_options = WaitForBackendOptions(),
-      const RpcOptions& rpc_options = RpcOptions()) {
-    int num_ok = 0;
-    int num_failure = 0;
-    int num_drops = 0;
-    int num_total = 0;
-    while (!SeenAllBackends(start_index, stop_index, rpc_options.service)) {
-      SendRpcAndCount(&num_total, &num_ok, &num_failure, &num_drops,
-                      rpc_options);
-    }
-    if (wait_options.reset_counters) ResetBackendCounters();
-    gpr_log(GPR_INFO,
-            "Performed %d warm up requests against the backends. "
-            "%d succeeded, %d failed, %d dropped.",
-            num_total, num_ok, num_failure, num_drops);
-    if (!wait_options.allow_failures) EXPECT_EQ(num_failure, 0);
-    return std::make_tuple(num_ok, num_failure, num_drops);
-  }
-
-  void WaitForBackend(
-      size_t backend_idx,
-      const WaitForBackendOptions& wait_options = WaitForBackendOptions(),
-      const RpcOptions& rpc_options = RpcOptions()) {
-    gpr_log(GPR_INFO, "========= WAITING FOR BACKEND %lu ==========",
-            static_cast<unsigned long>(backend_idx));
-    do {
-      Status status = SendRpc(rpc_options);
-      if (!wait_options.allow_failures) {
-        EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
-                                 << " message=" << status.error_message();
-      }
-    } while (!SeenBackend(backend_idx, rpc_options.service));
-    if (wait_options.reset_counters) ResetBackendCounters();
-    gpr_log(GPR_INFO, "========= BACKEND %lu READY ==========",
-            static_cast<unsigned long>(backend_idx));
-  }
-
-  grpc_core::ServerAddressList CreateAddressListFromPortList(
-      const std::vector<int>& ports) {
-    grpc_core::ServerAddressList addresses;
-    for (int port : ports) {
-      absl::StatusOr<grpc_core::URI> lb_uri = grpc_core::URI::Parse(
-          absl::StrCat(ipv6_only_ ? "ipv6:[::1]:" : "ipv4:127.0.0.1:", port));
-      GPR_ASSERT(lb_uri.ok());
-      grpc_resolved_address address;
-      GPR_ASSERT(grpc_parse_uri(*lb_uri, &address));
-      addresses.emplace_back(address.addr, address.len, nullptr);
-    }
-    return addresses;
-  }
-
-  std::string CreateMetadataValueThatHashesToBackendPort(int port) {
-    return absl::StrCat(ipv6_only_ ? "[::1]" : "127.0.0.1", ":", port, "_0");
-  }
-
-  std::string CreateMetadataValueThatHashesToBackend(int index) {
-    return CreateMetadataValueThatHashesToBackendPort(backends_[index]->port());
-  }
-
-  void SetNextResolution(
-      const std::vector<int>& ports,
-      grpc_core::FakeResolverResponseGenerator* response_generator = nullptr) {
-    if (!GetParam().use_fake_resolver()) return;  // Not used with xds resolver.
-    grpc_core::ExecCtx exec_ctx;
-    grpc_core::Resolver::Result result;
-    result.addresses = CreateAddressListFromPortList(ports);
-    grpc_error_handle error = GRPC_ERROR_NONE;
-    const char* service_config_json =
-        GetParam().enable_load_reporting()
-            ? kDefaultServiceConfig
-            : kDefaultServiceConfigWithoutLoadReporting;
-    result.service_config =
-        grpc_core::ServiceConfig::Create(nullptr, service_config_json, &error);
-    ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error);
-    ASSERT_NE(result.service_config.get(), nullptr);
-    if (response_generator == nullptr) {
-      response_generator = response_generator_.get();
-    }
-    response_generator->SetResponse(std::move(result));
-  }
-
-  void SetNextResolutionForLbChannelAllBalancers(
-      const char* service_config_json = nullptr,
-      const char* expected_targets = nullptr,
-      grpc_core::FakeResolverResponseGenerator* response_generator = nullptr) {
-    std::vector<int> ports;
-    for (size_t i = 0; i < balancers_.size(); ++i) {
-      ports.emplace_back(balancers_[i]->port());
-    }
-    SetNextResolutionForLbChannel(ports, service_config_json, expected_targets,
-                                  response_generator);
-  }
-
-  void SetNextResolutionForLbChannel(
-      const std::vector<int>& ports, const char* service_config_json = nullptr,
-      const char* expected_targets = nullptr,
-      grpc_core::FakeResolverResponseGenerator* response_generator = nullptr) {
-    grpc_core::ExecCtx exec_ctx;
-    grpc_core::Resolver::Result result;
-    result.addresses = CreateAddressListFromPortList(ports);
-    if (service_config_json != nullptr) {
-      grpc_error_handle error = GRPC_ERROR_NONE;
-      result.service_config = grpc_core::ServiceConfig::Create(
-          nullptr, service_config_json, &error);
-      ASSERT_NE(result.service_config.get(), nullptr);
-      ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error);
-    }
-    if (expected_targets != nullptr) {
-      grpc_arg expected_targets_arg = grpc_channel_arg_string_create(
-          const_cast<char*>(GRPC_ARG_FAKE_SECURITY_EXPECTED_TARGETS),
-          const_cast<char*>(expected_targets));
-      result.args =
-          grpc_channel_args_copy_and_add(nullptr, &expected_targets_arg, 1);
-    }
-    if (response_generator == nullptr) {
-      response_generator = lb_channel_response_generator_.get();
-    }
-    response_generator->SetResponse(std::move(result));
-  }
-
-  void SetNextReresolutionResponse(const std::vector<int>& ports) {
-    grpc_core::ExecCtx exec_ctx;
-    grpc_core::Resolver::Result result;
-    result.addresses = CreateAddressListFromPortList(ports);
-    response_generator_->SetReresolutionResponse(std::move(result));
-  }
-
-  std::vector<int> GetBackendPorts(size_t start_index = 0,
-                                   size_t stop_index = 0) const {
-    if (stop_index == 0) stop_index = backends_.size();
-    std::vector<int> backend_ports;
-    for (size_t i = start_index; i < stop_index; ++i) {
-      backend_ports.push_back(backends_[i]->port());
-    }
-    return backend_ports;
-  }
-
-  Status SendRpc(const RpcOptions& rpc_options = RpcOptions(),
-                 EchoResponse* response = nullptr) {
-    const bool local_response = (response == nullptr);
-    if (local_response) response = new EchoResponse;
-    ClientContext context;
-    EchoRequest request;
-    if (rpc_options.server_expected_error != StatusCode::OK) {
-      auto* error = request.mutable_param()->mutable_expected_error();
-      error->set_code(rpc_options.server_expected_error);
-    }
-    rpc_options.SetupRpc(&context, &request);
-    Status status;
-    switch (rpc_options.service) {
-      case SERVICE_ECHO:
-        status =
-            SendRpcMethod(&stub_, rpc_options, &context, request, response);
-        break;
-      case SERVICE_ECHO1:
-        status =
-            SendRpcMethod(&stub1_, rpc_options, &context, request, response);
-        break;
-      case SERVICE_ECHO2:
-        status =
-            SendRpcMethod(&stub2_, rpc_options, &context, request, response);
-        break;
-    }
-    if (local_response) delete response;
-    return status;
-  }
-
-  void CheckRpcSendOk(const size_t times = 1,
-                      const RpcOptions& rpc_options = RpcOptions()) {
-    for (size_t i = 0; i < times; ++i) {
-      EchoResponse response;
-      const Status status = SendRpc(rpc_options, &response);
-      EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
-                               << " message=" << status.error_message();
-      EXPECT_EQ(response.message(), kRequestMessage);
-    }
-  }
-
-  struct CheckRpcSendFailureOptions {
-    std::function<bool(size_t)> continue_predicate = [](size_t i) {
-      return i < 1;
-    };
-    RpcOptions rpc_options;
-    StatusCode expected_error_code = StatusCode::OK;
-
-    CheckRpcSendFailureOptions() {}
-
-    CheckRpcSendFailureOptions& set_times(size_t times) {
-      continue_predicate = [times](size_t i) { return i < times; };
-      return *this;
-    }
-
-    CheckRpcSendFailureOptions& set_continue_predicate(
-        std::function<bool(size_t)> pred) {
-      continue_predicate = std::move(pred);
-      return *this;
-    }
-
-    CheckRpcSendFailureOptions& set_rpc_options(const RpcOptions& options) {
-      rpc_options = options;
-      return *this;
-    }
-
-    CheckRpcSendFailureOptions& set_expected_error_code(StatusCode code) {
-      expected_error_code = code;
-      return *this;
-    }
-  };
-
-  void CheckRpcSendFailure(const CheckRpcSendFailureOptions& options =
-                               CheckRpcSendFailureOptions()) {
-    for (size_t i = 0; options.continue_predicate(i); ++i) {
-      const Status status = SendRpc(options.rpc_options);
-      EXPECT_FALSE(status.ok());
-      if (options.expected_error_code != StatusCode::OK) {
-        EXPECT_EQ(options.expected_error_code, status.error_code());
-      }
-    }
-  }
-
-  bool WaitForNack(
-      std::function<AdsServiceImpl::ResponseState::State()> get_state,
-      StatusCode expected_status = StatusCode::UNAVAILABLE) {
-    auto deadline = absl::Now() + absl::Seconds(30);
-    bool success = true;
-    CheckRpcSendFailure(CheckRpcSendFailureOptions()
-                            .set_continue_predicate([&](size_t) {
-                              if (absl::Now() >= deadline) {
-                                success = false;
-                                return false;
-                              }
-                              return get_state() !=
-                                     AdsServiceImpl::ResponseState::NACKED;
-                            })
-                            .set_expected_error_code(expected_status));
-    return success;
-  }
-
-  bool WaitForLdsNack(StatusCode expected_status = StatusCode::UNAVAILABLE) {
-    return WaitForNack(
-        [&]() {
-          return balancers_[0]->ads_service()->lds_response_state().state;
-        },
-        expected_status);
-  }
-
-  bool WaitForRdsNack() {
-    return WaitForNack(
-        [&]() { return RouteConfigurationResponseState(0).state; });
-  }
-
-  bool WaitForCdsNack() {
-    return WaitForNack([&]() {
-      return balancers_[0]->ads_service()->cds_response_state().state;
-    });
-  }
-
-  bool WaitForEdsNack() {
-    return WaitForNack([&]() {
-      return balancers_[0]->ads_service()->eds_response_state().state;
-    });
-  }
-
-  static Listener BuildListener(const RouteConfiguration& route_config) {
-    HttpConnectionManager http_connection_manager;
-    *(http_connection_manager.mutable_route_config()) = route_config;
-    auto* filter = http_connection_manager.add_http_filters();
-    filter->set_name("router");
-    filter->mutable_typed_config()->PackFrom(
-        envoy::extensions::filters::http::router::v3::Router());
-    Listener listener;
-    listener.set_name(kServerName);
-    listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
-        http_connection_manager);
-    return listener;
-  }
-
-  AdsServiceImpl::EdsResourceArgs::Endpoint CreateEndpoint(
-      size_t backend_idx, HealthStatus health_status = HealthStatus::UNKNOWN,
-      int lb_weight = 1) {
-    return AdsServiceImpl::EdsResourceArgs::Endpoint(
-        backends_[backend_idx]->port(), health_status, lb_weight);
-  }
-
-  std::vector<AdsServiceImpl::EdsResourceArgs::Endpoint>
-  CreateEndpointsForBackends(size_t start_index = 0, size_t stop_index = 0,
-                             HealthStatus health_status = HealthStatus::UNKNOWN,
-                             int lb_weight = 1) {
-    if (stop_index == 0) stop_index = backends_.size();
-    std::vector<AdsServiceImpl::EdsResourceArgs::Endpoint> endpoints;
-    for (size_t i = start_index; i < stop_index; ++i) {
-      endpoints.emplace_back(CreateEndpoint(i, health_status, lb_weight));
-    }
-    return endpoints;
-  }
-
-  AdsServiceImpl::EdsResourceArgs::Endpoint MakeNonExistantEndpoint() {
-    return AdsServiceImpl::EdsResourceArgs::Endpoint(
-        grpc_pick_unused_port_or_die());
-  }
-
-  ClusterLoadAssignment BuildEdsResource(
-      const AdsServiceImpl::EdsResourceArgs& args,
-      const char* eds_service_name = kDefaultEdsServiceName) {
-    ClusterLoadAssignment assignment;
-    assignment.set_cluster_name(eds_service_name);
-    for (const auto& locality : args.locality_list) {
-      auto* endpoints = assignment.add_endpoints();
-      endpoints->mutable_load_balancing_weight()->set_value(locality.lb_weight);
-      endpoints->set_priority(locality.priority);
-      endpoints->mutable_locality()->set_region(kDefaultLocalityRegion);
-      endpoints->mutable_locality()->set_zone(kDefaultLocalityZone);
-      endpoints->mutable_locality()->set_sub_zone(locality.sub_zone);
-      for (size_t i = 0; i < locality.endpoints.size(); ++i) {
-        const int& port = locality.endpoints[i].port;
-        auto* lb_endpoints = endpoints->add_lb_endpoints();
-        if (locality.endpoints.size() > i &&
-            locality.endpoints[i].health_status != HealthStatus::UNKNOWN) {
-          lb_endpoints->set_health_status(locality.endpoints[i].health_status);
-        }
-        if (locality.endpoints.size() > i &&
-            locality.endpoints[i].lb_weight >= 1) {
-          lb_endpoints->mutable_load_balancing_weight()->set_value(
-              locality.endpoints[i].lb_weight);
-        }
-        auto* endpoint = lb_endpoints->mutable_endpoint();
-        auto* address = endpoint->mutable_address();
-        auto* socket_address = address->mutable_socket_address();
-        socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1");
-        socket_address->set_port_value(port);
-      }
-    }
-    if (!args.drop_categories.empty()) {
-      auto* policy = assignment.mutable_policy();
-      for (const auto& p : args.drop_categories) {
-        const std::string& name = p.first;
-        const uint32_t parts_per_million = p.second;
-        auto* drop_overload = policy->add_drop_overloads();
-        drop_overload->set_category(name);
-        auto* drop_percentage = drop_overload->mutable_drop_percentage();
-        drop_percentage->set_numerator(parts_per_million);
-        drop_percentage->set_denominator(args.drop_denominator);
-      }
-    }
-    return assignment;
-  }
-
-  void SetListenerAndRouteConfiguration(
-      int idx, Listener listener, const RouteConfiguration& route_config) {
-    auto* api_listener =
-        listener.mutable_api_listener()->mutable_api_listener();
-    HttpConnectionManager http_connection_manager;
-    api_listener->UnpackTo(&http_connection_manager);
-    if (GetParam().enable_rds_testing()) {
-      auto* rds = http_connection_manager.mutable_rds();
-      rds->set_route_config_name(kDefaultRouteConfigurationName);
-      rds->mutable_config_source()->mutable_ads();
-      balancers_[idx]->ads_service()->SetRdsResource(route_config);
-    } else {
-      *http_connection_manager.mutable_route_config() = route_config;
-    }
-    api_listener->PackFrom(http_connection_manager);
-    balancers_[idx]->ads_service()->SetLdsResource(listener);
-  }
-
-  void SetRouteConfiguration(int idx, const RouteConfiguration& route_config) {
-    if (GetParam().enable_rds_testing()) {
-      balancers_[idx]->ads_service()->SetRdsResource(route_config);
-    } else {
-      balancers_[idx]->ads_service()->SetLdsResource(
-          BuildListener(route_config));
-    }
-  }
-
-  AdsServiceImpl::ResponseState RouteConfigurationResponseState(int idx) const {
-    AdsServiceImpl* ads_service = balancers_[idx]->ads_service();
-    if (GetParam().enable_rds_testing()) {
-      return ads_service->rds_response_state();
-    }
-    return ads_service->lds_response_state();
-  }
-
- public:
-  // This method could benefit test subclasses; to make it accessible
-  // via bind with a qualified name, it needs to be public.
-  void SetEdsResourceWithDelay(size_t i,
-                               const ClusterLoadAssignment& assignment,
-                               int delay_ms) {
-    GPR_ASSERT(delay_ms > 0);
-    gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(delay_ms));
-    balancers_[i]->ads_service()->SetEdsResource(assignment);
-  }
-
- protected:
-  class XdsServingStatusNotifier
-      : public grpc::experimental::XdsServerServingStatusNotifierInterface {
-   public:
-    void OnServingStatusUpdate(std::string uri,
-                               ServingStatusUpdate update) override {
-      grpc_core::MutexLock lock(&mu_);
-      status_map[uri] = update.status;
-      cond_.Signal();
-    }
-
-    void WaitOnServingStatusChange(std::string uri,
-                                   grpc::StatusCode expected_status) {
-      grpc_core::MutexLock lock(&mu_);
-      std::map<std::string, grpc::Status>::iterator it;
-      while ((it = status_map.find(uri)) == status_map.end() ||
-             it->second.error_code() != expected_status) {
-        cond_.Wait(&mu_);
-      }
-    }
-
-   private:
-    grpc_core::Mutex mu_;
-    grpc_core::CondVar cond_;
-    std::map<std::string, grpc::Status> status_map ABSL_GUARDED_BY(mu_);
-  };
-
-  class ServerThread {
-   public:
-    explicit ServerThread(XdsEnd2endTest* test_obj,
-                          bool use_xds_enabled_server = false)
-        : test_obj_(test_obj),
-          port_(grpc_pick_unused_port_or_die()),
-          use_xds_enabled_server_(use_xds_enabled_server) {}
-    virtual ~ServerThread(){};
-
-    void Start() {
-      gpr_log(GPR_INFO, "starting %s server on port %d", Type(), port_);
-      GPR_ASSERT(!running_);
-      running_ = true;
-      StartAllServices();
-      grpc_core::Mutex mu;
-      // We need to acquire the lock here in order to prevent the notify_one
-      // by ServerThread::Serve from firing before the wait below is hit.
-      grpc_core::MutexLock lock(&mu);
-      grpc_core::CondVar cond;
-      thread_ = absl::make_unique<std::thread>(
-          std::bind(&ServerThread::Serve, this, &mu, &cond));
-      cond.Wait(&mu);
-      gpr_log(GPR_INFO, "%s server startup complete", Type());
-    }
-
-    void Serve(grpc_core::Mutex* mu, grpc_core::CondVar* cond) {
-      // We need to acquire the lock here in order to prevent the notify_one
-      // below from firing before its corresponding wait is executed.
-      grpc_core::MutexLock lock(mu);
-      std::ostringstream server_address;
-      server_address << "localhost:" << port_;
-      if (use_xds_enabled_server_) {
-        XdsServerBuilder builder;
-        if (GetParam().bootstrap_source() ==
-            TestType::kBootstrapFromChannelArg) {
-          builder.SetOption(
-              absl::make_unique<XdsChannelArgsServerBuilderOption>(test_obj_));
-        }
-        builder.set_status_notifier(&notifier_);
-        builder.AddListeningPort(server_address.str(), Credentials());
-        RegisterAllServices(&builder);
-        server_ = builder.BuildAndStart();
-      } else {
-        ServerBuilder builder;
-        builder.AddListeningPort(server_address.str(), Credentials());
-        RegisterAllServices(&builder);
-        server_ = builder.BuildAndStart();
-      }
-      cond->Signal();
-    }
-
-    void Shutdown() {
-      if (!running_) return;
-      gpr_log(GPR_INFO, "%s about to shutdown", Type());
-      ShutdownAllServices();
-      server_->Shutdown(grpc_timeout_milliseconds_to_deadline(0));
-      thread_->join();
-      gpr_log(GPR_INFO, "%s shutdown completed", Type());
-      running_ = false;
-    }
-
-    virtual std::shared_ptr<ServerCredentials> Credentials() {
-      return std::make_shared<SecureServerCredentials>(
-          grpc_fake_transport_security_server_credentials_create());
-    }
-
-    int port() const { return port_; }
-
-    bool use_xds_enabled_server() const { return use_xds_enabled_server_; }
-
-    XdsServingStatusNotifier* notifier() { return &notifier_; }
-
-   private:
-    class XdsChannelArgsServerBuilderOption
-        : public ::grpc::ServerBuilderOption {
-     public:
-      explicit XdsChannelArgsServerBuilderOption(XdsEnd2endTest* test_obj)
-          : test_obj_(test_obj) {}
-
-      void UpdateArguments(grpc::ChannelArguments* args) override {
-        args->SetString(
-            GRPC_ARG_TEST_ONLY_DO_NOT_USE_IN_PROD_XDS_BOOTSTRAP_CONFIG,
-            GetParam().use_v2() ? kBootstrapFileV2 : kBootstrapFileV3);
-        args->SetPointerWithVtable(
-            GRPC_ARG_TEST_ONLY_DO_NOT_USE_IN_PROD_XDS_CLIENT_CHANNEL_ARGS,
-            &test_obj_->xds_channel_args_, &kChannelArgsArgVtable);
-      }
-
-      void UpdatePlugins(
-          std::vector<std::unique_ptr<grpc::ServerBuilderPlugin>>* /*plugins*/)
-          override {}
-
-     private:
-      XdsEnd2endTest* test_obj_;
-    };
-
-    virtual void RegisterAllServices(ServerBuilder* builder) = 0;
-    virtual void StartAllServices() = 0;
-    virtual void ShutdownAllServices() = 0;
-
-    virtual const char* Type() = 0;
-
-    XdsEnd2endTest* test_obj_;
-    const int port_;
-    std::unique_ptr<Server> server_;
-    XdsServingStatusNotifier notifier_;
-    std::unique_ptr<std::thread> thread_;
-    bool running_ = false;
-    const bool use_xds_enabled_server_;
-  };
-
-  class BackendServerThread : public ServerThread {
-   public:
-    explicit BackendServerThread(XdsEnd2endTest* test_obj,
-                                 bool use_xds_enabled_server)
-        : ServerThread(test_obj, use_xds_enabled_server) {}
-
-    BackendServiceImpl<::grpc::testing::EchoTestService::Service>*
-    backend_service() {
-      return &backend_service_;
-    }
-    BackendServiceImpl<::grpc::testing::EchoTest1Service::Service>*
-    backend_service1() {
-      return &backend_service1_;
-    }
-    BackendServiceImpl<::grpc::testing::EchoTest2Service::Service>*
-    backend_service2() {
-      return &backend_service2_;
-    }
-
-    std::shared_ptr<ServerCredentials> Credentials() override {
-      if (GetParam().use_xds_credentials()) {
-        if (use_xds_enabled_server()) {
-          // We are testing server's use of XdsServerCredentials
-          return XdsServerCredentials(InsecureServerCredentials());
-        } else {
-          // We are testing client's use of XdsCredentials
-          std::string root_cert = ReadFile(kCaCertPath);
-          std::string identity_cert = ReadFile(kServerCertPath);
-          std::string private_key = ReadFile(kServerKeyPath);
-          std::vector<experimental::IdentityKeyCertPair>
-              identity_key_cert_pairs = {{private_key, identity_cert}};
-          auto certificate_provider = std::make_shared<
-              grpc::experimental::StaticDataCertificateProvider>(
-              root_cert, identity_key_cert_pairs);
-          grpc::experimental::TlsServerCredentialsOptions options(
-              certificate_provider);
-          options.watch_root_certs();
-          options.watch_identity_key_cert_pairs();
-          options.set_cert_request_type(
-              GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY);
-          return grpc::experimental::TlsServerCredentials(options);
-        }
-      }
-      return ServerThread::Credentials();
-    }
-
-   private:
-    void RegisterAllServices(ServerBuilder* builder) override {
-      builder->RegisterService(&backend_service_);
-      builder->RegisterService(&backend_service1_);
-      builder->RegisterService(&backend_service2_);
-    }
-
-    void StartAllServices() override {
-      backend_service_.Start();
-      backend_service1_.Start();
-      backend_service2_.Start();
-    }
-
-    void ShutdownAllServices() override {
-      backend_service_.Shutdown();
-      backend_service1_.Shutdown();
-      backend_service2_.Shutdown();
-    }
-
-    const char* Type() override { return "Backend"; }
-
-    BackendServiceImpl<::grpc::testing::EchoTestService::Service>
-        backend_service_;
-    BackendServiceImpl<::grpc::testing::EchoTest1Service::Service>
-        backend_service1_;
-    BackendServiceImpl<::grpc::testing::EchoTest2Service::Service>
-        backend_service2_;
-  };
-
-  class BalancerServerThread : public ServerThread {
-   public:
-    explicit BalancerServerThread(XdsEnd2endTest* test_obj,
-                                  int client_load_reporting_interval = 0)
-        : ServerThread(test_obj),
-          ads_service_(new AdsServiceImpl()),
-          lrs_service_(new LrsServiceImpl(client_load_reporting_interval)) {}
-
-    AdsServiceImpl* ads_service() { return ads_service_.get(); }
-    LrsServiceImpl* lrs_service() { return lrs_service_.get(); }
-
-   private:
-    void RegisterAllServices(ServerBuilder* builder) override {
-      builder->RegisterService(ads_service_->v2_rpc_service());
-      builder->RegisterService(ads_service_->v3_rpc_service());
-      builder->RegisterService(lrs_service_->v2_rpc_service());
-      builder->RegisterService(lrs_service_->v3_rpc_service());
-    }
-
-    void StartAllServices() override {
-      ads_service_->Start();
-      lrs_service_->Start();
-    }
-
-    void ShutdownAllServices() override {
-      ads_service_->Shutdown();
-      lrs_service_->Shutdown();
-    }
-
-    const char* Type() override { return "Balancer"; }
-
-    std::shared_ptr<AdsServiceImpl> ads_service_;
-    std::shared_ptr<LrsServiceImpl> lrs_service_;
-  };
-
-#ifndef DISABLED_XDS_PROTO_IN_CC
-  class AdminServerThread : public ServerThread {
-   public:
-    explicit AdminServerThread(XdsEnd2endTest* test_obj)
-        : ServerThread(test_obj) {}
-
-   private:
-    void RegisterAllServices(ServerBuilder* builder) override {
-      builder->RegisterService(&csds_service_);
-    }
-    void StartAllServices() override {}
-    void ShutdownAllServices() override {}
-
-    const char* Type() override { return "Admin"; }
-
-    grpc::xds::experimental::ClientStatusDiscoveryService csds_service_;
-  };
-#endif  // DISABLED_XDS_PROTO_IN_CC
-
-  class LongRunningRpc {
-   public:
-    void StartRpc(grpc::testing::EchoTestService::Stub* stub,
-                  const RpcOptions& rpc_options =
-                      RpcOptions().set_timeout_ms(0).set_client_cancel_after_us(
-                          1 * 1000 * 1000)) {
-      sender_thread_ = std::thread([this, stub, rpc_options]() {
-        EchoRequest request;
-        EchoResponse response;
-        rpc_options.SetupRpc(&context_, &request);
-        status_ = stub->Echo(&context_, request, &response);
-      });
-    }
-
-    void CancelRpc() {
-      context_.TryCancel();
-      if (sender_thread_.joinable()) sender_thread_.join();
-    }
-
-    Status GetStatus() {
-      if (sender_thread_.joinable()) sender_thread_.join();
-      return status_;
-    }
-
-   private:
-    std::thread sender_thread_;
-    ClientContext context_;
-    Status status_;
-  };
-
-  struct ConcurrentRpc {
-    ClientContext context;
-    Status status;
-    grpc_millis elapsed_time;
-    EchoResponse response;
-  };
-
-  std::vector<ConcurrentRpc> SendConcurrentRpcs(
-      grpc::testing::EchoTestService::Stub* stub, size_t num_rpcs,
-      const RpcOptions& rpc_options) {
-    // Variables for RPCs.
-    std::vector<ConcurrentRpc> rpcs(num_rpcs);
-    EchoRequest request;
-    // Variables for synchronization
-    absl::Mutex mu;
-    absl::CondVar cv;
-    size_t completed = 0;
-    // Set-off callback RPCs
-    for (size_t i = 0; i < num_rpcs; i++) {
-      ConcurrentRpc* rpc = &rpcs[i];
-      rpc_options.SetupRpc(&rpc->context, &request);
-      grpc_millis t0 = NowFromCycleCounter();
-      stub->async()->Echo(&rpc->context, &request, &rpc->response,
-                          [rpc, &mu, &completed, &cv, num_rpcs, t0](Status s) {
-                            rpc->status = s;
-                            rpc->elapsed_time = NowFromCycleCounter() - t0;
-                            bool done;
-                            {
-                              absl::MutexLock lock(&mu);
-                              done = (++completed) == num_rpcs;
-                            }
-                            if (done) cv.Signal();
-                          });
-    }
-    {
-      absl::MutexLock lock(&mu);
-      cv.Wait(&mu);
-    }
-    EXPECT_EQ(completed, num_rpcs);
-    return rpcs;
-  }
-
-  const size_t num_backends_;
-  const size_t num_balancers_;
-  const int client_load_reporting_interval_seconds_;
-  bool ipv6_only_ = false;
-  std::shared_ptr<Channel> channel_;
-  std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_;
-  std::unique_ptr<grpc::testing::EchoTest1Service::Stub> stub1_;
-  std::unique_ptr<grpc::testing::EchoTest2Service::Stub> stub2_;
-  std::vector<std::unique_ptr<BackendServerThread>> backends_;
-  std::vector<std::unique_ptr<BalancerServerThread>> balancers_;
-  grpc_core::RefCountedPtr<grpc_core::FakeResolverResponseGenerator>
-      response_generator_;
-  grpc_core::RefCountedPtr<grpc_core::FakeResolverResponseGenerator>
-      lb_channel_response_generator_;
-  grpc_core::RefCountedPtr<grpc_core::FakeResolverResponseGenerator>
-      logical_dns_cluster_resolver_response_generator_;
-  int xds_resource_does_not_exist_timeout_ms_ = 0;
-  absl::InlinedVector<grpc_arg, 2> xds_channel_args_to_add_;
-  grpc_channel_args xds_channel_args_;
-
-  Listener default_listener_;
-  RouteConfiguration default_route_config_;
-  Cluster default_cluster_;
-  bool use_xds_enabled_server_;
-  bool bootstrap_contents_from_env_var_;
-};
-
-class BasicTest : public XdsEnd2endTest {
- public:
-  BasicTest() : XdsEnd2endTest(4, 1) {}
-};
-
-// Tests that the balancer sends the correct response to the client, and the
-// client sends RPCs to the backends using the default child policy.
-TEST_P(BasicTest, Vanilla) {
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  const size_t kNumRpcsPerAddress = 100;
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  // Make sure that trying to connect works without a call.
-  channel_->GetState(true /* try_to_connect */);
-  // We need to wait for all backends to come online.
-  WaitForAllBackends();
-  // Send kNumRpcsPerAddress RPCs per server.
-  CheckRpcSendOk(kNumRpcsPerAddress * num_backends_);
-  // Each backend should have gotten 100 requests.
-  for (size_t i = 0; i < backends_.size(); ++i) {
-    EXPECT_EQ(kNumRpcsPerAddress,
-              backends_[i]->backend_service()->request_count());
-  }
-  // Check LB policy name for the channel.
-  EXPECT_EQ(
-      (GetParam().use_fake_resolver() ? "xds_cluster_resolver_experimental"
-                                      : "xds_cluster_manager_experimental"),
-      channel_->GetLoadBalancingPolicyName());
-}
-
-TEST_P(BasicTest, IgnoresUnhealthyEndpoints) {
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  const size_t kNumRpcsPerAddress = 100;
-  auto endpoints = CreateEndpointsForBackends();
-  endpoints[0].health_status = HealthStatus::DRAINING;
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", std::move(endpoints), kDefaultLocalityWeight,
-       kDefaultLocalityPriority},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  // Make sure that trying to connect works without a call.
-  channel_->GetState(true /* try_to_connect */);
-  // We need to wait for all backends to come online.
-  WaitForAllBackends(/*start_index=*/1);
-  // Send kNumRpcsPerAddress RPCs per server.
-  CheckRpcSendOk(kNumRpcsPerAddress * (num_backends_ - 1));
-  // Each backend should have gotten 100 requests.
-  for (size_t i = 1; i < backends_.size(); ++i) {
-    EXPECT_EQ(kNumRpcsPerAddress,
-              backends_[i]->backend_service()->request_count());
-  }
-}
-
-// Tests that subchannel sharing works when the same backend is listed
-// multiple times.
-TEST_P(BasicTest, SameBackendListedMultipleTimes) {
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Same backend listed twice.
-  auto endpoints = CreateEndpointsForBackends(0, 1);
-  endpoints.push_back(endpoints.front());
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", endpoints},
-  });
-  const size_t kNumRpcsPerAddress = 10;
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  // We need to wait for the backend to come online.
-  WaitForBackend(0);
-  // Send kNumRpcsPerAddress RPCs per server.
-  CheckRpcSendOk(kNumRpcsPerAddress * endpoints.size());
-  // Backend should have gotten 20 requests.
-  EXPECT_EQ(kNumRpcsPerAddress * endpoints.size(),
-            backends_[0]->backend_service()->request_count());
-  // And they should have come from a single client port, because of
-  // subchannel sharing.
-  EXPECT_EQ(1UL, backends_[0]->backend_service()->clients().size());
-}
-
-// Tests that RPCs will be blocked until a non-empty serverlist is received.
-TEST_P(BasicTest, InitiallyEmptyServerlist) {
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  const int kServerlistDelayMs = 500 * grpc_test_slowdown_factor();
-  const int kCallDeadlineMs = kServerlistDelayMs * 2;
-  // First response is an empty serverlist, sent right away.
-  AdsServiceImpl::EdsResourceArgs::Locality empty_locality("locality0", {});
-  AdsServiceImpl::EdsResourceArgs args({
-      empty_locality,
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  // Send non-empty serverlist only after kServerlistDelayMs.
-  args = AdsServiceImpl::EdsResourceArgs({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  std::thread delayed_resource_setter(std::bind(
-      &BasicTest::SetEdsResourceWithDelay, this, 0,
-      BuildEdsResource(args, DefaultEdsServiceName()), kServerlistDelayMs));
-  const auto t0 = system_clock::now();
-  // Client will block: LB will initially send empty serverlist.
-  CheckRpcSendOk(
-      1, RpcOptions().set_timeout_ms(kCallDeadlineMs).set_wait_for_ready(true));
-  const auto ellapsed_ms =
-      std::chrono::duration_cast<std::chrono::milliseconds>(
-          system_clock::now() - t0);
-  // but eventually, the LB sends a serverlist update that allows the call to
-  // proceed. The call delay must be larger than the delay in sending the
-  // populated serverlist but under the call's deadline (which is enforced by
-  // the call's deadline).
-  EXPECT_GT(ellapsed_ms.count(), kServerlistDelayMs);
-  delayed_resource_setter.join();
-}
-
-// Tests that RPCs will fail with UNAVAILABLE instead of DEADLINE_EXCEEDED if
-// all the servers are unreachable.
-TEST_P(BasicTest, AllServersUnreachableFailFast) {
-  // Set Rpc timeout to 5 seconds to ensure there is enough time
-  // for communication with the xDS server to take place upon test start up.
-  const uint32_t kRpcTimeoutMs = 5000;
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  const size_t kNumUnreachableServers = 5;
-  std::vector<AdsServiceImpl::EdsResourceArgs::Endpoint> endpoints;
-  for (size_t i = 0; i < kNumUnreachableServers; ++i) {
-    endpoints.emplace_back(grpc_pick_unused_port_or_die());
-  }
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", endpoints},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  const Status status = SendRpc(RpcOptions().set_timeout_ms(kRpcTimeoutMs));
-  // The error shouldn't be DEADLINE_EXCEEDED because timeout is set to 5
-  // seconds, and we should disocver in that time that the target backend is
-  // down.
-  EXPECT_EQ(StatusCode::UNAVAILABLE, status.error_code());
-}
-
-// Tests that RPCs fail when the backends are down, and will succeed again
-// after the backends are restarted.
-TEST_P(BasicTest, BackendsRestart) {
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  WaitForAllBackends();
-  // Stop backends.  RPCs should fail.
-  ShutdownAllBackends();
-  // Sending multiple failed requests instead of just one to ensure that the
-  // client notices that all backends are down before we restart them. If we
-  // didn't do this, then a single RPC could fail here due to the race
-  // condition between the LB pick and the GOAWAY from the chosen backend
-  // being shut down, which would not actually prove that the client noticed
-  // that all of the backends are down. Then, when we send another request
-  // below (which we expect to succeed), if the callbacks happen in the wrong
-  // order, the same race condition could happen again due to the client not
-  // yet having noticed that the backends were all down.
-  CheckRpcSendFailure(CheckRpcSendFailureOptions().set_times(num_backends_));
-  // Restart all backends.  RPCs should start succeeding again.
-  StartAllBackends();
-  CheckRpcSendOk(1, RpcOptions().set_timeout_ms(2000).set_wait_for_ready(true));
-}
-
-TEST_P(BasicTest, IgnoresDuplicateUpdates) {
-  const size_t kNumRpcsPerAddress = 100;
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  // Wait for all backends to come online.
-  WaitForAllBackends();
-  // Send kNumRpcsPerAddress RPCs per server, but send an EDS update in
-  // between.  If the update is not ignored, this will cause the
-  // round_robin policy to see an update, which will randomly reset its
-  // position in the address list.
-  for (size_t i = 0; i < kNumRpcsPerAddress; ++i) {
-    CheckRpcSendOk(2);
-    balancers_[0]->ads_service()->SetEdsResource(
-        BuildEdsResource(args, DefaultEdsServiceName()));
-    CheckRpcSendOk(2);
-  }
-  // Each backend should have gotten the right number of requests.
-  for (size_t i = 1; i < backends_.size(); ++i) {
-    EXPECT_EQ(kNumRpcsPerAddress,
-              backends_[i]->backend_service()->request_count());
-  }
-}
-
-using XdsResolverOnlyTest = BasicTest;
-
-TEST_P(XdsResolverOnlyTest, ResourceTypeVersionPersistsAcrossStreamRestarts) {
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 1)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
-  // Wait for backends to come online.
-  WaitForAllBackends(0, 1);
-  // Stop balancer.
-  balancers_[0]->Shutdown();
-  // Tell balancer to require minimum version 1 for all resource types.
-  balancers_[0]->ads_service()->SetResourceMinVersion(kLdsTypeUrl, 1);
-  balancers_[0]->ads_service()->SetResourceMinVersion(kRdsTypeUrl, 1);
-  balancers_[0]->ads_service()->SetResourceMinVersion(kCdsTypeUrl, 1);
-  balancers_[0]->ads_service()->SetResourceMinVersion(kEdsTypeUrl, 1);
-  // Update backend, just so we can be sure that the client has
-  // reconnected to the balancer.
-  AdsServiceImpl::EdsResourceArgs args2({
-      {"locality0", CreateEndpointsForBackends(1, 2)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args2));
-  // Restart balancer.
-  balancers_[0]->Start();
-  // Make sure client has reconnected.
-  WaitForAllBackends(1, 2);
-}
-
-// Tests switching over from one cluster to another.
-TEST_P(XdsResolverOnlyTest, ChangeClusters) {
-  const char* kNewClusterName = "new_cluster_name";
-  const char* kNewEdsServiceName = "new_eds_service_name";
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 2)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
-  // We need to wait for all backends to come online.
-  WaitForAllBackends(0, 2);
-  // Populate new EDS resource.
-  AdsServiceImpl::EdsResourceArgs args2({
-      {"locality0", CreateEndpointsForBackends(2, 4)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args2, kNewEdsServiceName));
-  // Populate new CDS resource.
-  Cluster new_cluster = default_cluster_;
-  new_cluster.set_name(kNewClusterName);
-  new_cluster.mutable_eds_cluster_config()->set_service_name(
-      kNewEdsServiceName);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster);
-  // Change RDS resource to point to new cluster.
-  RouteConfiguration new_route_config = default_route_config_;
-  new_route_config.mutable_virtual_hosts(0)
-      ->mutable_routes(0)
-      ->mutable_route()
-      ->set_cluster(kNewClusterName);
-  SetListenerAndRouteConfiguration(0, default_listener_, new_route_config);
-  // Wait for all new backends to be used.
-  std::tuple<int, int, int> counts = WaitForAllBackends(2, 4);
-  // Make sure no RPCs failed in the transition.
-  EXPECT_EQ(0, std::get<1>(counts));
-}
-
-// Tests that we go into TRANSIENT_FAILURE if the Cluster disappears.
-TEST_P(XdsResolverOnlyTest, ClusterRemoved) {
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
-  // We need to wait for all backends to come online.
-  WaitForAllBackends();
-  // Unset CDS resource.
-  balancers_[0]->ads_service()->UnsetResource(kCdsTypeUrl, kDefaultClusterName);
-  // Wait for RPCs to start failing.
-  do {
-  } while (SendRpc(RpcOptions(), nullptr).ok());
-  // Make sure RPCs are still failing.
-  CheckRpcSendFailure(CheckRpcSendFailureOptions().set_times(1000));
-  // Make sure we ACK'ed the update.
-  EXPECT_EQ(balancers_[0]->ads_service()->cds_response_state().state,
-            AdsServiceImpl::ResponseState::ACKED);
-}
-
-// Tests that we restart all xDS requests when we reestablish the ADS call.
-TEST_P(XdsResolverOnlyTest, RestartsRequestsUponReconnection) {
-  // Manually configure use of RDS.
-  auto listener = default_listener_;
-  HttpConnectionManager http_connection_manager;
-  listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
-      &http_connection_manager);
-  auto* rds = http_connection_manager.mutable_rds();
-  rds->set_route_config_name(kDefaultRouteConfigurationName);
-  rds->mutable_config_source()->mutable_ads();
-  listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
-      http_connection_manager);
-  balancers_[0]->ads_service()->SetLdsResource(listener);
-  balancers_[0]->ads_service()->SetRdsResource(default_route_config_);
-  const char* kNewClusterName = "new_cluster_name";
-  const char* kNewEdsServiceName = "new_eds_service_name";
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 2)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
-  // We need to wait for all backends to come online.
-  WaitForAllBackends(0, 2);
-  // Now shut down and restart the balancer.  When the client
-  // reconnects, it should automatically restart the requests for all
-  // resource types.
-  balancers_[0]->Shutdown();
-  balancers_[0]->Start();
-  // Make sure things are still working.
-  CheckRpcSendOk(100);
-  // Populate new EDS resource.
-  AdsServiceImpl::EdsResourceArgs args2({
-      {"locality0", CreateEndpointsForBackends(2, 4)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args2, kNewEdsServiceName));
-  // Populate new CDS resource.
-  Cluster new_cluster = default_cluster_;
-  new_cluster.set_name(kNewClusterName);
-  new_cluster.mutable_eds_cluster_config()->set_service_name(
-      kNewEdsServiceName);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster);
-  // Change RDS resource to point to new cluster.
-  RouteConfiguration new_route_config = default_route_config_;
-  new_route_config.mutable_virtual_hosts(0)
-      ->mutable_routes(0)
-      ->mutable_route()
-      ->set_cluster(kNewClusterName);
-  balancers_[0]->ads_service()->SetRdsResource(new_route_config);
-  // Wait for all new backends to be used.
-  std::tuple<int, int, int> counts = WaitForAllBackends(2, 4);
-  // Make sure no RPCs failed in the transition.
-  EXPECT_EQ(0, std::get<1>(counts));
-}
-
-TEST_P(XdsResolverOnlyTest, DefaultRouteSpecifiesSlashPrefix) {
-  RouteConfiguration route_config = default_route_config_;
-  route_config.mutable_virtual_hosts(0)
-      ->mutable_routes(0)
-      ->mutable_match()
-      ->set_prefix("/");
-  SetListenerAndRouteConfiguration(0, default_listener_, route_config);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
-  // We need to wait for all backends to come online.
-  WaitForAllBackends();
-}
-
-TEST_P(XdsResolverOnlyTest, CircuitBreaking) {
-  constexpr size_t kMaxConcurrentRequests = 10;
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Populate new EDS resources.
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 1)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
-  // Update CDS resource to set max concurrent request.
-  CircuitBreakers circuit_breaks;
-  Cluster cluster = default_cluster_;
-  auto* threshold = cluster.mutable_circuit_breakers()->add_thresholds();
-  threshold->set_priority(RoutingPriority::DEFAULT);
-  threshold->mutable_max_requests()->set_value(kMaxConcurrentRequests);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  // Send exactly max_concurrent_requests long RPCs.
-  LongRunningRpc rpcs[kMaxConcurrentRequests];
-  for (size_t i = 0; i < kMaxConcurrentRequests; ++i) {
-    rpcs[i].StartRpc(stub_.get());
-  }
-  // Wait for all RPCs to be in flight.
-  while (backends_[0]->backend_service()->RpcsWaitingForClientCancel() <
-         kMaxConcurrentRequests) {
-    gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
-                                 gpr_time_from_micros(1 * 1000, GPR_TIMESPAN)));
-  }
-  // Sending a RPC now should fail, the error message should tell us
-  // we hit the max concurrent requests limit and got dropped.
-  Status status = SendRpc();
-  EXPECT_FALSE(status.ok());
-  EXPECT_EQ(status.error_message(), "circuit breaker drop");
-  // Cancel one RPC to allow another one through
-  rpcs[0].CancelRpc();
-  status = SendRpc();
-  EXPECT_TRUE(status.ok());
-  for (size_t i = 1; i < kMaxConcurrentRequests; ++i) {
-    rpcs[i].CancelRpc();
-  }
-  // Make sure RPCs go to the correct backend:
-  EXPECT_EQ(kMaxConcurrentRequests + 1,
-            backends_[0]->backend_service()->request_count());
-}
-
-TEST_P(XdsResolverOnlyTest, CircuitBreakingMultipleChannelsShareCallCounter) {
-  constexpr size_t kMaxConcurrentRequests = 10;
-  // Populate new EDS resources.
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 1)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
-  // Update CDS resource to set max concurrent request.
-  CircuitBreakers circuit_breaks;
-  Cluster cluster = default_cluster_;
-  auto* threshold = cluster.mutable_circuit_breakers()->add_thresholds();
-  threshold->set_priority(RoutingPriority::DEFAULT);
-  threshold->mutable_max_requests()->set_value(kMaxConcurrentRequests);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  // Create second channel.
-  auto response_generator2 =
-      grpc_core::MakeRefCounted<grpc_core::FakeResolverResponseGenerator>();
-  auto lb_response_generator2 =
-      grpc_core::MakeRefCounted<grpc_core::FakeResolverResponseGenerator>();
-  grpc_arg xds_arg = grpc_core::FakeResolverResponseGenerator::MakeChannelArg(
-      lb_response_generator2.get());
-  grpc_channel_args xds_channel_args2 = {1, &xds_arg};
-  auto channel2 = CreateChannel(
-      /*failover_timeout=*/0, /*server_name=*/kServerName,
-      response_generator2.get(), &xds_channel_args2);
-  auto stub2 = grpc::testing::EchoTestService::NewStub(channel2);
-  // Set resolution results for both channels and for the xDS channel.
-  SetNextResolution({});
-  SetNextResolution({}, response_generator2.get());
-  SetNextResolutionForLbChannelAllBalancers();
-  SetNextResolutionForLbChannelAllBalancers(nullptr, nullptr,
-                                            lb_response_generator2.get());
-  // Send exactly max_concurrent_requests long RPCs, alternating between
-  // the two channels.
-  LongRunningRpc rpcs[kMaxConcurrentRequests];
-  for (size_t i = 0; i < kMaxConcurrentRequests; ++i) {
-    rpcs[i].StartRpc(i % 2 == 0 ? stub_.get() : stub2.get());
-  }
-  // Wait for all RPCs to be in flight.
-  while (backends_[0]->backend_service()->RpcsWaitingForClientCancel() <
-         kMaxConcurrentRequests) {
-    gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
-                                 gpr_time_from_micros(1 * 1000, GPR_TIMESPAN)));
-  }
-  // Sending a RPC now should fail, the error message should tell us
-  // we hit the max concurrent requests limit and got dropped.
-  Status status = SendRpc();
-  EXPECT_FALSE(status.ok());
-  EXPECT_EQ(status.error_message(), "circuit breaker drop");
-  // Cancel one RPC to allow another one through
-  rpcs[0].CancelRpc();
-  status = SendRpc();
-  EXPECT_TRUE(status.ok());
-  for (size_t i = 1; i < kMaxConcurrentRequests; ++i) {
-    rpcs[i].CancelRpc();
-  }
-  // Make sure RPCs go to the correct backend:
-  EXPECT_EQ(kMaxConcurrentRequests + 1,
-            backends_[0]->backend_service()->request_count());
-}
-
-TEST_P(XdsResolverOnlyTest, ClusterChangeAfterAdsCallFails) {
-  const char* kNewEdsResourceName = "new_eds_resource_name";
-  // Populate EDS resources.
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 1)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
-  SetNextResolutionForLbChannelAllBalancers();
-  // Check that the channel is working.
-  CheckRpcSendOk();
-  // Stop and restart the balancer.
-  balancers_[0]->Shutdown();
-  balancers_[0]->Start();
-  // Create new EDS resource.
-  AdsServiceImpl::EdsResourceArgs args2({
-      {"locality0", CreateEndpointsForBackends(1, 2)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args2, kNewEdsResourceName));
-  // Change CDS resource to point to new EDS resource.
-  auto cluster = default_cluster_;
-  cluster.mutable_eds_cluster_config()->set_service_name(kNewEdsResourceName);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  // Make sure client sees the change.
-  // TODO(roth): This should not be allowing errors.  The errors are
-  // being caused by a bug that triggers in the following situation:
-  //
-  // 1. xDS call fails.
-  // 2. When xDS call is restarted, the server sends the updated CDS
-  //    resource that points to the new EDS resource name.
-  // 3. When the client receives the CDS update, it does two things:
-  //    - Sends the update to the CDS LB policy, which creates a new
-  //      xds_cluster_resolver policy using the new EDS service name.
-  //    - Notices that the CDS update no longer refers to the old EDS
-  //      service name, so removes that resource, notifying the old
-  //      xds_cluster_resolver policy that the resource no longer exists.
-  //
-  // Need to figure out a way to fix this bug, and then change this to
-  // not allow failures.
-  WaitForBackend(1, WaitForBackendOptions().set_allow_failures(true));
-}
-
-using GlobalXdsClientTest = BasicTest;
-
-TEST_P(GlobalXdsClientTest, MultipleChannelsShareXdsClient) {
-  const char* kNewServerName = "new-server.example.com";
-  Listener listener = default_listener_;
-  listener.set_name(kNewServerName);
-  SetListenerAndRouteConfiguration(0, listener, default_route_config_);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
-  WaitForAllBackends();
-  // Create second channel and tell it to connect to kNewServerName.
-  auto channel2 = CreateChannel(/*failover_timeout=*/0, kNewServerName);
-  channel2->GetState(/*try_to_connect=*/true);
-  ASSERT_TRUE(
-      channel2->WaitForConnected(grpc_timeout_milliseconds_to_deadline(100)));
-  // Make sure there's only one client connected.
-  EXPECT_EQ(1UL, balancers_[0]->ads_service()->clients().size());
-}
-
-// Tests that the NACK for multiple bad LDS resources includes both errors.
-TEST_P(GlobalXdsClientTest, MultipleBadResources) {
-  constexpr char kServerName2[] = "server.other.com";
-  constexpr char kServerName3[] = "server.another.com";
-  auto listener = default_listener_;
-  listener.clear_api_listener();
-  balancers_[0]->ads_service()->SetLdsResource(listener);
-  listener.set_name(kServerName2);
-  balancers_[0]->ads_service()->SetLdsResource(listener);
-  listener = default_listener_;
-  listener.set_name(kServerName3);
-  SetListenerAndRouteConfiguration(0, listener, default_route_config_);
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 1)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
-  SetNextResolutionForLbChannelAllBalancers();
-  CheckRpcSendFailure();
-  // Need to create a second channel to subscribe to a second LDS resource.
-  auto channel2 = CreateChannel(0, kServerName2);
-  auto stub2 = grpc::testing::EchoTestService::NewStub(channel2);
-  {
-    ClientContext context;
-    EchoRequest request;
-    request.set_message(kRequestMessage);
-    EchoResponse response;
-    grpc::Status status = stub2->Echo(&context, request, &response);
-    EXPECT_FALSE(status.ok());
-    // Wait for second NACK to be reported to xDS server.
-    auto deadline = absl::Now() + absl::Seconds(30);
-    bool timed_out = false;
-    CheckRpcSendFailure(
-        CheckRpcSendFailureOptions().set_continue_predicate([&](size_t) {
-          if (absl::Now() >= deadline) {
-            timed_out = true;
-            return false;
-          }
-          const auto response_state =
-              balancers_[0]->ads_service()->lds_response_state();
-          return response_state.state !=
-                     AdsServiceImpl::ResponseState::NACKED ||
-                 ::testing::Matches(::testing::ContainsRegex(absl::StrCat(
-                     kServerName,
-                     ": validation error.*"
-                     "Listener has neither address nor ApiListener.*",
-                     kServerName2,
-                     ": validation error.*"
-                     "Listener has neither address nor ApiListener")))(
-                     response_state.error_message);
-        }));
-    ASSERT_FALSE(timed_out);
-  }
-  // Now start a new channel with a third server name, this one with a
-  // valid resource.
-  auto channel3 = CreateChannel(0, kServerName3);
-  auto stub3 = grpc::testing::EchoTestService::NewStub(channel3);
-  {
-    ClientContext context;
-    EchoRequest request;
-    request.set_message(kRequestMessage);
-    EchoResponse response;
-    grpc::Status status = stub3->Echo(&context, request, &response);
-    EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
-                             << " message=" << status.error_message();
-  }
-}
-
-// Tests that we don't trigger does-not-exist callbacks for a resource
-// that was previously valid but is updated to be invalid.
-TEST_P(GlobalXdsClientTest, InvalidListenerStillExistsIfPreviouslyCached) {
-  // Set up valid resources and check that the channel works.
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 1)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
-  SetNextResolutionForLbChannelAllBalancers();
-  CheckRpcSendOk();
-  // Now send an update changing the Listener to be invalid.
-  auto listener = default_listener_;
-  listener.clear_api_listener();
-  balancers_[0]->ads_service()->SetLdsResource(listener);
-  // Wait for xDS server to see NACK.
-  auto deadline = absl::Now() + absl::Seconds(30);
-  do {
-    CheckRpcSendOk();
-    ASSERT_LT(absl::Now(), deadline);
-  } while (balancers_[0]->ads_service()->lds_response_state().state !=
-           AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(balancers_[0]->ads_service()->lds_response_state().error_message,
-              ::testing::ContainsRegex(absl::StrCat(
-                  kServerName,
-                  ": validation error.*"
-                  "Listener has neither address nor ApiListener")));
-  // Check one more time, just to make sure it still works after NACK.
-  CheckRpcSendOk();
-}
-
-class XdsResolverLoadReportingOnlyTest : public XdsEnd2endTest {
- public:
-  XdsResolverLoadReportingOnlyTest() : XdsEnd2endTest(4, 1, 3) {}
-};
-
-// Tests load reporting when switching over from one cluster to another.
-TEST_P(XdsResolverLoadReportingOnlyTest, ChangeClusters) {
-  const char* kNewClusterName = "new_cluster_name";
-  const char* kNewEdsServiceName = "new_eds_service_name";
-  balancers_[0]->lrs_service()->set_cluster_names(
-      {kDefaultClusterName, kNewClusterName});
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // cluster kDefaultClusterName -> locality0 -> backends 0 and 1
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 2)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
-  // cluster kNewClusterName -> locality1 -> backends 2 and 3
-  AdsServiceImpl::EdsResourceArgs args2({
-      {"locality1", CreateEndpointsForBackends(2, 4)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args2, kNewEdsServiceName));
-  // CDS resource for kNewClusterName.
-  Cluster new_cluster = default_cluster_;
-  new_cluster.set_name(kNewClusterName);
-  new_cluster.mutable_eds_cluster_config()->set_service_name(
-      kNewEdsServiceName);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster);
-  // Wait for all backends to come online.
-  int num_ok = 0;
-  int num_failure = 0;
-  int num_drops = 0;
-  std::tie(num_ok, num_failure, num_drops) = WaitForAllBackends(0, 2);
-  // The load report received at the balancer should be correct.
-  std::vector<ClientStats> load_report =
-      balancers_[0]->lrs_service()->WaitForLoadReport();
-  EXPECT_THAT(
-      load_report,
-      ::testing::ElementsAre(::testing::AllOf(
-          ::testing::Property(&ClientStats::cluster_name, kDefaultClusterName),
-          ::testing::Property(
-              &ClientStats::locality_stats,
-              ::testing::ElementsAre(::testing::Pair(
-                  "locality0",
-                  ::testing::AllOf(
-                      ::testing::Field(&ClientStats::LocalityStats::
-                                           total_successful_requests,
-                                       num_ok),
-                      ::testing::Field(&ClientStats::LocalityStats::
-                                           total_requests_in_progress,
-                                       0UL),
-                      ::testing::Field(
-                          &ClientStats::LocalityStats::total_error_requests,
-                          num_failure),
-                      ::testing::Field(
-                          &ClientStats::LocalityStats::total_issued_requests,
-                          num_failure + num_ok))))),
-          ::testing::Property(&ClientStats::total_dropped_requests,
-                              num_drops))));
-  // Change RDS resource to point to new cluster.
-  RouteConfiguration new_route_config = default_route_config_;
-  new_route_config.mutable_virtual_hosts(0)
-      ->mutable_routes(0)
-      ->mutable_route()
-      ->set_cluster(kNewClusterName);
-  SetListenerAndRouteConfiguration(0, default_listener_, new_route_config);
-  // Wait for all new backends to be used.
-  std::tie(num_ok, num_failure, num_drops) = WaitForAllBackends(2, 4);
-  // The load report received at the balancer should be correct.
-  load_report = balancers_[0]->lrs_service()->WaitForLoadReport();
-  EXPECT_THAT(
-      load_report,
-      ::testing::ElementsAre(
-          ::testing::AllOf(
-              ::testing::Property(&ClientStats::cluster_name,
-                                  kDefaultClusterName),
-              ::testing::Property(
-                  &ClientStats::locality_stats,
-                  ::testing::ElementsAre(::testing::Pair(
-                      "locality0",
-                      ::testing::AllOf(
-                          ::testing::Field(&ClientStats::LocalityStats::
-                                               total_successful_requests,
-                                           ::testing::Lt(num_ok)),
-                          ::testing::Field(&ClientStats::LocalityStats::
-                                               total_requests_in_progress,
-                                           0UL),
-                          ::testing::Field(
-                              &ClientStats::LocalityStats::total_error_requests,
-                              ::testing::Le(num_failure)),
-                          ::testing::Field(
-                              &ClientStats::LocalityStats::
-                                  total_issued_requests,
-                              ::testing::Le(num_failure + num_ok)))))),
-              ::testing::Property(&ClientStats::total_dropped_requests,
-                                  num_drops)),
-          ::testing::AllOf(
-              ::testing::Property(&ClientStats::cluster_name, kNewClusterName),
-              ::testing::Property(
-                  &ClientStats::locality_stats,
-                  ::testing::ElementsAre(::testing::Pair(
-                      "locality1",
-                      ::testing::AllOf(
-                          ::testing::Field(&ClientStats::LocalityStats::
-                                               total_successful_requests,
-                                           ::testing::Le(num_ok)),
-                          ::testing::Field(&ClientStats::LocalityStats::
-                                               total_requests_in_progress,
-                                           0UL),
-                          ::testing::Field(
-                              &ClientStats::LocalityStats::total_error_requests,
-                              ::testing::Le(num_failure)),
-                          ::testing::Field(
-                              &ClientStats::LocalityStats::
-                                  total_issued_requests,
-                              ::testing::Le(num_failure + num_ok)))))),
-              ::testing::Property(&ClientStats::total_dropped_requests,
-                                  num_drops))));
-  int total_ok = 0;
-  int total_failure = 0;
-  for (const ClientStats& client_stats : load_report) {
-    total_ok += client_stats.total_successful_requests();
-    total_failure += client_stats.total_error_requests();
-  }
-  EXPECT_EQ(total_ok, num_ok);
-  EXPECT_EQ(total_failure, num_failure);
-  // The LRS service got a single request, and sent a single response.
-  EXPECT_EQ(1U, balancers_[0]->lrs_service()->request_count());
-  EXPECT_EQ(1U, balancers_[0]->lrs_service()->response_count());
-}
-
-using SecureNamingTest = BasicTest;
-
-// Tests that secure naming check passes if target name is expected.
-TEST_P(SecureNamingTest, TargetNameIsExpected) {
-  SetNextResolution({});
-  SetNextResolutionForLbChannel({balancers_[0]->port()}, nullptr, "xds_server");
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  CheckRpcSendOk();
-}
-
-// Tests that secure naming check fails if target name is unexpected.
-TEST_P(SecureNamingTest, TargetNameIsUnexpected) {
-  GRPC_GTEST_FLAG_SET_DEATH_TEST_STYLE("threadsafe");
-  SetNextResolution({});
-  SetNextResolutionForLbChannel({balancers_[0]->port()}, nullptr,
-                                "incorrect_server_name");
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  // Make sure that we blow up (via abort() from the security connector) when
-  // the name from the balancer doesn't match expectations.
-  ASSERT_DEATH_IF_SUPPORTED({ CheckRpcSendOk(); }, "");
-}
-
-using LdsTest = BasicTest;
-
-// Tests that LDS client should send a NACK if there is no API listener in the
-// Listener in the LDS response.
-TEST_P(LdsTest, NoApiListener) {
-  auto listener = default_listener_;
-  listener.clear_api_listener();
-  balancers_[0]->ads_service()->SetLdsResource(listener);
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForLdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->lds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(
-      response_state.error_message,
-      ::testing::HasSubstr("Listener has neither address nor ApiListener"));
-}
-
-// Tests that LDS client should send a NACK if the route_specifier in the
-// http_connection_manager is neither inlined route_config nor RDS.
-TEST_P(LdsTest, WrongRouteSpecifier) {
-  auto listener = default_listener_;
-  HttpConnectionManager http_connection_manager;
-  listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
-      &http_connection_manager);
-  http_connection_manager.mutable_scoped_routes();
-  listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
-      http_connection_manager);
-  balancers_[0]->ads_service()->SetLdsResource(listener);
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForLdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->lds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(
-      response_state.error_message,
-      ::testing::HasSubstr(
-          "HttpConnectionManager neither has inlined route_config nor RDS."));
-}
-
-// Tests that LDS client should send a NACK if the rds message in the
-// http_connection_manager is missing the config_source field.
-TEST_P(LdsTest, RdsMissingConfigSource) {
-  auto listener = default_listener_;
-  HttpConnectionManager http_connection_manager;
-  listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
-      &http_connection_manager);
-  http_connection_manager.mutable_rds()->set_route_config_name(
-      kDefaultRouteConfigurationName);
-  listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
-      http_connection_manager);
-  balancers_[0]->ads_service()->SetLdsResource(listener);
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForLdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->lds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr(
-                  "HttpConnectionManager missing config_source for RDS."));
-}
-
-// Tests that LDS client should send a NACK if the rds message in the
-// http_connection_manager has a config_source field that does not specify
-// ADS.
-TEST_P(LdsTest, RdsConfigSourceDoesNotSpecifyAds) {
-  auto listener = default_listener_;
-  HttpConnectionManager http_connection_manager;
-  listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
-      &http_connection_manager);
-  auto* rds = http_connection_manager.mutable_rds();
-  rds->set_route_config_name(kDefaultRouteConfigurationName);
-  rds->mutable_config_source()->mutable_self();
-  listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
-      http_connection_manager);
-  balancers_[0]->ads_service()->SetLdsResource(listener);
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForLdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->lds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr("HttpConnectionManager ConfigSource for "
-                                   "RDS does not specify ADS."));
-}
-
-// Tests that we NACK non-terminal filters at the end of the list.
-TEST_P(LdsTest, NacksNonTerminalHttpFilterAtEndOfList) {
-  SetNextResolutionForLbChannelAllBalancers();
-  auto listener = default_listener_;
-  HttpConnectionManager http_connection_manager;
-  listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
-      &http_connection_manager);
-  auto* filter = http_connection_manager.mutable_http_filters(0);
-  filter->set_name("unknown");
-  filter->mutable_typed_config()->set_type_url(
-      "grpc.testing.client_only_http_filter");
-  listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
-      http_connection_manager);
-  SetListenerAndRouteConfiguration(0, listener, default_route_config_);
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForLdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->lds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr(
-                  "non-terminal filter for config type grpc.testing"
-                  ".client_only_http_filter is the last filter in the chain"));
-}
-
-// Test that we NACK terminal filters that are not at the end of the list.
-TEST_P(LdsTest, NacksTerminalFilterBeforeEndOfList) {
-  SetNextResolutionForLbChannelAllBalancers();
-  auto listener = default_listener_;
-  HttpConnectionManager http_connection_manager;
-  listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
-      &http_connection_manager);
-  *http_connection_manager.add_http_filters() =
-      http_connection_manager.http_filters(0);
-  listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
-      http_connection_manager);
-  SetListenerAndRouteConfiguration(0, listener, default_route_config_);
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForLdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->lds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(
-      response_state.error_message,
-      ::testing::HasSubstr(
-          "terminal filter for config type envoy.extensions.filters.http"
-          ".router.v3.Router must be the last filter in the chain"));
-}
-
-// Test that we NACK empty filter names.
-TEST_P(LdsTest, RejectsEmptyHttpFilterName) {
-  auto listener = default_listener_;
-  HttpConnectionManager http_connection_manager;
-  listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
-      &http_connection_manager);
-  *http_connection_manager.add_http_filters() =
-      http_connection_manager.http_filters(0);
-  auto* filter = http_connection_manager.mutable_http_filters(0);
-  filter->Clear();
-  filter->mutable_typed_config()->PackFrom(Listener());
-  listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
-      http_connection_manager);
-  SetListenerAndRouteConfiguration(0, listener, default_route_config_);
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForLdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->lds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr("empty filter name at index 0"));
-}
-
-// Test that we NACK duplicate HTTP filter names.
-TEST_P(LdsTest, RejectsDuplicateHttpFilterName) {
-  auto listener = default_listener_;
-  HttpConnectionManager http_connection_manager;
-  listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
-      &http_connection_manager);
-  *http_connection_manager.add_http_filters() =
-      http_connection_manager.http_filters(0);
-  http_connection_manager.mutable_http_filters(0)
-      ->mutable_typed_config()
-      ->PackFrom(HTTPFault());
-  listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
-      http_connection_manager);
-  SetListenerAndRouteConfiguration(0, listener, default_route_config_);
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForLdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->lds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr("duplicate HTTP filter name: router"));
-}
-
-// Test that we NACK unknown filter types.
-TEST_P(LdsTest, RejectsUnknownHttpFilterType) {
-  auto listener = default_listener_;
-  HttpConnectionManager http_connection_manager;
-  listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
-      &http_connection_manager);
-  *http_connection_manager.add_http_filters() =
-      http_connection_manager.http_filters(0);
-  auto* filter = http_connection_manager.mutable_http_filters(0);
-  filter->set_name("unknown");
-  filter->mutable_typed_config()->PackFrom(Listener());
-  listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
-      http_connection_manager);
-  SetListenerAndRouteConfiguration(0, listener, default_route_config_);
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForLdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->lds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr("no filter registered for config type "
-                                   "envoy.config.listener.v3.Listener"));
-}
-
-// Test that we ignore optional unknown filter types.
-TEST_P(LdsTest, IgnoresOptionalUnknownHttpFilterType) {
-  auto listener = default_listener_;
-  HttpConnectionManager http_connection_manager;
-  listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
-      &http_connection_manager);
-  *http_connection_manager.add_http_filters() =
-      http_connection_manager.http_filters(0);
-  auto* filter = http_connection_manager.mutable_http_filters(0);
-  filter->set_name("unknown");
-  filter->mutable_typed_config()->PackFrom(Listener());
-  filter->set_is_optional(true);
-  listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
-      http_connection_manager);
-  SetListenerAndRouteConfiguration(0, listener, default_route_config_);
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  SetNextResolutionForLbChannelAllBalancers();
-  WaitForAllBackends();
-  EXPECT_EQ(balancers_[0]->ads_service()->lds_response_state().state,
-            AdsServiceImpl::ResponseState::ACKED);
-}
-
-// Test that we NACK filters without configs.
-TEST_P(LdsTest, RejectsHttpFilterWithoutConfig) {
-  auto listener = default_listener_;
-  HttpConnectionManager http_connection_manager;
-  listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
-      &http_connection_manager);
-  *http_connection_manager.add_http_filters() =
-      http_connection_manager.http_filters(0);
-  auto* filter = http_connection_manager.mutable_http_filters(0);
-  filter->Clear();
-  filter->set_name("unknown");
-  listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
-      http_connection_manager);
-  SetListenerAndRouteConfiguration(0, listener, default_route_config_);
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForLdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->lds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr(
-                  "no filter config specified for filter name unknown"));
-}
-
-// Test that we ignore optional filters without configs.
-TEST_P(LdsTest, IgnoresOptionalHttpFilterWithoutConfig) {
-  auto listener = default_listener_;
-  HttpConnectionManager http_connection_manager;
-  listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
-      &http_connection_manager);
-  *http_connection_manager.add_http_filters() =
-      http_connection_manager.http_filters(0);
-  auto* filter = http_connection_manager.mutable_http_filters(0);
-  filter->Clear();
-  filter->set_name("unknown");
-  filter->set_is_optional(true);
-  listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
-      http_connection_manager);
-  SetListenerAndRouteConfiguration(0, listener, default_route_config_);
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  SetNextResolutionForLbChannelAllBalancers();
-  WaitForAllBackends();
-  EXPECT_EQ(balancers_[0]->ads_service()->lds_response_state().state,
-            AdsServiceImpl::ResponseState::ACKED);
-}
-
-// Test that we NACK unparseable filter configs.
-TEST_P(LdsTest, RejectsUnparseableHttpFilterType) {
-  auto listener = default_listener_;
-  HttpConnectionManager http_connection_manager;
-  listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
-      &http_connection_manager);
-  *http_connection_manager.add_http_filters() =
-      http_connection_manager.http_filters(0);
-  auto* filter = http_connection_manager.mutable_http_filters(0);
-  filter->set_name("unknown");
-  filter->mutable_typed_config()->PackFrom(listener);
-  filter->mutable_typed_config()->set_type_url(
-      "type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault");
-  listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
-      http_connection_manager);
-  SetListenerAndRouteConfiguration(0, listener, default_route_config_);
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForLdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->lds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(
-      response_state.error_message,
-      ::testing::HasSubstr(
-          "filter config for type "
-          "envoy.extensions.filters.http.fault.v3.HTTPFault failed to parse"));
-}
-
-// Test that we NACK HTTP filters unsupported on client-side.
-TEST_P(LdsTest, RejectsHttpFiltersNotSupportedOnClients) {
-  auto listener = default_listener_;
-  HttpConnectionManager http_connection_manager;
-  listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
-      &http_connection_manager);
-  *http_connection_manager.add_http_filters() =
-      http_connection_manager.http_filters(0);
-  auto* filter = http_connection_manager.mutable_http_filters(0);
-  filter->set_name("grpc.testing.server_only_http_filter");
-  filter->mutable_typed_config()->set_type_url(
-      "grpc.testing.server_only_http_filter");
-  listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
-      http_connection_manager);
-  SetListenerAndRouteConfiguration(0, listener, default_route_config_);
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForLdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->lds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(
-      response_state.error_message,
-      ::testing::HasSubstr("Filter grpc.testing.server_only_http_filter is not "
-                           "supported on clients"));
-}
-
-// Test that we ignore optional HTTP filters unsupported on client-side.
-TEST_P(LdsTest, IgnoresOptionalHttpFiltersNotSupportedOnClients) {
-  auto listener = default_listener_;
-  HttpConnectionManager http_connection_manager;
-  listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
-      &http_connection_manager);
-  *http_connection_manager.add_http_filters() =
-      http_connection_manager.http_filters(0);
-  auto* filter = http_connection_manager.mutable_http_filters(0);
-  filter->set_name("grpc.testing.server_only_http_filter");
-  filter->mutable_typed_config()->set_type_url(
-      "grpc.testing.server_only_http_filter");
-  filter->set_is_optional(true);
-  listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
-      http_connection_manager);
-  SetListenerAndRouteConfiguration(0, listener, default_route_config_);
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 1)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  SetNextResolutionForLbChannelAllBalancers();
-  WaitForBackend(0);
-  EXPECT_EQ(balancers_[0]->ads_service()->lds_response_state().state,
-            AdsServiceImpl::ResponseState::ACKED);
-}
-
-using LdsV2Test = LdsTest;
-
-// Tests that we ignore the HTTP filter list in v2.
-// TODO(roth): The test framework is not set up to allow us to test
-// the server sending v2 resources when the client requests v3, so this
-// just tests a pure v2 setup.  When we have time, fix this.
-TEST_P(LdsV2Test, IgnoresHttpFilters) {
-  auto listener = default_listener_;
-  HttpConnectionManager http_connection_manager;
-  listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
-      &http_connection_manager);
-  auto* filter = http_connection_manager.add_http_filters();
-  filter->set_name("unknown");
-  filter->mutable_typed_config()->PackFrom(Listener());
-  listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
-      http_connection_manager);
-  SetListenerAndRouteConfiguration(0, listener, default_route_config_);
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 1)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  SetNextResolutionForLbChannelAllBalancers();
-  CheckRpcSendOk();
-}
-
-using LdsRdsTest = BasicTest;
-
-// Tests that LDS client should send an ACK upon correct LDS response (with
-// inlined RDS result).
-TEST_P(LdsRdsTest, Vanilla) {
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  (void)SendRpc();
-  EXPECT_EQ(RouteConfigurationResponseState(0).state,
-            AdsServiceImpl::ResponseState::ACKED);
-  // Make sure we actually used the RPC service for the right version of xDS.
-  EXPECT_EQ(balancers_[0]->ads_service()->seen_v2_client(),
-            GetParam().use_v2());
-  EXPECT_NE(balancers_[0]->ads_service()->seen_v3_client(),
-            GetParam().use_v2());
-}
-
-// Tests that we go into TRANSIENT_FAILURE if the Listener is removed.
-TEST_P(LdsRdsTest, ListenerRemoved) {
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
-  // We need to wait for all backends to come online.
-  WaitForAllBackends();
-  // Unset LDS resource.
-  balancers_[0]->ads_service()->UnsetResource(kLdsTypeUrl, kServerName);
-  // Wait for RPCs to start failing.
-  do {
-  } while (SendRpc(RpcOptions(), nullptr).ok());
-  // Make sure RPCs are still failing.
-  CheckRpcSendFailure(CheckRpcSendFailureOptions().set_times(1000));
-  // Make sure we ACK'ed the update.
-  EXPECT_EQ(balancers_[0]->ads_service()->lds_response_state().state,
-            AdsServiceImpl::ResponseState::ACKED);
-}
-
-// Tests that LDS client ACKs but fails if matching domain can't be found in
-// the LDS response.
-TEST_P(LdsRdsTest, NoMatchedDomain) {
-  RouteConfiguration route_config = default_route_config_;
-  route_config.mutable_virtual_hosts(0)->clear_domains();
-  route_config.mutable_virtual_hosts(0)->add_domains("unmatched_domain");
-  SetRouteConfiguration(0, route_config);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  CheckRpcSendFailure();
-  // Do a bit of polling, to allow the ACK to get to the ADS server.
-  channel_->WaitForConnected(grpc_timeout_milliseconds_to_deadline(100));
-  const auto response_state = RouteConfigurationResponseState(0);
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::ACKED);
-}
-
-// Tests that LDS client should choose the virtual host with matching domain
-// if multiple virtual hosts exist in the LDS response.
-TEST_P(LdsRdsTest, ChooseMatchedDomain) {
-  RouteConfiguration route_config = default_route_config_;
-  *(route_config.add_virtual_hosts()) = route_config.virtual_hosts(0);
-  route_config.mutable_virtual_hosts(0)->clear_domains();
-  route_config.mutable_virtual_hosts(0)->add_domains("unmatched_domain");
-  SetRouteConfiguration(0, route_config);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  (void)SendRpc();
-  EXPECT_EQ(RouteConfigurationResponseState(0).state,
-            AdsServiceImpl::ResponseState::ACKED);
-}
-
-// Tests that LDS client should choose the last route in the virtual host if
-// multiple routes exist in the LDS response.
-TEST_P(LdsRdsTest, ChooseLastRoute) {
-  RouteConfiguration route_config = default_route_config_;
-  *(route_config.mutable_virtual_hosts(0)->add_routes()) =
-      route_config.virtual_hosts(0).routes(0);
-  route_config.mutable_virtual_hosts(0)
-      ->mutable_routes(0)
-      ->mutable_route()
-      ->mutable_cluster_header();
-  SetRouteConfiguration(0, route_config);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  (void)SendRpc();
-  EXPECT_EQ(RouteConfigurationResponseState(0).state,
-            AdsServiceImpl::ResponseState::ACKED);
-}
-
-// Tests that LDS client should ignore route which has query_parameters.
-TEST_P(LdsRdsTest, RouteMatchHasQueryParameters) {
-  RouteConfiguration route_config = default_route_config_;
-  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/");
-  route1->mutable_match()->add_query_parameters();
-  SetRouteConfiguration(0, route_config);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
-  const auto response_state = RouteConfigurationResponseState(0);
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr("No valid routes specified."));
-}
-
-// Tests that LDS client should send a ACK if route match has a prefix
-// that is either empty or a single slash
-TEST_P(LdsRdsTest, RouteMatchHasValidPrefixEmptyOrSingleSlash) {
-  RouteConfiguration route_config = default_route_config_;
-  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  route1->mutable_match()->set_prefix("");
-  auto* default_route = route_config.mutable_virtual_hosts(0)->add_routes();
-  default_route->mutable_match()->set_prefix("/");
-  default_route->mutable_route()->set_cluster(kDefaultClusterName);
-  SetRouteConfiguration(0, route_config);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  (void)SendRpc();
-  const auto response_state = RouteConfigurationResponseState(0);
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::ACKED);
-}
-
-// Tests that LDS client should ignore route which has a path
-// prefix string does not start with "/".
-TEST_P(LdsRdsTest, RouteMatchHasInvalidPrefixNoLeadingSlash) {
-  RouteConfiguration route_config = default_route_config_;
-  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  route1->mutable_match()->set_prefix("grpc.testing.EchoTest1Service/");
-  SetRouteConfiguration(0, route_config);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
-  const auto response_state = RouteConfigurationResponseState(0);
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr("No valid routes specified."));
-}
-
-// Tests that LDS client should ignore route which has a prefix
-// string with more than 2 slashes.
-TEST_P(LdsRdsTest, RouteMatchHasInvalidPrefixExtraContent) {
-  RouteConfiguration route_config = default_route_config_;
-  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/Echo1/");
-  SetRouteConfiguration(0, route_config);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
-  const auto response_state = RouteConfigurationResponseState(0);
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr("No valid routes specified."));
-}
-
-// Tests that LDS client should ignore route which has a prefix
-// string "//".
-TEST_P(LdsRdsTest, RouteMatchHasInvalidPrefixDoubleSlash) {
-  RouteConfiguration route_config = default_route_config_;
-  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  route1->mutable_match()->set_prefix("//");
-  SetRouteConfiguration(0, route_config);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
-  const auto response_state = RouteConfigurationResponseState(0);
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr("No valid routes specified."));
-}
-
-// Tests that LDS client should ignore route which has path
-// but it's empty.
-TEST_P(LdsRdsTest, RouteMatchHasInvalidPathEmptyPath) {
-  RouteConfiguration route_config = default_route_config_;
-  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  route1->mutable_match()->set_path("");
-  SetRouteConfiguration(0, route_config);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
-  const auto response_state = RouteConfigurationResponseState(0);
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr("No valid routes specified."));
-}
-
-// Tests that LDS client should ignore route which has path
-// string does not start with "/".
-TEST_P(LdsRdsTest, RouteMatchHasInvalidPathNoLeadingSlash) {
-  RouteConfiguration route_config = default_route_config_;
-  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  route1->mutable_match()->set_path("grpc.testing.EchoTest1Service/Echo1");
-  SetRouteConfiguration(0, route_config);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
-  const auto response_state = RouteConfigurationResponseState(0);
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr("No valid routes specified."));
-}
-
-// Tests that LDS client should ignore route which has path
-// string that has too many slashes; for example, ends with "/".
-TEST_P(LdsRdsTest, RouteMatchHasInvalidPathTooManySlashes) {
-  RouteConfiguration route_config = default_route_config_;
-  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  route1->mutable_match()->set_path("/grpc.testing.EchoTest1Service/Echo1/");
-  SetRouteConfiguration(0, route_config);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
-  const auto response_state = RouteConfigurationResponseState(0);
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr("No valid routes specified."));
-}
-
-// Tests that LDS client should ignore route which has path
-// string that has only 1 slash: missing "/" between service and method.
-TEST_P(LdsRdsTest, RouteMatchHasInvalidPathOnlyOneSlash) {
-  RouteConfiguration route_config = default_route_config_;
-  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  route1->mutable_match()->set_path("/grpc.testing.EchoTest1Service.Echo1");
-  SetRouteConfiguration(0, route_config);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
-  const auto response_state = RouteConfigurationResponseState(0);
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr("No valid routes specified."));
-}
-
-// Tests that LDS client should ignore route which has path
-// string that is missing service.
-TEST_P(LdsRdsTest, RouteMatchHasInvalidPathMissingService) {
-  RouteConfiguration route_config = default_route_config_;
-  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  route1->mutable_match()->set_path("//Echo1");
-  SetRouteConfiguration(0, route_config);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
-  const auto response_state = RouteConfigurationResponseState(0);
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr("No valid routes specified."));
-}
-
-// Tests that LDS client should ignore route which has path
-// string that is missing method.
-TEST_P(LdsRdsTest, RouteMatchHasInvalidPathMissingMethod) {
-  RouteConfiguration route_config = default_route_config_;
-  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  route1->mutable_match()->set_path("/grpc.testing.EchoTest1Service/");
-  SetRouteConfiguration(0, route_config);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
-  const auto response_state = RouteConfigurationResponseState(0);
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr("No valid routes specified."));
-}
-
-// Test that LDS client should reject route which has invalid path regex.
-TEST_P(LdsRdsTest, RouteMatchHasInvalidPathRegex) {
-  const char* kNewCluster1Name = "new_cluster_1";
-  RouteConfiguration route_config = default_route_config_;
-  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  route1->mutable_match()->mutable_safe_regex()->set_regex("a[z-a]");
-  route1->mutable_route()->set_cluster(kNewCluster1Name);
-  SetRouteConfiguration(0, route_config);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
-  const auto response_state = RouteConfigurationResponseState(0);
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr(
-                  "path matcher: Invalid regex string specified in matcher."));
-}
-
-// Tests that LDS client should send a NACK if route has an action other than
-// RouteAction in the LDS response.
-TEST_P(LdsRdsTest, RouteHasNoRouteAction) {
-  RouteConfiguration route_config = default_route_config_;
-  route_config.mutable_virtual_hosts(0)->mutable_routes(0)->mutable_redirect();
-  SetRouteConfiguration(0, route_config);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
-  const auto response_state = RouteConfigurationResponseState(0);
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr("No RouteAction found in route."));
-}
-
-TEST_P(LdsRdsTest, RouteActionClusterHasEmptyClusterName) {
-  RouteConfiguration route_config = default_route_config_;
-  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/");
-  route1->mutable_route()->set_cluster("");
-  auto* default_route = route_config.mutable_virtual_hosts(0)->add_routes();
-  default_route->mutable_match()->set_prefix("");
-  default_route->mutable_route()->set_cluster(kDefaultClusterName);
-  SetRouteConfiguration(0, route_config);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
-  const auto response_state = RouteConfigurationResponseState(0);
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(
-      response_state.error_message,
-      ::testing::HasSubstr("RouteAction cluster contains empty cluster name."));
-}
-
-TEST_P(LdsRdsTest, RouteActionWeightedTargetHasIncorrectTotalWeightSet) {
-  const size_t kWeight75 = 75;
-  const char* kNewCluster1Name = "new_cluster_1";
-  RouteConfiguration route_config = default_route_config_;
-  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/");
-  auto* weighted_cluster1 =
-      route1->mutable_route()->mutable_weighted_clusters()->add_clusters();
-  weighted_cluster1->set_name(kNewCluster1Name);
-  weighted_cluster1->mutable_weight()->set_value(kWeight75);
-  route1->mutable_route()
-      ->mutable_weighted_clusters()
-      ->mutable_total_weight()
-      ->set_value(kWeight75 + 1);
-  auto* default_route = route_config.mutable_virtual_hosts(0)->add_routes();
-  default_route->mutable_match()->set_prefix("");
-  default_route->mutable_route()->set_cluster(kDefaultClusterName);
-  SetRouteConfiguration(0, route_config);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
-  const auto response_state = RouteConfigurationResponseState(0);
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr(
-                  "RouteAction weighted_cluster has incorrect total weight"));
-}
-
-TEST_P(LdsRdsTest, RouteActionWeightedClusterHasZeroTotalWeight) {
-  const char* kNewCluster1Name = "new_cluster_1";
-  RouteConfiguration route_config = default_route_config_;
-  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/");
-  auto* weighted_cluster1 =
-      route1->mutable_route()->mutable_weighted_clusters()->add_clusters();
-  weighted_cluster1->set_name(kNewCluster1Name);
-  weighted_cluster1->mutable_weight()->set_value(0);
-  route1->mutable_route()
-      ->mutable_weighted_clusters()
-      ->mutable_total_weight()
-      ->set_value(0);
-  auto* default_route = route_config.mutable_virtual_hosts(0)->add_routes();
-  default_route->mutable_match()->set_prefix("");
-  default_route->mutable_route()->set_cluster(kDefaultClusterName);
-  SetRouteConfiguration(0, route_config);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
-  const auto response_state = RouteConfigurationResponseState(0);
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(
-      response_state.error_message,
-      ::testing::HasSubstr(
-          "RouteAction weighted_cluster has no valid clusters specified."));
-}
-
-TEST_P(LdsRdsTest, RouteActionWeightedTargetClusterHasEmptyClusterName) {
-  const size_t kWeight75 = 75;
-  RouteConfiguration route_config = default_route_config_;
-  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/");
-  auto* weighted_cluster1 =
-      route1->mutable_route()->mutable_weighted_clusters()->add_clusters();
-  weighted_cluster1->set_name("");
-  weighted_cluster1->mutable_weight()->set_value(kWeight75);
-  route1->mutable_route()
-      ->mutable_weighted_clusters()
-      ->mutable_total_weight()
-      ->set_value(kWeight75);
-  auto* default_route = route_config.mutable_virtual_hosts(0)->add_routes();
-  default_route->mutable_match()->set_prefix("");
-  default_route->mutable_route()->set_cluster(kDefaultClusterName);
-  SetRouteConfiguration(0, route_config);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
-  const auto response_state = RouteConfigurationResponseState(0);
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr("RouteAction weighted_cluster cluster "
-                                   "contains empty cluster name."));
-}
-
-TEST_P(LdsRdsTest, RouteActionWeightedTargetClusterHasNoWeight) {
-  const size_t kWeight75 = 75;
-  const char* kNewCluster1Name = "new_cluster_1";
-  RouteConfiguration route_config = default_route_config_;
-  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/");
-  auto* weighted_cluster1 =
-      route1->mutable_route()->mutable_weighted_clusters()->add_clusters();
-  weighted_cluster1->set_name(kNewCluster1Name);
-  route1->mutable_route()
-      ->mutable_weighted_clusters()
-      ->mutable_total_weight()
-      ->set_value(kWeight75);
-  auto* default_route = route_config.mutable_virtual_hosts(0)->add_routes();
-  default_route->mutable_match()->set_prefix("");
-  default_route->mutable_route()->set_cluster(kDefaultClusterName);
-  SetRouteConfiguration(0, route_config);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
-  const auto response_state = RouteConfigurationResponseState(0);
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr(
-                  "RouteAction weighted_cluster cluster missing weight"));
-}
-
-TEST_P(LdsRdsTest, RouteHeaderMatchInvalidRegex) {
-  const char* kNewCluster1Name = "new_cluster_1";
-  RouteConfiguration route_config = default_route_config_;
-  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/");
-  auto* header_matcher1 = route1->mutable_match()->add_headers();
-  header_matcher1->set_name("header1");
-  header_matcher1->mutable_safe_regex_match()->set_regex("a[z-a]");
-  route1->mutable_route()->set_cluster(kNewCluster1Name);
-  SetRouteConfiguration(0, route_config);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
-  const auto response_state = RouteConfigurationResponseState(0);
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(
-      response_state.error_message,
-      ::testing::HasSubstr(
-          "header matcher: Invalid regex string specified in matcher."));
-}
-
-TEST_P(LdsRdsTest, RouteHeaderMatchInvalidRange) {
-  const char* kNewCluster1Name = "new_cluster_1";
-  RouteConfiguration route_config = default_route_config_;
-  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/");
-  auto* header_matcher1 = route1->mutable_match()->add_headers();
-  header_matcher1->set_name("header1");
-  header_matcher1->mutable_range_match()->set_start(1001);
-  header_matcher1->mutable_range_match()->set_end(1000);
-  route1->mutable_route()->set_cluster(kNewCluster1Name);
-  SetRouteConfiguration(0, route_config);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
-  const auto response_state = RouteConfigurationResponseState(0);
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(
-      response_state.error_message,
-      ::testing::HasSubstr(
-          "header matcher: Invalid range specifier specified: end cannot be "
-          "smaller than start."));
-}
-
-// Tests that LDS client should choose the default route (with no matching
-// specified) after unable to find a match with previous routes.
-TEST_P(LdsRdsTest, XdsRoutingPathMatching) {
-  const char* kNewCluster1Name = "new_cluster_1";
-  const char* kNewEdsService1Name = "new_eds_service_name_1";
-  const char* kNewCluster2Name = "new_cluster_2";
-  const char* kNewEdsService2Name = "new_eds_service_name_2";
-  const size_t kNumEcho1Rpcs = 10;
-  const size_t kNumEcho2Rpcs = 20;
-  const size_t kNumEchoRpcs = 30;
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Populate new EDS resources.
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 2)},
-  });
-  AdsServiceImpl::EdsResourceArgs args1({
-      {"locality0", CreateEndpointsForBackends(2, 3)},
-  });
-  AdsServiceImpl::EdsResourceArgs args2({
-      {"locality0", CreateEndpointsForBackends(3, 4)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args1, kNewEdsService1Name));
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args2, kNewEdsService2Name));
-  // Populate new CDS resources.
-  Cluster new_cluster1 = default_cluster_;
-  new_cluster1.set_name(kNewCluster1Name);
-  new_cluster1.mutable_eds_cluster_config()->set_service_name(
-      kNewEdsService1Name);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster1);
-  Cluster new_cluster2 = default_cluster_;
-  new_cluster2.set_name(kNewCluster2Name);
-  new_cluster2.mutable_eds_cluster_config()->set_service_name(
-      kNewEdsService2Name);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster2);
-  // Populating Route Configurations for LDS.
-  RouteConfiguration new_route_config = default_route_config_;
-  auto* route1 = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  route1->mutable_match()->set_path("/grpc.testing.EchoTest1Service/Echo1");
-  route1->mutable_route()->set_cluster(kNewCluster1Name);
-  auto* route2 = new_route_config.mutable_virtual_hosts(0)->add_routes();
-  route2->mutable_match()->set_path("/grpc.testing.EchoTest2Service/Echo2");
-  route2->mutable_route()->set_cluster(kNewCluster2Name);
-  auto* route3 = new_route_config.mutable_virtual_hosts(0)->add_routes();
-  route3->mutable_match()->set_path("/grpc.testing.EchoTest3Service/Echo3");
-  route3->mutable_route()->set_cluster(kDefaultClusterName);
-  auto* default_route = new_route_config.mutable_virtual_hosts(0)->add_routes();
-  default_route->mutable_match()->set_prefix("");
-  default_route->mutable_route()->set_cluster(kDefaultClusterName);
-  SetRouteConfiguration(0, new_route_config);
-  WaitForAllBackends(0, 2);
-  CheckRpcSendOk(kNumEchoRpcs, RpcOptions().set_wait_for_ready(true));
-  CheckRpcSendOk(kNumEcho1Rpcs, RpcOptions()
-                                    .set_rpc_service(SERVICE_ECHO1)
-                                    .set_rpc_method(METHOD_ECHO1)
-                                    .set_wait_for_ready(true));
-  CheckRpcSendOk(kNumEcho2Rpcs, RpcOptions()
-                                    .set_rpc_service(SERVICE_ECHO2)
-                                    .set_rpc_method(METHOD_ECHO2)
-                                    .set_wait_for_ready(true));
-  // Make sure RPCs all go to the correct backend.
-  for (size_t i = 0; i < 2; ++i) {
-    EXPECT_EQ(kNumEchoRpcs / 2,
-              backends_[i]->backend_service()->request_count());
-    EXPECT_EQ(0, backends_[i]->backend_service1()->request_count());
-    EXPECT_EQ(0, backends_[i]->backend_service2()->request_count());
-  }
-  EXPECT_EQ(0, backends_[2]->backend_service()->request_count());
-  EXPECT_EQ(kNumEcho1Rpcs, backends_[2]->backend_service1()->request_count());
-  EXPECT_EQ(0, backends_[2]->backend_service2()->request_count());
-  EXPECT_EQ(0, backends_[3]->backend_service()->request_count());
-  EXPECT_EQ(0, backends_[3]->backend_service1()->request_count());
-  EXPECT_EQ(kNumEcho2Rpcs, backends_[3]->backend_service2()->request_count());
-}
-
-TEST_P(LdsRdsTest, XdsRoutingPathMatchingCaseInsensitive) {
-  const char* kNewCluster1Name = "new_cluster_1";
-  const char* kNewEdsService1Name = "new_eds_service_name_1";
-  const char* kNewCluster2Name = "new_cluster_2";
-  const char* kNewEdsService2Name = "new_eds_service_name_2";
-  const size_t kNumEcho1Rpcs = 10;
-  const size_t kNumEchoRpcs = 30;
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Populate new EDS resources.
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 1)},
-  });
-  AdsServiceImpl::EdsResourceArgs args1({
-      {"locality0", CreateEndpointsForBackends(1, 2)},
-  });
-  AdsServiceImpl::EdsResourceArgs args2({
-      {"locality0", CreateEndpointsForBackends(2, 3)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args1, kNewEdsService1Name));
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args2, kNewEdsService2Name));
-  // Populate new CDS resources.
-  Cluster new_cluster1 = default_cluster_;
-  new_cluster1.set_name(kNewCluster1Name);
-  new_cluster1.mutable_eds_cluster_config()->set_service_name(
-      kNewEdsService1Name);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster1);
-  Cluster new_cluster2 = default_cluster_;
-  new_cluster2.set_name(kNewCluster2Name);
-  new_cluster2.mutable_eds_cluster_config()->set_service_name(
-      kNewEdsService2Name);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster2);
-  // Populating Route Configurations for LDS.
-  RouteConfiguration new_route_config = default_route_config_;
-  // First route will not match, since it's case-sensitive.
-  // Second route will match with same path.
-  auto* route1 = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  route1->mutable_match()->set_path("/GrPc.TeStInG.EcHoTeSt1SErViCe/EcHo1");
-  route1->mutable_route()->set_cluster(kNewCluster1Name);
-  auto* route2 = new_route_config.mutable_virtual_hosts(0)->add_routes();
-  route2->mutable_match()->set_path("/GrPc.TeStInG.EcHoTeSt1SErViCe/EcHo1");
-  route2->mutable_match()->mutable_case_sensitive()->set_value(false);
-  route2->mutable_route()->set_cluster(kNewCluster2Name);
-  auto* default_route = new_route_config.mutable_virtual_hosts(0)->add_routes();
-  default_route->mutable_match()->set_prefix("");
-  default_route->mutable_route()->set_cluster(kDefaultClusterName);
-  SetRouteConfiguration(0, new_route_config);
-  CheckRpcSendOk(kNumEchoRpcs, RpcOptions().set_wait_for_ready(true));
-  CheckRpcSendOk(kNumEcho1Rpcs, RpcOptions()
-                                    .set_rpc_service(SERVICE_ECHO1)
-                                    .set_rpc_method(METHOD_ECHO1)
-                                    .set_wait_for_ready(true));
-  // Make sure RPCs all go to the correct backend.
-  EXPECT_EQ(kNumEchoRpcs, backends_[0]->backend_service()->request_count());
-  EXPECT_EQ(0, backends_[0]->backend_service1()->request_count());
-  EXPECT_EQ(0, backends_[1]->backend_service()->request_count());
-  EXPECT_EQ(0, backends_[1]->backend_service1()->request_count());
-  EXPECT_EQ(0, backends_[2]->backend_service()->request_count());
-  EXPECT_EQ(kNumEcho1Rpcs, backends_[2]->backend_service1()->request_count());
-}
-
-TEST_P(LdsRdsTest, XdsRoutingPrefixMatching) {
-  const char* kNewCluster1Name = "new_cluster_1";
-  const char* kNewEdsService1Name = "new_eds_service_name_1";
-  const char* kNewCluster2Name = "new_cluster_2";
-  const char* kNewEdsService2Name = "new_eds_service_name_2";
-  const size_t kNumEcho1Rpcs = 10;
-  const size_t kNumEcho2Rpcs = 20;
-  const size_t kNumEchoRpcs = 30;
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Populate new EDS resources.
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 2)},
-  });
-  AdsServiceImpl::EdsResourceArgs args1({
-      {"locality0", CreateEndpointsForBackends(2, 3)},
-  });
-  AdsServiceImpl::EdsResourceArgs args2({
-      {"locality0", CreateEndpointsForBackends(3, 4)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args1, kNewEdsService1Name));
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args2, kNewEdsService2Name));
-  // Populate new CDS resources.
-  Cluster new_cluster1 = default_cluster_;
-  new_cluster1.set_name(kNewCluster1Name);
-  new_cluster1.mutable_eds_cluster_config()->set_service_name(
-      kNewEdsService1Name);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster1);
-  Cluster new_cluster2 = default_cluster_;
-  new_cluster2.set_name(kNewCluster2Name);
-  new_cluster2.mutable_eds_cluster_config()->set_service_name(
-      kNewEdsService2Name);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster2);
-  // Populating Route Configurations for LDS.
-  RouteConfiguration new_route_config = default_route_config_;
-  auto* route1 = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/");
-  route1->mutable_route()->set_cluster(kNewCluster1Name);
-  auto* route2 = new_route_config.mutable_virtual_hosts(0)->add_routes();
-  route2->mutable_match()->set_prefix("/grpc.testing.EchoTest2Service/");
-  route2->mutable_route()->set_cluster(kNewCluster2Name);
-  auto* default_route = new_route_config.mutable_virtual_hosts(0)->add_routes();
-  default_route->mutable_match()->set_prefix("");
-  default_route->mutable_route()->set_cluster(kDefaultClusterName);
-  SetRouteConfiguration(0, new_route_config);
-  WaitForAllBackends(0, 2);
-  CheckRpcSendOk(kNumEchoRpcs, RpcOptions().set_wait_for_ready(true));
-  CheckRpcSendOk(
-      kNumEcho1Rpcs,
-      RpcOptions().set_rpc_service(SERVICE_ECHO1).set_wait_for_ready(true));
-  CheckRpcSendOk(
-      kNumEcho2Rpcs,
-      RpcOptions().set_rpc_service(SERVICE_ECHO2).set_wait_for_ready(true));
-  // Make sure RPCs all go to the correct backend.
-  for (size_t i = 0; i < 2; ++i) {
-    EXPECT_EQ(kNumEchoRpcs / 2,
-              backends_[i]->backend_service()->request_count());
-    EXPECT_EQ(0, backends_[i]->backend_service1()->request_count());
-    EXPECT_EQ(0, backends_[i]->backend_service2()->request_count());
-  }
-  EXPECT_EQ(0, backends_[2]->backend_service()->request_count());
-  EXPECT_EQ(kNumEcho1Rpcs, backends_[2]->backend_service1()->request_count());
-  EXPECT_EQ(0, backends_[2]->backend_service2()->request_count());
-  EXPECT_EQ(0, backends_[3]->backend_service()->request_count());
-  EXPECT_EQ(0, backends_[3]->backend_service1()->request_count());
-  EXPECT_EQ(kNumEcho2Rpcs, backends_[3]->backend_service2()->request_count());
-}
-
-TEST_P(LdsRdsTest, XdsRoutingPrefixMatchingCaseInsensitive) {
-  const char* kNewCluster1Name = "new_cluster_1";
-  const char* kNewEdsService1Name = "new_eds_service_name_1";
-  const char* kNewCluster2Name = "new_cluster_2";
-  const char* kNewEdsService2Name = "new_eds_service_name_2";
-  const size_t kNumEcho1Rpcs = 10;
-  const size_t kNumEchoRpcs = 30;
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Populate new EDS resources.
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 1)},
-  });
-  AdsServiceImpl::EdsResourceArgs args1({
-      {"locality0", CreateEndpointsForBackends(1, 2)},
-  });
-  AdsServiceImpl::EdsResourceArgs args2({
-      {"locality0", CreateEndpointsForBackends(2, 3)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args1, kNewEdsService1Name));
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args2, kNewEdsService2Name));
-  // Populate new CDS resources.
-  Cluster new_cluster1 = default_cluster_;
-  new_cluster1.set_name(kNewCluster1Name);
-  new_cluster1.mutable_eds_cluster_config()->set_service_name(
-      kNewEdsService1Name);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster1);
-  Cluster new_cluster2 = default_cluster_;
-  new_cluster2.set_name(kNewCluster2Name);
-  new_cluster2.mutable_eds_cluster_config()->set_service_name(
-      kNewEdsService2Name);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster2);
-  // Populating Route Configurations for LDS.
-  RouteConfiguration new_route_config = default_route_config_;
-  // First route will not match, since it's case-sensitive.
-  // Second route will match with same path.
-  auto* route1 = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  route1->mutable_match()->set_prefix("/GrPc.TeStInG.EcHoTeSt1SErViCe");
-  route1->mutable_route()->set_cluster(kNewCluster1Name);
-  auto* route2 = new_route_config.mutable_virtual_hosts(0)->add_routes();
-  route2->mutable_match()->set_prefix("/GrPc.TeStInG.EcHoTeSt1SErViCe");
-  route2->mutable_match()->mutable_case_sensitive()->set_value(false);
-  route2->mutable_route()->set_cluster(kNewCluster2Name);
-  auto* default_route = new_route_config.mutable_virtual_hosts(0)->add_routes();
-  default_route->mutable_match()->set_prefix("");
-  default_route->mutable_route()->set_cluster(kDefaultClusterName);
-  SetRouteConfiguration(0, new_route_config);
-  CheckRpcSendOk(kNumEchoRpcs, RpcOptions().set_wait_for_ready(true));
-  CheckRpcSendOk(kNumEcho1Rpcs, RpcOptions()
-                                    .set_rpc_service(SERVICE_ECHO1)
-                                    .set_rpc_method(METHOD_ECHO1)
-                                    .set_wait_for_ready(true));
-  // Make sure RPCs all go to the correct backend.
-  EXPECT_EQ(kNumEchoRpcs, backends_[0]->backend_service()->request_count());
-  EXPECT_EQ(0, backends_[0]->backend_service1()->request_count());
-  EXPECT_EQ(0, backends_[1]->backend_service()->request_count());
-  EXPECT_EQ(0, backends_[1]->backend_service1()->request_count());
-  EXPECT_EQ(0, backends_[2]->backend_service()->request_count());
-  EXPECT_EQ(kNumEcho1Rpcs, backends_[2]->backend_service1()->request_count());
-}
-
-TEST_P(LdsRdsTest, XdsRoutingPathRegexMatching) {
-  const char* kNewCluster1Name = "new_cluster_1";
-  const char* kNewEdsService1Name = "new_eds_service_name_1";
-  const char* kNewCluster2Name = "new_cluster_2";
-  const char* kNewEdsService2Name = "new_eds_service_name_2";
-  const size_t kNumEcho1Rpcs = 10;
-  const size_t kNumEcho2Rpcs = 20;
-  const size_t kNumEchoRpcs = 30;
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Populate new EDS resources.
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 2)},
-  });
-  AdsServiceImpl::EdsResourceArgs args1({
-      {"locality0", CreateEndpointsForBackends(2, 3)},
-  });
-  AdsServiceImpl::EdsResourceArgs args2({
-      {"locality0", CreateEndpointsForBackends(3, 4)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args1, kNewEdsService1Name));
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args2, kNewEdsService2Name));
-  // Populate new CDS resources.
-  Cluster new_cluster1 = default_cluster_;
-  new_cluster1.set_name(kNewCluster1Name);
-  new_cluster1.mutable_eds_cluster_config()->set_service_name(
-      kNewEdsService1Name);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster1);
-  Cluster new_cluster2 = default_cluster_;
-  new_cluster2.set_name(kNewCluster2Name);
-  new_cluster2.mutable_eds_cluster_config()->set_service_name(
-      kNewEdsService2Name);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster2);
-  // Populating Route Configurations for LDS.
-  RouteConfiguration new_route_config = default_route_config_;
-  auto* route1 = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  // Will match "/grpc.testing.EchoTest1Service/"
-  route1->mutable_match()->mutable_safe_regex()->set_regex(".*1.*");
-  route1->mutable_route()->set_cluster(kNewCluster1Name);
-  auto* route2 = new_route_config.mutable_virtual_hosts(0)->add_routes();
-  // Will match "/grpc.testing.EchoTest2Service/"
-  route2->mutable_match()->mutable_safe_regex()->set_regex(".*2.*");
-  route2->mutable_route()->set_cluster(kNewCluster2Name);
-  auto* default_route = new_route_config.mutable_virtual_hosts(0)->add_routes();
-  default_route->mutable_match()->set_prefix("");
-  default_route->mutable_route()->set_cluster(kDefaultClusterName);
-  SetRouteConfiguration(0, new_route_config);
-  WaitForAllBackends(0, 2);
-  CheckRpcSendOk(kNumEchoRpcs, RpcOptions().set_wait_for_ready(true));
-  CheckRpcSendOk(
-      kNumEcho1Rpcs,
-      RpcOptions().set_rpc_service(SERVICE_ECHO1).set_wait_for_ready(true));
-  CheckRpcSendOk(
-      kNumEcho2Rpcs,
-      RpcOptions().set_rpc_service(SERVICE_ECHO2).set_wait_for_ready(true));
-  // Make sure RPCs all go to the correct backend.
-  for (size_t i = 0; i < 2; ++i) {
-    EXPECT_EQ(kNumEchoRpcs / 2,
-              backends_[i]->backend_service()->request_count());
-    EXPECT_EQ(0, backends_[i]->backend_service1()->request_count());
-    EXPECT_EQ(0, backends_[i]->backend_service2()->request_count());
-  }
-  EXPECT_EQ(0, backends_[2]->backend_service()->request_count());
-  EXPECT_EQ(kNumEcho1Rpcs, backends_[2]->backend_service1()->request_count());
-  EXPECT_EQ(0, backends_[2]->backend_service2()->request_count());
-  EXPECT_EQ(0, backends_[3]->backend_service()->request_count());
-  EXPECT_EQ(0, backends_[3]->backend_service1()->request_count());
-  EXPECT_EQ(kNumEcho2Rpcs, backends_[3]->backend_service2()->request_count());
-}
-
-TEST_P(LdsRdsTest, XdsRoutingWeightedCluster) {
-  const char* kNewCluster1Name = "new_cluster_1";
-  const char* kNewEdsService1Name = "new_eds_service_name_1";
-  const char* kNewCluster2Name = "new_cluster_2";
-  const char* kNewEdsService2Name = "new_eds_service_name_2";
-  const char* kNotUsedClusterName = "not_used_cluster";
-  const size_t kNumEchoRpcs = 10;  // RPCs that will go to a fixed backend.
-  const size_t kWeight75 = 75;
-  const size_t kWeight25 = 25;
-  const double kErrorTolerance = 0.05;
-  const double kWeight75Percent = static_cast<double>(kWeight75) / 100;
-  const double kWeight25Percent = static_cast<double>(kWeight25) / 100;
-  const size_t kNumEcho1Rpcs =
-      ComputeIdealNumRpcs(kWeight75Percent, kErrorTolerance);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Populate new EDS resources.
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 1)},
-  });
-  AdsServiceImpl::EdsResourceArgs args1({
-      {"locality0", CreateEndpointsForBackends(1, 2)},
-  });
-  AdsServiceImpl::EdsResourceArgs args2({
-      {"locality0", CreateEndpointsForBackends(2, 3)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args1, kNewEdsService1Name));
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args2, kNewEdsService2Name));
-  // Populate new CDS resources.
-  Cluster new_cluster1 = default_cluster_;
-  new_cluster1.set_name(kNewCluster1Name);
-  new_cluster1.mutable_eds_cluster_config()->set_service_name(
-      kNewEdsService1Name);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster1);
-  Cluster new_cluster2 = default_cluster_;
-  new_cluster2.set_name(kNewCluster2Name);
-  new_cluster2.mutable_eds_cluster_config()->set_service_name(
-      kNewEdsService2Name);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster2);
-  // Populating Route Configurations for LDS.
-  RouteConfiguration new_route_config = default_route_config_;
-  auto* route1 = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/");
-  auto* weighted_cluster1 =
-      route1->mutable_route()->mutable_weighted_clusters()->add_clusters();
-  weighted_cluster1->set_name(kNewCluster1Name);
-  weighted_cluster1->mutable_weight()->set_value(kWeight75);
-  auto* weighted_cluster2 =
-      route1->mutable_route()->mutable_weighted_clusters()->add_clusters();
-  weighted_cluster2->set_name(kNewCluster2Name);
-  weighted_cluster2->mutable_weight()->set_value(kWeight25);
-  // Cluster with weight 0 will not be used.
-  auto* weighted_cluster3 =
-      route1->mutable_route()->mutable_weighted_clusters()->add_clusters();
-  weighted_cluster3->set_name(kNotUsedClusterName);
-  weighted_cluster3->mutable_weight()->set_value(0);
-  route1->mutable_route()
-      ->mutable_weighted_clusters()
-      ->mutable_total_weight()
-      ->set_value(kWeight75 + kWeight25);
-  auto* default_route = new_route_config.mutable_virtual_hosts(0)->add_routes();
-  default_route->mutable_match()->set_prefix("");
-  default_route->mutable_route()->set_cluster(kDefaultClusterName);
-  SetRouteConfiguration(0, new_route_config);
-  WaitForAllBackends(0, 1);
-  WaitForAllBackends(1, 3, WaitForBackendOptions(),
-                     RpcOptions().set_rpc_service(SERVICE_ECHO1));
-  CheckRpcSendOk(kNumEchoRpcs);
-  CheckRpcSendOk(kNumEcho1Rpcs, RpcOptions().set_rpc_service(SERVICE_ECHO1));
-  // Make sure RPCs all go to the correct backend.
-  EXPECT_EQ(kNumEchoRpcs, backends_[0]->backend_service()->request_count());
-  EXPECT_EQ(0, backends_[0]->backend_service1()->request_count());
-  EXPECT_EQ(0, backends_[1]->backend_service()->request_count());
-  const int weight_75_request_count =
-      backends_[1]->backend_service1()->request_count();
-  EXPECT_EQ(0, backends_[2]->backend_service()->request_count());
-  const int weight_25_request_count =
-      backends_[2]->backend_service1()->request_count();
-  gpr_log(GPR_INFO, "target_75 received %d rpcs and target_25 received %d rpcs",
-          weight_75_request_count, weight_25_request_count);
-  EXPECT_THAT(static_cast<double>(weight_75_request_count) / kNumEcho1Rpcs,
-              ::testing::DoubleNear(kWeight75Percent, kErrorTolerance));
-  EXPECT_THAT(static_cast<double>(weight_25_request_count) / kNumEcho1Rpcs,
-              ::testing::DoubleNear(kWeight25Percent, kErrorTolerance));
-}
-
-TEST_P(LdsRdsTest, RouteActionWeightedTargetDefaultRoute) {
-  const char* kNewCluster1Name = "new_cluster_1";
-  const char* kNewEdsService1Name = "new_eds_service_name_1";
-  const char* kNewCluster2Name = "new_cluster_2";
-  const char* kNewEdsService2Name = "new_eds_service_name_2";
-  const size_t kWeight75 = 75;
-  const size_t kWeight25 = 25;
-  const double kErrorTolerance = 0.05;
-  const double kWeight75Percent = static_cast<double>(kWeight75) / 100;
-  const double kWeight25Percent = static_cast<double>(kWeight25) / 100;
-  const size_t kNumEchoRpcs =
-      ComputeIdealNumRpcs(kWeight75Percent, kErrorTolerance);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Populate new EDS resources.
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 1)},
-  });
-  AdsServiceImpl::EdsResourceArgs args1({
-      {"locality0", CreateEndpointsForBackends(1, 2)},
-  });
-  AdsServiceImpl::EdsResourceArgs args2({
-      {"locality0", CreateEndpointsForBackends(2, 3)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args1, kNewEdsService1Name));
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args2, kNewEdsService2Name));
-  // Populate new CDS resources.
-  Cluster new_cluster1 = default_cluster_;
-  new_cluster1.set_name(kNewCluster1Name);
-  new_cluster1.mutable_eds_cluster_config()->set_service_name(
-      kNewEdsService1Name);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster1);
-  Cluster new_cluster2 = default_cluster_;
-  new_cluster2.set_name(kNewCluster2Name);
-  new_cluster2.mutable_eds_cluster_config()->set_service_name(
-      kNewEdsService2Name);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster2);
-  // Populating Route Configurations for LDS.
-  RouteConfiguration new_route_config = default_route_config_;
-  auto* route1 = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  route1->mutable_match()->set_prefix("");
-  auto* weighted_cluster1 =
-      route1->mutable_route()->mutable_weighted_clusters()->add_clusters();
-  weighted_cluster1->set_name(kNewCluster1Name);
-  weighted_cluster1->mutable_weight()->set_value(kWeight75);
-  auto* weighted_cluster2 =
-      route1->mutable_route()->mutable_weighted_clusters()->add_clusters();
-  weighted_cluster2->set_name(kNewCluster2Name);
-  weighted_cluster2->mutable_weight()->set_value(kWeight25);
-  route1->mutable_route()
-      ->mutable_weighted_clusters()
-      ->mutable_total_weight()
-      ->set_value(kWeight75 + kWeight25);
-  SetRouteConfiguration(0, new_route_config);
-  WaitForAllBackends(1, 3);
-  CheckRpcSendOk(kNumEchoRpcs);
-  // Make sure RPCs all go to the correct backend.
-  EXPECT_EQ(0, backends_[0]->backend_service()->request_count());
-  const int weight_75_request_count =
-      backends_[1]->backend_service()->request_count();
-  const int weight_25_request_count =
-      backends_[2]->backend_service()->request_count();
-  gpr_log(GPR_INFO, "target_75 received %d rpcs and target_25 received %d rpcs",
-          weight_75_request_count, weight_25_request_count);
-  EXPECT_THAT(static_cast<double>(weight_75_request_count) / kNumEchoRpcs,
-              ::testing::DoubleNear(kWeight75Percent, kErrorTolerance));
-  EXPECT_THAT(static_cast<double>(weight_25_request_count) / kNumEchoRpcs,
-              ::testing::DoubleNear(kWeight25Percent, kErrorTolerance));
-}
-
-TEST_P(LdsRdsTest, XdsRoutingWeightedClusterUpdateWeights) {
-  const char* kNewCluster1Name = "new_cluster_1";
-  const char* kNewEdsService1Name = "new_eds_service_name_1";
-  const char* kNewCluster2Name = "new_cluster_2";
-  const char* kNewEdsService2Name = "new_eds_service_name_2";
-  const char* kNewCluster3Name = "new_cluster_3";
-  const char* kNewEdsService3Name = "new_eds_service_name_3";
-  const size_t kNumEchoRpcs = 10;
-  const size_t kWeight75 = 75;
-  const size_t kWeight25 = 25;
-  const size_t kWeight50 = 50;
-  const double kErrorTolerance = 0.05;
-  const double kWeight75Percent = static_cast<double>(kWeight75) / 100;
-  const double kWeight25Percent = static_cast<double>(kWeight25) / 100;
-  const double kWeight50Percent = static_cast<double>(kWeight50) / 100;
-  const size_t kNumEcho1Rpcs7525 =
-      ComputeIdealNumRpcs(kWeight75Percent, kErrorTolerance);
-  const size_t kNumEcho1Rpcs5050 =
-      ComputeIdealNumRpcs(kWeight50Percent, kErrorTolerance);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Populate new EDS resources.
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 1)},
-  });
-  AdsServiceImpl::EdsResourceArgs args1({
-      {"locality0", CreateEndpointsForBackends(1, 2)},
-  });
-  AdsServiceImpl::EdsResourceArgs args2({
-      {"locality0", CreateEndpointsForBackends(2, 3)},
-  });
-  AdsServiceImpl::EdsResourceArgs args3({
-      {"locality0", CreateEndpointsForBackends(3, 4)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args1, kNewEdsService1Name));
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args2, kNewEdsService2Name));
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args3, kNewEdsService3Name));
-  // Populate new CDS resources.
-  Cluster new_cluster1 = default_cluster_;
-  new_cluster1.set_name(kNewCluster1Name);
-  new_cluster1.mutable_eds_cluster_config()->set_service_name(
-      kNewEdsService1Name);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster1);
-  Cluster new_cluster2 = default_cluster_;
-  new_cluster2.set_name(kNewCluster2Name);
-  new_cluster2.mutable_eds_cluster_config()->set_service_name(
-      kNewEdsService2Name);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster2);
-  Cluster new_cluster3 = default_cluster_;
-  new_cluster3.set_name(kNewCluster3Name);
-  new_cluster3.mutable_eds_cluster_config()->set_service_name(
-      kNewEdsService3Name);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster3);
-  // Populating Route Configurations.
-  RouteConfiguration new_route_config = default_route_config_;
-  auto* route1 = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/");
-  auto* weighted_cluster1 =
-      route1->mutable_route()->mutable_weighted_clusters()->add_clusters();
-  weighted_cluster1->set_name(kNewCluster1Name);
-  weighted_cluster1->mutable_weight()->set_value(kWeight75);
-  auto* weighted_cluster2 =
-      route1->mutable_route()->mutable_weighted_clusters()->add_clusters();
-  weighted_cluster2->set_name(kNewCluster2Name);
-  weighted_cluster2->mutable_weight()->set_value(kWeight25);
-  route1->mutable_route()
-      ->mutable_weighted_clusters()
-      ->mutable_total_weight()
-      ->set_value(kWeight75 + kWeight25);
-  auto* default_route = new_route_config.mutable_virtual_hosts(0)->add_routes();
-  default_route->mutable_match()->set_prefix("");
-  default_route->mutable_route()->set_cluster(kDefaultClusterName);
-  SetRouteConfiguration(0, new_route_config);
-  WaitForAllBackends(0, 1);
-  WaitForAllBackends(1, 3, WaitForBackendOptions(),
-                     RpcOptions().set_rpc_service(SERVICE_ECHO1));
-  CheckRpcSendOk(kNumEchoRpcs);
-  CheckRpcSendOk(kNumEcho1Rpcs7525,
-                 RpcOptions().set_rpc_service(SERVICE_ECHO1));
-  // Make sure RPCs all go to the correct backend.
-  EXPECT_EQ(kNumEchoRpcs, backends_[0]->backend_service()->request_count());
-  EXPECT_EQ(0, backends_[0]->backend_service1()->request_count());
-  EXPECT_EQ(0, backends_[1]->backend_service()->request_count());
-  const int weight_75_request_count =
-      backends_[1]->backend_service1()->request_count();
-  EXPECT_EQ(0, backends_[1]->backend_service2()->request_count());
-  EXPECT_EQ(0, backends_[2]->backend_service()->request_count());
-  const int weight_25_request_count =
-      backends_[2]->backend_service1()->request_count();
-  EXPECT_EQ(0, backends_[3]->backend_service()->request_count());
-  EXPECT_EQ(0, backends_[3]->backend_service1()->request_count());
-  gpr_log(GPR_INFO, "target_75 received %d rpcs and target_25 received %d rpcs",
-          weight_75_request_count, weight_25_request_count);
-  EXPECT_THAT(static_cast<double>(weight_75_request_count) / kNumEcho1Rpcs7525,
-              ::testing::DoubleNear(kWeight75Percent, kErrorTolerance));
-  EXPECT_THAT(static_cast<double>(weight_25_request_count) / kNumEcho1Rpcs7525,
-              ::testing::DoubleNear(kWeight25Percent, kErrorTolerance));
-  // Change Route Configurations: same clusters different weights.
-  weighted_cluster1->mutable_weight()->set_value(kWeight50);
-  weighted_cluster2->mutable_weight()->set_value(kWeight50);
-  // Change default route to a new cluster to help to identify when new
-  // polices are seen by the client.
-  default_route->mutable_route()->set_cluster(kNewCluster3Name);
-  SetRouteConfiguration(0, new_route_config);
-  ResetBackendCounters();
-  WaitForAllBackends(3, 4);
-  CheckRpcSendOk(kNumEchoRpcs);
-  CheckRpcSendOk(kNumEcho1Rpcs5050,
-                 RpcOptions().set_rpc_service(SERVICE_ECHO1));
-  // Make sure RPCs all go to the correct backend.
-  EXPECT_EQ(0, backends_[0]->backend_service()->request_count());
-  EXPECT_EQ(0, backends_[0]->backend_service1()->request_count());
-  EXPECT_EQ(0, backends_[1]->backend_service()->request_count());
-  const int weight_50_request_count_1 =
-      backends_[1]->backend_service1()->request_count();
-  EXPECT_EQ(0, backends_[2]->backend_service()->request_count());
-  const int weight_50_request_count_2 =
-      backends_[2]->backend_service1()->request_count();
-  EXPECT_EQ(kNumEchoRpcs, backends_[3]->backend_service()->request_count());
-  EXPECT_EQ(0, backends_[3]->backend_service1()->request_count());
-  EXPECT_THAT(
-      static_cast<double>(weight_50_request_count_1) / kNumEcho1Rpcs5050,
-      ::testing::DoubleNear(kWeight50Percent, kErrorTolerance));
-  EXPECT_THAT(
-      static_cast<double>(weight_50_request_count_2) / kNumEcho1Rpcs5050,
-      ::testing::DoubleNear(kWeight50Percent, kErrorTolerance));
-}
-
-TEST_P(LdsRdsTest, XdsRoutingWeightedClusterUpdateClusters) {
-  const char* kNewCluster1Name = "new_cluster_1";
-  const char* kNewEdsService1Name = "new_eds_service_name_1";
-  const char* kNewCluster2Name = "new_cluster_2";
-  const char* kNewEdsService2Name = "new_eds_service_name_2";
-  const char* kNewCluster3Name = "new_cluster_3";
-  const char* kNewEdsService3Name = "new_eds_service_name_3";
-  const size_t kNumEchoRpcs = 10;
-  const size_t kWeight75 = 75;
-  const size_t kWeight25 = 25;
-  const size_t kWeight50 = 50;
-  const double kErrorTolerance = 0.05;
-  const double kWeight75Percent = static_cast<double>(kWeight75) / 100;
-  const double kWeight25Percent = static_cast<double>(kWeight25) / 100;
-  const double kWeight50Percent = static_cast<double>(kWeight50) / 100;
-  const size_t kNumEcho1Rpcs7525 =
-      ComputeIdealNumRpcs(kWeight75Percent, kErrorTolerance);
-  const size_t kNumEcho1Rpcs5050 =
-      ComputeIdealNumRpcs(kWeight50Percent, kErrorTolerance);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Populate new EDS resources.
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 1)},
-  });
-  AdsServiceImpl::EdsResourceArgs args1({
-      {"locality0", CreateEndpointsForBackends(1, 2)},
-  });
-  AdsServiceImpl::EdsResourceArgs args2({
-      {"locality0", CreateEndpointsForBackends(2, 3)},
-  });
-  AdsServiceImpl::EdsResourceArgs args3({
-      {"locality0", CreateEndpointsForBackends(3, 4)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args1, kNewEdsService1Name));
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args2, kNewEdsService2Name));
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args3, kNewEdsService3Name));
-  // Populate new CDS resources.
-  Cluster new_cluster1 = default_cluster_;
-  new_cluster1.set_name(kNewCluster1Name);
-  new_cluster1.mutable_eds_cluster_config()->set_service_name(
-      kNewEdsService1Name);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster1);
-  Cluster new_cluster2 = default_cluster_;
-  new_cluster2.set_name(kNewCluster2Name);
-  new_cluster2.mutable_eds_cluster_config()->set_service_name(
-      kNewEdsService2Name);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster2);
-  Cluster new_cluster3 = default_cluster_;
-  new_cluster3.set_name(kNewCluster3Name);
-  new_cluster3.mutable_eds_cluster_config()->set_service_name(
-      kNewEdsService3Name);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster3);
-  // Populating Route Configurations.
-  RouteConfiguration new_route_config = default_route_config_;
-  auto* route1 = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/");
-  auto* weighted_cluster1 =
-      route1->mutable_route()->mutable_weighted_clusters()->add_clusters();
-  weighted_cluster1->set_name(kNewCluster1Name);
-  weighted_cluster1->mutable_weight()->set_value(kWeight75);
-  auto* weighted_cluster2 =
-      route1->mutable_route()->mutable_weighted_clusters()->add_clusters();
-  weighted_cluster2->set_name(kDefaultClusterName);
-  weighted_cluster2->mutable_weight()->set_value(kWeight25);
-  route1->mutable_route()
-      ->mutable_weighted_clusters()
-      ->mutable_total_weight()
-      ->set_value(kWeight75 + kWeight25);
-  auto* default_route = new_route_config.mutable_virtual_hosts(0)->add_routes();
-  default_route->mutable_match()->set_prefix("");
-  default_route->mutable_route()->set_cluster(kDefaultClusterName);
-  SetRouteConfiguration(0, new_route_config);
-  WaitForBackend(0);
-  WaitForBackend(1, WaitForBackendOptions(),
-                 RpcOptions().set_rpc_service(SERVICE_ECHO1));
-  CheckRpcSendOk(kNumEchoRpcs);
-  CheckRpcSendOk(kNumEcho1Rpcs7525,
-                 RpcOptions().set_rpc_service(SERVICE_ECHO1));
-  // Make sure RPCs all go to the correct backend.
-  EXPECT_EQ(kNumEchoRpcs, backends_[0]->backend_service()->request_count());
-  int weight_25_request_count =
-      backends_[0]->backend_service1()->request_count();
-  EXPECT_EQ(0, backends_[1]->backend_service()->request_count());
-  int weight_75_request_count =
-      backends_[1]->backend_service1()->request_count();
-  EXPECT_EQ(0, backends_[2]->backend_service()->request_count());
-  EXPECT_EQ(0, backends_[2]->backend_service1()->request_count());
-  EXPECT_EQ(0, backends_[3]->backend_service()->request_count());
-  EXPECT_EQ(0, backends_[3]->backend_service1()->request_count());
-  gpr_log(GPR_INFO, "target_75 received %d rpcs and target_25 received %d rpcs",
-          weight_75_request_count, weight_25_request_count);
-  EXPECT_THAT(static_cast<double>(weight_75_request_count) / kNumEcho1Rpcs7525,
-              ::testing::DoubleNear(kWeight75Percent, kErrorTolerance));
-  EXPECT_THAT(static_cast<double>(weight_25_request_count) / kNumEcho1Rpcs7525,
-              ::testing::DoubleNear(kWeight25Percent, kErrorTolerance));
-  // Change Route Configurations: new set of clusters with different weights.
-  weighted_cluster1->mutable_weight()->set_value(kWeight50);
-  weighted_cluster2->set_name(kNewCluster2Name);
-  weighted_cluster2->mutable_weight()->set_value(kWeight50);
-  SetRouteConfiguration(0, new_route_config);
-  ResetBackendCounters();
-  WaitForBackend(2, WaitForBackendOptions(),
-                 RpcOptions().set_rpc_service(SERVICE_ECHO1));
-  CheckRpcSendOk(kNumEchoRpcs);
-  CheckRpcSendOk(kNumEcho1Rpcs5050,
-                 RpcOptions().set_rpc_service(SERVICE_ECHO1));
-  // Make sure RPCs all go to the correct backend.
-  EXPECT_EQ(kNumEchoRpcs, backends_[0]->backend_service()->request_count());
-  EXPECT_EQ(0, backends_[0]->backend_service1()->request_count());
-  EXPECT_EQ(0, backends_[1]->backend_service()->request_count());
-  const int weight_50_request_count_1 =
-      backends_[1]->backend_service1()->request_count();
-  EXPECT_EQ(0, backends_[2]->backend_service()->request_count());
-  const int weight_50_request_count_2 =
-      backends_[2]->backend_service1()->request_count();
-  EXPECT_EQ(0, backends_[3]->backend_service()->request_count());
-  EXPECT_EQ(0, backends_[3]->backend_service1()->request_count());
-  EXPECT_THAT(
-      static_cast<double>(weight_50_request_count_1) / kNumEcho1Rpcs5050,
-      ::testing::DoubleNear(kWeight50Percent, kErrorTolerance));
-  EXPECT_THAT(
-      static_cast<double>(weight_50_request_count_2) / kNumEcho1Rpcs5050,
-      ::testing::DoubleNear(kWeight50Percent, kErrorTolerance));
-  // Change Route Configurations.
-  weighted_cluster1->mutable_weight()->set_value(kWeight75);
-  weighted_cluster2->set_name(kNewCluster3Name);
-  weighted_cluster2->mutable_weight()->set_value(kWeight25);
-  SetRouteConfiguration(0, new_route_config);
-  ResetBackendCounters();
-  WaitForBackend(3, WaitForBackendOptions(),
-                 RpcOptions().set_rpc_service(SERVICE_ECHO1));
-  CheckRpcSendOk(kNumEchoRpcs);
-  CheckRpcSendOk(kNumEcho1Rpcs7525,
-                 RpcOptions().set_rpc_service(SERVICE_ECHO1));
-  // Make sure RPCs all go to the correct backend.
-  EXPECT_EQ(kNumEchoRpcs, backends_[0]->backend_service()->request_count());
-  EXPECT_EQ(0, backends_[0]->backend_service1()->request_count());
-  EXPECT_EQ(0, backends_[1]->backend_service()->request_count());
-  weight_75_request_count = backends_[1]->backend_service1()->request_count();
-  EXPECT_EQ(0, backends_[2]->backend_service()->request_count());
-  EXPECT_EQ(0, backends_[2]->backend_service1()->request_count());
-  EXPECT_EQ(0, backends_[3]->backend_service()->request_count());
-  weight_25_request_count = backends_[3]->backend_service1()->request_count();
-  gpr_log(GPR_INFO, "target_75 received %d rpcs and target_25 received %d rpcs",
-          weight_75_request_count, weight_25_request_count);
-  EXPECT_THAT(static_cast<double>(weight_75_request_count) / kNumEcho1Rpcs7525,
-              ::testing::DoubleNear(kWeight75Percent, kErrorTolerance));
-  EXPECT_THAT(static_cast<double>(weight_25_request_count) / kNumEcho1Rpcs7525,
-              ::testing::DoubleNear(kWeight25Percent, kErrorTolerance));
-}
-
-TEST_P(LdsRdsTest, XdsRoutingClusterUpdateClusters) {
-  const char* kNewClusterName = "new_cluster";
-  const char* kNewEdsServiceName = "new_eds_service_name";
-  const size_t kNumEchoRpcs = 5;
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Populate new EDS resources.
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 1)},
-  });
-  AdsServiceImpl::EdsResourceArgs args1({
-      {"locality0", CreateEndpointsForBackends(1, 2)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args1, kNewEdsServiceName));
-  // Populate new CDS resources.
-  Cluster new_cluster = default_cluster_;
-  new_cluster.set_name(kNewClusterName);
-  new_cluster.mutable_eds_cluster_config()->set_service_name(
-      kNewEdsServiceName);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster);
-  // Send Route Configuration.
-  RouteConfiguration new_route_config = default_route_config_;
-  SetRouteConfiguration(0, new_route_config);
-  WaitForAllBackends(0, 1);
-  CheckRpcSendOk(kNumEchoRpcs);
-  // Make sure RPCs all go to the correct backend.
-  EXPECT_EQ(kNumEchoRpcs, backends_[0]->backend_service()->request_count());
-  // Change Route Configurations: new default cluster.
-  auto* default_route =
-      new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  default_route->mutable_route()->set_cluster(kNewClusterName);
-  SetRouteConfiguration(0, new_route_config);
-  WaitForAllBackends(1, 2);
-  CheckRpcSendOk(kNumEchoRpcs);
-  // Make sure RPCs all go to the correct backend.
-  EXPECT_EQ(kNumEchoRpcs, backends_[1]->backend_service()->request_count());
-}
-
-TEST_P(LdsRdsTest, XdsRoutingClusterUpdateClustersWithPickingDelays) {
-  const char* kNewClusterName = "new_cluster";
-  const char* kNewEdsServiceName = "new_eds_service_name";
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Populate new EDS resources.
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 1)},
-  });
-  AdsServiceImpl::EdsResourceArgs args1({
-      {"locality0", CreateEndpointsForBackends(1, 2)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args1, kNewEdsServiceName));
-  // Populate new CDS resources.
-  Cluster new_cluster = default_cluster_;
-  new_cluster.set_name(kNewClusterName);
-  new_cluster.mutable_eds_cluster_config()->set_service_name(
-      kNewEdsServiceName);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster);
-  // Bring down the current backend: 0, this will delay route picking time,
-  // resulting in un-committed RPCs.
-  ShutdownBackend(0);
-  // Send a RouteConfiguration with a default route that points to
-  // backend 0.
-  RouteConfiguration new_route_config = default_route_config_;
-  SetRouteConfiguration(0, new_route_config);
-  // Send exactly one RPC with no deadline and with wait_for_ready=true.
-  // This RPC will not complete until after backend 0 is started.
-  std::thread sending_rpc([this]() {
-    CheckRpcSendOk(1, RpcOptions().set_wait_for_ready(true).set_timeout_ms(0));
-  });
-  // Send a non-wait_for_ready RPC which should fail, this will tell us
-  // that the client has received the update and attempted to connect.
-  const Status status = SendRpc(RpcOptions().set_timeout_ms(0));
-  EXPECT_FALSE(status.ok());
-  // Send a update RouteConfiguration to use backend 1.
-  auto* default_route =
-      new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  default_route->mutable_route()->set_cluster(kNewClusterName);
-  SetRouteConfiguration(0, new_route_config);
-  // Wait for RPCs to go to the new backend: 1, this ensures that the client
-  // has processed the update.
-  WaitForBackend(
-      1, WaitForBackendOptions().set_reset_counters(false).set_allow_failures(
-             true));
-  // Bring up the previous backend: 0, this will allow the delayed RPC to
-  // finally call on_call_committed upon completion.
-  StartBackend(0);
-  sending_rpc.join();
-  // Make sure RPCs go to the correct backend:
-  EXPECT_EQ(1, backends_[0]->backend_service()->request_count());
-  EXPECT_EQ(1, backends_[1]->backend_service()->request_count());
-}
-
-TEST_P(LdsRdsTest, XdsRoutingApplyXdsTimeout) {
-  const int64_t kTimeoutMillis = 500;
-  const int64_t kTimeoutNano = kTimeoutMillis * 1000000;
-  const int64_t kTimeoutGrpcTimeoutHeaderMaxSecond = 1;
-  const int64_t kTimeoutMaxStreamDurationSecond = 2;
-  const int64_t kTimeoutHttpMaxStreamDurationSecond = 3;
-  const int64_t kTimeoutApplicationSecond = 4;
-  const char* kNewCluster1Name = "new_cluster_1";
-  const char* kNewEdsService1Name = "new_eds_service_name_1";
-  const char* kNewCluster2Name = "new_cluster_2";
-  const char* kNewEdsService2Name = "new_eds_service_name_2";
-  const char* kNewCluster3Name = "new_cluster_3";
-  const char* kNewEdsService3Name = "new_eds_service_name_3";
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Populate new EDS resources.
-  AdsServiceImpl::EdsResourceArgs args(
-      {{"locality0", {MakeNonExistantEndpoint()}}});
-  AdsServiceImpl::EdsResourceArgs args1(
-      {{"locality0", {MakeNonExistantEndpoint()}}});
-  AdsServiceImpl::EdsResourceArgs args2(
-      {{"locality0", {MakeNonExistantEndpoint()}}});
-  AdsServiceImpl::EdsResourceArgs args3(
-      {{"locality0", {MakeNonExistantEndpoint()}}});
-  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args1, kNewEdsService1Name));
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args2, kNewEdsService2Name));
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args3, kNewEdsService3Name));
-  // Populate new CDS resources.
-  Cluster new_cluster1 = default_cluster_;
-  new_cluster1.set_name(kNewCluster1Name);
-  new_cluster1.mutable_eds_cluster_config()->set_service_name(
-      kNewEdsService1Name);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster1);
-  Cluster new_cluster2 = default_cluster_;
-  new_cluster2.set_name(kNewCluster2Name);
-  new_cluster2.mutable_eds_cluster_config()->set_service_name(
-      kNewEdsService2Name);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster2);
-  Cluster new_cluster3 = default_cluster_;
-  new_cluster3.set_name(kNewCluster3Name);
-  new_cluster3.mutable_eds_cluster_config()->set_service_name(
-      kNewEdsService3Name);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster3);
-  // Construct listener.
-  auto listener = default_listener_;
-  HttpConnectionManager http_connection_manager;
-  listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
-      &http_connection_manager);
-  // Set up HTTP max_stream_duration of 3.5 seconds
-  auto* duration =
-      http_connection_manager.mutable_common_http_protocol_options()
-          ->mutable_max_stream_duration();
-  duration->set_seconds(kTimeoutHttpMaxStreamDurationSecond);
-  duration->set_nanos(kTimeoutNano);
-  listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
-      http_connection_manager);
-  // Construct route config.
-  RouteConfiguration new_route_config = default_route_config_;
-  // route 1: Set max_stream_duration of 2.5 seconds, Set
-  // grpc_timeout_header_max of 1.5
-  auto* route1 = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  route1->mutable_match()->set_path("/grpc.testing.EchoTest1Service/Echo1");
-  route1->mutable_route()->set_cluster(kNewCluster1Name);
-  auto* max_stream_duration =
-      route1->mutable_route()->mutable_max_stream_duration();
-  duration = max_stream_duration->mutable_max_stream_duration();
-  duration->set_seconds(kTimeoutMaxStreamDurationSecond);
-  duration->set_nanos(kTimeoutNano);
-  duration = max_stream_duration->mutable_grpc_timeout_header_max();
-  duration->set_seconds(kTimeoutGrpcTimeoutHeaderMaxSecond);
-  duration->set_nanos(kTimeoutNano);
-  // route 2: Set max_stream_duration of 2.5 seconds
-  auto* route2 = new_route_config.mutable_virtual_hosts(0)->add_routes();
-  route2->mutable_match()->set_path("/grpc.testing.EchoTest2Service/Echo2");
-  route2->mutable_route()->set_cluster(kNewCluster2Name);
-  max_stream_duration = route2->mutable_route()->mutable_max_stream_duration();
-  duration = max_stream_duration->mutable_max_stream_duration();
-  duration->set_seconds(kTimeoutMaxStreamDurationSecond);
-  duration->set_nanos(kTimeoutNano);
-  // route 3: No timeout values in route configuration
-  auto* route3 = new_route_config.mutable_virtual_hosts(0)->add_routes();
-  route3->mutable_match()->set_path("/grpc.testing.EchoTestService/Echo");
-  route3->mutable_route()->set_cluster(kNewCluster3Name);
-  // Set listener and route config.
-  SetListenerAndRouteConfiguration(0, std::move(listener), new_route_config);
-  // Test grpc_timeout_header_max of 1.5 seconds applied
-  grpc_millis t0 = NowFromCycleCounter();
-  grpc_millis t1 =
-      t0 + kTimeoutGrpcTimeoutHeaderMaxSecond * 1000 + kTimeoutMillis;
-  grpc_millis t2 = t0 + kTimeoutMaxStreamDurationSecond * 1000 + kTimeoutMillis;
-  CheckRpcSendFailure(
-      CheckRpcSendFailureOptions()
-          .set_rpc_options(
-              RpcOptions()
-                  .set_rpc_service(SERVICE_ECHO1)
-                  .set_rpc_method(METHOD_ECHO1)
-                  .set_wait_for_ready(true)
-                  .set_timeout_ms(kTimeoutApplicationSecond * 1000))
-          .set_expected_error_code(StatusCode::DEADLINE_EXCEEDED));
-  t0 = NowFromCycleCounter();
-  EXPECT_GE(t0, t1);
-  EXPECT_LT(t0, t2);
-  // Test max_stream_duration of 2.5 seconds applied
-  t0 = NowFromCycleCounter();
-  t1 = t0 + kTimeoutMaxStreamDurationSecond * 1000 + kTimeoutMillis;
-  t2 = t0 + kTimeoutHttpMaxStreamDurationSecond * 1000 + kTimeoutMillis;
-  CheckRpcSendFailure(
-      CheckRpcSendFailureOptions()
-          .set_rpc_options(
-              RpcOptions()
-                  .set_rpc_service(SERVICE_ECHO2)
-                  .set_rpc_method(METHOD_ECHO2)
-                  .set_wait_for_ready(true)
-                  .set_timeout_ms(kTimeoutApplicationSecond * 1000))
-          .set_expected_error_code(StatusCode::DEADLINE_EXCEEDED));
-  t0 = NowFromCycleCounter();
-  EXPECT_GE(t0, t1);
-  EXPECT_LT(t0, t2);
-  // Test http_stream_duration of 3.5 seconds applied
-  t0 = NowFromCycleCounter();
-  t1 = t0 + kTimeoutHttpMaxStreamDurationSecond * 1000 + kTimeoutMillis;
-  t2 = t0 + kTimeoutApplicationSecond * 1000 + kTimeoutMillis;
-  CheckRpcSendFailure(
-      CheckRpcSendFailureOptions()
-          .set_rpc_options(RpcOptions().set_wait_for_ready(true).set_timeout_ms(
-              kTimeoutApplicationSecond * 1000))
-          .set_expected_error_code(StatusCode::DEADLINE_EXCEEDED));
-  t0 = NowFromCycleCounter();
-  EXPECT_GE(t0, t1);
-  EXPECT_LT(t0, t2);
-}
-
-TEST_P(LdsRdsTest, XdsRoutingApplyApplicationTimeoutWhenXdsTimeoutExplicit0) {
-  const int64_t kTimeoutNano = 500000000;
-  const int64_t kTimeoutMaxStreamDurationSecond = 2;
-  const int64_t kTimeoutHttpMaxStreamDurationSecond = 3;
-  const int64_t kTimeoutApplicationSecond = 4;
-  const char* kNewCluster1Name = "new_cluster_1";
-  const char* kNewEdsService1Name = "new_eds_service_name_1";
-  const char* kNewCluster2Name = "new_cluster_2";
-  const char* kNewEdsService2Name = "new_eds_service_name_2";
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Populate new EDS resources.
-  AdsServiceImpl::EdsResourceArgs args(
-      {{"locality0", {MakeNonExistantEndpoint()}}});
-  AdsServiceImpl::EdsResourceArgs args1(
-      {{"locality0", {MakeNonExistantEndpoint()}}});
-  AdsServiceImpl::EdsResourceArgs args2(
-      {{"locality0", {MakeNonExistantEndpoint()}}});
-  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args1, kNewEdsService1Name));
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args2, kNewEdsService2Name));
-  // Populate new CDS resources.
-  Cluster new_cluster1 = default_cluster_;
-  new_cluster1.set_name(kNewCluster1Name);
-  new_cluster1.mutable_eds_cluster_config()->set_service_name(
-      kNewEdsService1Name);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster1);
-  Cluster new_cluster2 = default_cluster_;
-  new_cluster2.set_name(kNewCluster2Name);
-  new_cluster2.mutable_eds_cluster_config()->set_service_name(
-      kNewEdsService2Name);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster2);
-  // Construct listener.
-  auto listener = default_listener_;
-  HttpConnectionManager http_connection_manager;
-  listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
-      &http_connection_manager);
-  // Set up HTTP max_stream_duration of 3.5 seconds
-  auto* duration =
-      http_connection_manager.mutable_common_http_protocol_options()
-          ->mutable_max_stream_duration();
-  duration->set_seconds(kTimeoutHttpMaxStreamDurationSecond);
-  duration->set_nanos(kTimeoutNano);
-  listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
-      http_connection_manager);
-  // Construct route config.
-  RouteConfiguration new_route_config = default_route_config_;
-  // route 1: Set max_stream_duration of 2.5 seconds, Set
-  // grpc_timeout_header_max of 0
-  auto* route1 = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  route1->mutable_match()->set_path("/grpc.testing.EchoTest1Service/Echo1");
-  route1->mutable_route()->set_cluster(kNewCluster1Name);
-  auto* max_stream_duration =
-      route1->mutable_route()->mutable_max_stream_duration();
-  duration = max_stream_duration->mutable_max_stream_duration();
-  duration->set_seconds(kTimeoutMaxStreamDurationSecond);
-  duration->set_nanos(kTimeoutNano);
-  duration = max_stream_duration->mutable_grpc_timeout_header_max();
-  duration->set_seconds(0);
-  duration->set_nanos(0);
-  // route 2: Set max_stream_duration to 0
-  auto* route2 = new_route_config.mutable_virtual_hosts(0)->add_routes();
-  route2->mutable_match()->set_path("/grpc.testing.EchoTest2Service/Echo2");
-  route2->mutable_route()->set_cluster(kNewCluster2Name);
-  max_stream_duration = route2->mutable_route()->mutable_max_stream_duration();
-  duration = max_stream_duration->mutable_max_stream_duration();
-  duration->set_seconds(0);
-  duration->set_nanos(0);
-  // Set listener and route config.
-  SetListenerAndRouteConfiguration(0, std::move(listener), new_route_config);
-  // Test application timeout is applied for route 1
-  auto t0 = system_clock::now();
-  CheckRpcSendFailure(
-      CheckRpcSendFailureOptions()
-          .set_rpc_options(
-              RpcOptions()
-                  .set_rpc_service(SERVICE_ECHO1)
-                  .set_rpc_method(METHOD_ECHO1)
-                  .set_wait_for_ready(true)
-                  .set_timeout_ms(kTimeoutApplicationSecond * 1000))
-          .set_expected_error_code(StatusCode::DEADLINE_EXCEEDED));
-  auto ellapsed_nano_seconds =
-      std::chrono::duration_cast<std::chrono::nanoseconds>(system_clock::now() -
-                                                           t0);
-  EXPECT_GT(ellapsed_nano_seconds.count(),
-            kTimeoutApplicationSecond * 1000000000);
-  // Test application timeout is applied for route 2
-  t0 = system_clock::now();
-  CheckRpcSendFailure(
-      CheckRpcSendFailureOptions()
-          .set_rpc_options(
-              RpcOptions()
-                  .set_rpc_service(SERVICE_ECHO2)
-                  .set_rpc_method(METHOD_ECHO2)
-                  .set_wait_for_ready(true)
-                  .set_timeout_ms(kTimeoutApplicationSecond * 1000))
-          .set_expected_error_code(StatusCode::DEADLINE_EXCEEDED));
-  ellapsed_nano_seconds = std::chrono::duration_cast<std::chrono::nanoseconds>(
-      system_clock::now() - t0);
-  EXPECT_GT(ellapsed_nano_seconds.count(),
-            kTimeoutApplicationSecond * 1000000000);
-}
-
-TEST_P(LdsRdsTest, XdsRoutingApplyApplicationTimeoutWhenHttpTimeoutExplicit0) {
-  const int64_t kTimeoutApplicationSecond = 4;
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Populate new EDS resources.
-  AdsServiceImpl::EdsResourceArgs args(
-      {{"locality0", {MakeNonExistantEndpoint()}}});
-  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
-  auto listener = default_listener_;
-  HttpConnectionManager http_connection_manager;
-  listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
-      &http_connection_manager);
-  // Set up HTTP max_stream_duration to be explicit 0
-  auto* duration =
-      http_connection_manager.mutable_common_http_protocol_options()
-          ->mutable_max_stream_duration();
-  duration->set_seconds(0);
-  duration->set_nanos(0);
-  listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
-      http_connection_manager);
-  // Set listener and route config.
-  SetListenerAndRouteConfiguration(0, std::move(listener),
-                                   default_route_config_);
-  // Test application timeout is applied for route 1
-  auto t0 = system_clock::now();
-  CheckRpcSendFailure(
-      CheckRpcSendFailureOptions()
-          .set_rpc_options(RpcOptions().set_wait_for_ready(true).set_timeout_ms(
-              kTimeoutApplicationSecond * 1000))
-          .set_expected_error_code(StatusCode::DEADLINE_EXCEEDED));
-  auto ellapsed_nano_seconds =
-      std::chrono::duration_cast<std::chrono::nanoseconds>(system_clock::now() -
-                                                           t0);
-  EXPECT_GT(ellapsed_nano_seconds.count(),
-            kTimeoutApplicationSecond * 1000000000);
-}
-
-// Test to ensure application-specified deadline won't be affected when
-// the xDS config does not specify a timeout.
-TEST_P(LdsRdsTest, XdsRoutingWithOnlyApplicationTimeout) {
-  const int64_t kTimeoutApplicationSecond = 4;
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Populate new EDS resources.
-  AdsServiceImpl::EdsResourceArgs args(
-      {{"locality0", {MakeNonExistantEndpoint()}}});
-  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
-  auto t0 = system_clock::now();
-  CheckRpcSendFailure(
-      CheckRpcSendFailureOptions()
-          .set_rpc_options(RpcOptions().set_wait_for_ready(true).set_timeout_ms(
-              kTimeoutApplicationSecond * 1000))
-          .set_expected_error_code(StatusCode::DEADLINE_EXCEEDED));
-  auto ellapsed_nano_seconds =
-      std::chrono::duration_cast<std::chrono::nanoseconds>(system_clock::now() -
-                                                           t0);
-  EXPECT_GT(ellapsed_nano_seconds.count(),
-            kTimeoutApplicationSecond * 1000000000);
-}
-
-TEST_P(LdsRdsTest, XdsRetryPolicyNumRetries) {
-  const size_t kNumRetries = 3;
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Populate new EDS resources.
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 1)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
-  // Construct route config to set retry policy.
-  RouteConfiguration new_route_config = default_route_config_;
-  auto* route1 = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  auto* retry_policy = route1->mutable_route()->mutable_retry_policy();
-  retry_policy->set_retry_on(
-      "5xx,cancelled,deadline-exceeded,internal,resource-exhausted,"
-      "unavailable");
-  retry_policy->mutable_num_retries()->set_value(kNumRetries);
-  SetRouteConfiguration(0, new_route_config);
-  // Ensure we retried the correct number of times on all supported status.
-  CheckRpcSendFailure(
-      CheckRpcSendFailureOptions()
-          .set_rpc_options(
-              RpcOptions().set_server_expected_error(StatusCode::CANCELLED))
-          .set_expected_error_code(StatusCode::CANCELLED));
-  EXPECT_EQ(kNumRetries + 1, backends_[0]->backend_service()->request_count());
-  ResetBackendCounters();
-  CheckRpcSendFailure(
-      CheckRpcSendFailureOptions()
-          .set_rpc_options(RpcOptions().set_server_expected_error(
-              StatusCode::DEADLINE_EXCEEDED))
-          .set_expected_error_code(StatusCode::DEADLINE_EXCEEDED));
-  EXPECT_EQ(kNumRetries + 1, backends_[0]->backend_service()->request_count());
-  ResetBackendCounters();
-  CheckRpcSendFailure(
-      CheckRpcSendFailureOptions()
-          .set_rpc_options(
-              RpcOptions().set_server_expected_error(StatusCode::INTERNAL))
-          .set_expected_error_code(StatusCode::INTERNAL));
-  EXPECT_EQ(kNumRetries + 1, backends_[0]->backend_service()->request_count());
-  ResetBackendCounters();
-  CheckRpcSendFailure(
-      CheckRpcSendFailureOptions()
-          .set_rpc_options(RpcOptions().set_server_expected_error(
-              StatusCode::RESOURCE_EXHAUSTED))
-          .set_expected_error_code(StatusCode::RESOURCE_EXHAUSTED));
-  EXPECT_EQ(kNumRetries + 1, backends_[0]->backend_service()->request_count());
-  ResetBackendCounters();
-  CheckRpcSendFailure(
-      CheckRpcSendFailureOptions()
-          .set_rpc_options(
-              RpcOptions().set_server_expected_error(StatusCode::UNAVAILABLE))
-          .set_expected_error_code(StatusCode::UNAVAILABLE));
-  EXPECT_EQ(kNumRetries + 1, backends_[0]->backend_service()->request_count());
-  ResetBackendCounters();
-  // Ensure we don't retry on an unsupported status.
-  CheckRpcSendFailure(
-      CheckRpcSendFailureOptions()
-          .set_rpc_options(RpcOptions().set_server_expected_error(
-              StatusCode::UNAUTHENTICATED))
-          .set_expected_error_code(StatusCode::UNAUTHENTICATED));
-  EXPECT_EQ(1, backends_[0]->backend_service()->request_count());
-}
-
-TEST_P(LdsRdsTest, XdsRetryPolicyAtVirtualHostLevel) {
-  const size_t kNumRetries = 3;
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Populate new EDS resources.
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 1)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
-  // Construct route config to set retry policy.
-  RouteConfiguration new_route_config = default_route_config_;
-  auto* retry_policy =
-      new_route_config.mutable_virtual_hosts(0)->mutable_retry_policy();
-  retry_policy->set_retry_on(
-      "cancelled,deadline-exceeded,internal,resource-exhausted,unavailable");
-  retry_policy->mutable_num_retries()->set_value(kNumRetries);
-  SetRouteConfiguration(0, new_route_config);
-  // Ensure we retried the correct number of times on a supported status.
-  CheckRpcSendFailure(
-      CheckRpcSendFailureOptions()
-          .set_rpc_options(RpcOptions().set_server_expected_error(
-              StatusCode::DEADLINE_EXCEEDED))
-          .set_expected_error_code(StatusCode::DEADLINE_EXCEEDED));
-  EXPECT_EQ(kNumRetries + 1, backends_[0]->backend_service()->request_count());
-}
-
-TEST_P(LdsRdsTest, XdsRetryPolicyLongBackOff) {
-  // Set num retries to 3, but due to longer back off, we expect only 1 retry
-  // will take place.
-  const size_t kNumRetries = 3;
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Populate new EDS resources.
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 1)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
-  // Construct route config to set retry policy.
-  RouteConfiguration new_route_config = default_route_config_;
-  auto* route1 = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  auto* retry_policy = route1->mutable_route()->mutable_retry_policy();
-  retry_policy->set_retry_on(
-      "5xx,cancelled,deadline-exceeded,internal,resource-exhausted,"
-      "unavailable");
-  retry_policy->mutable_num_retries()->set_value(kNumRetries);
-  auto base_interval =
-      retry_policy->mutable_retry_back_off()->mutable_base_interval();
-  // Set backoff to 1 second, 1/2 of rpc timeout of 2 second.
-  base_interval->set_seconds(1 * grpc_test_slowdown_factor());
-  base_interval->set_nanos(0);
-  SetRouteConfiguration(0, new_route_config);
-  // No need to set max interval and just let it be the default of 10x of base.
-  // We expect 1 retry before the RPC times out with DEADLINE_EXCEEDED.
-  CheckRpcSendFailure(
-      CheckRpcSendFailureOptions()
-          .set_rpc_options(
-              RpcOptions().set_timeout_ms(2500).set_server_expected_error(
-                  StatusCode::CANCELLED))
-          .set_expected_error_code(StatusCode::DEADLINE_EXCEEDED));
-  EXPECT_EQ(1 + 1, backends_[0]->backend_service()->request_count());
-}
-
-TEST_P(LdsRdsTest, XdsRetryPolicyMaxBackOff) {
-  // Set num retries to 3, but due to longer back off, we expect only 2 retry
-  // will take place, while the 2nd one will obey the max backoff.
-  const size_t kNumRetries = 3;
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Populate new EDS resources.
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 1)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
-  // Construct route config to set retry policy.
-  RouteConfiguration new_route_config = default_route_config_;
-  auto* route1 = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  auto* retry_policy = route1->mutable_route()->mutable_retry_policy();
-  retry_policy->set_retry_on(
-      "5xx,cancelled,deadline-exceeded,internal,resource-exhausted,"
-      "unavailable");
-  retry_policy->mutable_num_retries()->set_value(kNumRetries);
-  auto base_interval =
-      retry_policy->mutable_retry_back_off()->mutable_base_interval();
-  // Set backoff to 1 second.
-  base_interval->set_seconds(1 * grpc_test_slowdown_factor());
-  base_interval->set_nanos(0);
-  auto max_interval =
-      retry_policy->mutable_retry_back_off()->mutable_max_interval();
-  // Set max interval to be the same as base, so 2 retries will take 2 seconds
-  // and both retries will take place before the 2.5 seconds rpc timeout.
-  // Tested to ensure if max is not set, this test will be the same as
-  // XdsRetryPolicyLongBackOff and we will only see 1 retry in that case.
-  max_interval->set_seconds(1 * grpc_test_slowdown_factor());
-  max_interval->set_nanos(0);
-  SetRouteConfiguration(0, new_route_config);
-  // We expect 2 retry before the RPC times out with DEADLINE_EXCEEDED.
-  CheckRpcSendFailure(
-      CheckRpcSendFailureOptions()
-          .set_rpc_options(
-              RpcOptions().set_timeout_ms(2500).set_server_expected_error(
-                  StatusCode::CANCELLED))
-          .set_expected_error_code(StatusCode::DEADLINE_EXCEEDED));
-  EXPECT_EQ(2 + 1, backends_[0]->backend_service()->request_count());
-}
-
-TEST_P(LdsRdsTest, XdsRetryPolicyUnsupportedStatusCode) {
-  const size_t kNumRetries = 3;
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Populate new EDS resources.
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 1)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
-  // Construct route config to set retry policy.
-  RouteConfiguration new_route_config = default_route_config_;
-  auto* route1 = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  auto* retry_policy = route1->mutable_route()->mutable_retry_policy();
-  retry_policy->set_retry_on("5xx");
-  retry_policy->mutable_num_retries()->set_value(kNumRetries);
-  SetRouteConfiguration(0, new_route_config);
-  // We expect no retry.
-  CheckRpcSendFailure(
-      CheckRpcSendFailureOptions()
-          .set_rpc_options(RpcOptions().set_server_expected_error(
-              StatusCode::DEADLINE_EXCEEDED))
-          .set_expected_error_code(StatusCode::DEADLINE_EXCEEDED));
-  EXPECT_EQ(1, backends_[0]->backend_service()->request_count());
-}
-
-TEST_P(LdsRdsTest, XdsRetryPolicyInvalidNumRetriesZero) {
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Populate new EDS resources.
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 1)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
-  // Construct route config to set retry policy.
-  RouteConfiguration new_route_config = default_route_config_;
-  auto* route1 = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  auto* retry_policy = route1->mutable_route()->mutable_retry_policy();
-  retry_policy->set_retry_on("deadline-exceeded");
-  // Setting num_retries to zero is not valid.
-  retry_policy->mutable_num_retries()->set_value(0);
-  SetRouteConfiguration(0, new_route_config);
-  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
-  const auto response_state = RouteConfigurationResponseState(0);
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(
-      response_state.error_message,
-      ::testing::HasSubstr(
-          "RouteAction RetryPolicy num_retries set to invalid value 0."));
-}
-
-TEST_P(LdsRdsTest, XdsRetryPolicyRetryBackOffMissingBaseInterval) {
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Populate new EDS resources.
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 1)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
-  // Construct route config to set retry policy.
-  RouteConfiguration new_route_config = default_route_config_;
-  auto* route1 = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  auto* retry_policy = route1->mutable_route()->mutable_retry_policy();
-  retry_policy->set_retry_on("deadline-exceeded");
-  retry_policy->mutable_num_retries()->set_value(1);
-  // RetryBackoff is there but base interval is missing.
-  auto max_interval =
-      retry_policy->mutable_retry_back_off()->mutable_max_interval();
-  max_interval->set_seconds(0);
-  max_interval->set_nanos(250000000);
-  SetRouteConfiguration(0, new_route_config);
-  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
-  const auto response_state = RouteConfigurationResponseState(0);
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(
-      response_state.error_message,
-      ::testing::HasSubstr(
-          "RouteAction RetryPolicy RetryBackoff missing base interval."));
-}
-
-TEST_P(LdsRdsTest, XdsRoutingHeadersMatching) {
-  const char* kNewClusterName = "new_cluster";
-  const char* kNewEdsServiceName = "new_eds_service_name";
-  const size_t kNumEcho1Rpcs = 100;
-  const size_t kNumEchoRpcs = 5;
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Populate new EDS resources.
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 1)},
-  });
-  AdsServiceImpl::EdsResourceArgs args1({
-      {"locality0", CreateEndpointsForBackends(1, 2)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args1, kNewEdsServiceName));
-  // Populate new CDS resources.
-  Cluster new_cluster = default_cluster_;
-  new_cluster.set_name(kNewClusterName);
-  new_cluster.mutable_eds_cluster_config()->set_service_name(
-      kNewEdsServiceName);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster);
-  // Populating Route Configurations for LDS.
-  RouteConfiguration route_config = default_route_config_;
-  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/");
-  auto* header_matcher1 = route1->mutable_match()->add_headers();
-  header_matcher1->set_name("header1");
-  header_matcher1->set_exact_match("POST,PUT,GET");
-  auto* header_matcher2 = route1->mutable_match()->add_headers();
-  header_matcher2->set_name("header2");
-  header_matcher2->mutable_safe_regex_match()->set_regex("[a-z]*");
-  auto* header_matcher3 = route1->mutable_match()->add_headers();
-  header_matcher3->set_name("header3");
-  header_matcher3->mutable_range_match()->set_start(1);
-  header_matcher3->mutable_range_match()->set_end(1000);
-  auto* header_matcher4 = route1->mutable_match()->add_headers();
-  header_matcher4->set_name("header4");
-  header_matcher4->set_present_match(false);
-  auto* header_matcher5 = route1->mutable_match()->add_headers();
-  header_matcher5->set_name("header5");
-  header_matcher5->set_present_match(true);
-  auto* header_matcher6 = route1->mutable_match()->add_headers();
-  header_matcher6->set_name("header6");
-  header_matcher6->set_prefix_match("/grpc");
-  auto* header_matcher7 = route1->mutable_match()->add_headers();
-  header_matcher7->set_name("header7");
-  header_matcher7->set_suffix_match(".cc");
-  header_matcher7->set_invert_match(true);
-  route1->mutable_route()->set_cluster(kNewClusterName);
-  auto* default_route = route_config.mutable_virtual_hosts(0)->add_routes();
-  default_route->mutable_match()->set_prefix("");
-  default_route->mutable_route()->set_cluster(kDefaultClusterName);
-  SetRouteConfiguration(0, route_config);
-  std::vector<std::pair<std::string, std::string>> metadata = {
-      {"header1", "POST"},
-      {"header2", "blah"},
-      {"header3", "1"},
-      {"header5", "anything"},
-      {"header6", "/grpc.testing.EchoTest1Service/"},
-      {"header1", "PUT"},
-      {"header7", "grpc.java"},
-      {"header1", "GET"},
-  };
-  const auto header_match_rpc_options = RpcOptions()
-                                            .set_rpc_service(SERVICE_ECHO1)
-                                            .set_rpc_method(METHOD_ECHO1)
-                                            .set_metadata(std::move(metadata));
-  // Make sure all backends are up.
-  WaitForBackend(0);
-  WaitForBackend(1, WaitForBackendOptions(), header_match_rpc_options);
-  // Send RPCs.
-  CheckRpcSendOk(kNumEchoRpcs);
-  CheckRpcSendOk(kNumEcho1Rpcs, header_match_rpc_options);
-  EXPECT_EQ(kNumEchoRpcs, backends_[0]->backend_service()->request_count());
-  EXPECT_EQ(0, backends_[0]->backend_service1()->request_count());
-  EXPECT_EQ(0, backends_[0]->backend_service2()->request_count());
-  EXPECT_EQ(0, backends_[1]->backend_service()->request_count());
-  EXPECT_EQ(kNumEcho1Rpcs, backends_[1]->backend_service1()->request_count());
-  EXPECT_EQ(0, backends_[1]->backend_service2()->request_count());
-  const auto response_state = RouteConfigurationResponseState(0);
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::ACKED);
-}
-
-TEST_P(LdsRdsTest, XdsRoutingHeadersMatchingSpecialHeaderContentType) {
-  const char* kNewClusterName = "new_cluster";
-  const char* kNewEdsServiceName = "new_eds_service_name";
-  const size_t kNumEchoRpcs = 100;
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Populate new EDS resources.
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 1)},
-  });
-  AdsServiceImpl::EdsResourceArgs args1({
-      {"locality0", CreateEndpointsForBackends(1, 2)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args1, kNewEdsServiceName));
-  // Populate new CDS resources.
-  Cluster new_cluster = default_cluster_;
-  new_cluster.set_name(kNewClusterName);
-  new_cluster.mutable_eds_cluster_config()->set_service_name(
-      kNewEdsServiceName);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster);
-  // Populating Route Configurations for LDS.
-  RouteConfiguration route_config = default_route_config_;
-  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  route1->mutable_match()->set_prefix("");
-  auto* header_matcher1 = route1->mutable_match()->add_headers();
-  header_matcher1->set_name("content-type");
-  header_matcher1->set_exact_match("notapplication/grpc");
-  route1->mutable_route()->set_cluster(kNewClusterName);
-  auto* default_route = route_config.mutable_virtual_hosts(0)->add_routes();
-  default_route->mutable_match()->set_prefix("");
-  auto* header_matcher2 = default_route->mutable_match()->add_headers();
-  header_matcher2->set_name("content-type");
-  header_matcher2->set_exact_match("application/grpc");
-  default_route->mutable_route()->set_cluster(kDefaultClusterName);
-  SetRouteConfiguration(0, route_config);
-  // Make sure the backend is up.
-  WaitForAllBackends(0, 1);
-  // Send RPCs.
-  CheckRpcSendOk(kNumEchoRpcs);
-  EXPECT_EQ(kNumEchoRpcs, backends_[0]->backend_service()->request_count());
-  EXPECT_EQ(0, backends_[1]->backend_service()->request_count());
-  const auto response_state = RouteConfigurationResponseState(0);
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::ACKED);
-}
-
-TEST_P(LdsRdsTest, XdsRoutingHeadersMatchingSpecialCasesToIgnore) {
-  const char* kNewCluster1Name = "new_cluster_1";
-  const char* kNewEdsService1Name = "new_eds_service_name_1";
-  const size_t kNumEchoRpcs = 100;
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Populate new EDS resources.
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 1)},
-  });
-  AdsServiceImpl::EdsResourceArgs args1({
-      {"locality0", CreateEndpointsForBackends(1, 2)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args1, kNewEdsService1Name));
-  // Populate new CDS resources.
-  Cluster new_cluster1 = default_cluster_;
-  new_cluster1.set_name(kNewCluster1Name);
-  new_cluster1.mutable_eds_cluster_config()->set_service_name(
-      kNewEdsService1Name);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster1);
-  // Populating Route Configurations for LDS.
-  RouteConfiguration route_config = default_route_config_;
-  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  route1->mutable_match()->set_prefix("");
-  auto* header_matcher1 = route1->mutable_match()->add_headers();
-  header_matcher1->set_name("grpc-foo-bin");
-  header_matcher1->set_present_match(true);
-  route1->mutable_route()->set_cluster(kNewCluster1Name);
-  auto* default_route = route_config.mutable_virtual_hosts(0)->add_routes();
-  default_route->mutable_match()->set_prefix("");
-  default_route->mutable_route()->set_cluster(kDefaultClusterName);
-  SetRouteConfiguration(0, route_config);
-  // Send headers which will mismatch each route
-  std::vector<std::pair<std::string, std::string>> metadata = {
-      {"grpc-foo-bin", "grpc-foo-bin"},
-  };
-  WaitForAllBackends(0, 1);
-  CheckRpcSendOk(kNumEchoRpcs, RpcOptions().set_metadata(metadata));
-  // Verify that only the default backend got RPCs since all previous routes
-  // were mismatched.
-  EXPECT_EQ(kNumEchoRpcs, backends_[0]->backend_service()->request_count());
-  EXPECT_EQ(0, backends_[1]->backend_service()->request_count());
-  const auto response_state = RouteConfigurationResponseState(0);
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::ACKED);
-}
-
-TEST_P(LdsRdsTest, XdsRoutingRuntimeFractionMatching) {
-  const char* kNewClusterName = "new_cluster";
-  const char* kNewEdsServiceName = "new_eds_service_name";
-  const double kErrorTolerance = 0.05;
-  const size_t kRouteMatchNumerator = 25;
-  const double kRouteMatchPercent =
-      static_cast<double>(kRouteMatchNumerator) / 100;
-  const size_t kNumRpcs =
-      ComputeIdealNumRpcs(kRouteMatchPercent, kErrorTolerance);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Populate new EDS resources.
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 1)},
-  });
-  AdsServiceImpl::EdsResourceArgs args1({
-      {"locality0", CreateEndpointsForBackends(1, 2)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args1, kNewEdsServiceName));
-  // Populate new CDS resources.
-  Cluster new_cluster = default_cluster_;
-  new_cluster.set_name(kNewClusterName);
-  new_cluster.mutable_eds_cluster_config()->set_service_name(
-      kNewEdsServiceName);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster);
-  // Populating Route Configurations for LDS.
-  RouteConfiguration route_config = default_route_config_;
-  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  route1->mutable_match()
-      ->mutable_runtime_fraction()
-      ->mutable_default_value()
-      ->set_numerator(kRouteMatchNumerator);
-  route1->mutable_route()->set_cluster(kNewClusterName);
-  auto* default_route = route_config.mutable_virtual_hosts(0)->add_routes();
-  default_route->mutable_match()->set_prefix("");
-  default_route->mutable_route()->set_cluster(kDefaultClusterName);
-  SetRouteConfiguration(0, route_config);
-  WaitForAllBackends(0, 2);
-  CheckRpcSendOk(kNumRpcs);
-  const int default_backend_count =
-      backends_[0]->backend_service()->request_count();
-  const int matched_backend_count =
-      backends_[1]->backend_service()->request_count();
-  EXPECT_THAT(static_cast<double>(default_backend_count) / kNumRpcs,
-              ::testing::DoubleNear(1 - kRouteMatchPercent, kErrorTolerance));
-  EXPECT_THAT(static_cast<double>(matched_backend_count) / kNumRpcs,
-              ::testing::DoubleNear(kRouteMatchPercent, kErrorTolerance));
-  const auto response_state = RouteConfigurationResponseState(0);
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::ACKED);
-}
-
-TEST_P(LdsRdsTest, XdsRoutingHeadersMatchingUnmatchCases) {
-  const char* kNewCluster1Name = "new_cluster_1";
-  const char* kNewEdsService1Name = "new_eds_service_name_1";
-  const char* kNewCluster2Name = "new_cluster_2";
-  const char* kNewEdsService2Name = "new_eds_service_name_2";
-  const char* kNewCluster3Name = "new_cluster_3";
-  const char* kNewEdsService3Name = "new_eds_service_name_3";
-  const size_t kNumEcho1Rpcs = 100;
-  const size_t kNumEchoRpcs = 5;
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Populate new EDS resources.
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 1)},
-  });
-  AdsServiceImpl::EdsResourceArgs args1({
-      {"locality0", CreateEndpointsForBackends(1, 2)},
-  });
-  AdsServiceImpl::EdsResourceArgs args2({
-      {"locality0", CreateEndpointsForBackends(2, 3)},
-  });
-  AdsServiceImpl::EdsResourceArgs args3({
-      {"locality0", CreateEndpointsForBackends(3, 4)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args1, kNewEdsService1Name));
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args2, kNewEdsService2Name));
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args3, kNewEdsService3Name));
-  // Populate new CDS resources.
-  Cluster new_cluster1 = default_cluster_;
-  new_cluster1.set_name(kNewCluster1Name);
-  new_cluster1.mutable_eds_cluster_config()->set_service_name(
-      kNewEdsService1Name);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster1);
-  Cluster new_cluster2 = default_cluster_;
-  new_cluster2.set_name(kNewCluster2Name);
-  new_cluster2.mutable_eds_cluster_config()->set_service_name(
-      kNewEdsService2Name);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster2);
-  Cluster new_cluster3 = default_cluster_;
-  new_cluster3.set_name(kNewCluster3Name);
-  new_cluster3.mutable_eds_cluster_config()->set_service_name(
-      kNewEdsService3Name);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster3);
-  // Populating Route Configurations for LDS.
-  RouteConfiguration route_config = default_route_config_;
-  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/");
-  auto* header_matcher1 = route1->mutable_match()->add_headers();
-  header_matcher1->set_name("header1");
-  header_matcher1->set_exact_match("POST");
-  route1->mutable_route()->set_cluster(kNewCluster1Name);
-  auto route2 = route_config.mutable_virtual_hosts(0)->add_routes();
-  route2->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/");
-  auto* header_matcher2 = route2->mutable_match()->add_headers();
-  header_matcher2->set_name("header2");
-  header_matcher2->mutable_range_match()->set_start(1);
-  header_matcher2->mutable_range_match()->set_end(1000);
-  route2->mutable_route()->set_cluster(kNewCluster2Name);
-  auto route3 = route_config.mutable_virtual_hosts(0)->add_routes();
-  route3->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/");
-  auto* header_matcher3 = route3->mutable_match()->add_headers();
-  header_matcher3->set_name("header3");
-  header_matcher3->mutable_safe_regex_match()->set_regex("[a-z]*");
-  route3->mutable_route()->set_cluster(kNewCluster3Name);
-  auto* default_route = route_config.mutable_virtual_hosts(0)->add_routes();
-  default_route->mutable_match()->set_prefix("");
-  default_route->mutable_route()->set_cluster(kDefaultClusterName);
-  SetRouteConfiguration(0, route_config);
-  // Send headers which will mismatch each route
-  std::vector<std::pair<std::string, std::string>> metadata = {
-      {"header1", "POST"},
-      {"header2", "1000"},
-      {"header3", "123"},
-      {"header1", "GET"},
-  };
-  WaitForAllBackends(0, 1);
-  CheckRpcSendOk(kNumEchoRpcs, RpcOptions().set_metadata(metadata));
-  CheckRpcSendOk(kNumEcho1Rpcs, RpcOptions()
-                                    .set_rpc_service(SERVICE_ECHO1)
-                                    .set_rpc_method(METHOD_ECHO1)
-                                    .set_metadata(metadata));
-  // Verify that only the default backend got RPCs since all previous routes
-  // were mismatched.
-  for (size_t i = 1; i < 4; ++i) {
-    EXPECT_EQ(0, backends_[i]->backend_service()->request_count());
-    EXPECT_EQ(0, backends_[i]->backend_service1()->request_count());
-    EXPECT_EQ(0, backends_[i]->backend_service2()->request_count());
-  }
-  EXPECT_EQ(kNumEchoRpcs, backends_[0]->backend_service()->request_count());
-  EXPECT_EQ(kNumEcho1Rpcs, backends_[0]->backend_service1()->request_count());
-  EXPECT_EQ(0, backends_[0]->backend_service2()->request_count());
-  const auto response_state = RouteConfigurationResponseState(0);
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::ACKED);
-}
-
-TEST_P(LdsRdsTest, XdsRoutingChangeRoutesWithoutChangingClusters) {
-  const char* kNewClusterName = "new_cluster";
-  const char* kNewEdsServiceName = "new_eds_service_name";
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Populate new EDS resources.
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 1)},
-  });
-  AdsServiceImpl::EdsResourceArgs args1({
-      {"locality0", CreateEndpointsForBackends(1, 2)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args1, kNewEdsServiceName));
-  // Populate new CDS resources.
-  Cluster new_cluster = default_cluster_;
-  new_cluster.set_name(kNewClusterName);
-  new_cluster.mutable_eds_cluster_config()->set_service_name(
-      kNewEdsServiceName);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster);
-  // Populating Route Configurations for LDS.
-  RouteConfiguration route_config = default_route_config_;
-  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/");
-  route1->mutable_route()->set_cluster(kNewClusterName);
-  auto* default_route = route_config.mutable_virtual_hosts(0)->add_routes();
-  default_route->mutable_match()->set_prefix("");
-  default_route->mutable_route()->set_cluster(kDefaultClusterName);
-  SetRouteConfiguration(0, route_config);
-  // Make sure all backends are up and that requests for each RPC
-  // service go to the right backends.
-  WaitForBackend(0, WaitForBackendOptions().set_reset_counters(false));
-  WaitForBackend(1, WaitForBackendOptions().set_reset_counters(false),
-                 RpcOptions().set_rpc_service(SERVICE_ECHO1));
-  WaitForBackend(0, WaitForBackendOptions().set_reset_counters(false),
-                 RpcOptions().set_rpc_service(SERVICE_ECHO2));
-  // Requests for services Echo and Echo2 should have gone to backend 0.
-  EXPECT_EQ(1, backends_[0]->backend_service()->request_count());
-  EXPECT_EQ(0, backends_[0]->backend_service1()->request_count());
-  EXPECT_EQ(1, backends_[0]->backend_service2()->request_count());
-  // Requests for service Echo1 should have gone to backend 1.
-  EXPECT_EQ(0, backends_[1]->backend_service()->request_count());
-  EXPECT_EQ(1, backends_[1]->backend_service1()->request_count());
-  EXPECT_EQ(0, backends_[1]->backend_service2()->request_count());
-  // Now send an update that changes the first route to match a
-  // different RPC service, and wait for the client to make the change.
-  route1->mutable_match()->set_prefix("/grpc.testing.EchoTest2Service/");
-  SetRouteConfiguration(0, route_config);
-  WaitForBackend(1, WaitForBackendOptions(),
-                 RpcOptions().set_rpc_service(SERVICE_ECHO2));
-  // Now repeat the earlier test, making sure all traffic goes to the
-  // right place.
-  WaitForBackend(0, WaitForBackendOptions().set_reset_counters(false));
-  WaitForBackend(0, WaitForBackendOptions().set_reset_counters(false),
-                 RpcOptions().set_rpc_service(SERVICE_ECHO1));
-  WaitForBackend(1, WaitForBackendOptions().set_reset_counters(false),
-                 RpcOptions().set_rpc_service(SERVICE_ECHO2));
-  // Requests for services Echo and Echo1 should have gone to backend 0.
-  EXPECT_EQ(1, backends_[0]->backend_service()->request_count());
-  EXPECT_EQ(1, backends_[0]->backend_service1()->request_count());
-  EXPECT_EQ(0, backends_[0]->backend_service2()->request_count());
-  // Requests for service Echo2 should have gone to backend 1.
-  EXPECT_EQ(0, backends_[1]->backend_service()->request_count());
-  EXPECT_EQ(0, backends_[1]->backend_service1()->request_count());
-  EXPECT_EQ(1, backends_[1]->backend_service2()->request_count());
-}
-
-// Test that we NACK unknown filter types in VirtualHost.
-TEST_P(LdsRdsTest, RejectsUnknownHttpFilterTypeInVirtualHost) {
-  if (GetParam().use_v2()) return;  // Filters supported in v3 only.
-  RouteConfiguration route_config = default_route_config_;
-  auto* per_filter_config =
-      route_config.mutable_virtual_hosts(0)->mutable_typed_per_filter_config();
-  (*per_filter_config)["unknown"].PackFrom(Listener());
-  SetListenerAndRouteConfiguration(0, default_listener_, route_config);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
-  const auto response_state = RouteConfigurationResponseState(0);
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr("no filter registered for config type "
-                                   "envoy.config.listener.v3.Listener"));
-}
-
-// Test that we ignore optional unknown filter types in VirtualHost.
-TEST_P(LdsRdsTest, IgnoresOptionalUnknownHttpFilterTypeInVirtualHost) {
-  if (GetParam().use_v2()) return;  // Filters supported in v3 only.
-  RouteConfiguration route_config = default_route_config_;
-  auto* per_filter_config =
-      route_config.mutable_virtual_hosts(0)->mutable_typed_per_filter_config();
-  ::envoy::config::route::v3::FilterConfig filter_config;
-  filter_config.mutable_config()->PackFrom(Listener());
-  filter_config.set_is_optional(true);
-  (*per_filter_config)["unknown"].PackFrom(filter_config);
-  SetListenerAndRouteConfiguration(0, default_listener_, route_config);
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  WaitForAllBackends();
-  EXPECT_EQ(RouteConfigurationResponseState(0).state,
-            AdsServiceImpl::ResponseState::ACKED);
-}
-
-// Test that we NACK filters without configs in VirtualHost.
-TEST_P(LdsRdsTest, RejectsHttpFilterWithoutConfigInVirtualHost) {
-  if (GetParam().use_v2()) return;  // Filters supported in v3 only.
-  RouteConfiguration route_config = default_route_config_;
-  auto* per_filter_config =
-      route_config.mutable_virtual_hosts(0)->mutable_typed_per_filter_config();
-  (*per_filter_config)["unknown"];
-  SetListenerAndRouteConfiguration(0, default_listener_, route_config);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
-  const auto response_state = RouteConfigurationResponseState(0);
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr(
-                  "no filter config specified for filter name unknown"));
-}
-
-// Test that we NACK filters without configs in FilterConfig in VirtualHost.
-TEST_P(LdsRdsTest, RejectsHttpFilterWithoutConfigInFilterConfigInVirtualHost) {
-  if (GetParam().use_v2()) return;  // Filters supported in v3 only.
-  RouteConfiguration route_config = default_route_config_;
-  auto* per_filter_config =
-      route_config.mutable_virtual_hosts(0)->mutable_typed_per_filter_config();
-  (*per_filter_config)["unknown"].PackFrom(
-      ::envoy::config::route::v3::FilterConfig());
-  SetListenerAndRouteConfiguration(0, default_listener_, route_config);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
-  const auto response_state = RouteConfigurationResponseState(0);
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr(
-                  "no filter config specified for filter name unknown"));
-}
-
-// Test that we ignore optional filters without configs in VirtualHost.
-TEST_P(LdsRdsTest, IgnoresOptionalHttpFilterWithoutConfigInVirtualHost) {
-  if (GetParam().use_v2()) return;  // Filters supported in v3 only.
-  RouteConfiguration route_config = default_route_config_;
-  auto* per_filter_config =
-      route_config.mutable_virtual_hosts(0)->mutable_typed_per_filter_config();
-  ::envoy::config::route::v3::FilterConfig filter_config;
-  filter_config.set_is_optional(true);
-  (*per_filter_config)["unknown"].PackFrom(filter_config);
-  SetListenerAndRouteConfiguration(0, default_listener_, route_config);
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  WaitForAllBackends();
-  EXPECT_EQ(RouteConfigurationResponseState(0).state,
-            AdsServiceImpl::ResponseState::ACKED);
-}
-
-// Test that we NACK unparseable filter types in VirtualHost.
-TEST_P(LdsRdsTest, RejectsUnparseableHttpFilterTypeInVirtualHost) {
-  if (GetParam().use_v2()) return;  // Filters supported in v3 only.
-  RouteConfiguration route_config = default_route_config_;
-  auto* per_filter_config =
-      route_config.mutable_virtual_hosts(0)->mutable_typed_per_filter_config();
-  (*per_filter_config)["unknown"].PackFrom(
-      envoy::extensions::filters::http::router::v3::Router());
-  SetListenerAndRouteConfiguration(0, default_listener_, route_config);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
-  const auto response_state = RouteConfigurationResponseState(0);
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(
-      response_state.error_message,
-      ::testing::HasSubstr("router filter does not support config override"));
-}
-
-// Test that we NACK unknown filter types in Route.
-TEST_P(LdsRdsTest, RejectsUnknownHttpFilterTypeInRoute) {
-  if (GetParam().use_v2()) return;  // Filters supported in v3 only.
-  RouteConfiguration route_config = default_route_config_;
-  auto* per_filter_config = route_config.mutable_virtual_hosts(0)
-                                ->mutable_routes(0)
-                                ->mutable_typed_per_filter_config();
-  (*per_filter_config)["unknown"].PackFrom(Listener());
-  SetListenerAndRouteConfiguration(0, default_listener_, route_config);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
-  const auto response_state = RouteConfigurationResponseState(0);
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr("no filter registered for config type "
-                                   "envoy.config.listener.v3.Listener"));
-}
-
-// Test that we ignore optional unknown filter types in Route.
-TEST_P(LdsRdsTest, IgnoresOptionalUnknownHttpFilterTypeInRoute) {
-  if (GetParam().use_v2()) return;  // Filters supported in v3 only.
-  RouteConfiguration route_config = default_route_config_;
-  auto* per_filter_config = route_config.mutable_virtual_hosts(0)
-                                ->mutable_routes(0)
-                                ->mutable_typed_per_filter_config();
-  ::envoy::config::route::v3::FilterConfig filter_config;
-  filter_config.mutable_config()->PackFrom(Listener());
-  filter_config.set_is_optional(true);
-  (*per_filter_config)["unknown"].PackFrom(filter_config);
-  SetListenerAndRouteConfiguration(0, default_listener_, route_config);
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  WaitForAllBackends();
-  EXPECT_EQ(RouteConfigurationResponseState(0).state,
-            AdsServiceImpl::ResponseState::ACKED);
-}
-
-// Test that we NACK filters without configs in Route.
-TEST_P(LdsRdsTest, RejectsHttpFilterWithoutConfigInRoute) {
-  if (GetParam().use_v2()) return;  // Filters supported in v3 only.
-  RouteConfiguration route_config = default_route_config_;
-  auto* per_filter_config = route_config.mutable_virtual_hosts(0)
-                                ->mutable_routes(0)
-                                ->mutable_typed_per_filter_config();
-  (*per_filter_config)["unknown"];
-  SetListenerAndRouteConfiguration(0, default_listener_, route_config);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
-  const auto response_state = RouteConfigurationResponseState(0);
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr(
-                  "no filter config specified for filter name unknown"));
-}
-
-// Test that we NACK filters without configs in FilterConfig in Route.
-TEST_P(LdsRdsTest, RejectsHttpFilterWithoutConfigInFilterConfigInRoute) {
-  if (GetParam().use_v2()) return;  // Filters supported in v3 only.
-  RouteConfiguration route_config = default_route_config_;
-  auto* per_filter_config = route_config.mutable_virtual_hosts(0)
-                                ->mutable_routes(0)
-                                ->mutable_typed_per_filter_config();
-  (*per_filter_config)["unknown"].PackFrom(
-      ::envoy::config::route::v3::FilterConfig());
-  SetListenerAndRouteConfiguration(0, default_listener_, route_config);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
-  const auto response_state = RouteConfigurationResponseState(0);
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr(
-                  "no filter config specified for filter name unknown"));
-}
-
-// Test that we ignore optional filters without configs in Route.
-TEST_P(LdsRdsTest, IgnoresOptionalHttpFilterWithoutConfigInRoute) {
-  if (GetParam().use_v2()) return;  // Filters supported in v3 only.
-  RouteConfiguration route_config = default_route_config_;
-  auto* per_filter_config = route_config.mutable_virtual_hosts(0)
-                                ->mutable_routes(0)
-                                ->mutable_typed_per_filter_config();
-  ::envoy::config::route::v3::FilterConfig filter_config;
-  filter_config.set_is_optional(true);
-  (*per_filter_config)["unknown"].PackFrom(filter_config);
-  SetListenerAndRouteConfiguration(0, default_listener_, route_config);
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  WaitForAllBackends();
-  EXPECT_EQ(RouteConfigurationResponseState(0).state,
-            AdsServiceImpl::ResponseState::ACKED);
-}
-
-// Test that we NACK unparseable filter types in Route.
-TEST_P(LdsRdsTest, RejectsUnparseableHttpFilterTypeInRoute) {
-  if (GetParam().use_v2()) return;  // Filters supported in v3 only.
-  RouteConfiguration route_config = default_route_config_;
-  auto* per_filter_config = route_config.mutable_virtual_hosts(0)
-                                ->mutable_routes(0)
-                                ->mutable_typed_per_filter_config();
-  (*per_filter_config)["unknown"].PackFrom(
-      envoy::extensions::filters::http::router::v3::Router());
-  SetListenerAndRouteConfiguration(0, default_listener_, route_config);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
-  const auto response_state = RouteConfigurationResponseState(0);
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(
-      response_state.error_message,
-      ::testing::HasSubstr("router filter does not support config override"));
-}
-
-// Test that we NACK unknown filter types in ClusterWeight.
-TEST_P(LdsRdsTest, RejectsUnknownHttpFilterTypeInClusterWeight) {
-  if (GetParam().use_v2()) return;  // Filters supported in v3 only.
-  RouteConfiguration route_config = default_route_config_;
-  auto* cluster_weight = route_config.mutable_virtual_hosts(0)
-                             ->mutable_routes(0)
-                             ->mutable_route()
-                             ->mutable_weighted_clusters()
-                             ->add_clusters();
-  cluster_weight->set_name(kDefaultClusterName);
-  cluster_weight->mutable_weight()->set_value(100);
-  auto* per_filter_config = cluster_weight->mutable_typed_per_filter_config();
-  (*per_filter_config)["unknown"].PackFrom(Listener());
-  SetListenerAndRouteConfiguration(0, default_listener_, route_config);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
-  const auto response_state = RouteConfigurationResponseState(0);
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr("no filter registered for config type "
-                                   "envoy.config.listener.v3.Listener"));
-}
-
-// Test that we ignore optional unknown filter types in ClusterWeight.
-TEST_P(LdsRdsTest, IgnoresOptionalUnknownHttpFilterTypeInClusterWeight) {
-  if (GetParam().use_v2()) return;  // Filters supported in v3 only.
-  RouteConfiguration route_config = default_route_config_;
-  auto* cluster_weight = route_config.mutable_virtual_hosts(0)
-                             ->mutable_routes(0)
-                             ->mutable_route()
-                             ->mutable_weighted_clusters()
-                             ->add_clusters();
-  cluster_weight->set_name(kDefaultClusterName);
-  cluster_weight->mutable_weight()->set_value(100);
-  auto* per_filter_config = cluster_weight->mutable_typed_per_filter_config();
-  ::envoy::config::route::v3::FilterConfig filter_config;
-  filter_config.mutable_config()->PackFrom(Listener());
-  filter_config.set_is_optional(true);
-  (*per_filter_config)["unknown"].PackFrom(filter_config);
-  SetListenerAndRouteConfiguration(0, default_listener_, route_config);
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  WaitForAllBackends();
-  EXPECT_EQ(RouteConfigurationResponseState(0).state,
-            AdsServiceImpl::ResponseState::ACKED);
-}
-
-// Test that we NACK filters without configs in ClusterWeight.
-TEST_P(LdsRdsTest, RejectsHttpFilterWithoutConfigInClusterWeight) {
-  if (GetParam().use_v2()) return;  // Filters supported in v3 only.
-  RouteConfiguration route_config = default_route_config_;
-  auto* cluster_weight = route_config.mutable_virtual_hosts(0)
-                             ->mutable_routes(0)
-                             ->mutable_route()
-                             ->mutable_weighted_clusters()
-                             ->add_clusters();
-  cluster_weight->set_name(kDefaultClusterName);
-  cluster_weight->mutable_weight()->set_value(100);
-  auto* per_filter_config = cluster_weight->mutable_typed_per_filter_config();
-  (*per_filter_config)["unknown"];
-  SetListenerAndRouteConfiguration(0, default_listener_, route_config);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
-  const auto response_state = RouteConfigurationResponseState(0);
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr(
-                  "no filter config specified for filter name unknown"));
-}
-
-// Test that we NACK filters without configs in FilterConfig in ClusterWeight.
-TEST_P(LdsRdsTest,
-       RejectsHttpFilterWithoutConfigInFilterConfigInClusterWeight) {
-  if (GetParam().use_v2()) return;  // Filters supported in v3 only.
-  RouteConfiguration route_config = default_route_config_;
-  auto* cluster_weight = route_config.mutable_virtual_hosts(0)
-                             ->mutable_routes(0)
-                             ->mutable_route()
-                             ->mutable_weighted_clusters()
-                             ->add_clusters();
-  cluster_weight->set_name(kDefaultClusterName);
-  cluster_weight->mutable_weight()->set_value(100);
-  auto* per_filter_config = cluster_weight->mutable_typed_per_filter_config();
-  (*per_filter_config)["unknown"].PackFrom(
-      ::envoy::config::route::v3::FilterConfig());
-  SetListenerAndRouteConfiguration(0, default_listener_, route_config);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
-  const auto response_state = RouteConfigurationResponseState(0);
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr(
-                  "no filter config specified for filter name unknown"));
-}
-
-// Test that we ignore optional filters without configs in ClusterWeight.
-TEST_P(LdsRdsTest, IgnoresOptionalHttpFilterWithoutConfigInClusterWeight) {
-  if (GetParam().use_v2()) return;  // Filters supported in v3 only.
-  RouteConfiguration route_config = default_route_config_;
-  auto* cluster_weight = route_config.mutable_virtual_hosts(0)
-                             ->mutable_routes(0)
-                             ->mutable_route()
-                             ->mutable_weighted_clusters()
-                             ->add_clusters();
-  cluster_weight->set_name(kDefaultClusterName);
-  cluster_weight->mutable_weight()->set_value(100);
-  auto* per_filter_config = cluster_weight->mutable_typed_per_filter_config();
-  ::envoy::config::route::v3::FilterConfig filter_config;
-  filter_config.set_is_optional(true);
-  (*per_filter_config)["unknown"].PackFrom(filter_config);
-  SetListenerAndRouteConfiguration(0, default_listener_, route_config);
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  WaitForAllBackends();
-  EXPECT_EQ(RouteConfigurationResponseState(0).state,
-            AdsServiceImpl::ResponseState::ACKED);
-}
-
-// Test that we NACK unparseable filter types in ClusterWeight.
-TEST_P(LdsRdsTest, RejectsUnparseableHttpFilterTypeInClusterWeight) {
-  if (GetParam().use_v2()) return;  // Filters supported in v3 only.
-  RouteConfiguration route_config = default_route_config_;
-  auto* cluster_weight = route_config.mutable_virtual_hosts(0)
-                             ->mutable_routes(0)
-                             ->mutable_route()
-                             ->mutable_weighted_clusters()
-                             ->add_clusters();
-  cluster_weight->set_name(kDefaultClusterName);
-  cluster_weight->mutable_weight()->set_value(100);
-  auto* per_filter_config = cluster_weight->mutable_typed_per_filter_config();
-  (*per_filter_config)["unknown"].PackFrom(
-      envoy::extensions::filters::http::router::v3::Router());
-  SetListenerAndRouteConfiguration(0, default_listener_, route_config);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForRdsNack()) << "timed out waiting for NACK";
-  const auto response_state = RouteConfigurationResponseState(0);
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(
-      response_state.error_message,
-      ::testing::HasSubstr("router filter does not support config override"));
-}
-
-using CdsTest = BasicTest;
-
-// Tests that CDS client should send an ACK upon correct CDS response.
-TEST_P(CdsTest, Vanilla) {
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  (void)SendRpc();
-  EXPECT_EQ(balancers_[0]->ads_service()->cds_response_state().state,
-            AdsServiceImpl::ResponseState::ACKED);
-}
-
-TEST_P(CdsTest, LogicalDNSClusterType) {
-  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER",
-             "true");
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Create Logical DNS Cluster
-  auto cluster = default_cluster_;
-  cluster.set_type(Cluster::LOGICAL_DNS);
-  auto* address = cluster.mutable_load_assignment()
-                      ->add_endpoints()
-                      ->add_lb_endpoints()
-                      ->mutable_endpoint()
-                      ->mutable_address()
-                      ->mutable_socket_address();
-  address->set_address(kServerName);
-  address->set_port_value(443);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  // Set Logical DNS result
-  {
-    grpc_core::ExecCtx exec_ctx;
-    grpc_core::Resolver::Result result;
-    result.addresses = CreateAddressListFromPortList(GetBackendPorts(1, 2));
-    logical_dns_cluster_resolver_response_generator_->SetResponse(
-        std::move(result));
-  }
-  // Wait for traffic to go to backend 1.
-  WaitForBackend(1);
-  gpr_unsetenv(
-      "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER");
-}
-
-TEST_P(CdsTest, LogicalDNSClusterTypeMissingLoadAssignment) {
-  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER",
-             "true");
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Create Logical DNS Cluster
-  auto cluster = default_cluster_;
-  cluster.set_type(Cluster::LOGICAL_DNS);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->cds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr(
-                  "load_assignment not present for LOGICAL_DNS cluster"));
-  gpr_unsetenv(
-      "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER");
-}
-
-TEST_P(CdsTest, LogicalDNSClusterTypeMissingLocalities) {
-  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER",
-             "true");
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Create Logical DNS Cluster
-  auto cluster = default_cluster_;
-  cluster.set_type(Cluster::LOGICAL_DNS);
-  cluster.mutable_load_assignment();
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->cds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(
-      response_state.error_message,
-      ::testing::HasSubstr("load_assignment for LOGICAL_DNS cluster must have "
-                           "exactly one locality, found 0"));
-  gpr_unsetenv(
-      "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER");
-}
-
-TEST_P(CdsTest, LogicalDNSClusterTypeMultipleLocalities) {
-  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER",
-             "true");
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Create Logical DNS Cluster
-  auto cluster = default_cluster_;
-  cluster.set_type(Cluster::LOGICAL_DNS);
-  auto* load_assignment = cluster.mutable_load_assignment();
-  load_assignment->add_endpoints();
-  load_assignment->add_endpoints();
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->cds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(
-      response_state.error_message,
-      ::testing::HasSubstr("load_assignment for LOGICAL_DNS cluster must have "
-                           "exactly one locality, found 2"));
-  gpr_unsetenv(
-      "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER");
-}
-
-TEST_P(CdsTest, LogicalDNSClusterTypeMissingEndpoints) {
-  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER",
-             "true");
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Create Logical DNS Cluster
-  auto cluster = default_cluster_;
-  cluster.set_type(Cluster::LOGICAL_DNS);
-  cluster.mutable_load_assignment()->add_endpoints();
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->cds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr(
-                  "locality for LOGICAL_DNS cluster must have exactly one "
-                  "endpoint, found 0"));
-  gpr_unsetenv(
-      "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER");
-}
-
-TEST_P(CdsTest, LogicalDNSClusterTypeMultipleEndpoints) {
-  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER",
-             "true");
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Create Logical DNS Cluster
-  auto cluster = default_cluster_;
-  cluster.set_type(Cluster::LOGICAL_DNS);
-  auto* locality = cluster.mutable_load_assignment()->add_endpoints();
-  locality->add_lb_endpoints();
-  locality->add_lb_endpoints();
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->cds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr(
-                  "locality for LOGICAL_DNS cluster must have exactly one "
-                  "endpoint, found 2"));
-  gpr_unsetenv(
-      "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER");
-}
-
-TEST_P(CdsTest, LogicalDNSClusterTypeEmptyEndpoint) {
-  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER",
-             "true");
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Create Logical DNS Cluster
-  auto cluster = default_cluster_;
-  cluster.set_type(Cluster::LOGICAL_DNS);
-  cluster.mutable_load_assignment()->add_endpoints()->add_lb_endpoints();
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->cds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr("LbEndpoint endpoint field not set"));
-  gpr_unsetenv(
-      "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER");
-}
-
-TEST_P(CdsTest, LogicalDNSClusterTypeEndpointMissingAddress) {
-  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER",
-             "true");
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Create Logical DNS Cluster
-  auto cluster = default_cluster_;
-  cluster.set_type(Cluster::LOGICAL_DNS);
-  cluster.mutable_load_assignment()
-      ->add_endpoints()
-      ->add_lb_endpoints()
-      ->mutable_endpoint();
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->cds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr("Endpoint address field not set"));
-  gpr_unsetenv(
-      "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER");
-}
-
-TEST_P(CdsTest, LogicalDNSClusterTypeAddressMissingSocketAddress) {
-  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER",
-             "true");
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Create Logical DNS Cluster
-  auto cluster = default_cluster_;
-  cluster.set_type(Cluster::LOGICAL_DNS);
-  cluster.mutable_load_assignment()
-      ->add_endpoints()
-      ->add_lb_endpoints()
-      ->mutable_endpoint()
-      ->mutable_address();
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->cds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr("Address socket_address field not set"));
-  gpr_unsetenv(
-      "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER");
-}
-
-TEST_P(CdsTest, LogicalDNSClusterTypeSocketAddressHasResolverName) {
-  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER",
-             "true");
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Create Logical DNS Cluster
-  auto cluster = default_cluster_;
-  cluster.set_type(Cluster::LOGICAL_DNS);
-  cluster.mutable_load_assignment()
-      ->add_endpoints()
-      ->add_lb_endpoints()
-      ->mutable_endpoint()
-      ->mutable_address()
-      ->mutable_socket_address()
-      ->set_resolver_name("foo");
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->cds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr("LOGICAL_DNS clusters must NOT have a "
-                                   "custom resolver name set"));
-  gpr_unsetenv(
-      "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER");
-}
-
-TEST_P(CdsTest, LogicalDNSClusterTypeSocketAddressMissingAddress) {
-  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER",
-             "true");
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Create Logical DNS Cluster
-  auto cluster = default_cluster_;
-  cluster.set_type(Cluster::LOGICAL_DNS);
-  cluster.mutable_load_assignment()
-      ->add_endpoints()
-      ->add_lb_endpoints()
-      ->mutable_endpoint()
-      ->mutable_address()
-      ->mutable_socket_address();
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->cds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr("SocketAddress address field not set"));
-  gpr_unsetenv(
-      "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER");
-}
-
-TEST_P(CdsTest, LogicalDNSClusterTypeSocketAddressMissingPort) {
-  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER",
-             "true");
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Create Logical DNS Cluster
-  auto cluster = default_cluster_;
-  cluster.set_type(Cluster::LOGICAL_DNS);
-  cluster.mutable_load_assignment()
-      ->add_endpoints()
-      ->add_lb_endpoints()
-      ->mutable_endpoint()
-      ->mutable_address()
-      ->mutable_socket_address()
-      ->set_address(kServerName);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->cds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr("SocketAddress port_value field not set"));
-  gpr_unsetenv(
-      "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER");
-}
-
-TEST_P(CdsTest, AggregateClusterType) {
-  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER",
-             "true");
-  const char* kNewCluster1Name = "new_cluster_1";
-  const char* kNewEdsService1Name = "new_eds_service_name_1";
-  const char* kNewCluster2Name = "new_cluster_2";
-  const char* kNewEdsService2Name = "new_eds_service_name_2";
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Populate new EDS resources.
-  AdsServiceImpl::EdsResourceArgs args1({
-      {"locality0", CreateEndpointsForBackends(1, 2)},
-  });
-  AdsServiceImpl::EdsResourceArgs args2({
-      {"locality0", CreateEndpointsForBackends(2, 3)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args1, kNewEdsService1Name));
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args2, kNewEdsService2Name));
-  // Populate new CDS resources.
-  Cluster new_cluster1 = default_cluster_;
-  new_cluster1.set_name(kNewCluster1Name);
-  new_cluster1.mutable_eds_cluster_config()->set_service_name(
-      kNewEdsService1Name);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster1);
-  Cluster new_cluster2 = default_cluster_;
-  new_cluster2.set_name(kNewCluster2Name);
-  new_cluster2.mutable_eds_cluster_config()->set_service_name(
-      kNewEdsService2Name);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster2);
-  // Create Aggregate Cluster
-  auto cluster = default_cluster_;
-  CustomClusterType* custom_cluster = cluster.mutable_cluster_type();
-  custom_cluster->set_name("envoy.clusters.aggregate");
-  ClusterConfig cluster_config;
-  cluster_config.add_clusters(kNewCluster1Name);
-  cluster_config.add_clusters(kNewCluster2Name);
-  custom_cluster->mutable_typed_config()->PackFrom(cluster_config);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  // Wait for traffic to go to backend 1.
-  WaitForBackend(1);
-  // Shutdown backend 1 and wait for all traffic to go to backend 2.
-  ShutdownBackend(1);
-  WaitForBackend(2, WaitForBackendOptions().set_allow_failures(true));
-  EXPECT_EQ(balancers_[0]->ads_service()->cds_response_state().state,
-            AdsServiceImpl::ResponseState::ACKED);
-  // Bring backend 1 back and ensure all traffic go back to it.
-  StartBackend(1);
-  WaitForBackend(1);
-  gpr_unsetenv(
-      "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER");
-}
-
-TEST_P(CdsTest, AggregateClusterEdsToLogicalDns) {
-  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER",
-             "true");
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  const char* kNewCluster1Name = "new_cluster_1";
-  const char* kNewEdsService1Name = "new_eds_service_name_1";
-  const char* kLogicalDNSClusterName = "logical_dns_cluster";
-  // Populate new EDS resources.
-  AdsServiceImpl::EdsResourceArgs args1({
-      {"locality0", CreateEndpointsForBackends(1, 2)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args1, kNewEdsService1Name));
-  // Populate new CDS resources.
-  Cluster new_cluster1 = default_cluster_;
-  new_cluster1.set_name(kNewCluster1Name);
-  new_cluster1.mutable_eds_cluster_config()->set_service_name(
-      kNewEdsService1Name);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster1);
-  // Create Logical DNS Cluster
-  auto logical_dns_cluster = default_cluster_;
-  logical_dns_cluster.set_name(kLogicalDNSClusterName);
-  logical_dns_cluster.set_type(Cluster::LOGICAL_DNS);
-  auto* address = logical_dns_cluster.mutable_load_assignment()
-                      ->add_endpoints()
-                      ->add_lb_endpoints()
-                      ->mutable_endpoint()
-                      ->mutable_address()
-                      ->mutable_socket_address();
-  address->set_address(kServerName);
-  address->set_port_value(443);
-  balancers_[0]->ads_service()->SetCdsResource(logical_dns_cluster);
-  // Create Aggregate Cluster
-  auto cluster = default_cluster_;
-  CustomClusterType* custom_cluster = cluster.mutable_cluster_type();
-  custom_cluster->set_name("envoy.clusters.aggregate");
-  ClusterConfig cluster_config;
-  cluster_config.add_clusters(kNewCluster1Name);
-  cluster_config.add_clusters(kLogicalDNSClusterName);
-  custom_cluster->mutable_typed_config()->PackFrom(cluster_config);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  // Set Logical DNS result
-  {
-    grpc_core::ExecCtx exec_ctx;
-    grpc_core::Resolver::Result result;
-    result.addresses = CreateAddressListFromPortList(GetBackendPorts(2, 3));
-    logical_dns_cluster_resolver_response_generator_->SetResponse(
-        std::move(result));
-  }
-  // Wait for traffic to go to backend 1.
-  WaitForBackend(1);
-  // Shutdown backend 1 and wait for all traffic to go to backend 2.
-  ShutdownBackend(1);
-  WaitForBackend(2, WaitForBackendOptions().set_allow_failures(true));
-  EXPECT_EQ(balancers_[0]->ads_service()->cds_response_state().state,
-            AdsServiceImpl::ResponseState::ACKED);
-  // Bring backend 1 back and ensure all traffic go back to it.
-  StartBackend(1);
-  WaitForBackend(1);
-  gpr_unsetenv(
-      "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER");
-}
-
-TEST_P(CdsTest, AggregateClusterLogicalDnsToEds) {
-  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER",
-             "true");
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  const char* kNewCluster2Name = "new_cluster_2";
-  const char* kNewEdsService2Name = "new_eds_service_name_2";
-  const char* kLogicalDNSClusterName = "logical_dns_cluster";
-  // Populate new EDS resources.
-  AdsServiceImpl::EdsResourceArgs args2({
-      {"locality0", CreateEndpointsForBackends(2, 3)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args2, kNewEdsService2Name));
-  // Populate new CDS resources.
-  Cluster new_cluster2 = default_cluster_;
-  new_cluster2.set_name(kNewCluster2Name);
-  new_cluster2.mutable_eds_cluster_config()->set_service_name(
-      kNewEdsService2Name);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster2);
-  // Create Logical DNS Cluster
-  auto logical_dns_cluster = default_cluster_;
-  logical_dns_cluster.set_name(kLogicalDNSClusterName);
-  logical_dns_cluster.set_type(Cluster::LOGICAL_DNS);
-  auto* address = logical_dns_cluster.mutable_load_assignment()
-                      ->add_endpoints()
-                      ->add_lb_endpoints()
-                      ->mutable_endpoint()
-                      ->mutable_address()
-                      ->mutable_socket_address();
-  address->set_address(kServerName);
-  address->set_port_value(443);
-  balancers_[0]->ads_service()->SetCdsResource(logical_dns_cluster);
-  // Create Aggregate Cluster
-  auto cluster = default_cluster_;
-  CustomClusterType* custom_cluster = cluster.mutable_cluster_type();
-  custom_cluster->set_name("envoy.clusters.aggregate");
-  ClusterConfig cluster_config;
-  cluster_config.add_clusters(kLogicalDNSClusterName);
-  cluster_config.add_clusters(kNewCluster2Name);
-  custom_cluster->mutable_typed_config()->PackFrom(cluster_config);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  // Set Logical DNS result
-  {
-    grpc_core::ExecCtx exec_ctx;
-    grpc_core::Resolver::Result result;
-    result.addresses = CreateAddressListFromPortList(GetBackendPorts(1, 2));
-    logical_dns_cluster_resolver_response_generator_->SetResponse(
-        std::move(result));
-  }
-  // Wait for traffic to go to backend 1.
-  WaitForBackend(1);
-  // Shutdown backend 1 and wait for all traffic to go to backend 2.
-  ShutdownBackend(1);
-  WaitForBackend(2, WaitForBackendOptions().set_allow_failures(true));
-  EXPECT_EQ(balancers_[0]->ads_service()->cds_response_state().state,
-            AdsServiceImpl::ResponseState::ACKED);
-  // Bring backend 1 back and ensure all traffic go back to it.
-  StartBackend(1);
-  WaitForBackend(1);
-  gpr_unsetenv(
-      "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER");
-}
-
-// Test that CDS client should send a NACK if cluster type is Logical DNS but
-// the feature is not yet supported.
-TEST_P(CdsTest, LogicalDNSClusterTypeDisabled) {
-  auto cluster = default_cluster_;
-  cluster.set_type(Cluster::LOGICAL_DNS);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->cds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr("DiscoveryType is not valid."));
-}
-
-// Test that CDS client should send a NACK if cluster type is AGGREGATE but
-// the feature is not yet supported.
-TEST_P(CdsTest, AggregateClusterTypeDisabled) {
-  auto cluster = default_cluster_;
-  CustomClusterType* custom_cluster = cluster.mutable_cluster_type();
-  custom_cluster->set_name("envoy.clusters.aggregate");
-  ClusterConfig cluster_config;
-  cluster_config.add_clusters("cluster1");
-  cluster_config.add_clusters("cluster2");
-  custom_cluster->mutable_typed_config()->PackFrom(cluster_config);
-  cluster.set_type(Cluster::LOGICAL_DNS);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->cds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr("DiscoveryType is not valid."));
-}
-
-// Tests that CDS client should send a NACK if the cluster type in CDS
-// response is unsupported.
-TEST_P(CdsTest, UnsupportedClusterType) {
-  auto cluster = default_cluster_;
-  cluster.set_type(Cluster::STATIC);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->cds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr("DiscoveryType is not valid."));
-}
-
-// Tests that the NACK for multiple bad resources includes both errors.
-TEST_P(CdsTest, MultipleBadResources) {
-  constexpr char kClusterName2[] = "cluster_name_2";
-  constexpr char kClusterName3[] = "cluster_name_3";
-  // Add cluster with unsupported type.
-  auto cluster = default_cluster_;
-  cluster.set_name(kClusterName2);
-  cluster.set_type(Cluster::STATIC);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  // Add second cluster with the same error.
-  cluster.set_name(kClusterName3);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  // Change RouteConfig to point to all clusters.
-  RouteConfiguration route_config = default_route_config_;
-  route_config.mutable_virtual_hosts(0)->clear_routes();
-  // First route: default cluster, selected based on header.
-  auto* route = route_config.mutable_virtual_hosts(0)->add_routes();
-  route->mutable_match()->set_prefix("");
-  auto* header_matcher = route->mutable_match()->add_headers();
-  header_matcher->set_name("cluster");
-  header_matcher->set_exact_match(kDefaultClusterName);
-  route->mutable_route()->set_cluster(kDefaultClusterName);
-  // Second route: cluster 2, selected based on header.
-  route = route_config.mutable_virtual_hosts(0)->add_routes();
-  route->mutable_match()->set_prefix("");
-  header_matcher = route->mutable_match()->add_headers();
-  header_matcher->set_name("cluster");
-  header_matcher->set_exact_match(kClusterName2);
-  route->mutable_route()->set_cluster(kClusterName2);
-  // Third route: cluster 3, used by default.
-  route = route_config.mutable_virtual_hosts(0)->add_routes();
-  route->mutable_match()->set_prefix("");
-  route->mutable_route()->set_cluster(kClusterName3);
-  SetRouteConfiguration(0, route_config);
-  // Add EDS resource.
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 1)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
-  // Send RPC.
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->cds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(
-      response_state.error_message,
-      ::testing::ContainsRegex(absl::StrCat(kClusterName2,
-                                            ": validation error.*"
-                                            "DiscoveryType is not valid.*",
-                                            kClusterName3,
-                                            ": validation error.*"
-                                            "DiscoveryType is not valid")));
-  // RPCs for default cluster should succeed.
-  std::vector<std::pair<std::string, std::string>> metadata_default_cluster = {
-      {"cluster", kDefaultClusterName},
-  };
-  CheckRpcSendOk(
-      1, RpcOptions().set_metadata(std::move(metadata_default_cluster)));
-  // RPCs for cluster 2 should fail.
-  std::vector<std::pair<std::string, std::string>> metadata_cluster_2 = {
-      {"cluster", kClusterName2},
-  };
-  CheckRpcSendFailure(CheckRpcSendFailureOptions().set_rpc_options(
-      RpcOptions().set_metadata(std::move(metadata_cluster_2))));
-}
-
-// Tests that we don't trigger does-not-exist callbacks for a resource
-// that was previously valid but is updated to be invalid.
-TEST_P(CdsTest, InvalidClusterStillExistsIfPreviouslyCached) {
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 1)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Check that everything works.
-  CheckRpcSendOk();
-  // Now send an update changing the Cluster to be invalid.
-  auto cluster = default_cluster_;
-  cluster.set_type(Cluster::STATIC);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  // Wait for xDS server to see NACK.
-  auto deadline = absl::Now() + absl::Seconds(30);
-  do {
-    CheckRpcSendOk();
-    ASSERT_LT(absl::Now(), deadline);
-  } while (balancers_[0]->ads_service()->cds_response_state().state !=
-           AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(balancers_[0]->ads_service()->cds_response_state().error_message,
-              ::testing::ContainsRegex(absl::StrCat(
-                  kDefaultClusterName,
-                  ": validation error.*DiscoveryType is not valid")));
-  // Check one more time, just to make sure it still works after NACK.
-  CheckRpcSendOk();
-}
-
-// Tests that CDS client should send a NACK if the eds_config in CDS response
-// is other than ADS.
-TEST_P(CdsTest, WrongEdsConfig) {
-  auto cluster = default_cluster_;
-  cluster.mutable_eds_cluster_config()->mutable_eds_config()->mutable_self();
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->cds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr("EDS ConfigSource is not ADS."));
-}
-
-// Tests that CDS client should send a NACK if the lb_policy in CDS response
-// is other than ROUND_ROBIN.
-TEST_P(CdsTest, WrongLbPolicy) {
-  auto cluster = default_cluster_;
-  cluster.set_lb_policy(Cluster::LEAST_REQUEST);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->cds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr("LB policy is not supported."));
-}
-
-// Tests that CDS client should send a NACK if the lrs_server in CDS response
-// is other than SELF.
-TEST_P(CdsTest, WrongLrsServer) {
-  auto cluster = default_cluster_;
-  cluster.mutable_lrs_server()->mutable_ads();
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->cds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr("LRS ConfigSource is not self."));
-}
-
-// Tests that ring hash policy that hashes using channel id ensures all RPCs
-// to go 1 particular backend.
-TEST_P(CdsTest, RingHashChannelIdHashing) {
-  auto cluster = default_cluster_;
-  cluster.set_lb_policy(Cluster::RING_HASH);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  auto new_route_config = default_route_config_;
-  auto* route = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  auto* hash_policy = route->mutable_route()->add_hash_policy();
-  hash_policy->mutable_filter_state()->set_key("io.grpc.channel_id");
-  SetListenerAndRouteConfiguration(0, default_listener_, new_route_config);
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  SetNextResolutionForLbChannelAllBalancers();
-  CheckRpcSendOk(100);
-  bool found = false;
-  for (size_t i = 0; i < backends_.size(); ++i) {
-    if (backends_[i]->backend_service()->request_count() > 0) {
-      EXPECT_EQ(backends_[i]->backend_service()->request_count(), 100)
-          << "backend " << i;
-      EXPECT_FALSE(found) << "backend " << i;
-      found = true;
-    }
-  }
-  EXPECT_TRUE(found);
-}
-
-// Tests that ring hash policy that hashes using a header value can spread
-// RPCs across all the backends.
-TEST_P(CdsTest, RingHashHeaderHashing) {
-  auto cluster = default_cluster_;
-  cluster.set_lb_policy(Cluster::RING_HASH);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  auto new_route_config = default_route_config_;
-  auto* route = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  auto* hash_policy = route->mutable_route()->add_hash_policy();
-  hash_policy->mutable_header()->set_header_name("address_hash");
-  SetListenerAndRouteConfiguration(0, default_listener_, new_route_config);
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  SetNextResolutionForLbChannelAllBalancers();
-  // Note each type of RPC will contains a header value that will always be
-  // hashed to a specific backend as the header value matches the value used
-  // to create the entry in the ring.
-  std::vector<std::pair<std::string, std::string>> metadata = {
-      {"address_hash", CreateMetadataValueThatHashesToBackend(0)}};
-  std::vector<std::pair<std::string, std::string>> metadata1 = {
-      {"address_hash", CreateMetadataValueThatHashesToBackend(1)}};
-  std::vector<std::pair<std::string, std::string>> metadata2 = {
-      {"address_hash", CreateMetadataValueThatHashesToBackend(2)}};
-  std::vector<std::pair<std::string, std::string>> metadata3 = {
-      {"address_hash", CreateMetadataValueThatHashesToBackend(3)}};
-  const auto rpc_options = RpcOptions().set_metadata(std::move(metadata));
-  const auto rpc_options1 = RpcOptions().set_metadata(std::move(metadata1));
-  const auto rpc_options2 = RpcOptions().set_metadata(std::move(metadata2));
-  const auto rpc_options3 = RpcOptions().set_metadata(std::move(metadata3));
-  WaitForBackend(0, WaitForBackendOptions(), rpc_options);
-  WaitForBackend(1, WaitForBackendOptions(), rpc_options1);
-  WaitForBackend(2, WaitForBackendOptions(), rpc_options2);
-  WaitForBackend(3, WaitForBackendOptions(), rpc_options3);
-  CheckRpcSendOk(100, rpc_options);
-  CheckRpcSendOk(100, rpc_options1);
-  CheckRpcSendOk(100, rpc_options2);
-  CheckRpcSendOk(100, rpc_options3);
-  for (size_t i = 0; i < backends_.size(); ++i) {
-    EXPECT_EQ(100, backends_[i]->backend_service()->request_count());
-  }
-}
-
-// Tests that ring hash policy that hashes using a header value and regex
-// rewrite to aggregate RPCs to 1 backend.
-TEST_P(CdsTest, RingHashHeaderHashingWithRegexRewrite) {
-  auto cluster = default_cluster_;
-  cluster.set_lb_policy(Cluster::RING_HASH);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  auto new_route_config = default_route_config_;
-  auto* route = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  auto* hash_policy = route->mutable_route()->add_hash_policy();
-  hash_policy->mutable_header()->set_header_name("address_hash");
-  hash_policy->mutable_header()
-      ->mutable_regex_rewrite()
-      ->mutable_pattern()
-      ->set_regex("[0-9]+");
-  hash_policy->mutable_header()->mutable_regex_rewrite()->set_substitution(
-      "foo");
-  SetListenerAndRouteConfiguration(0, default_listener_, new_route_config);
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  SetNextResolutionForLbChannelAllBalancers();
-  std::vector<std::pair<std::string, std::string>> metadata = {
-      {"address_hash", CreateMetadataValueThatHashesToBackend(0)}};
-  std::vector<std::pair<std::string, std::string>> metadata1 = {
-      {"address_hash", CreateMetadataValueThatHashesToBackend(1)}};
-  std::vector<std::pair<std::string, std::string>> metadata2 = {
-      {"address_hash", CreateMetadataValueThatHashesToBackend(2)}};
-  std::vector<std::pair<std::string, std::string>> metadata3 = {
-      {"address_hash", CreateMetadataValueThatHashesToBackend(3)}};
-  const auto rpc_options = RpcOptions().set_metadata(std::move(metadata));
-  const auto rpc_options1 = RpcOptions().set_metadata(std::move(metadata1));
-  const auto rpc_options2 = RpcOptions().set_metadata(std::move(metadata2));
-  const auto rpc_options3 = RpcOptions().set_metadata(std::move(metadata3));
-  CheckRpcSendOk(100, rpc_options);
-  CheckRpcSendOk(100, rpc_options1);
-  CheckRpcSendOk(100, rpc_options2);
-  CheckRpcSendOk(100, rpc_options3);
-  bool found = false;
-  for (size_t i = 0; i < backends_.size(); ++i) {
-    if (backends_[i]->backend_service()->request_count() > 0) {
-      EXPECT_EQ(backends_[i]->backend_service()->request_count(), 400)
-          << "backend " << i;
-      EXPECT_FALSE(found) << "backend " << i;
-      found = true;
-    }
-  }
-  EXPECT_TRUE(found);
-}
-
-// Tests that ring hash policy that hashes using a random value.
-TEST_P(CdsTest, RingHashNoHashPolicy) {
-  const double kDistribution50Percent = 0.5;
-  const double kErrorTolerance = 0.05;
-  const uint32_t kRpcTimeoutMs = 10000;
-  const size_t kNumRpcs =
-      ComputeIdealNumRpcs(kDistribution50Percent, kErrorTolerance);
-  auto cluster = default_cluster_;
-  // Increasing min ring size for random distribution.
-  cluster.mutable_ring_hash_lb_config()->mutable_minimum_ring_size()->set_value(
-      100000);
-  cluster.set_lb_policy(Cluster::RING_HASH);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  AdsServiceImpl::EdsResourceArgs args(
-      {{"locality0", CreateEndpointsForBackends(0, 2)}});
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  SetNextResolutionForLbChannelAllBalancers();
-  // TODO(donnadionne): remove extended timeout after ring creation
-  // optimization.
-  WaitForAllBackends(0, 2, WaitForBackendOptions(),
-                     RpcOptions().set_timeout_ms(kRpcTimeoutMs));
-  CheckRpcSendOk(kNumRpcs);
-  const int request_count_1 = backends_[0]->backend_service()->request_count();
-  const int request_count_2 = backends_[1]->backend_service()->request_count();
-  EXPECT_THAT(static_cast<double>(request_count_1) / kNumRpcs,
-              ::testing::DoubleNear(kDistribution50Percent, kErrorTolerance));
-  EXPECT_THAT(static_cast<double>(request_count_2) / kNumRpcs,
-              ::testing::DoubleNear(kDistribution50Percent, kErrorTolerance));
-}
-
-// Test that ring hash policy evaluation will continue past the terminal
-// policy if no results are produced yet.
-TEST_P(CdsTest, RingHashContinuesPastTerminalPolicyThatDoesNotProduceResult) {
-  auto cluster = default_cluster_;
-  cluster.set_lb_policy(Cluster::RING_HASH);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  auto new_route_config = default_route_config_;
-  auto* route = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  auto* hash_policy = route->mutable_route()->add_hash_policy();
-  hash_policy->mutable_header()->set_header_name("header_not_present");
-  hash_policy->set_terminal(true);
-  auto* hash_policy2 = route->mutable_route()->add_hash_policy();
-  hash_policy2->mutable_header()->set_header_name("address_hash");
-  SetListenerAndRouteConfiguration(0, default_listener_, new_route_config);
-  AdsServiceImpl::EdsResourceArgs args(
-      {{"locality0", CreateEndpointsForBackends(0, 2)}});
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  SetNextResolutionForLbChannelAllBalancers();
-  std::vector<std::pair<std::string, std::string>> metadata = {
-      {"address_hash", CreateMetadataValueThatHashesToBackend(0)}};
-  const auto rpc_options = RpcOptions().set_metadata(std::move(metadata));
-  CheckRpcSendOk(100, rpc_options);
-  EXPECT_EQ(backends_[0]->backend_service()->request_count(), 100);
-  EXPECT_EQ(backends_[1]->backend_service()->request_count(), 0);
-}
-
-// Test random hash is used when header hashing specified a header field that
-// the RPC did not have.
-TEST_P(CdsTest, RingHashOnHeaderThatIsNotPresent) {
-  const double kDistribution50Percent = 0.5;
-  const double kErrorTolerance = 0.05;
-  const uint32_t kRpcTimeoutMs = 10000;
-  const size_t kNumRpcs =
-      ComputeIdealNumRpcs(kDistribution50Percent, kErrorTolerance);
-  auto cluster = default_cluster_;
-  // Increasing min ring size for random distribution.
-  cluster.mutable_ring_hash_lb_config()->mutable_minimum_ring_size()->set_value(
-      100000);
-  cluster.set_lb_policy(Cluster::RING_HASH);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  auto new_route_config = default_route_config_;
-  auto* route = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  auto* hash_policy = route->mutable_route()->add_hash_policy();
-  hash_policy->mutable_header()->set_header_name("header_not_present");
-  SetListenerAndRouteConfiguration(0, default_listener_, new_route_config);
-  AdsServiceImpl::EdsResourceArgs args(
-      {{"locality0", CreateEndpointsForBackends(0, 2)}});
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  SetNextResolutionForLbChannelAllBalancers();
-  std::vector<std::pair<std::string, std::string>> metadata = {
-      {"unmatched_header", absl::StrFormat("%" PRIu32, rand())},
-  };
-  const auto rpc_options = RpcOptions().set_metadata(std::move(metadata));
-  // TODO(donnadionne): remove extended timeout after ring creation
-  // optimization.
-  WaitForAllBackends(0, 2, WaitForBackendOptions(),
-                     RpcOptions().set_timeout_ms(kRpcTimeoutMs));
-  CheckRpcSendOk(kNumRpcs, rpc_options);
-  const int request_count_1 = backends_[0]->backend_service()->request_count();
-  const int request_count_2 = backends_[1]->backend_service()->request_count();
-  EXPECT_THAT(static_cast<double>(request_count_1) / kNumRpcs,
-              ::testing::DoubleNear(kDistribution50Percent, kErrorTolerance));
-  EXPECT_THAT(static_cast<double>(request_count_2) / kNumRpcs,
-              ::testing::DoubleNear(kDistribution50Percent, kErrorTolerance));
-}
-
-// Test random hash is used when only unsupported hash policies are
-// configured.
-TEST_P(CdsTest, RingHashUnsupportedHashPolicyDefaultToRandomHashing) {
-  const double kDistribution50Percent = 0.5;
-  const double kErrorTolerance = 0.05;
-  const uint32_t kRpcTimeoutMs = 10000;
-  const size_t kNumRpcs =
-      ComputeIdealNumRpcs(kDistribution50Percent, kErrorTolerance);
-  auto cluster = default_cluster_;
-  // Increasing min ring size for random distribution.
-  cluster.mutable_ring_hash_lb_config()->mutable_minimum_ring_size()->set_value(
-      100000);
-  cluster.set_lb_policy(Cluster::RING_HASH);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  auto new_route_config = default_route_config_;
-  auto* route = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  auto* hash_policy_unsupported_1 = route->mutable_route()->add_hash_policy();
-  hash_policy_unsupported_1->mutable_cookie()->set_name("cookie");
-  auto* hash_policy_unsupported_2 = route->mutable_route()->add_hash_policy();
-  hash_policy_unsupported_2->mutable_connection_properties()->set_source_ip(
-      true);
-  auto* hash_policy_unsupported_3 = route->mutable_route()->add_hash_policy();
-  hash_policy_unsupported_3->mutable_query_parameter()->set_name(
-      "query_parameter");
-  SetListenerAndRouteConfiguration(0, default_listener_, new_route_config);
-  AdsServiceImpl::EdsResourceArgs args(
-      {{"locality0", CreateEndpointsForBackends(0, 2)}});
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  SetNextResolutionForLbChannelAllBalancers();
-  // TODO(donnadionne): remove extended timeout after ring creation
-  // optimization.
-  WaitForAllBackends(0, 2, WaitForBackendOptions(),
-                     RpcOptions().set_timeout_ms(kRpcTimeoutMs));
-  CheckRpcSendOk(kNumRpcs);
-  const int request_count_1 = backends_[0]->backend_service()->request_count();
-  const int request_count_2 = backends_[1]->backend_service()->request_count();
-  EXPECT_THAT(static_cast<double>(request_count_1) / kNumRpcs,
-              ::testing::DoubleNear(kDistribution50Percent, kErrorTolerance));
-  EXPECT_THAT(static_cast<double>(request_count_2) / kNumRpcs,
-              ::testing::DoubleNear(kDistribution50Percent, kErrorTolerance));
-}
-
-// Tests that ring hash policy that hashes using a random value can spread
-// RPCs across all the backends according to locality weight.
-TEST_P(CdsTest, RingHashRandomHashingDistributionAccordingToEndpointWeight) {
-  const size_t kWeight1 = 1;
-  const size_t kWeight2 = 2;
-  const size_t kWeightTotal = kWeight1 + kWeight2;
-  const double kWeight33Percent = static_cast<double>(kWeight1) / kWeightTotal;
-  const double kWeight66Percent = static_cast<double>(kWeight2) / kWeightTotal;
-  const double kErrorTolerance = 0.05;
-  const uint32_t kRpcTimeoutMs = 10000;
-  const size_t kNumRpcs =
-      ComputeIdealNumRpcs(kWeight33Percent, kErrorTolerance);
-  auto cluster = default_cluster_;
-  // Increasing min ring size for random distribution.
-  cluster.mutable_ring_hash_lb_config()->mutable_minimum_ring_size()->set_value(
-      100000);
-  cluster.set_lb_policy(Cluster::RING_HASH);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  AdsServiceImpl::EdsResourceArgs args(
-      {{"locality0",
-        {CreateEndpoint(0, HealthStatus::UNKNOWN, 1),
-         CreateEndpoint(1, HealthStatus::UNKNOWN, 2)}}});
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  SetNextResolutionForLbChannelAllBalancers();
-  // TODO(donnadionne): remove extended timeout after ring creation
-  // optimization.
-  WaitForAllBackends(0, 2, WaitForBackendOptions(),
-                     RpcOptions().set_timeout_ms(kRpcTimeoutMs));
-  CheckRpcSendOk(kNumRpcs);
-  const int weight_33_request_count =
-      backends_[0]->backend_service()->request_count();
-  const int weight_66_request_count =
-      backends_[1]->backend_service()->request_count();
-  EXPECT_THAT(static_cast<double>(weight_33_request_count) / kNumRpcs,
-              ::testing::DoubleNear(kWeight33Percent, kErrorTolerance));
-  EXPECT_THAT(static_cast<double>(weight_66_request_count) / kNumRpcs,
-              ::testing::DoubleNear(kWeight66Percent, kErrorTolerance));
-}
-
-// Tests that ring hash policy that hashes using a random value can spread
-// RPCs across all the backends according to locality weight.
-TEST_P(CdsTest,
-       RingHashRandomHashingDistributionAccordingToLocalityAndEndpointWeight) {
-  const size_t kWeight1 = 1 * 1;
-  const size_t kWeight2 = 2 * 2;
-  const size_t kWeightTotal = kWeight1 + kWeight2;
-  const double kWeight20Percent = static_cast<double>(kWeight1) / kWeightTotal;
-  const double kWeight80Percent = static_cast<double>(kWeight2) / kWeightTotal;
-  const double kErrorTolerance = 0.05;
-  const uint32_t kRpcTimeoutMs = 10000;
-  const size_t kNumRpcs =
-      ComputeIdealNumRpcs(kWeight20Percent, kErrorTolerance);
-  auto cluster = default_cluster_;
-  // Increasing min ring size for random distribution.
-  cluster.mutable_ring_hash_lb_config()->mutable_minimum_ring_size()->set_value(
-      100000);
-  cluster.set_lb_policy(Cluster::RING_HASH);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  AdsServiceImpl::EdsResourceArgs args(
-      {{"locality0", {CreateEndpoint(0, HealthStatus::UNKNOWN, 1)}, 1},
-       {"locality1", {CreateEndpoint(1, HealthStatus::UNKNOWN, 2)}, 2}});
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  SetNextResolutionForLbChannelAllBalancers();
-  // TODO(donnadionne): remove extended timeout after ring creation
-  // optimization.
-  WaitForAllBackends(0, 2, WaitForBackendOptions(),
-                     RpcOptions().set_timeout_ms(kRpcTimeoutMs));
-  CheckRpcSendOk(kNumRpcs);
-  const int weight_20_request_count =
-      backends_[0]->backend_service()->request_count();
-  const int weight_80_request_count =
-      backends_[1]->backend_service()->request_count();
-  EXPECT_THAT(static_cast<double>(weight_20_request_count) / kNumRpcs,
-              ::testing::DoubleNear(kWeight20Percent, kErrorTolerance));
-  EXPECT_THAT(static_cast<double>(weight_80_request_count) / kNumRpcs,
-              ::testing::DoubleNear(kWeight80Percent, kErrorTolerance));
-}
-
-// Tests round robin is not implacted by the endpoint weight, and that the
-// localities in a locality map are picked according to their weights.
-TEST_P(CdsTest, RingHashEndpointWeightDoesNotImpactWeightedRoundRobin) {
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  const int kLocalityWeight0 = 2;
-  const int kLocalityWeight1 = 8;
-  const int kTotalLocalityWeight = kLocalityWeight0 + kLocalityWeight1;
-  const double kLocalityWeightRate0 =
-      static_cast<double>(kLocalityWeight0) / kTotalLocalityWeight;
-  const double kLocalityWeightRate1 =
-      static_cast<double>(kLocalityWeight1) / kTotalLocalityWeight;
-  const double kErrorTolerance = 0.05;
-  const size_t kNumRpcs =
-      ComputeIdealNumRpcs(kLocalityWeightRate0, kErrorTolerance);
-  // ADS response contains 2 localities, each of which contains 1 backend.
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0",
-       {CreateEndpoint(0, HealthStatus::UNKNOWN, 8)},
-       kLocalityWeight0},
-      {"locality1",
-       {CreateEndpoint(1, HealthStatus::UNKNOWN, 2)},
-       kLocalityWeight1},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  // Wait for both backends to be ready.
-  WaitForAllBackends(0, 2);
-  // Send kNumRpcs RPCs.
-  CheckRpcSendOk(kNumRpcs);
-  // The locality picking rates should be roughly equal to the expectation.
-  const double locality_picked_rate_0 =
-      static_cast<double>(backends_[0]->backend_service()->request_count()) /
-      kNumRpcs;
-  const double locality_picked_rate_1 =
-      static_cast<double>(backends_[1]->backend_service()->request_count()) /
-      kNumRpcs;
-  EXPECT_THAT(locality_picked_rate_0,
-              ::testing::DoubleNear(kLocalityWeightRate0, kErrorTolerance));
-  EXPECT_THAT(locality_picked_rate_1,
-              ::testing::DoubleNear(kLocalityWeightRate1, kErrorTolerance));
-}
-
-// Tests that ring hash policy that hashes using a fixed string ensures all
-// RPCs to go 1 particular backend; and that subsequent hashing policies are
-// ignored due to the setting of terminal.
-TEST_P(CdsTest, RingHashFixedHashingTerminalPolicy) {
-  auto cluster = default_cluster_;
-  cluster.set_lb_policy(Cluster::RING_HASH);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  auto new_route_config = default_route_config_;
-  auto* route = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  auto* hash_policy = route->mutable_route()->add_hash_policy();
-  hash_policy->mutable_header()->set_header_name("fixed_string");
-  hash_policy->set_terminal(true);
-  auto* hash_policy_to_be_ignored = route->mutable_route()->add_hash_policy();
-  hash_policy_to_be_ignored->mutable_header()->set_header_name("random_string");
-  SetListenerAndRouteConfiguration(0, default_listener_, new_route_config);
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  SetNextResolutionForLbChannelAllBalancers();
-  std::vector<std::pair<std::string, std::string>> metadata = {
-      {"fixed_string", "fixed_value"},
-      {"random_string", absl::StrFormat("%" PRIu32, rand())},
-  };
-  const auto rpc_options = RpcOptions().set_metadata(std::move(metadata));
-  CheckRpcSendOk(100, rpc_options);
-  bool found = false;
-  for (size_t i = 0; i < backends_.size(); ++i) {
-    if (backends_[i]->backend_service()->request_count() > 0) {
-      EXPECT_EQ(backends_[i]->backend_service()->request_count(), 100)
-          << "backend " << i;
-      EXPECT_FALSE(found) << "backend " << i;
-      found = true;
-    }
-  }
-  EXPECT_TRUE(found);
-}
-
-// Test that the channel will go from idle to ready via connecting;
-// (tho it is not possible to catch the connecting state before moving to
-// ready)
-TEST_P(CdsTest, RingHashIdleToReady) {
-  auto cluster = default_cluster_;
-  cluster.set_lb_policy(Cluster::RING_HASH);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  auto new_route_config = default_route_config_;
-  auto* route = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  auto* hash_policy = route->mutable_route()->add_hash_policy();
-  hash_policy->mutable_filter_state()->set_key("io.grpc.channel_id");
-  SetListenerAndRouteConfiguration(0, default_listener_, new_route_config);
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  SetNextResolutionForLbChannelAllBalancers();
-  EXPECT_EQ(GRPC_CHANNEL_IDLE, channel_->GetState(false));
-  CheckRpcSendOk();
-  EXPECT_EQ(GRPC_CHANNEL_READY, channel_->GetState(false));
-}
-
-// Test that when the first pick is down leading to a transient failure, we
-// will move on to the next ring hash entry.
-TEST_P(CdsTest, RingHashTransientFailureCheckNextOne) {
-  auto cluster = default_cluster_;
-  cluster.set_lb_policy(Cluster::RING_HASH);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  auto new_route_config = default_route_config_;
-  auto* route = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  auto* hash_policy = route->mutable_route()->add_hash_policy();
-  hash_policy->mutable_header()->set_header_name("address_hash");
-  SetListenerAndRouteConfiguration(0, default_listener_, new_route_config);
-  std::vector<AdsServiceImpl::EdsResourceArgs::Endpoint> endpoints;
-  const int unused_port = grpc_pick_unused_port_or_die();
-  endpoints.emplace_back(unused_port);
-  endpoints.emplace_back(backends_[1]->port());
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", std::move(endpoints)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  SetNextResolutionForLbChannelAllBalancers();
-  std::vector<std::pair<std::string, std::string>> metadata = {
-      {"address_hash",
-       CreateMetadataValueThatHashesToBackendPort(unused_port)}};
-  const auto rpc_options = RpcOptions().set_metadata(std::move(metadata));
-  WaitForBackend(1, WaitForBackendOptions(), rpc_options);
-  CheckRpcSendOk(100, rpc_options);
-  EXPECT_EQ(0, backends_[0]->backend_service()->request_count());
-  EXPECT_EQ(100, backends_[1]->backend_service()->request_count());
-}
-
-// Test that when a backend goes down, we will move on to the next subchannel
-// (with a lower priority).  When the backend comes back up, traffic will move
-// back.
-TEST_P(CdsTest, RingHashSwitchToLowerPrioirtyAndThenBack) {
-  auto cluster = default_cluster_;
-  cluster.set_lb_policy(Cluster::RING_HASH);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  auto new_route_config = default_route_config_;
-  auto* route = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  auto* hash_policy = route->mutable_route()->add_hash_policy();
-  hash_policy->mutable_header()->set_header_name("address_hash");
-  SetListenerAndRouteConfiguration(0, default_listener_, new_route_config);
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 1), kDefaultLocalityWeight,
-       0},
-      {"locality1", CreateEndpointsForBackends(1, 2), kDefaultLocalityWeight,
-       1},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  SetNextResolutionForLbChannelAllBalancers();
-  std::vector<std::pair<std::string, std::string>> metadata = {
-      {"address_hash", CreateMetadataValueThatHashesToBackend(0)}};
-  const auto rpc_options = RpcOptions().set_metadata(std::move(metadata));
-  WaitForBackend(0, WaitForBackendOptions(), rpc_options);
-  ShutdownBackend(0);
-  WaitForBackend(1, WaitForBackendOptions().set_allow_failures(true),
-                 rpc_options);
-  StartBackend(0);
-  WaitForBackend(0, WaitForBackendOptions(), rpc_options);
-  CheckRpcSendOk(100, rpc_options);
-  EXPECT_EQ(100, backends_[0]->backend_service()->request_count());
-  EXPECT_EQ(0, backends_[1]->backend_service()->request_count());
-}
-
-// Test that when all backends are down, we will keep reattempting.
-TEST_P(CdsTest, RingHashAllFailReattempt) {
-  const uint32_t kConnectionTimeoutMilliseconds = 5000;
-  auto cluster = default_cluster_;
-  cluster.set_lb_policy(Cluster::RING_HASH);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  auto new_route_config = default_route_config_;
-  auto* route = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  auto* hash_policy = route->mutable_route()->add_hash_policy();
-  hash_policy->mutable_header()->set_header_name("address_hash");
-  SetListenerAndRouteConfiguration(0, default_listener_, new_route_config);
-  std::vector<AdsServiceImpl::EdsResourceArgs::Endpoint> endpoints;
-  endpoints.emplace_back(grpc_pick_unused_port_or_die());
-  endpoints.emplace_back(backends_[1]->port());
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", std::move(endpoints)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  SetNextResolutionForLbChannelAllBalancers();
-  std::vector<std::pair<std::string, std::string>> metadata = {
-      {"address_hash", CreateMetadataValueThatHashesToBackend(0)}};
-  EXPECT_EQ(GRPC_CHANNEL_IDLE, channel_->GetState(false));
-  ShutdownBackend(1);
-  CheckRpcSendFailure(CheckRpcSendFailureOptions().set_rpc_options(
-      RpcOptions().set_metadata(std::move(metadata))));
-  StartBackend(1);
-  // Ensure we are actively connecting without any traffic.
-  EXPECT_TRUE(channel_->WaitForConnected(
-      grpc_timeout_milliseconds_to_deadline(kConnectionTimeoutMilliseconds)));
-}
-
-// Test that when all backends are down and then up, we may pick a TF backend
-// and we will then jump to ready backend.
-TEST_P(CdsTest, RingHashTransientFailureSkipToAvailableReady) {
-  const uint32_t kConnectionTimeoutMilliseconds = 5000;
-  auto cluster = default_cluster_;
-  cluster.set_lb_policy(Cluster::RING_HASH);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  auto new_route_config = default_route_config_;
-  auto* route = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  auto* hash_policy = route->mutable_route()->add_hash_policy();
-  hash_policy->mutable_header()->set_header_name("address_hash");
-  SetListenerAndRouteConfiguration(0, default_listener_, new_route_config);
-  std::vector<AdsServiceImpl::EdsResourceArgs::Endpoint> endpoints;
-  // Make sure we include some unused ports to fill the ring.
-  endpoints.emplace_back(backends_[0]->port());
-  endpoints.emplace_back(backends_[1]->port());
-  endpoints.emplace_back(grpc_pick_unused_port_or_die());
-  endpoints.emplace_back(grpc_pick_unused_port_or_die());
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", std::move(endpoints)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  SetNextResolutionForLbChannelAllBalancers();
-  std::vector<std::pair<std::string, std::string>> metadata = {
-      {"address_hash", CreateMetadataValueThatHashesToBackend(0)}};
-  const auto rpc_options = RpcOptions().set_metadata(std::move(metadata));
-  EXPECT_EQ(GRPC_CHANNEL_IDLE, channel_->GetState(false));
-  ShutdownBackend(0);
-  ShutdownBackend(1);
-  CheckRpcSendFailure(
-      CheckRpcSendFailureOptions().set_rpc_options(rpc_options));
-  EXPECT_EQ(GRPC_CHANNEL_TRANSIENT_FAILURE, channel_->GetState(false));
-  // Bring up 0, should be picked as the RPC is hashed to it.
-  StartBackend(0);
-  EXPECT_TRUE(channel_->WaitForConnected(
-      grpc_timeout_milliseconds_to_deadline(kConnectionTimeoutMilliseconds)));
-  WaitForBackend(0, WaitForBackendOptions(), rpc_options);
-  // Bring down 0 and bring up 1.
-  // Note the RPC contains a header value that will always be hashed to
-  // backend 0. So by purposely bring down backend 0 and bring up another
-  // backend, this will ensure Picker's first choice of backend 0 will fail
-  // and it will
-  // 1. reattempt backend 0 and
-  // 2. go through the remaining subchannels to find one in READY.
-  // Since the the entries in the ring is pretty distributed and we have
-  // unused ports to fill the ring, it is almost guaranteed that the Picker
-  // will go through some non-READY entries and skip them as per design.
-  ShutdownBackend(0);
-  CheckRpcSendFailure(
-      CheckRpcSendFailureOptions().set_rpc_options(rpc_options));
-  StartBackend(1);
-  EXPECT_TRUE(channel_->WaitForConnected(
-      grpc_timeout_milliseconds_to_deadline(kConnectionTimeoutMilliseconds)));
-  WaitForBackend(1, WaitForBackendOptions(), rpc_options);
-}
-
-// Test unspported hash policy types are all ignored before a supported
-// policy.
-TEST_P(CdsTest, RingHashUnsupportedHashPolicyUntilChannelIdHashing) {
-  auto cluster = default_cluster_;
-  cluster.set_lb_policy(Cluster::RING_HASH);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  auto new_route_config = default_route_config_;
-  auto* route = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  auto* hash_policy_unsupported_1 = route->mutable_route()->add_hash_policy();
-  hash_policy_unsupported_1->mutable_cookie()->set_name("cookie");
-  auto* hash_policy_unsupported_2 = route->mutable_route()->add_hash_policy();
-  hash_policy_unsupported_2->mutable_connection_properties()->set_source_ip(
-      true);
-  auto* hash_policy_unsupported_3 = route->mutable_route()->add_hash_policy();
-  hash_policy_unsupported_3->mutable_query_parameter()->set_name(
-      "query_parameter");
-  auto* hash_policy = route->mutable_route()->add_hash_policy();
-  hash_policy->mutable_filter_state()->set_key("io.grpc.channel_id");
-  SetListenerAndRouteConfiguration(0, default_listener_, new_route_config);
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  SetNextResolutionForLbChannelAllBalancers();
-  CheckRpcSendOk(100);
-  bool found = false;
-  for (size_t i = 0; i < backends_.size(); ++i) {
-    if (backends_[i]->backend_service()->request_count() > 0) {
-      EXPECT_EQ(backends_[i]->backend_service()->request_count(), 100)
-          << "backend " << i;
-      EXPECT_FALSE(found) << "backend " << i;
-      found = true;
-    }
-  }
-  EXPECT_TRUE(found);
-}
-
-// Test we nack when ring hash policy has invalid hash function (something
-// other than XX_HASH.
-TEST_P(CdsTest, RingHashPolicyHasInvalidHashFunction) {
-  auto cluster = default_cluster_;
-  cluster.set_lb_policy(Cluster::RING_HASH);
-  cluster.mutable_ring_hash_lb_config()->set_hash_function(
-      Cluster::RingHashLbConfig::MURMUR_HASH_2);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  auto new_route_config = default_route_config_;
-  auto* route = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  auto* hash_policy = route->mutable_route()->add_hash_policy();
-  hash_policy->mutable_filter_state()->set_key("io.grpc.channel_id");
-  SetListenerAndRouteConfiguration(0, default_listener_, new_route_config);
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->cds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(
-      response_state.error_message,
-      ::testing::HasSubstr("ring hash lb config has invalid hash function."));
-}
-
-// Test we nack when ring hash policy has invalid ring size.
-TEST_P(CdsTest, RingHashPolicyHasInvalidMinimumRingSize) {
-  auto cluster = default_cluster_;
-  cluster.set_lb_policy(Cluster::RING_HASH);
-  cluster.mutable_ring_hash_lb_config()->mutable_minimum_ring_size()->set_value(
-      0);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  auto new_route_config = default_route_config_;
-  auto* route = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  auto* hash_policy = route->mutable_route()->add_hash_policy();
-  hash_policy->mutable_filter_state()->set_key("io.grpc.channel_id");
-  SetListenerAndRouteConfiguration(0, default_listener_, new_route_config);
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->cds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr(
-                  "min_ring_size is not in the range of 1 to 8388608."));
-}
-
-// Test we nack when ring hash policy has invalid ring size.
-TEST_P(CdsTest, RingHashPolicyHasInvalidMaxmumRingSize) {
-  auto cluster = default_cluster_;
-  cluster.set_lb_policy(Cluster::RING_HASH);
-  cluster.mutable_ring_hash_lb_config()->mutable_maximum_ring_size()->set_value(
-      8388609);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  auto new_route_config = default_route_config_;
-  auto* route = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  auto* hash_policy = route->mutable_route()->add_hash_policy();
-  hash_policy->mutable_filter_state()->set_key("io.grpc.channel_id");
-  SetListenerAndRouteConfiguration(0, default_listener_, new_route_config);
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->cds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr(
-                  "max_ring_size is not in the range of 1 to 8388608."));
-}
-
-// Test we nack when ring hash policy has invalid ring size.
-TEST_P(CdsTest, RingHashPolicyHasInvalidRingSizeMinGreaterThanMax) {
-  auto cluster = default_cluster_;
-  cluster.set_lb_policy(Cluster::RING_HASH);
-  cluster.mutable_ring_hash_lb_config()->mutable_maximum_ring_size()->set_value(
-      5000);
-  cluster.mutable_ring_hash_lb_config()->mutable_minimum_ring_size()->set_value(
-      5001);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  auto new_route_config = default_route_config_;
-  auto* route = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
-  auto* hash_policy = route->mutable_route()->add_hash_policy();
-  hash_policy->mutable_filter_state()->set_key("io.grpc.channel_id");
-  SetListenerAndRouteConfiguration(0, default_listener_, new_route_config);
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  SetNextResolutionForLbChannelAllBalancers();
-  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->cds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr(
-                  "min_ring_size cannot be greater than max_ring_size."));
-}
-
-class XdsSecurityTest : public BasicTest {
- protected:
-  void SetUp() override {
-    BasicTest::SetUp();
-    root_cert_ = ReadFile(kCaCertPath);
-    bad_root_cert_ = ReadFile(kBadClientCertPath);
-    identity_pair_ = ReadTlsIdentityPair(kClientKeyPath, kClientCertPath);
-    // TODO(yashykt): Use different client certs here instead of reusing
-    // server certs after https://github.com/grpc/grpc/pull/24876 is merged
-    fallback_identity_pair_ =
-        ReadTlsIdentityPair(kServerKeyPath, kServerCertPath);
-    bad_identity_pair_ =
-        ReadTlsIdentityPair(kBadClientKeyPath, kBadClientCertPath);
-    server_san_exact_.set_exact("*.test.google.fr");
-    server_san_prefix_.set_prefix("waterzooi.test.google");
-    server_san_suffix_.set_suffix("google.fr");
-    server_san_contains_.set_contains("google");
-    server_san_regex_.mutable_safe_regex()->mutable_google_re2();
-    server_san_regex_.mutable_safe_regex()->set_regex(
-        "(foo|waterzooi).test.google.(fr|be)");
-    bad_san_1_.set_exact("192.168.1.4");
-    bad_san_2_.set_exact("foo.test.google.in");
-    authenticated_identity_ = {"testclient"};
-    fallback_authenticated_identity_ = {"*.test.google.fr",
-                                        "waterzooi.test.google.be",
-                                        "*.test.youtube.com", "192.168.1.3"};
-    AdsServiceImpl::EdsResourceArgs args({
-        {"locality0", CreateEndpointsForBackends(0, 1)},
-    });
-    balancers_[0]->ads_service()->SetEdsResource(
-        BuildEdsResource(args, DefaultEdsServiceName()));
-    SetNextResolutionForLbChannelAllBalancers();
-  }
-
-  void TearDown() override {
-    g_fake1_cert_data_map = nullptr;
-    g_fake2_cert_data_map = nullptr;
-    BasicTest::TearDown();
-  }
-
-  // Sends CDS updates with the new security configuration and verifies that
-  // after propagation, this new configuration is used for connections. If \a
-  // identity_instance_name and \a root_instance_name are both empty,
-  // connections are expected to use fallback credentials.
-  void UpdateAndVerifyXdsSecurityConfiguration(
-      absl::string_view root_instance_name,
-      absl::string_view root_certificate_name,
-      absl::string_view identity_instance_name,
-      absl::string_view identity_certificate_name,
-      const std::vector<StringMatcher>& san_matchers,
-      const std::vector<std::string>& expected_authenticated_identity,
-      bool test_expects_failure = false) {
-    auto cluster = default_cluster_;
-    if (!identity_instance_name.empty() || !root_instance_name.empty()) {
-      auto* transport_socket = cluster.mutable_transport_socket();
-      transport_socket->set_name("envoy.transport_sockets.tls");
-      UpstreamTlsContext upstream_tls_context;
-      if (!identity_instance_name.empty()) {
-        upstream_tls_context.mutable_common_tls_context()
-            ->mutable_tls_certificate_provider_instance()
-            ->set_instance_name(std::string(identity_instance_name));
-        upstream_tls_context.mutable_common_tls_context()
-            ->mutable_tls_certificate_provider_instance()
-            ->set_certificate_name(std::string(identity_certificate_name));
-      }
-      if (!root_instance_name.empty()) {
-        upstream_tls_context.mutable_common_tls_context()
-            ->mutable_validation_context()
-            ->mutable_ca_certificate_provider_instance()
-            ->set_instance_name(std::string(root_instance_name));
-        upstream_tls_context.mutable_common_tls_context()
-            ->mutable_validation_context()
-            ->mutable_ca_certificate_provider_instance()
-            ->set_certificate_name(std::string(root_certificate_name));
-      }
-      if (!san_matchers.empty()) {
-        auto* validation_context =
-            upstream_tls_context.mutable_common_tls_context()
-                ->mutable_validation_context();
-        for (const auto& san_matcher : san_matchers) {
-          *validation_context->add_match_subject_alt_names() = san_matcher;
-        }
-      }
-      transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context);
-    }
-    balancers_[0]->ads_service()->SetCdsResource(cluster);
-    // The updates might take time to have an effect, so use a retry loop.
-    constexpr int kRetryCount = 100;
-    int num_tries = 0;
-    for (; num_tries < kRetryCount; num_tries++) {
-      // Give some time for the updates to propagate.
-      gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(100));
-      if (test_expects_failure) {
-        // Restart the servers to force a reconnection so that previously
-        // connected subchannels are not used for the RPC.
-        ShutdownBackend(0);
-        StartBackend(0);
-        if (SendRpc().ok()) {
-          gpr_log(GPR_ERROR, "RPC succeeded. Failure expected. Trying again.");
-          continue;
-        }
-      } else {
-        WaitForBackend(0, WaitForBackendOptions().set_allow_failures(true));
-        Status status = SendRpc();
-        if (!status.ok()) {
-          gpr_log(GPR_ERROR, "RPC failed. code=%d message=%s Trying again.",
-                  status.error_code(), status.error_message().c_str());
-          continue;
-        }
-        if (backends_[0]->backend_service()->last_peer_identity() !=
-            expected_authenticated_identity) {
-          gpr_log(
-              GPR_ERROR,
-              "Expected client identity does not match. (actual) %s vs "
-              "(expected) %s Trying again.",
-              absl::StrJoin(
-                  backends_[0]->backend_service()->last_peer_identity(), ",")
-                  .c_str(),
-              absl::StrJoin(expected_authenticated_identity, ",").c_str());
-          continue;
-        }
-      }
-      break;
-    }
-    EXPECT_LT(num_tries, kRetryCount);
-  }
-
-  std::string root_cert_;
-  std::string bad_root_cert_;
-  grpc_core::PemKeyCertPairList identity_pair_;
-  grpc_core::PemKeyCertPairList fallback_identity_pair_;
-  grpc_core::PemKeyCertPairList bad_identity_pair_;
-  StringMatcher server_san_exact_;
-  StringMatcher server_san_prefix_;
-  StringMatcher server_san_suffix_;
-  StringMatcher server_san_contains_;
-  StringMatcher server_san_regex_;
-  StringMatcher bad_san_1_;
-  StringMatcher bad_san_2_;
-  std::vector<std::string> authenticated_identity_;
-  std::vector<std::string> fallback_authenticated_identity_;
-};
-
-TEST_P(XdsSecurityTest, UnknownTransportSocket) {
-  auto cluster = default_cluster_;
-  auto* transport_socket = cluster.mutable_transport_socket();
-  transport_socket->set_name("unknown_transport_socket");
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->cds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr(
-                  "Unrecognized transport socket: unknown_transport_socket"));
-}
-
-TEST_P(XdsSecurityTest,
-       TLSConfigurationWithoutValidationContextCertificateProviderInstance) {
-  auto cluster = default_cluster_;
-  auto* transport_socket = cluster.mutable_transport_socket();
-  transport_socket->set_name("envoy.transport_sockets.tls");
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->cds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr("TLS configuration provided but no "
-                                   "ca_certificate_provider_instance found."));
-}
-
-TEST_P(
-    XdsSecurityTest,
-    MatchSubjectAltNamesProvidedWithoutValidationContextCertificateProviderInstance) {
-  auto cluster = default_cluster_;
-  auto* transport_socket = cluster.mutable_transport_socket();
-  transport_socket->set_name("envoy.transport_sockets.tls");
-  UpstreamTlsContext upstream_tls_context;
-  auto* validation_context = upstream_tls_context.mutable_common_tls_context()
-                                 ->mutable_validation_context();
-  *validation_context->add_match_subject_alt_names() = server_san_exact_;
-  transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->cds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr("TLS configuration provided but no "
-                                   "ca_certificate_provider_instance found."));
-}
-
-TEST_P(
-    XdsSecurityTest,
-    TlsCertificateProviderInstanceWithoutValidationContextCertificateProviderInstance) {
-  auto cluster = default_cluster_;
-  auto* transport_socket = cluster.mutable_transport_socket();
-  transport_socket->set_name("envoy.transport_sockets.tls");
-  UpstreamTlsContext upstream_tls_context;
-  upstream_tls_context.mutable_common_tls_context()
-      ->mutable_tls_certificate_provider_instance()
-      ->set_instance_name(std::string("fake_plugin1"));
-  transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->cds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr("TLS configuration provided but no "
-                                   "ca_certificate_provider_instance found."));
-}
-
-TEST_P(XdsSecurityTest, RegexSanMatcherDoesNotAllowIgnoreCase) {
-  auto cluster = default_cluster_;
-  auto* transport_socket = cluster.mutable_transport_socket();
-  transport_socket->set_name("envoy.transport_sockets.tls");
-  UpstreamTlsContext upstream_tls_context;
-  upstream_tls_context.mutable_common_tls_context()
-      ->mutable_validation_context()
-      ->mutable_ca_certificate_provider_instance()
-      ->set_instance_name(std::string("fake_plugin1"));
-  auto* validation_context = upstream_tls_context.mutable_common_tls_context()
-                                 ->mutable_validation_context();
-  StringMatcher matcher;
-  matcher.mutable_safe_regex()->mutable_google_re2();
-  matcher.mutable_safe_regex()->set_regex(
-      "(foo|waterzooi).test.google.(fr|be)");
-  matcher.set_ignore_case(true);
-  *validation_context->add_match_subject_alt_names() = matcher;
-  transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->cds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr(
-                  "StringMatcher: ignore_case has no effect for SAFE_REGEX."));
-}
-
-TEST_P(XdsSecurityTest, UnknownRootCertificateProvider) {
-  auto cluster = default_cluster_;
-  auto* transport_socket = cluster.mutable_transport_socket();
-  transport_socket->set_name("envoy.transport_sockets.tls");
-  UpstreamTlsContext upstream_tls_context;
-  upstream_tls_context.mutable_common_tls_context()
-      ->mutable_validation_context()
-      ->mutable_ca_certificate_provider_instance()
-      ->set_instance_name("unknown");
-  transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->cds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr(
-                  "Unrecognized certificate provider instance name: unknown"));
-}
-
-TEST_P(XdsSecurityTest, UnknownIdentityCertificateProvider) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  auto cluster = default_cluster_;
-  auto* transport_socket = cluster.mutable_transport_socket();
-  transport_socket->set_name("envoy.transport_sockets.tls");
-  UpstreamTlsContext upstream_tls_context;
-  upstream_tls_context.mutable_common_tls_context()
-      ->mutable_tls_certificate_provider_instance()
-      ->set_instance_name("unknown");
-  upstream_tls_context.mutable_common_tls_context()
-      ->mutable_validation_context()
-      ->mutable_ca_certificate_provider_instance()
-      ->set_instance_name("fake_plugin1");
-  transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->cds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr(
-                  "Unrecognized certificate provider instance name: unknown"));
-  g_fake1_cert_data_map = nullptr;
-}
-
-TEST_P(XdsSecurityTest,
-       NacksCertificateValidationContextWithVerifyCertificateSpki) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  auto cluster = default_cluster_;
-  auto* transport_socket = cluster.mutable_transport_socket();
-  transport_socket->set_name("envoy.transport_sockets.tls");
-  UpstreamTlsContext upstream_tls_context;
-  upstream_tls_context.mutable_common_tls_context()
-      ->mutable_validation_context()
-      ->mutable_ca_certificate_provider_instance()
-      ->set_instance_name("fake_plugin1");
-  upstream_tls_context.mutable_common_tls_context()
-      ->mutable_validation_context()
-      ->add_verify_certificate_spki("spki");
-  transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->cds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(
-      response_state.error_message,
-      ::testing::HasSubstr(
-          "CertificateValidationContext: verify_certificate_spki unsupported"));
-}
-
-TEST_P(XdsSecurityTest,
-       NacksCertificateValidationContextWithVerifyCertificateHash) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  auto cluster = default_cluster_;
-  auto* transport_socket = cluster.mutable_transport_socket();
-  transport_socket->set_name("envoy.transport_sockets.tls");
-  UpstreamTlsContext upstream_tls_context;
-  upstream_tls_context.mutable_common_tls_context()
-      ->mutable_validation_context()
-      ->mutable_ca_certificate_provider_instance()
-      ->set_instance_name("fake_plugin1");
-  upstream_tls_context.mutable_common_tls_context()
-      ->mutable_validation_context()
-      ->add_verify_certificate_hash("hash");
-  transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->cds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(
-      response_state.error_message,
-      ::testing::HasSubstr(
-          "CertificateValidationContext: verify_certificate_hash unsupported"));
-}
-
-TEST_P(XdsSecurityTest,
-       NacksCertificateValidationContextWithRequireSignedCertificateTimes) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  auto cluster = default_cluster_;
-  auto* transport_socket = cluster.mutable_transport_socket();
-  transport_socket->set_name("envoy.transport_sockets.tls");
-  UpstreamTlsContext upstream_tls_context;
-  upstream_tls_context.mutable_common_tls_context()
-      ->mutable_validation_context()
-      ->mutable_ca_certificate_provider_instance()
-      ->set_instance_name("fake_plugin1");
-  upstream_tls_context.mutable_common_tls_context()
-      ->mutable_validation_context()
-      ->mutable_require_signed_certificate_timestamp()
-      ->set_value(true);
-  transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->cds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(
-      response_state.error_message,
-      ::testing::HasSubstr("CertificateValidationContext: "
-                           "require_signed_certificate_timestamp unsupported"));
-}
-
-TEST_P(XdsSecurityTest, NacksCertificateValidationContextWithCrl) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  auto cluster = default_cluster_;
-  auto* transport_socket = cluster.mutable_transport_socket();
-  transport_socket->set_name("envoy.transport_sockets.tls");
-  UpstreamTlsContext upstream_tls_context;
-  upstream_tls_context.mutable_common_tls_context()
-      ->mutable_validation_context()
-      ->mutable_ca_certificate_provider_instance()
-      ->set_instance_name("fake_plugin1");
-  upstream_tls_context.mutable_common_tls_context()
-      ->mutable_validation_context()
-      ->mutable_crl();
-  transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->cds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(
-      response_state.error_message,
-      ::testing::HasSubstr("CertificateValidationContext: crl unsupported"));
-}
-
-TEST_P(XdsSecurityTest,
-       NacksCertificateValidationContextWithCustomValidatorConfig) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  auto cluster = default_cluster_;
-  auto* transport_socket = cluster.mutable_transport_socket();
-  transport_socket->set_name("envoy.transport_sockets.tls");
-  UpstreamTlsContext upstream_tls_context;
-  upstream_tls_context.mutable_common_tls_context()
-      ->mutable_validation_context()
-      ->mutable_ca_certificate_provider_instance()
-      ->set_instance_name("fake_plugin1");
-  upstream_tls_context.mutable_common_tls_context()
-      ->mutable_validation_context()
-      ->mutable_custom_validator_config();
-  transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->cds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(
-      response_state.error_message,
-      ::testing::HasSubstr(
-          "CertificateValidationContext: custom_validator_config unsupported"));
-}
-
-TEST_P(XdsSecurityTest, NacksValidationContextSdsSecretConfig) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  auto cluster = default_cluster_;
-  auto* transport_socket = cluster.mutable_transport_socket();
-  transport_socket->set_name("envoy.transport_sockets.tls");
-  UpstreamTlsContext upstream_tls_context;
-  upstream_tls_context.mutable_common_tls_context()
-      ->mutable_validation_context_sds_secret_config();
-  transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->cds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(
-      response_state.error_message,
-      ::testing::HasSubstr("validation_context_sds_secret_config unsupported"));
-}
-
-TEST_P(XdsSecurityTest, NacksTlsParams) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  auto cluster = default_cluster_;
-  auto* transport_socket = cluster.mutable_transport_socket();
-  transport_socket->set_name("envoy.transport_sockets.tls");
-  UpstreamTlsContext upstream_tls_context;
-  upstream_tls_context.mutable_common_tls_context()
-      ->mutable_validation_context()
-      ->mutable_ca_certificate_provider_instance()
-      ->set_instance_name("fake_plugin1");
-  upstream_tls_context.mutable_common_tls_context()->mutable_tls_params();
-  transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->cds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr("tls_params unsupported"));
-}
-
-TEST_P(XdsSecurityTest, NacksCustomHandshaker) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  auto cluster = default_cluster_;
-  auto* transport_socket = cluster.mutable_transport_socket();
-  transport_socket->set_name("envoy.transport_sockets.tls");
-  UpstreamTlsContext upstream_tls_context;
-  upstream_tls_context.mutable_common_tls_context()
-      ->mutable_validation_context()
-      ->mutable_ca_certificate_provider_instance()
-      ->set_instance_name("fake_plugin1");
-  upstream_tls_context.mutable_common_tls_context()
-      ->mutable_custom_handshaker();
-  transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->cds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr("custom_handshaker unsupported"));
-}
-
-TEST_P(XdsSecurityTest, NacksTlsCertificates) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  auto cluster = default_cluster_;
-  auto* transport_socket = cluster.mutable_transport_socket();
-  transport_socket->set_name("envoy.transport_sockets.tls");
-  UpstreamTlsContext upstream_tls_context;
-  upstream_tls_context.mutable_common_tls_context()
-      ->mutable_validation_context()
-      ->mutable_ca_certificate_provider_instance()
-      ->set_instance_name("fake_plugin1");
-  upstream_tls_context.mutable_common_tls_context()->add_tls_certificates();
-  transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->cds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr("tls_certificates unsupported"));
-}
-
-TEST_P(XdsSecurityTest, NacksTlsCertificateSdsSecretConfigs) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  auto cluster = default_cluster_;
-  auto* transport_socket = cluster.mutable_transport_socket();
-  transport_socket->set_name("envoy.transport_sockets.tls");
-  UpstreamTlsContext upstream_tls_context;
-  upstream_tls_context.mutable_common_tls_context()
-      ->mutable_validation_context()
-      ->mutable_ca_certificate_provider_instance()
-      ->set_instance_name("fake_plugin1");
-  upstream_tls_context.mutable_common_tls_context()
-      ->add_tls_certificate_sds_secret_configs();
-  transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->cds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(
-      response_state.error_message,
-      ::testing::HasSubstr("tls_certificate_sds_secret_configs unsupported"));
-}
-
-TEST_P(XdsSecurityTest, TestTlsConfigurationInCombinedValidationContext) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  auto cluster = default_cluster_;
-  auto* transport_socket = cluster.mutable_transport_socket();
-  transport_socket->set_name("envoy.transport_sockets.tls");
-  UpstreamTlsContext upstream_tls_context;
-  upstream_tls_context.mutable_common_tls_context()
-      ->mutable_combined_validation_context()
-      ->mutable_default_validation_context()
-      ->mutable_ca_certificate_provider_instance()
-      ->set_instance_name("fake_plugin1");
-  transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  WaitForBackend(0, WaitForBackendOptions().set_allow_failures(true));
-  Status status = SendRpc();
-  EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
-                           << " message=" << status.error_message();
-}
-
-// TODO(yashykt): Remove this test once we stop supporting old fields
-TEST_P(XdsSecurityTest,
-       TestTlsConfigurationInValidationContextCertificateProviderInstance) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  auto cluster = default_cluster_;
-  auto* transport_socket = cluster.mutable_transport_socket();
-  transport_socket->set_name("envoy.transport_sockets.tls");
-  UpstreamTlsContext upstream_tls_context;
-  upstream_tls_context.mutable_common_tls_context()
-      ->mutable_combined_validation_context()
-      ->mutable_validation_context_certificate_provider_instance()
-      ->set_instance_name("fake_plugin1");
-  transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  WaitForBackend(0, WaitForBackendOptions().set_allow_failures(true));
-  Status status = SendRpc();
-  EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
-                           << " message=" << status.error_message();
-}
-
-TEST_P(XdsSecurityTest, TestMtlsConfigurationWithNoSanMatchers) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "fake_plugin1",
-                                          "", {}, authenticated_identity_);
-  g_fake1_cert_data_map = nullptr;
-}
-
-TEST_P(XdsSecurityTest, TestMtlsConfigurationWithExactSanMatcher) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "fake_plugin1",
-                                          "", {server_san_exact_},
-                                          authenticated_identity_);
-  g_fake1_cert_data_map = nullptr;
-}
-
-TEST_P(XdsSecurityTest, TestMtlsConfigurationWithPrefixSanMatcher) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "fake_plugin1",
-                                          "", {server_san_prefix_},
-                                          authenticated_identity_);
-  g_fake1_cert_data_map = nullptr;
-}
-
-TEST_P(XdsSecurityTest, TestMtlsConfigurationWithSuffixSanMatcher) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "fake_plugin1",
-                                          "", {server_san_suffix_},
-                                          authenticated_identity_);
-  g_fake1_cert_data_map = nullptr;
-}
-
-TEST_P(XdsSecurityTest, TestMtlsConfigurationWithContainsSanMatcher) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "fake_plugin1",
-                                          "", {server_san_contains_},
-                                          authenticated_identity_);
-  g_fake1_cert_data_map = nullptr;
-}
-
-TEST_P(XdsSecurityTest, TestMtlsConfigurationWithRegexSanMatcher) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "fake_plugin1",
-                                          "", {server_san_regex_},
-                                          authenticated_identity_);
-  g_fake1_cert_data_map = nullptr;
-}
-
-TEST_P(XdsSecurityTest, TestMtlsConfigurationWithSanMatchersUpdate) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  UpdateAndVerifyXdsSecurityConfiguration(
-      "fake_plugin1", "", "fake_plugin1", "",
-      {server_san_exact_, server_san_prefix_}, authenticated_identity_);
-  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "fake_plugin1",
-                                          "", {bad_san_1_, bad_san_2_}, {},
-                                          true /* failure */);
-  UpdateAndVerifyXdsSecurityConfiguration(
-      "fake_plugin1", "", "fake_plugin1", "",
-      {server_san_prefix_, server_san_regex_}, authenticated_identity_);
-  g_fake1_cert_data_map = nullptr;
-}
-
-TEST_P(XdsSecurityTest, TestMtlsConfigurationWithRootPluginUpdate) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  FakeCertificateProvider::CertDataMap fake2_cert_map = {
-      {"", {bad_root_cert_, bad_identity_pair_}}};
-  g_fake2_cert_data_map = &fake2_cert_map;
-  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "fake_plugin1",
-                                          "", {server_san_exact_},
-                                          authenticated_identity_);
-  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin2" /* bad root */, "",
-                                          "fake_plugin1", "", {}, {},
-                                          true /* failure */);
-  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "fake_plugin1",
-                                          "", {server_san_exact_},
-                                          authenticated_identity_);
-  g_fake1_cert_data_map = nullptr;
-  g_fake2_cert_data_map = nullptr;
-}
-
-TEST_P(XdsSecurityTest, TestMtlsConfigurationWithIdentityPluginUpdate) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  FakeCertificateProvider::CertDataMap fake2_cert_map = {
-      {"", {root_cert_, fallback_identity_pair_}}};
-  g_fake2_cert_data_map = &fake2_cert_map;
-  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "fake_plugin1",
-                                          "", {server_san_exact_},
-                                          authenticated_identity_);
-  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "fake_plugin2",
-                                          "", {server_san_exact_},
-                                          fallback_authenticated_identity_);
-  g_fake1_cert_data_map = nullptr;
-  g_fake2_cert_data_map = nullptr;
-}
-
-TEST_P(XdsSecurityTest, TestMtlsConfigurationWithBothPluginsUpdated) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  FakeCertificateProvider::CertDataMap fake2_cert_map = {
-      {"", {bad_root_cert_, bad_identity_pair_}},
-      {"good", {root_cert_, fallback_identity_pair_}}};
-  g_fake2_cert_data_map = &fake2_cert_map;
-  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin2", "", "fake_plugin2",
-                                          "", {}, {}, true /* failure */);
-  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "fake_plugin1",
-                                          "", {server_san_prefix_},
-                                          authenticated_identity_);
-  UpdateAndVerifyXdsSecurityConfiguration(
-      "fake_plugin2", "good", "fake_plugin2", "good", {server_san_prefix_},
-      fallback_authenticated_identity_);
-  g_fake1_cert_data_map = nullptr;
-  g_fake2_cert_data_map = nullptr;
-}
-
-TEST_P(XdsSecurityTest, TestMtlsConfigurationWithRootCertificateNameUpdate) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}},
-      {"bad", {bad_root_cert_, bad_identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "fake_plugin1",
-                                          "", {server_san_regex_},
-                                          authenticated_identity_);
-  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "bad", "fake_plugin1",
-                                          "", {server_san_regex_}, {},
-                                          true /* failure */);
-  g_fake1_cert_data_map = nullptr;
-}
-
-TEST_P(XdsSecurityTest,
-       TestMtlsConfigurationWithIdentityCertificateNameUpdate) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}},
-      {"bad", {bad_root_cert_, bad_identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "fake_plugin1",
-                                          "", {server_san_exact_},
-                                          authenticated_identity_);
-  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "fake_plugin1",
-                                          "bad", {server_san_exact_}, {},
-                                          true /* failure */);
-  g_fake1_cert_data_map = nullptr;
-}
-
-TEST_P(XdsSecurityTest,
-       TestMtlsConfigurationWithIdentityCertificateNameUpdateGoodCerts) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}},
-      {"good", {root_cert_, fallback_identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "fake_plugin1",
-                                          "", {server_san_exact_},
-                                          authenticated_identity_);
-  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "fake_plugin1",
-                                          "good", {server_san_exact_},
-                                          fallback_authenticated_identity_);
-  g_fake1_cert_data_map = nullptr;
-}
-
-TEST_P(XdsSecurityTest, TestMtlsConfigurationWithBothCertificateNamesUpdated) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}},
-      {"bad", {bad_root_cert_, bad_identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "bad", "fake_plugin1",
-                                          "bad", {server_san_prefix_}, {},
-                                          true /* failure */);
-  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "fake_plugin1",
-                                          "", {server_san_prefix_},
-                                          authenticated_identity_);
-  g_fake1_cert_data_map = nullptr;
-}
-
-TEST_P(XdsSecurityTest, TestTlsConfigurationWithNoSanMatchers) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "", "", {},
-                                          {} /* unauthenticated */);
-  g_fake1_cert_data_map = nullptr;
-}
-
-TEST_P(XdsSecurityTest, TestTlsConfigurationWithSanMatchers) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  UpdateAndVerifyXdsSecurityConfiguration(
-      "fake_plugin1", "", "", "",
-      {server_san_exact_, server_san_prefix_, server_san_regex_},
-      {} /* unauthenticated */);
-  g_fake1_cert_data_map = nullptr;
-}
-
-TEST_P(XdsSecurityTest, TestTlsConfigurationWithSanMatchersUpdate) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  UpdateAndVerifyXdsSecurityConfiguration(
-      "fake_plugin1", "", "", "", {server_san_exact_, server_san_prefix_},
-      {} /* unauthenticated */);
-  UpdateAndVerifyXdsSecurityConfiguration(
-      "fake_plugin1", "", "", "", {bad_san_1_, bad_san_2_},
-      {} /* unauthenticated */, true /* failure */);
-  UpdateAndVerifyXdsSecurityConfiguration(
-      "fake_plugin1", "", "", "", {server_san_prefix_, server_san_regex_},
-      {} /* unauthenticated */);
-  g_fake1_cert_data_map = nullptr;
-}
-
-TEST_P(XdsSecurityTest, TestTlsConfigurationWithRootCertificateNameUpdate) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}},
-      {"bad", {bad_root_cert_, bad_identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "", "",
-                                          {server_san_exact_},
-                                          {} /* unauthenticated */);
-  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "bad", "", "",
-                                          {server_san_exact_}, {},
-                                          true /* failure */);
-  g_fake1_cert_data_map = nullptr;
-}
-
-TEST_P(XdsSecurityTest, TestTlsConfigurationWithRootPluginUpdate) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  FakeCertificateProvider::CertDataMap fake2_cert_map = {
-      {"", {bad_root_cert_, bad_identity_pair_}}};
-  g_fake2_cert_data_map = &fake2_cert_map;
-  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "", "",
-                                          {server_san_exact_},
-                                          {} /* unauthenticated */);
-  UpdateAndVerifyXdsSecurityConfiguration(
-      "fake_plugin2", "", "", "", {server_san_exact_}, {}, true /* failure */);
-  g_fake1_cert_data_map = nullptr;
-  g_fake2_cert_data_map = nullptr;
-}
-
-TEST_P(XdsSecurityTest, TestFallbackConfiguration) {
-  UpdateAndVerifyXdsSecurityConfiguration("", "", "", "", {},
-                                          fallback_authenticated_identity_);
-  g_fake1_cert_data_map = nullptr;
-}
-
-TEST_P(XdsSecurityTest, TestMtlsToTls) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "fake_plugin1",
-                                          "", {server_san_exact_},
-                                          authenticated_identity_);
-  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "", "",
-                                          {server_san_exact_},
-                                          {} /* unauthenticated */);
-  g_fake1_cert_data_map = nullptr;
-}
-
-TEST_P(XdsSecurityTest, TestMtlsToFallback) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "fake_plugin1",
-                                          "", {server_san_exact_},
-                                          authenticated_identity_);
-  UpdateAndVerifyXdsSecurityConfiguration("", "", "", "", {},
-                                          fallback_authenticated_identity_);
-  g_fake1_cert_data_map = nullptr;
-}
-
-TEST_P(XdsSecurityTest, TestTlsToMtls) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "", "",
-                                          {server_san_exact_},
-                                          {} /* unauthenticated */);
-  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "fake_plugin1",
-                                          "", {server_san_exact_},
-                                          authenticated_identity_);
-  g_fake1_cert_data_map = nullptr;
-}
-
-TEST_P(XdsSecurityTest, TestTlsToFallback) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "", "",
-                                          {server_san_exact_},
-                                          {} /* unauthenticated */);
-  UpdateAndVerifyXdsSecurityConfiguration("", "", "", "", {},
-                                          fallback_authenticated_identity_);
-  g_fake1_cert_data_map = nullptr;
-}
-
-TEST_P(XdsSecurityTest, TestFallbackToMtls) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  UpdateAndVerifyXdsSecurityConfiguration("", "", "", "", {},
-                                          fallback_authenticated_identity_);
-  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "fake_plugin1",
-                                          "", {server_san_exact_},
-                                          authenticated_identity_);
-  g_fake1_cert_data_map = nullptr;
-}
-
-TEST_P(XdsSecurityTest, TestFallbackToTls) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  UpdateAndVerifyXdsSecurityConfiguration("", "", "", "", {},
-                                          fallback_authenticated_identity_);
-  UpdateAndVerifyXdsSecurityConfiguration("fake_plugin1", "", "", "",
-                                          {server_san_exact_},
-                                          {} /* unauthenticated */);
-  g_fake1_cert_data_map = nullptr;
-}
-
-TEST_P(XdsSecurityTest, TestFileWatcherCertificateProvider) {
-  UpdateAndVerifyXdsSecurityConfiguration("file_plugin", "", "file_plugin", "",
-                                          {server_san_exact_},
-                                          authenticated_identity_);
-}
-
-class XdsEnabledServerTest : public XdsEnd2endTest {
- protected:
-  XdsEnabledServerTest()
-      : XdsEnd2endTest(1, 1, 100, true /* use_xds_enabled_server */) {}
-
-  void SetUp() override {
-    XdsEnd2endTest::SetUp();
-    AdsServiceImpl::EdsResourceArgs args({
-        {"locality0", CreateEndpointsForBackends(0, 1)},
-    });
-    balancers_[0]->ads_service()->SetEdsResource(
-        BuildEdsResource(args, DefaultEdsServiceName()));
-    SetNextResolution({});
-    SetNextResolutionForLbChannelAllBalancers();
-  }
-};
-
-TEST_P(XdsEnabledServerTest, Basic) {
-  Listener listener;
-  listener.set_name(
-      absl::StrCat("grpc/server?xds.resource.listening_address=",
-                   ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()));
-  listener.mutable_address()->mutable_socket_address()->set_address(
-      ipv6_only_ ? "::1" : "127.0.0.1");
-  listener.mutable_address()->mutable_socket_address()->set_port_value(
-      backends_[0]->port());
-  listener.add_filter_chains()->add_filters()->mutable_typed_config()->PackFrom(
-      HttpConnectionManager());
-  balancers_[0]->ads_service()->SetLdsResource(listener);
-  WaitForBackend(0);
-}
-
-TEST_P(XdsEnabledServerTest, BadLdsUpdateNoApiListenerNorAddress) {
-  Listener listener;
-  listener.set_name(
-      absl::StrCat("grpc/server?xds.resource.listening_address=",
-                   ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()));
-  listener.add_filter_chains()->add_filters()->mutable_typed_config()->PackFrom(
-      HttpConnectionManager());
-  balancers_[0]->ads_service()->SetLdsResource(listener);
-  ASSERT_TRUE(WaitForLdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->lds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(
-      response_state.error_message,
-      ::testing::HasSubstr("Listener has neither address nor ApiListener"));
-}
-
-TEST_P(XdsEnabledServerTest, BadLdsUpdateBothApiListenerAndAddress) {
-  Listener listener;
-  listener.set_name(
-      absl::StrCat("grpc/server?xds.resource.listening_address=",
-                   ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()));
-  listener.mutable_address()->mutable_socket_address()->set_address(
-      ipv6_only_ ? "::1" : "127.0.0.1");
-  listener.mutable_address()->mutable_socket_address()->set_port_value(
-      backends_[0]->port());
-  auto* filter_chain = listener.add_filter_chains();
-  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
-      HttpConnectionManager());
-  listener.mutable_api_listener();
-  balancers_[0]->ads_service()->SetLdsResource(listener);
-  ASSERT_TRUE(WaitForLdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->lds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(
-      response_state.error_message,
-      ::testing::HasSubstr("Listener has both address and ApiListener"));
-}
-
-TEST_P(XdsEnabledServerTest, UnsupportedL4Filter) {
-  Listener listener;
-  listener.set_name(
-      absl::StrCat("grpc/server?xds.resource.listening_address=",
-                   ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()));
-  listener.mutable_address()->mutable_socket_address()->set_address(
-      ipv6_only_ ? "::1" : "127.0.0.1");
-  listener.mutable_address()->mutable_socket_address()->set_port_value(
-      backends_[0]->port());
-  listener.add_filter_chains()->add_filters()->mutable_typed_config()->PackFrom(default_listener_ /* any proto object other than HttpConnectionManager */);
-  balancers_[0]->ads_service()->SetLdsResource(listener);
-  ASSERT_TRUE(WaitForLdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->lds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr("Unsupported filter type"));
-}
-
-TEST_P(XdsEnabledServerTest, UnsupportedHttpFilter) {
-  Listener listener;
-  listener.set_name(
-      absl::StrCat("grpc/server?xds.resource.listening_address=",
-                   ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()));
-  listener.mutable_address()->mutable_socket_address()->set_address(
-      ipv6_only_ ? "::1" : "127.0.0.1");
-  listener.mutable_address()->mutable_socket_address()->set_port_value(
-      backends_[0]->port());
-  HttpConnectionManager http_connection_manager;
-  auto* http_filter = http_connection_manager.add_http_filters();
-  http_filter->set_name("grpc.testing.unsupported_http_filter");
-  http_filter->mutable_typed_config()->set_type_url(
-      "grpc.testing.unsupported_http_filter");
-  listener.add_filter_chains()->add_filters()->mutable_typed_config()->PackFrom(
-      http_connection_manager);
-  balancers_[0]->ads_service()->SetLdsResource(listener);
-  ASSERT_TRUE(WaitForLdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->lds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr("no filter registered for config type "
-                                   "grpc.testing.unsupported_http_filter"));
-}
-
-TEST_P(XdsEnabledServerTest, HttpFilterNotSupportedOnServer) {
-  Listener listener;
-  listener.set_name(
-      absl::StrCat("grpc/server?xds.resource.listening_address=",
-                   ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()));
-  listener.mutable_address()->mutable_socket_address()->set_address(
-      ipv6_only_ ? "::1" : "127.0.0.1");
-  listener.mutable_address()->mutable_socket_address()->set_port_value(
-      backends_[0]->port());
-  HttpConnectionManager http_connection_manager;
-  auto* http_filter = http_connection_manager.add_http_filters();
-  http_filter->set_name("grpc.testing.client_only_http_filter");
-  http_filter->mutable_typed_config()->set_type_url(
-      "grpc.testing.client_only_http_filter");
-  http_filter = http_connection_manager.add_http_filters();
-  http_filter->set_name("router");
-  http_filter->mutable_typed_config()->PackFrom(
-      envoy::extensions::filters::http::router::v3::Router());
-  listener.add_filter_chains()->add_filters()->mutable_typed_config()->PackFrom(
-      http_connection_manager);
-  balancers_[0]->ads_service()->SetLdsResource(listener);
-  ASSERT_TRUE(WaitForLdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->lds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(
-      response_state.error_message,
-      ::testing::HasSubstr("Filter grpc.testing.client_only_http_filter is not "
-                           "supported on servers"));
-}
-
-TEST_P(XdsEnabledServerTest,
-       HttpFilterNotSupportedOnServerIgnoredWhenOptional) {
-  Listener listener;
-  listener.set_name(
-      absl::StrCat("grpc/server?xds.resource.listening_address=",
-                   ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()));
-  listener.mutable_address()->mutable_socket_address()->set_address(
-      ipv6_only_ ? "::1" : "127.0.0.1");
-  listener.mutable_address()->mutable_socket_address()->set_port_value(
-      backends_[0]->port());
-  HttpConnectionManager http_connection_manager;
-  auto* http_filter = http_connection_manager.add_http_filters();
-  http_filter->set_name("grpc.testing.client_only_http_filter");
-  http_filter->mutable_typed_config()->set_type_url(
-      "grpc.testing.client_only_http_filter");
-  http_filter->set_is_optional(true);
-  listener.add_filter_chains()->add_filters()->mutable_typed_config()->PackFrom(
-      http_connection_manager);
-  balancers_[0]->ads_service()->SetLdsResource(listener);
-  WaitForBackend(0);
-  const auto response_state =
-      balancers_[0]->ads_service()->lds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::ACKED);
-}
-
-// Verify that a mismatch of listening address results in "not serving"
-// status.
-TEST_P(XdsEnabledServerTest, ListenerAddressMismatch) {
-  Listener listener;
-  listener.set_name(
-      absl::StrCat("grpc/server?xds.resource.listening_address=",
-                   ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()));
-  // Set a different listening address in the LDS update
-  listener.mutable_address()->mutable_socket_address()->set_address(
-      "192.168.1.1");
-  listener.mutable_address()->mutable_socket_address()->set_port_value(
-      backends_[0]->port());
-  listener.add_filter_chains()->add_filters()->mutable_typed_config()->PackFrom(
-      HttpConnectionManager());
-  balancers_[0]->ads_service()->SetLdsResource(listener);
-  backends_[0]->notifier()->WaitOnServingStatusChange(
-      absl::StrCat(ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()),
-      grpc::StatusCode::FAILED_PRECONDITION);
-}
-
-TEST_P(XdsEnabledServerTest, UseOriginalDstNotSupported) {
-  Listener listener;
-  listener.set_name(
-      absl::StrCat("grpc/server?xds.resource.listening_address=",
-                   ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()));
-  listener.mutable_address()->mutable_socket_address()->set_address(
-      ipv6_only_ ? "::1" : "127.0.0.1");
-  listener.mutable_address()->mutable_socket_address()->set_port_value(
-      backends_[0]->port());
-  listener.add_filter_chains()->add_filters()->mutable_typed_config()->PackFrom(
-      HttpConnectionManager());
-  listener.mutable_use_original_dst()->set_value(true);
-  balancers_[0]->ads_service()->SetLdsResource(listener);
-  ASSERT_TRUE(WaitForLdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->lds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(
-      response_state.error_message,
-      ::testing::HasSubstr("Field \'use_original_dst\' is not supported."));
-}
-
-class XdsServerSecurityTest : public XdsEnd2endTest {
- protected:
-  XdsServerSecurityTest()
-      : XdsEnd2endTest(1, 1, 100, true /* use_xds_enabled_server */) {}
-
-  void SetUp() override {
-    XdsEnd2endTest::SetUp();
-    root_cert_ = ReadFile(kCaCertPath);
-    bad_root_cert_ = ReadFile(kBadClientCertPath);
-    identity_pair_ = ReadTlsIdentityPair(kServerKeyPath, kServerCertPath);
-    bad_identity_pair_ =
-        ReadTlsIdentityPair(kBadClientKeyPath, kBadClientCertPath);
-    identity_pair_2_ = ReadTlsIdentityPair(kClientKeyPath, kClientCertPath);
-    server_authenticated_identity_ = {"*.test.google.fr",
-                                      "waterzooi.test.google.be",
-                                      "*.test.youtube.com", "192.168.1.3"};
-    server_authenticated_identity_2_ = {"testclient"};
-    client_authenticated_identity_ = {"*.test.google.fr",
-                                      "waterzooi.test.google.be",
-                                      "*.test.youtube.com", "192.168.1.3"};
-    AdsServiceImpl::EdsResourceArgs args({
-        {"locality0", CreateEndpointsForBackends(0, 1)},
-    });
-    balancers_[0]->ads_service()->SetEdsResource(
-        BuildEdsResource(args, DefaultEdsServiceName()));
-    SetNextResolution({});
-    SetNextResolutionForLbChannelAllBalancers();
-  }
-
-  void TearDown() override {
-    g_fake1_cert_data_map = nullptr;
-    g_fake2_cert_data_map = nullptr;
-    XdsEnd2endTest::TearDown();
-  }
-
-  void SetLdsUpdate(absl::string_view root_instance_name,
-                    absl::string_view root_certificate_name,
-                    absl::string_view identity_instance_name,
-                    absl::string_view identity_certificate_name,
-                    bool require_client_certificates) {
-    Listener listener;
-    listener.set_name(absl::StrCat(
-        ipv6_only_ ? "grpc/server?xds.resource.listening_address=[::1]:"
-                   : "grpc/server?xds.resource.listening_address=127.0.0.1:",
-        backends_[0]->port()));
-    listener.mutable_address()->mutable_socket_address()->set_address(
-        ipv6_only_ ? "[::1]" : "127.0.0.1");
-    listener.mutable_address()->mutable_socket_address()->set_port_value(
-        backends_[0]->port());
-    auto* filter_chain = listener.add_filter_chains();
-    filter_chain->add_filters()->mutable_typed_config()->PackFrom(
-        HttpConnectionManager());
-    if (!identity_instance_name.empty()) {
-      auto* transport_socket = filter_chain->mutable_transport_socket();
-      transport_socket->set_name("envoy.transport_sockets.tls");
-      DownstreamTlsContext downstream_tls_context;
-      downstream_tls_context.mutable_common_tls_context()
-          ->mutable_tls_certificate_provider_instance()
-          ->set_instance_name(std::string(identity_instance_name));
-      downstream_tls_context.mutable_common_tls_context()
-          ->mutable_tls_certificate_provider_instance()
-          ->set_certificate_name(std::string(identity_certificate_name));
-      if (!root_instance_name.empty()) {
-        downstream_tls_context.mutable_common_tls_context()
-            ->mutable_validation_context()
-            ->mutable_ca_certificate_provider_instance()
-            ->set_instance_name(std::string(root_instance_name));
-        downstream_tls_context.mutable_common_tls_context()
-            ->mutable_validation_context()
-            ->mutable_ca_certificate_provider_instance()
-            ->set_certificate_name(std::string(root_certificate_name));
-        downstream_tls_context.mutable_require_client_certificate()->set_value(
-            require_client_certificates);
-      }
-      transport_socket->mutable_typed_config()->PackFrom(
-          downstream_tls_context);
-    }
-    balancers_[0]->ads_service()->SetLdsResource(listener);
-  }
-
-  std::shared_ptr<grpc::Channel> CreateMtlsChannel() {
-    ChannelArguments args;
-    // Override target name for host name check
-    args.SetString(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG,
-                   ipv6_only_ ? "::1" : "127.0.0.1");
-    args.SetInt(GRPC_ARG_USE_LOCAL_SUBCHANNEL_POOL, 1);
-    std::string uri = absl::StrCat(
-        ipv6_only_ ? "ipv6:[::1]:" : "ipv4:127.0.0.1:", backends_[0]->port());
-    // TODO(yashykt): Switch to using C++ API once b/173823806 is fixed.
-    grpc_tls_credentials_options* options =
-        grpc_tls_credentials_options_create();
-    grpc_tls_credentials_options_set_server_verification_option(
-        options, GRPC_TLS_SKIP_HOSTNAME_VERIFICATION);
-    grpc_tls_credentials_options_set_certificate_provider(
-        options,
-        grpc_core::MakeRefCounted<grpc_core::StaticDataCertificateProvider>(
-            ReadFile(kCaCertPath),
-            ReadTlsIdentityPair(kServerKeyPath, kServerCertPath))
-            .get());
-    grpc_tls_credentials_options_watch_root_certs(options);
-    grpc_tls_credentials_options_watch_identity_key_cert_pairs(options);
-    grpc_tls_server_authorization_check_config* check_config =
-        grpc_tls_server_authorization_check_config_create(
-            nullptr, ServerAuthCheckSchedule, nullptr, nullptr);
-    grpc_tls_credentials_options_set_server_authorization_check_config(
-        options, check_config);
-    auto channel_creds = std::make_shared<SecureChannelCredentials>(
-        grpc_tls_credentials_create(options));
-    grpc_tls_server_authorization_check_config_release(check_config);
-    return CreateCustomChannel(uri, channel_creds, args);
-  }
-
-  std::shared_ptr<grpc::Channel> CreateTlsChannel() {
-    ChannelArguments args;
-    // Override target name for host name check
-    args.SetString(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG,
-                   ipv6_only_ ? "::1" : "127.0.0.1");
-    args.SetInt(GRPC_ARG_USE_LOCAL_SUBCHANNEL_POOL, 1);
-    std::string uri = absl::StrCat(
-        ipv6_only_ ? "ipv6:[::1]:" : "ipv4:127.0.0.1:", backends_[0]->port());
-    // TODO(yashykt): Switch to using C++ API once b/173823806 is fixed.
-    grpc_tls_credentials_options* options =
-        grpc_tls_credentials_options_create();
-    grpc_tls_credentials_options_set_server_verification_option(
-        options, GRPC_TLS_SKIP_HOSTNAME_VERIFICATION);
-    grpc_tls_credentials_options_set_certificate_provider(
-        options,
-        grpc_core::MakeRefCounted<grpc_core::StaticDataCertificateProvider>(
-            ReadFile(kCaCertPath),
-            ReadTlsIdentityPair(kServerKeyPath, kServerCertPath))
-            .get());
-    grpc_tls_credentials_options_watch_root_certs(options);
-    grpc_tls_server_authorization_check_config* check_config =
-        grpc_tls_server_authorization_check_config_create(
-            nullptr, ServerAuthCheckSchedule, nullptr, nullptr);
-    grpc_tls_credentials_options_set_server_authorization_check_config(
-        options, check_config);
-    auto channel_creds = std::make_shared<SecureChannelCredentials>(
-        grpc_tls_credentials_create(options));
-    grpc_tls_server_authorization_check_config_release(check_config);
-    return CreateCustomChannel(uri, channel_creds, args);
-  }
-
-  std::shared_ptr<grpc::Channel> CreateInsecureChannel() {
-    ChannelArguments args;
-    // Override target name for host name check
-    args.SetString(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG,
-                   ipv6_only_ ? "::1" : "127.0.0.1");
-    args.SetInt(GRPC_ARG_USE_LOCAL_SUBCHANNEL_POOL, 1);
-    std::string uri = absl::StrCat(
-        ipv6_only_ ? "ipv6:[::1]:" : "ipv4:127.0.0.1:", backends_[0]->port());
-    return CreateCustomChannel(uri, InsecureChannelCredentials(), args);
-  }
-
-  void SendRpc(std::function<std::shared_ptr<grpc::Channel>()> channel_creator,
-               std::vector<std::string> expected_server_identity,
-               std::vector<std::string> expected_client_identity,
-               bool test_expects_failure = false) {
-    gpr_log(GPR_INFO, "Sending RPC");
-    int num_tries = 0;
-    constexpr int kRetryCount = 100;
-    for (; num_tries < kRetryCount; num_tries++) {
-      auto channel = channel_creator();
-      auto stub = grpc::testing::EchoTestService::NewStub(channel);
-      ClientContext context;
-      context.set_wait_for_ready(true);
-      context.set_deadline(grpc_timeout_milliseconds_to_deadline(2000));
-      EchoRequest request;
-      request.set_message(kRequestMessage);
-      EchoResponse response;
-      Status status = stub->Echo(&context, request, &response);
-      if (test_expects_failure) {
-        if (status.ok()) {
-          gpr_log(GPR_ERROR, "RPC succeeded. Failure expected. Trying again.");
-          continue;
-        }
-      } else {
-        if (!status.ok()) {
-          gpr_log(GPR_ERROR, "RPC failed. code=%d message=%s Trying again.",
-                  status.error_code(), status.error_message().c_str());
-          continue;
-        }
-        EXPECT_EQ(response.message(), kRequestMessage);
-        std::vector<std::string> peer_identity;
-        for (const auto& entry : context.auth_context()->GetPeerIdentity()) {
-          peer_identity.emplace_back(
-              std::string(entry.data(), entry.size()).c_str());
-        }
-        if (peer_identity != expected_server_identity) {
-          gpr_log(GPR_ERROR,
-                  "Expected server identity does not match. (actual) %s vs "
-                  "(expected) %s Trying again.",
-                  absl::StrJoin(peer_identity, ",").c_str(),
-                  absl::StrJoin(expected_server_identity, ",").c_str());
-          continue;
-        }
-        if (backends_[0]->backend_service()->last_peer_identity() !=
-            expected_client_identity) {
-          gpr_log(
-              GPR_ERROR,
-              "Expected client identity does not match. (actual) %s vs "
-              "(expected) %s Trying again.",
-              absl::StrJoin(
-                  backends_[0]->backend_service()->last_peer_identity(), ",")
-                  .c_str(),
-              absl::StrJoin(expected_client_identity, ",").c_str());
-          continue;
-        }
-      }
-      break;
-    }
-    EXPECT_LT(num_tries, kRetryCount);
-  }
-
-  std::string root_cert_;
-  std::string bad_root_cert_;
-  grpc_core::PemKeyCertPairList identity_pair_;
-  grpc_core::PemKeyCertPairList bad_identity_pair_;
-  grpc_core::PemKeyCertPairList identity_pair_2_;
-  std::vector<std::string> server_authenticated_identity_;
-  std::vector<std::string> server_authenticated_identity_2_;
-  std::vector<std::string> client_authenticated_identity_;
-};
-
-TEST_P(XdsServerSecurityTest, UnknownTransportSocket) {
-  Listener listener;
-  listener.set_name(
-      absl::StrCat("grpc/server?xds.resource.listening_address=",
-                   ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()));
-  auto* socket_address = listener.mutable_address()->mutable_socket_address();
-  socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1");
-  socket_address->set_port_value(backends_[0]->port());
-  auto* filter_chain = listener.add_filter_chains();
-  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
-      HttpConnectionManager());
-  auto* transport_socket = filter_chain->mutable_transport_socket();
-  transport_socket->set_name("unknown_transport_socket");
-  balancers_[0]->ads_service()->SetLdsResource(listener);
-  ASSERT_TRUE(WaitForLdsNack(StatusCode::DEADLINE_EXCEEDED))
-      << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->lds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr(
-                  "Unrecognized transport socket: unknown_transport_socket"));
-}
-
-TEST_P(XdsServerSecurityTest, NacksRequireSNI) {
-  Listener listener;
-  listener.set_name(
-      absl::StrCat("grpc/server?xds.resource.listening_address=",
-                   ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()));
-  auto* socket_address = listener.mutable_address()->mutable_socket_address();
-  socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1");
-  socket_address->set_port_value(backends_[0]->port());
-  auto* filter_chain = listener.add_filter_chains();
-  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
-      HttpConnectionManager());
-  auto* transport_socket = filter_chain->mutable_transport_socket();
-  transport_socket->set_name("envoy.transport_sockets.tls");
-  DownstreamTlsContext downstream_tls_context;
-  downstream_tls_context.mutable_common_tls_context()
-      ->mutable_tls_certificate_provider_instance()
-      ->set_instance_name("fake_plugin1");
-  downstream_tls_context.mutable_require_sni()->set_value(true);
-  transport_socket->mutable_typed_config()->PackFrom(downstream_tls_context);
-  balancers_[0]->ads_service()->SetLdsResource(listener);
-  ASSERT_TRUE(WaitForLdsNack(StatusCode::DEADLINE_EXCEEDED))
-      << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->lds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr("require_sni: unsupported"));
-}
-
-TEST_P(XdsServerSecurityTest, NacksOcspStaplePolicyOtherThanLenientStapling) {
-  Listener listener;
-  listener.set_name(
-      absl::StrCat("grpc/server?xds.resource.listening_address=",
-                   ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()));
-  auto* socket_address = listener.mutable_address()->mutable_socket_address();
-  socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1");
-  socket_address->set_port_value(backends_[0]->port());
-  auto* filter_chain = listener.add_filter_chains();
-  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
-      HttpConnectionManager());
-  auto* transport_socket = filter_chain->mutable_transport_socket();
-  transport_socket->set_name("envoy.transport_sockets.tls");
-  DownstreamTlsContext downstream_tls_context;
-  downstream_tls_context.mutable_common_tls_context()
-      ->mutable_tls_certificate_provider_instance()
-      ->set_instance_name("fake_plugin1");
-  downstream_tls_context.set_ocsp_staple_policy(
-      envoy::extensions::transport_sockets::tls::v3::
-          DownstreamTlsContext_OcspStaplePolicy_STRICT_STAPLING);
-  transport_socket->mutable_typed_config()->PackFrom(downstream_tls_context);
-  balancers_[0]->ads_service()->SetLdsResource(listener);
-  ASSERT_TRUE(WaitForLdsNack(StatusCode::DEADLINE_EXCEEDED))
-      << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->lds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr(
-                  "ocsp_staple_policy: Only LENIENT_STAPLING supported"));
-}
-
-TEST_P(
-    XdsServerSecurityTest,
-    NacksRequiringClientCertificateWithoutValidationCertificateProviderInstance) {
-  Listener listener;
-  listener.set_name(
-      absl::StrCat("grpc/server?xds.resource.listening_address=",
-                   ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()));
-  auto* socket_address = listener.mutable_address()->mutable_socket_address();
-  socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1");
-  socket_address->set_port_value(backends_[0]->port());
-  auto* filter_chain = listener.add_filter_chains();
-  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
-      HttpConnectionManager());
-  auto* transport_socket = filter_chain->mutable_transport_socket();
-  transport_socket->set_name("envoy.transport_sockets.tls");
-  DownstreamTlsContext downstream_tls_context;
-  downstream_tls_context.mutable_common_tls_context()
-      ->mutable_tls_certificate_provider_instance()
-      ->set_instance_name("fake_plugin1");
-  downstream_tls_context.mutable_require_client_certificate()->set_value(true);
-  transport_socket->mutable_typed_config()->PackFrom(downstream_tls_context);
-  balancers_[0]->ads_service()->SetLdsResource(listener);
-  ASSERT_TRUE(WaitForLdsNack(StatusCode::DEADLINE_EXCEEDED))
-      << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->lds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr(
-                  "TLS configuration requires client certificates but no "
-                  "certificate provider instance specified for validation."));
-}
-
-TEST_P(XdsServerSecurityTest,
-       NacksTlsConfigurationWithoutIdentityProviderInstance) {
-  Listener listener;
-  listener.set_name(
-      absl::StrCat("grpc/server?xds.resource.listening_address=",
-                   ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()));
-  auto* socket_address = listener.mutable_address()->mutable_socket_address();
-  socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1");
-  socket_address->set_port_value(backends_[0]->port());
-  auto* filter_chain = listener.add_filter_chains();
-  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
-      HttpConnectionManager());
-  auto* transport_socket = filter_chain->mutable_transport_socket();
-  transport_socket->set_name("envoy.transport_sockets.tls");
-  DownstreamTlsContext downstream_tls_context;
-  transport_socket->mutable_typed_config()->PackFrom(downstream_tls_context);
-  balancers_[0]->ads_service()->SetLdsResource(listener);
-  ASSERT_TRUE(WaitForLdsNack(StatusCode::DEADLINE_EXCEEDED))
-      << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->lds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr("TLS configuration provided but no "
-                                   "tls_certificate_provider_instance found."));
-}
-
-TEST_P(XdsServerSecurityTest, NacksMatchSubjectAltNames) {
-  Listener listener;
-  listener.set_name(
-      absl::StrCat("grpc/server?xds.resource.listening_address=",
-                   ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()));
-  auto* socket_address = listener.mutable_address()->mutable_socket_address();
-  socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1");
-  socket_address->set_port_value(backends_[0]->port());
-  auto* filter_chain = listener.add_filter_chains();
-  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
-      HttpConnectionManager());
-  auto* transport_socket = filter_chain->mutable_transport_socket();
-  transport_socket->set_name("envoy.transport_sockets.tls");
-  DownstreamTlsContext downstream_tls_context;
-  downstream_tls_context.mutable_common_tls_context()
-      ->mutable_tls_certificate_provider_instance()
-      ->set_instance_name("fake_plugin1");
-  downstream_tls_context.mutable_common_tls_context()
-      ->mutable_validation_context()
-      ->add_match_subject_alt_names()
-      ->set_exact("*.test.google.fr");
-  transport_socket->mutable_typed_config()->PackFrom(downstream_tls_context);
-  balancers_[0]->ads_service()->SetLdsResource(listener);
-  ASSERT_TRUE(WaitForLdsNack(StatusCode::DEADLINE_EXCEEDED))
-      << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->lds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(
-      response_state.error_message,
-      ::testing::HasSubstr("match_subject_alt_names not supported on servers"));
-}
-
-TEST_P(XdsServerSecurityTest, UnknownIdentityCertificateProvider) {
-  SetLdsUpdate("", "", "unknown", "", false);
-  SendRpc([this]() { return CreateTlsChannel(); }, {}, {},
-          true /* test_expects_failure */);
-  ASSERT_TRUE(WaitForLdsNack(StatusCode::DEADLINE_EXCEEDED))
-      << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->lds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr(
-                  "Unrecognized certificate provider instance name: unknown"));
-}
-
-TEST_P(XdsServerSecurityTest, UnknownRootCertificateProvider) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  SetLdsUpdate("unknown", "", "fake_plugin1", "", false);
-  ASSERT_TRUE(WaitForLdsNack(StatusCode::DEADLINE_EXCEEDED))
-      << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->lds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr(
-                  "Unrecognized certificate provider instance name: unknown"));
-}
-
-TEST_P(XdsServerSecurityTest,
-       TestDeprecateTlsCertificateCertificateProviderInstanceField) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  Listener listener;
-  listener.set_name(absl::StrCat(
-      ipv6_only_ ? "grpc/server?xds.resource.listening_address=[::1]:"
-                 : "grpc/server?xds.resource.listening_address=127.0.0.1:",
-      backends_[0]->port()));
-  listener.mutable_address()->mutable_socket_address()->set_address(
-      ipv6_only_ ? "[::1]" : "127.0.0.1");
-  listener.mutable_address()->mutable_socket_address()->set_port_value(
-      backends_[0]->port());
-  auto* filter_chain = listener.add_filter_chains();
-  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
-      HttpConnectionManager());
-  auto* transport_socket = filter_chain->mutable_transport_socket();
-  transport_socket->set_name("envoy.transport_sockets.tls");
-  DownstreamTlsContext downstream_tls_context;
-  downstream_tls_context.mutable_common_tls_context()
-      ->mutable_tls_certificate_certificate_provider_instance()
-      ->set_instance_name("fake_plugin1");
-  transport_socket->mutable_typed_config()->PackFrom(downstream_tls_context);
-  balancers_[0]->ads_service()->SetLdsResource(listener);
-  SendRpc([this]() { return CreateTlsChannel(); },
-          server_authenticated_identity_, {});
-}
-
-TEST_P(XdsServerSecurityTest, CertificatesNotAvailable) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map;
-  g_fake1_cert_data_map = &fake1_cert_map;
-  SetLdsUpdate("fake_plugin1", "", "fake_plugin1", "", true);
-  SendRpc([this]() { return CreateMtlsChannel(); }, {}, {},
-          true /* test_expects_failure */);
-}
-
-TEST_P(XdsServerSecurityTest, TestMtls) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  SetLdsUpdate("fake_plugin1", "", "fake_plugin1", "", true);
-  SendRpc([this]() { return CreateMtlsChannel(); },
-          server_authenticated_identity_, client_authenticated_identity_);
-}
-
-TEST_P(XdsServerSecurityTest, TestMtlsWithRootPluginUpdate) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  FakeCertificateProvider::CertDataMap fake2_cert_map = {
-      {"", {bad_root_cert_, bad_identity_pair_}}};
-  g_fake2_cert_data_map = &fake2_cert_map;
-  SetLdsUpdate("fake_plugin1", "", "fake_plugin1", "", true);
-  SendRpc([this]() { return CreateMtlsChannel(); },
-          server_authenticated_identity_, client_authenticated_identity_);
-  SetLdsUpdate("fake_plugin2", "", "fake_plugin1", "", true);
-  SendRpc([this]() { return CreateMtlsChannel(); }, {}, {},
-          true /* test_expects_failure */);
-}
-
-TEST_P(XdsServerSecurityTest, TestMtlsWithIdentityPluginUpdate) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  FakeCertificateProvider::CertDataMap fake2_cert_map = {
-      {"", {root_cert_, identity_pair_2_}}};
-  g_fake2_cert_data_map = &fake2_cert_map;
-  SetLdsUpdate("fake_plugin1", "", "fake_plugin1", "", true);
-  SendRpc([this]() { return CreateMtlsChannel(); },
-          server_authenticated_identity_, client_authenticated_identity_);
-  SetLdsUpdate("fake_plugin1", "", "fake_plugin2", "", true);
-  SendRpc([this]() { return CreateMtlsChannel(); },
-          server_authenticated_identity_2_, client_authenticated_identity_);
-}
-
-TEST_P(XdsServerSecurityTest, TestMtlsWithBothPluginsUpdated) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  FakeCertificateProvider::CertDataMap fake2_cert_map = {
-      {"good", {root_cert_, identity_pair_2_}},
-      {"", {bad_root_cert_, bad_identity_pair_}}};
-  g_fake2_cert_data_map = &fake2_cert_map;
-  SetLdsUpdate("fake_plugin2", "", "fake_plugin2", "", true);
-  SendRpc([this]() { return CreateMtlsChannel(); }, {}, {},
-          true /* test_expects_failure */);
-  SetLdsUpdate("fake_plugin1", "", "fake_plugin1", "", true);
-  SendRpc([this]() { return CreateMtlsChannel(); },
-          server_authenticated_identity_, client_authenticated_identity_);
-  SetLdsUpdate("fake_plugin2", "good", "fake_plugin2", "good", true);
-  SendRpc([this]() { return CreateMtlsChannel(); },
-          server_authenticated_identity_2_, client_authenticated_identity_);
-}
-
-TEST_P(XdsServerSecurityTest, TestMtlsWithRootCertificateNameUpdate) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}},
-      {"bad", {bad_root_cert_, bad_identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  SetLdsUpdate("fake_plugin1", "", "fake_plugin1", "", true);
-  SendRpc([this]() { return CreateMtlsChannel(); },
-          server_authenticated_identity_, client_authenticated_identity_);
-  SetLdsUpdate("fake_plugin1", "bad", "fake_plugin1", "", true);
-  SendRpc([this]() { return CreateMtlsChannel(); }, {}, {},
-          true /* test_expects_failure */);
-}
-
-TEST_P(XdsServerSecurityTest, TestMtlsWithIdentityCertificateNameUpdate) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}},
-      {"good", {root_cert_, identity_pair_2_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  SetLdsUpdate("fake_plugin1", "", "fake_plugin1", "", true);
-  SendRpc([this]() { return CreateMtlsChannel(); },
-          server_authenticated_identity_, client_authenticated_identity_);
-  SetLdsUpdate("fake_plugin1", "", "fake_plugin1", "good", true);
-  SendRpc([this]() { return CreateMtlsChannel(); },
-          server_authenticated_identity_2_, client_authenticated_identity_);
-}
-
-TEST_P(XdsServerSecurityTest, TestMtlsWithBothCertificateNamesUpdated) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}},
-      {"good", {root_cert_, identity_pair_2_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  SetLdsUpdate("fake_plugin1", "", "fake_plugin1", "", true);
-  SendRpc([this]() { return CreateMtlsChannel(); },
-          server_authenticated_identity_, client_authenticated_identity_);
-  SetLdsUpdate("fake_plugin1", "good", "fake_plugin1", "good", true);
-  SendRpc([this]() { return CreateMtlsChannel(); },
-          server_authenticated_identity_2_, client_authenticated_identity_);
-}
-
-TEST_P(XdsServerSecurityTest, TestMtlsNotRequiringButProvidingClientCerts) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  SetLdsUpdate("fake_plugin1", "", "fake_plugin1", "", false);
-  SendRpc([this]() { return CreateMtlsChannel(); },
-          server_authenticated_identity_, client_authenticated_identity_);
-}
-
-TEST_P(XdsServerSecurityTest, TestMtlsNotRequiringAndNotProvidingClientCerts) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  SetLdsUpdate("fake_plugin1", "", "fake_plugin1", "", false);
-  SendRpc([this]() { return CreateTlsChannel(); },
-          server_authenticated_identity_, {});
-}
-
-TEST_P(XdsServerSecurityTest, TestTls) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  SetLdsUpdate("", "", "fake_plugin1", "", false);
-  SendRpc([this]() { return CreateTlsChannel(); },
-          server_authenticated_identity_, {});
-}
-
-TEST_P(XdsServerSecurityTest, TestTlsWithIdentityPluginUpdate) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  FakeCertificateProvider::CertDataMap fake2_cert_map = {
-      {"", {root_cert_, identity_pair_2_}}};
-  g_fake2_cert_data_map = &fake2_cert_map;
-  SetLdsUpdate("", "", "fake_plugin1", "", false);
-  SendRpc([this]() { return CreateTlsChannel(); },
-          server_authenticated_identity_, {});
-  SetLdsUpdate("", "", "fake_plugin2", "", false);
-  SendRpc([this]() { return CreateTlsChannel(); },
-          server_authenticated_identity_2_, {});
-}
-
-TEST_P(XdsServerSecurityTest, TestTlsWithIdentityCertificateNameUpdate) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}},
-      {"good", {root_cert_, identity_pair_2_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  SetLdsUpdate("", "", "fake_plugin1", "", false);
-  SendRpc([this]() { return CreateTlsChannel(); },
-          server_authenticated_identity_, {});
-  SetLdsUpdate("", "", "fake_plugin1", "good", false);
-  SendRpc([this]() { return CreateTlsChannel(); },
-          server_authenticated_identity_2_, {});
-}
-
-TEST_P(XdsServerSecurityTest, TestFallback) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  SetLdsUpdate("", "", "", "", false);
-  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {});
-}
-
-TEST_P(XdsServerSecurityTest, TestMtlsToTls) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  SetLdsUpdate("fake_plugin1", "", "fake_plugin1", "", true);
-  SendRpc([this]() { return CreateTlsChannel(); }, {}, {},
-          true /* test_expects_failure */);
-  SetLdsUpdate("", "", "fake_plugin1", "", false);
-  SendRpc([this]() { return CreateTlsChannel(); },
-          server_authenticated_identity_, {});
-}
-
-TEST_P(XdsServerSecurityTest, TestTlsToMtls) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  SetLdsUpdate("", "", "fake_plugin1", "", false);
-  SendRpc([this]() { return CreateTlsChannel(); },
-          server_authenticated_identity_, {});
-  SetLdsUpdate("fake_plugin1", "", "fake_plugin1", "", true);
-  SendRpc([this]() { return CreateTlsChannel(); }, {}, {},
-          true /* test_expects_failure */);
-}
-
-TEST_P(XdsServerSecurityTest, TestMtlsToFallback) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  SetLdsUpdate("fake_plugin1", "", "fake_plugin1", "", false);
-  SendRpc([this]() { return CreateMtlsChannel(); },
-          server_authenticated_identity_, client_authenticated_identity_);
-  SetLdsUpdate("", "", "", "", false);
-  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {});
-}
-
-TEST_P(XdsServerSecurityTest, TestFallbackToMtls) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  SetLdsUpdate("", "", "", "", false);
-  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {});
-  SetLdsUpdate("fake_plugin1", "", "fake_plugin1", "", true);
-  SendRpc([this]() { return CreateMtlsChannel(); },
-          server_authenticated_identity_, client_authenticated_identity_);
-}
-
-TEST_P(XdsServerSecurityTest, TestTlsToFallback) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  SetLdsUpdate("", "", "fake_plugin1", "", false);
-  SendRpc([this]() { return CreateTlsChannel(); },
-          server_authenticated_identity_, {});
-  SetLdsUpdate("", "", "", "", false);
-  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {});
-}
-
-TEST_P(XdsServerSecurityTest, TestFallbackToTls) {
-  FakeCertificateProvider::CertDataMap fake1_cert_map = {
-      {"", {root_cert_, identity_pair_}}};
-  g_fake1_cert_data_map = &fake1_cert_map;
-  SetLdsUpdate("", "", "", "", false);
-  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {});
-  SetLdsUpdate("", "", "fake_plugin1", "", false);
-  SendRpc([this]() { return CreateTlsChannel(); },
-          server_authenticated_identity_, {});
-}
-
-class XdsEnabledServerStatusNotificationTest : public XdsServerSecurityTest {
- protected:
-  void SetValidLdsUpdate() { SetLdsUpdate("", "", "", "", false); }
-
-  void SetInvalidLdsUpdate() {
-    Listener listener;
-    listener.set_name(absl::StrCat(
-        "grpc/server?xds.resource.listening_address=",
-        ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()));
-    auto* socket_address = listener.mutable_address()->mutable_socket_address();
-    socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1");
-    socket_address->set_port_value(backends_[0]->port());
-    balancers_[0]->ads_service()->SetLdsResource(listener);
-  }
-
-  void UnsetLdsUpdate() {
-    balancers_[0]->ads_service()->UnsetResource(
-        kLdsTypeUrl, absl::StrCat("grpc/server?xds.resource.listening_address=",
-                                  ipv6_only_ ? "[::1]:" : "127.0.0.1:",
-                                  backends_[0]->port()));
-  }
-};
-
-TEST_P(XdsEnabledServerStatusNotificationTest, ServingStatus) {
-  SetValidLdsUpdate();
-  backends_[0]->notifier()->WaitOnServingStatusChange(
-      absl::StrCat(ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()),
-      grpc::StatusCode::OK);
-  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {});
-}
-
-TEST_P(XdsEnabledServerStatusNotificationTest, NotServingStatus) {
-  SetInvalidLdsUpdate();
-  backends_[0]->notifier()->WaitOnServingStatusChange(
-      absl::StrCat(ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()),
-      grpc::StatusCode::UNAVAILABLE);
-  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {},
-          true /* test_expects_failure */);
-}
-
-TEST_P(XdsEnabledServerStatusNotificationTest, ErrorUpdateWhenAlreadyServing) {
-  SetValidLdsUpdate();
-  backends_[0]->notifier()->WaitOnServingStatusChange(
-      absl::StrCat(ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()),
-      grpc::StatusCode::OK);
-  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {});
-  // Invalid update does not lead to a change in the serving status.
-  SetInvalidLdsUpdate();
-  do {
-    SendRpc([this]() { return CreateInsecureChannel(); }, {}, {});
-  } while (balancers_[0]->ads_service()->lds_response_state().state ==
-           AdsServiceImpl::ResponseState::SENT);
-  backends_[0]->notifier()->WaitOnServingStatusChange(
-      absl::StrCat(ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()),
-      grpc::StatusCode::OK);
-  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {});
-}
-
-TEST_P(XdsEnabledServerStatusNotificationTest,
-       NotServingStatusToServingStatusTransition) {
-  SetInvalidLdsUpdate();
-  backends_[0]->notifier()->WaitOnServingStatusChange(
-      absl::StrCat(ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()),
-      grpc::StatusCode::UNAVAILABLE);
-  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {},
-          true /* test_expects_failure */);
-  // Send a valid LDS update to change to serving status
-  SetValidLdsUpdate();
-  backends_[0]->notifier()->WaitOnServingStatusChange(
-      absl::StrCat(ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()),
-      grpc::StatusCode::OK);
-  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {});
-}
-
-// This test verifies that the resource getting deleted when already serving
-// results in future connections being dropped.
-TEST_P(XdsEnabledServerStatusNotificationTest,
-       ServingStatusToNonServingStatusTransition) {
-  SetValidLdsUpdate();
-  backends_[0]->notifier()->WaitOnServingStatusChange(
-      absl::StrCat(ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()),
-      grpc::StatusCode::OK);
-  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {});
-  // Deleting the resource should result in a non-serving status.
-  UnsetLdsUpdate();
-  backends_[0]->notifier()->WaitOnServingStatusChange(
-      absl::StrCat(ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()),
-      grpc::StatusCode::NOT_FOUND);
-  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {},
-          true /* test_expects_failure */);
-}
-
-TEST_P(XdsEnabledServerStatusNotificationTest, RepeatedServingStatusChanges) {
-  for (int i = 0; i < 5; i++) {
-    // Send a valid LDS update to get the server to start listening
-    SetValidLdsUpdate();
-    backends_[0]->notifier()->WaitOnServingStatusChange(
-        absl::StrCat(ipv6_only_ ? "[::1]:" : "127.0.0.1:",
-                     backends_[0]->port()),
-        grpc::StatusCode::OK);
-    SendRpc([this]() { return CreateInsecureChannel(); }, {}, {});
-    // Deleting the resource will make the server start rejecting connections
-    UnsetLdsUpdate();
-    backends_[0]->notifier()->WaitOnServingStatusChange(
-        absl::StrCat(ipv6_only_ ? "[::1]:" : "127.0.0.1:",
-                     backends_[0]->port()),
-        grpc::StatusCode::NOT_FOUND);
-    SendRpc([this]() { return CreateInsecureChannel(); }, {}, {},
-            true /* test_expects_failure */);
-  }
-}
-
-TEST_P(XdsEnabledServerStatusNotificationTest, ExistingRpcsOnResourceDeletion) {
-  // Send a valid LDS update to get the server to start listening
-  SetValidLdsUpdate();
-  backends_[0]->notifier()->WaitOnServingStatusChange(
-      absl::StrCat(ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()),
-      grpc::StatusCode::OK);
-  constexpr int kNumChannels = 10;
-  struct StreamingRpc {
-    std::shared_ptr<Channel> channel;
-    std::unique_ptr<grpc::testing::EchoTestService::Stub> stub;
-    ClientContext context;
-    std::unique_ptr<ClientReaderWriter<EchoRequest, EchoResponse>> stream;
-  } streaming_rpcs[kNumChannels];
-  EchoRequest request;
-  EchoResponse response;
-  request.set_message("Hello");
-  for (int i = 0; i < kNumChannels; i++) {
-    streaming_rpcs[i].channel = CreateInsecureChannel();
-    streaming_rpcs[i].stub =
-        grpc::testing::EchoTestService::NewStub(streaming_rpcs[i].channel);
-    streaming_rpcs[i].context.set_wait_for_ready(true);
-    streaming_rpcs[i].stream =
-        streaming_rpcs[i].stub->BidiStream(&streaming_rpcs[i].context);
-    EXPECT_TRUE(streaming_rpcs[i].stream->Write(request));
-    streaming_rpcs[i].stream->Read(&response);
-    EXPECT_EQ(request.message(), response.message());
-  }
-  // Deleting the resource will make the server start rejecting connections
-  UnsetLdsUpdate();
-  backends_[0]->notifier()->WaitOnServingStatusChange(
-      absl::StrCat(ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()),
-      grpc::StatusCode::NOT_FOUND);
-  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {},
-          true /* test_expects_failure */);
-  for (int i = 0; i < kNumChannels; i++) {
-    EXPECT_TRUE(streaming_rpcs[i].stream->Write(request));
-    streaming_rpcs[i].stream->Read(&response);
-    EXPECT_EQ(request.message(), response.message());
-    EXPECT_TRUE(streaming_rpcs[i].stream->WritesDone());
-    auto status = streaming_rpcs[i].stream->Finish();
-    EXPECT_TRUE(status.ok())
-        << status.error_message() << ", " << status.error_details() << ", "
-        << streaming_rpcs[i].context.debug_error_string();
-    // New RPCs on the existing channels should fail.
-    ClientContext new_context;
-    new_context.set_deadline(grpc_timeout_milliseconds_to_deadline(1000));
-    EXPECT_FALSE(
-        streaming_rpcs[i].stub->Echo(&new_context, request, &response).ok());
-  }
-}
-
-using XdsServerFilterChainMatchTest = XdsServerSecurityTest;
-
-TEST_P(XdsServerFilterChainMatchTest,
-       DefaultFilterChainUsedWhenNoFilterChainMentioned) {
-  Listener listener;
-  listener.set_name(
-      absl::StrCat("grpc/server?xds.resource.listening_address=",
-                   ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()));
-  auto* socket_address = listener.mutable_address()->mutable_socket_address();
-  socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1");
-  socket_address->set_port_value(backends_[0]->port());
-  listener.mutable_default_filter_chain()
-      ->add_filters()
-      ->mutable_typed_config()
-      ->PackFrom(HttpConnectionManager());
-  balancers_[0]->ads_service()->SetLdsResource(listener);
-  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {});
-}
-
-TEST_P(XdsServerFilterChainMatchTest,
-       DefaultFilterChainUsedWhenOtherFilterChainsDontMatch) {
-  Listener listener;
-  listener.set_name(
-      absl::StrCat("grpc/server?xds.resource.listening_address=",
-                   ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()));
-  auto* socket_address = listener.mutable_address()->mutable_socket_address();
-  socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1");
-  socket_address->set_port_value(backends_[0]->port());
-  // Add a filter chain that will never get matched
-  auto* filter_chain = listener.add_filter_chains();
-  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
-      HttpConnectionManager());
-  filter_chain->mutable_filter_chain_match()
-      ->mutable_destination_port()
-      ->set_value(8080);
-  // Add default filter chain that should get used
-  listener.mutable_default_filter_chain()
-      ->add_filters()
-      ->mutable_typed_config()
-      ->PackFrom(HttpConnectionManager());
-  balancers_[0]->ads_service()->SetLdsResource(listener);
-  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {});
-}
-
-TEST_P(XdsServerFilterChainMatchTest,
-       FilterChainsWithDestinationPortDontMatch) {
-  Listener listener;
-  listener.set_name(
-      absl::StrCat("grpc/server?xds.resource.listening_address=",
-                   ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()));
-  auto* socket_address = listener.mutable_address()->mutable_socket_address();
-  socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1");
-  socket_address->set_port_value(backends_[0]->port());
-  // Add filter chain with destination port that should never get matched
-  auto* filter_chain = listener.add_filter_chains();
-  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
-      HttpConnectionManager());
-  filter_chain->mutable_filter_chain_match()
-      ->mutable_destination_port()
-      ->set_value(8080);
-  balancers_[0]->ads_service()->SetLdsResource(listener);
-  // RPC should fail since no matching filter chain was found and no default
-  // filter chain is configured.
-  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {},
-          true /* test_expects_failure */);
-}
-
-TEST_P(XdsServerFilterChainMatchTest, FilterChainsWithServerNamesDontMatch) {
-  Listener listener;
-  listener.set_name(
-      absl::StrCat("grpc/server?xds.resource.listening_address=",
-                   ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()));
-  auto* socket_address = listener.mutable_address()->mutable_socket_address();
-  socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1");
-  socket_address->set_port_value(backends_[0]->port());
-  // Add filter chain with server name that should never get matched
-  auto* filter_chain = listener.add_filter_chains();
-  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
-      HttpConnectionManager());
-  filter_chain->mutable_filter_chain_match()->add_server_names("server_name");
-  balancers_[0]->ads_service()->SetLdsResource(listener);
-  // RPC should fail since no matching filter chain was found and no default
-  // filter chain is configured.
-  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {},
-          true /* test_expects_failure */);
-}
-
-TEST_P(XdsServerFilterChainMatchTest,
-       FilterChainsWithTransportProtocolsOtherThanRawBufferDontMatch) {
-  Listener listener;
-  listener.set_name(
-      absl::StrCat("grpc/server?xds.resource.listening_address=",
-                   ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()));
-  auto* socket_address = listener.mutable_address()->mutable_socket_address();
-  socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1");
-  socket_address->set_port_value(backends_[0]->port());
-  // Add filter chain with transport protocol "tls" that should never match
-  auto* filter_chain = listener.add_filter_chains();
-  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
-      HttpConnectionManager());
-  filter_chain->mutable_filter_chain_match()->set_transport_protocol("tls");
-  balancers_[0]->ads_service()->SetLdsResource(listener);
-  // RPC should fail since no matching filter chain was found and no default
-  // filter chain is configured.
-  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {},
-          true /* test_expects_failure */);
-}
-
-TEST_P(XdsServerFilterChainMatchTest,
-       FilterChainsWithApplicationProtocolsDontMatch) {
-  Listener listener;
-  listener.set_name(
-      absl::StrCat("grpc/server?xds.resource.listening_address=",
-                   ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()));
-  auto* socket_address = listener.mutable_address()->mutable_socket_address();
-  socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1");
-  socket_address->set_port_value(backends_[0]->port());
-  // Add filter chain with application protocol that should never get matched
-  auto* filter_chain = listener.add_filter_chains();
-  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
-      HttpConnectionManager());
-  filter_chain->mutable_filter_chain_match()->add_application_protocols("h2");
-  balancers_[0]->ads_service()->SetLdsResource(listener);
-  // RPC should fail since no matching filter chain was found and no default
-  // filter chain is configured.
-  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {},
-          true /* test_expects_failure */);
-}
-
-TEST_P(XdsServerFilterChainMatchTest,
-       FilterChainsWithTransportProtocolRawBufferIsPreferred) {
-  Listener listener;
-  listener.set_name(
-      absl::StrCat("grpc/server?xds.resource.listening_address=",
-                   ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()));
-  auto* socket_address = listener.mutable_address()->mutable_socket_address();
-  socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1");
-  socket_address->set_port_value(backends_[0]->port());
-  // Add filter chain with "raw_buffer" transport protocol
-  auto* filter_chain = listener.add_filter_chains();
-  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
-      HttpConnectionManager());
-  filter_chain->mutable_filter_chain_match()->set_transport_protocol(
-      "raw_buffer");
-  // Add another filter chain with no transport protocol set but application
-  // protocol set (fails match)
-  filter_chain = listener.add_filter_chains();
-  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
-      HttpConnectionManager());
-  filter_chain->mutable_filter_chain_match()->add_application_protocols("h2");
-  balancers_[0]->ads_service()->SetLdsResource(listener);
-  // A successful RPC proves that filter chains that mention "raw_buffer" as
-  // the transport protocol are chosen as the best match in the round.
-  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {});
-}
-
-TEST_P(XdsServerFilterChainMatchTest,
-       FilterChainsWithMoreSpecificDestinationPrefixRangesArePreferred) {
-  Listener listener;
-  listener.set_name(
-      absl::StrCat("grpc/server?xds.resource.listening_address=",
-                   ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()));
-  auto* socket_address = listener.mutable_address()->mutable_socket_address();
-  socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1");
-  socket_address->set_port_value(backends_[0]->port());
-  // Add filter chain with prefix range (length 4 and 16) but with server name
-  // mentioned. (Prefix range is matched first.)
-  auto* filter_chain = listener.add_filter_chains();
-  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
-      HttpConnectionManager());
-  auto* prefix_range =
-      filter_chain->mutable_filter_chain_match()->add_prefix_ranges();
-  prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1");
-  prefix_range->mutable_prefix_len()->set_value(4);
-  prefix_range =
-      filter_chain->mutable_filter_chain_match()->add_prefix_ranges();
-  prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1");
-  prefix_range->mutable_prefix_len()->set_value(16);
-  filter_chain->mutable_filter_chain_match()->add_server_names("server_name");
-  // Add filter chain with two prefix ranges (length 8 and 24). Since 24 is
-  // the highest match, it should be chosen.
-  filter_chain = listener.add_filter_chains();
-  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
-      HttpConnectionManager());
-  prefix_range =
-      filter_chain->mutable_filter_chain_match()->add_prefix_ranges();
-  prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1");
-  prefix_range->mutable_prefix_len()->set_value(8);
-  prefix_range =
-      filter_chain->mutable_filter_chain_match()->add_prefix_ranges();
-  prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1");
-  prefix_range->mutable_prefix_len()->set_value(24);
-  // Add another filter chain with a non-matching prefix range (with length
-  // 30)
-  filter_chain = listener.add_filter_chains();
-  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
-      HttpConnectionManager());
-  prefix_range =
-      filter_chain->mutable_filter_chain_match()->add_prefix_ranges();
-  prefix_range->set_address_prefix("192.168.1.1");
-  prefix_range->mutable_prefix_len()->set_value(30);
-  filter_chain->mutable_filter_chain_match()->add_server_names("server_name");
-  // Add another filter chain with no prefix range mentioned
-  filter_chain = listener.add_filter_chains();
-  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
-      HttpConnectionManager());
-  filter_chain->mutable_filter_chain_match()->add_server_names("server_name");
-  balancers_[0]->ads_service()->SetLdsResource(listener);
-  // A successful RPC proves that the filter chain with the longest matching
-  // prefix range was the best match.
-  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {});
-}
-
-TEST_P(XdsServerFilterChainMatchTest,
-       FilterChainsThatMentionSourceTypeArePreferred) {
-  Listener listener;
-  listener.set_name(
-      absl::StrCat("grpc/server?xds.resource.listening_address=",
-                   ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()));
-  auto* socket_address = listener.mutable_address()->mutable_socket_address();
-  socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1");
-  socket_address->set_port_value(backends_[0]->port());
-  // Add filter chain with the local source type (best match)
-  auto* filter_chain = listener.add_filter_chains();
-  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
-      HttpConnectionManager());
-  filter_chain->mutable_filter_chain_match()->set_source_type(
-      FilterChainMatch::SAME_IP_OR_LOOPBACK);
-  // Add filter chain with the external source type but bad source port.
-  // Note that backends_[0]->port() will never be a match for the source port
-  // because it is already being used by a backend.
-  filter_chain = listener.add_filter_chains();
-  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
-      HttpConnectionManager());
-  filter_chain->mutable_filter_chain_match()->set_source_type(
-      FilterChainMatch::EXTERNAL);
-  filter_chain->mutable_filter_chain_match()->add_source_ports(
-      backends_[0]->port());
-  // Add filter chain with the default source type (ANY) but bad source port.
-  filter_chain = listener.add_filter_chains();
-  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
-      HttpConnectionManager());
-  filter_chain->mutable_filter_chain_match()->add_source_ports(
-      backends_[0]->port());
-  balancers_[0]->ads_service()->SetLdsResource(listener);
-  // A successful RPC proves that the filter chain with the longest matching
-  // prefix range was the best match.
-  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {});
-}
-
-TEST_P(XdsServerFilterChainMatchTest,
-       FilterChainsWithMoreSpecificSourcePrefixRangesArePreferred) {
-  Listener listener;
-  listener.set_name(
-      absl::StrCat("grpc/server?xds.resource.listening_address=",
-                   ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()));
-  auto* socket_address = listener.mutable_address()->mutable_socket_address();
-  socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1");
-  socket_address->set_port_value(backends_[0]->port());
-  // Add filter chain with source prefix range (length 16) but with a bad
-  // source port mentioned. (Prefix range is matched first.) Note that
-  // backends_[0]->port() will never be a match for the source port because it
-  // is already being used by a backend.
-  auto* filter_chain = listener.add_filter_chains();
-  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
-      HttpConnectionManager());
-  auto* source_prefix_range =
-      filter_chain->mutable_filter_chain_match()->add_source_prefix_ranges();
-  source_prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1");
-  source_prefix_range->mutable_prefix_len()->set_value(4);
-  source_prefix_range =
-      filter_chain->mutable_filter_chain_match()->add_source_prefix_ranges();
-  source_prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1");
-  source_prefix_range->mutable_prefix_len()->set_value(16);
-  filter_chain->mutable_filter_chain_match()->add_source_ports(
-      backends_[0]->port());
-  // Add filter chain with two source prefix ranges (length 8 and 24). Since
-  // 24 is the highest match, it should be chosen.
-  filter_chain = listener.add_filter_chains();
-  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
-      HttpConnectionManager());
-  source_prefix_range =
-      filter_chain->mutable_filter_chain_match()->add_source_prefix_ranges();
-  source_prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1");
-  source_prefix_range->mutable_prefix_len()->set_value(8);
-  source_prefix_range =
-      filter_chain->mutable_filter_chain_match()->add_source_prefix_ranges();
-  source_prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1");
-  source_prefix_range->mutable_prefix_len()->set_value(24);
-  // Add another filter chain with a non-matching source prefix range (with
-  // length 30) and bad source port
-  filter_chain = listener.add_filter_chains();
-  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
-      HttpConnectionManager());
-  source_prefix_range =
-      filter_chain->mutable_filter_chain_match()->add_source_prefix_ranges();
-  source_prefix_range->set_address_prefix("192.168.1.1");
-  source_prefix_range->mutable_prefix_len()->set_value(30);
-  filter_chain->mutable_filter_chain_match()->add_source_ports(
-      backends_[0]->port());
-  // Add another filter chain with no source prefix range mentioned and bad
-  // source port
-  filter_chain = listener.add_filter_chains();
-  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
-      HttpConnectionManager());
-  filter_chain->mutable_filter_chain_match()->add_source_ports(
-      backends_[0]->port());
-  balancers_[0]->ads_service()->SetLdsResource(listener);
-  // A successful RPC proves that the filter chain with the longest matching
-  // source prefix range was the best match.
-  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {});
-}
-
-TEST_P(XdsServerFilterChainMatchTest,
-       FilterChainsWithMoreSpecificSourcePortArePreferred) {
-  Listener listener;
-  listener.set_name(
-      absl::StrCat("grpc/server?xds.resource.listening_address=",
-                   ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()));
-  auto* socket_address = listener.mutable_address()->mutable_socket_address();
-  socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1");
-  socket_address->set_port_value(backends_[0]->port());
-  auto* filter_chain = listener.add_filter_chains();
-  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
-      HttpConnectionManager());
-  // Since we don't know which port will be used by the channel, just add all
-  // ports except for 0.
-  for (int i = 1; i < 65536; i++) {
-    filter_chain->mutable_filter_chain_match()->add_source_ports(i);
-  }
-  // Add another filter chain with no source port mentioned with a bad
-  // DownstreamTlsContext configuration.
-  filter_chain = listener.add_filter_chains();
-  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
-      HttpConnectionManager());
-  auto* transport_socket = filter_chain->mutable_transport_socket();
-  transport_socket->set_name("envoy.transport_sockets.tls");
-  DownstreamTlsContext downstream_tls_context;
-  downstream_tls_context.mutable_common_tls_context()
-      ->mutable_tls_certificate_provider_instance()
-      ->set_instance_name("fake_plugin1");
-  transport_socket->mutable_typed_config()->PackFrom(downstream_tls_context);
-  balancers_[0]->ads_service()->SetLdsResource(listener);
-  // A successful RPC proves that the filter chain with matching source port
-  // was chosen.
-  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {});
-}
-
-TEST_P(XdsServerFilterChainMatchTest, DuplicateMatchNacked) {
-  Listener listener;
-  listener.set_name(
-      absl::StrCat("grpc/server?xds.resource.listening_address=",
-                   ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()));
-  auto* socket_address = listener.mutable_address()->mutable_socket_address();
-  socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1");
-  socket_address->set_port_value(backends_[0]->port());
-  // Add filter chain
-  auto* filter_chain = listener.add_filter_chains();
-  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
-      HttpConnectionManager());
-  // Add a duplicate filter chain
-  filter_chain = listener.add_filter_chains();
-  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
-      HttpConnectionManager());
-  balancers_[0]->ads_service()->SetLdsResource(listener);
-  ASSERT_TRUE(WaitForLdsNack(StatusCode::DEADLINE_EXCEEDED))
-      << "timed out waiting for NACK";
-  EXPECT_THAT(
-      balancers_[0]->ads_service()->lds_response_state().error_message,
-      ::testing::HasSubstr(
-          "Duplicate matching rules detected when adding filter chain: {}"));
-}
-
-TEST_P(XdsServerFilterChainMatchTest, DuplicateMatchOnPrefixRangesNacked) {
-  Listener listener;
-  listener.set_name(
-      absl::StrCat("grpc/server?xds.resource.listening_address=",
-                   ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()));
-  auto* socket_address = listener.mutable_address()->mutable_socket_address();
-  socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1");
-  socket_address->set_port_value(backends_[0]->port());
-  // Add filter chain with prefix range
-  auto* filter_chain = listener.add_filter_chains();
-  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
-      HttpConnectionManager());
-  auto* prefix_range =
-      filter_chain->mutable_filter_chain_match()->add_prefix_ranges();
-  prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1");
-  prefix_range->mutable_prefix_len()->set_value(16);
-  prefix_range =
-      filter_chain->mutable_filter_chain_match()->add_prefix_ranges();
-  prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1");
-  prefix_range->mutable_prefix_len()->set_value(24);
-  // Add a filter chain with a duplicate prefix range entry
-  filter_chain = listener.add_filter_chains();
-  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
-      HttpConnectionManager());
-  prefix_range =
-      filter_chain->mutable_filter_chain_match()->add_prefix_ranges();
-  prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1");
-  prefix_range->mutable_prefix_len()->set_value(16);
-  prefix_range =
-      filter_chain->mutable_filter_chain_match()->add_prefix_ranges();
-  prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1");
-  prefix_range->mutable_prefix_len()->set_value(32);
-  balancers_[0]->ads_service()->SetLdsResource(listener);
-  ASSERT_TRUE(WaitForLdsNack(StatusCode::DEADLINE_EXCEEDED))
-      << "timed out waiting for NACK";
-  if (ipv6_only_) {
-    EXPECT_THAT(
-        balancers_[0]->ads_service()->lds_response_state().error_message,
-        ::testing::HasSubstr(
-            "Duplicate matching rules detected when adding filter chain: "
-            "{prefix_ranges={{address_prefix=[::]:0, prefix_len=16}, "
-            "{address_prefix=[::]:0, prefix_len=32}}}"));
-  } else {
-    EXPECT_THAT(
-        balancers_[0]->ads_service()->lds_response_state().error_message,
-        ::testing::HasSubstr(
-            "Duplicate matching rules detected when adding filter chain: "
-            "{prefix_ranges={{address_prefix=127.0.0.0:0, prefix_len=16}, "
-            "{address_prefix=127.0.0.1:0, prefix_len=32}}}"));
-  }
-}
-
-TEST_P(XdsServerFilterChainMatchTest, DuplicateMatchOnTransportProtocolNacked) {
-  Listener listener;
-  listener.set_name(
-      absl::StrCat("grpc/server?xds.resource.listening_address=",
-                   ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()));
-  auto* socket_address = listener.mutable_address()->mutable_socket_address();
-  socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1");
-  socket_address->set_port_value(backends_[0]->port());
-  // Add filter chain with "raw_buffer" transport protocol
-  auto* filter_chain = listener.add_filter_chains();
-  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
-      HttpConnectionManager());
-  filter_chain->mutable_filter_chain_match()->set_transport_protocol(
-      "raw_buffer");
-  // Add a duplicate filter chain with the same "raw_buffer" transport
-  // protocol entry
-  filter_chain = listener.add_filter_chains();
-  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
-      HttpConnectionManager());
-  filter_chain->mutable_filter_chain_match()->set_transport_protocol(
-      "raw_buffer");
-  balancers_[0]->ads_service()->SetLdsResource(listener);
-  ASSERT_TRUE(WaitForLdsNack(StatusCode::DEADLINE_EXCEEDED))
-      << "timed out waiting for NACK";
-  EXPECT_THAT(
-      balancers_[0]->ads_service()->lds_response_state().error_message,
-      ::testing::HasSubstr("Duplicate matching rules detected when adding "
-                           "filter chain: {transport_protocol=raw_buffer}"));
-}
-
-TEST_P(XdsServerFilterChainMatchTest, DuplicateMatchOnLocalSourceTypeNacked) {
-  Listener listener;
-  listener.set_name(
-      absl::StrCat("grpc/server?xds.resource.listening_address=",
-                   ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()));
-  auto* socket_address = listener.mutable_address()->mutable_socket_address();
-  socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1");
-  socket_address->set_port_value(backends_[0]->port());
-  // Add filter chain with the local source type
-  auto* filter_chain = listener.add_filter_chains();
-  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
-      HttpConnectionManager());
-  filter_chain->mutable_filter_chain_match()->set_source_type(
-      FilterChainMatch::SAME_IP_OR_LOOPBACK);
-  // Add a duplicate filter chain with the same local source type entry
-  filter_chain = listener.add_filter_chains();
-  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
-      HttpConnectionManager());
-  filter_chain->mutable_filter_chain_match()->set_source_type(
-      FilterChainMatch::SAME_IP_OR_LOOPBACK);
-  balancers_[0]->ads_service()->SetLdsResource(listener);
-  ASSERT_TRUE(WaitForLdsNack(StatusCode::DEADLINE_EXCEEDED))
-      << "timed out waiting for NACK";
-  EXPECT_THAT(
-      balancers_[0]->ads_service()->lds_response_state().error_message,
-      ::testing::HasSubstr("Duplicate matching rules detected when adding "
-                           "filter chain: {source_type=SAME_IP_OR_LOOPBACK}"));
-}
-
-TEST_P(XdsServerFilterChainMatchTest,
-       DuplicateMatchOnExternalSourceTypeNacked) {
-  Listener listener;
-  listener.set_name(
-      absl::StrCat("grpc/server?xds.resource.listening_address=",
-                   ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()));
-  auto* socket_address = listener.mutable_address()->mutable_socket_address();
-  socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1");
-  socket_address->set_port_value(backends_[0]->port());
-  // Add filter chain with the external source type
-  auto* filter_chain = listener.add_filter_chains();
-  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
-      HttpConnectionManager());
-  filter_chain->mutable_filter_chain_match()->set_source_type(
-      FilterChainMatch::EXTERNAL);
-  // Add a duplicate filter chain with the same external source type entry
-  filter_chain = listener.add_filter_chains();
-  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
-      HttpConnectionManager());
-  filter_chain->mutable_filter_chain_match()->set_source_type(
-      FilterChainMatch::EXTERNAL);
-  balancers_[0]->ads_service()->SetLdsResource(listener);
-  ASSERT_TRUE(WaitForLdsNack(StatusCode::DEADLINE_EXCEEDED))
-      << "timed out waiting for NACK";
-  EXPECT_THAT(
-      balancers_[0]->ads_service()->lds_response_state().error_message,
-      ::testing::HasSubstr("Duplicate matching rules detected when adding "
-                           "filter chain: {source_type=EXTERNAL}"));
-}
-
-TEST_P(XdsServerFilterChainMatchTest,
-       DuplicateMatchOnSourcePrefixRangesNacked) {
-  Listener listener;
-  listener.set_name(
-      absl::StrCat("grpc/server?xds.resource.listening_address=",
-                   ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()));
-  auto* socket_address = listener.mutable_address()->mutable_socket_address();
-  socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1");
-  socket_address->set_port_value(backends_[0]->port());
-  // Add filter chain with source prefix range
-  auto* filter_chain = listener.add_filter_chains();
-  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
-      HttpConnectionManager());
-  auto* prefix_range =
-      filter_chain->mutable_filter_chain_match()->add_source_prefix_ranges();
-  prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1");
-  prefix_range->mutable_prefix_len()->set_value(16);
-  prefix_range =
-      filter_chain->mutable_filter_chain_match()->add_source_prefix_ranges();
-  prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1");
-  prefix_range->mutable_prefix_len()->set_value(24);
-  // Add a filter chain with a duplicate source prefix range entry
-  filter_chain = listener.add_filter_chains();
-  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
-      HttpConnectionManager());
-  prefix_range =
-      filter_chain->mutable_filter_chain_match()->add_source_prefix_ranges();
-  prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1");
-  prefix_range->mutable_prefix_len()->set_value(16);
-  prefix_range =
-      filter_chain->mutable_filter_chain_match()->add_source_prefix_ranges();
-  prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1");
-  prefix_range->mutable_prefix_len()->set_value(32);
-  balancers_[0]->ads_service()->SetLdsResource(listener);
-  ASSERT_TRUE(WaitForLdsNack(StatusCode::DEADLINE_EXCEEDED))
-      << "timed out waiting for NACK";
-  if (ipv6_only_) {
-    EXPECT_THAT(
-        balancers_[0]->ads_service()->lds_response_state().error_message,
-        ::testing::HasSubstr(
-            "Duplicate matching rules detected when adding filter chain: "
-            "{source_prefix_ranges={{address_prefix=[::]:0, prefix_len=16}, "
-            "{address_prefix=[::]:0, prefix_len=32}}}"));
-  } else {
-    EXPECT_THAT(
-        balancers_[0]->ads_service()->lds_response_state().error_message,
-        ::testing::HasSubstr(
-            "Duplicate matching rules detected when adding filter chain: "
-            "{source_prefix_ranges={{address_prefix=127.0.0.0:0, "
-            "prefix_len=16}, "
-            "{address_prefix=127.0.0.1:0, prefix_len=32}}}"));
-  }
-}
-
-TEST_P(XdsServerFilterChainMatchTest, DuplicateMatchOnSourcePortNacked) {
-  Listener listener;
-  listener.set_name(
-      absl::StrCat("grpc/server?xds.resource.listening_address=",
-                   ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()));
-  auto* socket_address = listener.mutable_address()->mutable_socket_address();
-  socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1");
-  socket_address->set_port_value(backends_[0]->port());
-  // Add filter chain with the external source type
-  auto* filter_chain = listener.add_filter_chains();
-  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
-      HttpConnectionManager());
-  filter_chain->mutable_filter_chain_match()->add_source_ports(8080);
-  // Add a duplicate filter chain with the same source port entry
-  filter_chain = listener.add_filter_chains();
-  filter_chain->add_filters()->mutable_typed_config()->PackFrom(
-      HttpConnectionManager());
-  filter_chain->mutable_filter_chain_match()->add_source_ports(8080);
-  balancers_[0]->ads_service()->SetLdsResource(listener);
-  ASSERT_TRUE(WaitForLdsNack(StatusCode::DEADLINE_EXCEEDED))
-      << "timed out waiting for NACK";
-  EXPECT_THAT(
-      balancers_[0]->ads_service()->lds_response_state().error_message,
-      ::testing::HasSubstr("Duplicate matching rules detected when adding "
-                           "filter chain: {source_ports={8080}}"));
-}
-
-using EdsTest = BasicTest;
-
-// Tests that EDS client should send a NACK if the EDS update contains
-// sparse priorities.
-TEST_P(EdsTest, NacksSparsePriorityList) {
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(), kDefaultLocalityWeight, 1},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
-  ASSERT_TRUE(WaitForEdsNack()) << "timed out waiting for NACK";
-  const auto response_state =
-      balancers_[0]->ads_service()->eds_response_state();
-  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
-  EXPECT_THAT(response_state.error_message,
-              ::testing::HasSubstr("sparse priority list"));
-}
-
-// In most of our tests, we use different names for different resource
-// types, to make sure that there are no cut-and-paste errors in the code
-// that cause us to look at data for the wrong resource type.  So we add
-// this test to make sure that the EDS resource name defaults to the
-// cluster name if not specified in the CDS resource.
-TEST_P(EdsTest, EdsServiceNameDefaultsToClusterName) {
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, kDefaultClusterName));
-  Cluster cluster = default_cluster_;
-  cluster.mutable_eds_cluster_config()->clear_service_name();
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  CheckRpcSendOk();
-}
-
-class TimeoutTest : public BasicTest {
- protected:
-  void SetUp() override {
-    xds_resource_does_not_exist_timeout_ms_ = 500;
-    BasicTest::SetUp();
-  }
-};
-
-// Tests that LDS client times out when no response received.
-TEST_P(TimeoutTest, Lds) {
-  balancers_[0]->ads_service()->SetResourceIgnore(kLdsTypeUrl);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  CheckRpcSendFailure();
-}
-
-TEST_P(TimeoutTest, Rds) {
-  balancers_[0]->ads_service()->SetResourceIgnore(kRdsTypeUrl);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  CheckRpcSendFailure();
-}
-
-// Tests that CDS client times out when no response received.
-TEST_P(TimeoutTest, Cds) {
-  balancers_[0]->ads_service()->SetResourceIgnore(kCdsTypeUrl);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  CheckRpcSendFailure();
-}
-
-TEST_P(TimeoutTest, Eds) {
-  balancers_[0]->ads_service()->SetResourceIgnore(kEdsTypeUrl);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  CheckRpcSendFailure();
-}
-
-using LocalityMapTest = BasicTest;
-
-// Tests that the localities in a locality map are picked according to their
-// weights.
-TEST_P(LocalityMapTest, WeightedRoundRobin) {
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  const int kLocalityWeight0 = 2;
-  const int kLocalityWeight1 = 8;
-  const int kTotalLocalityWeight = kLocalityWeight0 + kLocalityWeight1;
-  const double kLocalityWeightRate0 =
-      static_cast<double>(kLocalityWeight0) / kTotalLocalityWeight;
-  const double kLocalityWeightRate1 =
-      static_cast<double>(kLocalityWeight1) / kTotalLocalityWeight;
-  const double kErrorTolerance = 0.05;
-  const size_t kNumRpcs =
-      ComputeIdealNumRpcs(kLocalityWeightRate0, kErrorTolerance);
-  // ADS response contains 2 localities, each of which contains 1 backend.
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 1), kLocalityWeight0},
-      {"locality1", CreateEndpointsForBackends(1, 2), kLocalityWeight1},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  // Wait for both backends to be ready.
-  WaitForAllBackends(0, 2);
-  // Send kNumRpcs RPCs.
-  CheckRpcSendOk(kNumRpcs);
-  // The locality picking rates should be roughly equal to the expectation.
-  const double locality_picked_rate_0 =
-      static_cast<double>(backends_[0]->backend_service()->request_count()) /
-      kNumRpcs;
-  const double locality_picked_rate_1 =
-      static_cast<double>(backends_[1]->backend_service()->request_count()) /
-      kNumRpcs;
-  EXPECT_THAT(locality_picked_rate_0,
-              ::testing::DoubleNear(kLocalityWeightRate0, kErrorTolerance));
-  EXPECT_THAT(locality_picked_rate_1,
-              ::testing::DoubleNear(kLocalityWeightRate1, kErrorTolerance));
-}
-
-// Tests that we correctly handle a locality containing no endpoints.
-TEST_P(LocalityMapTest, LocalityContainingNoEndpoints) {
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  const size_t kNumRpcs = 5000;
-  // EDS response contains 2 localities, one with no endpoints.
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-      {"locality1", {}},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  // Wait for both backends to be ready.
-  WaitForAllBackends();
-  // Send kNumRpcs RPCs.
-  CheckRpcSendOk(kNumRpcs);
-  // All traffic should go to the reachable locality.
-  EXPECT_EQ(backends_[0]->backend_service()->request_count(),
-            kNumRpcs / backends_.size());
-  EXPECT_EQ(backends_[1]->backend_service()->request_count(),
-            kNumRpcs / backends_.size());
-  EXPECT_EQ(backends_[2]->backend_service()->request_count(),
-            kNumRpcs / backends_.size());
-  EXPECT_EQ(backends_[3]->backend_service()->request_count(),
-            kNumRpcs / backends_.size());
-}
-
-// EDS update with no localities.
-TEST_P(LocalityMapTest, NoLocalities) {
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource({}, DefaultEdsServiceName()));
-  Status status = SendRpc();
-  EXPECT_FALSE(status.ok());
-  EXPECT_EQ(status.error_code(), StatusCode::UNAVAILABLE);
-}
-
-// Tests that the locality map can work properly even when it contains a large
-// number of localities.
-TEST_P(LocalityMapTest, StressTest) {
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  const size_t kNumLocalities = 100;
-  const uint32_t kRpcTimeoutMs = 5000;
-  // The first ADS response contains kNumLocalities localities, each of which
-  // contains backend 0.
-  AdsServiceImpl::EdsResourceArgs args;
-  for (size_t i = 0; i < kNumLocalities; ++i) {
-    std::string name = absl::StrCat("locality", i);
-    AdsServiceImpl::EdsResourceArgs::Locality locality(
-        name, CreateEndpointsForBackends(0, 1));
-    args.locality_list.emplace_back(std::move(locality));
-  }
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  // The second ADS response contains 1 locality, which contains backend 1.
-  args = AdsServiceImpl::EdsResourceArgs({
-      {"locality0", CreateEndpointsForBackends(1, 2)},
-  });
-  std::thread delayed_resource_setter(
-      std::bind(&BasicTest::SetEdsResourceWithDelay, this, 0,
-                BuildEdsResource(args, DefaultEdsServiceName()), 60 * 1000));
-  // Wait until backend 0 is ready, before which kNumLocalities localities are
-  // received and handled by the xds policy.
-  WaitForBackend(0, WaitForBackendOptions().set_reset_counters(false),
-                 RpcOptions().set_timeout_ms(kRpcTimeoutMs));
-  EXPECT_EQ(0U, backends_[1]->backend_service()->request_count());
-  // Wait until backend 1 is ready, before which kNumLocalities localities are
-  // removed by the xds policy.
-  WaitForBackend(1);
-  delayed_resource_setter.join();
-}
-
-// Tests that the localities in a locality map are picked correctly after
-// update (addition, modification, deletion).
-TEST_P(LocalityMapTest, UpdateMap) {
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  const size_t kNumRpcs = 3000;
-  // The locality weight for the first 3 localities.
-  const std::vector<int> kLocalityWeights0 = {2, 3, 4};
-  const double kTotalLocalityWeight0 =
-      std::accumulate(kLocalityWeights0.begin(), kLocalityWeights0.end(), 0);
-  std::vector<double> locality_weight_rate_0;
-  locality_weight_rate_0.reserve(kLocalityWeights0.size());
-  for (int weight : kLocalityWeights0) {
-    locality_weight_rate_0.push_back(weight / kTotalLocalityWeight0);
-  }
-  // Delete the first locality, keep the second locality, change the third
-  // locality's weight from 4 to 2, and add a new locality with weight 6.
-  const std::vector<int> kLocalityWeights1 = {3, 2, 6};
-  const double kTotalLocalityWeight1 =
-      std::accumulate(kLocalityWeights1.begin(), kLocalityWeights1.end(), 0);
-  std::vector<double> locality_weight_rate_1 = {
-      0 /* placeholder for locality 0 */};
-  for (int weight : kLocalityWeights1) {
-    locality_weight_rate_1.push_back(weight / kTotalLocalityWeight1);
-  }
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 1), 2},
-      {"locality1", CreateEndpointsForBackends(1, 2), 3},
-      {"locality2", CreateEndpointsForBackends(2, 3), 4},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  // Wait for the first 3 backends to be ready.
-  WaitForAllBackends(0, 3);
-  gpr_log(GPR_INFO, "========= BEFORE FIRST BATCH ==========");
-  // Send kNumRpcs RPCs.
-  CheckRpcSendOk(kNumRpcs);
-  gpr_log(GPR_INFO, "========= DONE WITH FIRST BATCH ==========");
-  // The picking rates of the first 3 backends should be roughly equal to the
-  // expectation.
-  std::vector<double> locality_picked_rates;
-  for (size_t i = 0; i < 3; ++i) {
-    locality_picked_rates.push_back(
-        static_cast<double>(backends_[i]->backend_service()->request_count()) /
-        kNumRpcs);
-  }
-  const double kErrorTolerance = 0.2;
-  for (size_t i = 0; i < 3; ++i) {
-    gpr_log(GPR_INFO, "Locality %" PRIuPTR " rate %f", i,
-            locality_picked_rates[i]);
-    EXPECT_THAT(
-        locality_picked_rates[i],
-        ::testing::AllOf(
-            ::testing::Ge(locality_weight_rate_0[i] * (1 - kErrorTolerance)),
-            ::testing::Le(locality_weight_rate_0[i] * (1 + kErrorTolerance))));
-  }
-  args = AdsServiceImpl::EdsResourceArgs({
-      {"locality1", CreateEndpointsForBackends(1, 2), 3},
-      {"locality2", CreateEndpointsForBackends(2, 3), 2},
-      {"locality3", CreateEndpointsForBackends(3, 4), 6},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  // Backend 3 hasn't received any request.
-  EXPECT_EQ(0U, backends_[3]->backend_service()->request_count());
-  // Wait until the locality update has been processed, as signaled by backend
-  // 3 receiving a request.
-  WaitForAllBackends(3, 4);
-  gpr_log(GPR_INFO, "========= BEFORE SECOND BATCH ==========");
-  // Send kNumRpcs RPCs.
-  CheckRpcSendOk(kNumRpcs);
-  gpr_log(GPR_INFO, "========= DONE WITH SECOND BATCH ==========");
-  // Backend 0 no longer receives any request.
-  EXPECT_EQ(0U, backends_[0]->backend_service()->request_count());
-  // The picking rates of the last 3 backends should be roughly equal to the
-  // expectation.
-  locality_picked_rates = {0 /* placeholder for backend 0 */};
-  for (size_t i = 1; i < 4; ++i) {
-    locality_picked_rates.push_back(
-        static_cast<double>(backends_[i]->backend_service()->request_count()) /
-        kNumRpcs);
-  }
-  for (size_t i = 1; i < 4; ++i) {
-    gpr_log(GPR_INFO, "Locality %" PRIuPTR " rate %f", i,
-            locality_picked_rates[i]);
-    EXPECT_THAT(
-        locality_picked_rates[i],
-        ::testing::AllOf(
-            ::testing::Ge(locality_weight_rate_1[i] * (1 - kErrorTolerance)),
-            ::testing::Le(locality_weight_rate_1[i] * (1 + kErrorTolerance))));
-  }
-}
-
-// Tests that we don't fail RPCs when replacing all of the localities in
-// a given priority.
-TEST_P(LocalityMapTest, ReplaceAllLocalitiesInPriority) {
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 1)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  args = AdsServiceImpl::EdsResourceArgs({
-      {"locality1", CreateEndpointsForBackends(1, 2)},
-  });
-  std::thread delayed_resource_setter(
-      std::bind(&BasicTest::SetEdsResourceWithDelay, this, 0,
-                BuildEdsResource(args, DefaultEdsServiceName()), 5000));
-  // Wait for the first backend to be ready.
-  WaitForBackend(0);
-  // Keep sending RPCs until we switch over to backend 1, which tells us
-  // that we received the update.  No RPCs should fail during this
-  // transition.
-  WaitForBackend(1);
-  delayed_resource_setter.join();
-}
-
-class FailoverTest : public BasicTest {
- public:
-  void SetUp() override {
-    BasicTest::SetUp();
-    ResetStub(500);
-  }
-};
-
-// Localities with the highest priority are used when multiple priority exist.
-TEST_P(FailoverTest, ChooseHighestPriority) {
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 1), kDefaultLocalityWeight,
-       1},
-      {"locality1", CreateEndpointsForBackends(1, 2), kDefaultLocalityWeight,
-       2},
-      {"locality2", CreateEndpointsForBackends(2, 3), kDefaultLocalityWeight,
-       3},
-      {"locality3", CreateEndpointsForBackends(3, 4), kDefaultLocalityWeight,
-       0},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  WaitForBackend(3, WaitForBackendOptions().set_reset_counters(false));
-  for (size_t i = 0; i < 3; ++i) {
-    EXPECT_EQ(0U, backends_[i]->backend_service()->request_count());
-  }
-}
-
-// Does not choose priority with no endpoints.
-TEST_P(FailoverTest, DoesNotUsePriorityWithNoEndpoints) {
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 1), kDefaultLocalityWeight,
-       1},
-      {"locality1", CreateEndpointsForBackends(1, 2), kDefaultLocalityWeight,
-       2},
-      {"locality2", CreateEndpointsForBackends(2, 3), kDefaultLocalityWeight,
-       3},
-      {"locality3", {}, kDefaultLocalityWeight, 0},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  WaitForBackend(0, WaitForBackendOptions().set_reset_counters(false));
-  for (size_t i = 1; i < 3; ++i) {
-    EXPECT_EQ(0U, backends_[i]->backend_service()->request_count());
-  }
-}
-
-// Does not choose locality with no endpoints.
-TEST_P(FailoverTest, DoesNotUseLocalityWithNoEndpoints) {
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", {}, kDefaultLocalityWeight, 0},
-      {"locality1", CreateEndpointsForBackends(), kDefaultLocalityWeight, 0},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  // Wait for all backends to be used.
-  std::tuple<int, int, int> counts = WaitForAllBackends();
-  // Make sure no RPCs failed in the transition.
-  EXPECT_EQ(0, std::get<1>(counts));
-}
-
-// If the higher priority localities are not reachable, failover to the
-// highest priority among the rest.
-TEST_P(FailoverTest, Failover) {
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 1), kDefaultLocalityWeight,
-       1},
-      {"locality1", CreateEndpointsForBackends(1, 2), kDefaultLocalityWeight,
-       2},
-      {"locality2", CreateEndpointsForBackends(2, 3), kDefaultLocalityWeight,
-       3},
-      {"locality3", CreateEndpointsForBackends(3, 4), kDefaultLocalityWeight,
-       0},
-  });
-  ShutdownBackend(3);
-  ShutdownBackend(0);
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  WaitForBackend(1, WaitForBackendOptions().set_reset_counters(false));
-  for (size_t i = 0; i < 4; ++i) {
-    if (i == 1) continue;
-    EXPECT_EQ(0U, backends_[i]->backend_service()->request_count());
-  }
-}
-
-// If a locality with higher priority than the current one becomes ready,
-// switch to it.
-TEST_P(FailoverTest, SwitchBackToHigherPriority) {
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  const size_t kNumRpcs = 100;
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 1), kDefaultLocalityWeight,
-       1},
-      {"locality1", CreateEndpointsForBackends(1, 2), kDefaultLocalityWeight,
-       2},
-      {"locality2", CreateEndpointsForBackends(2, 3), kDefaultLocalityWeight,
-       3},
-      {"locality3", CreateEndpointsForBackends(3, 4), kDefaultLocalityWeight,
-       0},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  WaitForBackend(3);
-  ShutdownBackend(3);
-  ShutdownBackend(0);
-  WaitForBackend(
-      1, WaitForBackendOptions().set_reset_counters(false).set_allow_failures(
-             true));
-  for (size_t i = 0; i < 4; ++i) {
-    if (i == 1) continue;
-    EXPECT_EQ(0U, backends_[i]->backend_service()->request_count());
-  }
-  StartBackend(0);
-  WaitForBackend(0);
-  CheckRpcSendOk(kNumRpcs);
-  EXPECT_EQ(kNumRpcs, backends_[0]->backend_service()->request_count());
-}
-
-// The first update only contains unavailable priorities. The second update
-// contains available priorities.
-TEST_P(FailoverTest, UpdateInitialUnavailable) {
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 1), kDefaultLocalityWeight,
-       0},
-      {"locality1", CreateEndpointsForBackends(1, 2), kDefaultLocalityWeight,
-       1},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  args = AdsServiceImpl::EdsResourceArgs({
-      {"locality0", CreateEndpointsForBackends(0, 1), kDefaultLocalityWeight,
-       0},
-      {"locality1", CreateEndpointsForBackends(1, 2), kDefaultLocalityWeight,
-       1},
-      {"locality2", CreateEndpointsForBackends(2, 3), kDefaultLocalityWeight,
-       2},
-      {"locality3", CreateEndpointsForBackends(3, 4), kDefaultLocalityWeight,
-       3},
-  });
-  ShutdownBackend(0);
-  ShutdownBackend(1);
-  std::thread delayed_resource_setter(
-      std::bind(&BasicTest::SetEdsResourceWithDelay, this, 0,
-                BuildEdsResource(args, DefaultEdsServiceName()), 1000));
-  gpr_timespec deadline = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
-                                       gpr_time_from_millis(500, GPR_TIMESPAN));
-  // Send 0.5 second worth of RPCs.
-  do {
-    CheckRpcSendFailure();
-  } while (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), deadline) < 0);
-  WaitForBackend(
-      2, WaitForBackendOptions().set_reset_counters(false).set_allow_failures(
-             true));
-  for (size_t i = 0; i < 4; ++i) {
-    if (i == 2) continue;
-    EXPECT_EQ(0U, backends_[i]->backend_service()->request_count());
-  }
-  delayed_resource_setter.join();
-}
-
-// Tests that after the localities' priorities are updated, we still choose
-// the highest READY priority with the updated localities.
-TEST_P(FailoverTest, UpdatePriority) {
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  const size_t kNumRpcs = 100;
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 1), kDefaultLocalityWeight,
-       1},
-      {"locality1", CreateEndpointsForBackends(1, 2), kDefaultLocalityWeight,
-       2},
-      {"locality2", CreateEndpointsForBackends(2, 3), kDefaultLocalityWeight,
-       3},
-      {"locality3", CreateEndpointsForBackends(3, 4), kDefaultLocalityWeight,
-       0},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  args = AdsServiceImpl::EdsResourceArgs({
-      {"locality0", CreateEndpointsForBackends(0, 1), kDefaultLocalityWeight,
-       2},
-      {"locality1", CreateEndpointsForBackends(1, 2), kDefaultLocalityWeight,
-       0},
-      {"locality2", CreateEndpointsForBackends(2, 3), kDefaultLocalityWeight,
-       1},
-      {"locality3", CreateEndpointsForBackends(3, 4), kDefaultLocalityWeight,
-       3},
-  });
-  std::thread delayed_resource_setter(
-      std::bind(&BasicTest::SetEdsResourceWithDelay, this, 0,
-                BuildEdsResource(args, DefaultEdsServiceName()), 1000));
-  WaitForBackend(3, WaitForBackendOptions().set_reset_counters(false));
-  for (size_t i = 0; i < 3; ++i) {
-    EXPECT_EQ(0U, backends_[i]->backend_service()->request_count());
-  }
-  WaitForBackend(1);
-  CheckRpcSendOk(kNumRpcs);
-  EXPECT_EQ(kNumRpcs, backends_[1]->backend_service()->request_count());
-  delayed_resource_setter.join();
-}
-
-// Moves all localities in the current priority to a higher priority.
-TEST_P(FailoverTest, MoveAllLocalitiesInCurrentPriorityToHigherPriority) {
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // First update:
-  // - Priority 0 is locality 0, containing backend 0, which is down.
-  // - Priority 1 is locality 1, containing backends 1 and 2, which are up.
-  ShutdownBackend(0);
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, 1), kDefaultLocalityWeight,
-       0},
-      {"locality1", CreateEndpointsForBackends(1, 3), kDefaultLocalityWeight,
-       1},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  // Second update:
-  // - Priority 0 contains both localities 0 and 1.
-  // - Priority 1 is not present.
-  // - We add backend 3 to locality 1, just so we have a way to know
-  //   when the update has been seen by the client.
-  args = AdsServiceImpl::EdsResourceArgs({
-      {"locality0", CreateEndpointsForBackends(0, 1), kDefaultLocalityWeight,
-       0},
-      {"locality1", CreateEndpointsForBackends(1, 4), kDefaultLocalityWeight,
-       0},
-  });
-  std::thread delayed_resource_setter(
-      std::bind(&BasicTest::SetEdsResourceWithDelay, this, 0,
-                BuildEdsResource(args, DefaultEdsServiceName()), 1000));
-  // When we get the first update, all backends in priority 0 are down,
-  // so we will create priority 1.  Backends 1 and 2 should have traffic,
-  // but backend 3 should not.
-  WaitForAllBackends(1, 3, WaitForBackendOptions().set_reset_counters(false));
-  EXPECT_EQ(0UL, backends_[3]->backend_service()->request_count());
-  // When backend 3 gets traffic, we know the second update has been seen.
-  WaitForBackend(3);
-  // The ADS service of balancer 0 got at least 1 response.
-  EXPECT_GT(balancers_[0]->ads_service()->eds_response_state().state,
-            AdsServiceImpl::ResponseState::NOT_SENT);
-  delayed_resource_setter.join();
-}
-
-using DropTest = BasicTest;
-
-// Tests that RPCs are dropped according to the drop config.
-TEST_P(DropTest, Vanilla) {
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  const uint32_t kDropPerMillionForLb = 100000;
-  const uint32_t kDropPerMillionForThrottle = 200000;
-  const double kDropRateForLb = kDropPerMillionForLb / 1000000.0;
-  const double kDropRateForThrottle = kDropPerMillionForThrottle / 1000000.0;
-  const double kDropRateForLbAndThrottle =
-      kDropRateForLb + (1 - kDropRateForLb) * kDropRateForThrottle;
-  const double kErrorTolerance = 0.05;
-  const size_t kNumRpcs =
-      ComputeIdealNumRpcs(kDropRateForLbAndThrottle, kErrorTolerance);
-  // The ADS response contains two drop categories.
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  args.drop_categories = {{kLbDropType, kDropPerMillionForLb},
-                          {kThrottleDropType, kDropPerMillionForThrottle}};
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  WaitForAllBackends();
-  // Send kNumRpcs RPCs and count the drops.
-  size_t num_drops = 0;
-  for (size_t i = 0; i < kNumRpcs; ++i) {
-    EchoResponse response;
-    const Status status = SendRpc(RpcOptions(), &response);
-    if (!status.ok() &&
-        absl::StartsWith(status.error_message(), "EDS-configured drop: ")) {
-      ++num_drops;
-    } else {
-      EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
-                               << " message=" << status.error_message();
-      EXPECT_EQ(response.message(), kRequestMessage);
-    }
-  }
-  // The drop rate should be roughly equal to the expectation.
-  const double seen_drop_rate = static_cast<double>(num_drops) / kNumRpcs;
-  EXPECT_THAT(seen_drop_rate, ::testing::DoubleNear(kDropRateForLbAndThrottle,
-                                                    kErrorTolerance));
-}
-
-// Tests that drop config is converted correctly from per hundred.
-TEST_P(DropTest, DropPerHundred) {
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  const uint32_t kDropPerHundredForLb = 10;
-  const double kDropRateForLb = kDropPerHundredForLb / 100.0;
-  const double kErrorTolerance = 0.05;
-  const size_t kNumRpcs = ComputeIdealNumRpcs(kDropRateForLb, kErrorTolerance);
-  // The ADS response contains one drop category.
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  args.drop_categories = {{kLbDropType, kDropPerHundredForLb}};
-  args.drop_denominator = FractionalPercent::HUNDRED;
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  WaitForAllBackends();
-  // Send kNumRpcs RPCs and count the drops.
-  size_t num_drops = 0;
-  for (size_t i = 0; i < kNumRpcs; ++i) {
-    EchoResponse response;
-    const Status status = SendRpc(RpcOptions(), &response);
-    if (!status.ok() &&
-        absl::StartsWith(status.error_message(), "EDS-configured drop: ")) {
-      ++num_drops;
-    } else {
-      EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
-                               << " message=" << status.error_message();
-      EXPECT_EQ(response.message(), kRequestMessage);
-    }
-  }
-  // The drop rate should be roughly equal to the expectation.
-  const double seen_drop_rate = static_cast<double>(num_drops) / kNumRpcs;
-  EXPECT_THAT(seen_drop_rate,
-              ::testing::DoubleNear(kDropRateForLb, kErrorTolerance));
-}
-
-// Tests that drop config is converted correctly from per ten thousand.
-TEST_P(DropTest, DropPerTenThousand) {
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  const uint32_t kDropPerTenThousandForLb = 1000;
-  const double kDropRateForLb = kDropPerTenThousandForLb / 10000.0;
-  const double kErrorTolerance = 0.05;
-  const size_t kNumRpcs = ComputeIdealNumRpcs(kDropRateForLb, kErrorTolerance);
-  // The ADS response contains one drop category.
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  args.drop_categories = {{kLbDropType, kDropPerTenThousandForLb}};
-  args.drop_denominator = FractionalPercent::TEN_THOUSAND;
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  WaitForAllBackends();
-  // Send kNumRpcs RPCs and count the drops.
-  size_t num_drops = 0;
-  for (size_t i = 0; i < kNumRpcs; ++i) {
-    EchoResponse response;
-    const Status status = SendRpc(RpcOptions(), &response);
-    if (!status.ok() &&
-        absl::StartsWith(status.error_message(), "EDS-configured drop: ")) {
-      ++num_drops;
-    } else {
-      EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
-                               << " message=" << status.error_message();
-      EXPECT_EQ(response.message(), kRequestMessage);
-    }
-  }
-  // The drop rate should be roughly equal to the expectation.
-  const double seen_drop_rate = static_cast<double>(num_drops) / kNumRpcs;
-  EXPECT_THAT(seen_drop_rate,
-              ::testing::DoubleNear(kDropRateForLb, kErrorTolerance));
-}
-
-// Tests that drop is working correctly after update.
-TEST_P(DropTest, Update) {
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  const uint32_t kDropPerMillionForLb = 100000;
-  const uint32_t kDropPerMillionForThrottle = 200000;
-  const double kErrorTolerance = 0.05;
-  const double kDropRateForLb = kDropPerMillionForLb / 1000000.0;
-  const double kDropRateForThrottle = kDropPerMillionForThrottle / 1000000.0;
-  const double kDropRateForLbAndThrottle =
-      kDropRateForLb + (1 - kDropRateForLb) * kDropRateForThrottle;
-  const size_t kNumRpcsLbOnly =
-      ComputeIdealNumRpcs(kDropRateForLb, kErrorTolerance);
-  const size_t kNumRpcsBoth =
-      ComputeIdealNumRpcs(kDropRateForLbAndThrottle, kErrorTolerance);
-  // The first ADS response contains one drop category.
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  args.drop_categories = {{kLbDropType, kDropPerMillionForLb}};
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  WaitForAllBackends();
-  // Send kNumRpcsLbOnly RPCs and count the drops.
-  size_t num_drops = 0;
-  gpr_log(GPR_INFO, "========= BEFORE FIRST BATCH ==========");
-  for (size_t i = 0; i < kNumRpcsLbOnly; ++i) {
-    EchoResponse response;
-    const Status status = SendRpc(RpcOptions(), &response);
-    if (!status.ok() &&
-        absl::StartsWith(status.error_message(), "EDS-configured drop: ")) {
-      ++num_drops;
-    } else {
-      EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
-                               << " message=" << status.error_message();
-      EXPECT_EQ(response.message(), kRequestMessage);
-    }
-  }
-  gpr_log(GPR_INFO, "========= DONE WITH FIRST BATCH ==========");
-  // The drop rate should be roughly equal to the expectation.
-  double seen_drop_rate = static_cast<double>(num_drops) / kNumRpcsLbOnly;
-  gpr_log(GPR_INFO, "First batch drop rate %f", seen_drop_rate);
-  EXPECT_THAT(seen_drop_rate,
-              ::testing::DoubleNear(kDropRateForLb, kErrorTolerance));
-  // The second ADS response contains two drop categories, send an update EDS
-  // response.
-  args.drop_categories = {{kLbDropType, kDropPerMillionForLb},
-                          {kThrottleDropType, kDropPerMillionForThrottle}};
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  // Wait until the drop rate increases to the middle of the two configs,
-  // which implies that the update has been in effect.
-  const double kDropRateThreshold =
-      (kDropRateForLb + kDropRateForLbAndThrottle) / 2;
-  size_t num_rpcs = kNumRpcsBoth;
-  while (seen_drop_rate < kDropRateThreshold) {
-    EchoResponse response;
-    const Status status = SendRpc(RpcOptions(), &response);
-    ++num_rpcs;
-    if (!status.ok() &&
-        absl::StartsWith(status.error_message(), "EDS-configured drop: ")) {
-      ++num_drops;
-    } else {
-      EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
-                               << " message=" << status.error_message();
-      EXPECT_EQ(response.message(), kRequestMessage);
-    }
-    seen_drop_rate = static_cast<double>(num_drops) / num_rpcs;
-  }
-  // Send kNumRpcsBoth RPCs and count the drops.
-  num_drops = 0;
-  gpr_log(GPR_INFO, "========= BEFORE SECOND BATCH ==========");
-  for (size_t i = 0; i < kNumRpcsBoth; ++i) {
-    EchoResponse response;
-    const Status status = SendRpc(RpcOptions(), &response);
-    if (!status.ok() &&
-        absl::StartsWith(status.error_message(), "EDS-configured drop: ")) {
-      ++num_drops;
-    } else {
-      EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
-                               << " message=" << status.error_message();
-      EXPECT_EQ(response.message(), kRequestMessage);
-    }
-  }
-  gpr_log(GPR_INFO, "========= DONE WITH SECOND BATCH ==========");
-  // The new drop rate should be roughly equal to the expectation.
-  seen_drop_rate = static_cast<double>(num_drops) / kNumRpcsBoth;
-  gpr_log(GPR_INFO, "Second batch drop rate %f", seen_drop_rate);
-  EXPECT_THAT(seen_drop_rate, ::testing::DoubleNear(kDropRateForLbAndThrottle,
-                                                    kErrorTolerance));
-}
-
-// Tests that all the RPCs are dropped if any drop category drops 100%.
-TEST_P(DropTest, DropAll) {
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  const size_t kNumRpcs = 1000;
-  const uint32_t kDropPerMillionForLb = 100000;
-  const uint32_t kDropPerMillionForThrottle = 1000000;
-  // The ADS response contains two drop categories.
-  AdsServiceImpl::EdsResourceArgs args;
-  args.drop_categories = {{kLbDropType, kDropPerMillionForLb},
-                          {kThrottleDropType, kDropPerMillionForThrottle}};
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  // Send kNumRpcs RPCs and all of them are dropped.
-  for (size_t i = 0; i < kNumRpcs; ++i) {
-    EchoResponse response;
-    const Status status = SendRpc(RpcOptions(), &response);
-    EXPECT_EQ(status.error_code(), StatusCode::UNAVAILABLE);
-    EXPECT_THAT(status.error_message(),
-                ::testing::StartsWith("EDS-configured drop: "));
-  }
-}
-
-class BalancerUpdateTest : public XdsEnd2endTest {
- public:
-  BalancerUpdateTest() : XdsEnd2endTest(4, 3) {}
-};
-
-// Tests that the old LB call is still used after the balancer address update
-// as long as that call is still alive.
-TEST_P(BalancerUpdateTest, UpdateBalancersButKeepUsingOriginalBalancer) {
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  AdsServiceImpl::EdsResourceArgs args(
-      {{"locality0", CreateEndpointsForBackends(0, 1)}});
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  args = AdsServiceImpl::EdsResourceArgs(
-      {{"locality0", CreateEndpointsForBackends(1, 2)}});
-  balancers_[1]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  // Wait until the first backend is ready.
-  WaitForBackend(0);
-  // Send 10 requests.
-  gpr_log(GPR_INFO, "========= BEFORE FIRST BATCH ==========");
-  CheckRpcSendOk(10);
-  gpr_log(GPR_INFO, "========= DONE WITH FIRST BATCH ==========");
-  // All 10 requests should have gone to the first backend.
-  EXPECT_EQ(10U, backends_[0]->backend_service()->request_count());
-  // The ADS service of balancer 0 sent at least 1 response.
-  EXPECT_GT(balancers_[0]->ads_service()->eds_response_state().state,
-            AdsServiceImpl::ResponseState::NOT_SENT);
-  EXPECT_EQ(balancers_[1]->ads_service()->eds_response_state().state,
-            AdsServiceImpl::ResponseState::NOT_SENT)
-      << "Error Message:"
-      << balancers_[1]->ads_service()->eds_response_state().error_message;
-  EXPECT_EQ(balancers_[2]->ads_service()->eds_response_state().state,
-            AdsServiceImpl::ResponseState::NOT_SENT)
-      << "Error Message:"
-      << balancers_[2]->ads_service()->eds_response_state().error_message;
-  gpr_log(GPR_INFO, "========= ABOUT TO UPDATE 1 ==========");
-  SetNextResolutionForLbChannel({balancers_[1]->port()});
-  gpr_log(GPR_INFO, "========= UPDATE 1 DONE ==========");
-  EXPECT_EQ(0U, backends_[1]->backend_service()->request_count());
-  gpr_timespec deadline = gpr_time_add(
-      gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_millis(10000, GPR_TIMESPAN));
-  // Send 10 seconds worth of RPCs
-  do {
-    CheckRpcSendOk();
-  } while (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), deadline) < 0);
-  // The current LB call is still working, so xds continued using it to the
-  // first balancer, which doesn't assign the second backend.
-  EXPECT_EQ(0U, backends_[1]->backend_service()->request_count());
-  // The ADS service of balancer 0 sent at least 1 response.
-  EXPECT_GT(balancers_[0]->ads_service()->eds_response_state().state,
-            AdsServiceImpl::ResponseState::NOT_SENT);
-  EXPECT_EQ(balancers_[1]->ads_service()->eds_response_state().state,
-            AdsServiceImpl::ResponseState::NOT_SENT)
-      << "Error Message:"
-      << balancers_[1]->ads_service()->eds_response_state().error_message;
-  EXPECT_EQ(balancers_[2]->ads_service()->eds_response_state().state,
-            AdsServiceImpl::ResponseState::NOT_SENT)
-      << "Error Message:"
-      << balancers_[2]->ads_service()->eds_response_state().error_message;
-}
-
-// Tests that the old LB call is still used after multiple balancer address
-// updates as long as that call is still alive. Send an update with the same
-// set of LBs as the one in SetUp() in order to verify that the LB channel
-// inside xds keeps the initial connection (which by definition is also
-// present in the update).
-TEST_P(BalancerUpdateTest, Repeated) {
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  AdsServiceImpl::EdsResourceArgs args(
-      {{"locality0", CreateEndpointsForBackends(0, 1)}});
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  args = AdsServiceImpl::EdsResourceArgs(
-      {{"locality0", CreateEndpointsForBackends(1, 2)}});
-  balancers_[1]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  // Wait until the first backend is ready.
-  WaitForBackend(0);
-  // Send 10 requests.
-  gpr_log(GPR_INFO, "========= BEFORE FIRST BATCH ==========");
-  CheckRpcSendOk(10);
-  gpr_log(GPR_INFO, "========= DONE WITH FIRST BATCH ==========");
-  // All 10 requests should have gone to the first backend.
-  EXPECT_EQ(10U, backends_[0]->backend_service()->request_count());
-  // The ADS service of balancer 0 sent at least 1 response.
-  EXPECT_GT(balancers_[0]->ads_service()->eds_response_state().state,
-            AdsServiceImpl::ResponseState::NOT_SENT);
-  EXPECT_EQ(balancers_[1]->ads_service()->eds_response_state().state,
-            AdsServiceImpl::ResponseState::NOT_SENT)
-      << "Error Message:"
-      << balancers_[1]->ads_service()->eds_response_state().error_message;
-  EXPECT_EQ(balancers_[2]->ads_service()->eds_response_state().state,
-            AdsServiceImpl::ResponseState::NOT_SENT)
-      << "Error Message:"
-      << balancers_[2]->ads_service()->eds_response_state().error_message;
-  std::vector<int> ports;
-  ports.emplace_back(balancers_[0]->port());
-  ports.emplace_back(balancers_[1]->port());
-  ports.emplace_back(balancers_[2]->port());
-  gpr_log(GPR_INFO, "========= ABOUT TO UPDATE 1 ==========");
-  SetNextResolutionForLbChannel(ports);
-  gpr_log(GPR_INFO, "========= UPDATE 1 DONE ==========");
-  EXPECT_EQ(0U, backends_[1]->backend_service()->request_count());
-  gpr_timespec deadline = gpr_time_add(
-      gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_millis(10000, GPR_TIMESPAN));
-  // Send 10 seconds worth of RPCs
-  do {
-    CheckRpcSendOk();
-  } while (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), deadline) < 0);
-  // xds continued using the original LB call to the first balancer, which
-  // doesn't assign the second backend.
-  EXPECT_EQ(0U, backends_[1]->backend_service()->request_count());
-  ports.clear();
-  ports.emplace_back(balancers_[0]->port());
-  ports.emplace_back(balancers_[1]->port());
-  gpr_log(GPR_INFO, "========= ABOUT TO UPDATE 2 ==========");
-  SetNextResolutionForLbChannel(ports);
-  gpr_log(GPR_INFO, "========= UPDATE 2 DONE ==========");
-  EXPECT_EQ(0U, backends_[1]->backend_service()->request_count());
-  deadline = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
-                          gpr_time_from_millis(10000, GPR_TIMESPAN));
-  // Send 10 seconds worth of RPCs
-  do {
-    CheckRpcSendOk();
-  } while (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), deadline) < 0);
-  // xds continued using the original LB call to the first balancer, which
-  // doesn't assign the second backend.
-  EXPECT_EQ(0U, backends_[1]->backend_service()->request_count());
-}
-
-// Tests that if the balancer is down, the RPCs will still be sent to the
-// backends according to the last balancer response, until a new balancer is
-// reachable.
-TEST_P(BalancerUpdateTest, DeadUpdate) {
-  SetNextResolution({});
-  SetNextResolutionForLbChannel({balancers_[0]->port()});
-  AdsServiceImpl::EdsResourceArgs args(
-      {{"locality0", CreateEndpointsForBackends(0, 1)}});
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  args = AdsServiceImpl::EdsResourceArgs(
-      {{"locality0", CreateEndpointsForBackends(1, 2)}});
-  balancers_[1]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  // Start servers and send 10 RPCs per server.
-  gpr_log(GPR_INFO, "========= BEFORE FIRST BATCH ==========");
-  CheckRpcSendOk(10);
-  gpr_log(GPR_INFO, "========= DONE WITH FIRST BATCH ==========");
-  // All 10 requests should have gone to the first backend.
-  EXPECT_EQ(10U, backends_[0]->backend_service()->request_count());
-  // The ADS service of balancer 0 sent at least 1 response.
-  EXPECT_GT(balancers_[0]->ads_service()->eds_response_state().state,
-            AdsServiceImpl::ResponseState::NOT_SENT);
-  EXPECT_EQ(balancers_[1]->ads_service()->eds_response_state().state,
-            AdsServiceImpl::ResponseState::NOT_SENT)
-      << "Error Message:"
-      << balancers_[1]->ads_service()->eds_response_state().error_message;
-  EXPECT_EQ(balancers_[2]->ads_service()->eds_response_state().state,
-            AdsServiceImpl::ResponseState::NOT_SENT)
-      << "Error Message:"
-      << balancers_[2]->ads_service()->eds_response_state().error_message;
-  // Kill balancer 0
-  gpr_log(GPR_INFO, "********** ABOUT TO KILL BALANCER 0 *************");
-  balancers_[0]->Shutdown();
-  gpr_log(GPR_INFO, "********** KILLED BALANCER 0 *************");
-  // This is serviced by the existing child policy.
-  gpr_log(GPR_INFO, "========= BEFORE SECOND BATCH ==========");
-  CheckRpcSendOk(10);
-  gpr_log(GPR_INFO, "========= DONE WITH SECOND BATCH ==========");
-  // All 10 requests should again have gone to the first backend.
-  EXPECT_EQ(20U, backends_[0]->backend_service()->request_count());
-  EXPECT_EQ(0U, backends_[1]->backend_service()->request_count());
-  // The ADS service of no balancers sent anything
-  EXPECT_EQ(balancers_[0]->ads_service()->eds_response_state().state,
-            AdsServiceImpl::ResponseState::NOT_SENT)
-      << "Error Message:"
-      << balancers_[0]->ads_service()->eds_response_state().error_message;
-  EXPECT_EQ(balancers_[1]->ads_service()->eds_response_state().state,
-            AdsServiceImpl::ResponseState::NOT_SENT)
-      << "Error Message:"
-      << balancers_[1]->ads_service()->eds_response_state().error_message;
-  EXPECT_EQ(balancers_[2]->ads_service()->eds_response_state().state,
-            AdsServiceImpl::ResponseState::NOT_SENT)
-      << "Error Message:"
-      << balancers_[2]->ads_service()->eds_response_state().error_message;
-  gpr_log(GPR_INFO, "========= ABOUT TO UPDATE 1 ==========");
-  SetNextResolutionForLbChannel({balancers_[1]->port()});
-  gpr_log(GPR_INFO, "========= UPDATE 1 DONE ==========");
-  // Wait until update has been processed, as signaled by the second backend
-  // receiving a request. In the meantime, the client continues to be serviced
-  // (by the first backend) without interruption.
-  EXPECT_EQ(0U, backends_[1]->backend_service()->request_count());
-  WaitForBackend(1);
-  // This is serviced by the updated RR policy
-  backends_[1]->backend_service()->ResetCounters();
-  gpr_log(GPR_INFO, "========= BEFORE THIRD BATCH ==========");
-  CheckRpcSendOk(10);
-  gpr_log(GPR_INFO, "========= DONE WITH THIRD BATCH ==========");
-  // All 10 requests should have gone to the second backend.
-  EXPECT_EQ(10U, backends_[1]->backend_service()->request_count());
-  // The ADS service of balancer 1 sent at least 1 response.
-  EXPECT_EQ(balancers_[0]->ads_service()->eds_response_state().state,
-            AdsServiceImpl::ResponseState::NOT_SENT)
-      << "Error Message:"
-      << balancers_[0]->ads_service()->eds_response_state().error_message;
-  EXPECT_GT(balancers_[1]->ads_service()->eds_response_state().state,
-            AdsServiceImpl::ResponseState::NOT_SENT);
-  EXPECT_EQ(balancers_[2]->ads_service()->eds_response_state().state,
-            AdsServiceImpl::ResponseState::NOT_SENT)
-      << "Error Message:"
-      << balancers_[2]->ads_service()->eds_response_state().error_message;
-}
-
-class ClientLoadReportingTest : public XdsEnd2endTest {
- public:
-  ClientLoadReportingTest() : XdsEnd2endTest(4, 1, 3) {}
-};
-
-// Tests that the load report received at the balancer is correct.
-TEST_P(ClientLoadReportingTest, Vanilla) {
-  if (GetParam().use_fake_resolver()) {
-    balancers_[0]->lrs_service()->set_cluster_names({kServerName});
-  }
-  SetNextResolution({});
-  SetNextResolutionForLbChannel({balancers_[0]->port()});
-  const size_t kNumRpcsPerAddress = 10;
-  const size_t kNumFailuresPerAddress = 3;
-  // TODO(juanlishen): Partition the backends after multiple localities is
-  // tested.
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  // Wait until all backends are ready.
-  int num_ok = 0;
-  int num_failure = 0;
-  int num_drops = 0;
-  std::tie(num_ok, num_failure, num_drops) = WaitForAllBackends();
-  // Send kNumRpcsPerAddress RPCs per server.
-  CheckRpcSendOk(kNumRpcsPerAddress * num_backends_);
-  CheckRpcSendFailure(CheckRpcSendFailureOptions()
-                          .set_times(kNumFailuresPerAddress * num_backends_)
-                          .set_rpc_options(RpcOptions().set_server_fail(true)));
-  // Check that each backend got the right number of requests.
-  for (size_t i = 0; i < backends_.size(); ++i) {
-    EXPECT_EQ(kNumRpcsPerAddress + kNumFailuresPerAddress,
-              backends_[i]->backend_service()->request_count());
-  }
-  // The load report received at the balancer should be correct.
-  std::vector<ClientStats> load_report =
-      balancers_[0]->lrs_service()->WaitForLoadReport();
-  ASSERT_EQ(load_report.size(), 1UL);
-  ClientStats& client_stats = load_report.front();
-  EXPECT_EQ(kNumRpcsPerAddress * num_backends_ + num_ok,
-            client_stats.total_successful_requests());
-  EXPECT_EQ(0U, client_stats.total_requests_in_progress());
-  EXPECT_EQ((kNumRpcsPerAddress + kNumFailuresPerAddress) * num_backends_ +
-                num_ok + num_failure,
-            client_stats.total_issued_requests());
-  EXPECT_EQ(kNumFailuresPerAddress * num_backends_ + num_failure,
-            client_stats.total_error_requests());
-  EXPECT_EQ(0U, client_stats.total_dropped_requests());
-  // The LRS service got a single request, and sent a single response.
-  EXPECT_EQ(1U, balancers_[0]->lrs_service()->request_count());
-  EXPECT_EQ(1U, balancers_[0]->lrs_service()->response_count());
-}
-
-// Tests send_all_clusters.
-TEST_P(ClientLoadReportingTest, SendAllClusters) {
-  balancers_[0]->lrs_service()->set_send_all_clusters(true);
-  SetNextResolution({});
-  SetNextResolutionForLbChannel({balancers_[0]->port()});
-  const size_t kNumRpcsPerAddress = 10;
-  const size_t kNumFailuresPerAddress = 3;
-  // TODO(juanlishen): Partition the backends after multiple localities is
-  // tested.
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  // Wait until all backends are ready.
-  int num_ok = 0;
-  int num_failure = 0;
-  int num_drops = 0;
-  std::tie(num_ok, num_failure, num_drops) = WaitForAllBackends();
-  // Send kNumRpcsPerAddress RPCs per server.
-  CheckRpcSendOk(kNumRpcsPerAddress * num_backends_);
-  CheckRpcSendFailure(CheckRpcSendFailureOptions()
-                          .set_times(kNumFailuresPerAddress * num_backends_)
-                          .set_rpc_options(RpcOptions().set_server_fail(true)));
-  // Check that each backend got the right number of requests.
-  for (size_t i = 0; i < backends_.size(); ++i) {
-    EXPECT_EQ(kNumRpcsPerAddress + kNumFailuresPerAddress,
-              backends_[i]->backend_service()->request_count());
-  }
-  // The load report received at the balancer should be correct.
-  std::vector<ClientStats> load_report =
-      balancers_[0]->lrs_service()->WaitForLoadReport();
-  ASSERT_EQ(load_report.size(), 1UL);
-  ClientStats& client_stats = load_report.front();
-  EXPECT_EQ(kNumRpcsPerAddress * num_backends_ + num_ok,
-            client_stats.total_successful_requests());
-  EXPECT_EQ(0U, client_stats.total_requests_in_progress());
-  EXPECT_EQ((kNumRpcsPerAddress + kNumFailuresPerAddress) * num_backends_ +
-                num_ok + num_failure,
-            client_stats.total_issued_requests());
-  EXPECT_EQ(kNumFailuresPerAddress * num_backends_ + num_failure,
-            client_stats.total_error_requests());
-  EXPECT_EQ(0U, client_stats.total_dropped_requests());
-  // The LRS service got a single request, and sent a single response.
-  EXPECT_EQ(1U, balancers_[0]->lrs_service()->request_count());
-  EXPECT_EQ(1U, balancers_[0]->lrs_service()->response_count());
-}
-
-// Tests that we don't include stats for clusters that are not requested
-// by the LRS server.
-TEST_P(ClientLoadReportingTest, HonorsClustersRequestedByLrsServer) {
-  balancers_[0]->lrs_service()->set_cluster_names({"bogus"});
-  SetNextResolution({});
-  SetNextResolutionForLbChannel({balancers_[0]->port()});
-  const size_t kNumRpcsPerAddress = 100;
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  // Wait until all backends are ready.
-  int num_ok = 0;
-  int num_failure = 0;
-  int num_drops = 0;
-  std::tie(num_ok, num_failure, num_drops) = WaitForAllBackends();
-  // Send kNumRpcsPerAddress RPCs per server.
-  CheckRpcSendOk(kNumRpcsPerAddress * num_backends_);
-  // Each backend should have gotten 100 requests.
-  for (size_t i = 0; i < backends_.size(); ++i) {
-    EXPECT_EQ(kNumRpcsPerAddress,
-              backends_[i]->backend_service()->request_count());
-  }
-  // The LRS service got a single request, and sent a single response.
-  EXPECT_EQ(1U, balancers_[0]->lrs_service()->request_count());
-  EXPECT_EQ(1U, balancers_[0]->lrs_service()->response_count());
-  // The load report received at the balancer should be correct.
-  std::vector<ClientStats> load_report =
-      balancers_[0]->lrs_service()->WaitForLoadReport();
-  ASSERT_EQ(load_report.size(), 0UL);
-}
-
-// Tests that if the balancer restarts, the client load report contains the
-// stats before and after the restart correctly.
-TEST_P(ClientLoadReportingTest, BalancerRestart) {
-  if (GetParam().use_fake_resolver()) {
-    balancers_[0]->lrs_service()->set_cluster_names({kServerName});
-  }
-  SetNextResolution({});
-  SetNextResolutionForLbChannel({balancers_[0]->port()});
-  const size_t kNumBackendsFirstPass = backends_.size() / 2;
-  const size_t kNumBackendsSecondPass =
-      backends_.size() - kNumBackendsFirstPass;
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends(0, kNumBackendsFirstPass)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  // Wait until all backends returned by the balancer are ready.
-  int num_ok = 0;
-  int num_failure = 0;
-  int num_drops = 0;
-  std::tie(num_ok, num_failure, num_drops) =
-      WaitForAllBackends(/* start_index */ 0,
-                         /* stop_index */ kNumBackendsFirstPass);
-  std::vector<ClientStats> load_report =
-      balancers_[0]->lrs_service()->WaitForLoadReport();
-  ASSERT_EQ(load_report.size(), 1UL);
-  ClientStats client_stats = std::move(load_report.front());
-  EXPECT_EQ(static_cast<size_t>(num_ok),
-            client_stats.total_successful_requests());
-  EXPECT_EQ(0U, client_stats.total_requests_in_progress());
-  EXPECT_EQ(0U, client_stats.total_error_requests());
-  EXPECT_EQ(0U, client_stats.total_dropped_requests());
-  // Shut down the balancer.
-  balancers_[0]->Shutdown();
-  // We should continue using the last EDS response we received from the
-  // balancer before it was shut down.
-  // Note: We need to use WaitForAllBackends() here instead of just
-  // CheckRpcSendOk(kNumBackendsFirstPass), because when the balancer
-  // shuts down, the XdsClient will generate an error to the
-  // ServiceConfigWatcher, which will cause the xds resolver to send a
-  // no-op update to the LB policy.  When this update gets down to the
-  // round_robin child policy for the locality, it will generate a new
-  // subchannel list, which resets the start index randomly.  So we need
-  // to be a little more permissive here to avoid spurious failures.
-  ResetBackendCounters();
-  int num_started = std::get<0>(WaitForAllBackends(
-      /* start_index */ 0, /* stop_index */ kNumBackendsFirstPass));
-  // Now restart the balancer, this time pointing to the new backends.
-  balancers_[0]->Start();
-  args = AdsServiceImpl::EdsResourceArgs({
-      {"locality0", CreateEndpointsForBackends(kNumBackendsFirstPass)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  // Wait for queries to start going to one of the new backends.
-  // This tells us that we're now using the new serverlist.
-  std::tie(num_ok, num_failure, num_drops) =
-      WaitForAllBackends(/* start_index */ kNumBackendsFirstPass);
-  num_started += num_ok + num_failure + num_drops;
-  // Send one RPC per backend.
-  CheckRpcSendOk(kNumBackendsSecondPass);
-  num_started += kNumBackendsSecondPass;
-  // Check client stats.
-  load_report = balancers_[0]->lrs_service()->WaitForLoadReport();
-  ASSERT_EQ(load_report.size(), 1UL);
-  client_stats = std::move(load_report.front());
-  EXPECT_EQ(num_started, client_stats.total_successful_requests());
-  EXPECT_EQ(0U, client_stats.total_requests_in_progress());
-  EXPECT_EQ(0U, client_stats.total_error_requests());
-  EXPECT_EQ(0U, client_stats.total_dropped_requests());
-}
-
-class ClientLoadReportingWithDropTest : public XdsEnd2endTest {
- public:
-  ClientLoadReportingWithDropTest() : XdsEnd2endTest(4, 1, 20) {}
-};
-
-// Tests that the drop stats are correctly reported by client load reporting.
-TEST_P(ClientLoadReportingWithDropTest, Vanilla) {
-  if (GetParam().use_fake_resolver()) {
-    balancers_[0]->lrs_service()->set_cluster_names({kServerName});
-  }
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  const uint32_t kDropPerMillionForLb = 100000;
-  const uint32_t kDropPerMillionForThrottle = 200000;
-  const double kErrorTolerance = 0.05;
-  const double kDropRateForLb = kDropPerMillionForLb / 1000000.0;
-  const double kDropRateForThrottle = kDropPerMillionForThrottle / 1000000.0;
-  const double kDropRateForLbAndThrottle =
-      kDropRateForLb + (1 - kDropRateForLb) * kDropRateForThrottle;
-  const size_t kNumRpcs =
-      ComputeIdealNumRpcs(kDropRateForLbAndThrottle, kErrorTolerance);
-  // The ADS response contains two drop categories.
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  args.drop_categories = {{kLbDropType, kDropPerMillionForLb},
-                          {kThrottleDropType, kDropPerMillionForThrottle}};
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  int num_ok = 0;
-  int num_failure = 0;
-  int num_drops = 0;
-  std::tie(num_ok, num_failure, num_drops) = WaitForAllBackends();
-  const size_t num_warmup = num_ok + num_failure + num_drops;
-  // Send kNumRpcs RPCs and count the drops.
-  for (size_t i = 0; i < kNumRpcs; ++i) {
-    EchoResponse response;
-    const Status status = SendRpc(RpcOptions(), &response);
-    if (!status.ok() &&
-        absl::StartsWith(status.error_message(), "EDS-configured drop: ")) {
-      ++num_drops;
-    } else {
-      EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
-                               << " message=" << status.error_message();
-      EXPECT_EQ(response.message(), kRequestMessage);
-    }
-  }
-  // The drop rate should be roughly equal to the expectation.
-  const double seen_drop_rate = static_cast<double>(num_drops) / kNumRpcs;
-  EXPECT_THAT(seen_drop_rate, ::testing::DoubleNear(kDropRateForLbAndThrottle,
-                                                    kErrorTolerance));
-  // Check client stats.
-  const size_t total_rpc = num_warmup + kNumRpcs;
-  ClientStats client_stats;
-  do {
-    std::vector<ClientStats> load_reports =
-        balancers_[0]->lrs_service()->WaitForLoadReport();
-    for (const auto& load_report : load_reports) {
-      client_stats += load_report;
-    }
-  } while (client_stats.total_issued_requests() +
-               client_stats.total_dropped_requests() <
-           total_rpc);
-  EXPECT_EQ(num_drops, client_stats.total_dropped_requests());
-  EXPECT_THAT(static_cast<double>(client_stats.dropped_requests(kLbDropType)) /
-                  total_rpc,
-              ::testing::DoubleNear(kDropRateForLb, kErrorTolerance));
-  EXPECT_THAT(
-      static_cast<double>(client_stats.dropped_requests(kThrottleDropType)) /
-          (total_rpc * (1 - kDropRateForLb)),
-      ::testing::DoubleNear(kDropRateForThrottle, kErrorTolerance));
-}
-
-class FaultInjectionTest : public XdsEnd2endTest {
- public:
-  FaultInjectionTest() : XdsEnd2endTest(1, 1) {}
-
-  // Builds a Listener with Fault Injection filter config. If the http_fault
-  // is nullptr, then assign an empty filter config. This filter config is
-  // required to enable the fault injection features.
-  static Listener BuildListenerWithFaultInjection(
-      const HTTPFault& http_fault = HTTPFault()) {
-    HttpConnectionManager http_connection_manager;
-    Listener listener;
-    listener.set_name(kServerName);
-    HttpFilter* fault_filter = http_connection_manager.add_http_filters();
-    fault_filter->set_name("envoy.fault");
-    fault_filter->mutable_typed_config()->PackFrom(http_fault);
-    HttpFilter* router_filter = http_connection_manager.add_http_filters();
-    router_filter->set_name("router");
-    router_filter->mutable_typed_config()->PackFrom(
-        envoy::extensions::filters::http::router::v3::Router());
-    listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
-        http_connection_manager);
-    return listener;
-  }
-
-  RouteConfiguration BuildRouteConfigurationWithFaultInjection(
-      const HTTPFault& http_fault) {
-    // Package as Any
-    google::protobuf::Any filter_config;
-    filter_config.PackFrom(http_fault);
-    // Plug into the RouteConfiguration
-    RouteConfiguration new_route_config = default_route_config_;
-    auto* config_map = new_route_config.mutable_virtual_hosts(0)
-                           ->mutable_routes(0)
-                           ->mutable_typed_per_filter_config();
-    (*config_map)["envoy.fault"] = std::move(filter_config);
-    return new_route_config;
-  }
-
-  void SetFilterConfig(HTTPFault& http_fault) {
-    switch (GetParam().filter_config_setup()) {
-      case TestType::FilterConfigSetup::kRouteOverride: {
-        Listener listener = BuildListenerWithFaultInjection();
-        RouteConfiguration route =
-            BuildRouteConfigurationWithFaultInjection(http_fault);
-        SetListenerAndRouteConfiguration(0, listener, route);
-        break;
-      }
-      case TestType::FilterConfigSetup::kHTTPConnectionManagerOriginal: {
-        Listener listener = BuildListenerWithFaultInjection(http_fault);
-        SetListenerAndRouteConfiguration(0, listener, default_route_config_);
-      }
-    };
-  }
-};
-
-// Test to ensure the most basic fault injection config works.
-TEST_P(FaultInjectionTest, XdsFaultInjectionAlwaysAbort) {
-  const uint32_t kAbortPercentagePerHundred = 100;
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Construct the fault injection filter config
-  HTTPFault http_fault;
-  auto* abort_percentage = http_fault.mutable_abort()->mutable_percentage();
-  abort_percentage->set_numerator(kAbortPercentagePerHundred);
-  abort_percentage->set_denominator(FractionalPercent::HUNDRED);
-  http_fault.mutable_abort()->set_grpc_status(
-      static_cast<uint32_t>(StatusCode::ABORTED));
-  // Config fault injection via different setup
-  SetFilterConfig(http_fault);
-  // Fire several RPCs, and expect all of them to be aborted.
-  CheckRpcSendFailure(
-      CheckRpcSendFailureOptions()
-          .set_times(5)
-          .set_rpc_options(RpcOptions().set_wait_for_ready(true))
-          .set_expected_error_code(StatusCode::ABORTED));
-}
-
-// Without the listener config, the fault injection won't be enabled.
-TEST_P(FaultInjectionTest, XdsFaultInjectionWithoutListenerFilter) {
-  const uint32_t kAbortPercentagePerHundred = 100;
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Create an EDS resource
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  // Construct the fault injection filter config
-  HTTPFault http_fault;
-  auto* abort_percentage = http_fault.mutable_abort()->mutable_percentage();
-  abort_percentage->set_numerator(kAbortPercentagePerHundred);
-  abort_percentage->set_denominator(FractionalPercent::HUNDRED);
-  http_fault.mutable_abort()->set_grpc_status(
-      static_cast<uint32_t>(StatusCode::ABORTED));
-  // Turn on fault injection
-  RouteConfiguration route =
-      BuildRouteConfigurationWithFaultInjection(http_fault);
-  SetListenerAndRouteConfiguration(0, default_listener_, route);
-  // Fire several RPCs, and expect all of them to be pass.
-  CheckRpcSendOk(5, RpcOptions().set_wait_for_ready(true));
-}
-
-TEST_P(FaultInjectionTest, XdsFaultInjectionPercentageAbort) {
-  const uint32_t kAbortPercentagePerHundred = 50;
-  const double kAbortRate = kAbortPercentagePerHundred / 100.0;
-  const double kErrorTolerance = 0.05;
-  const size_t kNumRpcs = ComputeIdealNumRpcs(kAbortRate, kErrorTolerance);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Create an EDS resource
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  // Construct the fault injection filter config
-  HTTPFault http_fault;
-  auto* abort_percentage = http_fault.mutable_abort()->mutable_percentage();
-  abort_percentage->set_numerator(kAbortPercentagePerHundred);
-  abort_percentage->set_denominator(FractionalPercent::HUNDRED);
-  http_fault.mutable_abort()->set_grpc_status(
-      static_cast<uint32_t>(StatusCode::ABORTED));
-  // Config fault injection via different setup
-  SetFilterConfig(http_fault);
-  // Send kNumRpcs RPCs and count the aborts.
-  int num_total = 0, num_ok = 0, num_failure = 0, num_aborted = 0;
-  for (size_t i = 0; i < kNumRpcs; ++i) {
-    SendRpcAndCount(&num_total, &num_ok, &num_failure, &num_aborted,
-                    RpcOptions(), "Fault injected");
-  }
-  EXPECT_EQ(kNumRpcs, num_total);
-  EXPECT_EQ(0, num_failure);
-  // The abort rate should be roughly equal to the expectation.
-  const double seen_abort_rate = static_cast<double>(num_aborted) / kNumRpcs;
-  EXPECT_THAT(seen_abort_rate,
-              ::testing::DoubleNear(kAbortRate, kErrorTolerance));
-}
-
-TEST_P(FaultInjectionTest, XdsFaultInjectionPercentageAbortViaHeaders) {
-  const uint32_t kAbortPercentageCap = 100;
-  const uint32_t kAbortPercentage = 50;
-  const double kAbortRate = kAbortPercentage / 100.0;
-  const double kErrorTolerance = 0.05;
-  const size_t kNumRpcs = ComputeIdealNumRpcs(kAbortRate, kErrorTolerance);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Create an EDS resource
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  // Construct the fault injection filter config
-  HTTPFault http_fault;
-  http_fault.mutable_abort()->mutable_header_abort();
-  http_fault.mutable_abort()->mutable_percentage()->set_numerator(
-      kAbortPercentageCap);
-  // Config fault injection via different setup
-  SetFilterConfig(http_fault);
-  // Send kNumRpcs RPCs and count the aborts.
-  std::vector<std::pair<std::string, std::string>> metadata = {
-      {"x-envoy-fault-abort-grpc-request", "10"},
-      {"x-envoy-fault-abort-percentage", std::to_string(kAbortPercentage)},
-  };
-  int num_total = 0, num_ok = 0, num_failure = 0, num_aborted = 0;
-  RpcOptions options = RpcOptions().set_metadata(metadata);
-  for (size_t i = 0; i < kNumRpcs; ++i) {
-    SendRpcAndCount(&num_total, &num_ok, &num_failure, &num_aborted, options,
-                    "Fault injected");
-  }
-  EXPECT_EQ(kNumRpcs, num_total);
-  EXPECT_EQ(0, num_failure);
-  // The abort rate should be roughly equal to the expectation.
-  const double seen_abort_rate = static_cast<double>(num_aborted) / kNumRpcs;
-  EXPECT_THAT(seen_abort_rate,
-              ::testing::DoubleNear(kAbortRate, kErrorTolerance));
-}
-
-TEST_P(FaultInjectionTest, XdsFaultInjectionPercentageDelay) {
-  const uint32_t kRpcTimeoutMilliseconds = grpc_test_slowdown_factor() * 3000;
-  const uint32_t kFixedDelaySeconds = 100;
-  const uint32_t kDelayPercentagePerHundred = 50;
-  const double kDelayRate = kDelayPercentagePerHundred / 100.0;
-  const double kErrorTolerance = 0.05;
-  const size_t kNumRpcs = ComputeIdealNumRpcs(kDelayRate, kErrorTolerance);
-  const size_t kMaxConcurrentRequests = kNumRpcs;
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Create an EDS resource
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  // Loosen the max concurrent request limit
-  Cluster cluster = default_cluster_;
-  auto* threshold = cluster.mutable_circuit_breakers()->add_thresholds();
-  threshold->set_priority(RoutingPriority::DEFAULT);
-  threshold->mutable_max_requests()->set_value(kMaxConcurrentRequests);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  // Construct the fault injection filter config
-  HTTPFault http_fault;
-  auto* delay_percentage = http_fault.mutable_delay()->mutable_percentage();
-  delay_percentage->set_numerator(kDelayPercentagePerHundred);
-  delay_percentage->set_denominator(FractionalPercent::HUNDRED);
-  auto* fixed_delay = http_fault.mutable_delay()->mutable_fixed_delay();
-  fixed_delay->set_seconds(kFixedDelaySeconds);
-  // Config fault injection via different setup
-  SetFilterConfig(http_fault);
-  // Send kNumRpcs RPCs and count the delays.
-  RpcOptions rpc_options = RpcOptions()
-                               .set_timeout_ms(kRpcTimeoutMilliseconds)
-                               .set_skip_cancelled_check(true);
-  std::vector<ConcurrentRpc> rpcs =
-      SendConcurrentRpcs(stub_.get(), kNumRpcs, rpc_options);
-  size_t num_delayed = 0;
-  for (auto& rpc : rpcs) {
-    if (rpc.status.error_code() == StatusCode::OK) continue;
-    EXPECT_EQ(StatusCode::DEADLINE_EXCEEDED, rpc.status.error_code());
-    ++num_delayed;
-  }
-  // The delay rate should be roughly equal to the expectation.
-  const double seen_delay_rate = static_cast<double>(num_delayed) / kNumRpcs;
-  EXPECT_THAT(seen_delay_rate,
-              ::testing::DoubleNear(kDelayRate, kErrorTolerance));
-}
-
-TEST_P(FaultInjectionTest, XdsFaultInjectionPercentageDelayViaHeaders) {
-  const uint32_t kFixedDelayMilliseconds = 100000;
-  const uint32_t kRpcTimeoutMilliseconds = grpc_test_slowdown_factor() * 3000;
-  const uint32_t kDelayPercentageCap = 100;
-  const uint32_t kDelayPercentage = 50;
-  const double kDelayRate = kDelayPercentage / 100.0;
-  const double kErrorTolerance = 0.05;
-  const size_t kNumRpcs = ComputeIdealNumRpcs(kDelayRate, kErrorTolerance);
-  const size_t kMaxConcurrentRequests = kNumRpcs;
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Create an EDS resource
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  // Loosen the max concurrent request limit
-  Cluster cluster = default_cluster_;
-  auto* threshold = cluster.mutable_circuit_breakers()->add_thresholds();
-  threshold->set_priority(RoutingPriority::DEFAULT);
-  threshold->mutable_max_requests()->set_value(kMaxConcurrentRequests);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  // Construct the fault injection filter config
-  HTTPFault http_fault;
-  http_fault.mutable_delay()->mutable_header_delay();
-  http_fault.mutable_delay()->mutable_percentage()->set_numerator(
-      kDelayPercentageCap);
-  // Config fault injection via different setup
-  SetFilterConfig(http_fault);
-  // Send kNumRpcs RPCs and count the delays.
-  std::vector<std::pair<std::string, std::string>> metadata = {
-      {"x-envoy-fault-delay-request", std::to_string(kFixedDelayMilliseconds)},
-      {"x-envoy-fault-delay-request-percentage",
-       std::to_string(kDelayPercentage)},
-  };
-  RpcOptions rpc_options = RpcOptions()
-                               .set_metadata(metadata)
-                               .set_timeout_ms(kRpcTimeoutMilliseconds)
-                               .set_skip_cancelled_check(true);
-  std::vector<ConcurrentRpc> rpcs =
-      SendConcurrentRpcs(stub_.get(), kNumRpcs, rpc_options);
-  size_t num_delayed = 0;
-  for (auto& rpc : rpcs) {
-    if (rpc.status.error_code() == StatusCode::OK) continue;
-    EXPECT_EQ(StatusCode::DEADLINE_EXCEEDED, rpc.status.error_code());
-    ++num_delayed;
-  }
-  // The delay rate should be roughly equal to the expectation.
-  const double seen_delay_rate = static_cast<double>(num_delayed) / kNumRpcs;
-  EXPECT_THAT(seen_delay_rate,
-              ::testing::DoubleNear(kDelayRate, kErrorTolerance));
-}
-
-TEST_P(FaultInjectionTest, XdsFaultInjectionAlwaysDelayPercentageAbort) {
-  const uint32_t kAbortPercentagePerHundred = 50;
-  const double kAbortRate = kAbortPercentagePerHundred / 100.0;
-  const uint32_t kFixedDelaySeconds = 1;
-  const uint32_t kRpcTimeoutMilliseconds = 100 * 1000;  // 100s should not reach
-  const uint32_t kConnectionTimeoutMilliseconds =
-      10 * 1000;  // 10s should not reach
-  const double kErrorTolerance = 0.05;
-  const size_t kNumRpcs = ComputeIdealNumRpcs(kAbortRate, kErrorTolerance);
-  const size_t kMaxConcurrentRequests = kNumRpcs;
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Create an EDS resource
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  // Loosen the max concurrent request limit
-  Cluster cluster = default_cluster_;
-  auto* threshold = cluster.mutable_circuit_breakers()->add_thresholds();
-  threshold->set_priority(RoutingPriority::DEFAULT);
-  threshold->mutable_max_requests()->set_value(kMaxConcurrentRequests);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  // Construct the fault injection filter config
-  HTTPFault http_fault;
-  auto* abort_percentage = http_fault.mutable_abort()->mutable_percentage();
-  abort_percentage->set_numerator(kAbortPercentagePerHundred);
-  abort_percentage->set_denominator(FractionalPercent::HUNDRED);
-  http_fault.mutable_abort()->set_grpc_status(
-      static_cast<uint32_t>(StatusCode::ABORTED));
-  auto* delay_percentage = http_fault.mutable_delay()->mutable_percentage();
-  delay_percentage->set_numerator(1000000);  // Always inject DELAY!
-  delay_percentage->set_denominator(FractionalPercent::MILLION);
-  auto* fixed_delay = http_fault.mutable_delay()->mutable_fixed_delay();
-  fixed_delay->set_seconds(kFixedDelaySeconds);
-  // Config fault injection via different setup
-  SetFilterConfig(http_fault);
-  // Allow the channel to connect to one backends, so the herd of queued RPCs
-  // won't be executed on the same ExecCtx object and using the cached Now()
-  // value, which causes millisecond level delay error.
-  channel_->WaitForConnected(
-      grpc_timeout_milliseconds_to_deadline(kConnectionTimeoutMilliseconds));
-  // Send kNumRpcs RPCs and count the aborts.
-  int num_aborted = 0;
-  RpcOptions rpc_options = RpcOptions().set_timeout_ms(kRpcTimeoutMilliseconds);
-  std::vector<ConcurrentRpc> rpcs =
-      SendConcurrentRpcs(stub_.get(), kNumRpcs, rpc_options);
-  for (auto& rpc : rpcs) {
-    EXPECT_GE(rpc.elapsed_time, kFixedDelaySeconds * 1000);
-    if (rpc.status.error_code() == StatusCode::OK) continue;
-    EXPECT_EQ("Fault injected", rpc.status.error_message());
-    ++num_aborted;
-  }
-  // The abort rate should be roughly equal to the expectation.
-  const double seen_abort_rate = static_cast<double>(num_aborted) / kNumRpcs;
-  EXPECT_THAT(seen_abort_rate,
-              ::testing::DoubleNear(kAbortRate, kErrorTolerance));
-}
-
-// This test and the above test apply different denominators to delay and
-// abort. This ensures that we are using the right denominator for each
-// injected fault in our code.
-TEST_P(FaultInjectionTest,
-       XdsFaultInjectionAlwaysDelayPercentageAbortSwitchDenominator) {
-  const uint32_t kAbortPercentagePerMillion = 500000;
-  const double kAbortRate = kAbortPercentagePerMillion / 1000000.0;
-  const uint32_t kFixedDelaySeconds = 1;                // 1s
-  const uint32_t kRpcTimeoutMilliseconds = 100 * 1000;  // 100s should not reach
-  const uint32_t kConnectionTimeoutMilliseconds =
-      10 * 1000;  // 10s should not reach
-  const double kErrorTolerance = 0.05;
-  const size_t kNumRpcs = ComputeIdealNumRpcs(kAbortRate, kErrorTolerance);
-  const size_t kMaxConcurrentRequests = kNumRpcs;
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Create an EDS resource
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  // Loosen the max concurrent request limit
-  Cluster cluster = default_cluster_;
-  auto* threshold = cluster.mutable_circuit_breakers()->add_thresholds();
-  threshold->set_priority(RoutingPriority::DEFAULT);
-  threshold->mutable_max_requests()->set_value(kMaxConcurrentRequests);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  // Construct the fault injection filter config
-  HTTPFault http_fault;
-  auto* abort_percentage = http_fault.mutable_abort()->mutable_percentage();
-  abort_percentage->set_numerator(kAbortPercentagePerMillion);
-  abort_percentage->set_denominator(FractionalPercent::MILLION);
-  http_fault.mutable_abort()->set_grpc_status(
-      static_cast<uint32_t>(StatusCode::ABORTED));
-  auto* delay_percentage = http_fault.mutable_delay()->mutable_percentage();
-  delay_percentage->set_numerator(100);  // Always inject DELAY!
-  delay_percentage->set_denominator(FractionalPercent::HUNDRED);
-  auto* fixed_delay = http_fault.mutable_delay()->mutable_fixed_delay();
-  fixed_delay->set_seconds(kFixedDelaySeconds);
-  // Config fault injection via different setup
-  SetFilterConfig(http_fault);
-  // Allow the channel to connect to one backends, so the herd of queued RPCs
-  // won't be executed on the same ExecCtx object and using the cached Now()
-  // value, which causes millisecond level delay error.
-  channel_->WaitForConnected(
-      grpc_timeout_milliseconds_to_deadline(kConnectionTimeoutMilliseconds));
-  // Send kNumRpcs RPCs and count the aborts.
-  int num_aborted = 0;
-  RpcOptions rpc_options = RpcOptions().set_timeout_ms(kRpcTimeoutMilliseconds);
-  std::vector<ConcurrentRpc> rpcs =
-      SendConcurrentRpcs(stub_.get(), kNumRpcs, rpc_options);
-  for (auto& rpc : rpcs) {
-    EXPECT_GE(rpc.elapsed_time, kFixedDelaySeconds * 1000);
-    if (rpc.status.error_code() == StatusCode::OK) continue;
-    EXPECT_EQ("Fault injected", rpc.status.error_message());
-    ++num_aborted;
-  }
-  // The abort rate should be roughly equal to the expectation.
-  const double seen_abort_rate = static_cast<double>(num_aborted) / kNumRpcs;
-  EXPECT_THAT(seen_abort_rate,
-              ::testing::DoubleNear(kAbortRate, kErrorTolerance));
-}
-
-TEST_P(FaultInjectionTest, XdsFaultInjectionMaxFault) {
-  const uint32_t kMaxFault = 10;
-  const uint32_t kNumRpcs = 30;  // kNumRpcs should be bigger than kMaxFault
-  const uint32_t kRpcTimeoutMs = 4000;     // 4 seconds
-  const uint32_t kLongDelaySeconds = 100;  // 100 seconds
-  const uint32_t kAlwaysDelayPercentage = 100;
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Create an EDS resource
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  // Construct the fault injection filter config
-  HTTPFault http_fault;
-  auto* delay_percentage = http_fault.mutable_delay()->mutable_percentage();
-  delay_percentage->set_numerator(
-      kAlwaysDelayPercentage);  // Always inject DELAY!
-  delay_percentage->set_denominator(FractionalPercent::HUNDRED);
-  auto* fixed_delay = http_fault.mutable_delay()->mutable_fixed_delay();
-  fixed_delay->set_seconds(kLongDelaySeconds);
-  http_fault.mutable_max_active_faults()->set_value(kMaxFault);
-  // Config fault injection via different setup
-  SetFilterConfig(http_fault);
-  // Sends a batch of long running RPCs with long timeout to consume all
-  // active faults quota.
-  int num_delayed = 0;
-  RpcOptions rpc_options = RpcOptions().set_timeout_ms(kRpcTimeoutMs);
-  std::vector<ConcurrentRpc> rpcs =
-      SendConcurrentRpcs(stub_.get(), kNumRpcs, rpc_options);
-  for (auto& rpc : rpcs) {
-    if (rpc.status.error_code() == StatusCode::OK) continue;
-    EXPECT_EQ(StatusCode::DEADLINE_EXCEEDED, rpc.status.error_code());
-    ++num_delayed;
-  }
-  // Only kMaxFault number of RPC should be fault injected..
-  EXPECT_EQ(kMaxFault, num_delayed);
-}
-
-TEST_P(FaultInjectionTest, XdsFaultInjectionBidiStreamDelayOk) {
-  // kRpcTimeoutMilliseconds is 10s should never be reached.
-  const uint32_t kRpcTimeoutMilliseconds = grpc_test_slowdown_factor() * 10000;
-  const uint32_t kFixedDelaySeconds = 1;
-  const uint32_t kDelayPercentagePerHundred = 100;
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Create an EDS resource
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  // Construct the fault injection filter config
-  HTTPFault http_fault;
-  auto* delay_percentage = http_fault.mutable_delay()->mutable_percentage();
-  delay_percentage->set_numerator(kDelayPercentagePerHundred);
-  delay_percentage->set_denominator(FractionalPercent::HUNDRED);
-  auto* fixed_delay = http_fault.mutable_delay()->mutable_fixed_delay();
-  fixed_delay->set_seconds(kFixedDelaySeconds);
-  // Config fault injection via different setup
-  SetFilterConfig(http_fault);
-  ClientContext context;
-  context.set_deadline(
-      grpc_timeout_milliseconds_to_deadline(kRpcTimeoutMilliseconds));
-  auto stream = stub_->BidiStream(&context);
-  stream->WritesDone();
-  auto status = stream->Finish();
-  EXPECT_TRUE(status.ok()) << status.error_message() << ", "
-                           << status.error_details() << ", "
-                           << context.debug_error_string();
-}
-
-// This case catches a bug in the retry code that was triggered by a bad
-// interaction with the FI code.  See https://github.com/grpc/grpc/pull/27217
-// for description.
-TEST_P(FaultInjectionTest, XdsFaultInjectionBidiStreamDelayError) {
-  const uint32_t kRpcTimeoutMilliseconds = grpc_test_slowdown_factor() * 500;
-  const uint32_t kFixedDelaySeconds = 100;
-  const uint32_t kDelayPercentagePerHundred = 100;
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Create an EDS resource
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  // Construct the fault injection filter config
-  HTTPFault http_fault;
-  auto* delay_percentage = http_fault.mutable_delay()->mutable_percentage();
-  delay_percentage->set_numerator(kDelayPercentagePerHundred);
-  delay_percentage->set_denominator(FractionalPercent::HUNDRED);
-  auto* fixed_delay = http_fault.mutable_delay()->mutable_fixed_delay();
-  fixed_delay->set_seconds(kFixedDelaySeconds);
-  // Config fault injection via different setup
-  SetFilterConfig(http_fault);
-  ClientContext context;
-  context.set_deadline(
-      grpc_timeout_milliseconds_to_deadline(kRpcTimeoutMilliseconds));
-  auto stream = stub_->BidiStream(&context);
-  stream->WritesDone();
-  auto status = stream->Finish();
-  EXPECT_EQ(StatusCode::DEADLINE_EXCEEDED, status.error_code())
-      << status.error_message() << ", " << status.error_details() << ", "
-      << context.debug_error_string();
-}
-
-class BootstrapSourceTest : public XdsEnd2endTest {
- public:
-  BootstrapSourceTest() : XdsEnd2endTest(4, 1) {}
-};
-
-TEST_P(BootstrapSourceTest, Vanilla) {
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", CreateEndpointsForBackends()},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  WaitForAllBackends();
-}
-
-#ifndef DISABLED_XDS_PROTO_IN_CC
-class ClientStatusDiscoveryServiceTest : public XdsEnd2endTest {
- public:
-  ClientStatusDiscoveryServiceTest() : XdsEnd2endTest(1, 1) {}
-
-  void SetUp() override {
-    XdsEnd2endTest::SetUp();
-    admin_server_thread_ = absl::make_unique<AdminServerThread>(this);
-    admin_server_thread_->Start();
-    std::string admin_server_address = absl::StrCat(
-        ipv6_only_ ? "[::1]:" : "127.0.0.1:", admin_server_thread_->port());
-    admin_channel_ = grpc::CreateChannel(
-        admin_server_address,
-        std::make_shared<SecureChannelCredentials>(
-            grpc_fake_transport_security_credentials_create()));
-    csds_stub_ =
-        envoy::service::status::v3::ClientStatusDiscoveryService::NewStub(
-            admin_channel_);
-    if (GetParam().use_csds_streaming()) {
-      stream_ = csds_stub_->StreamClientStatus(&stream_context_);
-    }
-  }
-
-  void TearDown() override {
-    if (stream_ != nullptr) {
-      EXPECT_TRUE(stream_->WritesDone());
-      Status status = stream_->Finish();
-      EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
-                               << " message=" << status.error_message();
-    }
-    admin_server_thread_->Shutdown();
-    XdsEnd2endTest::TearDown();
-  }
-
-  envoy::service::status::v3::ClientStatusResponse FetchCsdsResponse() {
-    envoy::service::status::v3::ClientStatusResponse response;
-    if (!GetParam().use_csds_streaming()) {
-      // Fetch through unary pulls
-      ClientContext context;
-      Status status = csds_stub_->FetchClientStatus(
-          &context, envoy::service::status::v3::ClientStatusRequest(),
-          &response);
-      EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
-                               << " message=" << status.error_message();
-    } else {
-      // Fetch through streaming pulls
-      EXPECT_TRUE(
-          stream_->Write(envoy::service::status::v3::ClientStatusRequest()));
-      EXPECT_TRUE(stream_->Read(&response));
-    }
-    return response;
-  }
-
- private:
-  std::unique_ptr<AdminServerThread> admin_server_thread_;
-  std::shared_ptr<Channel> admin_channel_;
-  std::unique_ptr<
-      envoy::service::status::v3::ClientStatusDiscoveryService::Stub>
-      csds_stub_;
-  ClientContext stream_context_;
-  std::unique_ptr<
-      ClientReaderWriter<envoy::service::status::v3::ClientStatusRequest,
-                         envoy::service::status::v3::ClientStatusResponse>>
-      stream_;
-};
-
-MATCHER_P4(EqNode, id, user_agent_name, user_agent_version, client_features,
-           "equals Node") {
-  bool ok = true;
-  ok &= ::testing::ExplainMatchResult(id, arg.id(), result_listener);
-  ok &= ::testing::ExplainMatchResult(user_agent_name, arg.user_agent_name(),
-                                      result_listener);
-  ok &= ::testing::ExplainMatchResult(
-      user_agent_version, arg.user_agent_version(), result_listener);
-  ok &= ::testing::ExplainMatchResult(client_features, arg.client_features(),
-                                      result_listener);
-  return ok;
-}
-
-MATCHER_P2(EqListenersConfigDump, version_info, dynamic_listeners,
-           "equals ListenerConfigDump") {
-  bool ok = true;
-  ok &= ::testing::ExplainMatchResult(::testing::ElementsAre(),
-                                      arg.static_listeners(), result_listener);
-  ok &= ::testing::ExplainMatchResult(version_info, arg.version_info(),
-                                      result_listener);
-  ok &= ::testing::ExplainMatchResult(dynamic_listeners,
-                                      arg.dynamic_listeners(), result_listener);
-  return ok;
-}
-
-MATCHER_P2(EqDynamicListenerState, version_info, listener,
-           "equals DynamicListenerState") {
-  bool ok = true;
-  ok &= ::testing::ExplainMatchResult(version_info, arg.version_info(),
-                                      result_listener);
-  ok &=
-      ::testing::ExplainMatchResult(listener, arg.listener(), result_listener);
-  return ok;
-}
-
-MATCHER_P2(EqListener, name, api_listener, "equals Listener") {
-  bool ok = true;
-  ok &= ::testing::ExplainMatchResult(name, arg.name(), result_listener);
-  ok &= ::testing::ExplainMatchResult(
-      api_listener, arg.api_listener().api_listener(), result_listener);
-  return ok;
-}
-
-MATCHER_P(EqHttpConnectionManagerNotRds, route_config,
-          "equals HttpConnectionManager") {
-  bool ok = true;
-  ok &= ::testing::ExplainMatchResult(route_config, arg.route_config(),
-                                      result_listener);
-  return ok;
-}
-
-MATCHER_P(EqRouteConfigurationName, name, "equals RouteConfiguration") {
-  bool ok = true;
-  ok &= ::testing::ExplainMatchResult(name, arg.name(), result_listener);
-  return ok;
-}
-
-MATCHER_P2(EqRouteConfiguration, name, cluster_name,
-           "equals RouteConfiguration") {
-  bool ok = true;
-  ok &= ::testing::ExplainMatchResult(name, arg.name(), result_listener);
-  ok &= ::testing::ExplainMatchResult(
-      ::testing::ElementsAre(::testing::Property(
-          &envoy::config::route::v3::VirtualHost::routes,
-          ::testing::ElementsAre(::testing::Property(
-              &envoy::config::route::v3::Route::route,
-              ::testing::Property(
-                  &envoy::config::route::v3::RouteAction::cluster,
-                  cluster_name))))),
-      arg.virtual_hosts(), result_listener);
-  return ok;
-}
-
-MATCHER_P(EqRoutesConfigDump, dynamic_route_configs,
-          "equals RoutesConfigDump") {
-  bool ok = true;
-  ok &= ::testing::ExplainMatchResult(
-      ::testing::ElementsAre(), arg.static_route_configs(), result_listener);
-  ok &= ::testing::ExplainMatchResult(
-      dynamic_route_configs, arg.dynamic_route_configs(), result_listener);
-  return ok;
-}
-
-MATCHER_P2(EqClustersConfigDump, version_info, dynamic_active_clusters,
-           "equals ClustersConfigDump") {
-  bool ok = true;
-  ok &= ::testing::ExplainMatchResult(::testing::ElementsAre(),
-                                      arg.static_clusters(), result_listener);
-  ok &= ::testing::ExplainMatchResult(::testing::ElementsAre(),
-                                      arg.dynamic_warming_clusters(),
-                                      result_listener);
-  ok &= ::testing::ExplainMatchResult(version_info, arg.version_info(),
-                                      result_listener);
-  ok &= ::testing::ExplainMatchResult(
-      dynamic_active_clusters, arg.dynamic_active_clusters(), result_listener);
-  return ok;
-}
-
-MATCHER_P(EqCluster, name, "equals Cluster") {
-  bool ok = true;
-  ok &= ::testing::ExplainMatchResult(name, arg.name(), result_listener);
-  return ok;
-}
-
-MATCHER_P(EqEndpointsConfigDump, dynamic_endpoint_configs,
-          "equals EndpointsConfigDump") {
-  bool ok = true;
-  ok &= ::testing::ExplainMatchResult(dynamic_endpoint_configs,
-                                      arg.dynamic_endpoint_configs(),
-                                      result_listener);
-  return ok;
-}
-
-MATCHER_P(EqEndpoint, port, "equals Endpoint") {
-  bool ok = true;
-  ok &= ::testing::ExplainMatchResult(
-      port, arg.address().socket_address().port_value(), result_listener);
-  return ok;
-}
-
-MATCHER_P2(EqLocalityLbEndpoints, port, weight, "equals LocalityLbEndpoints") {
-  bool ok = true;
-  ok &= ::testing::ExplainMatchResult(
-      ::testing::ElementsAre(::testing::Property(
-          &envoy::config::endpoint::v3::LbEndpoint::endpoint,
-          EqEndpoint(port))),
-      arg.lb_endpoints(), result_listener);
-  ok &= ::testing::ExplainMatchResult(
-      weight, arg.load_balancing_weight().value(), result_listener);
-  return ok;
-}
-
-MATCHER_P(EqClusterLoadAssignmentName, cluster_name,
-          "equals ClusterLoadAssignment") {
-  bool ok = true;
-  ok &= ::testing::ExplainMatchResult(cluster_name, arg.cluster_name(),
-                                      result_listener);
-  return ok;
-}
-
-MATCHER_P3(EqClusterLoadAssignment, cluster_name, port, weight,
-           "equals ClusterLoadAssignment") {
-  bool ok = true;
-  ok &= ::testing::ExplainMatchResult(cluster_name, arg.cluster_name(),
-                                      result_listener);
-  ok &= ::testing::ExplainMatchResult(
-      ::testing::ElementsAre(EqLocalityLbEndpoints(port, weight)),
-      arg.endpoints(), result_listener);
-  return ok;
-}
-
-MATCHER_P2(EqUpdateFailureState, details, version_info,
-           "equals UpdateFailureState") {
-  bool ok = true;
-  ok &= ::testing::ExplainMatchResult(details, arg.details(), result_listener);
-  ok &= ::testing::ExplainMatchResult(version_info, arg.version_info(),
-                                      result_listener);
-  return ok;
-}
-
-MATCHER_P(UnpackListener, matcher, "is a Listener") {
-  Listener config;
-  if (!::testing::ExplainMatchResult(true, arg.UnpackTo(&config),
-                                     result_listener)) {
-    return false;
-  }
-  return ::testing::ExplainMatchResult(matcher, config, result_listener);
-}
-
-MATCHER_P(UnpackRouteConfiguration, matcher, "is a RouteConfiguration") {
-  RouteConfiguration config;
-  if (!::testing::ExplainMatchResult(true, arg.UnpackTo(&config),
-                                     result_listener)) {
-    return false;
-  }
-  return ::testing::ExplainMatchResult(matcher, config, result_listener);
-}
-
-MATCHER_P(UnpackHttpConnectionManager, matcher, "is a HttpConnectionManager") {
-  HttpConnectionManager config;
-  if (!::testing::ExplainMatchResult(true, arg.UnpackTo(&config),
-                                     result_listener)) {
-    return false;
-  }
-  return ::testing::ExplainMatchResult(matcher, config, result_listener);
-}
-
-MATCHER_P(UnpackCluster, matcher, "is a Cluster") {
-  Cluster config;
-  if (!::testing::ExplainMatchResult(true, arg.UnpackTo(&config),
-                                     result_listener)) {
-    return false;
-  }
-  return ::testing::ExplainMatchResult(matcher, config, result_listener);
-}
-
-MATCHER_P(UnpackClusterLoadAssignment, matcher, "is a ClusterLoadAssignment") {
-  ClusterLoadAssignment config;
-  if (!::testing::ExplainMatchResult(true, arg.UnpackTo(&config),
-                                     result_listener)) {
-    return false;
-  }
-  return ::testing::ExplainMatchResult(matcher, config, result_listener);
-}
-
-MATCHER_P5(EqDynamicListener, name, version_info, client_status,
-           api_listener_matcher, error_state, "equals DynamicListener") {
-  bool ok = true;
-  ok &= ::testing::ExplainMatchResult(false, arg.has_warming_state(),
-                                      result_listener);
-  ok &= ::testing::ExplainMatchResult(false, arg.has_draining_state(),
-                                      result_listener);
-  ok &= ::testing::ExplainMatchResult(name, arg.name(), result_listener);
-  ok &= ::testing::ExplainMatchResult(client_status, arg.client_status(),
-                                      result_listener);
-  if (client_status == ClientResourceStatus::ACKED ||
-      client_status == ClientResourceStatus::NACKED) {
-    ok &= ::testing::ExplainMatchResult(
-        EqDynamicListenerState(version_info, UnpackListener(EqListener(
-                                                 name, api_listener_matcher))),
-        arg.active_state(), result_listener);
-  }
-  ok &= ::testing::ExplainMatchResult(error_state, arg.error_state(),
-                                      result_listener);
-  return ok;
-}
-
-MATCHER_P5(EqDynamicRouteConfig, name, version_info, client_status,
-           cluster_name, error_state, "equals DynamicRouteConfig") {
-  bool ok = true;
-  ok &= ::testing::ExplainMatchResult(version_info, arg.version_info(),
-                                      result_listener);
-  if (client_status == ClientResourceStatus::REQUESTED ||
-      client_status == ClientResourceStatus::DOES_NOT_EXIST) {
-    ok &= ::testing::ExplainMatchResult(
-        UnpackRouteConfiguration(EqRouteConfigurationName(name)),
-        arg.route_config(), result_listener);
-  } else {
-    ok &= ::testing::ExplainMatchResult(
-        UnpackRouteConfiguration(EqRouteConfiguration(name, cluster_name)),
-        arg.route_config(), result_listener);
-  }
-  ok &= ::testing::ExplainMatchResult(error_state, arg.error_state(),
-                                      result_listener);
-  ok &= ::testing::ExplainMatchResult(client_status, arg.client_status(),
-                                      result_listener);
-  return ok;
-}
-
-MATCHER_P4(EqDynamicCluster, name, version_info, client_status, error_state,
-           "equals DynamicCluster") {
-  bool ok = true;
-  ok &= ::testing::ExplainMatchResult(UnpackCluster(EqCluster(name)),
-                                      arg.cluster(), result_listener);
-  ok &= ::testing::ExplainMatchResult(version_info, arg.version_info(),
-                                      result_listener);
-  ok &= ::testing::ExplainMatchResult(client_status, arg.client_status(),
-                                      result_listener);
-  ok &= ::testing::ExplainMatchResult(error_state, arg.error_state(),
-                                      result_listener);
-  return ok;
-}
-
-MATCHER_P6(EqDynamicEndpointConfig, name, version_info, client_status, port,
-           weight, error_state, "equals DynamicEndpointConfig") {
-  bool ok = true;
-  if (client_status == ClientResourceStatus::REQUESTED ||
-      client_status == ClientResourceStatus::DOES_NOT_EXIST) {
-    ok &= ::testing::ExplainMatchResult(
-        UnpackClusterLoadAssignment(EqClusterLoadAssignmentName(name)),
-        arg.endpoint_config(), result_listener);
-  } else {
-    ok &= ::testing::ExplainMatchResult(
-        UnpackClusterLoadAssignment(
-            EqClusterLoadAssignment(name, port, weight)),
-        arg.endpoint_config(), result_listener);
-  }
-  ok &= ::testing::ExplainMatchResult(version_info, arg.version_info(),
-                                      result_listener);
-  ok &= ::testing::ExplainMatchResult(client_status, arg.client_status(),
-                                      result_listener);
-  ok &= ::testing::ExplainMatchResult(error_state, arg.error_state(),
-                                      result_listener);
-  return ok;
-}
-
-MATCHER(IsRdsEnabledHCM, "is a RDS enabled HttpConnectionManager") {
-  return ::testing::ExplainMatchResult(
-      UnpackHttpConnectionManager(
-          ::testing::Property(&HttpConnectionManager::has_rds, true)),
-      arg, result_listener);
-}
-
-MATCHER_P2(EqNoRdsHCM, route_configuration_name, cluster_name,
-           "equals RDS disabled HttpConnectionManager") {
-  return ::testing::ExplainMatchResult(
-      UnpackHttpConnectionManager(EqHttpConnectionManagerNotRds(
-          EqRouteConfiguration(route_configuration_name, cluster_name))),
-      arg, result_listener);
-}
-
-TEST_P(ClientStatusDiscoveryServiceTest, XdsConfigDumpVanilla) {
-  const size_t kNumRpcs = 5;
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  AdsServiceImpl::EdsResourceArgs args(
-      {{"locality0", CreateEndpointsForBackends(0, 1)}});
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  // Send several RPCs to ensure the xDS setup works
-  CheckRpcSendOk(kNumRpcs);
-  // Fetches the client config
-  auto csds_response = FetchCsdsResponse();
-  gpr_log(GPR_INFO, "xDS config dump: %s", csds_response.DebugString().c_str());
-  EXPECT_EQ(1, csds_response.config_size());
-  const auto& client_config = csds_response.config(0);
-  // Validate the Node information
-  EXPECT_THAT(client_config.node(),
-              EqNode("xds_end2end_test", ::testing::HasSubstr("C-core"),
-                     ::testing::HasSubstr(grpc_version_string()),
-                     ::testing::ElementsAre(
-                         "envoy.lb.does_not_support_overprovisioning")));
-  // Prepare matches for RDS on or off
-  ::testing::Matcher<google::protobuf::Any> api_listener_matcher;
-  ::testing::Matcher<envoy::admin::v3::RoutesConfigDump>
-      route_config_dump_matcher;
-  if (GetParam().enable_rds_testing()) {
-    api_listener_matcher = IsRdsEnabledHCM();
-    route_config_dump_matcher =
-        EqRoutesConfigDump(::testing::ElementsAre(EqDynamicRouteConfig(
-            kDefaultRouteConfigurationName, "1", ClientResourceStatus::ACKED,
-            kDefaultClusterName, ::testing::_)));
-  } else {
-    api_listener_matcher =
-        EqNoRdsHCM(kDefaultRouteConfigurationName, kDefaultClusterName);
-    route_config_dump_matcher = EqRoutesConfigDump(::testing::ElementsAre());
-  }
-  // Validate the dumped xDS configs
-  EXPECT_THAT(
-      client_config.xds_config(),
-      ::testing::UnorderedElementsAre(
-          ::testing::Property(
-              &envoy::service::status::v3::PerXdsConfig::listener_config,
-              EqListenersConfigDump(
-                  "1", ::testing::ElementsAre(EqDynamicListener(
-                           kServerName, "1", ClientResourceStatus::ACKED,
-                           api_listener_matcher, ::testing::_)))),
-          ::testing::Property(
-              &envoy::service::status::v3::PerXdsConfig::route_config,
-              route_config_dump_matcher),
-          ::testing::Property(
-              &envoy::service::status::v3::PerXdsConfig::cluster_config,
-              EqClustersConfigDump(
-                  "1", ::testing::ElementsAre(EqDynamicCluster(
-                           kDefaultClusterName, "1",
-                           ClientResourceStatus::ACKED, ::testing::_)))),
-          ::testing::Property(
-              &envoy::service::status::v3::PerXdsConfig::endpoint_config,
-              EqEndpointsConfigDump(
-                  ::testing::ElementsAre(EqDynamicEndpointConfig(
-                      kDefaultEdsServiceName, "1", ClientResourceStatus::ACKED,
-                      backends_[0]->port(), kDefaultLocalityWeight,
-                      ::testing::_))))));
-}
-
-TEST_P(ClientStatusDiscoveryServiceTest, XdsConfigDumpEmpty) {
-  // The CSDS service should not fail if XdsClient is not initialized or there
-  // is no working xDS configs.
-  FetchCsdsResponse();
-}
-
-TEST_P(ClientStatusDiscoveryServiceTest, XdsConfigDumpListenerError) {
-  int kFetchConfigRetries = 3;
-  int kFetchIntervalMilliseconds = 200;
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  AdsServiceImpl::EdsResourceArgs args(
-      {{"locality0", CreateEndpointsForBackends(0, 1)}});
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  // Ensure the xDS resolver has working configs.
-  CheckRpcSendOk();
-  // Bad Listener should be rejected.
-  Listener listener;
-  listener.set_name(kServerName);
-  balancers_[0]->ads_service()->SetLdsResource(listener);
-  // The old xDS configs should still be effective.
-  CheckRpcSendOk();
-  ::testing::Matcher<google::protobuf::Any> api_listener_matcher;
-  if (GetParam().enable_rds_testing()) {
-    api_listener_matcher = IsRdsEnabledHCM();
-  } else {
-    api_listener_matcher =
-        EqNoRdsHCM(kDefaultRouteConfigurationName, kDefaultClusterName);
-  }
-  for (int o = 0; o < kFetchConfigRetries; o++) {
-    auto csds_response = FetchCsdsResponse();
-    // Check if error state is propagated
-    bool ok = ::testing::Value(
-        csds_response.config(0).xds_config(),
-        ::testing::Contains(::testing::Property(
-            &envoy::service::status::v3::PerXdsConfig::listener_config,
-            EqListenersConfigDump(
-                "1",
-                ::testing::ElementsAre(EqDynamicListener(
-                    kServerName, "1", ClientResourceStatus::NACKED,
-                    api_listener_matcher,
-                    EqUpdateFailureState(
-                        ::testing::HasSubstr(
-                            "Listener has neither address nor ApiListener"),
-                        "2")))))));
-    if (ok) return;  // TEST PASSED!
-    gpr_sleep_until(
-        grpc_timeout_milliseconds_to_deadline(kFetchIntervalMilliseconds));
-  }
-  FAIL() << "error_state not seen in CSDS responses";
-}
-
-TEST_P(ClientStatusDiscoveryServiceTest, XdsConfigDumpRouteError) {
-  int kFetchConfigRetries = 3;
-  int kFetchIntervalMilliseconds = 200;
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  AdsServiceImpl::EdsResourceArgs args(
-      {{"locality0", CreateEndpointsForBackends(0, 1)}});
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  // Ensure the xDS resolver has working configs.
-  CheckRpcSendOk();
-  // Bad route config will be rejected.
-  RouteConfiguration route_config;
-  route_config.set_name(kDefaultRouteConfigurationName);
-  route_config.add_virtual_hosts();
-  SetRouteConfiguration(0, route_config);
-  // The old xDS configs should still be effective.
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  CheckRpcSendOk();
-  for (int o = 0; o < kFetchConfigRetries; o++) {
-    auto csds_response = FetchCsdsResponse();
-    bool ok = false;
-    if (GetParam().enable_rds_testing()) {
-      ok = ::testing::Value(
-          csds_response.config(0).xds_config(),
-          ::testing::Contains(::testing::Property(
-              &envoy::service::status::v3::PerXdsConfig::route_config,
-              EqRoutesConfigDump(::testing::ElementsAre(EqDynamicRouteConfig(
-                  kDefaultRouteConfigurationName, "1",
-                  ClientResourceStatus::NACKED, kDefaultClusterName,
-                  EqUpdateFailureState(
-                      ::testing::HasSubstr("VirtualHost has no domains"),
-                      "2")))))));
-    } else {
-      ok = ::testing::Value(
-          csds_response.config(0).xds_config(),
-          ::testing::Contains(::testing::Property(
-              &envoy::service::status::v3::PerXdsConfig::listener_config,
-              EqListenersConfigDump(
-                  "1",
-                  ::testing::ElementsAre(EqDynamicListener(
-                      kServerName, "1", ClientResourceStatus::NACKED,
-                      EqNoRdsHCM(kDefaultRouteConfigurationName,
-                                 kDefaultClusterName),
-                      EqUpdateFailureState(
-                          ::testing::HasSubstr("VirtualHost has no domains"),
-                          "2")))))));
-    }
-    if (ok) return;  // TEST PASSED!
-    gpr_sleep_until(
-        grpc_timeout_milliseconds_to_deadline(kFetchIntervalMilliseconds));
-  }
-  FAIL() << "error_state not seen in CSDS responses";
-}
-
-TEST_P(ClientStatusDiscoveryServiceTest, XdsConfigDumpClusterError) {
-  int kFetchConfigRetries = 3;
-  int kFetchIntervalMilliseconds = 200;
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  AdsServiceImpl::EdsResourceArgs args(
-      {{"locality0", CreateEndpointsForBackends(0, 1)}});
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  // Ensure the xDS resolver has working configs.
-  CheckRpcSendOk();
-  // Listener without any route, will be rejected.
-  Cluster cluster;
-  cluster.set_name(kDefaultClusterName);
-  balancers_[0]->ads_service()->SetCdsResource(cluster);
-  // The old xDS configs should still be effective.
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  CheckRpcSendOk();
-  for (int o = 0; o < kFetchConfigRetries; o++) {
-    auto csds_response = FetchCsdsResponse();
-    // Check if error state is propagated
-    bool ok = ::testing::Value(
-        csds_response.config(0).xds_config(),
-        ::testing::Contains(::testing::Property(
-            &envoy::service::status::v3::PerXdsConfig::cluster_config,
-            EqClustersConfigDump(
-                "1", ::testing::ElementsAre(EqDynamicCluster(
-                         kDefaultClusterName, "1", ClientResourceStatus::NACKED,
-                         EqUpdateFailureState(
-                             ::testing::HasSubstr("DiscoveryType not found"),
-                             "2")))))));
-    if (ok) return;  // TEST PASSED!
-    gpr_sleep_until(
-        grpc_timeout_milliseconds_to_deadline(kFetchIntervalMilliseconds));
-  }
-  FAIL() << "error_state not seen in CSDS responses";
-}
-
-TEST_P(ClientStatusDiscoveryServiceTest, XdsConfigDumpEndpointError) {
-  int kFetchConfigRetries = 3;
-  int kFetchIntervalMilliseconds = 200;
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  AdsServiceImpl::EdsResourceArgs args(
-      {{"locality0", CreateEndpointsForBackends(0, 1)}});
-  balancers_[0]->ads_service()->SetEdsResource(
-      BuildEdsResource(args, DefaultEdsServiceName()));
-  // Ensure the xDS resolver has working configs.
-  CheckRpcSendOk();
-  // Bad endpoint config will be rejected.
-  ClusterLoadAssignment cluster_load_assignment;
-  cluster_load_assignment.set_cluster_name(kDefaultEdsServiceName);
-  auto* endpoints = cluster_load_assignment.add_endpoints();
-  endpoints->mutable_load_balancing_weight()->set_value(1);
-  auto* endpoint = endpoints->add_lb_endpoints()->mutable_endpoint();
-  endpoint->mutable_address()->mutable_socket_address()->set_port_value(1 << 1);
-  balancers_[0]->ads_service()->SetEdsResource(cluster_load_assignment);
-  // The old xDS configs should still be effective.
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  CheckRpcSendOk();
-  for (int o = 0; o < kFetchConfigRetries; o++) {
-    auto csds_response = FetchCsdsResponse();
-    // Check if error state is propagated
-    bool ok = ::testing::Value(
-        csds_response.config(0).xds_config(),
-        ::testing::Contains(::testing::Property(
-            &envoy::service::status::v3::PerXdsConfig::endpoint_config,
-            EqEndpointsConfigDump(
-                ::testing::ElementsAre(EqDynamicEndpointConfig(
-                    kDefaultEdsServiceName, "1", ClientResourceStatus::NACKED,
-                    backends_[0]->port(), kDefaultLocalityWeight,
-                    EqUpdateFailureState(::testing::HasSubstr("Empty locality"),
-                                         "2")))))));
-    if (ok) return;  // TEST PASSED!
-    gpr_sleep_until(
-        grpc_timeout_milliseconds_to_deadline(kFetchIntervalMilliseconds));
-  }
-  FAIL() << "error_state not seen in CSDS responses";
-}
-
-TEST_P(ClientStatusDiscoveryServiceTest, XdsConfigDumpListenerRequested) {
-  int kTimeoutMillisecond = 1000;
-  balancers_[0]->ads_service()->UnsetResource(kLdsTypeUrl, kServerName);
-  CheckRpcSendFailure(
-      CheckRpcSendFailureOptions()
-          .set_rpc_options(RpcOptions().set_timeout_ms(kTimeoutMillisecond))
-          .set_expected_error_code(StatusCode::DEADLINE_EXCEEDED));
-  auto csds_response = FetchCsdsResponse();
-  EXPECT_THAT(csds_response.config(0).xds_config(),
-              ::testing::Contains(::testing::Property(
-                  &envoy::service::status::v3::PerXdsConfig::listener_config,
-                  EqListenersConfigDump(
-                      ::testing::_, ::testing::ElementsAre(EqDynamicListener(
-                                        kServerName, ::testing::_,
-                                        ClientResourceStatus::REQUESTED,
-                                        ::testing::_, ::testing::_))))));
-}
-
-TEST_P(ClientStatusDiscoveryServiceTest, XdsConfigDumpClusterRequested) {
-  int kTimeoutMillisecond = 1000;
-  std::string kClusterName1 = "cluster-1";
-  std::string kClusterName2 = "cluster-2";
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  // Create a route config requesting two non-existing clusters
-  RouteConfiguration route_config;
-  route_config.set_name(kDefaultRouteConfigurationName);
-  auto* vh = route_config.add_virtual_hosts();
-  // The VirtualHost must match the domain name, otherwise will cause resolver
-  // transient failure.
-  vh->add_domains("*");
-  auto* routes1 = vh->add_routes();
-  routes1->mutable_match()->set_prefix("");
-  routes1->mutable_route()->set_cluster(kClusterName1);
-  auto* routes2 = vh->add_routes();
-  routes2->mutable_match()->set_prefix("");
-  routes2->mutable_route()->set_cluster(kClusterName2);
-  SetRouteConfiguration(0, route_config);
-  // Try to get the configs plumb through
-  CheckRpcSendFailure(
-      CheckRpcSendFailureOptions()
-          .set_rpc_options(RpcOptions().set_timeout_ms(kTimeoutMillisecond))
-          .set_expected_error_code(StatusCode::DEADLINE_EXCEEDED));
-  auto csds_response = FetchCsdsResponse();
-  EXPECT_THAT(csds_response.config(0).xds_config(),
-              ::testing::Contains(::testing::Property(
-                  &envoy::service::status::v3::PerXdsConfig::cluster_config,
-                  EqClustersConfigDump(
-                      ::testing::_,
-                      ::testing::UnorderedElementsAre(
-                          EqDynamicCluster(kClusterName1, ::testing::_,
-                                           ClientResourceStatus::REQUESTED,
-                                           ::testing::_),
-                          EqDynamicCluster(kClusterName2, ::testing::_,
-                                           ClientResourceStatus::REQUESTED,
-                                           ::testing::_))))));
-}
-
-class CsdsShortAdsTimeoutTest : public ClientStatusDiscoveryServiceTest {
-  void SetUp() override {
-    // Shorten the ADS subscription timeout to speed up the test run.
-    xds_resource_does_not_exist_timeout_ms_ = 2000;
-    ClientStatusDiscoveryServiceTest::SetUp();
-  }
-};
-
-TEST_P(CsdsShortAdsTimeoutTest, XdsConfigDumpListenerDoesNotExist) {
-  int kTimeoutMillisecond = 1000000;  // 1000s wait for the transient failure.
-  balancers_[0]->ads_service()->UnsetResource(kLdsTypeUrl, kServerName);
-  CheckRpcSendFailure(
-      CheckRpcSendFailureOptions()
-          .set_rpc_options(RpcOptions().set_timeout_ms(kTimeoutMillisecond))
-          .set_expected_error_code(grpc::UNAVAILABLE));
-  auto csds_response = FetchCsdsResponse();
-  EXPECT_THAT(csds_response.config(0).xds_config(),
-              ::testing::Contains(::testing::Property(
-                  &envoy::service::status::v3::PerXdsConfig::listener_config,
-                  EqListenersConfigDump(
-                      ::testing::_, ::testing::ElementsAre(EqDynamicListener(
-                                        kServerName, ::testing::_,
-                                        ClientResourceStatus::DOES_NOT_EXIST,
-                                        ::testing::_, ::testing::_))))));
-}
-
-TEST_P(CsdsShortAdsTimeoutTest, XdsConfigDumpRouteConfigDoesNotExist) {
-  if (!GetParam().enable_rds_testing()) return;
-  int kTimeoutMillisecond = 1000000;  // 1000s wait for the transient failure.
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  balancers_[0]->ads_service()->UnsetResource(kRdsTypeUrl,
-                                              kDefaultRouteConfigurationName);
-  CheckRpcSendFailure(
-      CheckRpcSendFailureOptions()
-          .set_rpc_options(RpcOptions().set_timeout_ms(kTimeoutMillisecond))
-          .set_expected_error_code(grpc::UNAVAILABLE));
-  auto csds_response = FetchCsdsResponse();
-  EXPECT_THAT(
-      csds_response.config(0).xds_config(),
-      ::testing::Contains(::testing::Property(
-          &envoy::service::status::v3::PerXdsConfig::route_config,
-          EqRoutesConfigDump(::testing::ElementsAre(
-              EqDynamicRouteConfig(kDefaultRouteConfigurationName, ::testing::_,
-                                   ClientResourceStatus::DOES_NOT_EXIST,
-                                   ::testing::_, ::testing::_))))));
-}
-
-TEST_P(CsdsShortAdsTimeoutTest, XdsConfigDumpClusterDoesNotExist) {
-  int kTimeoutMillisecond = 1000000;  // 1000s wait for the transient failure.
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  balancers_[0]->ads_service()->UnsetResource(kCdsTypeUrl, kDefaultClusterName);
-  CheckRpcSendFailure(
-      CheckRpcSendFailureOptions()
-          .set_rpc_options(RpcOptions().set_timeout_ms(kTimeoutMillisecond))
-          .set_expected_error_code(grpc::UNAVAILABLE));
-  auto csds_response = FetchCsdsResponse();
-  EXPECT_THAT(csds_response.config(0).xds_config(),
-              ::testing::Contains(::testing::Property(
-                  &envoy::service::status::v3::PerXdsConfig::cluster_config,
-                  EqClustersConfigDump(::testing::_,
-                                       ::testing::ElementsAre(EqDynamicCluster(
-                                           kDefaultClusterName, ::testing::_,
-                                           ClientResourceStatus::DOES_NOT_EXIST,
-                                           ::testing::_))))));
-}
-
-TEST_P(CsdsShortAdsTimeoutTest, XdsConfigDumpEndpointDoesNotExist) {
-  int kTimeoutMillisecond = 1000000;  // 1000s wait for the transient failure.
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  balancers_[0]->ads_service()->UnsetResource(kEdsTypeUrl,
-                                              kDefaultEdsServiceName);
-  CheckRpcSendFailure(
-      CheckRpcSendFailureOptions()
-          .set_rpc_options(RpcOptions().set_timeout_ms(kTimeoutMillisecond))
-          .set_expected_error_code(grpc::UNAVAILABLE));
-  auto csds_response = FetchCsdsResponse();
-  EXPECT_THAT(
-      csds_response.config(0).xds_config(),
-      ::testing::Contains(::testing::Property(
-          &envoy::service::status::v3::PerXdsConfig::endpoint_config,
-          EqEndpointsConfigDump(::testing::ElementsAre(EqDynamicEndpointConfig(
-              kDefaultEdsServiceName, ::testing::_,
-              ClientResourceStatus::DOES_NOT_EXIST, ::testing::_, ::testing::_,
-              ::testing::_))))));
-}
-#endif  // DISABLED_XDS_PROTO_IN_CC
-
-std::string TestTypeName(const ::testing::TestParamInfo<TestType>& info) {
-  return info.param.AsString();
-}
-
-// Run with all combinations of xds/fake resolver and enabling load reporting.
-INSTANTIATE_TEST_SUITE_P(
-    XdsTest, BasicTest,
-    ::testing::Values(
-        TestType(), TestType().set_enable_load_reporting(),
-        TestType().set_use_fake_resolver(),
-        TestType().set_use_fake_resolver().set_enable_load_reporting()),
-    &TestTypeName);
-
-// Run with both fake resolver and xds resolver.
-// Don't run with load reporting or v2 or RDS, since they are irrelevant to
-// the tests.
-INSTANTIATE_TEST_SUITE_P(XdsTest, SecureNamingTest,
-                         ::testing::Values(TestType(),
-                                           TestType().set_use_fake_resolver()),
-                         &TestTypeName);
-
-// LDS depends on XdsResolver.
-INSTANTIATE_TEST_SUITE_P(XdsTest, LdsTest, ::testing::Values(TestType()),
-                         &TestTypeName);
-INSTANTIATE_TEST_SUITE_P(XdsTest, LdsV2Test,
-                         ::testing::Values(TestType().set_use_v2()),
-                         &TestTypeName);
-
-// LDS/RDS commmon tests depend on XdsResolver.
-INSTANTIATE_TEST_SUITE_P(
-    XdsTest, LdsRdsTest,
-    ::testing::Values(TestType(), TestType().set_enable_rds_testing(),
-                      // Also test with xDS v2.
-                      TestType().set_enable_rds_testing().set_use_v2()),
-    &TestTypeName);
-
-// CDS depends on XdsResolver.
-INSTANTIATE_TEST_SUITE_P(
-    XdsTest, CdsTest,
-    ::testing::Values(TestType(), TestType().set_enable_load_reporting()),
-    &TestTypeName);
-
-// CDS depends on XdsResolver.
-// Security depends on v3.
-// Not enabling load reporting or RDS, since those are irrelevant to these
-// tests.
-INSTANTIATE_TEST_SUITE_P(
-    XdsTest, XdsSecurityTest,
-    ::testing::Values(TestType().set_use_xds_credentials()), &TestTypeName);
-
-// We are only testing the server here.
-// Run with bootstrap from env var, so that we use a global XdsClient
-// instance.  Otherwise, we would need to use a separate fake resolver
-// result generator on the client and server sides.
-INSTANTIATE_TEST_SUITE_P(XdsTest, XdsEnabledServerTest,
-                         ::testing::Values(TestType().set_bootstrap_source(
-                             TestType::kBootstrapFromEnvVar)),
-                         &TestTypeName);
-
-// We are only testing the server here.
-INSTANTIATE_TEST_SUITE_P(XdsTest, XdsServerSecurityTest,
-                         ::testing::Values(TestType()
-                                               .set_use_fake_resolver()
-                                               .set_use_xds_credentials()),
-                         &TestTypeName);
-
-// We are only testing the server here.
-INSTANTIATE_TEST_SUITE_P(XdsTest, XdsEnabledServerStatusNotificationTest,
-                         ::testing::Values(TestType()
-                                               .set_use_fake_resolver()
-                                               .set_use_xds_credentials()),
-                         &TestTypeName);
-
-// We are only testing the server here.
-INSTANTIATE_TEST_SUITE_P(XdsTest, XdsServerFilterChainMatchTest,
-                         ::testing::Values(TestType()
-                                               .set_use_fake_resolver()
-                                               .set_use_xds_credentials()),
-                         &TestTypeName);
-
-// EDS could be tested with or without XdsResolver, but the tests would
-// be the same either way, so we test it only with XdsResolver.
-INSTANTIATE_TEST_SUITE_P(
-    XdsTest, EdsTest,
-    ::testing::Values(TestType(), TestType().set_enable_load_reporting()),
-    &TestTypeName);
-
-// Test initial resource timeouts for each resource type.
-// Do this only for XdsResolver with RDS enabled, so that we can test
-// all resource types.
-// Run with V3 only, since the functionality is no different in V2.
-INSTANTIATE_TEST_SUITE_P(XdsTest, TimeoutTest,
-                         ::testing::Values(TestType().set_enable_rds_testing()),
-                         &TestTypeName);
-
-// XdsResolverOnlyTest depends on XdsResolver.
-INSTANTIATE_TEST_SUITE_P(
-    XdsTest, XdsResolverOnlyTest,
-    ::testing::Values(TestType(), TestType().set_enable_load_reporting()),
-    &TestTypeName);
-
-// Runs with bootstrap from env var, so that there's a global XdsClient.
-INSTANTIATE_TEST_SUITE_P(
-    XdsTest, GlobalXdsClientTest,
-    ::testing::Values(
-        TestType().set_bootstrap_source(TestType::kBootstrapFromEnvVar),
-        TestType()
-            .set_bootstrap_source(TestType::kBootstrapFromEnvVar)
-            .set_enable_load_reporting()),
-    &TestTypeName);
-
-// XdsResolverLoadReprtingOnlyTest depends on XdsResolver and load reporting.
-INSTANTIATE_TEST_SUITE_P(
-    XdsTest, XdsResolverLoadReportingOnlyTest,
-    ::testing::Values(TestType().set_enable_load_reporting()), &TestTypeName);
-
-INSTANTIATE_TEST_SUITE_P(
-    XdsTest, LocalityMapTest,
-    ::testing::Values(
-        TestType(), TestType().set_enable_load_reporting(),
-        TestType().set_use_fake_resolver(),
-        TestType().set_use_fake_resolver().set_enable_load_reporting()),
-    &TestTypeName);
-
-INSTANTIATE_TEST_SUITE_P(
-    XdsTest, FailoverTest,
-    ::testing::Values(
-        TestType(), TestType().set_enable_load_reporting(),
-        TestType().set_use_fake_resolver(),
-        TestType().set_use_fake_resolver().set_enable_load_reporting()),
-    &TestTypeName);
-
-INSTANTIATE_TEST_SUITE_P(
-    XdsTest, DropTest,
-    ::testing::Values(
-        TestType(), TestType().set_enable_load_reporting(),
-        TestType().set_use_fake_resolver(),
-        TestType().set_use_fake_resolver().set_enable_load_reporting()),
-    &TestTypeName);
-
-INSTANTIATE_TEST_SUITE_P(
-    XdsTest, BalancerUpdateTest,
-    ::testing::Values(
-        TestType().set_use_fake_resolver(),
-        TestType().set_use_fake_resolver().set_enable_load_reporting(),
-        TestType().set_enable_load_reporting()),
-    &TestTypeName);
-
-// Load reporting tests are not run with load reporting disabled.
-INSTANTIATE_TEST_SUITE_P(
-    XdsTest, ClientLoadReportingTest,
-    ::testing::Values(
-        TestType().set_enable_load_reporting(),
-        TestType().set_enable_load_reporting().set_use_fake_resolver()),
-    &TestTypeName);
-
-// Load reporting tests are not run with load reporting disabled.
-INSTANTIATE_TEST_SUITE_P(
-    XdsTest, ClientLoadReportingWithDropTest,
-    ::testing::Values(
-        TestType().set_enable_load_reporting(),
-        TestType().set_enable_load_reporting().set_use_fake_resolver()),
-    &TestTypeName);
-
-INSTANTIATE_TEST_SUITE_P(
-    XdsTest, FaultInjectionTest,
-    ::testing::Values(
-        TestType(), TestType().set_enable_rds_testing(),
-        TestType().set_filter_config_setup(
-            TestType::FilterConfigSetup::kRouteOverride),
-        TestType().set_enable_rds_testing().set_filter_config_setup(
-            TestType::FilterConfigSetup::kRouteOverride)),
-    &TestTypeName);
-
-INSTANTIATE_TEST_SUITE_P(
-    XdsTest, BootstrapSourceTest,
-    ::testing::Values(
-        TestType().set_bootstrap_source(TestType::kBootstrapFromEnvVar),
-        TestType().set_bootstrap_source(TestType::kBootstrapFromFile)),
-    &TestTypeName);
-
-#ifndef DISABLED_XDS_PROTO_IN_CC
-// Run CSDS tests with RDS enabled and disabled.
-// These need to run with the bootstrap from an env var instead of from
-// a channel arg, since there needs to be a global XdsClient instance.
-INSTANTIATE_TEST_SUITE_P(
-    XdsTest, ClientStatusDiscoveryServiceTest,
-    ::testing::Values(
-        TestType().set_bootstrap_source(TestType::kBootstrapFromEnvVar),
-        TestType()
-            .set_bootstrap_source(TestType::kBootstrapFromEnvVar)
-            .set_enable_rds_testing(),
-        TestType()
-            .set_bootstrap_source(TestType::kBootstrapFromEnvVar)
-            .set_use_csds_streaming(),
-        TestType()
-            .set_bootstrap_source(TestType::kBootstrapFromEnvVar)
-            .set_enable_rds_testing()
-            .set_use_csds_streaming()),
-    &TestTypeName);
-INSTANTIATE_TEST_SUITE_P(
-    XdsTest, CsdsShortAdsTimeoutTest,
-    ::testing::Values(
-        TestType().set_bootstrap_source(TestType::kBootstrapFromEnvVar),
-        TestType()
-            .set_bootstrap_source(TestType::kBootstrapFromEnvVar)
-            .set_enable_rds_testing(),
-        TestType()
-            .set_bootstrap_source(TestType::kBootstrapFromEnvVar)
-            .set_use_csds_streaming(),
-        TestType()
-            .set_bootstrap_source(TestType::kBootstrapFromEnvVar)
-            .set_enable_rds_testing()
-            .set_use_csds_streaming()),
-    &TestTypeName);
-#endif  // DISABLED_XDS_PROTO_IN_CC
-
-}  // namespace
-}  // namespace testing
-}  // namespace grpc
-
-int main(int argc, char** argv) {
-  grpc::testing::TestEnvironment env(argc, argv);
-  ::testing::InitGoogleTest(&argc, argv);
-  grpc::testing::WriteBootstrapFiles();
-  // Make the backup poller poll very frequently in order to pick up
-  // updates from all the subchannels's FDs.
-  GPR_GLOBAL_CONFIG_SET(grpc_client_channel_backup_poll_interval_ms, 1);
-#if TARGET_OS_IPHONE
-  // Workaround Apple CFStream bug
-  gpr_setenv("grpc_cfstream", "0");
-#endif
-  grpc_core::CertificateProviderRegistry::RegisterCertificateProviderFactory(
-      absl::make_unique<grpc::testing::FakeCertificateProviderFactory>(
-          "fake1", &grpc::testing::g_fake1_cert_data_map));
-  grpc_core::CertificateProviderRegistry::RegisterCertificateProviderFactory(
-      absl::make_unique<grpc::testing::FakeCertificateProviderFactory>(
-          "fake2", &grpc::testing::g_fake2_cert_data_map));
-  grpc_init();
-  grpc_core::XdsHttpFilterRegistry::RegisterFilter(
-      absl::make_unique<grpc::testing::NoOpHttpFilter>(
-          "grpc.testing.client_only_http_filter", true, false),
-      {"grpc.testing.client_only_http_filter"});
-  grpc_core::XdsHttpFilterRegistry::RegisterFilter(
-      absl::make_unique<grpc::testing::NoOpHttpFilter>(
-          "grpc.testing.server_only_http_filter", false, true),
-      {"grpc.testing.server_only_http_filter"});
-  const auto result = RUN_ALL_TESTS();
-  grpc_shutdown();
-  return result;
-}
index 0351330..ffb4cc3 100644 (file)
@@ -15,9 +15,9 @@
 load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_package")
 load("//bazel:cc_grpc_library.bzl", "cc_grpc_library")
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
-grpc_package(name = "test/core/ext/census")
+grpc_package(name = "test/cpp/ext/filters/census")
 
 grpc_cc_test(
     name = "grpc_opencensus_plugin_test",
index f9384e1..b9203e7 100644 (file)
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 load("//bazel:grpc_build_system.bzl", "grpc_cc_binary", "grpc_cc_library", "grpc_cc_test", "grpc_package")
 
index 85a84a7..85f0bef 100644 (file)
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 load("//bazel:grpc_build_system.bzl", "grpc_cc_binary", "grpc_cc_library", "grpc_cc_test", "grpc_package")
 
index 96762c8..9808775 100644 (file)
@@ -12,7 +12,7 @@ target 'CronetTests' do
 
   pod '!ProtoCompiler',            :path => "#{GRPC_LOCAL_SRC}/src/objective-c"
   pod '!ProtoCompiler-gRPCCppPlugin', :path => "#{GRPC_LOCAL_SRC}/src/objective-c"
-  pod 'Protobuf-C++', :podspec => "#{GRPC_LOCAL_SRC}/src/cpp", :inhibit_warnings => true
+  pod 'Protobuf-C++', :podspec => "#{GRPC_LOCAL_SRC}/third_party/protobuf", :inhibit_warnings => true
 
   pod 'BoringSSL-GRPC',       :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c", :inhibit_warnings => true
 
@@ -26,36 +26,7 @@ target 'CronetTests' do
   pod 'gRPC-Core/Tests', :path => GRPC_LOCAL_SRC, :inhibit_warnings => true
 end
 
-# gRPC-Core.podspec needs to be modified to be successfully used for local development. A Podfile's
-# pre_install hook lets us do that. The block passed to it runs after the podspecs are downloaded
-# and before they are installed in the user project.
-#
-# This podspec searches for the gRPC core library headers under "$(PODS_ROOT)/gRPC-Core", where
-# Cocoapods normally places the downloaded sources. When doing local development of the libraries,
-# though, Cocoapods just takes the sources from whatever directory was specified using `:path`, and
-# doesn't copy them under $(PODS_ROOT). When using static libraries, one can sometimes rely on the
-# symbolic links to the pods headers that Cocoapods creates under "$(PODS_ROOT)/Headers". But those
-# aren't created when using dynamic frameworks. So our solution is to modify the podspec on the fly
-# to point at the local directory where the sources are.
-#
-# TODO(jcanizales): Send a PR to Cocoapods to get rid of this need.
 pre_install do |installer|
-  # This is the gRPC-Core podspec object, as initialized by its podspec file.
-  grpc_core_spec = installer.pod_targets.find{|t| t.name.start_with?('gRPC-Core')}.root_spec
-
-  # Copied from gRPC-Core.podspec, except for the adjusted src_root:
-  src_root = "$(PODS_ROOT)/../#{GRPC_LOCAL_SRC}"
-  grpc_core_spec.pod_target_xcconfig = {
-    'GRPC_SRC_ROOT' => src_root,
-    'HEADER_SEARCH_PATHS' => '"$(inherited)" "$(GRPC_SRC_ROOT)/include"',
-    'USER_HEADER_SEARCH_PATHS' => '"$(GRPC_SRC_ROOT)"',
-    # If we don't set these two settings, `include/grpc/support/time.h` and
-    # `src/core/lib/gpr/string.h` shadow the system `<time.h>` and `<string.h>`, breaking the
-    # build.
-    'USE_HEADERMAP' => 'NO',
-    'ALWAYS_SEARCH_USER_PATHS' => 'NO',
-  }
-
   # This is the RemoteTestCpp podspec object.
   remote_test_cpp_spec = installer.pod_targets.find{|t| t.name.start_with?('RemoteTestCpp')}.root_spec
 
index 3ca7a22..6b52891 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_package")
 
 grpc_package(name = "test/cpp/microbenchmarks")
 
+load("//test/cpp/microbenchmarks:grpc_benchmark_config.bzl", "grpc_benchmark_args")
+
 grpc_cc_test(
     name = "noop-benchmark",
     srcs = ["noop-benchmark.cc"],
@@ -71,6 +73,7 @@ grpc_cc_library(
 grpc_cc_test(
     name = "bm_closure",
     srcs = ["bm_closure.cc"],
+    args = grpc_benchmark_args(),
     tags = [
         "no_mac",
         "no_windows",
@@ -81,6 +84,7 @@ grpc_cc_test(
 grpc_cc_test(
     name = "bm_alarm",
     srcs = ["bm_alarm.cc"],
+    args = grpc_benchmark_args(),
     tags = [
         "no_mac",
         "no_windows",
@@ -92,6 +96,7 @@ grpc_cc_test(
     name = "bm_arena",
     size = "large",
     srcs = ["bm_arena.cc"],
+    args = grpc_benchmark_args(),
     tags = [
         "no_mac",
         "no_windows",
@@ -104,6 +109,7 @@ grpc_cc_test(
 grpc_cc_test(
     name = "bm_byte_buffer",
     srcs = ["bm_byte_buffer.cc"],
+    args = grpc_benchmark_args(),
     tags = [
         "no_mac",
         "no_windows",
@@ -115,6 +121,7 @@ grpc_cc_test(
 grpc_cc_test(
     name = "bm_channel",
     srcs = ["bm_channel.cc"],
+    args = grpc_benchmark_args(),
     tags = [
         "no_mac",
         "no_windows",
@@ -126,6 +133,7 @@ grpc_cc_test(
 grpc_cc_test(
     name = "bm_call_create",
     srcs = ["bm_call_create.cc"],
+    args = grpc_benchmark_args(),
     tags = [
         "no_mac",
         "no_windows",
@@ -137,6 +145,7 @@ grpc_cc_test(
 grpc_cc_test(
     name = "bm_cq",
     srcs = ["bm_cq.cc"],
+    args = grpc_benchmark_args(),
     tags = [
         "no_mac",
         "no_windows",
@@ -147,6 +156,7 @@ grpc_cc_test(
 grpc_cc_test(
     name = "bm_cq_multiple_threads",
     srcs = ["bm_cq_multiple_threads.cc"],
+    args = grpc_benchmark_args(),
     tags = [
         "no_mac",
         "no_windows",
@@ -158,6 +168,7 @@ grpc_cc_test(
 grpc_cc_test(
     name = "bm_error",
     srcs = ["bm_error.cc"],
+    args = grpc_benchmark_args(),
     tags = [
         "no_mac",
         "no_windows",
@@ -185,6 +196,7 @@ grpc_cc_test(
     srcs = [
         "bm_fullstack_streaming_ping_pong.cc",
     ],
+    args = grpc_benchmark_args(),
     tags = [
         "no_mac",  # to emulate "excluded_poll_engines: poll"
         "no_windows",
@@ -206,6 +218,7 @@ grpc_cc_test(
     srcs = [
         "bm_fullstack_streaming_pump.cc",
     ],
+    args = grpc_benchmark_args(),
     tags = [
         "no_mac",  # to emulate "excluded_poll_engines: poll"
         "no_windows",
@@ -217,6 +230,7 @@ grpc_cc_test(
     name = "bm_fullstack_trickle",
     size = "large",
     srcs = ["bm_fullstack_trickle.cc"],
+    args = grpc_benchmark_args(),
     external_deps = [
         "absl/flags:flag",
     ],
@@ -243,6 +257,7 @@ grpc_cc_test(
     srcs = [
         "bm_fullstack_unary_ping_pong.cc",
     ],
+    args = grpc_benchmark_args(),
     tags = [
         "no_mac",  # to emulate "excluded_poll_engines: poll"
         "no_windows",
@@ -253,6 +268,7 @@ grpc_cc_test(
 grpc_cc_test(
     name = "bm_metadata",
     srcs = ["bm_metadata.cc"],
+    args = grpc_benchmark_args(),
     tags = [
         "no_mac",
         "no_windows",
@@ -264,6 +280,7 @@ grpc_cc_test(
 grpc_cc_test(
     name = "bm_chttp2_hpack",
     srcs = ["bm_chttp2_hpack.cc"],
+    args = grpc_benchmark_args(),
     tags = [
         "no_mac",
         "no_windows",
@@ -275,6 +292,7 @@ grpc_cc_test(
 grpc_cc_test(
     name = "bm_chttp2_transport",
     srcs = ["bm_chttp2_transport.cc"],
+    args = grpc_benchmark_args(),
     tags = [
         "no_mac",
         "no_windows",
@@ -286,6 +304,7 @@ grpc_cc_test(
 grpc_cc_test(
     name = "bm_opencensus_plugin",
     srcs = ["bm_opencensus_plugin.cc"],
+    args = grpc_benchmark_args(),
     language = "C++",
     deps = [
         ":helpers_secure",
@@ -297,6 +316,7 @@ grpc_cc_test(
 grpc_cc_test(
     name = "bm_timer",
     srcs = ["bm_timer.cc"],
+    args = grpc_benchmark_args(),
     tags = [
         "no_mac",
         "no_windows",
@@ -308,6 +328,7 @@ grpc_cc_test(
 grpc_cc_test(
     name = "bm_pollset",
     srcs = ["bm_pollset.cc"],
+    args = grpc_benchmark_args(),
     tags = [
         "no_mac",
         "no_windows",
@@ -319,6 +340,7 @@ grpc_cc_test(
     name = "bm_threadpool",
     size = "large",
     srcs = ["bm_threadpool.cc"],
+    args = grpc_benchmark_args(),
     tags = [
         "manual",
         "no_windows",
@@ -361,6 +383,7 @@ grpc_cc_test(
     srcs = [
         "bm_callback_unary_ping_pong.cc",
     ],
+    args = grpc_benchmark_args(),
     tags = [
         "manual",
         "no_mac",
@@ -388,6 +411,7 @@ grpc_cc_test(
     srcs = [
         "bm_callback_streaming_ping_pong.cc",
     ],
+    args = grpc_benchmark_args(),
     tags = [
         "manual",
         "no_mac",
index c08643c..4c756c1 100644 (file)
@@ -324,6 +324,7 @@ static void DoNothing(void* /*arg*/, grpc_error_handle /*error*/) {}
 class FakeClientChannelFactory : public grpc_core::ClientChannelFactory {
  public:
   grpc_core::RefCountedPtr<grpc_core::Subchannel> CreateSubchannel(
+      const grpc_resolved_address& /*address*/,
       const grpc_channel_args* /*args*/) override {
     return nullptr;
   }
@@ -449,7 +450,7 @@ class NoOp {
  public:
   class Op {
    public:
-    Op(NoOp* /*p*/, grpc_call_stack* /*s*/) {}
+    Op(NoOp* /*p*/, grpc_call_stack* /*s*/, grpc_core::Arena*) {}
     void Finish() {}
   };
 };
@@ -466,11 +467,11 @@ class SendEmptyMetadata {
 
   class Op {
    public:
-    Op(SendEmptyMetadata* p, grpc_call_stack* /*s*/) {
-      grpc_metadata_batch_init(&batch_);
+    Op(SendEmptyMetadata* p, grpc_call_stack* /*s*/, grpc_core::Arena* arena)
+        : batch_(arena) {
       p->op_payload_.send_initial_metadata.send_initial_metadata = &batch_;
     }
-    void Finish() { grpc_metadata_batch_destroy(&batch_); }
+    void Finish() {}
 
    private:
     grpc_metadata_batch batch_;
@@ -547,7 +548,7 @@ static void BM_IsolatedFilter(benchmark::State& state) {
     GPR_TIMER_SCOPE("BenchmarkCycle", 0);
     GRPC_ERROR_UNREF(
         grpc_call_stack_init(channel_stack, 1, DoNothing, nullptr, &call_args));
-    typename TestOp::Op op(&test_op_data, call_stack);
+    typename TestOp::Op op(&test_op_data, call_stack, call_args.arena);
     grpc_call_stack_destroy(call_stack, &final_info, nullptr);
     op.Finish();
     grpc_core::ExecCtx::Get()->Flush();
index 1615aa5..529f41e 100644 (file)
@@ -30,9 +30,9 @@
 
 #include "src/core/ext/transport/chttp2/transport/hpack_encoder.h"
 #include "src/core/ext/transport/chttp2/transport/hpack_parser.h"
-#include "src/core/ext/transport/chttp2/transport/incoming_metadata.h"
 #include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/slice/slice_string_helpers.h"
+#include "src/core/lib/transport/metadata_batch.h"
 #include "src/core/lib/transport/static_metadata.h"
 #include "src/core/lib/transport/timeout_encoding.h"
 #include "test/core/util/test_config.h"
@@ -69,9 +69,9 @@ static void BM_HpackEncoderEncodeDeadline(benchmark::State& state) {
   grpc_core::ExecCtx exec_ctx;
   grpc_millis saved_now = grpc_core::ExecCtx::Get()->Now();
 
-  grpc_metadata_batch b;
-  grpc_metadata_batch_init(&b);
-  b.deadline = saved_now + 30 * 1000;
+  auto arena = grpc_core::MakeScopedArena(1024);
+  grpc_metadata_batch b(arena.get());
+  b.Set(grpc_core::GrpcTimeoutMetadata(), saved_now + 30 * 1000);
 
   grpc_core::HPackCompressor c;
   grpc_transport_one_way_stats stats;
@@ -91,7 +91,6 @@ static void BM_HpackEncoderEncodeDeadline(benchmark::State& state) {
     grpc_slice_buffer_reset_and_unref_internal(&outbuf);
     grpc_core::ExecCtx::Get()->Flush();
   }
-  grpc_metadata_batch_destroy(&b);
   grpc_slice_buffer_destroy_internal(&outbuf);
 
   std::ostringstream label;
@@ -112,14 +111,9 @@ static void BM_HpackEncoderEncodeHeader(benchmark::State& state) {
   grpc_core::ExecCtx exec_ctx;
   static bool logged_representative_output = false;
 
-  grpc_metadata_batch b;
-  grpc_metadata_batch_init(&b);
-  std::vector<grpc_mdelem> elems = Fixture::GetElems();
-  std::vector<grpc_linked_mdelem> storage(elems.size());
-  for (size_t i = 0; i < elems.size(); i++) {
-    GPR_ASSERT(GRPC_LOG_IF_ERROR(
-        "addmd", grpc_metadata_batch_add_tail(&b, &storage[i], elems[i])));
-  }
+  auto arena = grpc_core::MakeScopedArena(1024);
+  grpc_metadata_batch b(arena.get());
+  Fixture::Prepare(&b);
 
   grpc_core::HPackCompressor c;
   grpc_transport_one_way_stats stats;
@@ -148,7 +142,6 @@ static void BM_HpackEncoderEncodeHeader(benchmark::State& state) {
     grpc_slice_buffer_reset_and_unref_internal(&outbuf);
     grpc_core::ExecCtx::Get()->Flush();
   }
-  grpc_metadata_batch_destroy(&b);
   grpc_slice_buffer_destroy_internal(&outbuf);
 
   std::ostringstream label;
@@ -167,24 +160,28 @@ namespace hpack_encoder_fixtures {
 class EmptyBatch {
  public:
   static constexpr bool kEnableTrueBinary = false;
-  static std::vector<grpc_mdelem> GetElems() { return {}; }
+  static void Prepare(grpc_metadata_batch*) {}
 };
 
 class SingleStaticElem {
  public:
   static constexpr bool kEnableTrueBinary = false;
-  static std::vector<grpc_mdelem> GetElems() {
-    return {GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE};
+  static void Prepare(grpc_metadata_batch* b) {
+    GPR_ASSERT(GRPC_LOG_IF_ERROR(
+        "addmd",
+        b->Append(GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE)));
   }
 };
 
 class SingleInternedElem {
  public:
   static constexpr bool kEnableTrueBinary = false;
-  static std::vector<grpc_mdelem> GetElems() {
-    return {grpc_mdelem_from_slices(
-        grpc_slice_intern(grpc_slice_from_static_string("abc")),
-        grpc_slice_intern(grpc_slice_from_static_string("def")))};
+  static void Prepare(grpc_metadata_batch* b) {
+    GPR_ASSERT(GRPC_LOG_IF_ERROR(
+        "addmd",
+        b->Append(grpc_mdelem_from_slices(
+            grpc_slice_intern(grpc_slice_from_static_string("abc")),
+            grpc_slice_intern(grpc_slice_from_static_string("def"))))));
   }
 };
 
@@ -192,13 +189,14 @@ template <int kLength, bool kTrueBinary>
 class SingleInternedBinaryElem {
  public:
   static constexpr bool kEnableTrueBinary = kTrueBinary;
-  static std::vector<grpc_mdelem> GetElems() {
+  static void Prepare(grpc_metadata_batch* b) {
     grpc_slice bytes = MakeBytes();
-    std::vector<grpc_mdelem> out = {grpc_mdelem_from_slices(
-        grpc_slice_intern(grpc_slice_from_static_string("abc-bin")),
-        grpc_slice_intern(bytes))};
+    GPR_ASSERT(GRPC_LOG_IF_ERROR(
+        "addmd",
+        b->Append(grpc_mdelem_from_slices(
+            grpc_slice_intern(grpc_slice_from_static_string("abc-bin")),
+            grpc_slice_intern(bytes)))));
     grpc_slice_unref(bytes);
-    return out;
   }
 
  private:
@@ -215,19 +213,22 @@ class SingleInternedBinaryElem {
 class SingleInternedKeyElem {
  public:
   static constexpr bool kEnableTrueBinary = false;
-  static std::vector<grpc_mdelem> GetElems() {
-    return {grpc_mdelem_from_slices(
-        grpc_slice_intern(grpc_slice_from_static_string("abc")),
-        grpc_slice_from_static_string("def"))};
+  static void Prepare(grpc_metadata_batch* b) {
+    GPR_ASSERT(GRPC_LOG_IF_ERROR(
+        "addmd", b->Append(grpc_mdelem_from_slices(
+                     grpc_slice_intern(grpc_slice_from_static_string("abc")),
+                     grpc_slice_from_static_string("def")))));
   }
 };
 
 class SingleNonInternedElem {
  public:
   static constexpr bool kEnableTrueBinary = false;
-  static std::vector<grpc_mdelem> GetElems() {
-    return {grpc_mdelem_from_slices(grpc_slice_from_static_string("abc"),
-                                    grpc_slice_from_static_string("def"))};
+  static void Prepare(grpc_metadata_batch* b) {
+    GPR_ASSERT(
+        GRPC_LOG_IF_ERROR("addmd", b->Append(grpc_mdelem_from_slices(
+                                       grpc_slice_from_static_string("abc"),
+                                       grpc_slice_from_static_string("def")))));
   }
 };
 
@@ -235,9 +236,10 @@ template <int kLength, bool kTrueBinary>
 class SingleNonInternedBinaryElem {
  public:
   static constexpr bool kEnableTrueBinary = kTrueBinary;
-  static std::vector<grpc_mdelem> GetElems() {
-    return {grpc_mdelem_from_slices(grpc_slice_from_static_string("abc-bin"),
-                                    MakeBytes())};
+  static void Prepare(grpc_metadata_batch* b) {
+    GPR_ASSERT(GRPC_LOG_IF_ERROR(
+        "addmd", b->Append(grpc_mdelem_from_slices(
+                     grpc_slice_from_static_string("abc-bin"), MakeBytes()))));
   }
 
  private:
@@ -254,23 +256,31 @@ class SingleNonInternedBinaryElem {
 class RepresentativeClientInitialMetadata {
  public:
   static constexpr bool kEnableTrueBinary = true;
-  static std::vector<grpc_mdelem> GetElems() {
-    return {
-        GRPC_MDELEM_SCHEME_HTTP,
-        GRPC_MDELEM_METHOD_POST,
-        grpc_mdelem_from_slices(
+  static void Prepare(grpc_metadata_batch* b) {
+    GPR_ASSERT(GRPC_LOG_IF_ERROR("addmd", b->Append(GRPC_MDELEM_SCHEME_HTTP)));
+    GPR_ASSERT(GRPC_LOG_IF_ERROR("addmd", b->Append(GRPC_MDELEM_METHOD_POST)));
+    GPR_ASSERT(GRPC_LOG_IF_ERROR(
+        "addmd",
+        b->Append(grpc_mdelem_from_slices(
             GRPC_MDSTR_PATH,
-            grpc_slice_intern(grpc_slice_from_static_string("/foo/bar"))),
-        grpc_mdelem_from_slices(GRPC_MDSTR_AUTHORITY,
-                                grpc_slice_intern(grpc_slice_from_static_string(
-                                    "foo.test.google.fr:1234"))),
-        GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE_COMMA_GZIP,
-        GRPC_MDELEM_TE_TRAILERS,
-        GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC,
-        grpc_mdelem_from_slices(
-            GRPC_MDSTR_USER_AGENT,
-            grpc_slice_intern(grpc_slice_from_static_string(
-                "grpc-c/3.0.0-dev (linux; chttp2; green)")))};
+            grpc_slice_intern(grpc_slice_from_static_string("/foo/bar"))))));
+    GPR_ASSERT(GRPC_LOG_IF_ERROR(
+        "addmd", b->Append(grpc_mdelem_from_slices(
+                     GRPC_MDSTR_AUTHORITY,
+                     grpc_slice_intern(grpc_slice_from_static_string(
+                         "foo.test.google.fr:1234"))))));
+    GPR_ASSERT(GRPC_LOG_IF_ERROR(
+        "addmd",
+        b->Append(
+            GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE_COMMA_GZIP)));
+    b->Set(grpc_core::TeMetadata(), grpc_core::TeMetadata::kTrailers);
+    GPR_ASSERT(GRPC_LOG_IF_ERROR(
+        "addmd", b->Append(GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC)));
+    GPR_ASSERT(GRPC_LOG_IF_ERROR(
+        "addmd", b->Append(grpc_mdelem_from_slices(
+                     GRPC_MDSTR_USER_AGENT,
+                     grpc_slice_intern(grpc_slice_from_static_string(
+                         "grpc-c/3.0.0-dev (linux; chttp2; green)"))))));
   }
 };
 
@@ -280,17 +290,22 @@ class RepresentativeClientInitialMetadata {
 class MoreRepresentativeClientInitialMetadata {
  public:
   static constexpr bool kEnableTrueBinary = true;
-  static std::vector<grpc_mdelem> GetElems() {
-    return {
-        GRPC_MDELEM_SCHEME_HTTP,
-        GRPC_MDELEM_METHOD_POST,
-        grpc_mdelem_from_slices(GRPC_MDSTR_PATH,
-                                grpc_slice_intern(grpc_slice_from_static_string(
-                                    "/grpc.test.FooService/BarMethod"))),
-        grpc_mdelem_from_slices(GRPC_MDSTR_AUTHORITY,
-                                grpc_slice_intern(grpc_slice_from_static_string(
-                                    "foo.test.google.fr:1234"))),
-        grpc_mdelem_from_slices(
+  static void Prepare(grpc_metadata_batch* b) {
+    GPR_ASSERT(GRPC_LOG_IF_ERROR("addmd", b->Append(GRPC_MDELEM_SCHEME_HTTP)));
+    GPR_ASSERT(GRPC_LOG_IF_ERROR("addmd", b->Append(GRPC_MDELEM_METHOD_POST)));
+    GPR_ASSERT(GRPC_LOG_IF_ERROR(
+        "addmd",
+        b->Append(grpc_mdelem_from_slices(
+            GRPC_MDSTR_PATH, grpc_slice_intern(grpc_slice_from_static_string(
+                                 "/grpc.test.FooService/BarMethod"))))));
+    GPR_ASSERT(GRPC_LOG_IF_ERROR(
+        "addmd", b->Append(grpc_mdelem_from_slices(
+                     GRPC_MDSTR_AUTHORITY,
+                     grpc_slice_intern(grpc_slice_from_static_string(
+                         "foo.test.google.fr:1234"))))));
+    GPR_ASSERT(GRPC_LOG_IF_ERROR(
+        "addmd",
+        b->Append(grpc_mdelem_from_slices(
             GRPC_MDSTR_GRPC_TRACE_BIN,
             grpc_slice_from_static_string("\x00\x01\x02\x03\x04\x05\x06\x07\x08"
                                           "\x09\x0a\x0b\x0c\x0d\x0e\x0f"
@@ -298,37 +313,49 @@ class MoreRepresentativeClientInitialMetadata {
                                           "\x19\x1a\x1b\x1c\x1d\x1e\x1f"
                                           "\x20\x21\x22\x23\x24\x25\x26\x27\x28"
                                           "\x29\x2a\x2b\x2c\x2d\x2e\x2f"
-                                          "\x30")),
-        grpc_mdelem_from_slices(
+                                          "\x30")))));
+    GPR_ASSERT(GRPC_LOG_IF_ERROR(
+        "addmd",
+        b->Append(grpc_mdelem_from_slices(
             GRPC_MDSTR_GRPC_TAGS_BIN,
             grpc_slice_from_static_string("\x00\x01\x02\x03\x04\x05\x06\x07\x08"
                                           "\x09\x0a\x0b\x0c\x0d\x0e\x0f"
-                                          "\x10\x11\x12\x13")),
-        GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE_COMMA_GZIP,
-        GRPC_MDELEM_TE_TRAILERS,
-        GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC,
-        grpc_mdelem_from_slices(
-            GRPC_MDSTR_USER_AGENT,
-            grpc_slice_intern(grpc_slice_from_static_string(
-                "grpc-c/3.0.0-dev (linux; chttp2; green)")))};
+                                          "\x10\x11\x12\x13")))));
+    GPR_ASSERT(GRPC_LOG_IF_ERROR(
+        "addmd",
+        b->Append(
+            GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE_COMMA_GZIP)));
+    b->Set(grpc_core::TeMetadata(), grpc_core::TeMetadata::kTrailers);
+    GPR_ASSERT(GRPC_LOG_IF_ERROR(
+        "addmd", b->Append(GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC)));
+    GPR_ASSERT(GRPC_LOG_IF_ERROR(
+        "addmd", b->Append(grpc_mdelem_from_slices(
+                     GRPC_MDSTR_USER_AGENT,
+                     grpc_slice_intern(grpc_slice_from_static_string(
+                         "grpc-c/3.0.0-dev (linux; chttp2; green)"))))));
   }
 };
 
 class RepresentativeServerInitialMetadata {
  public:
   static constexpr bool kEnableTrueBinary = true;
-  static std::vector<grpc_mdelem> GetElems() {
-    return {GRPC_MDELEM_STATUS_200,
-            GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC,
-            GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE_COMMA_GZIP};
+  static void Prepare(grpc_metadata_batch* b) {
+    GPR_ASSERT(GRPC_LOG_IF_ERROR("addmd", b->Append(GRPC_MDELEM_STATUS_200)));
+    GPR_ASSERT(GRPC_LOG_IF_ERROR(
+        "addmd", b->Append(GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC)));
+    GPR_ASSERT(GRPC_LOG_IF_ERROR(
+        "addmd",
+        b->Append(
+            GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE_COMMA_GZIP)));
   }
 };
 
 class RepresentativeServerTrailingMetadata {
  public:
   static constexpr bool kEnableTrueBinary = true;
-  static std::vector<grpc_mdelem> GetElems() {
-    return {GRPC_MDELEM_GRPC_STATUS_0};
+  static void Prepare(grpc_metadata_batch* b) {
+    GPR_ASSERT(
+        GRPC_LOG_IF_ERROR("addmd", b->Append(GRPC_MDELEM_GRPC_STATUS_0)));
   }
 };
 
@@ -438,12 +465,7 @@ static void BM_HpackParserInitDestroy(benchmark::State& state) {
 }
 BENCHMARK(BM_HpackParserInitDestroy);
 
-static grpc_error_handle UnrefHeader(void* /*user_data*/, grpc_mdelem md) {
-  GRPC_MDELEM_UNREF(md);
-  return GRPC_ERROR_NONE;
-}
-
-template <class Fixture, grpc_error_handle (*OnHeader)(void*, grpc_mdelem)>
+template <class Fixture>
 static void BM_HpackParserParseHeader(benchmark::State& state) {
   TrackCounters track_counters;
   grpc_core::ExecCtx exec_ctx;
@@ -452,30 +474,40 @@ static void BM_HpackParserParseHeader(benchmark::State& state) {
   grpc_core::HPackParser p;
   const int kArenaSize = 4096 * 4096;
   auto* arena = grpc_core::Arena::Create(kArenaSize);
-  p.BeginFrame([arena](grpc_mdelem e) { return OnHeader(arena, e); },
+  grpc_core::ManualConstructor<grpc_metadata_batch> b;
+  b.Init(arena);
+  p.BeginFrame(&*b, std::numeric_limits<uint32_t>::max(),
                grpc_core::HPackParser::Boundary::None,
-               grpc_core::HPackParser::Priority::None);
+               grpc_core::HPackParser::Priority::None,
+               grpc_core::HPackParser::LogInfo{
+                   1, grpc_core::HPackParser::LogInfo::kHeaders, false});
   for (auto slice : init_slices) {
     GPR_ASSERT(GRPC_ERROR_NONE == p.Parse(slice, false));
   }
   while (state.KeepRunning()) {
+    b->Clear();
     for (auto slice : benchmark_slices) {
       GPR_ASSERT(GRPC_ERROR_NONE == p.Parse(slice, false));
     }
     grpc_core::ExecCtx::Get()->Flush();
     // Recreate arena every 4k iterations to avoid oom
     if (0 == (state.iterations() & 0xfff)) {
+      b.Destroy();
       arena->Destroy();
       arena = grpc_core::Arena::Create(kArenaSize);
-      p.BeginFrame([arena](grpc_mdelem e) { return OnHeader(arena, e); },
+      b.Init(arena);
+      p.BeginFrame(&*b, std::numeric_limits<uint32_t>::max(),
                    grpc_core::HPackParser::Boundary::None,
-                   grpc_core::HPackParser::Priority::None);
+                   grpc_core::HPackParser::Priority::None,
+                   grpc_core::HPackParser::LogInfo{
+                       1, grpc_core::HPackParser::LogInfo::kHeaders, false});
     }
   }
   // Clean up
-  arena->Destroy();
+  b.Destroy();
   for (auto slice : init_slices) grpc_slice_unref(slice);
   for (auto slice : benchmark_slices) grpc_slice_unref(slice);
+  arena->Destroy();
 
   track_counters.Finish(state);
 }
@@ -706,14 +738,13 @@ class MoreRepresentativeClientInitialMetadata {
          'x',  ')'})};
   }
   static std::vector<grpc_slice> GetBenchmarkSlices() {
-    return {MakeSlice(
-        {0xc7, 0xc6, 0xc5, 0xc4, 0x7f, 0x04, 0x31, 0x00, 0x01, 0x02, 0x03, 0x04,
-         0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
-         0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c,
-         0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
-         0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x7f, 0x03, 0x14, 0x00,
-         0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
-         0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0xc1, 0xc0, 0xbf, 0xbe})};
+    return {MakeSlice({
+        0xc7, 0xc6, 0xc5, 0xc4, 0x7f, 0x04, 0x31, 0x00, 0x01, 0x02, 0x03, 0x04,
+        0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
+        0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c,
+        0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
+        0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
+    })};
   }
 };
 
@@ -770,91 +801,6 @@ class RepresentativeServerTrailingMetadata {
   }
 };
 
-static void free_timeout(void* p) { gpr_free(p); }
-
-// Benchmark the current on_initial_header implementation
-static grpc_error_handle OnInitialHeader(void* user_data, grpc_mdelem md) {
-  // Setup for benchmark. This will bloat the absolute values of this benchmark
-  grpc_chttp2_incoming_metadata_buffer buffer(
-      static_cast<grpc_core::Arena*>(user_data));
-  bool seen_error = false;
-
-  // Below here is the code we actually care about benchmarking
-  if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_STATUS) &&
-      !grpc_mdelem_eq(md, GRPC_MDELEM_GRPC_STATUS_0)) {
-    seen_error = true;
-  }
-  if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_TIMEOUT)) {
-    grpc_millis* cached_timeout =
-        static_cast<grpc_millis*>(grpc_mdelem_get_user_data(md, free_timeout));
-    grpc_millis timeout;
-    if (cached_timeout != nullptr) {
-      timeout = *cached_timeout;
-    } else {
-      if (GPR_UNLIKELY(
-              !grpc_http2_decode_timeout(GRPC_MDVALUE(md), &timeout))) {
-        char* val = grpc_slice_to_c_string(GRPC_MDVALUE(md));
-        gpr_log(GPR_ERROR, "Ignoring bad timeout value '%s'", val);
-        gpr_free(val);
-        timeout = GRPC_MILLIS_INF_FUTURE;
-      }
-      if (GRPC_MDELEM_IS_INTERNED(md)) {
-        /* not already parsed: parse it now, and store the
-         * result away */
-        cached_timeout =
-            static_cast<grpc_millis*>(gpr_malloc(sizeof(grpc_millis)));
-        *cached_timeout = timeout;
-        grpc_mdelem_set_user_data(md, free_timeout, cached_timeout);
-      }
-    }
-    benchmark::DoNotOptimize(timeout);
-    GRPC_MDELEM_UNREF(md);
-  } else {
-    const size_t new_size = buffer.size + GRPC_MDELEM_LENGTH(md);
-    if (!seen_error) {
-      buffer.size = new_size;
-    }
-    grpc_error_handle error =
-        grpc_chttp2_incoming_metadata_buffer_add(&buffer, md);
-    if (error != GRPC_ERROR_NONE) {
-      GPR_ASSERT(0);
-    }
-  }
-  return GRPC_ERROR_NONE;
-}
-
-// Benchmark timeout handling
-static grpc_error_handle OnHeaderTimeout(void* /*user_data*/, grpc_mdelem md) {
-  if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_TIMEOUT)) {
-    grpc_millis* cached_timeout =
-        static_cast<grpc_millis*>(grpc_mdelem_get_user_data(md, free_timeout));
-    grpc_millis timeout;
-    if (cached_timeout != nullptr) {
-      timeout = *cached_timeout;
-    } else {
-      if (!grpc_http2_decode_timeout(GRPC_MDVALUE(md), &timeout)) {
-        char* val = grpc_slice_to_c_string(GRPC_MDVALUE(md));
-        gpr_log(GPR_ERROR, "Ignoring bad timeout value '%s'", val);
-        gpr_free(val);
-        timeout = GRPC_MILLIS_INF_FUTURE;
-      }
-      if (GRPC_MDELEM_IS_INTERNED(md)) {
-        /* not already parsed: parse it now, and store the
-         * result away */
-        cached_timeout =
-            static_cast<grpc_millis*>(gpr_malloc(sizeof(grpc_millis)));
-        *cached_timeout = timeout;
-        grpc_mdelem_set_user_data(md, free_timeout, cached_timeout);
-      }
-    }
-    benchmark::DoNotOptimize(timeout);
-    GRPC_MDELEM_UNREF(md);
-  } else {
-    GPR_ASSERT(0);
-  }
-  return GRPC_ERROR_NONE;
-}
-
 // Send the same deadline repeatedly
 class SameDeadline {
  public:
@@ -869,55 +815,39 @@ class SameDeadline {
   }
 };
 
-BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, EmptyBatch, UnrefHeader);
-BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, IndexedSingleStaticElem,
-                   UnrefHeader);
-BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, AddIndexedSingleStaticElem,
-                   UnrefHeader);
-BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, KeyIndexedSingleStaticElem,
-                   UnrefHeader);
-BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, IndexedSingleInternedElem,
-                   UnrefHeader);
-BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, AddIndexedSingleInternedElem,
-                   UnrefHeader);
-BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, KeyIndexedSingleInternedElem,
-                   UnrefHeader);
-BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedElem, UnrefHeader);
-BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<1, false>,
-                   UnrefHeader);
-BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<3, false>,
-                   UnrefHeader);
-BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<10, false>,
-                   UnrefHeader);
-BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<31, false>,
-                   UnrefHeader);
-BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<100, false>,
-                   UnrefHeader);
-BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<1, true>,
-                   UnrefHeader);
-BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<3, true>,
-                   UnrefHeader);
-BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<10, true>,
-                   UnrefHeader);
-BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<31, true>,
-                   UnrefHeader);
-BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<100, true>,
-                   UnrefHeader);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, EmptyBatch);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, IndexedSingleStaticElem);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, AddIndexedSingleStaticElem);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, KeyIndexedSingleStaticElem);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, IndexedSingleInternedElem);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, AddIndexedSingleInternedElem);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, KeyIndexedSingleInternedElem);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedElem);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<1, false>);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<3, false>);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<10, false>);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<31, false>);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<100, false>);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<1, true>);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<3, true>);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<10, true>);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<31, true>);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<100, true>);
 BENCHMARK_TEMPLATE(BM_HpackParserParseHeader,
-                   RepresentativeClientInitialMetadata, UnrefHeader);
+                   RepresentativeClientInitialMetadata);
 BENCHMARK_TEMPLATE(BM_HpackParserParseHeader,
-                   MoreRepresentativeClientInitialMetadata, UnrefHeader);
+                   MoreRepresentativeClientInitialMetadata);
 BENCHMARK_TEMPLATE(BM_HpackParserParseHeader,
-                   RepresentativeServerInitialMetadata, UnrefHeader);
+                   RepresentativeServerInitialMetadata);
 BENCHMARK_TEMPLATE(BM_HpackParserParseHeader,
-                   RepresentativeServerTrailingMetadata, UnrefHeader);
+                   RepresentativeServerTrailingMetadata);
 BENCHMARK_TEMPLATE(BM_HpackParserParseHeader,
-                   RepresentativeClientInitialMetadata, OnInitialHeader);
+                   RepresentativeClientInitialMetadata);
 BENCHMARK_TEMPLATE(BM_HpackParserParseHeader,
-                   MoreRepresentativeClientInitialMetadata, OnInitialHeader);
+                   MoreRepresentativeClientInitialMetadata);
 BENCHMARK_TEMPLATE(BM_HpackParserParseHeader,
-                   RepresentativeServerInitialMetadata, OnInitialHeader);
-BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, SameDeadline, OnHeaderTimeout);
+                   RepresentativeServerInitialMetadata);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, SameDeadline);
 
 }  // namespace hpack_parser_fixtures
 
index 2b992c1..7aaa338 100644 (file)
@@ -287,23 +287,31 @@ BENCHMARK(BM_StreamCreateDestroy);
 
 class RepresentativeClientInitialMetadata {
  public:
-  static std::vector<grpc_mdelem> GetElems() {
-    return {
-        GRPC_MDELEM_SCHEME_HTTP,
-        GRPC_MDELEM_METHOD_POST,
-        grpc_mdelem_from_slices(GRPC_MDSTR_PATH,
-                                grpc_slice_intern(grpc_slice_from_static_string(
-                                    "/foo/bar/bm_chttp2_transport"))),
-        grpc_mdelem_from_slices(GRPC_MDSTR_AUTHORITY,
-                                grpc_slice_intern(grpc_slice_from_static_string(
-                                    "foo.test.google.fr:1234"))),
-        GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE_COMMA_GZIP,
-        GRPC_MDELEM_TE_TRAILERS,
-        GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC,
-        grpc_mdelem_from_slices(
-            GRPC_MDSTR_USER_AGENT,
-            grpc_slice_intern(grpc_slice_from_static_string(
-                "grpc-c/3.0.0-dev (linux; chttp2; green)")))};
+  static void Prepare(grpc_metadata_batch* b) {
+    GPR_ASSERT(GRPC_LOG_IF_ERROR("addmd", b->Append(GRPC_MDELEM_SCHEME_HTTP)));
+    GPR_ASSERT(GRPC_LOG_IF_ERROR("addmd", b->Append(GRPC_MDELEM_METHOD_POST)));
+    GPR_ASSERT(GRPC_LOG_IF_ERROR(
+        "addmd",
+        b->Append(grpc_mdelem_from_slices(
+            GRPC_MDSTR_PATH, grpc_slice_intern(grpc_slice_from_static_string(
+                                 "/foo/bar/bm_chttp2_transport"))))));
+    GPR_ASSERT(GRPC_LOG_IF_ERROR(
+        "addmd", b->Append(grpc_mdelem_from_slices(
+                     GRPC_MDSTR_AUTHORITY,
+                     grpc_slice_intern(grpc_slice_from_static_string(
+                         "foo.test.google.fr:1234"))))));
+    GPR_ASSERT(GRPC_LOG_IF_ERROR(
+        "addmd",
+        b->Append(
+            GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE_COMMA_GZIP)));
+    b->Set(grpc_core::TeMetadata(), grpc_core::TeMetadata::kTrailers);
+    GPR_ASSERT(GRPC_LOG_IF_ERROR(
+        "addmd", b->Append(GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC)));
+    GPR_ASSERT(GRPC_LOG_IF_ERROR(
+        "addmd", b->Append(grpc_mdelem_from_slices(
+                     GRPC_MDSTR_USER_AGENT,
+                     grpc_slice_intern(grpc_slice_from_static_string(
+                         "grpc-c/3.0.0-dev (linux; chttp2; green)"))))));
   }
 };
 
@@ -323,15 +331,9 @@ static void BM_StreamCreateSendInitialMetadataDestroy(benchmark::State& state) {
     op.payload = &op_payload;
   };
 
-  grpc_metadata_batch b;
-  grpc_metadata_batch_init(&b);
-  b.deadline = GRPC_MILLIS_INF_FUTURE;
-  std::vector<grpc_mdelem> elems = Metadata::GetElems();
-  std::vector<grpc_linked_mdelem> storage(elems.size());
-  for (size_t i = 0; i < elems.size(); i++) {
-    GPR_ASSERT(GRPC_LOG_IF_ERROR(
-        "addmd", grpc_metadata_batch_add_tail(&b, &storage[i], elems[i])));
-  }
+  auto arena = grpc_core::MakeScopedArena(1024);
+  grpc_metadata_batch b(arena.get());
+  Metadata::Prepare(&b);
 
   f.FlushExecCtx();
   gpr_event bm_done;
@@ -359,7 +361,6 @@ static void BM_StreamCreateSendInitialMetadataDestroy(benchmark::State& state) {
   grpc_core::ExecCtx::Run(DEBUG_LOCATION, start.get(), GRPC_ERROR_NONE);
   f.FlushExecCtx();
   gpr_event_wait(&bm_done, gpr_inf_future(GPR_CLOCK_REALTIME));
-  grpc_metadata_batch_destroy(&b);
   track_counters.Finish(state);
 }
 BENCHMARK_TEMPLATE(BM_StreamCreateSendInitialMetadataDestroy,
@@ -427,16 +428,9 @@ static void BM_TransportStreamSend(benchmark::State& state) {
   grpc_slice send_slice = grpc_slice_malloc_large(state.range(0));
   memset(GRPC_SLICE_START_PTR(send_slice), 0, GRPC_SLICE_LENGTH(send_slice));
   grpc_core::ManualConstructor<grpc_core::SliceBufferByteStream> send_stream;
-  grpc_metadata_batch b;
-  grpc_metadata_batch_init(&b);
-  b.deadline = GRPC_MILLIS_INF_FUTURE;
-  std::vector<grpc_mdelem> elems =
-      RepresentativeClientInitialMetadata::GetElems();
-  std::vector<grpc_linked_mdelem> storage(elems.size());
-  for (size_t i = 0; i < elems.size(); i++) {
-    GPR_ASSERT(GRPC_LOG_IF_ERROR(
-        "addmd", grpc_metadata_batch_add_tail(&b, &storage[i], elems[i])));
-  }
+  auto arena = grpc_core::MakeScopedArena(1024);
+  grpc_metadata_batch b(arena.get());
+  RepresentativeClientInitialMetadata::Prepare(&b);
 
   gpr_event* bm_done = new gpr_event;
   gpr_event_init(bm_done);
@@ -491,7 +485,6 @@ static void BM_TransportStreamSend(benchmark::State& state) {
       MakeOnceClosure([s](grpc_error_handle /*error*/) { delete s; }));
   f.FlushExecCtx();
   track_counters.Finish(state);
-  grpc_metadata_batch_destroy(&b);
   grpc_slice_unref(send_slice);
 }
 BENCHMARK(BM_TransportStreamSend)->Range(0, 128 * 1024 * 1024);
@@ -569,18 +562,9 @@ static void BM_TransportStreamRecv(benchmark::State& state) {
     op.payload = &op_payload;
   };
 
-  grpc_metadata_batch b;
-  grpc_metadata_batch_init(&b);
-  grpc_metadata_batch b_recv;
-  grpc_metadata_batch_init(&b_recv);
-  b.deadline = GRPC_MILLIS_INF_FUTURE;
-  std::vector<grpc_mdelem> elems =
-      RepresentativeClientInitialMetadata::GetElems();
-  std::vector<grpc_linked_mdelem> storage(elems.size());
-  for (size_t i = 0; i < elems.size(); i++) {
-    GPR_ASSERT(GRPC_LOG_IF_ERROR(
-        "addmd", grpc_metadata_batch_add_tail(&b, &storage[i], elems[i])));
-  }
+  auto arena = grpc_core::MakeScopedArena(1024);
+  grpc_metadata_batch b(arena.get());
+  RepresentativeClientInitialMetadata::Prepare(&b);
 
   std::unique_ptr<TestClosure> do_nothing =
       MakeTestClosure([](grpc_error_handle /*error*/) {});
@@ -632,17 +616,18 @@ static void BM_TransportStreamRecv(benchmark::State& state) {
   });
 
   drain_continue = MakeTestClosure([&](grpc_error_handle /*error*/) {
-    recv_stream->Pull(&recv_slice);
+    GPR_ASSERT(GRPC_LOG_IF_ERROR("Pull", recv_stream->Pull(&recv_slice)));
     received += GRPC_SLICE_LENGTH(recv_slice);
     grpc_slice_unref_internal(recv_slice);
     grpc_core::Closure::Run(DEBUG_LOCATION, drain.get(), GRPC_ERROR_NONE);
   });
 
   reset_op();
+  auto b_recv = absl::make_unique<grpc_metadata_batch>(arena.get());
   op.send_initial_metadata = true;
   op.payload->send_initial_metadata.send_initial_metadata = &b;
   op.recv_initial_metadata = true;
-  op.payload->recv_initial_metadata.recv_initial_metadata = &b_recv;
+  op.payload->recv_initial_metadata.recv_initial_metadata = b_recv.get();
   op.payload->recv_initial_metadata.recv_initial_metadata_ready =
       do_nothing.get();
   op.on_complete = c.get();
@@ -676,10 +661,10 @@ static void BM_TransportStreamRecv(benchmark::State& state) {
   f.FlushExecCtx();
   gpr_event_wait(stream_cancel_done, gpr_inf_future(GPR_CLOCK_REALTIME));
   done_events.emplace_back(stream_cancel_done);
-  s->DestroyThen(
-      MakeOnceClosure([s](grpc_error_handle /*error*/) { delete s; }));
-  grpc_metadata_batch_destroy(&b);
-  grpc_metadata_batch_destroy(&b_recv);
+  s->DestroyThen(MakeOnceClosure([s, &b_recv](grpc_error_handle /*error*/) {
+    b_recv.reset();
+    delete s;
+  }));
   f.FlushExecCtx();
   track_counters.Finish(state);
   grpc_slice_unref(incoming_data);
index 66bc5d8..d33991d 100644 (file)
@@ -162,7 +162,7 @@ static void teardown() {
 */
 static void BM_Cq_Throughput(benchmark::State& state) {
   gpr_timespec deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
-  auto thd_idx = state.thread_index;
+  auto thd_idx = state.thread_index();
 
   gpr_mu_lock(&g_mu);
   g_threads_active++;
index 1559e9c..544d887 100644 (file)
 #include "test/cpp/microbenchmarks/helpers.h"
 #include "test/cpp/util/test_config.h"
 
-class ErrorDeleter {
+class ErrorHandleHolder {
  public:
-  void operator()(grpc_error_handle error) { GRPC_ERROR_UNREF(error); }
+  explicit ErrorHandleHolder(grpc_error_handle error) : error_(error) {}
+  ~ErrorHandleHolder() { GRPC_ERROR_UNREF(error_); }
+  const grpc_error_handle& get() const { return error_; }
+
+ private:
+  grpc_error_handle error_;
 };
-typedef std::unique_ptr<grpc_error, ErrorDeleter> ErrorPtr;
 
 static void BM_ErrorCreateFromStatic(benchmark::State& state) {
   TrackCounters track_counters;
@@ -70,7 +74,7 @@ static void BM_ErrorCreateAndSetIntAndStr(benchmark::State& state) {
         grpc_error_set_int(
             GRPC_ERROR_CREATE_FROM_STATIC_STRING("GOAWAY received"),
             GRPC_ERROR_INT_HTTP2_ERROR, (intptr_t)0),
-        GRPC_ERROR_STR_RAW_BYTES, grpc_slice_from_static_string("raw bytes")));
+        GRPC_ERROR_STR_RAW_BYTES, "raw bytes"));
   }
   track_counters.Finish(state);
 }
@@ -93,8 +97,7 @@ static void BM_ErrorCreateAndSetStrLoop(benchmark::State& state) {
   grpc_error_handle error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error");
   const char* str = "hello";
   for (auto _ : state) {
-    error = grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE,
-                               grpc_slice_from_static_string(str));
+    error = grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE, str);
   }
   GRPC_ERROR_UNREF(error);
   track_counters.Finish(state);
@@ -132,7 +135,7 @@ BENCHMARK(BM_ErrorGetIntFromNoError);
 
 static void BM_ErrorGetMissingInt(benchmark::State& state) {
   TrackCounters track_counters;
-  ErrorPtr error(grpc_error_set_int(
+  ErrorHandleHolder error(grpc_error_set_int(
       GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error"), GRPC_ERROR_INT_INDEX, 1));
   for (auto _ : state) {
     intptr_t value;
@@ -144,7 +147,7 @@ BENCHMARK(BM_ErrorGetMissingInt);
 
 static void BM_ErrorGetPresentInt(benchmark::State& state) {
   TrackCounters track_counters;
-  ErrorPtr error(grpc_error_set_int(
+  ErrorHandleHolder error(grpc_error_set_int(
       GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error"), GRPC_ERROR_INT_OFFSET, 1));
   for (auto _ : state) {
     intptr_t value;
@@ -180,7 +183,7 @@ class SimpleError {
 
  private:
   const grpc_millis deadline_ = GRPC_MILLIS_INF_FUTURE;
-  ErrorPtr error_{GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error")};
+  ErrorHandleHolder error_{GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error")};
 };
 
 class ErrorWithGrpcStatus {
@@ -190,7 +193,7 @@ class ErrorWithGrpcStatus {
 
  private:
   const grpc_millis deadline_ = GRPC_MILLIS_INF_FUTURE;
-  ErrorPtr error_{grpc_error_set_int(
+  ErrorHandleHolder error_{grpc_error_set_int(
       GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error"), GRPC_ERROR_INT_GRPC_STATUS,
       GRPC_STATUS_UNIMPLEMENTED)};
 };
@@ -202,7 +205,7 @@ class ErrorWithHttpError {
 
  private:
   const grpc_millis deadline_ = GRPC_MILLIS_INF_FUTURE;
-  ErrorPtr error_{grpc_error_set_int(
+  ErrorHandleHolder error_{grpc_error_set_int(
       GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error"), GRPC_ERROR_INT_HTTP2_ERROR,
       GRPC_HTTP2_COMPRESSION_ERROR)};
 };
@@ -214,11 +217,11 @@ class ErrorWithNestedGrpcStatus {
 
  private:
   const grpc_millis deadline_ = GRPC_MILLIS_INF_FUTURE;
-  ErrorPtr nested_error_{grpc_error_set_int(
+  ErrorHandleHolder nested_error_{grpc_error_set_int(
       GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error"), GRPC_ERROR_INT_GRPC_STATUS,
       GRPC_STATUS_UNIMPLEMENTED)};
   grpc_error_handle nested_errors_[1] = {nested_error_.get()};
-  ErrorPtr error_{GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
+  ErrorHandleHolder error_{GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
       "Error", nested_errors_, 1)};
 };
 
@@ -227,7 +230,7 @@ static void BM_ErrorStringOnNewError(benchmark::State& state) {
   TrackCounters track_counters;
   for (auto _ : state) {
     Fixture fixture;
-    grpc_error_string(fixture.error());
+    grpc_error_std_string(fixture.error());
   }
   track_counters.Finish(state);
 }
@@ -237,7 +240,7 @@ static void BM_ErrorStringRepeatedly(benchmark::State& state) {
   TrackCounters track_counters;
   Fixture fixture;
   for (auto _ : state) {
-    grpc_error_string(fixture.error());
+    grpc_error_std_string(fixture.error());
   }
   track_counters.Finish(state);
 }
@@ -249,9 +252,9 @@ static void BM_ErrorGetStatus(benchmark::State& state) {
   grpc_core::ExecCtx exec_ctx;
   for (auto _ : state) {
     grpc_status_code status;
-    grpc_slice slice;
-    grpc_error_get_status(fixture.error(), fixture.deadline(), &status, &slice,
-                          nullptr, nullptr);
+    std::string message;
+    grpc_error_get_status(fixture.error(), fixture.deadline(), &status,
+                          &message, nullptr, nullptr);
   }
 
   track_counters.Finish(state);
index 4c3a6a1..6d7394a 100644 (file)
@@ -306,9 +306,10 @@ static void BM_PumpStreamServerToClient_Trickle(benchmark::State& state) {
       }
     };
     gpr_timespec warmup_start = gpr_now(GPR_CLOCK_MONOTONIC);
-    for (int i = 0; i < GPR_MAX(absl::GetFlag(FLAGS_warmup_iterations),
-                                absl::GetFlag(FLAGS_warmup_megabytes) * 1024 *
-                                    1024 / (14 + state.range(0)));
+    for (int i = 0;
+         i < std::max(int64_t(absl::GetFlag(FLAGS_warmup_iterations)),
+                      absl::GetFlag(FLAGS_warmup_megabytes) * 1024 * 1024 /
+                          (14 + state.range(0)));
          i++) {
       inner_loop(true);
       if (gpr_time_cmp(gpr_time_sub(gpr_now(GPR_CLOCK_MONOTONIC), warmup_start),
@@ -420,9 +421,9 @@ static void BM_PumpUnbalancedUnary_Trickle(benchmark::State& state) {
                         fixture->cq(), fixture->cq(), tag(slot));
   };
   gpr_timespec warmup_start = gpr_now(GPR_CLOCK_MONOTONIC);
-  for (int i = 0; i < GPR_MAX(absl::GetFlag(FLAGS_warmup_iterations),
-                              absl::GetFlag(FLAGS_warmup_megabytes) * 1024 *
-                                  1024 / (14 + state.range(0)));
+  for (int i = 0; i < std::max(int64_t(absl::GetFlag(FLAGS_warmup_iterations)),
+                               absl::GetFlag(FLAGS_warmup_megabytes) * 1024 *
+                                   1024 / (14 + state.range(0)));
        i++) {
     inner_loop(true);
     if (gpr_time_cmp(
index 7a3aadb..800162f 100644 (file)
@@ -28,6 +28,7 @@
 #include <grpc/grpc.h>
 #include <grpcpp/grpcpp.h>
 
+#include "src/core/lib/config/core_configuration.h"
 #include "src/cpp/ext/filters/census/grpc_plugin.h"
 #include "src/proto/grpc/testing/echo.grpc.pb.h"
 #include "test/core/util/test_config.h"
@@ -86,6 +87,7 @@ class EchoServerThread final {
 };
 
 static void BM_E2eLatencyCensusDisabled(benchmark::State& state) {
+  grpc_core::CoreConfiguration::Reset();
   grpc::testing::TestGrpcScope grpc_scope;
   EchoServerThread server;
   std::unique_ptr<grpc::testing::EchoTestService::Stub> stub =
@@ -102,6 +104,7 @@ static void BM_E2eLatencyCensusDisabled(benchmark::State& state) {
 BENCHMARK(BM_E2eLatencyCensusDisabled);
 
 static void BM_E2eLatencyCensusEnabled(benchmark::State& state) {
+  grpc_core::CoreConfiguration::Reset();
   // Now start the test by registering the plugin (once in the execution)
   RegisterOnce();
   // This we can safely repeat, and doing so clears accumulated data to avoid
index dd57bce..b65efae 100644 (file)
@@ -152,12 +152,13 @@ class SuicideFunctorForAdd : public grpc_completion_queue_functor {
 // Performs the scenario of external thread(s) adding closures into pool.
 static void BM_ThreadPoolExternalAdd(benchmark::State& state) {
   static grpc_core::ThreadPool* external_add_pool = nullptr;
+  int thread_idx = state.thread_index();
   // Setup for each run of test.
-  if (state.thread_index == 0) {
+  if (thread_idx == 0) {
     const int num_threads = state.range(1);
     external_add_pool = new grpc_core::ThreadPool(num_threads);
   }
-  const int num_iterations = state.range(0) / state.threads;
+  const int num_iterations = state.range(0) / state.threads();
   while (state.KeepRunningBatch(num_iterations)) {
     BlockingCounter counter(num_iterations);
     for (int i = 0; i < num_iterations; ++i) {
@@ -167,7 +168,7 @@ static void BM_ThreadPoolExternalAdd(benchmark::State& state) {
   }
 
   // Teardown at the end of each test run.
-  if (state.thread_index == 0) {
+  if (thread_idx == 0) {
     state.SetItemsProcessed(state.range(0));
     delete external_add_pool;
   }
index 08ff75a..86e1534 100644 (file)
@@ -185,8 +185,10 @@ class EndpointPairFixture : public BaseFixture {
         grpc_endpoint_add_to_pollset(endpoints.server, pollset);
       }
 
-      server_->c_server()->core_server->SetupTransport(
-          server_transport_, nullptr, server_args, nullptr);
+      GPR_ASSERT(GRPC_LOG_IF_ERROR(
+          "SetupTransport",
+          server_->c_server()->core_server->SetupTransport(
+              server_transport_, nullptr, server_args, nullptr)));
       grpc_chttp2_transport_start_reading(server_transport_, nullptr, nullptr,
                                           nullptr);
     }
diff --git a/test/cpp/microbenchmarks/grpc_benchmark_config.bzl b/test/cpp/microbenchmarks/grpc_benchmark_config.bzl
new file mode 100644 (file)
index 0000000..5b80171
--- /dev/null
@@ -0,0 +1,18 @@
+# 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.
+"""Configuration macros for grpc microbenchmarking"""
+
+def grpc_benchmark_args():
+    """Command line arguments for running a microbenchmark as a test"""
+    return ["--benchmark_min_time=0.001"]
index b35c37c..85bb419 100644 (file)
@@ -20,7 +20,7 @@ package(
     ],
 )
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_py_binary")
 load(":generate_resolver_component_tests.bzl", "generate_resolver_component_tests")
index 8781177..10af8bf 100644 (file)
@@ -20,7 +20,7 @@ package(
     ],
 )
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 load("//bazel:grpc_build_system.bzl", "grpc_py_binary")
 
index 9d22564..04506a1 100644 (file)
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_package")
 
index f49795e..900d55d 100644 (file)
@@ -81,8 +81,9 @@ class EndpointPairFixture {
         grpc_endpoint_add_to_pollset(endpoints.server, pollset);
       }
 
-      server_->c_server()->core_server->SetupTransport(transport, nullptr,
-                                                       server_args, nullptr);
+      GPR_ASSERT(GRPC_LOG_IF_ERROR(
+          "SetupTransport", server_->c_server()->core_server->SetupTransport(
+                                transport, nullptr, server_args, nullptr)));
       grpc_chttp2_transport_start_reading(transport, nullptr, nullptr, nullptr);
     }
 
index 6fdcfd0..c856a50 100644 (file)
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 load("//bazel:grpc_build_system.bzl", "grpc_cc_binary", "grpc_cc_library", "grpc_cc_test", "grpc_package")
 load("//test/cpp/qps:qps_benchmark_script.bzl", "json_run_localhost_batch", "qps_json_driver_batch")
index 9d2c723..61914e9 100644 (file)
@@ -191,8 +191,8 @@ class Client {
     if (median_latency_collection_interval_seconds_ > 0) {
       std::vector<double> medians_per_interval =
           threads_[0]->GetMedianPerIntervalList();
-      gpr_log(GPR_INFO, "Num threads: %ld", threads_.size());
-      gpr_log(GPR_INFO, "Number of medians: %ld", medians_per_interval.size());
+      gpr_log(GPR_INFO, "Num threads: %zu", threads_.size());
+      gpr_log(GPR_INFO, "Number of medians: %zu", medians_per_interval.size());
       for (size_t j = 0; j < medians_per_interval.size(); j++) {
         gpr_log(GPR_INFO, "%f", medians_per_interval[j]);
       }
index d2ecb63..0a70084 100644 (file)
@@ -270,7 +270,12 @@ static void ReceiveFinalStatusFromClients(
             stats.request_results(i).count();
       }
       result.add_client_stats()->CopyFrom(stats);
-      // That final status should be the last message on the client stream
+      // Check that final status was should be the last message on the client
+      // stream.
+      // TODO(jtattermusch): note that that waiting for Read to return can take
+      // long on some scenarios (e.g. unconstrained streaming_from_server). See
+      // https://github.com/grpc/grpc/blob/3bd0cd208ea549760a2daf595f79b91b247fe240/test/cpp/qps/server_async.cc#L176
+      // where the shutdown delay pretty much determines the wait here.
       GPR_ASSERT(!client->stream->Read(&client_status));
     } else {
       gpr_log(GPR_ERROR, "Couldn't get final status from client %zu", i);
diff --git a/test/cpp/qps/gen_build_yaml.py b/test/cpp/qps/gen_build_yaml.py
deleted file mode 100755 (executable)
index 75a4cd4..0000000
+++ /dev/null
@@ -1,200 +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.
-
-from __future__ import print_function
-
-import json
-import os
-import pipes
-import shutil
-import sys
-
-import yaml
-
-run_tests_root = os.path.abspath(
-    os.path.join(os.path.dirname(sys.argv[0]), '../../../tools/run_tests'))
-sys.path.append(run_tests_root)
-
-import performance.scenario_config as scenario_config
-
-configs_from_yaml = yaml.load(
-    open(
-        os.path.join(os.path.dirname(sys.argv[0]),
-                     '../../../build_handwritten.yaml')))['configs'].keys()
-
-
-def mutate_scenario(scenario_json, is_tsan):
-    # tweak parameters to get fast test times
-    scenario_json = dict(scenario_json)
-    scenario_json['warmup_seconds'] = 0
-    scenario_json['benchmark_seconds'] = 1
-    outstanding_rpcs_divisor = 1
-    if is_tsan and (
-            scenario_json['client_config']['client_type'] == 'SYNC_CLIENT' or
-            scenario_json['server_config']['server_type'] == 'SYNC_SERVER'):
-        outstanding_rpcs_divisor = 10
-    scenario_json['client_config']['outstanding_rpcs_per_channel'] = max(
-        1,
-        int(scenario_json['client_config']['outstanding_rpcs_per_channel'] /
-            outstanding_rpcs_divisor))
-    return scenario_json
-
-
-def _scenario_json_string(scenario_json, is_tsan):
-    scenarios_json = {
-        'scenarios': [
-            scenario_config.remove_nonproto_fields(
-                mutate_scenario(scenario_json, is_tsan))
-        ]
-    }
-    return json.dumps(scenarios_json)
-
-
-def threads_required(scenario_json, where, is_tsan):
-    scenario_json = mutate_scenario(scenario_json, is_tsan)
-    if scenario_json['%s_config' % where]['%s_type' %
-                                          where] == 'ASYNC_%s' % where.upper():
-        return scenario_json['%s_config' % where].get(
-            'async_%s_threads' % where, 0)
-    return scenario_json['client_config'][
-        'outstanding_rpcs_per_channel'] * scenario_json['client_config'][
-            'client_channels']
-
-
-def guess_cpu(scenario_json, is_tsan):
-    client = threads_required(scenario_json, 'client', is_tsan)
-    server = threads_required(scenario_json, 'server', is_tsan)
-    # make an arbitrary guess if set to auto-detect
-    # about the size of the jenkins instances we have for unit tests
-    if client == 0 or server == 0:
-        return 'capacity'
-    return (scenario_json['num_clients'] * client +
-            scenario_json['num_servers'] * server)
-
-
-def maybe_exclude_gcov(scenario_json):
-    if scenario_json['client_config']['client_channels'] > 100:
-        return ['gcov']
-    return []
-
-
-# Originally, this method was used to generate qps test cases for build.yaml,
-# but since the test cases are now extracted from bazel BUILD file,
-# this is not used for generating run_tests.py test cases anymore.
-# Nevertheless, the output is still used by json_run_localhost_scenario_gen.py
-# and qps_json_driver_scenario_gen.py to generate the scenario list for bazel.
-# TODO(jtattermusch): cleanup this file, so that it only generates data needed
-# by bazel.
-def generate_yaml():
-    return {
-        'tests':
-            [{
-                'name':
-                    'json_run_localhost',
-                'shortname':
-                    'json_run_localhost:%s' % scenario_json['name'],
-                'args': [
-                    '--scenarios_json',
-                    _scenario_json_string(scenario_json, False)
-                ],
-                'ci_platforms': ['linux'],
-                'platforms': ['linux'],
-                'flaky':
-                    False,
-                'language':
-                    'c++',
-                'boringssl':
-                    True,
-                'defaults':
-                    'boringssl',
-                'cpu_cost':
-                    guess_cpu(scenario_json, False),
-                'exclude_configs': ['tsan', 'asan'] +
-                                   maybe_exclude_gcov(scenario_json),
-                'timeout_seconds':
-                    2 * 60,
-                'excluded_poll_engines':
-                    scenario_json.get('EXCLUDED_POLL_ENGINES', []),
-                'auto_timeout_scaling':
-                    False
-            }
-             for scenario_json in scenario_config.CXXLanguage().scenarios()
-             if 'scalable' in scenario_json.get('CATEGORIES', [])] +
-            [{
-                'name':
-                    'qps_json_driver',
-                'shortname':
-                    'qps_json_driver:inproc_%s' % scenario_json['name'],
-                'args': [
-                    '--run_inproc', '--scenarios_json',
-                    _scenario_json_string(scenario_json, False)
-                ],
-                'ci_platforms': ['linux'],
-                'platforms': ['linux'],
-                'flaky':
-                    False,
-                'language':
-                    'c++',
-                'boringssl':
-                    True,
-                'defaults':
-                    'boringssl',
-                'cpu_cost':
-                    guess_cpu(scenario_json, False),
-                'exclude_configs': ['tsan', 'asan'],
-                'timeout_seconds':
-                    6 * 60,
-                'excluded_poll_engines':
-                    scenario_json.get('EXCLUDED_POLL_ENGINES', [])
-            }
-             for scenario_json in scenario_config.CXXLanguage().scenarios()
-             if 'inproc' in scenario_json.get('CATEGORIES', [])] +
-            [{
-                'name':
-                    'json_run_localhost',
-                'shortname':
-                    'json_run_localhost:%s_low_thread_count' %
-                    scenario_json['name'],
-                'args': [
-                    '--scenarios_json',
-                    _scenario_json_string(scenario_json, True)
-                ],
-                'ci_platforms': ['linux'],
-                'platforms': ['linux'],
-                'flaky':
-                    False,
-                'language':
-                    'c++',
-                'boringssl':
-                    True,
-                'defaults':
-                    'boringssl',
-                'cpu_cost':
-                    guess_cpu(scenario_json, True),
-                'exclude_configs':
-                    sorted(c
-                           for c in configs_from_yaml
-                           if c not in ('tsan', 'asan')),
-                'timeout_seconds':
-                    10 * 60,
-                'excluded_poll_engines':
-                    scenario_json.get('EXCLUDED_POLL_ENGINES', []),
-                'auto_timeout_scaling':
-                    False
-            }
-             for scenario_json in scenario_config.CXXLanguage().scenarios()
-             if 'scalable' in scenario_json.get('CATEGORIES', [])]
-    }
index 1e2caa2..1a3682e 100644 (file)
@@ -31,8 +31,8 @@
 namespace grpc {
 namespace testing {
 
-static const int WARMUP = 5;
-static const int BENCHMARK = 5;
+static const int WARMUP = 1;
+static const int BENCHMARK = 3;
 
 static void RunSynchronousUnaryPingPong() {
   gpr_log(GPR_INFO, "Running Synchronous Unary Ping Pong");
index 8ee66c6..c7c5028 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python2.7
+#!/usr/bin/env python3
 
 # Copyright 2018 gRPC authors.
 #
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import json
+import os
+import sys
 
-import gen_build_yaml as gen
-
-COPYRIGHT = """
-# Copyright 2021 The gRPC Authors
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""
-
-
-def generate_args():
-    all_scenario_set = gen.generate_yaml()
-    all_scenario_set = all_scenario_set['tests']
-    json_run_localhost_scenarios = \
-        [item for item in all_scenario_set if item['name'] == 'json_run_localhost']
-    json_run_localhost_arg_set = \
-        [item['args'][1] for item in json_run_localhost_scenarios \
-        if 'args' in item and len(item['args']) > 1]
-    deserialized_scenarios = [json.loads(item)['scenarios'][0] \
-                              for item in json_run_localhost_arg_set]
-    all_scenarios = {scenario['name'].encode('ascii', 'ignore'): \
-                    '\'{\'scenarios\' : [' + json.dumps(scenario) + ']}\'' \
-                    for scenario in deserialized_scenarios}
-
-    serialized_scenarios_str = str(all_scenarios).encode('ascii', 'ignore')
-    with open('json_run_localhost_scenarios.bzl', 'wb') as f:
-        f.write(COPYRIGHT)
-        f.write('"""Scenarios run on localhost."""\n\n')
-        f.write('JSON_RUN_LOCALHOST_SCENARIOS = ' + serialized_scenarios_str +
-                '\n')
+script_dir = os.path.dirname(os.path.abspath(__file__))
+sys.path.append(script_dir)
 
+import scenario_generator_helper as gen
 
-generate_args()
+gen.generate_scenarios_bzl(
+    gen.generate_json_run_localhost_scenarios(),
+    os.path.join(script_dir, 'json_run_localhost_scenarios.bzl'),
+    'JSON_RUN_LOCALHOST_SCENARIOS')
index b864297..e7b2820 100644 (file)
 # 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.
-"""Scenarios run on localhost."""
+"""AUTOGENERATED: configuration of benchmark scenarios to be run as bazel test"""
 
-JSON_RUN_LOCALHOST_SCENARIOS = {"cpp_protobuf_async_unary_75Kqps_600channel_60Krpcs_300Breq_50Bresp": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_unary_75Kqps_600channel_60Krpcs_300Breq_50Bresp", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}], "async_server_threads": 16, "threads_per_cq": 1, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 100, "rpc_type": "UNARY", "load_params": {"poisson": {"offered_load": 37500}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 50, "req_size": 300}}, "client_channels": 300, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_sync_streaming_from_client_qps_unconstrained_secure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_sync_streaming_from_client_qps_unconstrained_secure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "server_type": "SYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_server_threads": 0, "threads_per_cq": 3, "server_processes": 0}, "client_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 1, "rpc_type": "STREAMING_FROM_CLIENT", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "SYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 3, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_async_unary_qps_unconstrained_1cq_insecure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_unary_qps_unconstrained_1cq_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_server_threads": 0, "threads_per_cq": 1000000, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 13, "rpc_type": "UNARY", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 1000000, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_async_streaming_from_client_ping_pong_secure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_streaming_from_client_ping_pong_secure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}], "async_server_threads": 1, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}], "async_client_threads": 1, "outstanding_rpcs_per_channel": 1, "rpc_type": "STREAMING_FROM_CLIENT", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 1, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 1}]}\'', "cpp_generic_async_streaming_qps_1channel_1MBmsg_secure": '\'{\'scenarios\' : [{"name": "cpp_generic_async_streaming_qps_1channel_1MBmsg_secure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"async_server_threads": 0, "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "server_type": "ASYNC_GENERIC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "payload_config": {"bytebuf_params": {"resp_size": 1048576, "req_size": 1048576}}, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 100, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"bytebuf_params": {"resp_size": 1048576, "req_size": 1048576}}, "client_channels": 1, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_async_streaming_from_server_ping_pong_secure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_streaming_from_server_ping_pong_secure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}], "async_server_threads": 1, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}], "async_client_threads": 1, "outstanding_rpcs_per_channel": 1, "rpc_type": "STREAMING_FROM_SERVER", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 1, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 1}]}\'', "cpp_protobuf_async_streaming_qps_unconstrained_1mps_secure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_streaming_qps_unconstrained_1mps_secure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_server_threads": 0, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 100, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "messages_per_stream": 1, "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_generic_async_streaming_qps_unconstrained_64KBmsg_secure": '\'{\'scenarios\' : [{"name": "cpp_generic_async_streaming_qps_unconstrained_64KBmsg_secure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"async_server_threads": 0, "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "server_type": "ASYNC_GENERIC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "payload_config": {"bytebuf_params": {"resp_size": 65536, "req_size": 65536}}, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 100, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"bytebuf_params": {"resp_size": 65536, "req_size": 65536}}, "client_channels": 64, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_sync_streaming_ping_pong_insecure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_sync_streaming_ping_pong_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "SYNC_SERVER", "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_server_threads": 1, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 1, "outstanding_rpcs_per_channel": 1, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "SYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 1, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 1}]}\'', "cpp_generic_async_streaming_qps_unconstrained_1mps_secure": '\'{\'scenarios\' : [{"name": "cpp_generic_async_streaming_qps_unconstrained_1mps_secure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"async_server_threads": 0, "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "server_type": "ASYNC_GENERIC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "payload_config": {"bytebuf_params": {"resp_size": 0, "req_size": 0}}, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 100, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "messages_per_stream": 1, "payload_config": {"bytebuf_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_async_streaming_qps_unconstrained_1cq_secure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_streaming_qps_unconstrained_1cq_secure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_server_threads": 0, "threads_per_cq": 1000000, "server_processes": 0}, "client_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 13, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 1000000, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_generic_async_streaming_qps_unconstrained_10mps_secure": '\'{\'scenarios\' : [{"name": "cpp_generic_async_streaming_qps_unconstrained_10mps_secure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"async_server_threads": 0, "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "server_type": "ASYNC_GENERIC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "payload_config": {"bytebuf_params": {"resp_size": 0, "req_size": 0}}, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 100, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "messages_per_stream": 10, "payload_config": {"bytebuf_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_async_unary_ping_pong_insecure_1MB": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_unary_ping_pong_insecure_1MB", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_server_threads": 0, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 1, "outstanding_rpcs_per_channel": 1, "rpc_type": "UNARY", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 1048576, "req_size": 1048576}}, "client_channels": 1, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 1}]}\'', "cpp_generic_async_streaming_qps_one_server_core_secure": '\'{\'scenarios\' : [{"name": "cpp_generic_async_streaming_qps_one_server_core_secure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"async_server_threads": 1, "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "server_type": "ASYNC_GENERIC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "payload_config": {"bytebuf_params": {"resp_size": 0, "req_size": 0}}, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 13, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"bytebuf_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_sync_streaming_qps_unconstrained_10mps_insecure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_sync_streaming_qps_unconstrained_10mps_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "SYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_server_threads": 0, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 1, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "SYNC_CLIENT", "messages_per_stream": 10, "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_async_unary_qps_unconstrained_2waysharedcq_insecure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_unary_qps_unconstrained_2waysharedcq_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_server_threads": 0, "threads_per_cq": 2, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 100, "rpc_type": "UNARY", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 2, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_async_streaming_from_server_qps_unconstrained_insecure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_streaming_from_server_qps_unconstrained_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_server_threads": 0, "threads_per_cq": 3, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 100, "rpc_type": "STREAMING_FROM_SERVER", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 3, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_generic_async_streaming_qps_unconstrained_2waysharedcq_secure": '\'{\'scenarios\' : [{"name": "cpp_generic_async_streaming_qps_unconstrained_2waysharedcq_secure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"async_server_threads": 0, "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "server_type": "ASYNC_GENERIC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "payload_config": {"bytebuf_params": {"resp_size": 0, "req_size": 0}}, "threads_per_cq": 2, "server_processes": 0}, "client_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 100, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"bytebuf_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 2, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_generic_async_streaming_ping_pong_secure": '\'{\'scenarios\' : [{"name": "cpp_generic_async_streaming_ping_pong_secure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"async_server_threads": 1, "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "server_type": "ASYNC_GENERIC_SERVER", "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}], "payload_config": {"bytebuf_params": {"resp_size": 0, "req_size": 0}}, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}], "async_client_threads": 1, "outstanding_rpcs_per_channel": 1, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"bytebuf_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 1, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 1}]}\'', "cpp_protobuf_sync_streaming_from_server_qps_unconstrained_secure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_sync_streaming_from_server_qps_unconstrained_secure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "server_type": "SYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_server_threads": 0, "threads_per_cq": 3, "server_processes": 0}, "client_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 1, "rpc_type": "STREAMING_FROM_SERVER", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "SYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 3, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_sync_streaming_qps_unconstrained_10mps_secure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_sync_streaming_qps_unconstrained_10mps_secure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "server_type": "SYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_server_threads": 0, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 1, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "SYNC_CLIENT", "messages_per_stream": 10, "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_sync_unary_qps_unconstrained_secure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_sync_unary_qps_unconstrained_secure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "server_type": "SYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_server_threads": 0, "threads_per_cq": 3, "server_processes": 0}, "client_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 1, "rpc_type": "UNARY", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "SYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 3, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_sync_streaming_from_client_ping_pong_insecure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_sync_streaming_from_client_ping_pong_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "SYNC_SERVER", "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_server_threads": 1, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 1, "outstanding_rpcs_per_channel": 1, "rpc_type": "STREAMING_FROM_CLIENT", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "SYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 1, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 1}]}\'', "cpp_protobuf_sync_streaming_from_client_qps_unconstrained_insecure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_sync_streaming_from_client_qps_unconstrained_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "SYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_server_threads": 0, "threads_per_cq": 3, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 1, "rpc_type": "STREAMING_FROM_CLIENT", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "SYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 3, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_sync_streaming_from_client_ping_pong_secure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_sync_streaming_from_client_ping_pong_secure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "server_type": "SYNC_SERVER", "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}], "async_server_threads": 1, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}], "async_client_threads": 1, "outstanding_rpcs_per_channel": 1, "rpc_type": "STREAMING_FROM_CLIENT", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "SYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 1, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 1}]}\'', "cpp_protobuf_async_streaming_qps_unconstrained_insecure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_streaming_qps_unconstrained_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_server_threads": 0, "threads_per_cq": 3, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 100, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 3, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_async_streaming_qps_unconstrained_2waysharedcq_insecure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_streaming_qps_unconstrained_2waysharedcq_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_server_threads": 0, "threads_per_cq": 2, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 100, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 2, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_generic_async_streaming_qps_unconstrained_1cq_insecure": '\'{\'scenarios\' : [{"name": "cpp_generic_async_streaming_qps_unconstrained_1cq_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"async_server_threads": 0, "security_params": null, "server_type": "ASYNC_GENERIC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "payload_config": {"bytebuf_params": {"resp_size": 0, "req_size": 0}}, "threads_per_cq": 1000000, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 13, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"bytebuf_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 1000000, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_async_streaming_qps_unconstrained_10mps_insecure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_streaming_qps_unconstrained_10mps_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_server_threads": 0, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 100, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "messages_per_stream": 10, "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_generic_async_streaming_qps_unconstrained_64KBmsg_insecure": '\'{\'scenarios\' : [{"name": "cpp_generic_async_streaming_qps_unconstrained_64KBmsg_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"async_server_threads": 0, "security_params": null, "server_type": "ASYNC_GENERIC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "payload_config": {"bytebuf_params": {"resp_size": 65536, "req_size": 65536}}, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 100, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"bytebuf_params": {"resp_size": 65536, "req_size": 65536}}, "client_channels": 64, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_sync_streaming_qps_unconstrained_secure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_sync_streaming_qps_unconstrained_secure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "server_type": "SYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_server_threads": 0, "threads_per_cq": 3, "server_processes": 0}, "client_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 1, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "SYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 3, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_async_streaming_from_server_qps_unconstrained_secure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_streaming_from_server_qps_unconstrained_secure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_server_threads": 0, "threads_per_cq": 3, "server_processes": 0}, "client_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 100, "rpc_type": "STREAMING_FROM_SERVER", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 3, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_generic_async_streaming_qps_unconstrained_insecure": '\'{\'scenarios\' : [{"name": "cpp_generic_async_streaming_qps_unconstrained_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"async_server_threads": 0, "security_params": null, "server_type": "ASYNC_GENERIC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "payload_config": {"bytebuf_params": {"resp_size": 0, "req_size": 0}}, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 100, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"bytebuf_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_async_client_unary_1channel_64wide_128Breq_8MBresp_secure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_client_unary_1channel_64wide_128Breq_8MBresp_secure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}], "async_server_threads": 0, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}], "async_client_threads": 1, "outstanding_rpcs_per_channel": 1, "rpc_type": "UNARY", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 8388608, "req_size": 128}}, "client_channels": 1, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 1}]}\'', "cpp_protobuf_async_streaming_ping_pong_insecure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_streaming_ping_pong_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_server_threads": 1, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 1, "outstanding_rpcs_per_channel": 1, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 1, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 1}]}\'', "cpp_protobuf_sync_streaming_qps_unconstrained_insecure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_sync_streaming_qps_unconstrained_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "SYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_server_threads": 0, "threads_per_cq": 3, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 1, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "SYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 3, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_async_streaming_from_client_ping_pong_insecure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_streaming_from_client_ping_pong_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_server_threads": 1, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 1, "outstanding_rpcs_per_channel": 1, "rpc_type": "STREAMING_FROM_CLIENT", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 1, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 1}]}\'', "cpp_protobuf_async_streaming_from_client_1channel_1MB": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_streaming_from_client_1channel_1MB", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_server_threads": 0, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 1, "rpc_type": "STREAMING_FROM_CLIENT", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 1048576, "req_size": 1048576}}, "client_channels": 1, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 1}]}\'', "cpp_protobuf_async_unary_1channel_100rpcs_1MB": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_unary_1channel_100rpcs_1MB", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_server_threads": 0, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 100, "rpc_type": "UNARY", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 1048576, "req_size": 1048576}}, "client_channels": 1, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 1}]}\'', "cpp_generic_async_streaming_qps_unconstrained_secure": '\'{\'scenarios\' : [{"name": "cpp_generic_async_streaming_qps_unconstrained_secure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"async_server_threads": 0, "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "server_type": "ASYNC_GENERIC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "payload_config": {"bytebuf_params": {"resp_size": 0, "req_size": 0}}, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 100, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"bytebuf_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_generic_async_streaming_qps_1channel_1MBmsg_insecure": '\'{\'scenarios\' : [{"name": "cpp_generic_async_streaming_qps_1channel_1MBmsg_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"async_server_threads": 0, "security_params": null, "server_type": "ASYNC_GENERIC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "payload_config": {"bytebuf_params": {"resp_size": 1048576, "req_size": 1048576}}, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 100, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"bytebuf_params": {"resp_size": 1048576, "req_size": 1048576}}, "client_channels": 1, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_generic_async_streaming_qps_unconstrained_1mps_insecure": '\'{\'scenarios\' : [{"name": "cpp_generic_async_streaming_qps_unconstrained_1mps_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"async_server_threads": 0, "security_params": null, "server_type": "ASYNC_GENERIC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "payload_config": {"bytebuf_params": {"resp_size": 0, "req_size": 0}}, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 100, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "messages_per_stream": 1, "payload_config": {"bytebuf_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_async_streaming_qps_unconstrained_2waysharedcq_secure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_streaming_qps_unconstrained_2waysharedcq_secure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_server_threads": 0, "threads_per_cq": 2, "server_processes": 0}, "client_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 100, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 2, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_sync_streaming_ping_pong_secure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_sync_streaming_ping_pong_secure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "server_type": "SYNC_SERVER", "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}], "async_server_threads": 1, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}], "async_client_threads": 1, "outstanding_rpcs_per_channel": 1, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "SYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 1, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 1}]}\'', "cpp_protobuf_sync_streaming_from_server_qps_unconstrained_insecure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_sync_streaming_from_server_qps_unconstrained_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "SYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_server_threads": 0, "threads_per_cq": 3, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 1, "rpc_type": "STREAMING_FROM_SERVER", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "SYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 3, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_insecure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "SYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_server_threads": 0, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 10, "rpc_type": "UNARY", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_async_unary_ping_pong_insecure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_unary_ping_pong_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_server_threads": 1, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 1, "outstanding_rpcs_per_channel": 1, "rpc_type": "UNARY", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 1, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 1}]}\'', "cpp_protobuf_async_client_unary_1channel_64wide_128Breq_8MBresp_insecure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_client_unary_1channel_64wide_128Breq_8MBresp_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_server_threads": 0, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 1, "outstanding_rpcs_per_channel": 1, "rpc_type": "UNARY", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 8388608, "req_size": 128}}, "client_channels": 1, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 1}]}\'', "cpp_generic_async_streaming_ping_pong_insecure": '\'{\'scenarios\' : [{"name": "cpp_generic_async_streaming_ping_pong_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"async_server_threads": 1, "security_params": null, "server_type": "ASYNC_GENERIC_SERVER", "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}], "payload_config": {"bytebuf_params": {"resp_size": 0, "req_size": 0}}, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}], "async_client_threads": 1, "outstanding_rpcs_per_channel": 1, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"bytebuf_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 1, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 1}]}\'', "cpp_protobuf_sync_streaming_from_server_ping_pong_secure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_sync_streaming_from_server_ping_pong_secure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "server_type": "SYNC_SERVER", "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}], "async_server_threads": 1, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}], "async_client_threads": 1, "outstanding_rpcs_per_channel": 1, "rpc_type": "STREAMING_FROM_SERVER", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "SYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 1, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 1}]}\'', "cpp_protobuf_async_unary_qps_unconstrained_1cq_secure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_unary_qps_unconstrained_1cq_secure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_server_threads": 0, "threads_per_cq": 1000000, "server_processes": 0}, "client_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 13, "rpc_type": "UNARY", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 1000000, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_sync_unary_ping_pong_insecure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_sync_unary_ping_pong_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "SYNC_SERVER", "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_server_threads": 1, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 1, "outstanding_rpcs_per_channel": 1, "rpc_type": "UNARY", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "SYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 1, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 1}]}\'', "cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_insecure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "SYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_server_threads": 0, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 10, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_generic_async_streaming_qps_one_server_core_insecure": '\'{\'scenarios\' : [{"name": "cpp_generic_async_streaming_qps_one_server_core_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"async_server_threads": 1, "security_params": null, "server_type": "ASYNC_GENERIC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "payload_config": {"bytebuf_params": {"resp_size": 0, "req_size": 0}}, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 13, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"bytebuf_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_secure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_secure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "server_type": "SYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_server_threads": 0, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 10, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_async_streaming_from_server_ping_pong_insecure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_streaming_from_server_ping_pong_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_server_threads": 1, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 1, "outstanding_rpcs_per_channel": 1, "rpc_type": "STREAMING_FROM_SERVER", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 1, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 1}]}\'', "cpp_generic_async_streaming_qps_unconstrained_2waysharedcq_insecure": '\'{\'scenarios\' : [{"name": "cpp_generic_async_streaming_qps_unconstrained_2waysharedcq_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"async_server_threads": 0, "security_params": null, "server_type": "ASYNC_GENERIC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "payload_config": {"bytebuf_params": {"resp_size": 0, "req_size": 0}}, "threads_per_cq": 2, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 100, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"bytebuf_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 2, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_sync_streaming_qps_unconstrained_1mps_insecure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_sync_streaming_qps_unconstrained_1mps_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "SYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_server_threads": 0, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 1, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "SYNC_CLIENT", "messages_per_stream": 1, "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_sync_unary_qps_unconstrained_insecure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_sync_unary_qps_unconstrained_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "SYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_server_threads": 0, "threads_per_cq": 3, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 1, "rpc_type": "UNARY", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "SYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 3, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_async_unary_ping_pong_secure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_unary_ping_pong_secure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}], "async_server_threads": 1, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}], "async_client_threads": 1, "outstanding_rpcs_per_channel": 1, "rpc_type": "UNARY", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 1, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 1}]}\'', "cpp_protobuf_async_unary_qps_unconstrained_2waysharedcq_secure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_unary_qps_unconstrained_2waysharedcq_secure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_server_threads": 0, "threads_per_cq": 2, "server_processes": 0}, "client_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 100, "rpc_type": "UNARY", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 2, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_async_streaming_from_client_qps_unconstrained_insecure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_streaming_from_client_qps_unconstrained_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_server_threads": 0, "threads_per_cq": 3, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 100, "rpc_type": "STREAMING_FROM_CLIENT", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 3, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_sync_unary_ping_pong_secure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_sync_unary_ping_pong_secure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "server_type": "SYNC_SERVER", "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}], "async_server_threads": 1, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}], "async_client_threads": 1, "outstanding_rpcs_per_channel": 1, "rpc_type": "UNARY", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "SYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 1, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 1}]}\'', "cpp_protobuf_async_unary_qps_unconstrained_secure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_unary_qps_unconstrained_secure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_server_threads": 0, "threads_per_cq": 3, "server_processes": 0}, "client_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 100, "rpc_type": "UNARY", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 3, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_sync_streaming_from_server_ping_pong_insecure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_sync_streaming_from_server_ping_pong_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "SYNC_SERVER", "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_server_threads": 1, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 1, "outstanding_rpcs_per_channel": 1, "rpc_type": "STREAMING_FROM_SERVER", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "SYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 1, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 1}]}\'', "cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_secure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_secure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "server_type": "SYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_server_threads": 0, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 10, "rpc_type": "UNARY", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_async_streaming_qps_unconstrained_secure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_streaming_qps_unconstrained_secure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_server_threads": 0, "threads_per_cq": 3, "server_processes": 0}, "client_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 100, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 3, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_async_unary_qps_unconstrained_insecure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_unary_qps_unconstrained_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_server_threads": 0, "threads_per_cq": 3, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 100, "rpc_type": "UNARY", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 3, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_generic_async_streaming_qps_unconstrained_1cq_secure": '\'{\'scenarios\' : [{"name": "cpp_generic_async_streaming_qps_unconstrained_1cq_secure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"async_server_threads": 0, "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "server_type": "ASYNC_GENERIC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "payload_config": {"bytebuf_params": {"resp_size": 0, "req_size": 0}}, "threads_per_cq": 1000000, "server_processes": 0}, "client_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 13, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"bytebuf_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 1000000, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_generic_async_streaming_qps_unconstrained_10mps_insecure": '\'{\'scenarios\' : [{"name": "cpp_generic_async_streaming_qps_unconstrained_10mps_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"async_server_threads": 0, "security_params": null, "server_type": "ASYNC_GENERIC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "payload_config": {"bytebuf_params": {"resp_size": 0, "req_size": 0}}, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 100, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "messages_per_stream": 10, "payload_config": {"bytebuf_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_async_streaming_qps_unconstrained_10mps_secure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_streaming_qps_unconstrained_10mps_secure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_server_threads": 0, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 100, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "messages_per_stream": 10, "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_async_streaming_ping_pong_secure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_streaming_ping_pong_secure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}], "async_server_threads": 1, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}], "async_client_threads": 1, "outstanding_rpcs_per_channel": 1, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 1, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 1}]}\'', "cpp_protobuf_async_streaming_from_client_qps_unconstrained_secure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_streaming_from_client_qps_unconstrained_secure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_server_threads": 0, "threads_per_cq": 3, "server_processes": 0}, "client_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 100, "rpc_type": "STREAMING_FROM_CLIENT", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 3, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_async_streaming_qps_unconstrained_1cq_insecure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_streaming_qps_unconstrained_1cq_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_server_threads": 0, "threads_per_cq": 1000000, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 13, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 1000000, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_sync_streaming_qps_unconstrained_1mps_secure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_sync_streaming_qps_unconstrained_1mps_secure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "server_type": "SYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_server_threads": 0, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 1, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "SYNC_CLIENT", "messages_per_stream": 1, "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_async_streaming_qps_unconstrained_1mps_insecure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_streaming_qps_unconstrained_1mps_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_server_threads": 0, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 100, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "messages_per_stream": 1, "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_async_unary_ping_pong_secure_1MB": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_unary_ping_pong_secure_1MB", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}], "async_server_threads": 0, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}], "async_client_threads": 1, "outstanding_rpcs_per_channel": 1, "rpc_type": "UNARY", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 1048576, "req_size": 1048576}}, "client_channels": 1, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 1}]}\''}
+JSON_RUN_LOCALHOST_SCENARIOS = {
+    "cpp_protobuf_async_unary_75Kqps_600channel_60Krpcs_300Breq_50Bresp": '\'{"scenarios": [{"name": "cpp_protobuf_async_unary_75Kqps_600channel_60Krpcs_300Breq_50Bresp", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 100, "client_channels": 16, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 0, "rpc_type": "UNARY", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}], "payload_config": {"simple_params": {"req_size": 300, "resp_size": 50}}, "load_params": {"poisson": {"offered_load": 37500}}}, "server_config": {"server_type": "ASYNC_SERVER", "security_params": null, "async_server_threads": 16, "server_processes": 0, "threads_per_cq": 1, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_generic_async_streaming_ping_pong_secure": '\'{"scenarios": [{"name": "cpp_generic_async_streaming_ping_pong_secure", "num_servers": 1, "num_clients": 1, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "outstanding_rpcs_per_channel": 1, "client_channels": 1, "async_client_threads": 1, "client_processes": 0, "threads_per_cq": 0, "rpc_type": "STREAMING", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}], "payload_config": {"bytebuf_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "ASYNC_GENERIC_SERVER", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "async_server_threads": 1, "server_processes": 0, "threads_per_cq": 0, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}], "payload_config": {"bytebuf_params": {"req_size": 0, "resp_size": 0}}}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_generic_async_streaming_qps_unconstrained_secure": '\'{"scenarios": [{"name": "cpp_generic_async_streaming_qps_unconstrained_secure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "outstanding_rpcs_per_channel": 100, "client_channels": 16, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 2, "rpc_type": "STREAMING", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}], "payload_config": {"bytebuf_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "ASYNC_GENERIC_SERVER", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 2, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}], "payload_config": {"bytebuf_params": {"req_size": 0, "resp_size": 0}}}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_generic_async_streaming_qps_unconstrained_10mps_secure": '\'{"scenarios": [{"name": "cpp_generic_async_streaming_qps_unconstrained_10mps_secure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "outstanding_rpcs_per_channel": 100, "client_channels": 16, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 0, "rpc_type": "STREAMING", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}], "payload_config": {"bytebuf_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}, "messages_per_stream": 10}, "server_config": {"server_type": "ASYNC_GENERIC_SERVER", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 0, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}], "payload_config": {"bytebuf_params": {"req_size": 0, "resp_size": 0}}}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_generic_async_streaming_qps_1channel_1MBmsg_secure": '\'{"scenarios": [{"name": "cpp_generic_async_streaming_qps_1channel_1MBmsg_secure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "outstanding_rpcs_per_channel": 100, "client_channels": 1, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 0, "rpc_type": "STREAMING", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}], "payload_config": {"bytebuf_params": {"req_size": 1048576, "resp_size": 1048576}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "ASYNC_GENERIC_SERVER", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 0, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}], "payload_config": {"bytebuf_params": {"req_size": 1048576, "resp_size": 1048576}}}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_generic_async_streaming_qps_unconstrained_64KBmsg_secure": '\'{"scenarios": [{"name": "cpp_generic_async_streaming_qps_unconstrained_64KBmsg_secure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "outstanding_rpcs_per_channel": 100, "client_channels": 16, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 0, "rpc_type": "STREAMING", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}], "payload_config": {"bytebuf_params": {"req_size": 65536, "resp_size": 65536}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "ASYNC_GENERIC_SERVER", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 0, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}], "payload_config": {"bytebuf_params": {"req_size": 65536, "resp_size": 65536}}}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_async_streaming_qps_unconstrained_1cq_secure": '\'{"scenarios": [{"name": "cpp_protobuf_async_streaming_qps_unconstrained_1cq_secure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "outstanding_rpcs_per_channel": 13, "client_channels": 16, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 1000000, "rpc_type": "STREAMING", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "ASYNC_SERVER", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 1000000, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_async_unary_qps_unconstrained_1cq_secure": '\'{"scenarios": [{"name": "cpp_protobuf_async_unary_qps_unconstrained_1cq_secure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "outstanding_rpcs_per_channel": 13, "client_channels": 16, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 1000000, "rpc_type": "UNARY", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "ASYNC_SERVER", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 1000000, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_secure": '\'{"scenarios": [{"name": "cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_secure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "outstanding_rpcs_per_channel": 10, "client_channels": 16, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 0, "rpc_type": "UNARY", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "SYNC_SERVER", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 0, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_async_client_unary_1channel_64wide_128Breq_8MBresp_secure": '\'{"scenarios": [{"name": "cpp_protobuf_async_client_unary_1channel_64wide_128Breq_8MBresp_secure", "num_servers": 1, "num_clients": 1, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "outstanding_rpcs_per_channel": 1, "client_channels": 1, "async_client_threads": 1, "client_processes": 0, "threads_per_cq": 0, "rpc_type": "UNARY", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}], "payload_config": {"simple_params": {"req_size": 128, "resp_size": 8388608}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "ASYNC_SERVER", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 0, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_async_unary_ping_pong_secure_1MB": '\'{"scenarios": [{"name": "cpp_protobuf_async_unary_ping_pong_secure_1MB", "num_servers": 1, "num_clients": 1, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "outstanding_rpcs_per_channel": 1, "client_channels": 1, "async_client_threads": 1, "client_processes": 0, "threads_per_cq": 0, "rpc_type": "UNARY", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}], "payload_config": {"simple_params": {"req_size": 1048576, "resp_size": 1048576}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "ASYNC_SERVER", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 0, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_sync_unary_ping_pong_secure": '\'{"scenarios": [{"name": "cpp_protobuf_sync_unary_ping_pong_secure", "num_servers": 1, "num_clients": 1, "client_config": {"client_type": "SYNC_CLIENT", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "outstanding_rpcs_per_channel": 1, "client_channels": 1, "async_client_threads": 1, "client_processes": 0, "threads_per_cq": 0, "rpc_type": "UNARY", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "SYNC_SERVER", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "async_server_threads": 1, "server_processes": 0, "threads_per_cq": 0, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_sync_unary_qps_unconstrained_secure": '\'{"scenarios": [{"name": "cpp_protobuf_sync_unary_qps_unconstrained_secure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "SYNC_CLIENT", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "outstanding_rpcs_per_channel": 1, "client_channels": 16, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 2, "rpc_type": "UNARY", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "SYNC_SERVER", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 2, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_async_unary_ping_pong_secure": '\'{"scenarios": [{"name": "cpp_protobuf_async_unary_ping_pong_secure", "num_servers": 1, "num_clients": 1, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "outstanding_rpcs_per_channel": 1, "client_channels": 1, "async_client_threads": 1, "client_processes": 0, "threads_per_cq": 0, "rpc_type": "UNARY", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "ASYNC_SERVER", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "async_server_threads": 1, "server_processes": 0, "threads_per_cq": 0, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_async_unary_qps_unconstrained_secure": '\'{"scenarios": [{"name": "cpp_protobuf_async_unary_qps_unconstrained_secure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "outstanding_rpcs_per_channel": 100, "client_channels": 16, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 2, "rpc_type": "UNARY", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "ASYNC_SERVER", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 2, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_sync_streaming_ping_pong_secure": '\'{"scenarios": [{"name": "cpp_protobuf_sync_streaming_ping_pong_secure", "num_servers": 1, "num_clients": 1, "client_config": {"client_type": "SYNC_CLIENT", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "outstanding_rpcs_per_channel": 1, "client_channels": 1, "async_client_threads": 1, "client_processes": 0, "threads_per_cq": 0, "rpc_type": "STREAMING", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "SYNC_SERVER", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "async_server_threads": 1, "server_processes": 0, "threads_per_cq": 0, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_sync_streaming_qps_unconstrained_secure": '\'{"scenarios": [{"name": "cpp_protobuf_sync_streaming_qps_unconstrained_secure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "SYNC_CLIENT", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "outstanding_rpcs_per_channel": 1, "client_channels": 16, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 2, "rpc_type": "STREAMING", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "SYNC_SERVER", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 2, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_sync_streaming_qps_unconstrained_10mps_secure": '\'{"scenarios": [{"name": "cpp_protobuf_sync_streaming_qps_unconstrained_10mps_secure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "SYNC_CLIENT", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "outstanding_rpcs_per_channel": 1, "client_channels": 16, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 0, "rpc_type": "STREAMING", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}, "messages_per_stream": 10}, "server_config": {"server_type": "SYNC_SERVER", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 0, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_async_streaming_ping_pong_secure": '\'{"scenarios": [{"name": "cpp_protobuf_async_streaming_ping_pong_secure", "num_servers": 1, "num_clients": 1, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "outstanding_rpcs_per_channel": 1, "client_channels": 1, "async_client_threads": 1, "client_processes": 0, "threads_per_cq": 0, "rpc_type": "STREAMING", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "ASYNC_SERVER", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "async_server_threads": 1, "server_processes": 0, "threads_per_cq": 0, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_async_streaming_qps_unconstrained_secure": '\'{"scenarios": [{"name": "cpp_protobuf_async_streaming_qps_unconstrained_secure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "outstanding_rpcs_per_channel": 100, "client_channels": 16, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 2, "rpc_type": "STREAMING", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "ASYNC_SERVER", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 2, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_async_streaming_qps_unconstrained_10mps_secure": '\'{"scenarios": [{"name": "cpp_protobuf_async_streaming_qps_unconstrained_10mps_secure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "outstanding_rpcs_per_channel": 100, "client_channels": 16, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 0, "rpc_type": "STREAMING", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}, "messages_per_stream": 10}, "server_config": {"server_type": "ASYNC_SERVER", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 0, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_sync_streaming_from_client_ping_pong_secure": '\'{"scenarios": [{"name": "cpp_protobuf_sync_streaming_from_client_ping_pong_secure", "num_servers": 1, "num_clients": 1, "client_config": {"client_type": "SYNC_CLIENT", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "outstanding_rpcs_per_channel": 1, "client_channels": 1, "async_client_threads": 1, "client_processes": 0, "threads_per_cq": 0, "rpc_type": "STREAMING_FROM_CLIENT", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "SYNC_SERVER", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "async_server_threads": 1, "server_processes": 0, "threads_per_cq": 0, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_sync_streaming_from_client_qps_unconstrained_secure": '\'{"scenarios": [{"name": "cpp_protobuf_sync_streaming_from_client_qps_unconstrained_secure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "SYNC_CLIENT", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "outstanding_rpcs_per_channel": 1, "client_channels": 16, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 2, "rpc_type": "STREAMING_FROM_CLIENT", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "SYNC_SERVER", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 2, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_async_streaming_from_client_ping_pong_secure": '\'{"scenarios": [{"name": "cpp_protobuf_async_streaming_from_client_ping_pong_secure", "num_servers": 1, "num_clients": 1, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "outstanding_rpcs_per_channel": 1, "client_channels": 1, "async_client_threads": 1, "client_processes": 0, "threads_per_cq": 0, "rpc_type": "STREAMING_FROM_CLIENT", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "ASYNC_SERVER", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "async_server_threads": 1, "server_processes": 0, "threads_per_cq": 0, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_async_streaming_from_client_qps_unconstrained_secure": '\'{"scenarios": [{"name": "cpp_protobuf_async_streaming_from_client_qps_unconstrained_secure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "outstanding_rpcs_per_channel": 100, "client_channels": 16, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 2, "rpc_type": "STREAMING_FROM_CLIENT", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "ASYNC_SERVER", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 2, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_sync_streaming_from_server_ping_pong_secure": '\'{"scenarios": [{"name": "cpp_protobuf_sync_streaming_from_server_ping_pong_secure", "num_servers": 1, "num_clients": 1, "client_config": {"client_type": "SYNC_CLIENT", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "outstanding_rpcs_per_channel": 1, "client_channels": 1, "async_client_threads": 1, "client_processes": 0, "threads_per_cq": 0, "rpc_type": "STREAMING_FROM_SERVER", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "SYNC_SERVER", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "async_server_threads": 1, "server_processes": 0, "threads_per_cq": 0, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_sync_streaming_from_server_qps_unconstrained_secure": '\'{"scenarios": [{"name": "cpp_protobuf_sync_streaming_from_server_qps_unconstrained_secure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "SYNC_CLIENT", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "outstanding_rpcs_per_channel": 1, "client_channels": 4, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 2, "rpc_type": "STREAMING_FROM_SERVER", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "SYNC_SERVER", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 2, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_async_streaming_from_server_ping_pong_secure": '\'{"scenarios": [{"name": "cpp_protobuf_async_streaming_from_server_ping_pong_secure", "num_servers": 1, "num_clients": 1, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "outstanding_rpcs_per_channel": 1, "client_channels": 1, "async_client_threads": 1, "client_processes": 0, "threads_per_cq": 0, "rpc_type": "STREAMING_FROM_SERVER", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "ASYNC_SERVER", "security_params": {"use_test_ca": true, "server_host_override": "foo.test.google.fr"}, "async_server_threads": 1, "server_processes": 0, "threads_per_cq": 0, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_generic_async_streaming_ping_pong_insecure": '\'{"scenarios": [{"name": "cpp_generic_async_streaming_ping_pong_insecure", "num_servers": 1, "num_clients": 1, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 1, "client_channels": 1, "async_client_threads": 1, "client_processes": 0, "threads_per_cq": 0, "rpc_type": "STREAMING", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}], "payload_config": {"bytebuf_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "ASYNC_GENERIC_SERVER", "security_params": null, "async_server_threads": 1, "server_processes": 0, "threads_per_cq": 0, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}], "payload_config": {"bytebuf_params": {"req_size": 0, "resp_size": 0}}}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_generic_async_streaming_qps_unconstrained_insecure": '\'{"scenarios": [{"name": "cpp_generic_async_streaming_qps_unconstrained_insecure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 100, "client_channels": 16, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 2, "rpc_type": "STREAMING", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"bytebuf_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "ASYNC_GENERIC_SERVER", "security_params": null, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 2, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"bytebuf_params": {"req_size": 0, "resp_size": 0}}}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_generic_async_streaming_qps_unconstrained_10mps_insecure": '\'{"scenarios": [{"name": "cpp_generic_async_streaming_qps_unconstrained_10mps_insecure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 100, "client_channels": 16, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 0, "rpc_type": "STREAMING", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"bytebuf_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}, "messages_per_stream": 10}, "server_config": {"server_type": "ASYNC_GENERIC_SERVER", "security_params": null, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 0, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"bytebuf_params": {"req_size": 0, "resp_size": 0}}}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_generic_async_streaming_qps_1channel_1MBmsg_insecure": '\'{"scenarios": [{"name": "cpp_generic_async_streaming_qps_1channel_1MBmsg_insecure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 100, "client_channels": 1, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 0, "rpc_type": "STREAMING", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"bytebuf_params": {"req_size": 1048576, "resp_size": 1048576}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "ASYNC_GENERIC_SERVER", "security_params": null, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 0, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"bytebuf_params": {"req_size": 1048576, "resp_size": 1048576}}}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_generic_async_streaming_qps_unconstrained_64KBmsg_insecure": '\'{"scenarios": [{"name": "cpp_generic_async_streaming_qps_unconstrained_64KBmsg_insecure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 100, "client_channels": 16, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 0, "rpc_type": "STREAMING", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"bytebuf_params": {"req_size": 65536, "resp_size": 65536}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "ASYNC_GENERIC_SERVER", "security_params": null, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 0, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"bytebuf_params": {"req_size": 65536, "resp_size": 65536}}}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_async_streaming_qps_unconstrained_1cq_insecure": '\'{"scenarios": [{"name": "cpp_protobuf_async_streaming_qps_unconstrained_1cq_insecure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 13, "client_channels": 16, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 1000000, "rpc_type": "STREAMING", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "ASYNC_SERVER", "security_params": null, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 1000000, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_async_unary_qps_unconstrained_1cq_insecure": '\'{"scenarios": [{"name": "cpp_protobuf_async_unary_qps_unconstrained_1cq_insecure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 13, "client_channels": 16, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 1000000, "rpc_type": "UNARY", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "ASYNC_SERVER", "security_params": null, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 1000000, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_insecure": '\'{"scenarios": [{"name": "cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_insecure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 10, "client_channels": 16, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 0, "rpc_type": "UNARY", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "SYNC_SERVER", "security_params": null, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 0, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_async_client_unary_1channel_64wide_128Breq_8MBresp_insecure": '\'{"scenarios": [{"name": "cpp_protobuf_async_client_unary_1channel_64wide_128Breq_8MBresp_insecure", "num_servers": 1, "num_clients": 1, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 1, "client_channels": 1, "async_client_threads": 1, "client_processes": 0, "threads_per_cq": 0, "rpc_type": "UNARY", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"simple_params": {"req_size": 128, "resp_size": 8388608}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "ASYNC_SERVER", "security_params": null, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 0, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}, {"name": "grpc.minimal_stack", "int_value": 1}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_async_unary_ping_pong_insecure_1MB": '\'{"scenarios": [{"name": "cpp_protobuf_async_unary_ping_pong_insecure_1MB", "num_servers": 1, "num_clients": 1, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 1, "client_channels": 1, "async_client_threads": 1, "client_processes": 0, "threads_per_cq": 0, "rpc_type": "UNARY", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"simple_params": {"req_size": 1048576, "resp_size": 1048576}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "ASYNC_SERVER", "security_params": null, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 0, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}, {"name": "grpc.minimal_stack", "int_value": 1}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_sync_unary_ping_pong_insecure": '\'{"scenarios": [{"name": "cpp_protobuf_sync_unary_ping_pong_insecure", "num_servers": 1, "num_clients": 1, "client_config": {"client_type": "SYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 1, "client_channels": 1, "async_client_threads": 1, "client_processes": 0, "threads_per_cq": 0, "rpc_type": "UNARY", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "SYNC_SERVER", "security_params": null, "async_server_threads": 1, "server_processes": 0, "threads_per_cq": 0, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}, {"name": "grpc.minimal_stack", "int_value": 1}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_sync_unary_qps_unconstrained_insecure": '\'{"scenarios": [{"name": "cpp_protobuf_sync_unary_qps_unconstrained_insecure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "SYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 1, "client_channels": 16, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 2, "rpc_type": "UNARY", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "SYNC_SERVER", "security_params": null, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 2, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_async_unary_ping_pong_insecure": '\'{"scenarios": [{"name": "cpp_protobuf_async_unary_ping_pong_insecure", "num_servers": 1, "num_clients": 1, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 1, "client_channels": 1, "async_client_threads": 1, "client_processes": 0, "threads_per_cq": 0, "rpc_type": "UNARY", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "ASYNC_SERVER", "security_params": null, "async_server_threads": 1, "server_processes": 0, "threads_per_cq": 0, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}, {"name": "grpc.minimal_stack", "int_value": 1}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_async_unary_qps_unconstrained_insecure": '\'{"scenarios": [{"name": "cpp_protobuf_async_unary_qps_unconstrained_insecure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 100, "client_channels": 16, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 2, "rpc_type": "UNARY", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "ASYNC_SERVER", "security_params": null, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 2, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_sync_streaming_ping_pong_insecure": '\'{"scenarios": [{"name": "cpp_protobuf_sync_streaming_ping_pong_insecure", "num_servers": 1, "num_clients": 1, "client_config": {"client_type": "SYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 1, "client_channels": 1, "async_client_threads": 1, "client_processes": 0, "threads_per_cq": 0, "rpc_type": "STREAMING", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "SYNC_SERVER", "security_params": null, "async_server_threads": 1, "server_processes": 0, "threads_per_cq": 0, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}, {"name": "grpc.minimal_stack", "int_value": 1}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_sync_streaming_qps_unconstrained_insecure": '\'{"scenarios": [{"name": "cpp_protobuf_sync_streaming_qps_unconstrained_insecure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "SYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 1, "client_channels": 16, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 2, "rpc_type": "STREAMING", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "SYNC_SERVER", "security_params": null, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 2, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_sync_streaming_qps_unconstrained_10mps_insecure": '\'{"scenarios": [{"name": "cpp_protobuf_sync_streaming_qps_unconstrained_10mps_insecure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "SYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 1, "client_channels": 16, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 0, "rpc_type": "STREAMING", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}, "messages_per_stream": 10}, "server_config": {"server_type": "SYNC_SERVER", "security_params": null, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 0, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_async_streaming_ping_pong_insecure": '\'{"scenarios": [{"name": "cpp_protobuf_async_streaming_ping_pong_insecure", "num_servers": 1, "num_clients": 1, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 1, "client_channels": 1, "async_client_threads": 1, "client_processes": 0, "threads_per_cq": 0, "rpc_type": "STREAMING", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "ASYNC_SERVER", "security_params": null, "async_server_threads": 1, "server_processes": 0, "threads_per_cq": 0, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}, {"name": "grpc.minimal_stack", "int_value": 1}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_async_streaming_qps_unconstrained_insecure": '\'{"scenarios": [{"name": "cpp_protobuf_async_streaming_qps_unconstrained_insecure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 100, "client_channels": 16, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 2, "rpc_type": "STREAMING", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "ASYNC_SERVER", "security_params": null, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 2, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_async_streaming_qps_unconstrained_10mps_insecure": '\'{"scenarios": [{"name": "cpp_protobuf_async_streaming_qps_unconstrained_10mps_insecure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 100, "client_channels": 16, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 0, "rpc_type": "STREAMING", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}, "messages_per_stream": 10}, "server_config": {"server_type": "ASYNC_SERVER", "security_params": null, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 0, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_sync_streaming_from_client_ping_pong_insecure": '\'{"scenarios": [{"name": "cpp_protobuf_sync_streaming_from_client_ping_pong_insecure", "num_servers": 1, "num_clients": 1, "client_config": {"client_type": "SYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 1, "client_channels": 1, "async_client_threads": 1, "client_processes": 0, "threads_per_cq": 0, "rpc_type": "STREAMING_FROM_CLIENT", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "SYNC_SERVER", "security_params": null, "async_server_threads": 1, "server_processes": 0, "threads_per_cq": 0, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}, {"name": "grpc.minimal_stack", "int_value": 1}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_sync_streaming_from_client_qps_unconstrained_insecure": '\'{"scenarios": [{"name": "cpp_protobuf_sync_streaming_from_client_qps_unconstrained_insecure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "SYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 1, "client_channels": 16, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 2, "rpc_type": "STREAMING_FROM_CLIENT", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "SYNC_SERVER", "security_params": null, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 2, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_async_streaming_from_client_ping_pong_insecure": '\'{"scenarios": [{"name": "cpp_protobuf_async_streaming_from_client_ping_pong_insecure", "num_servers": 1, "num_clients": 1, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 1, "client_channels": 1, "async_client_threads": 1, "client_processes": 0, "threads_per_cq": 0, "rpc_type": "STREAMING_FROM_CLIENT", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "ASYNC_SERVER", "security_params": null, "async_server_threads": 1, "server_processes": 0, "threads_per_cq": 0, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}, {"name": "grpc.minimal_stack", "int_value": 1}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_async_streaming_from_client_qps_unconstrained_insecure": '\'{"scenarios": [{"name": "cpp_protobuf_async_streaming_from_client_qps_unconstrained_insecure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 100, "client_channels": 16, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 2, "rpc_type": "STREAMING_FROM_CLIENT", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "ASYNC_SERVER", "security_params": null, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 2, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_sync_streaming_from_server_ping_pong_insecure": '\'{"scenarios": [{"name": "cpp_protobuf_sync_streaming_from_server_ping_pong_insecure", "num_servers": 1, "num_clients": 1, "client_config": {"client_type": "SYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 1, "client_channels": 1, "async_client_threads": 1, "client_processes": 0, "threads_per_cq": 0, "rpc_type": "STREAMING_FROM_SERVER", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "SYNC_SERVER", "security_params": null, "async_server_threads": 1, "server_processes": 0, "threads_per_cq": 0, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}, {"name": "grpc.minimal_stack", "int_value": 1}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_sync_streaming_from_server_qps_unconstrained_insecure": '\'{"scenarios": [{"name": "cpp_protobuf_sync_streaming_from_server_qps_unconstrained_insecure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "SYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 1, "client_channels": 4, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 2, "rpc_type": "STREAMING_FROM_SERVER", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "SYNC_SERVER", "security_params": null, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 2, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_async_streaming_from_server_ping_pong_insecure": '\'{"scenarios": [{"name": "cpp_protobuf_async_streaming_from_server_ping_pong_insecure", "num_servers": 1, "num_clients": 1, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 1, "client_channels": 1, "async_client_threads": 1, "client_processes": 0, "threads_per_cq": 0, "rpc_type": "STREAMING_FROM_SERVER", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "ASYNC_SERVER", "security_params": null, "async_server_threads": 1, "server_processes": 0, "threads_per_cq": 0, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}, {"name": "grpc.minimal_stack", "int_value": 1}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_async_streaming_from_server_qps_unconstrained_insecure": '\'{"scenarios": [{"name": "cpp_protobuf_async_streaming_from_server_qps_unconstrained_insecure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 100, "client_channels": 4, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 2, "rpc_type": "STREAMING_FROM_SERVER", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "ASYNC_SERVER", "security_params": null, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 2, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+}
index 3604605..76bff59 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python2.7
+#!/usr/bin/env python3
 
 # Copyright 2018 gRPC authors.
 #
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import json
+import os
+import sys
 
-import gen_build_yaml as gen
-
-COPYRIGHT = """
-# Copyright 2021 The gRPC Authors
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""
-
-
-def generate_args():
-    all_scenario_set = gen.generate_yaml()
-    all_scenario_set = all_scenario_set['tests']
-    qps_json_driver_scenario_set = \
-        [item for item in all_scenario_set if item['name'] == 'qps_json_driver']
-    qps_json_driver_arg_set = \
-        [item['args'][2] for item in qps_json_driver_scenario_set \
-        if 'args' in item and len(item['args']) > 2]
-    deserialized_scenarios = [json.loads(item)['scenarios'][0] \
-                            for item in qps_json_driver_arg_set]
-    all_scenarios = {scenario['name'].encode('ascii', 'ignore'): \
-                   '\'{\'scenarios\' : [' + json.dumps(scenario) + ']}\'' \
-                   for scenario in deserialized_scenarios}
-
-    serialized_scenarios_str = str(all_scenarios).encode('ascii', 'ignore')
-    with open('qps_json_driver_scenarios.bzl', 'w') as f:
-        f.write(COPYRIGHT)
-        f.write('"""Scenarios of qps driver."""\n\n')
-        f.write('QPS_JSON_DRIVER_SCENARIOS = ' + serialized_scenarios_str +
-                '\n')
+script_dir = os.path.dirname(os.path.abspath(__file__))
+sys.path.append(script_dir)
 
+import scenario_generator_helper as gen
 
-generate_args()
+gen.generate_scenarios_bzl(
+    gen.generate_qps_json_driver_scenarios(),
+    os.path.join(script_dir, 'qps_json_driver_scenarios.bzl'),
+    'QPS_JSON_DRIVER_SCENARIOS')
index 43401be..fe3a637 100644 (file)
 # 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.
-"""Scenarios of qps driver."""
+"""AUTOGENERATED: configuration of benchmark scenarios to be run as bazel test"""
 
-QPS_JSON_DRIVER_SCENARIOS = {"cpp_protobuf_sync_streaming_qps_unconstrained_insecure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_sync_streaming_qps_unconstrained_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "SYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_server_threads": 0, "threads_per_cq": 3, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 16, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "SYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 3, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_sync_streaming_qps_unconstrained_1mps_insecure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_sync_streaming_qps_unconstrained_1mps_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "SYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_server_threads": 0, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 16, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "SYNC_CLIENT", "messages_per_stream": 1, "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_async_unary_ping_pong_insecure_1MB": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_unary_ping_pong_insecure_1MB", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_server_threads": 0, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 1, "outstanding_rpcs_per_channel": 1, "rpc_type": "UNARY", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 1048576, "req_size": 1048576}}, "client_channels": 1, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 1}]}\'', "cpp_protobuf_sync_streaming_qps_unconstrained_10mps_insecure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_sync_streaming_qps_unconstrained_10mps_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "SYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_server_threads": 0, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 16, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "SYNC_CLIENT", "messages_per_stream": 10, "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_async_unary_qps_unconstrained_2waysharedcq_insecure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_unary_qps_unconstrained_2waysharedcq_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_server_threads": 0, "threads_per_cq": 2, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 100, "rpc_type": "UNARY", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 2, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_async_unary_qps_unconstrained_1cq_insecure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_unary_qps_unconstrained_1cq_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_server_threads": 0, "threads_per_cq": 1000000, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 13, "rpc_type": "UNARY", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 1000000, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_async_streaming_qps_unconstrained_insecure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_streaming_qps_unconstrained_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_server_threads": 0, "threads_per_cq": 3, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 100, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 3, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_async_streaming_qps_unconstrained_2waysharedcq_insecure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_streaming_qps_unconstrained_2waysharedcq_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_server_threads": 0, "threads_per_cq": 2, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 100, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 2, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_generic_async_streaming_qps_unconstrained_1cq_insecure": '\'{\'scenarios\' : [{"name": "cpp_generic_async_streaming_qps_unconstrained_1cq_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"async_server_threads": 0, "security_params": null, "server_type": "ASYNC_GENERIC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "payload_config": {"bytebuf_params": {"resp_size": 0, "req_size": 0}}, "threads_per_cq": 1000000, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 13, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"bytebuf_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 1000000, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_async_streaming_qps_unconstrained_10mps_insecure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_streaming_qps_unconstrained_10mps_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_server_threads": 0, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 100, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "messages_per_stream": 10, "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_generic_async_streaming_qps_unconstrained_64KBmsg_insecure": '\'{\'scenarios\' : [{"name": "cpp_generic_async_streaming_qps_unconstrained_64KBmsg_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"async_server_threads": 0, "security_params": null, "server_type": "ASYNC_GENERIC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "payload_config": {"bytebuf_params": {"resp_size": 65536, "req_size": 65536}}, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 100, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"bytebuf_params": {"resp_size": 65536, "req_size": 65536}}, "client_channels": 64, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_generic_async_streaming_qps_unconstrained_insecure": '\'{\'scenarios\' : [{"name": "cpp_generic_async_streaming_qps_unconstrained_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"async_server_threads": 0, "security_params": null, "server_type": "ASYNC_GENERIC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "payload_config": {"bytebuf_params": {"resp_size": 0, "req_size": 0}}, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 100, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"bytebuf_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_async_streaming_qps_unconstrained_1cq_insecure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_streaming_qps_unconstrained_1cq_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_server_threads": 0, "threads_per_cq": 1000000, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 13, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 1000000, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_async_streaming_from_server_qps_unconstrained_insecure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_streaming_from_server_qps_unconstrained_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_server_threads": 0, "threads_per_cq": 3, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 100, "rpc_type": "STREAMING_FROM_SERVER", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 3, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_async_streaming_from_client_1channel_1MB": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_streaming_from_client_1channel_1MB", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_server_threads": 0, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 1, "rpc_type": "STREAMING_FROM_CLIENT", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 1048576, "req_size": 1048576}}, "client_channels": 1, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 1}]}\'', "cpp_protobuf_async_unary_1channel_100rpcs_1MB": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_unary_1channel_100rpcs_1MB", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_server_threads": 0, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 100, "rpc_type": "UNARY", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 1048576, "req_size": 1048576}}, "client_channels": 1, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 1}]}\'', "cpp_generic_async_streaming_qps_1channel_1MBmsg_insecure": '\'{\'scenarios\' : [{"name": "cpp_generic_async_streaming_qps_1channel_1MBmsg_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"async_server_threads": 0, "security_params": null, "server_type": "ASYNC_GENERIC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "payload_config": {"bytebuf_params": {"resp_size": 1048576, "req_size": 1048576}}, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 100, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"bytebuf_params": {"resp_size": 1048576, "req_size": 1048576}}, "client_channels": 1, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_generic_async_streaming_qps_unconstrained_1mps_insecure": '\'{\'scenarios\' : [{"name": "cpp_generic_async_streaming_qps_unconstrained_1mps_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"async_server_threads": 0, "security_params": null, "server_type": "ASYNC_GENERIC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "payload_config": {"bytebuf_params": {"resp_size": 0, "req_size": 0}}, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 100, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "messages_per_stream": 1, "payload_config": {"bytebuf_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_insecure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "SYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_server_threads": 0, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 100, "rpc_type": "UNARY", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_async_client_unary_1channel_64wide_128Breq_8MBresp_insecure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_client_unary_1channel_64wide_128Breq_8MBresp_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_server_threads": 0, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 1, "outstanding_rpcs_per_channel": 1, "rpc_type": "UNARY", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 8388608, "req_size": 128}}, "client_channels": 1, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 1}]}\'', "cpp_protobuf_sync_streaming_from_client_qps_unconstrained_insecure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_sync_streaming_from_client_qps_unconstrained_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "SYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_server_threads": 0, "threads_per_cq": 3, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 16, "rpc_type": "STREAMING_FROM_CLIENT", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "SYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 3, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_insecure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "SYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_server_threads": 0, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 100, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_async_streaming_from_client_qps_unconstrained_insecure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_streaming_from_client_qps_unconstrained_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_server_threads": 0, "threads_per_cq": 3, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 100, "rpc_type": "STREAMING_FROM_CLIENT", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 3, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_generic_async_streaming_qps_unconstrained_2waysharedcq_insecure": '\'{\'scenarios\' : [{"name": "cpp_generic_async_streaming_qps_unconstrained_2waysharedcq_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"async_server_threads": 0, "security_params": null, "server_type": "ASYNC_GENERIC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "payload_config": {"bytebuf_params": {"resp_size": 0, "req_size": 0}}, "threads_per_cq": 2, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 100, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"bytebuf_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 2, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_sync_unary_qps_unconstrained_insecure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_sync_unary_qps_unconstrained_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "SYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_server_threads": 0, "threads_per_cq": 3, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 16, "rpc_type": "UNARY", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "SYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 3, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_sync_streaming_from_server_qps_unconstrained_insecure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_sync_streaming_from_server_qps_unconstrained_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "SYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_server_threads": 0, "threads_per_cq": 3, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 16, "rpc_type": "STREAMING_FROM_SERVER", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "SYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 3, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_protobuf_async_unary_qps_unconstrained_insecure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_unary_qps_unconstrained_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_server_threads": 0, "threads_per_cq": 3, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 100, "rpc_type": "UNARY", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 3, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_generic_async_streaming_qps_unconstrained_10mps_insecure": '\'{\'scenarios\' : [{"name": "cpp_generic_async_streaming_qps_unconstrained_10mps_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"async_server_threads": 0, "security_params": null, "server_type": "ASYNC_GENERIC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "payload_config": {"bytebuf_params": {"resp_size": 0, "req_size": 0}}, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 100, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "messages_per_stream": 10, "payload_config": {"bytebuf_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 0}]}\'', "cpp_generic_async_streaming_ping_pong_insecure": '\'{\'scenarios\' : [{"name": "cpp_generic_async_streaming_ping_pong_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"async_server_threads": 1, "security_params": null, "server_type": "ASYNC_GENERIC_SERVER", "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}], "payload_config": {"bytebuf_params": {"resp_size": 0, "req_size": 0}}, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "latency", "name": "grpc.optimization_target"}], "async_client_threads": 1, "outstanding_rpcs_per_channel": 1, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "payload_config": {"bytebuf_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 1, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 1}]}\'', "cpp_protobuf_async_streaming_qps_unconstrained_1mps_insecure": '\'{\'scenarios\' : [{"name": "cpp_protobuf_async_streaming_qps_unconstrained_1mps_insecure", "warmup_seconds": 0, "benchmark_seconds": 1, "num_servers": 1, "server_config": {"security_params": null, "server_type": "ASYNC_SERVER", "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_server_threads": 0, "threads_per_cq": 0, "server_processes": 0}, "client_config": {"security_params": null, "channel_args": [{"str_value": "throughput", "name": "grpc.optimization_target"}, {"int_value": 1, "name": "grpc.minimal_stack"}], "async_client_threads": 0, "outstanding_rpcs_per_channel": 100, "rpc_type": "STREAMING", "load_params": {"closed_loop": {}}, "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "client_type": "ASYNC_CLIENT", "messages_per_stream": 1, "payload_config": {"simple_params": {"resp_size": 0, "req_size": 0}}, "client_channels": 64, "threads_per_cq": 0, "client_processes": 0}, "num_clients": 0}]}\''}
+QPS_JSON_DRIVER_SCENARIOS = {
+    "cpp_generic_async_streaming_ping_pong_insecure": '\'{"scenarios": [{"name": "cpp_generic_async_streaming_ping_pong_insecure", "num_servers": 1, "num_clients": 1, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 1, "client_channels": 1, "async_client_threads": 1, "client_processes": 0, "threads_per_cq": 0, "rpc_type": "STREAMING", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}], "payload_config": {"bytebuf_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "ASYNC_GENERIC_SERVER", "security_params": null, "async_server_threads": 1, "server_processes": 0, "threads_per_cq": 0, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}], "payload_config": {"bytebuf_params": {"req_size": 0, "resp_size": 0}}}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_generic_async_streaming_qps_unconstrained_insecure": '\'{"scenarios": [{"name": "cpp_generic_async_streaming_qps_unconstrained_insecure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 100, "client_channels": 16, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 2, "rpc_type": "STREAMING", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"bytebuf_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "ASYNC_GENERIC_SERVER", "security_params": null, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 2, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"bytebuf_params": {"req_size": 0, "resp_size": 0}}}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_generic_async_streaming_qps_unconstrained_10mps_insecure": '\'{"scenarios": [{"name": "cpp_generic_async_streaming_qps_unconstrained_10mps_insecure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 100, "client_channels": 16, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 0, "rpc_type": "STREAMING", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"bytebuf_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}, "messages_per_stream": 10}, "server_config": {"server_type": "ASYNC_GENERIC_SERVER", "security_params": null, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 0, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"bytebuf_params": {"req_size": 0, "resp_size": 0}}}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_generic_async_streaming_qps_1channel_1MBmsg_insecure": '\'{"scenarios": [{"name": "cpp_generic_async_streaming_qps_1channel_1MBmsg_insecure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 100, "client_channels": 1, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 0, "rpc_type": "STREAMING", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"bytebuf_params": {"req_size": 1048576, "resp_size": 1048576}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "ASYNC_GENERIC_SERVER", "security_params": null, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 0, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"bytebuf_params": {"req_size": 1048576, "resp_size": 1048576}}}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_generic_async_streaming_qps_unconstrained_64KBmsg_insecure": '\'{"scenarios": [{"name": "cpp_generic_async_streaming_qps_unconstrained_64KBmsg_insecure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 100, "client_channels": 16, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 0, "rpc_type": "STREAMING", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"bytebuf_params": {"req_size": 65536, "resp_size": 65536}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "ASYNC_GENERIC_SERVER", "security_params": null, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 0, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"bytebuf_params": {"req_size": 65536, "resp_size": 65536}}}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_async_streaming_qps_unconstrained_1cq_insecure": '\'{"scenarios": [{"name": "cpp_protobuf_async_streaming_qps_unconstrained_1cq_insecure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 13, "client_channels": 16, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 1000000, "rpc_type": "STREAMING", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "ASYNC_SERVER", "security_params": null, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 1000000, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_async_unary_qps_unconstrained_1cq_insecure": '\'{"scenarios": [{"name": "cpp_protobuf_async_unary_qps_unconstrained_1cq_insecure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 13, "client_channels": 16, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 1000000, "rpc_type": "UNARY", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "ASYNC_SERVER", "security_params": null, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 1000000, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_insecure": '\'{"scenarios": [{"name": "cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_insecure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 10, "client_channels": 16, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 0, "rpc_type": "UNARY", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "SYNC_SERVER", "security_params": null, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 0, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_async_client_unary_1channel_64wide_128Breq_8MBresp_insecure": '\'{"scenarios": [{"name": "cpp_protobuf_async_client_unary_1channel_64wide_128Breq_8MBresp_insecure", "num_servers": 1, "num_clients": 1, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 1, "client_channels": 1, "async_client_threads": 1, "client_processes": 0, "threads_per_cq": 0, "rpc_type": "UNARY", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"simple_params": {"req_size": 128, "resp_size": 8388608}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "ASYNC_SERVER", "security_params": null, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 0, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}, {"name": "grpc.minimal_stack", "int_value": 1}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_async_unary_ping_pong_insecure_1MB": '\'{"scenarios": [{"name": "cpp_protobuf_async_unary_ping_pong_insecure_1MB", "num_servers": 1, "num_clients": 1, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 1, "client_channels": 1, "async_client_threads": 1, "client_processes": 0, "threads_per_cq": 0, "rpc_type": "UNARY", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"simple_params": {"req_size": 1048576, "resp_size": 1048576}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "ASYNC_SERVER", "security_params": null, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 0, "channel_args": [{"name": "grpc.optimization_target", "str_value": "latency"}, {"name": "grpc.minimal_stack", "int_value": 1}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_sync_unary_qps_unconstrained_insecure": '\'{"scenarios": [{"name": "cpp_protobuf_sync_unary_qps_unconstrained_insecure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "SYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 1, "client_channels": 16, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 2, "rpc_type": "UNARY", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "SYNC_SERVER", "security_params": null, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 2, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_async_unary_qps_unconstrained_insecure": '\'{"scenarios": [{"name": "cpp_protobuf_async_unary_qps_unconstrained_insecure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 100, "client_channels": 16, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 2, "rpc_type": "UNARY", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "ASYNC_SERVER", "security_params": null, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 2, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_sync_streaming_qps_unconstrained_insecure": '\'{"scenarios": [{"name": "cpp_protobuf_sync_streaming_qps_unconstrained_insecure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "SYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 1, "client_channels": 16, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 2, "rpc_type": "STREAMING", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "SYNC_SERVER", "security_params": null, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 2, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_sync_streaming_qps_unconstrained_10mps_insecure": '\'{"scenarios": [{"name": "cpp_protobuf_sync_streaming_qps_unconstrained_10mps_insecure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "SYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 1, "client_channels": 16, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 0, "rpc_type": "STREAMING", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}, "messages_per_stream": 10}, "server_config": {"server_type": "SYNC_SERVER", "security_params": null, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 0, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_async_streaming_qps_unconstrained_insecure": '\'{"scenarios": [{"name": "cpp_protobuf_async_streaming_qps_unconstrained_insecure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 100, "client_channels": 16, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 2, "rpc_type": "STREAMING", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "ASYNC_SERVER", "security_params": null, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 2, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_async_streaming_qps_unconstrained_10mps_insecure": '\'{"scenarios": [{"name": "cpp_protobuf_async_streaming_qps_unconstrained_10mps_insecure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 100, "client_channels": 16, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 0, "rpc_type": "STREAMING", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}, "messages_per_stream": 10}, "server_config": {"server_type": "ASYNC_SERVER", "security_params": null, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 0, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_sync_streaming_from_client_qps_unconstrained_insecure": '\'{"scenarios": [{"name": "cpp_protobuf_sync_streaming_from_client_qps_unconstrained_insecure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "SYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 1, "client_channels": 16, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 2, "rpc_type": "STREAMING_FROM_CLIENT", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "SYNC_SERVER", "security_params": null, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 2, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_async_streaming_from_client_qps_unconstrained_insecure": '\'{"scenarios": [{"name": "cpp_protobuf_async_streaming_from_client_qps_unconstrained_insecure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 100, "client_channels": 16, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 2, "rpc_type": "STREAMING_FROM_CLIENT", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "ASYNC_SERVER", "security_params": null, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 2, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_sync_streaming_from_server_qps_unconstrained_insecure": '\'{"scenarios": [{"name": "cpp_protobuf_sync_streaming_from_server_qps_unconstrained_insecure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "SYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 1, "client_channels": 4, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 2, "rpc_type": "STREAMING_FROM_SERVER", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "SYNC_SERVER", "security_params": null, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 2, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+    "cpp_protobuf_async_streaming_from_server_qps_unconstrained_insecure": '\'{"scenarios": [{"name": "cpp_protobuf_async_streaming_from_server_qps_unconstrained_insecure", "num_servers": 1, "num_clients": 0, "client_config": {"client_type": "ASYNC_CLIENT", "security_params": null, "outstanding_rpcs_per_channel": 100, "client_channels": 4, "async_client_threads": 0, "client_processes": 0, "threads_per_cq": 2, "rpc_type": "STREAMING_FROM_SERVER", "histogram_params": {"resolution": 0.01, "max_possible": 60000000000.0}, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}], "payload_config": {"simple_params": {"req_size": 0, "resp_size": 0}}, "load_params": {"closed_loop": {}}}, "server_config": {"server_type": "ASYNC_SERVER", "security_params": null, "async_server_threads": 0, "server_processes": 0, "threads_per_cq": 2, "channel_args": [{"name": "grpc.optimization_target", "str_value": "throughput"}, {"name": "grpc.minimal_stack", "int_value": 1}]}, "warmup_seconds": 0, "benchmark_seconds": 1}]}\'',
+}
index 19ff02b..38e70a8 100644 (file)
 namespace grpc {
 namespace testing {
 
-static const int WARMUP = 5;
-static const int BENCHMARK = 5;
+static const int WARMUP = 1;
+static const int BENCHMARK = 3;
 
 static void RunQPS() {
   gpr_log(GPR_INFO, "Running QPS test, open-loop");
 
   ClientConfig client_config;
   client_config.set_client_type(ASYNC_CLIENT);
-  client_config.set_outstanding_rpcs_per_channel(1000);
+  client_config.set_outstanding_rpcs_per_channel(100);
   client_config.set_client_channels(8);
   client_config.set_async_client_threads(8);
   client_config.set_rpc_type(STREAMING);
diff --git a/test/cpp/qps/scenario_generator_helper.py b/test/cpp/qps/scenario_generator_helper.py
new file mode 100755 (executable)
index 0000000..14666c7
--- /dev/null
@@ -0,0 +1,112 @@
+#!/usr/bin/env python3
+
+# Copyright 2021 The gRPC Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from __future__ import print_function
+
+import json
+import os
+import sys
+
+import yaml
+
+run_tests_root = os.path.abspath(
+    os.path.join(os.path.dirname(sys.argv[0]), '../../../tools/run_tests'))
+sys.path.append(run_tests_root)
+
+import performance.scenario_config as scenario_config
+
+_COPYRIGHT = """# Copyright 2021 The gRPC Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+
+
+def _mutate_scenario(scenario_json):
+    """Modifies vanilla benchmark scenario config to make it more suitable for running as a unit test."""
+    # tweak parameters to get fast test times
+    scenario_json = dict(scenario_json)
+    scenario_json['warmup_seconds'] = 0
+    scenario_json['benchmark_seconds'] = 1
+    outstanding_rpcs_divisor = 1
+    if scenario_json['client_config'][
+            'client_type'] == 'SYNC_CLIENT' or scenario_json['server_config'][
+                'server_type'] == 'SYNC_SERVER':
+        # reduce the number of threads needed for scenarios that use synchronous API
+        outstanding_rpcs_divisor = 10
+    scenario_json['client_config']['outstanding_rpcs_per_channel'] = max(
+        1, scenario_json['client_config']['outstanding_rpcs_per_channel'] //
+        outstanding_rpcs_divisor)
+    # Some scenarios use high channel count since when actually
+    # benchmarking, we want to saturate the machine that runs the benchmark.
+    # For unit test, this is an overkill.
+    max_client_channels = 16
+    if scenario_json['client_config']['rpc_type'] == 'STREAMING_FROM_SERVER':
+        # streaming from server scenarios tend to have trouble shutting down
+        # quickly if there are too many channels.
+        max_client_channels = 4
+
+    scenario_json['client_config']['client_channels'] = min(
+        max_client_channels, scenario_json['client_config']['client_channels'])
+
+    return scenario_config.remove_nonproto_fields(scenario_json)
+
+
+def generate_json_run_localhost_scenarios():
+    return [
+        _mutate_scenario(scenario_json)
+        for scenario_json in scenario_config.CXXLanguage().scenarios()
+        if 'scalable' in scenario_json.get('CATEGORIES', [])
+    ]
+
+
+def generate_qps_json_driver_scenarios():
+    return [
+        _mutate_scenario(scenario_json)
+        for scenario_json in scenario_config.CXXLanguage().scenarios()
+        if 'inproc' in scenario_json.get('CATEGORIES', [])
+    ]
+
+
+def generate_scenarios_bzl(json_scenarios, bzl_filename, bzl_variablename):
+    """Generate .bzl file that defines a variable with JSON scenario configs."""
+    all_scenarios = []
+    for scenario in json_scenarios:
+        scenario_name = scenario['name']
+        # argument will be passed as "--scenarios_json" to the test binary
+        # the string needs to be quoted in \' to ensure it gets passed as a single argument in shell
+        scenarios_json_arg_str = '\\\'%s\\\'' % json.dumps(
+            {'scenarios': [scenario]})
+        all_scenarios.append((scenario_name, scenarios_json_arg_str))
+
+    with open(bzl_filename, 'w') as f:
+        f.write(_COPYRIGHT)
+        f.write(
+            '"""AUTOGENERATED: configuration of benchmark scenarios to be run as bazel test"""\n\n'
+        )
+        f.write('%s = {\n' % bzl_variablename)
+        for scenario in all_scenarios:
+            f.write("    \"%s\": '%s',\n" % (scenario[0], scenario[1]))
+        f.write('}\n')
index d4c283c..16cffc9 100644 (file)
@@ -31,8 +31,8 @@
 namespace grpc {
 namespace testing {
 
-static const int WARMUP = 5;
-static const int BENCHMARK = 5;
+static const int WARMUP = 1;
+static const int BENCHMARK = 3;
 
 static void RunSynchronousUnaryPingPong() {
   gpr_log(GPR_INFO, "Running Synchronous Unary Ping Pong");
index 1314ab5..28c7cc7 100644 (file)
@@ -55,7 +55,7 @@ static void RunServer() {
 
   while (!got_sigint && !worker.Done()) {
     gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
-                                 gpr_time_from_seconds(5, GPR_TIMESPAN)));
+                                 gpr_time_from_millis(500, GPR_TIMESPAN)));
   }
 }
 
index 549c859..225fa02 100644 (file)
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 load("//bazel:grpc_build_system.bzl", "grpc_cc_binary", "grpc_cc_library", "grpc_cc_test", "grpc_package")
 
@@ -82,9 +82,17 @@ grpc_cc_test(
 grpc_cc_test(
     name = "authorization_policy_provider_test",
     srcs = ["authorization_policy_provider_test.cc"],
+    data = [
+        "//test/core/security/authorization/test_policies:invalid_policy.json",
+        "//test/core/security/authorization/test_policies:valid_policy_1.json",
+        "//test/core/security/authorization/test_policies:valid_policy_2.json",
+    ],
     external_deps = [
         "gtest",
     ],
+    # Test seems to be failing on iOS, but shouldn't be needed there anyway,
+    # since we don't support servers on iOS.
+    tags = ["no_test_ios"],
     deps = [
         "//:gpr",
         "//:grpc",
index 9b84af8..b642646 100644 (file)
 #include <grpcpp/security/authorization_policy_provider.h>
 
 #include "test/core/util/test_config.h"
+#include "test/core/util/tls_utils.h"
+
+#define VALID_POLICY_PATH_1 \
+  "test/core/security/authorization/test_policies/valid_policy_1.json"
+#define VALID_POLICY_PATH_2 \
+  "test/core/security/authorization/test_policies/valid_policy_2.json"
+#define INVALID_POLICY_PATH \
+  "test/core/security/authorization/test_policies/invalid_policy.json"
 
 namespace grpc {
 
 TEST(AuthorizationPolicyProviderTest, StaticDataCreateReturnsProvider) {
-  const char* authz_policy =
-      "{"
-      "  \"name\": \"authz\","
-      "  \"allow_rules\": ["
-      "    {"
-      "      \"name\": \"allow_policy\""
-      "    }"
-      "  ]"
-      "}";
   grpc::Status status;
   auto provider = experimental::StaticDataAuthorizationPolicyProvider::Create(
-      authz_policy, &status);
+      grpc_core::testing::GetFileContents(VALID_POLICY_PATH_1), &status);
   ASSERT_NE(provider, nullptr);
   EXPECT_NE(provider->c_provider(), nullptr);
   EXPECT_TRUE(status.ok());
@@ -40,10 +39,32 @@ TEST(AuthorizationPolicyProviderTest, StaticDataCreateReturnsProvider) {
 }
 
 TEST(AuthorizationPolicyProviderTest, StaticDataCreateReturnsErrorStatus) {
-  const char* authz_policy = "{}";
   grpc::Status status;
   auto provider = experimental::StaticDataAuthorizationPolicyProvider::Create(
-      authz_policy, &status);
+      grpc_core::testing::GetFileContents(INVALID_POLICY_PATH), &status);
+  ASSERT_EQ(provider, nullptr);
+  EXPECT_EQ(status.error_code(), grpc::StatusCode::INVALID_ARGUMENT);
+  EXPECT_EQ(status.error_message(), "\"name\" field is not present.");
+}
+
+TEST(AuthorizationPolicyProviderTest, FileWatcherCreateReturnsProvider) {
+  auto tmp_authz_policy = absl::make_unique<grpc_core::testing::TmpFile>(
+      grpc_core::testing::GetFileContents(VALID_POLICY_PATH_1));
+  grpc::Status status;
+  auto provider = experimental::FileWatcherAuthorizationPolicyProvider::Create(
+      tmp_authz_policy->name(), /*refresh_interval_sec=*/1, &status);
+  ASSERT_NE(provider, nullptr);
+  EXPECT_NE(provider->c_provider(), nullptr);
+  EXPECT_TRUE(status.ok());
+  EXPECT_TRUE(status.error_message().empty());
+}
+
+TEST(AuthorizationPolicyProviderTest, FileWatcherCreateReturnsErrorStatus) {
+  auto tmp_authz_policy = absl::make_unique<grpc_core::testing::TmpFile>(
+      grpc_core::testing::GetFileContents(INVALID_POLICY_PATH));
+  grpc::Status status;
+  auto provider = experimental::FileWatcherAuthorizationPolicyProvider::Create(
+      tmp_authz_policy->name(), /*refresh_interval_sec=*/1, &status);
   ASSERT_EQ(provider, nullptr);
   EXPECT_EQ(status.error_code(), grpc::StatusCode::INVALID_ARGUMENT);
   EXPECT_EQ(status.error_message(), "\"name\" field is not present.");
index 846475a..272b116 100644 (file)
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 load("//bazel:grpc_build_system.bzl", "grpc_cc_binary", "grpc_cc_library", "grpc_cc_test", "grpc_package")
 
index 9d84b04..480935f 100644 (file)
@@ -176,7 +176,7 @@ class LbFeedbackTest : public LoadReporterTest {
     ASSERT_THAT(static_cast<double>(lb_feedback.errors_per_second()),
                 DoubleNear(expected_eps, expected_eps * 0.3));
     gpr_log(GPR_INFO,
-            "Verified LB feedback matches the samples of index [%lu, %lu).",
+            "Verified LB feedback matches the samples of index [%zu, %zu).",
             start, start + count);
   }
 
index 13d816c..92b3159 100644 (file)
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 load("//bazel:grpc_build_system.bzl", "grpc_cc_binary", "grpc_cc_library", "grpc_cc_test", "grpc_package")
 
index 2b1ef7a..2f8ca7c 100644 (file)
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 load("//bazel:grpc_build_system.bzl", "grpc_cc_binary", "grpc_cc_library", "grpc_cc_test", "grpc_package")
 
index f2f46da..897dd08 100644 (file)
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 load("//bazel:grpc_build_system.bzl", "grpc_cc_binary", "grpc_cc_library", "grpc_cc_test", "grpc_package")
 
index f1dc741..9f8f1c9 100644 (file)
@@ -35,19 +35,15 @@ namespace {
 void* tag(intptr_t t) { return reinterpret_cast<void*>(t); }
 }  // namespace
 
-Status CliCall::Call(const std::shared_ptr<grpc::Channel>& channel,
-                     const std::string& method, const std::string& request,
-                     std::string* response,
-                     const OutgoingMetadataContainer& metadata,
+Status CliCall::Call(const std::string& request, std::string* response,
                      IncomingMetadataContainer* server_initial_metadata,
                      IncomingMetadataContainer* server_trailing_metadata) {
-  CliCall call(channel, method, metadata);
-  call.Write(request);
-  call.WritesDone();
-  if (!call.Read(response, server_initial_metadata)) {
+  Write(request);
+  WritesDone();
+  if (!Read(response, server_initial_metadata)) {
     fprintf(stderr, "Failed to read response.\n");
   }
-  return call.Finish(server_trailing_metadata);
+  return Finish(server_trailing_metadata);
 }
 
 CliCall::CliCall(const std::shared_ptr<grpc::Channel>& channel,
index f5454a1..d213073 100644 (file)
@@ -56,12 +56,9 @@ class CliCall final {
   ~CliCall();
 
   // Perform an unary generic RPC.
-  static Status Call(const std::shared_ptr<grpc::Channel>& channel,
-                     const std::string& method, const std::string& request,
-                     std::string* response,
-                     const OutgoingMetadataContainer& metadata,
-                     IncomingMetadataContainer* server_initial_metadata,
-                     IncomingMetadataContainer* server_trailing_metadata);
+  Status Call(const std::string& request, std::string* response,
+              IncomingMetadataContainer* server_initial_metadata,
+              IncomingMetadataContainer* server_trailing_metadata);
 
   // Send a generic request message in a synchronous manner. NOT thread-safe.
   void Write(const std::string& request);
index 9f8288a..c57defb 100644 (file)
@@ -109,9 +109,9 @@ TEST_F(CliCallTest, SimpleRpc) {
   std::multimap<grpc::string_ref, grpc::string_ref> server_initial_metadata,
       server_trailing_metadata;
   client_metadata.insert(std::pair<std::string, std::string>("key1", "val1"));
-  Status s2 = CliCall::Call(channel_, kMethod, request_bin, &response_bin,
-                            client_metadata, &server_initial_metadata,
-                            &server_trailing_metadata);
+  CliCall call(channel_, kMethod, client_metadata);
+  Status s2 = call.Call(request_bin, &response_bin, &server_initial_metadata,
+                        &server_trailing_metadata);
   EXPECT_TRUE(s2.ok());
 
   EXPECT_EQ(expected_response_bin, response_bin);
diff --git a/test/distrib/bazel/run_bazel_distrib_test.sh b/test/distrib/bazel/run_bazel_distrib_test.sh
new file mode 100755 (executable)
index 0000000..89babec
--- /dev/null
@@ -0,0 +1,36 @@
+#!/usr/bin/env bash
+# Copyright 2021 The gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+set -ex
+
+cd "$(dirname "$0")"
+
+# TODO(jtattermusch): make build work with bazel 2.2.0 and bazel 1.2.1 if that's reasonably simple.
+SUPPORTED_VERSIONS=(
+  "3.7.2"
+  "4.0.0"
+)
+
+FAILED_VERSIONS=""
+for VERSION in "${SUPPORTED_VERSIONS[@]}"; do
+    echo "Running bazel distribtest with bazel version ${VERSION}"
+    ./test_single_bazel_version.sh "${VERSION}" || FAILED_VERSIONS="${FAILED_VERSIONS}${VERSION} "
+done
+
+if [ "$FAILED_VERSIONS" != "" ]
+then
+  echo "Bazel distribtest failed: Failed to build with bazel versions ${FAILED_VERSIONS}"
+  exit 1
+fi
diff --git a/test/distrib/bazel/test_latest_bazel_version.sh b/test/distrib/bazel/test_latest_bazel_version.sh
new file mode 100755 (executable)
index 0000000..fb02a86
--- /dev/null
@@ -0,0 +1,27 @@
+#!/usr/bin/env bash
+# Copyright 2021 The gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+set -ex
+
+cd "$(dirname "$0")"
+
+GITHUB_URL="https://github.com"
+REPO="bazelbuild/bazel"
+
+VERSION=$(curl -Ls "${GITHUB_URL}/${REPO}/releases/latest" | \
+          grep "href=.*\.tar.gz" | \
+          grep -o "[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*")
+
+./test_single_bazel_version.sh "$VERSION"
diff --git a/test/distrib/bazel/test_single_bazel_version.sh b/test/distrib/bazel/test_single_bazel_version.sh
new file mode 100755 (executable)
index 0000000..ef338c9
--- /dev/null
@@ -0,0 +1,47 @@
+#!/usr/bin/env bash
+# Copyright 2021 The gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+set -ex
+
+if [ "$#" != "1" ] ; then
+    echo "Must supply bazel version to be tested." >/dev/stderr
+    exit 1
+fi
+
+VERSION="$1"
+
+cd "$(dirname "$0")"/../../..
+
+EXCLUDED_TARGETS=(
+  # iOS platform fails the analysis phase since there is no toolchain available
+  # for it.
+  "-//src/objective-c/..."
+  "-//third_party/objective_c/..."
+
+  # This could be a legitmate failure due to bitrot.
+  "-//src/proto/grpc/testing:test_gen_proto"
+
+  # This appears to be a legitimately broken BUILD file. There's a reference to
+  # a non-existent "link_dynamic_library.sh".
+  "-//third_party/toolchains/bazel_0.26.0_rbe_windows:all"
+
+  # TODO(jtattermusch): add back once fixed
+  "-//examples/android/binder/..."
+)
+
+export OVERRIDE_BAZEL_VERSION="$VERSION"
+# when running under bazel docker image, the workspace is read only.
+export OVERRIDE_BAZEL_WRAPPER_DOWNLOAD_DIR=/tmp
+bazel build -- //... "${EXCLUDED_TARGETS[@]}"
index 272d239..0ac0451 100644 (file)
@@ -12,4 +12,5 @@ exports_files([
     "futures.BUILD",
     "libuv.BUILD",
     "protobuf.patch",
+    "rules_python.patch",
 ])
index d0dfe12..dd96955 100644 (file)
@@ -54,6 +54,7 @@ static bool posix_source_addr_factory_get_source_addr(
     address_sorting_source_addr_factory* factory,
     const address_sorting_address* dest_addr,
     address_sorting_address* source_addr) {
+  (void)factory;
   bool source_addr_exists = false;
   // Android sets SOCK_CLOEXEC. Don't set this here for portability.
   int s = socket(((struct sockaddr*)dest_addr)->sa_family, SOCK_DGRAM, 0);
diff --git a/third_party/libprotobuf_mutator.BUILD b/third_party/libprotobuf_mutator.BUILD
new file mode 100644 (file)
index 0000000..107993e
--- /dev/null
@@ -0,0 +1,30 @@
+# 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.
+
+licenses(["notice"])
+
+cc_library(
+    name = "libprotobuf_mutator",
+    srcs = glob(
+        ["src/*.cc", "src/libfuzzer/*.cc"], 
+        exclude = ["src/*_test.cc", "src/libfuzzer/*_test.cc"]
+    ),
+    hdrs = glob(["src/*.h", "port/*.h", "src/libfuzzer/*.h"]),
+    deps = [
+        "@com_google_protobuf//:protobuf",
+        "@com_google_googletest//:gtest",
+    ],
+    visibility = ["//visibility:public"],
+    includes = ["."]
+)
index 6d6da06..b4a8519 100644 (file)
@@ -5,7 +5,7 @@ index 97ac28028..8b7585d9d 100644
 @@ -31,3 +31,9 @@
  # Copyright 2007 Google Inc. All Rights Reserved.
 
- __version__ = '3.17.3'
+ __version__ = '3.18.1'
 +
 +if __name__ != '__main__':
 +  try:
diff --git a/third_party/rake-compiler-dock/rake_arm64-darwin/Dockerfile b/third_party/rake-compiler-dock/rake_arm64-darwin/Dockerfile
new file mode 100644 (file)
index 0000000..e55fe06
--- /dev/null
@@ -0,0 +1 @@
+FROM larskanis/rake-compiler-dock-mri-arm64-darwin:1.1.0
diff --git a/third_party/rake-compiler-dock/rake_x86_64-darwin/Dockerfile b/third_party/rake-compiler-dock/rake_x86_64-darwin/Dockerfile
new file mode 100644 (file)
index 0000000..5c7bb86
--- /dev/null
@@ -0,0 +1 @@
+FROM larskanis/rake-compiler-dock-mri-x86_64-darwin:1.1.0
diff --git a/third_party/rules_python.patch b/third_party/rules_python.patch
new file mode 100644 (file)
index 0000000..3b2b5b8
--- /dev/null
@@ -0,0 +1,76 @@
+diff --git a/python/pip_install/pip_repository.bzl b/python/pip_install/pip_repository.bzl
+index c3007e1..f8a9234 100644
+--- a/python/pip_install/pip_repository.bzl
++++ b/python/pip_install/pip_repository.bzl
+@@ -39,7 +39,8 @@ def _resolve_python_interpreter(rctx):
+         if "/" not in python_interpreter:
+             python_interpreter = rctx.which(python_interpreter)
+         if not python_interpreter:
+-            fail("python interpreter not found")
++            print("WARNING: python interpreter not found. Python targets will not be functional")
++            return ""
+     return python_interpreter
+ def _parse_optional_attrs(rctx, args):
+@@ -93,13 +94,49 @@ def _parse_optional_attrs(rctx, args):
+     return args
++def _generate_stub_requirements_bzl(rctx):
++    contents = """\
++def requirement(name):
++    return "@{repo}//:empty"
++""".format(repo=rctx.attr.name)
++    rctx.file("requirements.bzl", contents)
++
+ _BUILD_FILE_CONTENTS = """\
+ package(default_visibility = ["//visibility:public"])
+ # Ensure the `requirements.bzl` source can be accessed by stardoc, since users load() from it
+ exports_files(["requirements.bzl"])
++
++py_library(
++    name = "empty",
++    srcs = [],
++)
+ """
++def _python_version_info(rctx, python_interpreter, info_index):
++    cmd = [
++        python_interpreter,
++        "-c",
++        "from __future__ import print_function; import sys; print(sys.version_info[{}])".format(info_index)
++    ]
++    result = rctx.execute(cmd)
++    if result.stderr or not result.stdout:
++      print("WARNING: Failed to get version info from {}".format(python_interpreter))
++      return None
++    return int(result.stdout.strip())
++
++def _python_version_supported(rctx, python_interpreter):
++    major_version = _python_version_info(rctx, python_interpreter, 0)
++    minor_version = _python_version_info(rctx, python_interpreter, 1)
++    if major_version == None or minor_version == None:
++        print("WARNING: Failed to get Python version of {}".format(python_interpreter))
++        return False
++    if (major_version != 3 or minor_version < 6):
++        print("WARNING: {} is of version {}.{}. This version is unsupported.".format(python_interpreter, major_version, minor_version))
++        return False
++    return True
++
++
+ def _pip_repository_impl(rctx):
+     python_interpreter = _resolve_python_interpreter(rctx)
+@@ -109,6 +146,11 @@ def _pip_repository_impl(rctx):
+     # We need a BUILD file to load the generated requirements.bzl
+     rctx.file("BUILD.bazel", _BUILD_FILE_CONTENTS)
++    # Check if python interpreter has minimum required version.
++    if not python_interpreter or not _python_version_supported(rctx, python_interpreter):
++      _generate_stub_requirements_bzl(rctx)
++      return
++
+     pypath = _construct_pypath(rctx)
+     if rctx.attr.incremental:
index bb0b9b4..5a8a128 100644 (file)
@@ -16,7 +16,7 @@ licenses(["notice"])  # Apache v2
 
 package(default_visibility = ["//visibility:public"])
 
-load("@bazel_toolchains//rules/exec_properties:exec_properties.bzl", "create_exec_properties_dict", "merge_dicts")
+load("@bazel_toolchains//rules/exec_properties:exec_properties.bzl", "create_rbe_exec_properties_dict")
 
 alias(
     name = "rbe_windows",
@@ -30,19 +30,10 @@ platform(
         "@bazel_tools//platforms:x86_64",
         "@bazel_tools//platforms:windows",
     ],
-    exec_properties = merge_dicts(
-        create_exec_properties_dict(
-            # See rbe_win2019/Dockerfile for image details
-            container_image = "docker://gcr.io/grpc-testing/rbe_windows2019_withdbg_toolchain@sha256:7b04ee7e29f942adbf4f70edd2ec4ba20a3e7237e1b54f5cae4b239c6ca41105",
-            os_family = "Windows",
-        ),
-        # TODO(jtattermusch): specifying 'labels = {"abc": "xyz"}' in create_exec_properties_dict
-        # is not possible without https://github.com/bazelbuild/bazel-toolchains/pull/748
-        # and currently the toolchain we're using is too old for that. To be able to select worker
-        # pools through labels, we use a workaround and populate the corresponding label values
-        # manually (see create_exec_properties_dict logic for how labels get transformed)
-        # Remove this workaround once we transition to a new-enough bazel toolchain.
-        # The next line corresponds to 'labels = {"os": "windows_2019", "machine_size": "small"}'
-        {"label:os": "windows_2019", "label:machine_size": "small"}
+    exec_properties = create_rbe_exec_properties_dict(
+        # See rbe_win2019/Dockerfile for image details
+        container_image = "docker://gcr.io/grpc-testing/rbe_windows2019_withdbg_toolchain@sha256:7b04ee7e29f942adbf4f70edd2ec4ba20a3e7237e1b54f5cae4b239c6ca41105",
+        os_family = "Windows",
+        labels = {"os": "windows_2019", "machine_size": "small"},
     ),
 )
index aaa549a..3f6fda9 100755 (executable)
@@ -25,7 +25,7 @@
 set -e
 
 # DISABLE_BAZEL_WRAPPER can be set to eliminate the wrapper logic
-if [ "${DISABLE_BAZEL_WRAPPER}" != "" ]
+if [ "${DISABLE_BAZEL_WRAPPER}" != "" ] && [ "${OVERRIDE_BAZEL_VERSION}" == "" ]
 then
   if [ "${BAZEL_REAL}" != "" ]
   then
@@ -42,14 +42,15 @@ fi
 
 # IMPORTANT: if you update the version here, other parts of infrastructure might needs updating as well
 # (e.g. win RBE builds, sanity checks, bazel toolchains etc.)
-VERSION=3.7.1
+VERSION=${OVERRIDE_BAZEL_VERSION:-4.2.1}
 echo "INFO: Running bazel wrapper (see //tools/bazel for details), bazel version $VERSION will be used instead of system-wide bazel installation." >&2
 
 # update tools/update_mirror.sh to populate the mirror with new bazel archives
 BASEURL_MIRROR="https://storage.googleapis.com/grpc-bazel-mirror/github.com/bazelbuild/bazel/releases/download"
 BASEURL="https://github.com/bazelbuild/bazel/releases/download"
 pushd "$(dirname "$0")" >/dev/null
-TOOLDIR=$(pwd)
+# bazel binary will be downloaded to GRPC_REPO_ROOT/tools directory by default
+DOWNLOAD_DIR=${OVERRIDE_BAZEL_WRAPPER_DOWNLOAD_DIR:-$(pwd)}
 
 case $(uname -sm) in
   "Linux x86_64")
@@ -68,13 +69,14 @@ case $(uname -sm) in
 esac
 
 filename="bazel-$VERSION-$suffix"
+filename_abs="${DOWNLOAD_DIR}/${filename}"
 
-if [ ! -x "$filename" ] ; then
+if [ ! -x "${filename_abs}" ] ; then
   # first try to download using mirror, fallback to download from github
   echo "Downloading bazel, will try URLs: ${BASEURL_MIRROR}/${VERSION}/${filename} ${BASEURL}/${VERSION}/${filename}" >&2
-  curl --fail -L --output "${filename}" "${BASEURL_MIRROR}/${VERSION}/${filename}" || curl --fail -L --output "${filename}" "${BASEURL}/${VERSION}/${filename}"
-  chmod a+x "$filename"
+  curl --fail -L --output "${filename_abs}" "${BASEURL_MIRROR}/${VERSION}/${filename}" || curl --fail -L --output "${filename_abs}" "${BASEURL}/${VERSION}/${filename}"
+  chmod a+x "${filename_abs}"
 fi
 
 popd >/dev/null
-exec "$TOOLDIR/$filename" "$@"
+exec "${filename_abs}" "$@"
index 480fdcb..9733eaf 100644 (file)
@@ -25,6 +25,20 @@ build:asan --linkopt=-fsanitize=address
 build:asan --action_env=ASAN_OPTIONS=detect_leaks=1:color=always
 build:asan --action_env=LSAN_OPTIONS=suppressions=test/core/util/lsan_suppressions.txt:report_objects=1
 
+build:fuzzer_asan --strip=never
+build:fuzzer_asan --define=grpc_build_fuzzers=true
+build:fuzzer_asan --copt=-fsanitize=fuzzer,address
+build:fuzzer_asan --copt=-fsanitize-coverage=edge
+build:fuzzer_asan --copt=-fsanitize-coverage=trace-cmp
+build:fuzzer_asan --copt=-O0
+build:fuzzer_asan --copt=-fno-omit-frame-pointer
+build:fuzzer_asan --copt=-DGPR_NO_DIRECT_SYSCALLS
+build:fuzzer_asan --copt=-DGRPC_ASAN
+build:fuzzer_asan --copt=-DADDRESS_SANITIZER  # used by absl
+build:fuzzer_asan --linkopt=-fsanitize=fuzzer,address
+build:fuzzer_asan --action_env=ASAN_OPTIONS=detect_leaks=1:color=always
+build:fuzzer_asan --action_env=LSAN_OPTIONS=suppressions=test/core/util/lsan_suppressions.txt:report_objects=1
+
 # We have a separate ASAN config for Mac OS to workaround a couple of bugs:
 # 1. https://github.com/bazelbuild/bazel/issues/6932
 #    _FORTIFY_SOURCE=1 is enabled by default on Mac OS, which breaks ASAN.
index 3b8807c..1fe2d01 100755 (executable)
@@ -94,8 +94,13 @@ def _extract_rules_from_bazel_xml(xml_tree):
             rule_clazz = rule_dict['class']
             rule_name = rule_dict['name']
             if rule_clazz in [
-                    'cc_library', 'cc_binary', 'cc_test', 'cc_proto_library',
-                    'proto_library'
+                    'cc_library',
+                    'cc_binary',
+                    'cc_test',
+                    'cc_proto_library',
+                    'proto_library',
+                    'upb_proto_library',
+                    'upb_proto_reflection_library',
             ]:
                 if rule_name in result:
                     raise Exception('Rule %s already present' % rule_name)
@@ -320,7 +325,6 @@ def _compute_transitive_metadata(
                     _extract_public_headers(bazel_rules[dep]))
                 collapsed_headers.update(
                     _extract_nonpublic_headers(bazel_rules[dep]))
-
     # This item is a "visited" flag
     bazel_rule['_PROCESSING_DONE'] = True
     # Following items are described in the docstinrg.
@@ -377,6 +381,55 @@ def update_test_metadata_with_transitive_metadata(
             lib_dict['language'] = 'c++'
 
 
+def _expand_upb_proto_library_rules(bazel_rules):
+    # Expand the .proto files from UPB proto library rules into the pre-generated
+    # upb.h and upb.c files.
+    GEN_UPB_ROOT = '//:src/core/ext/upb-generated/'
+    GEN_UPBDEFS_ROOT = '//:src/core/ext/upbdefs-generated/'
+    EXTERNAL_LINKS = [
+        ('@com_google_protobuf//', ':src/'),
+    ]
+    for name, bazel_rule in bazel_rules.items():
+        gen_func = bazel_rule.get('generator_function', None)
+        if gen_func in ('grpc_upb_proto_library',
+                        'grpc_upb_proto_reflection_library'):
+            # get proto dependency
+            deps = bazel_rule['deps']
+            if len(deps) != 1:
+                raise Exception(
+                    'upb rule "{0}" should have 1 proto dependency but has "{1}"'
+                    .format(name, deps))
+            proto_dep = deps[0]
+            proto_rule = bazel_rules.get(proto_dep, None)
+            if proto_rule is None:
+                raise Exception(
+                    'upb rule "{0}"\'s dependency "{1}" is not found'.format(
+                        name, proto_rule))
+            # deps is not properly fetched from bazel query for upb_proto_library target
+            # so add the upb dependency manually
+            bazel_rule['deps'] = [
+                '//external:upb_lib', '//external:upb_lib_descriptor',
+                '//external:upb_generated_code_support__only_for_generated_code_do_not_use__i_give_permission_to_break_me'
+            ]
+            # populate the upb_proto_library rule with pre-generated upb headers
+            # and sources using proto_rule
+            srcs = []
+            hdrs = []
+            for proto_src in proto_rule['srcs']:
+                for external_link in EXTERNAL_LINKS:
+                    if proto_src.startswith(external_link[0]):
+                        proto_src = proto_src[len(external_link[0]) +
+                                              len(external_link[1]):]
+                        break
+                proto_src = _extract_source_file_path(proto_src)
+                ext = '.upb' if gen_func == 'grpc_upb_proto_library' else '.upbdefs'
+                root = GEN_UPB_ROOT if gen_func == 'grpc_upb_proto_library' else GEN_UPBDEFS_ROOT
+                srcs.append(root + proto_src.replace('.proto', ext + '.c'))
+                hdrs.append(root + proto_src.replace('.proto', ext + '.h'))
+            bazel_rule['srcs'] = srcs
+            bazel_rule['hdrs'] = hdrs
+
+
 def _generate_build_metadata(build_extra_metadata: BuildDict,
                              bazel_rules: BuildDict) -> BuildDict:
     """Generate build metadata in build.yaml-like format bazel build metadata and build.yaml-specific "extra metadata"."""
@@ -478,15 +531,21 @@ def _exclude_unwanted_cc_tests(tests: List[str]) -> List[str]:
 
     # most qps tests are autogenerated, we are fine without them
     tests = [test for test in tests if not test.startswith('test/cpp/qps:')]
-
-    # we have trouble with census dependency outside of bazel
+    # microbenchmarks aren't needed for checking correctness
+    tests = [
+        test for test in tests
+        if not test.startswith('test/cpp/microbenchmarks:')
+    ]
     tests = [
         test for test in tests
-        if not test.startswith('test/cpp/ext/filters/census:')
+        if not test.startswith('test/core/promise/benchmark:')
     ]
+
+    # we have trouble with census dependency outside of bazel
     tests = [
         test for test in tests
-        if not test.startswith('test/cpp/microbenchmarks:bm_opencensus_plugin')
+        if not test.startswith('test/cpp/ext/filters/census:') and
+        not test.startswith('test/core/xds:xds_channel_stack_modifier_test')
     ]
 
     # missing opencensus/stats/stats.h
@@ -536,6 +595,9 @@ def _exclude_unwanted_cc_tests(tests: List[str]) -> List[str]:
         if not test.startswith('test/cpp/util:channelz_sampler_test')
     ]
 
+    # we don't need to generate fuzzers outside of bazel
+    tests = [test for test in tests if not test.endswith('_fuzzer')]
+
     return tests
 
 
@@ -857,115 +919,6 @@ _BUILD_EXTRA_METADATA = {
 
     # TODO(jtattermusch): add remaining tools such as grpc_print_google_default_creds_token (they are not used by bazel build)
 
-    # Fuzzers
-    'test/core/security:alts_credentials_fuzzer': {
-        'language': 'c++',
-        'build': 'fuzzer',
-        'corpus_dirs': ['test/core/security/corpus/alts_credentials_corpus'],
-        'maxlen': 2048,
-        '_TYPE': 'target',
-        '_RENAME': 'alts_credentials_fuzzer'
-    },
-    'test/core/end2end/fuzzers:client_fuzzer': {
-        'language': 'c++',
-        'build': 'fuzzer',
-        'corpus_dirs': ['test/core/end2end/fuzzers/client_fuzzer_corpus'],
-        'maxlen': 2048,
-        'dict': 'test/core/end2end/fuzzers/hpack.dictionary',
-        '_TYPE': 'target',
-        '_RENAME': 'client_fuzzer'
-    },
-    'test/core/transport/chttp2:hpack_parser_fuzzer': {
-        'language': 'c++',
-        'build': 'fuzzer',
-        'corpus_dirs': ['test/core/transport/chttp2/hpack_parser_corpus'],
-        'maxlen': 512,
-        'dict': 'test/core/end2end/fuzzers/hpack.dictionary',
-        '_TYPE': 'target',
-        '_RENAME': 'hpack_parser_fuzzer_test'
-    },
-    'test/core/http:request_fuzzer': {
-        'language': 'c++',
-        'build': 'fuzzer',
-        'corpus_dirs': ['test/core/http/request_corpus'],
-        'maxlen': 2048,
-        '_TYPE': 'target',
-        '_RENAME': 'http_request_fuzzer_test'
-    },
-    'test/core/http:response_fuzzer': {
-        'language': 'c++',
-        'build': 'fuzzer',
-        'corpus_dirs': ['test/core/http/response_corpus'],
-        'maxlen': 2048,
-        '_TYPE': 'target',
-        '_RENAME': 'http_response_fuzzer_test'
-    },
-    'test/core/json:json_fuzzer': {
-        'language': 'c++',
-        'build': 'fuzzer',
-        'corpus_dirs': ['test/core/json/corpus'],
-        'maxlen': 512,
-        '_TYPE': 'target',
-        '_RENAME': 'json_fuzzer_test'
-    },
-    'test/core/nanopb:fuzzer_response': {
-        'language': 'c++',
-        'build': 'fuzzer',
-        'corpus_dirs': ['test/core/nanopb/corpus_response'],
-        'maxlen': 128,
-        '_TYPE': 'target',
-        '_RENAME': 'nanopb_fuzzer_response_test'
-    },
-    'test/core/nanopb:fuzzer_serverlist': {
-        'language': 'c++',
-        'build': 'fuzzer',
-        'corpus_dirs': ['test/core/nanopb/corpus_serverlist'],
-        'maxlen': 128,
-        '_TYPE': 'target',
-        '_RENAME': 'nanopb_fuzzer_serverlist_test'
-    },
-    'test/core/slice:percent_decode_fuzzer': {
-        'language': 'c++',
-        'build': 'fuzzer',
-        'corpus_dirs': ['test/core/slice/percent_decode_corpus'],
-        'maxlen': 32,
-        '_TYPE': 'target',
-        '_RENAME': 'percent_decode_fuzzer'
-    },
-    'test/core/slice:percent_encode_fuzzer': {
-        'language': 'c++',
-        'build': 'fuzzer',
-        'corpus_dirs': ['test/core/slice/percent_encode_corpus'],
-        'maxlen': 32,
-        '_TYPE': 'target',
-        '_RENAME': 'percent_encode_fuzzer'
-    },
-    'test/core/end2end/fuzzers:server_fuzzer': {
-        'language': 'c++',
-        'build': 'fuzzer',
-        'corpus_dirs': ['test/core/end2end/fuzzers/server_fuzzer_corpus'],
-        'maxlen': 2048,
-        'dict': 'test/core/end2end/fuzzers/hpack.dictionary',
-        '_TYPE': 'target',
-        '_RENAME': 'server_fuzzer'
-    },
-    'test/core/security:ssl_server_fuzzer': {
-        'language': 'c++',
-        'build': 'fuzzer',
-        'corpus_dirs': ['test/core/security/corpus/ssl_server_corpus'],
-        'maxlen': 2048,
-        '_TYPE': 'target',
-        '_RENAME': 'ssl_server_fuzzer'
-    },
-    'test/core/uri:uri_fuzzer_test': {
-        'language': 'c++',
-        'build': 'fuzzer',
-        'corpus_dirs': ['test/core/uri/uri_corpus'],
-        'maxlen': 128,
-        '_TYPE': 'target',
-        '_RENAME': 'uri_fuzzer_test'
-    },
-
     # TODO(jtattermusch): these fuzzers had no build.yaml equivalent
     # test/core/compression:message_compress_fuzzer
     # test/core/compression:message_decompress_fuzzer
@@ -1003,6 +956,11 @@ for query in _BAZEL_DEPS_QUERIES:
     bazel_rules.update(
         _extract_rules_from_bazel_xml(_bazel_query_xml_tree(query)))
 
+# Step 1.5: The sources for UPB protos are pre-generated, so we want
+# to expand the UPB proto library bazel rules into the generated
+# .upb.h and .upb.c files.
+_expand_upb_proto_library_rules(bazel_rules)
+
 # Step 2: Extract the known bazel cc_test tests. While most tests
 # will be buildable with other build systems just fine, some of these tests
 # would be too difficult to build and run with other build systems,
diff --git a/tools/buildgen/plugins/make_fuzzer_tests.py b/tools/buildgen/plugins/make_fuzzer_tests.py
deleted file mode 100644 (file)
index 331c11b..0000000
+++ /dev/null
@@ -1,50 +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.
-"""Create tests for each fuzzer"""
-
-import copy
-import glob
-
-
-def mako_plugin(dictionary):
-    targets = dictionary['targets']
-    tests = dictionary['tests']
-    for tgt in targets:
-        if tgt['build'] == 'fuzzer':
-            new_target = copy.deepcopy(tgt)
-            new_target['build'] = 'test'
-            new_target['name'] += '_one_entry'
-            new_target['run'] = False
-            new_target['src'].append(
-                'test/core/util/one_corpus_entry_fuzzer.cc')
-
-            # avoid having two main() methods
-            to_remove = 'test/core/util/fuzzer_corpus_test.cc'
-            if to_remove in new_target['src']:
-                new_target['src'].remove(to_remove)
-
-            targets.append(new_target)
-            for corpus in new_target['corpus_dirs']:
-                for fn in sorted(glob.glob('%s/*' % corpus)):
-                    tests.append({
-                        'name': new_target['name'],
-                        'args': [fn],
-                        'exclude_configs': ['tsan'],
-                        'uses_polling': False,
-                        'platforms': ['mac', 'linux'],
-                        'ci_platforms': ['linux'],
-                        'flaky': False,
-                        'language': 'c++',
-                        'cpu_cost': 0.1,
-                    })
index 389f89c..a1d50f0 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python2.7
+#!/usr/bin/env python3
 
 # Copyright 2015 gRPC authors.
 #
@@ -74,6 +74,9 @@ CONFIG = [
     'deflate',
     'gzip',
     'stream/gzip',
+    # te: trailers strings
+    'te',
+    'trailers',
     # metadata elements
     # begin hpack static elements
     (':authority', ''),
@@ -144,7 +147,6 @@ CONFIG = [
     ('grpc-encoding', 'identity'),
     ('grpc-encoding', 'gzip'),
     ('grpc-encoding', 'deflate'),
-    ('te', 'trailers'),
     ('content-type', 'application/grpc'),
     (':scheme', 'grpc'),
     (':method', 'PUT'),
@@ -162,7 +164,6 @@ METADATA_BATCH_CALLOUTS = [
     ':status',
     ':authority',
     ':scheme',
-    'te',
     'grpc-message',
     'grpc-status',
     'grpc-payload-bin',
@@ -249,11 +250,11 @@ def fake_hash(elem):
 # utility: print a big comment block into a set of files
 def put_banner(files, banner):
     for f in files:
-        print >> f, '/*'
+        print('/*', file=f)
         for line in banner:
-            print >> f, ' * %s' % line
-        print >> f, ' */'
-        print >> f
+            print(' * %s' % line, file=f)
+        print(' */', file=f)
+        print('', file=f)
 
 
 # build a list of all the strings we need
@@ -303,29 +304,45 @@ for mask in range(1, 1 << len(STREAM_COMPRESSION_ALGORITHMS)):
 
 # output configuration
 args = sys.argv[1:]
-H = None
-C = None
+MD_H = None
+MD_C = None
+STR_H = None
+STR_C = None
 D = None
 if args:
-    if 'header' in args:
-        H = sys.stdout
+    if 'md_header' in args:
+        MD_H = sys.stdout
+    else:
+        MD_H = open('/dev/null', 'w')
+    if 'md_source' in args:
+        MD_C = sys.stdout
     else:
-        H = open('/dev/null', 'w')
-    if 'source' in args:
-        C = sys.stdout
+        MD_C = open('/dev/null', 'w')
+    if 'str_header' in args:
+        STR_H = sys.stdout
     else:
-        C = open('/dev/null', 'w')
+        STR_H = open('/dev/null', 'w')
+    if 'str_source' in args:
+        STR_C = sys.stdout
+    else:
+        STR_C = open('/dev/null', 'w')
     if 'dictionary' in args:
         D = sys.stdout
     else:
         D = open('/dev/null', 'w')
 else:
-    H = open(
+    MD_H = open(
         os.path.join(os.path.dirname(sys.argv[0]),
                      '../../../src/core/lib/transport/static_metadata.h'), 'w')
-    C = open(
+    MD_C = open(
         os.path.join(os.path.dirname(sys.argv[0]),
                      '../../../src/core/lib/transport/static_metadata.cc'), 'w')
+    STR_H = open(
+        os.path.join(os.path.dirname(sys.argv[0]),
+                     '../../../src/core/lib/slice/static_slice.h'), 'w')
+    STR_C = open(
+        os.path.join(os.path.dirname(sys.argv[0]),
+                     '../../../src/core/lib/slice/static_slice.cc'), 'w')
     D = open(
         os.path.join(os.path.dirname(sys.argv[0]),
                      '../../../test/core/end2end/fuzzers/hpack.dictionary'),
@@ -345,7 +362,8 @@ with open(sys.argv[0]) as my_source:
         if line[0] != '#':
             break
         copyright.append(line)
-    put_banner([H, C], [line[2:].rstrip() for line in copyright])
+    put_banner([MD_H, MD_C, STR_H, STR_C],
+               [line[2:].rstrip() for line in copyright])
 
 hex_bytes = [ord(c) for c in 'abcdefABCDEF0123456789']
 
@@ -363,7 +381,7 @@ def esc_dict(line):
     return out + "\""
 
 
-put_banner([H, C], """WARNING: Auto-generated code.
+put_banner([MD_H, MD_C, STR_H, STR_C], """WARNING: Auto-generated code.
 
 To make changes to this file, change
 tools/codegen/core/gen_static_metadata.py, and then re-run it.
@@ -372,21 +390,36 @@ See metadata.h for an explanation of the interface here, and metadata.cc for
 an explanation of what's going on.
 """.splitlines())
 
-print >> H, '#ifndef GRPC_CORE_LIB_TRANSPORT_STATIC_METADATA_H'
-print >> H, '#define GRPC_CORE_LIB_TRANSPORT_STATIC_METADATA_H'
-print >> H
-print >> H, '#include <grpc/support/port_platform.h>'
-print >> H
-print >> H, '#include <cstdint>'
-print >> H
-print >> H, '#include "src/core/lib/transport/metadata.h"'
-print >> H
-print >> C, '#include <grpc/support/port_platform.h>'
-print >> C
-print >> C, '#include "src/core/lib/transport/static_metadata.h"'
-print >> C
-print >> C, '#include "src/core/lib/slice/slice_internal.h"'
-print >> C
+print('#ifndef GRPC_CORE_LIB_TRANSPORT_STATIC_METADATA_H', file=MD_H)
+print('#define GRPC_CORE_LIB_TRANSPORT_STATIC_METADATA_H', file=MD_H)
+print('', file=MD_H)
+print('#include <grpc/support/port_platform.h>', file=MD_H)
+print('', file=MD_H)
+print('#include <cstdint>', file=MD_H)
+print('', file=MD_H)
+print('#include "src/core/lib/transport/metadata.h"', file=MD_H)
+print('#include "src/core/lib/slice/static_slice.h"', file=MD_H)
+print('', file=MD_H)
+print('#ifndef GRPC_CORE_LIB_SLICE_STATIC_SLICE_H', file=STR_H)
+print('#define GRPC_CORE_LIB_SLICE_STATIC_SLICE_H', file=STR_H)
+print('', file=STR_H)
+print('#include <grpc/support/port_platform.h>', file=STR_H)
+print('', file=STR_H)
+print('#include <cstdint>', file=STR_H)
+print('#include <type_traits>', file=STR_H)
+print('#include "src/core/lib/slice/slice_utils.h"', file=STR_H)
+print('#include "src/core/lib/slice/slice_refcount_base.h"', file=STR_H)
+print('', file=STR_H)
+print('#include <grpc/support/port_platform.h>', file=MD_C)
+print('', file=MD_C)
+print('#include "src/core/lib/transport/static_metadata.h"', file=MD_C)
+print('', file=MD_C)
+print('#include "src/core/lib/slice/slice_internal.h"', file=MD_C)
+print('', file=MD_C)
+print('#include <grpc/support/port_platform.h>', file=STR_C)
+print('', file=STR_C)
+print('#include "src/core/lib/slice/static_slice.h"', file=STR_C)
+print('', file=STR_C)
 
 str_ofs = 0
 id2strofs = {}
@@ -397,13 +430,13 @@ for i, elem in enumerate(all_strs):
 
 def slice_def_for_ctx(i):
     return (
-        'grpc_core::StaticMetadataSlice(&refcounts[%d].base, %d, g_bytes+%d)'
+        'grpc_core::StaticMetadataSlice(&g_static_metadata_slice_refcounts[%d].base, %d, g_static_metadata_bytes+%d)'
     ) % (i, len(all_strs[i]), id2strofs[i])
 
 
 def slice_def(i):
     return (
-        'grpc_core::StaticMetadataSlice(&grpc_static_metadata_refcounts()[%d].base, %d, g_bytes+%d)'
+        'grpc_core::StaticMetadataSlice(&g_static_metadata_slice_refcounts[%d].base, %d, g_static_metadata_bytes+%d)'
     ) % (i, len(all_strs[i]), id2strofs[i])
 
 
@@ -420,186 +453,132 @@ static_slice_dest_assert = (
     'static_assert(std::is_trivially_destructible' +
     '<grpc_core::StaticMetadataSlice>::value, '
     '"grpc_core::StaticMetadataSlice must be trivially destructible.");')
-print >> H, static_slice_dest_assert
-print >> H, '#define GRPC_STATIC_MDSTR_COUNT %d' % len(all_strs)
-print >> H, '''
-void grpc_init_static_metadata_ctx(void);
-void grpc_destroy_static_metadata_ctx(void);
-namespace grpc_core {
-#ifndef NDEBUG
-constexpr uint64_t kGrpcStaticMetadataInitCanary = 0xCAFEF00DC0FFEE11L;
-uint64_t StaticMetadataInitCanary();
-#endif
-extern const StaticMetadataSlice* g_static_metadata_slice_table;
-}
-inline const grpc_core::StaticMetadataSlice* grpc_static_slice_table() {
-  GPR_DEBUG_ASSERT(grpc_core::StaticMetadataInitCanary()
-    == grpc_core::kGrpcStaticMetadataInitCanary);
-  GPR_DEBUG_ASSERT(grpc_core::g_static_metadata_slice_table != nullptr);
-  return grpc_core::g_static_metadata_slice_table;
-}
-'''
+print(static_slice_dest_assert, file=STR_H)
+print('#define GRPC_STATIC_MDSTR_COUNT %d' % len(all_strs), file=STR_H)
 for i, elem in enumerate(all_strs):
-    print >> H, '/* "%s" */' % elem
-    print >> H, '#define %s (grpc_static_slice_table()[%d])' % (
-        mangle(elem).upper(), i)
-print >> H
-print >> C, 'static constexpr uint8_t g_bytes[] = {%s};' % (','.join(
-    '%d' % ord(c) for c in ''.join(all_strs)))
-print >> C
-print >> H, '''
+    print('/* "%s" */' % elem, file=STR_H)
+    print('#define %s (::grpc_core::g_static_metadata_slice_table[%d])' %
+          (mangle(elem).upper(), i),
+          file=STR_H)
+print('', file=STR_H)
+print('namespace grpc_core {', file=STR_C)
+print('',
+      'const uint8_t g_static_metadata_bytes[] = {%s};' %
+      (','.join('%d' % ord(c) for c in ''.join(all_strs))),
+      file=STR_C)
+print('', file=STR_C)
+print('''
 namespace grpc_core {
-struct StaticSliceRefcount;
-extern StaticSliceRefcount* g_static_metadata_slice_refcounts;
+extern StaticSliceRefcount g_static_metadata_slice_refcounts[GRPC_STATIC_MDSTR_COUNT];
+extern const StaticMetadataSlice g_static_metadata_slice_table[GRPC_STATIC_MDSTR_COUNT];
+extern const uint8_t g_static_metadata_bytes[];
 }
-inline grpc_core::StaticSliceRefcount* grpc_static_metadata_refcounts() {
-  GPR_DEBUG_ASSERT(grpc_core::StaticMetadataInitCanary()
-    == grpc_core::kGrpcStaticMetadataInitCanary);
-  GPR_DEBUG_ASSERT(grpc_core::g_static_metadata_slice_refcounts != nullptr);
-  return grpc_core::g_static_metadata_slice_refcounts;
-}
-'''
-print >> C, 'grpc_slice_refcount grpc_core::StaticSliceRefcount::kStaticSubRefcount;'
-print >> C, '''
-namespace grpc_core {
-struct StaticMetadataCtx {
-#ifndef NDEBUG
-  const uint64_t init_canary = kGrpcStaticMetadataInitCanary;
-#endif
-  StaticSliceRefcount
-    refcounts[GRPC_STATIC_MDSTR_COUNT] = {
-'''
+''',
+      file=STR_H)
+print('grpc_slice_refcount grpc_core::StaticSliceRefcount::kStaticSubRefcount;',
+      file=STR_C)
+print('''
+StaticSliceRefcount
+    g_static_metadata_slice_refcounts[GRPC_STATIC_MDSTR_COUNT] = {
+''',
+      file=STR_C)
 for i, elem in enumerate(all_strs):
-    print >> C, '  StaticSliceRefcount(%d), ' % i
-print >> C, '};'  # static slice refcounts
-print >> C
-print >> C, '''
+    print('  StaticSliceRefcount(%d), ' % i, file=STR_C)
+print('};', file=STR_C)  # static slice refcounts
+print('', file=STR_C)
+print('''
   const StaticMetadataSlice
-    slices[GRPC_STATIC_MDSTR_COUNT] = {
-'''
+    g_static_metadata_slice_table[GRPC_STATIC_MDSTR_COUNT] = {
+''',
+      file=STR_C)
 for i, elem in enumerate(all_strs):
-    print >> C, slice_def_for_ctx(i) + ','
-print >> C, '};'  # static slices
-print >> C, 'StaticMetadata static_mdelem_table[GRPC_STATIC_MDELEM_COUNT] = {'
+    print(slice_def_for_ctx(i) + ',', file=STR_C)
+print('};', file=STR_C)  # static slices
+print('namespace grpc_core {', file=MD_C)
+print('StaticMetadata g_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT] = {',
+      file=MD_C)
 for idx, (a, b) in enumerate(all_elems):
-    print >> C, 'StaticMetadata(%s,%s, %d),' % (slice_def_for_ctx(
-        str_idx(a)), slice_def_for_ctx(str_idx(b)), idx)
-print >> C, '};'  # static_mdelem_table
-print >> C, ('''
+    print('StaticMetadata(%s,%s, %d),' %
+          (slice_def_for_ctx(str_idx(a)), slice_def_for_ctx(str_idx(b)), idx),
+          file=MD_C)
+print('};', file=MD_C)  # static_mdelem_table
+print(('''
 /* Warning: the core static metadata currently operates under the soft constraint
 that the first GRPC_CHTTP2_LAST_STATIC_ENTRY (61) entries must contain
 metadata specified by the http2 hpack standard. The CHTTP2 transport reads the
 core metadata with this assumption in mind. If the order of the core static
 metadata is to be changed, then the CHTTP2 transport must be changed as well to
 stop relying on the core metadata. */
-''')
-print >> C, ('grpc_mdelem '
-             'static_mdelem_manifested[GRPC_STATIC_MDELEM_COUNT] = {')
-print >> C, '// clang-format off'
+'''),
+      file=MD_C)
+print(('grpc_mdelem '
+       'g_static_mdelem_manifested[GRPC_STATIC_MDELEM_COUNT] = {'),
+      file=MD_C)
+print('// clang-format off', file=MD_C)
 static_mds = []
 for i, elem in enumerate(all_elems):
     md_name = mangle(elem).upper()
     md_human_readable = '"%s": "%s"' % elem
     md_spec = '    /* %s: \n     %s */\n' % (md_name, md_human_readable)
     md_spec += '    GRPC_MAKE_MDELEM(\n'
-    md_spec += (('        &static_mdelem_table[%d].data(),\n' % i) +
+    md_spec += (('        &g_static_mdelem_table[%d].data(),\n' % i) +
                 '        GRPC_MDELEM_STORAGE_STATIC)')
     static_mds.append(md_spec)
-print >> C, ',\n'.join(static_mds)
-print >> C, '// clang-format on'
-print >> C, ('};')  # static_mdelem_manifested
-print >> C, '};'  # struct StaticMetadataCtx
-print >> C, '}'  # namespace grpc_core
-print >> C, '''
-namespace grpc_core {
-static StaticMetadataCtx* g_static_metadata_slice_ctx = nullptr;
-const StaticMetadataSlice* g_static_metadata_slice_table = nullptr;
-StaticSliceRefcount* g_static_metadata_slice_refcounts = nullptr;
-StaticMetadata* g_static_mdelem_table = nullptr;
-grpc_mdelem* g_static_mdelem_manifested = nullptr;
-#ifndef NDEBUG
-uint64_t StaticMetadataInitCanary() {
-  return g_static_metadata_slice_ctx->init_canary;
-}
-#endif
-}
-
-void grpc_init_static_metadata_ctx(void) {
-  grpc_core::g_static_metadata_slice_ctx
-    = new grpc_core::StaticMetadataCtx();
-  grpc_core::g_static_metadata_slice_table
-    = grpc_core::g_static_metadata_slice_ctx->slices;
-  grpc_core::g_static_metadata_slice_refcounts
-    = grpc_core::g_static_metadata_slice_ctx->refcounts;
-  grpc_core::g_static_mdelem_table
-    = grpc_core::g_static_metadata_slice_ctx->static_mdelem_table;
-  grpc_core::g_static_mdelem_manifested =
-      grpc_core::g_static_metadata_slice_ctx->static_mdelem_manifested;
-}
-
-void grpc_destroy_static_metadata_ctx(void) {
-  delete grpc_core::g_static_metadata_slice_ctx;
-  grpc_core::g_static_metadata_slice_ctx = nullptr;
-  grpc_core::g_static_metadata_slice_table = nullptr;
-  grpc_core::g_static_metadata_slice_refcounts = nullptr;
-  grpc_core::g_static_mdelem_table = nullptr;
-  grpc_core::g_static_mdelem_manifested = nullptr;
-}
-
-'''
-
-print >> C
-print >> H, '#define GRPC_IS_STATIC_METADATA_STRING(slice) \\'
-print >> H, ('  ((slice).refcount != NULL && (slice).refcount->GetType() == '
-             'grpc_slice_refcount::Type::STATIC)')
-print >> H
-print >> C
-print >> H, '#define GRPC_STATIC_METADATA_INDEX(static_slice) \\'
-print >> H, '(reinterpret_cast<grpc_core::StaticSliceRefcount*>((static_slice).refcount)->index)'
-print >> H
-
-print >> D, '# hpack fuzzing dictionary'
+print(',\n'.join(static_mds), file=MD_C)
+print('// clang-format on', file=MD_C)
+print(('};'), file=MD_C)  # static_mdelem_manifested
+print('}', file=MD_C)  # namespace grpc_core
+print('}', file=STR_C)  # namespace grpc_core
+
+print('', file=MD_C)
+print('#define GRPC_IS_STATIC_METADATA_STRING(slice) \\', file=STR_H)
+print(('  ((slice).refcount != NULL && (slice).refcount->GetType() == '
+       'grpc_slice_refcount::Type::STATIC)'),
+      file=STR_H)
+print('', file=STR_H)
+print('', file=STR_C)
+print('#define GRPC_STATIC_METADATA_INDEX(static_slice) \\', file=STR_H)
+print(
+    '(reinterpret_cast<grpc_core::StaticSliceRefcount*>((static_slice).refcount)->index)',
+    file=STR_H)
+print('', file=STR_H)
+
+print('# hpack fuzzing dictionary', file=D)
 for i, elem in enumerate(all_strs):
-    print >> D, '%s' % (esc_dict([len(elem)] + [ord(c) for c in elem]))
+    print('%s' % (esc_dict([len(elem)] + [ord(c) for c in elem])), file=D)
 for i, elem in enumerate(all_elems):
-    print >> D, '%s' % (esc_dict([0, len(elem[0])] + [ord(c) for c in elem[0]] +
-                                 [len(elem[1])] + [ord(c) for c in elem[1]]))
+    print('%s' % (esc_dict([0, len(elem[0])] + [ord(c) for c in elem[0]] +
+                           [len(elem[1])] + [ord(c) for c in elem[1]])),
+          file=D)
 
-print >> H, '#define GRPC_STATIC_MDELEM_COUNT %d' % len(all_elems)
-print >> H, '''
+print('#define GRPC_STATIC_MDELEM_COUNT %d' % len(all_elems), file=MD_H)
+print('''
 namespace grpc_core {
-extern StaticMetadata* g_static_mdelem_table;
-extern grpc_mdelem* g_static_mdelem_manifested;
+extern StaticMetadata g_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT];
+extern grpc_mdelem g_static_mdelem_manifested[GRPC_STATIC_MDELEM_COUNT];
 }
-inline grpc_core::StaticMetadata* grpc_static_mdelem_table() {
-  GPR_DEBUG_ASSERT(grpc_core::StaticMetadataInitCanary()
-    == grpc_core::kGrpcStaticMetadataInitCanary);
-  GPR_DEBUG_ASSERT(grpc_core::g_static_mdelem_table != nullptr);
-  return grpc_core::g_static_mdelem_table;
-}
-inline grpc_mdelem* grpc_static_mdelem_manifested() {
-  GPR_DEBUG_ASSERT(grpc_core::StaticMetadataInitCanary()
-    == grpc_core::kGrpcStaticMetadataInitCanary);
-  GPR_DEBUG_ASSERT(grpc_core::g_static_mdelem_manifested != nullptr);
-  return grpc_core::g_static_mdelem_manifested;
-}
-'''
-print >> H, ('extern uintptr_t '
-             'grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT];')
+''',
+      file=MD_H)
+print(('extern uintptr_t '
+       'grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT];'),
+      file=MD_H)
 
 for i, elem in enumerate(all_elems):
     md_name = mangle(elem).upper()
-    print >> H, '/* "%s": "%s" */' % elem
-    print >> H, ('#define %s (grpc_static_mdelem_manifested()[%d])' %
-                 (md_name, i))
-print >> H
-
-print >> C, ('uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT] '
-             '= {')
-print >> C, '  %s' % ','.join(
-    '%d' % static_userdata.get(elem, 0) for elem in all_elems)
-print >> C, '};'
-print >> C
+    print('/* "%s": "%s" */' % elem, file=MD_H)
+    print(('#define %s (::grpc_core::g_static_mdelem_manifested[%d])' %
+           (md_name, i)),
+          file=MD_H)
+print('', file=MD_H)
+
+print(('uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT] '
+       '= {'),
+      file=MD_C)
+print('  %s' %
+      ','.join('%d' % static_userdata.get(elem, 0) for elem in all_elems),
+      file=MD_C)
+print('};', file=MD_C)
+print('', file=MD_C)
 
 
 def md_idx(m):
@@ -621,7 +600,7 @@ def perfect_hash(keys, name):
     def f(i, p=p):
         i += p.offset
         x = i % p.t
-        y = i / p.t
+        y = i // p.t
         return x + p.r[y]
 
     return {
@@ -657,7 +636,7 @@ elem_keys = [
     str_idx(elem[0]) * len(all_strs) + str_idx(elem[1]) for elem in all_elems
 ]
 elem_hash = perfect_hash(elem_keys, 'elems')
-print >> C, elem_hash['code']
+print(elem_hash['code'], file=MD_C)
 
 keys = [0] * int(elem_hash['PHASHNKEYS'])
 idxs = [255] * int(elem_hash['PHASHNKEYS'])
@@ -666,35 +645,46 @@ for i, k in enumerate(elem_keys):
     assert keys[h] == 0
     keys[h] = k
     idxs[h] = i
-print >> C, 'static const uint16_t elem_keys[] = {%s};' % ','.join(
-    '%d' % k for k in keys)
-print >> C, 'static const uint8_t elem_idxs[] = {%s};' % ','.join(
-    '%d' % i for i in idxs)
-print >> C
-
-print >> H, 'grpc_mdelem grpc_static_mdelem_for_static_strings(intptr_t a, intptr_t b);'
-print >> C, 'grpc_mdelem grpc_static_mdelem_for_static_strings(intptr_t a, intptr_t b) {'
-print >> C, '  if (a == -1 || b == -1) return GRPC_MDNULL;'
-print >> C, '  uint32_t k = static_cast<uint32_t>(a * %d + b);' % len(all_strs)
-print >> C, '  uint32_t h = elems_phash(k);'
-print >> C, '  return h < GPR_ARRAY_SIZE(elem_keys) && elem_keys[h] == k && elem_idxs[h] != 255 ? GRPC_MAKE_MDELEM(&grpc_static_mdelem_table()[elem_idxs[h]].data(), GRPC_MDELEM_STORAGE_STATIC) : GRPC_MDNULL;'
-print >> C, '}'
-print >> C
-
-print >> H, 'typedef enum {'
+print('static const uint16_t elem_keys[] = {%s};' %
+      ','.join('%d' % k for k in keys),
+      file=MD_C)
+print('static const uint8_t elem_idxs[] = {%s};' %
+      ','.join('%d' % i for i in idxs),
+      file=MD_C)
+print('', file=MD_C)
+
+print(
+    'grpc_mdelem grpc_static_mdelem_for_static_strings(intptr_t a, intptr_t b);',
+    file=MD_H)
+print(
+    'grpc_mdelem grpc_static_mdelem_for_static_strings(intptr_t a, intptr_t b) {',
+    file=MD_C)
+print('  if (a == -1 || b == -1) return GRPC_MDNULL;', file=MD_C)
+print('  uint32_t k = static_cast<uint32_t>(a * %d + b);' % len(all_strs),
+      file=MD_C)
+print('  uint32_t h = elems_phash(k);', file=MD_C)
+print(
+    '  return h < GPR_ARRAY_SIZE(elem_keys) && elem_keys[h] == k && elem_idxs[h] != 255 ? GRPC_MAKE_MDELEM(&grpc_core::g_static_mdelem_table[elem_idxs[h]].data(), GRPC_MDELEM_STORAGE_STATIC) : GRPC_MDNULL;',
+    file=MD_C)
+print('}', file=MD_C)
+print('', file=MD_C)
+
+print('typedef enum {', file=MD_H)
 for elem in METADATA_BATCH_CALLOUTS:
-    print >> H, '  %s,' % mangle(elem, 'batch').upper()
-print >> H, '  GRPC_BATCH_CALLOUTS_COUNT'
-print >> H, '} grpc_metadata_batch_callouts_index;'
-print >> H
-print >> H, 'typedef union {'
-print >> H, '  struct grpc_linked_mdelem *array[GRPC_BATCH_CALLOUTS_COUNT];'
-print >> H, '  struct {'
+    print('  %s,' % mangle(elem, 'batch').upper(), file=MD_H)
+print('  GRPC_BATCH_CALLOUTS_COUNT', file=MD_H)
+print('} grpc_metadata_batch_callouts_index;', file=MD_H)
+print('', file=MD_H)
+print('typedef union {', file=MD_H)
+print('  struct grpc_linked_mdelem *array[GRPC_BATCH_CALLOUTS_COUNT];',
+      file=MD_H)
+print('  struct {', file=MD_H)
 for elem in METADATA_BATCH_CALLOUTS:
-    print >> H, '  struct grpc_linked_mdelem *%s;' % mangle(elem, '').lower()
-print >> H, '  } named;'
-print >> H, '} grpc_metadata_batch_callouts;'
-print >> H
+    print('  struct grpc_linked_mdelem *%s;' % mangle(elem, '').lower(),
+          file=MD_H)
+print('  } named;', file=MD_H)
+print('} grpc_metadata_batch_callouts;', file=MD_H)
+print('', file=MD_H)
 
 batch_idx_of_hdr = '#define GRPC_BATCH_INDEX_OF(slice) \\'
 static_slice = 'GRPC_IS_STATIC_METADATA_STRING((slice))'
@@ -714,31 +704,44 @@ batch_idx_of_pieces = [
     batch_invalid_u32, '?', slice_ref_idx_to_batch_idx, ':', batch_invalid_idx,
     ')'
 ]
-print >> H, ''.join(batch_idx_of_pieces)
-print >> H
-
-print >> H, 'extern const uint8_t grpc_static_accept_encoding_metadata[%d];' % (
-    1 << len(COMPRESSION_ALGORITHMS))
-print >> C, 'const uint8_t grpc_static_accept_encoding_metadata[%d] = {' % (
-    1 << len(COMPRESSION_ALGORITHMS))
-print >> C, '0,%s' % ','.join('%d' % md_idx(elem) for elem in compression_elems)
-print >> C, '};'
-print >> C
-
-print >> H, '#define GRPC_MDELEM_ACCEPT_ENCODING_FOR_ALGORITHMS(algs) (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table()[grpc_static_accept_encoding_metadata[(algs)]].data(), GRPC_MDELEM_STORAGE_STATIC))'
-print >> H
-
-print >> H, 'extern const uint8_t grpc_static_accept_stream_encoding_metadata[%d];' % (
-    1 << len(STREAM_COMPRESSION_ALGORITHMS))
-print >> C, 'const uint8_t grpc_static_accept_stream_encoding_metadata[%d] = {' % (
-    1 << len(STREAM_COMPRESSION_ALGORITHMS))
-print >> C, '0,%s' % ','.join(
-    '%d' % md_idx(elem) for elem in stream_compression_elems)
-print >> C, '};'
-
-print >> H, '#define GRPC_MDELEM_ACCEPT_STREAM_ENCODING_FOR_ALGORITHMS(algs) (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table()[grpc_static_accept_stream_encoding_metadata[(algs)]].data(), GRPC_MDELEM_STORAGE_STATIC))'
-
-print >> H, '#endif /* GRPC_CORE_LIB_TRANSPORT_STATIC_METADATA_H */'
-
-H.close()
-C.close()
+print(''.join(batch_idx_of_pieces), file=MD_H)
+print('', file=MD_H)
+
+print('extern const uint8_t grpc_static_accept_encoding_metadata[%d];' %
+      (1 << len(COMPRESSION_ALGORITHMS)),
+      file=MD_H)
+print('const uint8_t grpc_static_accept_encoding_metadata[%d] = {' %
+      (1 << len(COMPRESSION_ALGORITHMS)),
+      file=MD_C)
+print('0,%s' % ','.join('%d' % md_idx(elem) for elem in compression_elems),
+      file=MD_C)
+print('};', file=MD_C)
+print('', file=MD_C)
+
+print(
+    '#define GRPC_MDELEM_ACCEPT_ENCODING_FOR_ALGORITHMS(algs) (GRPC_MAKE_MDELEM(&grpc_core::g_static_mdelem_table[grpc_static_accept_encoding_metadata[(algs)]].data(), GRPC_MDELEM_STORAGE_STATIC))',
+    file=MD_H)
+print('', file=MD_H)
+
+print('extern const uint8_t grpc_static_accept_stream_encoding_metadata[%d];' %
+      (1 << len(STREAM_COMPRESSION_ALGORITHMS)),
+      file=MD_H)
+print('const uint8_t grpc_static_accept_stream_encoding_metadata[%d] = {' %
+      (1 << len(STREAM_COMPRESSION_ALGORITHMS)),
+      file=MD_C)
+print('0,%s' %
+      ','.join('%d' % md_idx(elem) for elem in stream_compression_elems),
+      file=MD_C)
+print('};', file=MD_C)
+
+print(
+    '#define GRPC_MDELEM_ACCEPT_STREAM_ENCODING_FOR_ALGORITHMS(algs) (GRPC_MAKE_MDELEM(&grpc_core::g_static_mdelem_table[grpc_static_accept_stream_encoding_metadata[(algs)]].data(), GRPC_MDELEM_STORAGE_STATIC))',
+    file=MD_H)
+
+print('#endif /* GRPC_CORE_LIB_TRANSPORT_STATIC_METADATA_H */', file=MD_H)
+print('#endif /* GRPC_CORE_LIB_SLICE_STATIC_SLICE_H */', file=STR_H)
+
+MD_H.close()
+MD_C.close()
+STR_H.close()
+STR_C.close()
index 2a4a313..d199199 100755 (executable)
@@ -166,7 +166,7 @@ def gen_bucket_code(histogram):
                                       256 * histogram.buckets)
     #print first_nontrivial, shift_data, bounds
     #if shift_data is not None: print [hex(x >> shift_data[0]) for x in code_bounds[first_nontrivial:]]
-    code = 'value = GPR_CLAMP(value, 0, %d);\n' % histogram.max
+    code = 'value = grpc_core::Clamp(value, 0, %d);\n' % histogram.max
     map_table = gen_map_table(code_bounds[first_nontrivial:], shift_data)
     if first_nontrivial is None:
         code += ('GRPC_STATS_INC_HISTOGRAM(GRPC_STATS_HISTOGRAM_%s, value);\n' %
index e7d1bb0..71eed50 100755 (executable)
@@ -120,36 +120,26 @@ proto_files=( \
   "google/api/expr/v1alpha1/checked.proto" \
   "google/api/expr/v1alpha1/syntax.proto" \
   "google/api/http.proto" \
-  "google/protobuf/any.proto" \
   "google/protobuf/descriptor.proto" \
-  "google/protobuf/duration.proto" \
-  "google/protobuf/empty.proto" \
-  "google/protobuf/struct.proto" \
-  "google/protobuf/timestamp.proto" \
-  "google/protobuf/wrappers.proto" \
   "google/rpc/status.proto" \
-  "src/proto/grpc/gcp/altscontext.proto" \
-  "src/proto/grpc/gcp/handshaker.proto" \
-  "src/proto/grpc/gcp/transport_security_common.proto" \
-  "src/proto/grpc/health/v1/health.proto" \
-  "src/proto/grpc/lb/v1/load_balancer.proto" \
   "third_party/istio/security/proto/providers/google/meshca.proto" \
   "udpa/annotations/migrate.proto" \
   "udpa/annotations/security.proto" \
   "udpa/annotations/sensitive.proto" \
   "udpa/annotations/status.proto" \
   "udpa/annotations/versioning.proto" \
-  "udpa/data/orca/v1/orca_load_report.proto" \
-  "udpa/type/v1/typed_struct.proto" \
   "validate/validate.proto" \
+  "xds/annotations/v3/status.proto" \
   "xds/core/v3/authority.proto" \
   "xds/core/v3/collection_entry.proto" \
   "xds/core/v3/context_params.proto" \
   "xds/core/v3/resource_locator.proto" \
   "xds/core/v3/resource_name.proto" \
-  "xds/core/v3/resource.proto")
+  "xds/core/v3/resource.proto" \
+  "xds/data/orca/v3/orca_load_report.proto" \
+  "xds/type/v3/typed_struct.proto")
 
-INCLUDE_OPTIONS="-I=$PWD/third_party/udpa \
+INCLUDE_OPTIONS="-I=$PWD/third_party/xds \
   -I=$PWD/third_party/envoy-api \
   -I=$PWD/third_party/googleapis \
   -I=$PWD/third_party/protobuf/src \
@@ -173,3 +163,9 @@ do
     --upb_out=$UPBDEFS_OUTPUT_DIR \
     --plugin=protoc-gen-upb=$UPBDEFS_PLUGIN
 done
+
+# generate upb files from bazel rules
+python3 tools/codegen/core/gen_upb_api_from_bazel_xml.py \
+  --upb_out=$UPB_OUTPUT_DIR \
+  --upbdefs_out=$UPBDEFS_OUTPUT_DIR \
+  --verbose
diff --git a/tools/codegen/core/gen_upb_api_from_bazel_xml.py b/tools/codegen/core/gen_upb_api_from_bazel_xml.py
new file mode 100755 (executable)
index 0000000..941bb70
--- /dev/null
@@ -0,0 +1,175 @@
+#!/usr/bin/env python3
+
+# 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.
+
+# This script generates upb source files (e.g. *.upb.c) from all upb targets
+# in Bazel BUILD file. These generate upb files are for non-Bazel build such
+# as makefile and python build which cannot generate them at the build time.
+#
+# As an example, for the following upb target
+#
+#   grpc_upb_proto_library(
+#     name = "grpc_health_upb",
+#     deps = ["//src/proto/grpc/health/v1:health_proto_descriptor"],
+#   )
+#
+# this will generate these upb source files at src/core/ext/upb-generated.
+#
+#   src/proto/grpc/health/v1/health.upb.c
+#   src/proto/grpc/health/v1/health.upb.h
+
+import argparse
+import collections
+import os
+import shutil
+import subprocess
+import xml.etree.ElementTree
+
+# Rule object representing the UPB rule of Bazel BUILD.
+Rule = collections.namedtuple('Rule', 'name type srcs deps proto_files')
+
+BAZEL_BIN = 'tools/bazel'
+
+
+def parse_bazel_rule(elem):
+    '''Returns a rule from bazel XML rule.'''
+    srcs = []
+    deps = []
+    for child in elem:
+        if child.tag == 'list' and child.attrib['name'] == 'srcs':
+            for tag in child:
+                if tag.tag == 'label':
+                    srcs.append(tag.attrib['value'])
+        if child.tag == 'list' and child.attrib['name'] == 'deps':
+            for tag in child:
+                if tag.tag == 'label':
+                    deps.append(tag.attrib['value'])
+    return Rule(elem.attrib['name'], elem.attrib['class'], srcs, deps, [])
+
+
+def read_upb_bazel_rules():
+    '''Runs bazel query on given package file and returns all upb rules.'''
+    # Use a wrapper version of bazel in gRPC not to use system-wide bazel
+    # to avoid bazel conflict when running on Kokoro.
+    result = subprocess.check_output(
+        [BAZEL_BIN, 'query', '--output', 'xml', '--noimplicit_deps', '//:all'])
+    root = xml.etree.ElementTree.fromstring(result)
+    rules = [
+        parse_bazel_rule(elem)
+        for elem in root
+        if elem.tag == 'rule' and elem.attrib['class'] in [
+            'upb_proto_library',
+            'upb_proto_reflection_library',
+        ]
+    ]
+    # query all dependencies of upb rules to get a list of proto files
+    all_deps = [dep for rule in rules for dep in rule.deps]
+    result = subprocess.check_output([
+        BAZEL_BIN, 'query', '--output', 'xml', '--noimplicit_deps',
+        ' union '.join(all_deps)
+    ])
+    root = xml.etree.ElementTree.fromstring(result)
+    dep_rules = {}
+    for dep_rule in (
+            parse_bazel_rule(elem) for elem in root if elem.tag == 'rule'):
+        dep_rules[dep_rule.name] = dep_rule
+    # add proto files to upb rules
+    for rule in rules:
+        if len(rule.deps) == 1:
+            dep_rule = dep_rules.get(rule.deps[0], None)
+            if dep_rule:
+                rule.proto_files.extend(dep_rule.srcs)
+    return rules
+
+
+def build_upb_bazel_rules(rules):
+    result = subprocess.check_output([BAZEL_BIN, 'build'] +
+                                     [rule.name for rule in rules])
+
+
+def get_upb_path(proto_path, ext):
+    return proto_path.replace(':', '/').replace('.proto', ext)
+
+
+def get_bazel_bin_root_path(elink):
+    BAZEL_BIN_ROOT = 'bazel-bin/'
+    if elink[0].startswith('@'):
+        # external
+        return os.path.join(BAZEL_BIN_ROOT, 'external',
+                            elink[0].replace('@', '').replace('//', ''))
+    else:
+        # internal
+        return BAZEL_BIN_ROOT
+
+
+def copy_upb_generated_files(rules, args):
+    EXTERNAL_LINKS = [
+        ('@com_google_protobuf//', ':src/'),
+    ]
+    for rule in rules:
+        files = []
+        elink = ('//', '')
+        for external_link in EXTERNAL_LINKS:
+            if rule.proto_files[0].startswith(external_link[0]):
+                elink = external_link
+                break
+        if rule.type == 'upb_proto_library':
+            for proto_file in rule.proto_files:
+                proto_file = proto_file[len(elink[0]) + len(elink[1]):]
+                files.append(get_upb_path(proto_file, '.upb.h'))
+                files.append(get_upb_path(proto_file, '.upb.c'))
+            output_dir = args.upb_out
+        else:
+            for proto_file in rule.proto_files:
+                proto_file = proto_file[len(elink[0]) + len(elink[1]):]
+                files.append(get_upb_path(proto_file, '.upbdefs.h'))
+                files.append(get_upb_path(proto_file, '.upbdefs.c'))
+            output_dir = args.upbdefs_out
+        for file in files:
+            src = os.path.join(get_bazel_bin_root_path(elink), file)
+            dst = os.path.join(output_dir, file)
+            if args.verbose:
+                print('Copy:')
+                print('    {0}'.format(src))
+                print(' -> {0}'.format(dst))
+            os.makedirs(os.path.split(dst)[0], exist_ok=True)
+            shutil.copyfile(src, dst)
+
+
+parser = argparse.ArgumentParser(description='UPB code-gen from bazel')
+parser.add_argument('--verbose', default=False, action='store_true')
+parser.add_argument('--upb_out',
+                    default='src/core/ext/upb-generated',
+                    help='Output directory for upb targets')
+parser.add_argument('--upbdefs_out',
+                    default='src/core/ext/upbdefs-generated',
+                    help='Output directory for upbdefs targets')
+
+
+def main():
+    args = parser.parse_args()
+    rules = read_upb_bazel_rules()
+    if args.verbose:
+        print('Rules:')
+        for rule in rules:
+            print('  name={0} type={1} proto_files={2}'.format(
+                rule.name, rule.type, rule.proto_files))
+    if rules:
+        build_upb_bazel_rules(rules)
+        copy_upb_generated_files(rules, args)
+
+
+if __name__ == '__main__':
+    main()
index 3ed40d8..cba701d 100644 (file)
@@ -14,5 +14,5 @@
 
 # AUTO-GENERATED FROM `$REPO_ROOT/templates/tools/distrib/python/grpcio_tools/grpc_version.py.template`!!!
 
-VERSION = '1.41.1'
-PROTOBUF_VERSION = '3.17.3'
+VERSION = '1.42.0'
+PROTOBUF_VERSION = '3.18.1'
index 275dc14..4b67dd9 100644 (file)
@@ -14,5 +14,5 @@
 
 # AUTO-GENERATED FROM `$REPO_ROOT/templates/tools/distrib/python/grpcio_tools/grpc_version.py.template`!!!
 
-VERSION = '1.41.1'
-PROTOBUF_VERSION = '3.17.3'
+VERSION = '1.42.0'
+PROTOBUF_VERSION = '3.18.1'
index 04705e2..d8d7bd6 100644 (file)
 # limitations under the License.
 
 # AUTO-GENERATED BY make_grpcio_tools.py!
-CC_FILES=['google/protobuf/compiler/zip_writer.cc', 'google/protobuf/compiler/subprocess.cc', 'google/protobuf/compiler/ruby/ruby_generator.cc', 'google/protobuf/compiler/python/python_generator.cc', 'google/protobuf/compiler/plugin.pb.cc', 'google/protobuf/compiler/plugin.cc', 'google/protobuf/compiler/php/php_generator.cc', 'google/protobuf/compiler/objectivec/objectivec_primitive_field.cc', 'google/protobuf/compiler/objectivec/objectivec_oneof.cc', 'google/protobuf/compiler/objectivec/objectivec_message_field.cc', 'google/protobuf/compiler/objectivec/objectivec_message.cc', 'google/protobuf/compiler/objectivec/objectivec_map_field.cc', 'google/protobuf/compiler/objectivec/objectivec_helpers.cc', 'google/protobuf/compiler/objectivec/objectivec_generator.cc', 'google/protobuf/compiler/objectivec/objectivec_file.cc', 'google/protobuf/compiler/objectivec/objectivec_field.cc', 'google/protobuf/compiler/objectivec/objectivec_extension.cc', 'google/protobuf/compiler/objectivec/objectivec_enum_field.cc', 'google/protobuf/compiler/objectivec/objectivec_enum.cc', 'google/protobuf/compiler/js/well_known_types_embed.cc', 'google/protobuf/compiler/js/js_generator.cc', 'google/protobuf/compiler/java/java_string_field_lite.cc', 'google/protobuf/compiler/java/java_string_field.cc', 'google/protobuf/compiler/java/java_shared_code_generator.cc', 'google/protobuf/compiler/java/java_service.cc', 'google/protobuf/compiler/java/java_primitive_field_lite.cc', 'google/protobuf/compiler/java/java_primitive_field.cc', 'google/protobuf/compiler/java/java_name_resolver.cc', 'google/protobuf/compiler/java/java_message_lite.cc', 'google/protobuf/compiler/java/java_message_field_lite.cc', 'google/protobuf/compiler/java/java_message_field.cc', 'google/protobuf/compiler/java/java_message_builder_lite.cc', 'google/protobuf/compiler/java/java_message_builder.cc', 'google/protobuf/compiler/java/java_message.cc', 'google/protobuf/compiler/java/java_map_field_lite.cc', 'google/protobuf/compiler/java/java_map_field.cc', 'google/protobuf/compiler/java/java_kotlin_generator.cc', 'google/protobuf/compiler/java/java_helpers.cc', 'google/protobuf/compiler/java/java_generator_factory.cc', 'google/protobuf/compiler/java/java_generator.cc', 'google/protobuf/compiler/java/java_file.cc', 'google/protobuf/compiler/java/java_field.cc', 'google/protobuf/compiler/java/java_extension_lite.cc', 'google/protobuf/compiler/java/java_extension.cc', 'google/protobuf/compiler/java/java_enum_lite.cc', 'google/protobuf/compiler/java/java_enum_field_lite.cc', 'google/protobuf/compiler/java/java_enum_field.cc', 'google/protobuf/compiler/java/java_enum.cc', 'google/protobuf/compiler/java/java_doc_comment.cc', 'google/protobuf/compiler/java/java_context.cc', 'google/protobuf/compiler/csharp/csharp_wrapper_field.cc', 'google/protobuf/compiler/csharp/csharp_source_generator_base.cc', 'google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc', 'google/protobuf/compiler/csharp/csharp_repeated_message_field.cc', 'google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc', 'google/protobuf/compiler/csharp/csharp_reflection_class.cc', 'google/protobuf/compiler/csharp/csharp_primitive_field.cc', 'google/protobuf/compiler/csharp/csharp_message_field.cc', 'google/protobuf/compiler/csharp/csharp_message.cc', 'google/protobuf/compiler/csharp/csharp_map_field.cc', 'google/protobuf/compiler/csharp/csharp_helpers.cc', 'google/protobuf/compiler/csharp/csharp_generator.cc', 'google/protobuf/compiler/csharp/csharp_field_base.cc', 'google/protobuf/compiler/csharp/csharp_enum_field.cc', 'google/protobuf/compiler/csharp/csharp_enum.cc', 'google/protobuf/compiler/csharp/csharp_doc_comment.cc', 'google/protobuf/compiler/cpp/cpp_string_field.cc', 'google/protobuf/compiler/cpp/cpp_service.cc', 'google/protobuf/compiler/cpp/cpp_primitive_field.cc', 'google/protobuf/compiler/cpp/cpp_parse_function_generator.cc', 'google/protobuf/compiler/cpp/cpp_padding_optimizer.cc', 'google/protobuf/compiler/cpp/cpp_message_field.cc', 'google/protobuf/compiler/cpp/cpp_message.cc', 'google/protobuf/compiler/cpp/cpp_map_field.cc', 'google/protobuf/compiler/cpp/cpp_helpers.cc', 'google/protobuf/compiler/cpp/cpp_generator.cc', 'google/protobuf/compiler/cpp/cpp_file.cc', 'google/protobuf/compiler/cpp/cpp_field.cc', 'google/protobuf/compiler/cpp/cpp_extension.cc', 'google/protobuf/compiler/cpp/cpp_enum_field.cc', 'google/protobuf/compiler/cpp/cpp_enum.cc', 'google/protobuf/compiler/command_line_interface.cc', 'google/protobuf/compiler/code_generator.cc', 'google/protobuf/wrappers.pb.cc', 'google/protobuf/wire_format.cc', 'google/protobuf/util/type_resolver_util.cc', 'google/protobuf/util/time_util.cc', 'google/protobuf/util/message_differencer.cc', 'google/protobuf/util/json_util.cc', 'google/protobuf/util/internal/utility.cc', 'google/protobuf/util/internal/type_info_test_helper.cc', 'google/protobuf/util/internal/type_info.cc', 'google/protobuf/util/internal/protostream_objectwriter.cc', 'google/protobuf/util/internal/protostream_objectsource.cc', 'google/protobuf/util/internal/proto_writer.cc', 'google/protobuf/util/internal/object_writer.cc', 'google/protobuf/util/internal/json_stream_parser.cc', 'google/protobuf/util/internal/json_objectwriter.cc', 'google/protobuf/util/internal/json_escaping.cc', 'google/protobuf/util/internal/field_mask_utility.cc', 'google/protobuf/util/internal/error_listener.cc', 'google/protobuf/util/internal/default_value_objectwriter.cc', 'google/protobuf/util/internal/datapiece.cc', 'google/protobuf/util/field_mask_util.cc', 'google/protobuf/util/field_comparator.cc', 'google/protobuf/util/delimited_message_util.cc', 'google/protobuf/unknown_field_set.cc', 'google/protobuf/type.pb.cc', 'google/protobuf/timestamp.pb.cc', 'google/protobuf/text_format.cc', 'google/protobuf/stubs/substitute.cc', 'google/protobuf/struct.pb.cc', 'google/protobuf/source_context.pb.cc', 'google/protobuf/service.cc', 'google/protobuf/reflection_ops.cc', 'google/protobuf/message.cc', 'google/protobuf/map_field.cc', 'google/protobuf/io/tokenizer.cc', 'google/protobuf/io/printer.cc', 'google/protobuf/io/gzip_stream.cc', 'google/protobuf/generated_message_table_driven.cc', 'google/protobuf/generated_message_reflection.cc', 'google/protobuf/field_mask.pb.cc', 'google/protobuf/extension_set_heavy.cc', 'google/protobuf/empty.pb.cc', 'google/protobuf/dynamic_message.cc', 'google/protobuf/duration.pb.cc', 'google/protobuf/descriptor_database.cc', 'google/protobuf/descriptor.pb.cc', 'google/protobuf/descriptor.cc', 'google/protobuf/compiler/parser.cc', 'google/protobuf/compiler/importer.cc', 'google/protobuf/api.pb.cc', 'google/protobuf/any.pb.cc', 'google/protobuf/any.cc', 'google/protobuf/wire_format_lite.cc', 'google/protobuf/stubs/time.cc', 'google/protobuf/stubs/strutil.cc', 'google/protobuf/stubs/structurally_valid.cc', 'google/protobuf/stubs/stringprintf.cc', 'google/protobuf/stubs/stringpiece.cc', 'google/protobuf/stubs/statusor.cc', 'google/protobuf/stubs/status.cc', 'google/protobuf/stubs/int128.cc', 'google/protobuf/stubs/common.cc', 'google/protobuf/stubs/bytestream.cc', 'google/protobuf/repeated_field.cc', 'google/protobuf/parse_context.cc', 'google/protobuf/message_lite.cc', 'google/protobuf/map.cc', 'google/protobuf/io/zero_copy_stream_impl_lite.cc', 'google/protobuf/io/zero_copy_stream_impl.cc', 'google/protobuf/io/zero_copy_stream.cc', 'google/protobuf/io/strtod.cc', 'google/protobuf/io/io_win32.cc', 'google/protobuf/io/coded_stream.cc', 'google/protobuf/implicit_weak_message.cc', 'google/protobuf/generated_message_util.cc', 'google/protobuf/generated_message_table_driven_lite.cc', 'google/protobuf/generated_enum_util.cc', 'google/protobuf/field_access_listener.cc', 'google/protobuf/extension_set.cc', 'google/protobuf/arenastring.cc', 'google/protobuf/arena.cc', 'google/protobuf/any_lite.cc']
+CC_FILES=['google/protobuf/compiler/zip_writer.cc', 'google/protobuf/compiler/subprocess.cc', 'google/protobuf/compiler/ruby/ruby_generator.cc', 'google/protobuf/compiler/python/python_generator.cc', 'google/protobuf/compiler/plugin.pb.cc', 'google/protobuf/compiler/plugin.cc', 'google/protobuf/compiler/php/php_generator.cc', 'google/protobuf/compiler/objectivec/objectivec_primitive_field.cc', 'google/protobuf/compiler/objectivec/objectivec_oneof.cc', 'google/protobuf/compiler/objectivec/objectivec_message_field.cc', 'google/protobuf/compiler/objectivec/objectivec_message.cc', 'google/protobuf/compiler/objectivec/objectivec_map_field.cc', 'google/protobuf/compiler/objectivec/objectivec_helpers.cc', 'google/protobuf/compiler/objectivec/objectivec_generator.cc', 'google/protobuf/compiler/objectivec/objectivec_file.cc', 'google/protobuf/compiler/objectivec/objectivec_field.cc', 'google/protobuf/compiler/objectivec/objectivec_extension.cc', 'google/protobuf/compiler/objectivec/objectivec_enum_field.cc', 'google/protobuf/compiler/objectivec/objectivec_enum.cc', 'google/protobuf/compiler/js/well_known_types_embed.cc', 'google/protobuf/compiler/js/js_generator.cc', 'google/protobuf/compiler/java/java_string_field_lite.cc', 'google/protobuf/compiler/java/java_string_field.cc', 'google/protobuf/compiler/java/java_shared_code_generator.cc', 'google/protobuf/compiler/java/java_service.cc', 'google/protobuf/compiler/java/java_primitive_field_lite.cc', 'google/protobuf/compiler/java/java_primitive_field.cc', 'google/protobuf/compiler/java/java_name_resolver.cc', 'google/protobuf/compiler/java/java_message_lite.cc', 'google/protobuf/compiler/java/java_message_field_lite.cc', 'google/protobuf/compiler/java/java_message_field.cc', 'google/protobuf/compiler/java/java_message_builder_lite.cc', 'google/protobuf/compiler/java/java_message_builder.cc', 'google/protobuf/compiler/java/java_message.cc', 'google/protobuf/compiler/java/java_map_field_lite.cc', 'google/protobuf/compiler/java/java_map_field.cc', 'google/protobuf/compiler/java/java_kotlin_generator.cc', 'google/protobuf/compiler/java/java_helpers.cc', 'google/protobuf/compiler/java/java_generator_factory.cc', 'google/protobuf/compiler/java/java_generator.cc', 'google/protobuf/compiler/java/java_file.cc', 'google/protobuf/compiler/java/java_field.cc', 'google/protobuf/compiler/java/java_extension_lite.cc', 'google/protobuf/compiler/java/java_extension.cc', 'google/protobuf/compiler/java/java_enum_lite.cc', 'google/protobuf/compiler/java/java_enum_field_lite.cc', 'google/protobuf/compiler/java/java_enum_field.cc', 'google/protobuf/compiler/java/java_enum.cc', 'google/protobuf/compiler/java/java_doc_comment.cc', 'google/protobuf/compiler/java/java_context.cc', 'google/protobuf/compiler/csharp/csharp_wrapper_field.cc', 'google/protobuf/compiler/csharp/csharp_source_generator_base.cc', 'google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc', 'google/protobuf/compiler/csharp/csharp_repeated_message_field.cc', 'google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc', 'google/protobuf/compiler/csharp/csharp_reflection_class.cc', 'google/protobuf/compiler/csharp/csharp_primitive_field.cc', 'google/protobuf/compiler/csharp/csharp_message_field.cc', 'google/protobuf/compiler/csharp/csharp_message.cc', 'google/protobuf/compiler/csharp/csharp_map_field.cc', 'google/protobuf/compiler/csharp/csharp_helpers.cc', 'google/protobuf/compiler/csharp/csharp_generator.cc', 'google/protobuf/compiler/csharp/csharp_field_base.cc', 'google/protobuf/compiler/csharp/csharp_enum_field.cc', 'google/protobuf/compiler/csharp/csharp_enum.cc', 'google/protobuf/compiler/csharp/csharp_doc_comment.cc', 'google/protobuf/compiler/cpp/cpp_string_field.cc', 'google/protobuf/compiler/cpp/cpp_service.cc', 'google/protobuf/compiler/cpp/cpp_primitive_field.cc', 'google/protobuf/compiler/cpp/cpp_parse_function_generator.cc', 'google/protobuf/compiler/cpp/cpp_padding_optimizer.cc', 'google/protobuf/compiler/cpp/cpp_message_field.cc', 'google/protobuf/compiler/cpp/cpp_message.cc', 'google/protobuf/compiler/cpp/cpp_map_field.cc', 'google/protobuf/compiler/cpp/cpp_helpers.cc', 'google/protobuf/compiler/cpp/cpp_generator.cc', 'google/protobuf/compiler/cpp/cpp_file.cc', 'google/protobuf/compiler/cpp/cpp_field.cc', 'google/protobuf/compiler/cpp/cpp_extension.cc', 'google/protobuf/compiler/cpp/cpp_enum_field.cc', 'google/protobuf/compiler/cpp/cpp_enum.cc', 'google/protobuf/compiler/command_line_interface.cc', 'google/protobuf/compiler/code_generator.cc', 'google/protobuf/wrappers.pb.cc', 'google/protobuf/wire_format.cc', 'google/protobuf/util/type_resolver_util.cc', 'google/protobuf/util/time_util.cc', 'google/protobuf/util/message_differencer.cc', 'google/protobuf/util/json_util.cc', 'google/protobuf/util/internal/utility.cc', 'google/protobuf/util/internal/type_info_test_helper.cc', 'google/protobuf/util/internal/type_info.cc', 'google/protobuf/util/internal/protostream_objectwriter.cc', 'google/protobuf/util/internal/protostream_objectsource.cc', 'google/protobuf/util/internal/proto_writer.cc', 'google/protobuf/util/internal/object_writer.cc', 'google/protobuf/util/internal/json_stream_parser.cc', 'google/protobuf/util/internal/json_objectwriter.cc', 'google/protobuf/util/internal/json_escaping.cc', 'google/protobuf/util/internal/field_mask_utility.cc', 'google/protobuf/util/internal/error_listener.cc', 'google/protobuf/util/internal/default_value_objectwriter.cc', 'google/protobuf/util/internal/datapiece.cc', 'google/protobuf/util/field_mask_util.cc', 'google/protobuf/util/field_comparator.cc', 'google/protobuf/util/delimited_message_util.cc', 'google/protobuf/unknown_field_set.cc', 'google/protobuf/type.pb.cc', 'google/protobuf/timestamp.pb.cc', 'google/protobuf/text_format.cc', 'google/protobuf/stubs/substitute.cc', 'google/protobuf/struct.pb.cc', 'google/protobuf/source_context.pb.cc', 'google/protobuf/service.cc', 'google/protobuf/reflection_ops.cc', 'google/protobuf/message.cc', 'google/protobuf/map_field.cc', 'google/protobuf/io/tokenizer.cc', 'google/protobuf/io/printer.cc', 'google/protobuf/io/gzip_stream.cc', 'google/protobuf/generated_message_table_driven.cc', 'google/protobuf/generated_message_reflection.cc', 'google/protobuf/generated_message_bases.cc', 'google/protobuf/field_mask.pb.cc', 'google/protobuf/extension_set_heavy.cc', 'google/protobuf/empty.pb.cc', 'google/protobuf/dynamic_message.cc', 'google/protobuf/duration.pb.cc', 'google/protobuf/descriptor_database.cc', 'google/protobuf/descriptor.pb.cc', 'google/protobuf/descriptor.cc', 'google/protobuf/compiler/parser.cc', 'google/protobuf/compiler/importer.cc', 'google/protobuf/api.pb.cc', 'google/protobuf/any.pb.cc', 'google/protobuf/any.cc', 'google/protobuf/wire_format_lite.cc', 'google/protobuf/stubs/time.cc', 'google/protobuf/stubs/strutil.cc', 'google/protobuf/stubs/structurally_valid.cc', 'google/protobuf/stubs/stringprintf.cc', 'google/protobuf/stubs/stringpiece.cc', 'google/protobuf/stubs/statusor.cc', 'google/protobuf/stubs/status.cc', 'google/protobuf/stubs/int128.cc', 'google/protobuf/stubs/common.cc', 'google/protobuf/stubs/bytestream.cc', 'google/protobuf/repeated_field.cc', 'google/protobuf/parse_context.cc', 'google/protobuf/message_lite.cc', 'google/protobuf/map.cc', 'google/protobuf/io/zero_copy_stream_impl_lite.cc', 'google/protobuf/io/zero_copy_stream_impl.cc', 'google/protobuf/io/zero_copy_stream.cc', 'google/protobuf/io/strtod.cc', 'google/protobuf/io/io_win32.cc', 'google/protobuf/io/coded_stream.cc', 'google/protobuf/inlined_string_field.cc', 'google/protobuf/implicit_weak_message.cc', 'google/protobuf/generated_message_util.cc', 'google/protobuf/generated_message_table_driven_lite.cc', 'google/protobuf/generated_enum_util.cc', 'google/protobuf/extension_set.cc', 'google/protobuf/arenastring.cc', 'google/protobuf/arena.cc', 'google/protobuf/any_lite.cc']
 PROTO_FILES=['google/protobuf/wrappers.proto', 'google/protobuf/type.proto', 'google/protobuf/timestamp.proto', 'google/protobuf/struct.proto', 'google/protobuf/source_context.proto', 'google/protobuf/field_mask.proto', 'google/protobuf/empty.proto', 'google/protobuf/duration.proto', 'google/protobuf/descriptor.proto', 'google/protobuf/compiler/plugin.proto', 'google/protobuf/api.proto', 'google/protobuf/any.proto']
 
 CC_INCLUDE='third_party/protobuf/src'
 PROTO_INCLUDE='third_party/protobuf/src'
 
-PROTOBUF_SUBMODULE_VERSION="909a0f36a10075c4b4bc70fdee2c7e32dd612a72"
+PROTOBUF_SUBMODULE_VERSION="0dab03ba7bc438d7ba3eac2b2c1eb39ed520f928"
index 07a3092..6b842f5 100644 (file)
@@ -288,6 +288,7 @@ setuptools.setup(name='grpcio-tools',
                  classifiers=CLASSIFIERS,
                  ext_modules=extension_modules(),
                  packages=setuptools.find_packages('.'),
+                 python_requires='>=3.6',
                  install_requires=[
                      'protobuf>=3.5.0.post1, < 4.0dev',
                      'grpcio>={version}'.format(version=grpc_version.VERSION),
index 3acb218..4f6fbf9 100644 (file)
@@ -47,6 +47,7 @@ setuptools.setup(
     author_email='grpc-io@googlegroups.com',
     url='https://grpc.io',
     license='Apache License 2.0',
+    python_requires='>=3.6',
     install_requires=INSTALL_REQUIRES,
     setup_requires=SETUP_REQUIRES,
     classifiers=CLASSIFIERS)
index 2f0cd7a..2c02ccd 100755 (executable)
@@ -50,7 +50,7 @@ cmdline = [
 ]
 
 if args.fix:
-    cmdline.append('--fix')
+    cmdline.append('--fix-errors')
 
 if args.only_changed:
     orig_files = set(args.files)
diff --git a/tools/dockerfile/distribtest/python_dev_buster_x64/Dockerfile b/tools/dockerfile/distribtest/python_dev_buster_x64/Dockerfile
new file mode 100644 (file)
index 0000000..13cf328
--- /dev/null
@@ -0,0 +1,21 @@
+# 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.
+
+FROM debian:buster
+
+RUN apt-get update && apt-get install -y python3 python3-pip
+RUN pip3 install virtualenv==16.7.9
+
+RUN apt-get install -y build-essential
+RUN apt-get install -y python3-dev
diff --git a/tools/dockerfile/distribtest/python_dev_buster_x86/Dockerfile b/tools/dockerfile/distribtest/python_dev_buster_x86/Dockerfile
new file mode 100644 (file)
index 0000000..77fadd5
--- /dev/null
@@ -0,0 +1,27 @@
+# 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.
+
+FROM i386/debian:buster
+
+RUN apt-get update && apt-get install -y python3 python3-pip
+
+RUN pip3 install virtualenv==16.7.9
+
+RUN apt-get install -y build-essential
+RUN apt-get install -y python3-dev
+
+# docker is running on a 64-bit machine, so we need to
+# override "uname -m" to report i686 instead of x86_64, otherwise
+# python will choose a wrong binary package to install.
+ENTRYPOINT ["linux32"]
diff --git a/tools/dockerfile/distribtest/python_dev_fedora23_x64/Dockerfile b/tools/dockerfile/distribtest/python_dev_fedora23_x64/Dockerfile
deleted file mode 100644 (file)
index cfa3d93..0000000
+++ /dev/null
@@ -1,23 +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.
-
-FROM fedora:23
-
-RUN yum clean all && yum update -y && yum install -y python3 python3-pip
-RUN pip3 install virtualenv==16.7.9
-
-RUN yum groupinstall -y "Development Tools"
-RUN yum install -y redhat-rpm-config
-RUN yum install -y gcc-c++
-RUN yum install -y python3-devel
diff --git a/tools/dockerfile/distribtest/python_dev_fedora34_x64/Dockerfile b/tools/dockerfile/distribtest/python_dev_fedora34_x64/Dockerfile
new file mode 100644 (file)
index 0000000..26df8e8
--- /dev/null
@@ -0,0 +1,23 @@
+# Copyright 2021 The gRPC Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+FROM fedora:34
+
+RUN yum clean all && yum update -y && yum install -y python3 python3-pip
+RUN pip3 install virtualenv==16.7.9
+
+RUN yum groupinstall -y "Development Tools"
+RUN yum install -y redhat-rpm-config
+RUN yum install -y gcc-c++
+RUN yum install -y python3-devel
diff --git a/tools/dockerfile/distribtest/python_dev_jessie_x64/Dockerfile b/tools/dockerfile/distribtest/python_dev_jessie_x64/Dockerfile
deleted file mode 100644 (file)
index e4ee142..0000000
+++ /dev/null
@@ -1,21 +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.
-
-FROM debian:jessie
-
-RUN apt-get update && apt-get install -y python3 python3-pip
-RUN pip3 install virtualenv==16.7.9
-
-RUN apt-get install -y build-essential
-RUN apt-get install -y python3-dev
diff --git a/tools/dockerfile/distribtest/python_dev_jessie_x86/Dockerfile b/tools/dockerfile/distribtest/python_dev_jessie_x86/Dockerfile
deleted file mode 100644 (file)
index b59e4b4..0000000
+++ /dev/null
@@ -1,27 +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.
-
-FROM i386/debian:jessie
-
-RUN apt-get update && apt-get install -y python3 python3-pip
-
-RUN pip3 install virtualenv==16.7.9
-
-RUN apt-get install -y build-essential
-RUN apt-get install -y python3-dev
-
-# docker is running on a 64-bit machine, so we need to
-# override "uname -m" to report i686 instead of x86_64, otherwise
-# python will choose a wrong binary package to install.
-ENTRYPOINT ["linux32"]
index 519274e..4badb12 100644 (file)
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-FROM debian:8
+FROM debian:9
 
 
 #=================
@@ -26,6 +26,7 @@ RUN apt-get update && apt-get install -y \
   ccache \
   curl \
   git \
+  libbison-dev \
   libcurl4-openssl-dev \
   libgmp-dev \
   libgmp3-dev \
@@ -37,28 +38,19 @@ RUN apt-get update && apt-get install -y \
   time \
   unzip \
   wget \
-  zip && apt-get clean
-
-# Install other dependencies
-RUN ln -sf /usr/include/x86_64-linux-gnu/gmp.h /usr/include/gmp.h
-RUN wget http://ftp.gnu.org/gnu/bison/bison-3.4.2.tar.gz -O /var/local/bison-3.4.2.tar.gz
-RUN cd /var/local \
-  && tar -zxvf bison-3.4.2.tar.gz \
-  && cd /var/local/bison-3.4.2 \
-  && ./configure \
-  && make \
-  && make install
+  zip \
+  zlib1g-dev && apt-get clean
 
 # Compile PHP7 from source
 RUN git clone https://github.com/php/php-src /var/local/git/php-src
 RUN cd /var/local/git/php-src \
-  && git checkout PHP-7.2.22 \
+  && git checkout PHP-7.2.34 \
   && ./buildconf --force \
   && ./configure \
   --with-gmp \
   --with-openssl \
   --with-zlib \
-  && make \
+  && make -j$(nproc) \
   && make install
 
 
index d9533e1..8cc9dbd 100644 (file)
@@ -71,7 +71,7 @@ RUN python3.6 -m ensurepip && \
 # Bazel installation
 
 # Must be in sync with tools/bazel
-ENV BAZEL_VERSION 3.7.1
+ENV BAZEL_VERSION 4.2.1
 
 # The correct bazel version is already preinstalled, no need to use //tools/bazel wrapper.
 ENV DISABLE_BAZEL_WRAPPER 1
index c3282f1..90a1fee 100644 (file)
@@ -56,7 +56,7 @@ ENV ANDROID_NDK_HOME=/opt/android-sdk/ndk/21.4.7075529
 # Bazel installation
 
 # Must be in sync with tools/bazel
-ENV BAZEL_VERSION 3.7.1
+ENV BAZEL_VERSION 4.2.1
 
 # The correct bazel version is already preinstalled, no need to use //tools/bazel wrapper.
 ENV DISABLE_BAZEL_WRAPPER 1
diff --git a/tools/dockerfile/test/cxx_clang_12_x64/Dockerfile b/tools/dockerfile/test/cxx_clang_12_x64/Dockerfile
new file mode 100644 (file)
index 0000000..426f464
--- /dev/null
@@ -0,0 +1,54 @@
+# 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.
+
+FROM silkeh/clang:12
+
+RUN apt-get update && apt-get install -y build-essential curl git golang time wget zip
+#====================
+# Python dependencies
+
+# Install dependencies
+
+RUN apt-get update && apt-get install -y \
+    python-all-dev \
+    python3-all-dev \
+    python-setuptools
+
+# Install Python packages from PyPI
+RUN curl https://bootstrap.pypa.io/pip/2.7/get-pip.py | python2.7
+RUN pip install --upgrade pip==19.3.1
+RUN pip install virtualenv==16.7.9
+RUN pip install futures==3.1.1 enum34==1.1.10 protobuf==3.5.2.post1 six==1.16.0 twisted==19.10.0
+
+RUN pip install PyYAML==5.4.1
+RUN apt-get install python-is-python2
+# Google Cloud platform API libraries
+RUN pip install --upgrade google-auth==1.24.0 google-api-python-client==1.12.8 oauth2client==4.1.0
+
+#=================
+# C++ dependencies
+RUN apt-get update && apt-get -y install libgflags-dev libgtest-dev libc++-dev clang && apt-get clean
+
+#=================
+# Install cmake
+# Note that this step should be only used for distributions that have new enough cmake to satisfy gRPC's cmake version requirement.
+
+RUN apt-get update && apt-get install -y cmake && apt-get clean
+
+
+RUN mkdir /var/local/jenkins
+
+
+# Define the default command.
+CMD ["bash"]
diff --git a/tools/dockerfile/test/cxx_clang_4_x64/Dockerfile b/tools/dockerfile/test/cxx_clang_4_x64/Dockerfile
new file mode 100644 (file)
index 0000000..95d4aed
--- /dev/null
@@ -0,0 +1,54 @@
+# 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.
+
+FROM silkeh/clang:4
+
+RUN apt-get update && apt-get install -y build-essential curl git golang time wget zip
+#====================
+# Python dependencies
+
+# Install dependencies
+
+RUN apt-get update && apt-get install -y \
+    python-all-dev \
+    python3-all-dev \
+    python-setuptools
+
+# Install Python packages from PyPI
+RUN curl https://bootstrap.pypa.io/pip/2.7/get-pip.py | python2.7
+RUN pip install --upgrade pip==19.3.1
+RUN pip install virtualenv==16.7.9
+RUN pip install futures==3.1.1 enum34==1.1.10 protobuf==3.5.2.post1 six==1.16.0 twisted==19.10.0
+
+RUN pip install PyYAML==5.4.1
+RUN apt-get install python-is-python2
+# Google Cloud platform API libraries
+RUN pip install --upgrade google-auth==1.24.0 google-api-python-client==1.12.8 oauth2client==4.1.0
+
+#=================
+# C++ dependencies
+RUN apt-get update && apt-get -y install libgflags-dev libgtest-dev libc++-dev clang && apt-get clean
+
+#=================
+# Install cmake
+# Note that this step should be only used for distributions that have new enough cmake to satisfy gRPC's cmake version requirement.
+
+RUN apt-get update && apt-get install -y cmake && apt-get clean
+
+
+RUN mkdir /var/local/jenkins
+
+
+# Define the default command.
+CMD ["bash"]
diff --git a/tools/dockerfile/test/cxx_gcc_11_x64/Dockerfile b/tools/dockerfile/test/cxx_gcc_11_x64/Dockerfile
new file mode 100644 (file)
index 0000000..9437ca3
--- /dev/null
@@ -0,0 +1,54 @@
+# 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.
+
+FROM gcc:11
+
+RUN apt-get update && apt-get install -y curl git golang time wget zip
+#====================
+# Python dependencies
+
+# Install dependencies
+
+RUN apt-get update && apt-get install -y \
+    python-all-dev \
+    python3-all-dev \
+    python-setuptools
+
+# Install Python packages from PyPI
+RUN curl https://bootstrap.pypa.io/pip/2.7/get-pip.py | python2.7
+RUN pip install --upgrade pip==19.3.1
+RUN pip install virtualenv==16.7.9
+RUN pip install futures==3.1.1 enum34==1.1.10 protobuf==3.5.2.post1 six==1.16.0 twisted==19.10.0
+
+RUN pip install PyYAML==5.4.1
+RUN apt-get install python-is-python2
+# Google Cloud platform API libraries
+RUN pip install --upgrade google-auth==1.24.0 google-api-python-client==1.12.8 oauth2client==4.1.0
+
+#=================
+# C++ dependencies
+RUN apt-get update && apt-get -y install libgflags-dev libgtest-dev libc++-dev clang && apt-get clean
+
+#=================
+# Install cmake
+# Note that this step should be only used for distributions that have new enough cmake to satisfy gRPC's cmake version requirement.
+
+RUN apt-get update && apt-get install -y cmake && apt-get clean
+
+
+RUN mkdir /var/local/jenkins
+
+
+# Define the default command.
+CMD ["bash"]
index 03f7494..90a578b 100644 (file)
@@ -85,9 +85,6 @@ RUN apt-get update && apt-get install -t jessie-backports -y cmake && apt-get cl
 
 RUN mkdir /var/local/jenkins
 
-#================
-# libuv
-RUN cd /tmp     && wget http://dist.libuv.org/dist/v1.9.1/libuv-v1.9.1.tar.gz     && tar -xf libuv-v1.9.1.tar.gz     && cd libuv-v1.9.1     && sh autogen.sh && ./configure --prefix=/usr && make && make install
 
 # Install gcc-4.9 and other relevant items
 RUN apt-get update && apt-get -y install gcc gcc-multilib g++ g++-multilib && apt-get clean
diff --git a/tools/dockerfile/test/cxx_ubuntu1804_x64/Dockerfile b/tools/dockerfile/test/cxx_ubuntu1804_x64/Dockerfile
deleted file mode 100644 (file)
index 8201224..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-# Copyright 2015 gRPC authors.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-FROM ubuntu:18.04
-
-# Install Git and basic packages.
-RUN apt-get update && apt-get install -y \
-  autoconf \
-  autotools-dev \
-  build-essential \
-  bzip2 \
-  ccache \
-  curl \
-  dnsutils \
-  gcc \
-  gcc-multilib \
-  git \
-  golang \
-  gyp \
-  lcov \
-  libc6 \
-  libc6-dbg \
-  libc6-dev \
-  libgtest-dev \
-  libtool \
-  make \
-  perl \
-  strace \
-  python-dev \
-  python-setuptools \
-  python-yaml \
-  telnet \
-  unzip \
-  wget \
-  zip && apt-get clean
-
-#================
-# Build profiling
-RUN apt-get update && apt-get install -y time && apt-get clean
-
-#====================
-# Python dependencies
-
-# Install dependencies
-
-RUN apt-get update && apt-get install -y \
-    python-all-dev \
-    python3-all-dev \
-    python-setuptools
-
-# Install Python packages from PyPI
-RUN curl https://bootstrap.pypa.io/pip/2.7/get-pip.py | python2.7
-RUN pip install --upgrade pip==19.3.1
-RUN pip install virtualenv==16.7.9
-RUN pip install futures==3.1.1 enum34==1.1.10 protobuf==3.5.2.post1 six==1.16.0 twisted==19.10.0
-
-# Google Cloud platform API libraries
-RUN pip install --upgrade google-auth==1.24.0 google-api-python-client==1.12.8 oauth2client==4.1.0
-
-#=================
-# C++ dependencies
-RUN apt-get update && apt-get -y install libgflags-dev libgtest-dev libc++-dev clang && apt-get clean
-
-#=================
-# Install cmake
-# Note that this step should be only used for distributions that have new enough cmake to satisfy gRPC's cmake version requirement.
-
-RUN apt-get update && apt-get install -y cmake && apt-get clean
-
-
-RUN mkdir /var/local/jenkins
-
-
-# Define the default command.
-CMD ["bash"]
diff --git a/tools/dockerfile/test/php7_debian9_x64/Dockerfile b/tools/dockerfile/test/php7_debian9_x64/Dockerfile
new file mode 100644 (file)
index 0000000..c2c99f7
--- /dev/null
@@ -0,0 +1,85 @@
+# 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.
+
+FROM debian:9
+
+
+#=================
+# PHP7 dependencies
+
+# Install Git and basic packages.
+RUN apt-get update && apt-get install -y \
+  autoconf \
+  automake \
+  build-essential \
+  ccache \
+  curl \
+  git \
+  libbison-dev \
+  libcurl4-openssl-dev \
+  libgmp-dev \
+  libgmp3-dev \
+  libssl-dev \
+  libtool \
+  libxml2-dev \
+  pkg-config \
+  re2c \
+  time \
+  unzip \
+  wget \
+  zip \
+  zlib1g-dev && apt-get clean
+
+# Compile PHP7 from source
+RUN git clone https://github.com/php/php-src /var/local/git/php-src
+RUN cd /var/local/git/php-src \
+  && git checkout PHP-7.2.34 \
+  && ./buildconf --force \
+  && ./configure \
+  --with-gmp \
+  --with-openssl \
+  --with-zlib \
+  && make -j$(nproc) \
+  && make install
+
+#====================
+# Python dependencies
+
+# Install dependencies
+
+RUN apt-get update && apt-get install -y \
+    python-all-dev \
+    python3-all-dev \
+    python-setuptools
+
+# Install Python packages from PyPI
+RUN curl https://bootstrap.pypa.io/pip/2.7/get-pip.py | python2.7
+RUN pip install --upgrade pip==19.3.1
+RUN pip install virtualenv==16.7.9
+RUN pip install futures==3.1.1 enum34==1.1.10 protobuf==3.5.2.post1 six==1.16.0 twisted==19.10.0
+
+# Google Cloud platform API libraries
+RUN pip install --upgrade google-auth==1.24.0 google-api-python-client==1.12.8 oauth2client==4.1.0
+
+#=================     
+# PHP Test dependencies        
+
+ RUN apt-get update && apt-get install -y \    
+    valgrind
+
+
+RUN mkdir /var/local/jenkins
+
+# Define the default command.
+CMD ["bash"]
diff --git a/tools/dockerfile/test/php7_jessie_x64/Dockerfile b/tools/dockerfile/test/php7_jessie_x64/Dockerfile
deleted file mode 100644 (file)
index db91aaa..0000000
+++ /dev/null
@@ -1,93 +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.
-
-FROM debian:8
-
-
-#=================
-# PHP7 dependencies
-
-# Install Git and basic packages.
-RUN apt-get update && apt-get install -y \
-  autoconf \
-  automake \
-  build-essential \
-  ccache \
-  curl \
-  git \
-  libcurl4-openssl-dev \
-  libgmp-dev \
-  libgmp3-dev \
-  libssl-dev \
-  libtool \
-  libxml2-dev \
-  pkg-config \
-  re2c \
-  time \
-  unzip \
-  wget \
-  zip && apt-get clean
-
-# Install other dependencies
-RUN ln -sf /usr/include/x86_64-linux-gnu/gmp.h /usr/include/gmp.h
-RUN wget http://ftp.gnu.org/gnu/bison/bison-3.4.2.tar.gz -O /var/local/bison-3.4.2.tar.gz
-RUN cd /var/local \
-  && tar -zxvf bison-3.4.2.tar.gz \
-  && cd /var/local/bison-3.4.2 \
-  && ./configure \
-  && make \
-  && make install
-
-# Compile PHP7 from source
-RUN git clone https://github.com/php/php-src /var/local/git/php-src
-RUN cd /var/local/git/php-src \
-  && git checkout PHP-7.2.22 \
-  && ./buildconf --force \
-  && ./configure \
-  --with-gmp \
-  --with-openssl \
-  --with-zlib \
-  && make \
-  && make install
-
-#====================
-# Python dependencies
-
-# Install dependencies
-
-RUN apt-get update && apt-get install -y \
-    python-all-dev \
-    python3-all-dev \
-    python-setuptools
-
-# Install Python packages from PyPI
-RUN curl https://bootstrap.pypa.io/pip/2.7/get-pip.py | python2.7
-RUN pip install --upgrade pip==19.3.1
-RUN pip install virtualenv==16.7.9
-RUN pip install futures==3.1.1 enum34==1.1.10 protobuf==3.5.2.post1 six==1.16.0 twisted==19.10.0
-
-# Google Cloud platform API libraries
-RUN pip install --upgrade google-auth==1.24.0 google-api-python-client==1.12.8 oauth2client==4.1.0
-
-#=================     
-# PHP Test dependencies        
-
- RUN apt-get update && apt-get install -y \    
-    valgrind
-
-
-RUN mkdir /var/local/jenkins
-
-# Define the default command.
-CMD ["bash"]
index eecb297..f9af142 100644 (file)
@@ -30,12 +30,15 @@ RUN apk update && apk add \
   make \
   perl \
   strace \
-  python2-dev \
-  py2-pip \
+  python3-dev \
+  py3-pip \
   unzip \
   wget \
   zip
 
+RUN ln -s /usr/bin/pip3 /usr/bin/pip
+RUN ln -s /usr/bin/python3 /usr/bin/python
+
 # Install Python packages from PyPI
 RUN pip install --upgrade pip==19.3.1
 RUN pip install virtualenv
index 10ef23a..ec21345 100644 (file)
@@ -101,7 +101,7 @@ ENV CLANG_TIDY=clang-tidy-11
 # Bazel installation
 
 # Must be in sync with tools/bazel
-ENV BAZEL_VERSION 3.7.1
+ENV BAZEL_VERSION 4.2.1
 
 # The correct bazel version is already preinstalled, no need to use //tools/bazel wrapper.
 ENV DISABLE_BAZEL_WRAPPER 1
index d33914f..f7cd561 100644 (file)
@@ -40,7 +40,7 @@ PROJECT_NAME           = "GRPC C++"
 # could be handy for archiving the generated documentation or if some version
 # control system is used.
 
-PROJECT_NUMBER         = 1.41.1
+PROJECT_NUMBER         = 1.42.0
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description
 # for a project that appears at the top of each page and should give viewer a
@@ -883,8 +883,9 @@ include/grpc/census.h \
 include/grpc/compression.h \
 include/grpc/event_engine/endpoint_config.h \
 include/grpc/event_engine/event_engine.h \
+include/grpc/event_engine/internal/memory_allocator_impl.h \
+include/grpc/event_engine/memory_allocator.h \
 include/grpc/event_engine/port.h \
-include/grpc/event_engine/slice_allocator.h \
 include/grpc/fork.h \
 include/grpc/grpc.h \
 include/grpc/grpc_posix.h \
@@ -941,6 +942,7 @@ include/grpcpp/channel.h \
 include/grpcpp/client_context.h \
 include/grpcpp/completion_queue.h \
 include/grpcpp/create_channel.h \
+include/grpcpp/create_channel_binder.h \
 include/grpcpp/create_channel_posix.h \
 include/grpcpp/ext/health_check_service_server_builder_option.h \
 include/grpcpp/generic/async_generic_service.h \
@@ -1014,6 +1016,8 @@ include/grpcpp/resource_quota.h \
 include/grpcpp/security/auth_context.h \
 include/grpcpp/security/auth_metadata_processor.h \
 include/grpcpp/security/authorization_policy_provider.h \
+include/grpcpp/security/binder_credentials.h \
+include/grpcpp/security/binder_security_policy.h \
 include/grpcpp/security/credentials.h \
 include/grpcpp/security/server_credentials.h \
 include/grpcpp/security/tls_certificate_provider.h \
index 90657ac..c0f58c1 100644 (file)
@@ -40,7 +40,7 @@ PROJECT_NAME           = "GRPC C++"
 # could be handy for archiving the generated documentation or if some version
 # control system is used.
 
-PROJECT_NUMBER         = 1.41.1
+PROJECT_NUMBER         = 1.42.0
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description
 # for a project that appears at the top of each page and should give viewer a
@@ -883,8 +883,9 @@ include/grpc/census.h \
 include/grpc/compression.h \
 include/grpc/event_engine/endpoint_config.h \
 include/grpc/event_engine/event_engine.h \
+include/grpc/event_engine/internal/memory_allocator_impl.h \
+include/grpc/event_engine/memory_allocator.h \
 include/grpc/event_engine/port.h \
-include/grpc/event_engine/slice_allocator.h \
 include/grpc/fork.h \
 include/grpc/grpc.h \
 include/grpc/grpc_posix.h \
@@ -941,6 +942,7 @@ include/grpcpp/channel.h \
 include/grpcpp/client_context.h \
 include/grpcpp/completion_queue.h \
 include/grpcpp/create_channel.h \
+include/grpcpp/create_channel_binder.h \
 include/grpcpp/create_channel_posix.h \
 include/grpcpp/ext/health_check_service_server_builder_option.h \
 include/grpcpp/generic/async_generic_service.h \
@@ -1014,6 +1016,8 @@ include/grpcpp/resource_quota.h \
 include/grpcpp/security/auth_context.h \
 include/grpcpp/security/auth_metadata_processor.h \
 include/grpcpp/security/authorization_policy_provider.h \
+include/grpcpp/security/binder_credentials.h \
+include/grpcpp/security/binder_security_policy.h \
 include/grpcpp/security/credentials.h \
 include/grpcpp/security/server_credentials.h \
 include/grpcpp/security/tls_certificate_provider.h \
@@ -1093,6 +1097,7 @@ src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc \
 src/core/ext/filters/client_channel/lb_policy/priority/priority.cc \
 src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc \
 src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.h \
+src/core/ext/filters/client_channel/lb_policy/rls/rls.cc \
 src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc \
 src/core/ext/filters/client_channel/lb_policy/subchannel_list.h \
 src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc \
@@ -1112,6 +1117,7 @@ src/core/ext/filters/client_channel/proxy_mapper_registry.cc \
 src/core/ext/filters/client_channel/proxy_mapper_registry.h \
 src/core/ext/filters/client_channel/resolver.cc \
 src/core/ext/filters/client_channel/resolver.h \
+src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc \
 src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc \
 src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h \
 src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_event_engine.cc \
@@ -1144,18 +1150,15 @@ src/core/ext/filters/client_channel/retry_throttle.cc \
 src/core/ext/filters/client_channel/retry_throttle.h \
 src/core/ext/filters/client_channel/server_address.cc \
 src/core/ext/filters/client_channel/server_address.h \
-src/core/ext/filters/client_channel/service_config.cc \
-src/core/ext/filters/client_channel/service_config.h \
-src/core/ext/filters/client_channel/service_config_call_data.h \
 src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc \
-src/core/ext/filters/client_channel/service_config_parser.cc \
-src/core/ext/filters/client_channel/service_config_parser.h \
 src/core/ext/filters/client_channel/subchannel.cc \
 src/core/ext/filters/client_channel/subchannel.h \
 src/core/ext/filters/client_channel/subchannel_interface.h \
 src/core/ext/filters/client_channel/subchannel_pool_interface.cc \
 src/core/ext/filters/client_channel/subchannel_pool_interface.h \
 src/core/ext/filters/client_idle/client_idle_filter.cc \
+src/core/ext/filters/client_idle/idle_filter_state.cc \
+src/core/ext/filters/client_idle/idle_filter_state.h \
 src/core/ext/filters/deadline/deadline_filter.cc \
 src/core/ext/filters/deadline/deadline_filter.h \
 src/core/ext/filters/fault_injection/fault_injection_filter.cc \
@@ -1177,14 +1180,48 @@ src/core/ext/filters/max_age/max_age_filter.cc \
 src/core/ext/filters/max_age/max_age_filter.h \
 src/core/ext/filters/message_size/message_size_filter.cc \
 src/core/ext/filters/message_size/message_size_filter.h \
-src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc \
-src/core/ext/filters/workarounds/workaround_cronet_compression_filter.h \
-src/core/ext/filters/workarounds/workaround_utils.cc \
-src/core/ext/filters/workarounds/workaround_utils.h \
+src/core/ext/service_config/service_config.cc \
+src/core/ext/service_config/service_config.h \
+src/core/ext/service_config/service_config_call_data.h \
+src/core/ext/service_config/service_config_parser.cc \
+src/core/ext/service_config/service_config_parser.h \
+src/core/ext/transport/binder/client/binder_connector.cc \
+src/core/ext/transport/binder/client/binder_connector.h \
+src/core/ext/transport/binder/client/channel_create.cc \
+src/core/ext/transport/binder/client/channel_create_impl.cc \
+src/core/ext/transport/binder/client/channel_create_impl.h \
+src/core/ext/transport/binder/client/connection_id_generator.cc \
+src/core/ext/transport/binder/client/connection_id_generator.h \
+src/core/ext/transport/binder/client/endpoint_binder_pool.cc \
+src/core/ext/transport/binder/client/endpoint_binder_pool.h \
+src/core/ext/transport/binder/client/jni_utils.cc \
+src/core/ext/transport/binder/client/jni_utils.h \
+src/core/ext/transport/binder/client/security_policy_setting.cc \
+src/core/ext/transport/binder/client/security_policy_setting.h \
+src/core/ext/transport/binder/security_policy/binder_security_policy.cc \
+src/core/ext/transport/binder/server/binder_server.cc \
+src/core/ext/transport/binder/server/binder_server.h \
+src/core/ext/transport/binder/server/binder_server_credentials.cc \
+src/core/ext/transport/binder/transport/binder_stream.h \
+src/core/ext/transport/binder/transport/binder_transport.cc \
+src/core/ext/transport/binder/transport/binder_transport.h \
+src/core/ext/transport/binder/utils/transport_stream_receiver.h \
+src/core/ext/transport/binder/utils/transport_stream_receiver_impl.cc \
+src/core/ext/transport/binder/utils/transport_stream_receiver_impl.h \
+src/core/ext/transport/binder/wire_format/binder.h \
+src/core/ext/transport/binder/wire_format/binder_android.cc \
+src/core/ext/transport/binder/wire_format/binder_android.h \
+src/core/ext/transport/binder/wire_format/binder_constants.cc \
+src/core/ext/transport/binder/wire_format/binder_constants.h \
+src/core/ext/transport/binder/wire_format/transaction.cc \
+src/core/ext/transport/binder/wire_format/transaction.h \
+src/core/ext/transport/binder/wire_format/wire_reader.h \
+src/core/ext/transport/binder/wire_format/wire_reader_impl.cc \
+src/core/ext/transport/binder/wire_format/wire_reader_impl.h \
+src/core/ext/transport/binder/wire_format/wire_writer.cc \
+src/core/ext/transport/binder/wire_format/wire_writer.h \
 src/core/ext/transport/chttp2/alpn/alpn.cc \
 src/core/ext/transport/chttp2/alpn/alpn.h \
-src/core/ext/transport/chttp2/client/authority.cc \
-src/core/ext/transport/chttp2/client/authority.h \
 src/core/ext/transport/chttp2/client/chttp2_connector.cc \
 src/core/ext/transport/chttp2/client/chttp2_connector.h \
 src/core/ext/transport/chttp2/client/insecure/channel_create.cc \
@@ -1200,8 +1237,6 @@ src/core/ext/transport/chttp2/transport/bin_decoder.h \
 src/core/ext/transport/chttp2/transport/bin_encoder.cc \
 src/core/ext/transport/chttp2/transport/bin_encoder.h \
 src/core/ext/transport/chttp2/transport/chttp2_plugin.cc \
-src/core/ext/transport/chttp2/transport/chttp2_slice_allocator.cc \
-src/core/ext/transport/chttp2/transport/chttp2_slice_allocator.h \
 src/core/ext/transport/chttp2/transport/chttp2_transport.cc \
 src/core/ext/transport/chttp2/transport/chttp2_transport.h \
 src/core/ext/transport/chttp2/transport/context_list.cc \
@@ -1237,8 +1272,6 @@ src/core/ext/transport/chttp2/transport/http2_settings.cc \
 src/core/ext/transport/chttp2/transport/http2_settings.h \
 src/core/ext/transport/chttp2/transport/huffsyms.cc \
 src/core/ext/transport/chttp2/transport/huffsyms.h \
-src/core/ext/transport/chttp2/transport/incoming_metadata.cc \
-src/core/ext/transport/chttp2/transport/incoming_metadata.h \
 src/core/ext/transport/chttp2/transport/internal.h \
 src/core/ext/transport/chttp2/transport/parsing.cc \
 src/core/ext/transport/chttp2/transport/popularity_count.h \
@@ -1427,6 +1460,8 @@ src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.c \
 src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.h \
 src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c \
 src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.h \
+src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls.upb.c \
+src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls.upb.h \
 src/core/ext/upb-generated/udpa/annotations/migrate.upb.c \
 src/core/ext/upb-generated/udpa/annotations/migrate.upb.h \
 src/core/ext/upb-generated/udpa/annotations/security.upb.c \
@@ -1437,12 +1472,10 @@ src/core/ext/upb-generated/udpa/annotations/status.upb.c \
 src/core/ext/upb-generated/udpa/annotations/status.upb.h \
 src/core/ext/upb-generated/udpa/annotations/versioning.upb.c \
 src/core/ext/upb-generated/udpa/annotations/versioning.upb.h \
-src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c \
-src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h \
-src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.c \
-src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.h \
 src/core/ext/upb-generated/validate/validate.upb.c \
 src/core/ext/upb-generated/validate/validate.upb.h \
+src/core/ext/upb-generated/xds/annotations/v3/status.upb.c \
+src/core/ext/upb-generated/xds/annotations/v3/status.upb.h \
 src/core/ext/upb-generated/xds/core/v3/authority.upb.c \
 src/core/ext/upb-generated/xds/core/v3/authority.upb.h \
 src/core/ext/upb-generated/xds/core/v3/collection_entry.upb.c \
@@ -1455,6 +1488,10 @@ src/core/ext/upb-generated/xds/core/v3/resource_locator.upb.c \
 src/core/ext/upb-generated/xds/core/v3/resource_locator.upb.h \
 src/core/ext/upb-generated/xds/core/v3/resource_name.upb.c \
 src/core/ext/upb-generated/xds/core/v3/resource_name.upb.h \
+src/core/ext/upb-generated/xds/data/orca/v3/orca_load_report.upb.c \
+src/core/ext/upb-generated/xds/data/orca/v3/orca_load_report.upb.h \
+src/core/ext/upb-generated/xds/type/v3/typed_struct.upb.c \
+src/core/ext/upb-generated/xds/type/v3/typed_struct.upb.h \
 src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.c \
 src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.h \
 src/core/ext/upbdefs-generated/envoy/annotations/deprecation.upbdefs.c \
@@ -1625,10 +1662,10 @@ src/core/ext/upbdefs-generated/udpa/annotations/status.upbdefs.c \
 src/core/ext/upbdefs-generated/udpa/annotations/status.upbdefs.h \
 src/core/ext/upbdefs-generated/udpa/annotations/versioning.upbdefs.c \
 src/core/ext/upbdefs-generated/udpa/annotations/versioning.upbdefs.h \
-src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.c \
-src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.h \
 src/core/ext/upbdefs-generated/validate/validate.upbdefs.c \
 src/core/ext/upbdefs-generated/validate/validate.upbdefs.h \
+src/core/ext/upbdefs-generated/xds/annotations/v3/status.upbdefs.c \
+src/core/ext/upbdefs-generated/xds/annotations/v3/status.upbdefs.h \
 src/core/ext/upbdefs-generated/xds/core/v3/authority.upbdefs.c \
 src/core/ext/upbdefs-generated/xds/core/v3/authority.upbdefs.h \
 src/core/ext/upbdefs-generated/xds/core/v3/collection_entry.upbdefs.c \
@@ -1641,6 +1678,8 @@ src/core/ext/upbdefs-generated/xds/core/v3/resource_locator.upbdefs.c \
 src/core/ext/upbdefs-generated/xds/core/v3/resource_locator.upbdefs.h \
 src/core/ext/upbdefs-generated/xds/core/v3/resource_name.upbdefs.c \
 src/core/ext/upbdefs-generated/xds/core/v3/resource_name.upbdefs.h \
+src/core/ext/upbdefs-generated/xds/type/v3/typed_struct.upbdefs.c \
+src/core/ext/upbdefs-generated/xds/type/v3/typed_struct.upbdefs.h \
 src/core/ext/xds/certificate_provider_factory.h \
 src/core/ext/xds/certificate_provider_registry.cc \
 src/core/ext/xds/certificate_provider_registry.h \
@@ -1655,6 +1694,8 @@ src/core/ext/xds/xds_bootstrap.h \
 src/core/ext/xds/xds_certificate_provider.cc \
 src/core/ext/xds/xds_certificate_provider.h \
 src/core/ext/xds/xds_channel_args.h \
+src/core/ext/xds/xds_channel_stack_modifier.cc \
+src/core/ext/xds/xds_channel_stack_modifier.h \
 src/core/ext/xds/xds_client.cc \
 src/core/ext/xds/xds_client.h \
 src/core/ext/xds/xds_client_stats.cc \
@@ -1767,6 +1808,7 @@ src/core/lib/gprpp/arena.cc \
 src/core/lib/gprpp/arena.h \
 src/core/lib/gprpp/atomic_utils.h \
 src/core/lib/gprpp/bitset.h \
+src/core/lib/gprpp/chunked_vector.h \
 src/core/lib/gprpp/construct_destruct.h \
 src/core/lib/gprpp/debug_location.h \
 src/core/lib/gprpp/dual_ref_counted.h \
@@ -1796,6 +1838,7 @@ src/core/lib/gprpp/stat_windows.cc \
 src/core/lib/gprpp/status_helper.cc \
 src/core/lib/gprpp/status_helper.h \
 src/core/lib/gprpp/sync.h \
+src/core/lib/gprpp/table.h \
 src/core/lib/gprpp/thd.h \
 src/core/lib/gprpp/thd_posix.cc \
 src/core/lib/gprpp/thd_windows.cc \
@@ -1969,8 +2012,6 @@ src/core/lib/iomgr/timer_heap.cc \
 src/core/lib/iomgr/timer_heap.h \
 src/core/lib/iomgr/timer_manager.cc \
 src/core/lib/iomgr/timer_manager.h \
-src/core/lib/iomgr/udp_server.cc \
-src/core/lib/iomgr/udp_server.h \
 src/core/lib/iomgr/unix_sockets_posix.cc \
 src/core/lib/iomgr/unix_sockets_posix.h \
 src/core/lib/iomgr/unix_sockets_posix_noop.cc \
@@ -2099,14 +2140,24 @@ src/core/lib/slice/b64.h \
 src/core/lib/slice/percent_encoding.cc \
 src/core/lib/slice/percent_encoding.h \
 src/core/lib/slice/slice.cc \
+src/core/lib/slice/slice_api.cc \
 src/core/lib/slice/slice_buffer.cc \
 src/core/lib/slice/slice_intern.cc \
 src/core/lib/slice/slice_internal.h \
+src/core/lib/slice/slice_refcount.cc \
+src/core/lib/slice/slice_refcount.h \
+src/core/lib/slice/slice_refcount_base.h \
+src/core/lib/slice/slice_split.cc \
+src/core/lib/slice/slice_split.h \
 src/core/lib/slice/slice_string_helpers.cc \
 src/core/lib/slice/slice_string_helpers.h \
 src/core/lib/slice/slice_utils.h \
+src/core/lib/slice/static_slice.cc \
+src/core/lib/slice/static_slice.h \
 src/core/lib/surface/api_trace.cc \
 src/core/lib/surface/api_trace.h \
+src/core/lib/surface/builtins.cc \
+src/core/lib/surface/builtins.h \
 src/core/lib/surface/byte_buffer.cc \
 src/core/lib/surface/byte_buffer_reader.cc \
 src/core/lib/surface/call.cc \
@@ -2138,8 +2189,6 @@ src/core/lib/surface/server.h \
 src/core/lib/surface/validate_metadata.cc \
 src/core/lib/surface/validate_metadata.h \
 src/core/lib/surface/version.cc \
-src/core/lib/transport/authority_override.cc \
-src/core/lib/transport/authority_override.h \
 src/core/lib/transport/bdp_estimator.cc \
 src/core/lib/transport/bdp_estimator.h \
 src/core/lib/transport/byte_stream.cc \
@@ -2153,6 +2202,7 @@ src/core/lib/transport/metadata.cc \
 src/core/lib/transport/metadata.h \
 src/core/lib/transport/metadata_batch.cc \
 src/core/lib/transport/metadata_batch.h \
+src/core/lib/transport/parsed_metadata.h \
 src/core/lib/transport/pid_controller.cc \
 src/core/lib/transport/pid_controller.h \
 src/core/lib/transport/static_metadata.cc \
index b03a777..33635c4 100644 (file)
@@ -40,7 +40,7 @@ PROJECT_NAME           = "GRPC Core"
 # could be handy for archiving the generated documentation or if some version
 # control system is used.
 
-PROJECT_NUMBER         = 19.0.0
+PROJECT_NUMBER         = 20.0.0
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description
 # for a project that appears at the top of each page and should give viewer a
@@ -813,8 +813,9 @@ include/grpc/census.h \
 include/grpc/compression.h \
 include/grpc/event_engine/endpoint_config.h \
 include/grpc/event_engine/event_engine.h \
+include/grpc/event_engine/internal/memory_allocator_impl.h \
+include/grpc/event_engine/memory_allocator.h \
 include/grpc/event_engine/port.h \
-include/grpc/event_engine/slice_allocator.h \
 include/grpc/fork.h \
 include/grpc/grpc.h \
 include/grpc/grpc_posix.h \
index aff4e8f..a7d456f 100644 (file)
@@ -40,7 +40,7 @@ PROJECT_NAME           = "GRPC Core"
 # could be handy for archiving the generated documentation or if some version
 # control system is used.
 
-PROJECT_NUMBER         = 19.0.0
+PROJECT_NUMBER         = 20.0.0
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description
 # for a project that appears at the top of each page and should give viewer a
@@ -813,8 +813,9 @@ include/grpc/census.h \
 include/grpc/compression.h \
 include/grpc/event_engine/endpoint_config.h \
 include/grpc/event_engine/event_engine.h \
+include/grpc/event_engine/internal/memory_allocator_impl.h \
+include/grpc/event_engine/memory_allocator.h \
 include/grpc/event_engine/port.h \
-include/grpc/event_engine/slice_allocator.h \
 include/grpc/fork.h \
 include/grpc/grpc.h \
 include/grpc/grpc_posix.h \
@@ -917,6 +918,7 @@ src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc \
 src/core/ext/filters/client_channel/lb_policy/priority/priority.cc \
 src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc \
 src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.h \
+src/core/ext/filters/client_channel/lb_policy/rls/rls.cc \
 src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc \
 src/core/ext/filters/client_channel/lb_policy/subchannel_list.h \
 src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc \
@@ -937,6 +939,8 @@ src/core/ext/filters/client_channel/proxy_mapper_registry.h \
 src/core/ext/filters/client_channel/resolver.cc \
 src/core/ext/filters/client_channel/resolver.h \
 src/core/ext/filters/client_channel/resolver/README.md \
+src/core/ext/filters/client_channel/resolver/binder/README.md \
+src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc \
 src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc \
 src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h \
 src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_event_engine.cc \
@@ -971,18 +975,15 @@ src/core/ext/filters/client_channel/retry_throttle.cc \
 src/core/ext/filters/client_channel/retry_throttle.h \
 src/core/ext/filters/client_channel/server_address.cc \
 src/core/ext/filters/client_channel/server_address.h \
-src/core/ext/filters/client_channel/service_config.cc \
-src/core/ext/filters/client_channel/service_config.h \
-src/core/ext/filters/client_channel/service_config_call_data.h \
 src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc \
-src/core/ext/filters/client_channel/service_config_parser.cc \
-src/core/ext/filters/client_channel/service_config_parser.h \
 src/core/ext/filters/client_channel/subchannel.cc \
 src/core/ext/filters/client_channel/subchannel.h \
 src/core/ext/filters/client_channel/subchannel_interface.h \
 src/core/ext/filters/client_channel/subchannel_pool_interface.cc \
 src/core/ext/filters/client_channel/subchannel_pool_interface.h \
 src/core/ext/filters/client_idle/client_idle_filter.cc \
+src/core/ext/filters/client_idle/idle_filter_state.cc \
+src/core/ext/filters/client_idle/idle_filter_state.h \
 src/core/ext/filters/deadline/deadline_filter.cc \
 src/core/ext/filters/deadline/deadline_filter.h \
 src/core/ext/filters/fault_injection/fault_injection_filter.cc \
@@ -1004,17 +1005,16 @@ src/core/ext/filters/max_age/max_age_filter.cc \
 src/core/ext/filters/max_age/max_age_filter.h \
 src/core/ext/filters/message_size/message_size_filter.cc \
 src/core/ext/filters/message_size/message_size_filter.h \
-src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc \
-src/core/ext/filters/workarounds/workaround_cronet_compression_filter.h \
-src/core/ext/filters/workarounds/workaround_utils.cc \
-src/core/ext/filters/workarounds/workaround_utils.h \
+src/core/ext/service_config/service_config.cc \
+src/core/ext/service_config/service_config.h \
+src/core/ext/service_config/service_config_call_data.h \
+src/core/ext/service_config/service_config_parser.cc \
+src/core/ext/service_config/service_config_parser.h \
 src/core/ext/transport/README.md \
 src/core/ext/transport/binder/README.md \
 src/core/ext/transport/chttp2/README.md \
 src/core/ext/transport/chttp2/alpn/alpn.cc \
 src/core/ext/transport/chttp2/alpn/alpn.h \
-src/core/ext/transport/chttp2/client/authority.cc \
-src/core/ext/transport/chttp2/client/authority.h \
 src/core/ext/transport/chttp2/client/chttp2_connector.cc \
 src/core/ext/transport/chttp2/client/chttp2_connector.h \
 src/core/ext/transport/chttp2/client/insecure/README.md \
@@ -1035,8 +1035,6 @@ src/core/ext/transport/chttp2/transport/bin_decoder.h \
 src/core/ext/transport/chttp2/transport/bin_encoder.cc \
 src/core/ext/transport/chttp2/transport/bin_encoder.h \
 src/core/ext/transport/chttp2/transport/chttp2_plugin.cc \
-src/core/ext/transport/chttp2/transport/chttp2_slice_allocator.cc \
-src/core/ext/transport/chttp2/transport/chttp2_slice_allocator.h \
 src/core/ext/transport/chttp2/transport/chttp2_transport.cc \
 src/core/ext/transport/chttp2/transport/chttp2_transport.h \
 src/core/ext/transport/chttp2/transport/context_list.cc \
@@ -1072,8 +1070,6 @@ src/core/ext/transport/chttp2/transport/http2_settings.cc \
 src/core/ext/transport/chttp2/transport/http2_settings.h \
 src/core/ext/transport/chttp2/transport/huffsyms.cc \
 src/core/ext/transport/chttp2/transport/huffsyms.h \
-src/core/ext/transport/chttp2/transport/incoming_metadata.cc \
-src/core/ext/transport/chttp2/transport/incoming_metadata.h \
 src/core/ext/transport/chttp2/transport/internal.h \
 src/core/ext/transport/chttp2/transport/parsing.cc \
 src/core/ext/transport/chttp2/transport/popularity_count.h \
@@ -1262,6 +1258,8 @@ src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.c \
 src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.h \
 src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c \
 src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.h \
+src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls.upb.c \
+src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls.upb.h \
 src/core/ext/upb-generated/udpa/annotations/migrate.upb.c \
 src/core/ext/upb-generated/udpa/annotations/migrate.upb.h \
 src/core/ext/upb-generated/udpa/annotations/security.upb.c \
@@ -1272,12 +1270,10 @@ src/core/ext/upb-generated/udpa/annotations/status.upb.c \
 src/core/ext/upb-generated/udpa/annotations/status.upb.h \
 src/core/ext/upb-generated/udpa/annotations/versioning.upb.c \
 src/core/ext/upb-generated/udpa/annotations/versioning.upb.h \
-src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c \
-src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h \
-src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.c \
-src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.h \
 src/core/ext/upb-generated/validate/validate.upb.c \
 src/core/ext/upb-generated/validate/validate.upb.h \
+src/core/ext/upb-generated/xds/annotations/v3/status.upb.c \
+src/core/ext/upb-generated/xds/annotations/v3/status.upb.h \
 src/core/ext/upb-generated/xds/core/v3/authority.upb.c \
 src/core/ext/upb-generated/xds/core/v3/authority.upb.h \
 src/core/ext/upb-generated/xds/core/v3/collection_entry.upb.c \
@@ -1290,6 +1286,10 @@ src/core/ext/upb-generated/xds/core/v3/resource_locator.upb.c \
 src/core/ext/upb-generated/xds/core/v3/resource_locator.upb.h \
 src/core/ext/upb-generated/xds/core/v3/resource_name.upb.c \
 src/core/ext/upb-generated/xds/core/v3/resource_name.upb.h \
+src/core/ext/upb-generated/xds/data/orca/v3/orca_load_report.upb.c \
+src/core/ext/upb-generated/xds/data/orca/v3/orca_load_report.upb.h \
+src/core/ext/upb-generated/xds/type/v3/typed_struct.upb.c \
+src/core/ext/upb-generated/xds/type/v3/typed_struct.upb.h \
 src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.c \
 src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.h \
 src/core/ext/upbdefs-generated/envoy/annotations/deprecation.upbdefs.c \
@@ -1460,10 +1460,10 @@ src/core/ext/upbdefs-generated/udpa/annotations/status.upbdefs.c \
 src/core/ext/upbdefs-generated/udpa/annotations/status.upbdefs.h \
 src/core/ext/upbdefs-generated/udpa/annotations/versioning.upbdefs.c \
 src/core/ext/upbdefs-generated/udpa/annotations/versioning.upbdefs.h \
-src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.c \
-src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.h \
 src/core/ext/upbdefs-generated/validate/validate.upbdefs.c \
 src/core/ext/upbdefs-generated/validate/validate.upbdefs.h \
+src/core/ext/upbdefs-generated/xds/annotations/v3/status.upbdefs.c \
+src/core/ext/upbdefs-generated/xds/annotations/v3/status.upbdefs.h \
 src/core/ext/upbdefs-generated/xds/core/v3/authority.upbdefs.c \
 src/core/ext/upbdefs-generated/xds/core/v3/authority.upbdefs.h \
 src/core/ext/upbdefs-generated/xds/core/v3/collection_entry.upbdefs.c \
@@ -1476,6 +1476,8 @@ src/core/ext/upbdefs-generated/xds/core/v3/resource_locator.upbdefs.c \
 src/core/ext/upbdefs-generated/xds/core/v3/resource_locator.upbdefs.h \
 src/core/ext/upbdefs-generated/xds/core/v3/resource_name.upbdefs.c \
 src/core/ext/upbdefs-generated/xds/core/v3/resource_name.upbdefs.h \
+src/core/ext/upbdefs-generated/xds/type/v3/typed_struct.upbdefs.c \
+src/core/ext/upbdefs-generated/xds/type/v3/typed_struct.upbdefs.h \
 src/core/ext/xds/certificate_provider_factory.h \
 src/core/ext/xds/certificate_provider_registry.cc \
 src/core/ext/xds/certificate_provider_registry.h \
@@ -1490,6 +1492,8 @@ src/core/ext/xds/xds_bootstrap.h \
 src/core/ext/xds/xds_certificate_provider.cc \
 src/core/ext/xds/xds_certificate_provider.h \
 src/core/ext/xds/xds_channel_args.h \
+src/core/ext/xds/xds_channel_stack_modifier.cc \
+src/core/ext/xds/xds_channel_stack_modifier.h \
 src/core/ext/xds/xds_client.cc \
 src/core/ext/xds/xds_client.h \
 src/core/ext/xds/xds_client_stats.cc \
@@ -1606,6 +1610,7 @@ src/core/lib/gprpp/arena.cc \
 src/core/lib/gprpp/arena.h \
 src/core/lib/gprpp/atomic_utils.h \
 src/core/lib/gprpp/bitset.h \
+src/core/lib/gprpp/chunked_vector.h \
 src/core/lib/gprpp/construct_destruct.h \
 src/core/lib/gprpp/debug_location.h \
 src/core/lib/gprpp/dual_ref_counted.h \
@@ -1635,6 +1640,7 @@ src/core/lib/gprpp/stat_windows.cc \
 src/core/lib/gprpp/status_helper.cc \
 src/core/lib/gprpp/status_helper.h \
 src/core/lib/gprpp/sync.h \
+src/core/lib/gprpp/table.h \
 src/core/lib/gprpp/thd.h \
 src/core/lib/gprpp/thd_posix.cc \
 src/core/lib/gprpp/thd_windows.cc \
@@ -1809,8 +1815,6 @@ src/core/lib/iomgr/timer_heap.cc \
 src/core/lib/iomgr/timer_heap.h \
 src/core/lib/iomgr/timer_manager.cc \
 src/core/lib/iomgr/timer_manager.h \
-src/core/lib/iomgr/udp_server.cc \
-src/core/lib/iomgr/udp_server.h \
 src/core/lib/iomgr/unix_sockets_posix.cc \
 src/core/lib/iomgr/unix_sockets_posix.h \
 src/core/lib/iomgr/unix_sockets_posix_noop.cc \
@@ -1939,15 +1943,25 @@ src/core/lib/slice/b64.h \
 src/core/lib/slice/percent_encoding.cc \
 src/core/lib/slice/percent_encoding.h \
 src/core/lib/slice/slice.cc \
+src/core/lib/slice/slice_api.cc \
 src/core/lib/slice/slice_buffer.cc \
 src/core/lib/slice/slice_intern.cc \
 src/core/lib/slice/slice_internal.h \
+src/core/lib/slice/slice_refcount.cc \
+src/core/lib/slice/slice_refcount.h \
+src/core/lib/slice/slice_refcount_base.h \
+src/core/lib/slice/slice_split.cc \
+src/core/lib/slice/slice_split.h \
 src/core/lib/slice/slice_string_helpers.cc \
 src/core/lib/slice/slice_string_helpers.h \
 src/core/lib/slice/slice_utils.h \
+src/core/lib/slice/static_slice.cc \
+src/core/lib/slice/static_slice.h \
 src/core/lib/surface/README.md \
 src/core/lib/surface/api_trace.cc \
 src/core/lib/surface/api_trace.h \
+src/core/lib/surface/builtins.cc \
+src/core/lib/surface/builtins.h \
 src/core/lib/surface/byte_buffer.cc \
 src/core/lib/surface/byte_buffer_reader.cc \
 src/core/lib/surface/call.cc \
@@ -1980,8 +1994,6 @@ src/core/lib/surface/validate_metadata.cc \
 src/core/lib/surface/validate_metadata.h \
 src/core/lib/surface/version.cc \
 src/core/lib/transport/README.md \
-src/core/lib/transport/authority_override.cc \
-src/core/lib/transport/authority_override.h \
 src/core/lib/transport/bdp_estimator.cc \
 src/core/lib/transport/bdp_estimator.h \
 src/core/lib/transport/byte_stream.cc \
@@ -1995,6 +2007,7 @@ src/core/lib/transport/metadata.cc \
 src/core/lib/transport/metadata.h \
 src/core/lib/transport/metadata_batch.cc \
 src/core/lib/transport/metadata_batch.h \
+src/core/lib/transport/parsed_metadata.h \
 src/core/lib/transport/pid_controller.cc \
 src/core/lib/transport/pid_controller.h \
 src/core/lib/transport/static_metadata.cc \
index dc7f267..f5e3629 100644 (file)
@@ -40,7 +40,7 @@ PROJECT_NAME           = "GRPC Objective-C"
 # could be handy for archiving the generated documentation or if some version
 # control system is used.
 
-PROJECT_NUMBER         = 1.41.1
+PROJECT_NUMBER         = 1.42.0
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description
 # for a project that appears at the top of each page and should give viewer a
index ca68d7c..27c8f51 100644 (file)
@@ -40,7 +40,7 @@ PROJECT_NAME           = "GRPC Objective-C"
 # could be handy for archiving the generated documentation or if some version
 # control system is used.
 
-PROJECT_NUMBER         = 1.41.1
+PROJECT_NUMBER         = 1.42.0
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description
 # for a project that appears at the top of each page and should give viewer a
index 4035c5e..3eac9f3 100644 (file)
@@ -40,7 +40,7 @@ PROJECT_NAME           = "GRPC PHP"
 # could be handy for archiving the generated documentation or if some version
 # control system is used.
 
-PROJECT_NUMBER         = 1.41.1
+PROJECT_NUMBER         = 1.42.0
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description
 # for a project that appears at the top of each page and should give viewer a
diff --git a/tools/fuzzer/build_and_run_fuzzer.sh b/tools/fuzzer/build_and_run_fuzzer.sh
deleted file mode 100755 (executable)
index 392998f..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/bin/bash
-# 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.
-#
-
-set -ex
-
-cd $(dirname $0)/../..
-make CONFIG=$config $1 -j3
-mkdir -p fuzzer_output
-export ASAN_OPTIONS=handle_abort=1
-. tools/fuzzer/runners/$1.sh
diff --git a/tools/fuzzer/options/client_fuzzer.options b/tools/fuzzer/options/client_fuzzer.options
deleted file mode 100644 (file)
index fd2eebf..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-[libfuzzer]
-max_len = 2048
-dict = hpack.dictionary
diff --git a/tools/fuzzer/options/fuzzer.options b/tools/fuzzer/options/fuzzer.options
deleted file mode 100644 (file)
index 5d468bc..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-[libfuzzer]
-max_len = 512
diff --git a/tools/fuzzer/options/fuzzer_response.options b/tools/fuzzer/options/fuzzer_response.options
deleted file mode 100644 (file)
index 5dcdfac..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-[libfuzzer]
-max_len = 128
diff --git a/tools/fuzzer/options/fuzzer_serverlist.options b/tools/fuzzer/options/fuzzer_serverlist.options
deleted file mode 100644 (file)
index 5dcdfac..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-[libfuzzer]
-max_len = 128
diff --git a/tools/fuzzer/options/hpack_parser_fuzzer_test.options b/tools/fuzzer/options/hpack_parser_fuzzer_test.options
deleted file mode 100644 (file)
index 584487f..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-[libfuzzer]
-max_len = 512
-dict = hpack.dictionary
diff --git a/tools/fuzzer/options/percent_decode_fuzzer.options b/tools/fuzzer/options/percent_decode_fuzzer.options
deleted file mode 100644 (file)
index ea2785e..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-[libfuzzer]
-max_len = 32
diff --git a/tools/fuzzer/options/percent_encode_fuzzer.options b/tools/fuzzer/options/percent_encode_fuzzer.options
deleted file mode 100644 (file)
index ea2785e..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-[libfuzzer]
-max_len = 32
diff --git a/tools/fuzzer/options/request_fuzzer.options b/tools/fuzzer/options/request_fuzzer.options
deleted file mode 100644 (file)
index fd32ac1..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-[libfuzzer]
-max_len = 2048
-
diff --git a/tools/fuzzer/options/response_fuzzer.options b/tools/fuzzer/options/response_fuzzer.options
deleted file mode 100644 (file)
index fd32ac1..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-[libfuzzer]
-max_len = 2048
-
diff --git a/tools/fuzzer/options/server_fuzzer.options b/tools/fuzzer/options/server_fuzzer.options
deleted file mode 100644 (file)
index fd2eebf..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-[libfuzzer]
-max_len = 2048
-dict = hpack.dictionary
diff --git a/tools/fuzzer/options/ssl_server_fuzzer.options b/tools/fuzzer/options/ssl_server_fuzzer.options
deleted file mode 100644 (file)
index 60bd9b0..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-[libfuzzer]
-max_len = 2048
diff --git a/tools/fuzzer/options/uri_fuzzer_test.options b/tools/fuzzer/options/uri_fuzzer_test.options
deleted file mode 100644 (file)
index 5dcdfac..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-[libfuzzer]
-max_len = 128
diff --git a/tools/fuzzer/runners/alts_credentials_fuzzer.sh b/tools/fuzzer/runners/alts_credentials_fuzzer.sh
deleted file mode 100644 (file)
index 3aaff6b..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/bin/bash
-# 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.
-#
-
-flags="-max_total_time=$runtime -artifact_prefix=fuzzer_output/ -max_len=2048 -timeout=120"
-
-
-if [ "$jobs" != "1" ]
-then
-  flags="-jobs=$jobs -workers=$jobs $flags"
-fi
-
-if [ "$config" == "asan-trace-cmp" ]
-then
-  flags="-use_traces=1 $flags"
-fi
-
-bins/$config/alts_credentials_fuzzer $flags fuzzer_output test/core/security/corpus/alts_credentials_corpus
diff --git a/tools/fuzzer/runners/client_fuzzer.sh b/tools/fuzzer/runners/client_fuzzer.sh
deleted file mode 100644 (file)
index 680e665..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/bin/bash
-# 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.
-#
-
-flags="-max_total_time=$runtime -artifact_prefix=fuzzer_output/ -max_len=2048 -timeout=120"
-
-flags="$flags -dict=test/core/end2end/fuzzers/hpack.dictionary"
-
-if [ "$jobs" != "1" ]
-then
-  flags="-jobs=$jobs -workers=$jobs $flags"
-fi
-
-if [ "$config" == "asan-trace-cmp" ]
-then
-  flags="-use_traces=1 $flags"
-fi
-
-bins/$config/client_fuzzer $flags fuzzer_output test/core/end2end/fuzzers/client_fuzzer_corpus
diff --git a/tools/fuzzer/runners/hpack_parser_fuzzer_test.sh b/tools/fuzzer/runners/hpack_parser_fuzzer_test.sh
deleted file mode 100644 (file)
index 53f0f8d..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/bin/bash
-# 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.
-#
-
-flags="-max_total_time=$runtime -artifact_prefix=fuzzer_output/ -max_len=512 -timeout=120"
-
-flags="$flags -dict=test/core/end2end/fuzzers/hpack.dictionary"
-
-if [ "$jobs" != "1" ]
-then
-  flags="-jobs=$jobs -workers=$jobs $flags"
-fi
-
-if [ "$config" == "asan-trace-cmp" ]
-then
-  flags="-use_traces=1 $flags"
-fi
-
-bins/$config/hpack_parser_fuzzer_test $flags fuzzer_output test/core/transport/chttp2/hpack_parser_corpus
diff --git a/tools/fuzzer/runners/http_request_fuzzer_test.sh b/tools/fuzzer/runners/http_request_fuzzer_test.sh
deleted file mode 100644 (file)
index e39b271..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/bin/bash
-# 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.
-#
-
-flags="-max_total_time=$runtime -artifact_prefix=fuzzer_output/ -max_len=2048 -timeout=120"
-
-
-if [ "$jobs" != "1" ]
-then
-  flags="-jobs=$jobs -workers=$jobs $flags"
-fi
-
-if [ "$config" == "asan-trace-cmp" ]
-then
-  flags="-use_traces=1 $flags"
-fi
-
-bins/$config/http_request_fuzzer_test $flags fuzzer_output test/core/http/request_corpus
diff --git a/tools/fuzzer/runners/http_response_fuzzer_test.sh b/tools/fuzzer/runners/http_response_fuzzer_test.sh
deleted file mode 100644 (file)
index df49ac1..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/bin/bash
-# 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.
-#
-
-flags="-max_total_time=$runtime -artifact_prefix=fuzzer_output/ -max_len=2048 -timeout=120"
-
-
-if [ "$jobs" != "1" ]
-then
-  flags="-jobs=$jobs -workers=$jobs $flags"
-fi
-
-if [ "$config" == "asan-trace-cmp" ]
-then
-  flags="-use_traces=1 $flags"
-fi
-
-bins/$config/http_response_fuzzer_test $flags fuzzer_output test/core/http/response_corpus
diff --git a/tools/fuzzer/runners/json_fuzzer_test.sh b/tools/fuzzer/runners/json_fuzzer_test.sh
deleted file mode 100644 (file)
index 5710983..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/bin/bash
-# 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.
-#
-
-flags="-max_total_time=$runtime -artifact_prefix=fuzzer_output/ -max_len=512 -timeout=120"
-
-
-if [ "$jobs" != "1" ]
-then
-  flags="-jobs=$jobs -workers=$jobs $flags"
-fi
-
-if [ "$config" == "asan-trace-cmp" ]
-then
-  flags="-use_traces=1 $flags"
-fi
-
-bins/$config/json_fuzzer_test $flags fuzzer_output test/core/json/corpus
diff --git a/tools/fuzzer/runners/nanopb_fuzzer_response_test.sh b/tools/fuzzer/runners/nanopb_fuzzer_response_test.sh
deleted file mode 100644 (file)
index d589019..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/bin/bash
-# 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.
-#
-
-flags="-max_total_time=$runtime -artifact_prefix=fuzzer_output/ -max_len=128 -timeout=120"
-
-
-if [ "$jobs" != "1" ]
-then
-  flags="-jobs=$jobs -workers=$jobs $flags"
-fi
-
-if [ "$config" == "asan-trace-cmp" ]
-then
-  flags="-use_traces=1 $flags"
-fi
-
-bins/$config/nanopb_fuzzer_response_test $flags fuzzer_output test/core/nanopb/corpus_response
diff --git a/tools/fuzzer/runners/nanopb_fuzzer_serverlist_test.sh b/tools/fuzzer/runners/nanopb_fuzzer_serverlist_test.sh
deleted file mode 100644 (file)
index 942a093..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/bin/bash
-# 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.
-#
-
-flags="-max_total_time=$runtime -artifact_prefix=fuzzer_output/ -max_len=128 -timeout=120"
-
-
-if [ "$jobs" != "1" ]
-then
-  flags="-jobs=$jobs -workers=$jobs $flags"
-fi
-
-if [ "$config" == "asan-trace-cmp" ]
-then
-  flags="-use_traces=1 $flags"
-fi
-
-bins/$config/nanopb_fuzzer_serverlist_test $flags fuzzer_output test/core/nanopb/corpus_serverlist
diff --git a/tools/fuzzer/runners/percent_decode_fuzzer.sh b/tools/fuzzer/runners/percent_decode_fuzzer.sh
deleted file mode 100644 (file)
index 96510b7..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/bin/bash
-# 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.
-#
-
-flags="-max_total_time=$runtime -artifact_prefix=fuzzer_output/ -max_len=32 -timeout=120"
-
-
-if [ "$jobs" != "1" ]
-then
-  flags="-jobs=$jobs -workers=$jobs $flags"
-fi
-
-if [ "$config" == "asan-trace-cmp" ]
-then
-  flags="-use_traces=1 $flags"
-fi
-
-bins/$config/percent_decode_fuzzer $flags fuzzer_output test/core/slice/percent_decode_corpus
diff --git a/tools/fuzzer/runners/percent_encode_fuzzer.sh b/tools/fuzzer/runners/percent_encode_fuzzer.sh
deleted file mode 100644 (file)
index dc1b596..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/bin/bash
-# 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.
-#
-
-flags="-max_total_time=$runtime -artifact_prefix=fuzzer_output/ -max_len=32 -timeout=120"
-
-
-if [ "$jobs" != "1" ]
-then
-  flags="-jobs=$jobs -workers=$jobs $flags"
-fi
-
-if [ "$config" == "asan-trace-cmp" ]
-then
-  flags="-use_traces=1 $flags"
-fi
-
-bins/$config/percent_encode_fuzzer $flags fuzzer_output test/core/slice/percent_encode_corpus
diff --git a/tools/fuzzer/runners/server_fuzzer.sh b/tools/fuzzer/runners/server_fuzzer.sh
deleted file mode 100644 (file)
index 410cf5c..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/bin/bash
-# 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.
-#
-
-flags="-max_total_time=$runtime -artifact_prefix=fuzzer_output/ -max_len=2048 -timeout=120"
-
-flags="$flags -dict=test/core/end2end/fuzzers/hpack.dictionary"
-
-if [ "$jobs" != "1" ]
-then
-  flags="-jobs=$jobs -workers=$jobs $flags"
-fi
-
-if [ "$config" == "asan-trace-cmp" ]
-then
-  flags="-use_traces=1 $flags"
-fi
-
-bins/$config/server_fuzzer $flags fuzzer_output test/core/end2end/fuzzers/server_fuzzer_corpus
diff --git a/tools/fuzzer/runners/ssl_server_fuzzer.sh b/tools/fuzzer/runners/ssl_server_fuzzer.sh
deleted file mode 100644 (file)
index 3a23f2d..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/bin/bash
-# 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.
-#
-
-flags="-max_total_time=$runtime -artifact_prefix=fuzzer_output/ -max_len=2048 -timeout=120"
-
-
-if [ "$jobs" != "1" ]
-then
-  flags="-jobs=$jobs -workers=$jobs $flags"
-fi
-
-if [ "$config" == "asan-trace-cmp" ]
-then
-  flags="-use_traces=1 $flags"
-fi
-
-bins/$config/ssl_server_fuzzer $flags fuzzer_output test/core/security/corpus/ssl_server_corpus
diff --git a/tools/fuzzer/runners/uri_fuzzer_test.sh b/tools/fuzzer/runners/uri_fuzzer_test.sh
deleted file mode 100644 (file)
index 467b72a..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/bin/bash
-# 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.
-#
-
-flags="-max_total_time=$runtime -artifact_prefix=fuzzer_output/ -max_len=128 -timeout=120"
-
-
-if [ "$jobs" != "1" ]
-then
-  flags="-jobs=$jobs -workers=$jobs $flags"
-fi
-
-if [ "$config" == "asan-trace-cmp" ]
-then
-  flags="-use_traces=1 $flags"
-fi
-
-bins/$config/uri_fuzzer_test $flags fuzzer_output test/core/uri/uri_corpus
diff --git a/tools/github/pr_latency.py b/tools/github/pr_latency.py
deleted file mode 100644 (file)
index afc6b9f..0000000
+++ /dev/null
@@ -1,211 +0,0 @@
-#!/usr/bin/env python
-# 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.
-"""Measure the time between PR creation and completion of all tests.
-
-You'll need a github API token to avoid being rate-limited. See
-https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/
-
-This script goes over the most recent 100 pull requests. For PRs with a single
-commit, it uses the PR's creation as the initial time; otherwise, it uses the
-date of the last commit. This is somewhat fragile, and imposed by the fact that
-GitHub reports a PR's updated timestamp for any event that modifies the PR (e.g.
-comments), not just the addition of new commits.
-
-In addition, it ignores latencies greater than five hours, as that's likely due
-to a manual re-run of tests.
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-from datetime import datetime
-from datetime import timedelta
-import json
-import logging
-import pprint
-
-import urllib2
-
-logging.basicConfig(format='%(asctime)s %(message)s')
-
-PRS = 'https://api.github.com/repos/grpc/grpc/pulls?state=open&per_page=100'
-COMMITS = 'https://api.github.com/repos/grpc/grpc/pulls/{pr_number}/commits'
-
-
-def gh(url):
-    request = urllib2.Request(url)
-    if TOKEN:
-        request.add_header('Authorization', 'token {}'.format(TOKEN))
-    response = urllib2.urlopen(request)
-    return response.read()
-
-
-def print_csv_header():
-    print('pr,base_time,test_time,latency_seconds,successes,failures,errors')
-
-
-def output(pr,
-           base_time,
-           test_time,
-           diff_time,
-           successes,
-           failures,
-           errors,
-           mode='human'):
-    if mode == 'human':
-        print(
-            "PR #{} base time: {} UTC, Tests completed at: {} UTC. Latency: {}."
-            "\n\tSuccesses: {}, Failures: {}, Errors: {}".format(
-                pr, base_time, test_time, diff_time, successes, failures,
-                errors))
-    elif mode == 'csv':
-        print(','.join([
-            str(pr),
-            str(base_time),
-            str(test_time),
-            str(int((test_time - base_time).total_seconds())),
-            str(successes),
-            str(failures),
-            str(errors)
-        ]))
-
-
-def parse_timestamp(datetime_str):
-    return datetime.strptime(datetime_str, '%Y-%m-%dT%H:%M:%SZ')
-
-
-def to_posix_timestamp(dt):
-    return str((dt - datetime(1970, 1, 1)).total_seconds())
-
-
-def get_pr_data():
-    latest_prs = json.loads(gh(PRS))
-    res = [{
-        'number': pr['number'],
-        'created_at': parse_timestamp(pr['created_at']),
-        'updated_at': parse_timestamp(pr['updated_at']),
-        'statuses_url': pr['statuses_url']
-    } for pr in latest_prs]
-    return res
-
-
-def get_commits_data(pr_number):
-    commits = json.loads(gh(COMMITS.format(pr_number=pr_number)))
-    return {
-        'num_commits':
-            len(commits),
-        'most_recent_date':
-            parse_timestamp(commits[-1]['commit']['author']['date'])
-    }
-
-
-def get_status_data(statuses_url, system):
-    status_url = statuses_url.replace('statuses', 'status')
-    statuses = json.loads(gh(status_url + '?per_page=100'))
-    successes = 0
-    failures = 0
-    errors = 0
-    latest_datetime = None
-    if not statuses:
-        return None
-    if system == 'kokoro':
-        string_in_target_url = 'kokoro'
-    elif system == 'jenkins':
-        string_in_target_url = 'grpc-testing'
-    for status in statuses['statuses']:
-        if not status['target_url'] or string_in_target_url not in status[
-                'target_url']:
-            continue  # Ignore jenkins
-        if status['state'] == 'pending':
-            return None
-        elif status['state'] == 'success':
-            successes += 1
-        elif status['state'] == 'failure':
-            failures += 1
-        elif status['state'] == 'error':
-            errors += 1
-        if not latest_datetime:
-            latest_datetime = parse_timestamp(status['updated_at'])
-        else:
-            latest_datetime = max(latest_datetime,
-                                  parse_timestamp(status['updated_at']))
-    # First status is the most recent one.
-    if any([successes, failures, errors
-           ]) and sum([successes, failures, errors]) > 15:
-        return {
-            'latest_datetime': latest_datetime,
-            'successes': successes,
-            'failures': failures,
-            'errors': errors
-        }
-    else:
-        return None
-
-
-def build_args_parser():
-    import argparse
-    parser = argparse.ArgumentParser()
-    parser.add_argument('--format',
-                        type=str,
-                        choices=['human', 'csv'],
-                        default='human',
-                        help='Output format: are you a human or a machine?')
-    parser.add_argument('--system',
-                        type=str,
-                        choices=['jenkins', 'kokoro'],
-                        required=True,
-                        help='Consider only the given CI system')
-    parser.add_argument(
-        '--token',
-        type=str,
-        default='',
-        help='GitHub token to use its API with a higher rate limit')
-    return parser
-
-
-def main():
-    import sys
-    global TOKEN
-    args_parser = build_args_parser()
-    args = args_parser.parse_args()
-    TOKEN = args.token
-    if args.format == 'csv':
-        print_csv_header()
-    for pr_data in get_pr_data():
-        commit_data = get_commits_data(pr_data['number'])
-        # PR with a single commit -> use the PRs creation time.
-        # else -> use the latest commit's date.
-        base_timestamp = pr_data['updated_at']
-        if commit_data['num_commits'] > 1:
-            base_timestamp = commit_data['most_recent_date']
-        else:
-            base_timestamp = pr_data['created_at']
-        last_status = get_status_data(pr_data['statuses_url'], args.system)
-        if last_status:
-            diff = last_status['latest_datetime'] - base_timestamp
-            if diff < timedelta(hours=5):
-                output(pr_data['number'],
-                       base_timestamp,
-                       last_status['latest_datetime'],
-                       diff,
-                       last_status['successes'],
-                       last_status['failures'],
-                       last_status['errors'],
-                       mode=args.format)
-
-
-if __name__ == '__main__':
-    main()
index cce6400..8ec76fa 100644 (file)
@@ -1,4 +1,4 @@
-#!/bin/bash -ex
+#!/bin/bash
 # Copyright 2017 gRPC authors.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # limitations under the License.
 # Source this rc script to prepare the environment for macos builds
 
+# Print basic info about the mac worker
+echo "kokoro pool: \"$KOKORO_JOB_POOL\""
+echo "OS: $(sw_vers -productName) $(sw_vers -productVersion) $(sw_vers -buildVersion)"
+echo "CPU type: $(sysctl -n machdep.cpu.brand_string)"
+echo "CPU: $(sysctl -n machdep.cpu.vendor) $(uname -m) Family $(sysctl -n machdep.cpu.family) Model $(sysctl -n machdep.cpu.brand_string)"
+echo "CPU Cores: $(sysctl -n hw.ncpu)"
+echo "Memory: $(sysctl -n hw.memsize)"
+
+# Info on disk usage and mounted volumes
+mount
+df -h /tmpfs /
+
 # show original open file limit values
 launchctl limit maxfiles
 ulimit -a
@@ -61,16 +73,26 @@ then
   done
   [[ "$gpg_recv_keys_success" == 1 ]] || exit 1
   rvm get stable # Per https://stackoverflow.com/questions/65477613/rvm-where-is-ruby-3-0-0
+  # stop echoing bash commands temporarily to prevent rvm from polluting the logs
+  set +x
   source $HOME/.rvm/scripts/rvm
+
   for RUBY_VERSION in 2.5.0 2.7.0 3.0.0; do
+    echo "Installing ruby-${RUBY_VERSION}"
     time rvm install "ruby-${RUBY_VERSION}"
     time gem install bundler -v 1.17.3 --no-document
     time gem install rake-compiler --no-document
   done;
+  echo "Setting default ruby version."
   rvm use 2.5.0 --default
+  echo "Installing cocoapods."
   time gem install cocoapods --version 1.3.1 --no-document
+  echo "Updating osx-ssl-certs."
   rvm osx-ssl-certs status all
   rvm osx-ssl-certs update all
+
+  # restore echo
+  set -x
 fi
 
 if [ "${PREPARE_BUILD_INSTALL_DEPS_OBJC}" == "true" ]
@@ -146,18 +168,24 @@ fi
 
 if [ "${PREPARE_BUILD_INSTALL_DEPS_PHP}" == "true" ]
 then
-  # It's required to update the brew because it won't work with the default version Kokoro has.
-  # This can be fragile, though because the future version of brew can break. In that case,
-  # please consider to fix the certain version like https://github.com/grpc/grpc/pull/24837.
+  # It's required to update homebrew because it won't work with the default version Kokoro has.
+  # This can be fragile though because the future version of brew can break - consider pinning
+  # the formulas if that happens (see https://github.com/grpc/grpc/pull/24837).
   brew update || true
+  # macos mojave support for php7.3 brew formula removed MacOS Mojave support here: https://github.com/Homebrew/homebrew-core/commit/d8496609d310a233bfb46272ec7948845f32d7c5#diff-df64282b6e4230b6f35468dfbbd500fcd62b0f93b01b2b161e92f512b7feb1a3
+  # so we need earlier version of the formulata than that. See https://github.com/grpc/grpc/pull/24837 for an example of pinning homebrew formulas to a specific commit.
+  (cd /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core; git checkout 10b1944581fbbdc216057fd70e89dbbe3d04161e)
   brew config
 
-  # Install PHP 7.3 explictly to address missing php header files and
-  # to work well with the pre-installed phpunit 8.4
   brew install php@7.3 || true
-  export LDFLAGS="-L/usr/local/opt/php@7.3/lib $(LDFLAGS)"
-  export CPPFLAGS="-I/usr/local/opt/php@7.3/include $(CPPFLAGS)"
-  export PATH="/usr/local/opt/php@7.3/bin:/usr/local/opt/php@7.3/sbin:$PATH"
+  export LDFLAGS="-L/usr/local/opt/php@7.3/lib ${LDFLAGS}"
+  export CPPFLAGS="-I/usr/local/opt/php@7.3/include ${CPPFLAGS}"
+  export PATH="/usr/local/opt/php@7.3/bin:/usr/local/opt/php@7.3/sbin:${PATH}"
+
+  # the exit code from "brew install php@7.3" is useless
+  # so instead we check if PHP was indeed installed successfully.
+  # Failing early is better than cryptic errors later in the build process.
+  /usr/local/opt/php@7.3/bin/php --version
 
   # Workaround for https://github.com/Homebrew/homebrew-core/issues/41081
   mkdir -p /usr/local/lib/php/pecl
index f6855be..92274df 100755 (executable)
@@ -20,6 +20,10 @@ sudo apt update
 sudo apt install -y build-essential autoconf libtool pkg-config cmake python python-pip clang
 sudo pip install six
 
+# install python3.6 and pip
+sudo apt install -y python3 python3-pip
+python3 --version
+
 cd grpc
 
 # tests require port server to be running
diff --git a/tools/internal_ci/linux/grpc_bazel_distribtest.cfg b/tools/internal_ci/linux/grpc_bazel_distribtest.cfg
new file mode 100644 (file)
index 0000000..00b398d
--- /dev/null
@@ -0,0 +1,26 @@
+# 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.
+
+# Config file for the internal CI (in protobuf text format)
+
+# Location of the continuous shell script in repository.
+build_file: "grpc/tools/internal_ci/linux/grpc_bazel_distribtest.sh"
+timeout_mins: 120
+action {
+  define_artifacts {
+    regex: "**/*sponge_log.*"
+    regex: "github/grpc/reports/**"
+    regex: "github/grpc/artifacts/**"
+  }
+}
diff --git a/tools/internal_ci/linux/grpc_bazel_distribtest.sh b/tools/internal_ci/linux/grpc_bazel_distribtest.sh
new file mode 100755 (executable)
index 0000000..34a9945
--- /dev/null
@@ -0,0 +1,27 @@
+#!/bin/bash
+# Copyright 2021 The gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Build portability tests with an updated submodule
+
+set -ex
+
+# change to grpc repo root
+cd $(dirname $0)/../../..
+
+source tools/internal_ci/helper_scripts/prepare_build_linux_rc
+
+export DOCKERFILE_DIR=tools/dockerfile/test/bazel
+export DOCKER_RUN_SCRIPT=test/distrib/bazel/run_bazel_distrib_test.sh
+exec tools/run_tests/dockerize/build_and_run_docker.sh
diff --git a/tools/internal_ci/linux/grpc_bazel_distribtest_latest.cfg b/tools/internal_ci/linux/grpc_bazel_distribtest_latest.cfg
new file mode 100644 (file)
index 0000000..f0fe33c
--- /dev/null
@@ -0,0 +1,26 @@
+# Copyright 2021 The gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Config file for the internal CI (in protobuf text format)
+
+# Location of the continuous shell script in repository.
+build_file: "grpc/tools/internal_ci/linux/grpc_bazel_distribtest_latest.sh"
+timeout_mins: 120
+action {
+  define_artifacts {
+    regex: "**/*sponge_log.*"
+    regex: "github/grpc/reports/**"
+    regex: "github/grpc/artifacts/**"
+  }
+}
diff --git a/tools/internal_ci/linux/grpc_bazel_distribtest_latest.sh b/tools/internal_ci/linux/grpc_bazel_distribtest_latest.sh
new file mode 100755 (executable)
index 0000000..11de663
--- /dev/null
@@ -0,0 +1,27 @@
+#!/bin/bash
+# Copyright 2021 The gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Build portability tests with an updated submodule
+
+set -ex
+
+# change to grpc repo root
+cd $(dirname $0)/../../..
+
+source tools/internal_ci/helper_scripts/prepare_build_linux_rc
+
+export DOCKERFILE_DIR=tools/dockerfile/test/bazel
+export DOCKER_RUN_SCRIPT=/test/distrib/bazel/test_latest_bazel_version.sh
+exec tools/run_tests/dockerize/build_and_run_docker.sh
index d744f90..454e2fe 100644 (file)
@@ -35,7 +35,7 @@ echo $ANDROID_NDK_HOME
 bazel build --define=use_strict_warning=true \
   --fat_apk_cpu=x86_64,arm64-v8a \
   --extra_toolchains=@rules_python//python:autodetecting_toolchain_nonstrict \
-  //examples/android/binder/java/io/grpc/binder/cpp/example:app \
+  //examples/android/binder/java/io/grpc/binder/cpp/exampleclient:app \
   //examples/android/binder/java/io/grpc/binder/cpp/exampleserver:app
 
 # Make sure the Java code that will be invoked by binder transport
index 4d92aa0..f646f6b 100644 (file)
@@ -20,6 +20,6 @@ timeout_mins: 240
 action {
   define_artifacts {
     regex: "**/*sponge_log.*"
-    regex: "**/perf_reports/**"
+    regex: "**/github/grpc/runner/**"
   }
 }
index 1998567..e0a4cda 100755 (executable)
@@ -32,6 +32,9 @@ gcloud container clusters get-credentials benchmarks-prod2 \
 # Set up environment variables.
 LOAD_TEST_PREFIX="${KOKORO_BUILD_INITIATOR}"
 # BEGIN differentiate experimental configuration from master configuration.
+if [[ "${KOKORO_BUILD_INITIATOR%%-*}" == kokoro ]]; then
+    LOAD_TEST_PREFIX=kokoro
+fi
 # Use the "official" BQ tables so that the measurements will show up in the
 # "official" public dashboard.
 BIGQUERY_TABLE_8CORE=e2e_benchmarks.ci_master_results_8core
@@ -53,18 +56,23 @@ GRPC_GO_GITREF="$(git ls-remote https://github.com/grpc/grpc-go.git master | cut
 GRPC_JAVA_GITREF="$(git ls-remote https://github.com/grpc/grpc-java.git master | cut -f1)"
 # Kokoro jobs run on dedicated pools.
 DRIVER_POOL=drivers-ci
-WORKER_POOL_8CORE=workers-8core-ci
-WORKER_POOL_32CORE=workers-32core-ci
+WORKER_POOL_8CORE=workers-c2-8core-ci
+WORKER_POOL_8CORE_NUM_CORES=8
+# c2-standard-30 is the closest machine spec to 32 core there is
+WORKER_POOL_32CORE=workers-c2-30core-ci
+WORKER_POOL_32CORE_NUM_CORES=30
 
 # Update go version.
-TEST_INFRA_GOVERSION=go1.17
+TEST_INFRA_GOVERSION=go1.17.1
 go get "golang.org/dl/${TEST_INFRA_GOVERSION}"
 "${TEST_INFRA_GOVERSION}" download
 
-# Clone test-infra repository to one upper level directory than grpc.
+# Fetch test-infra repository and build all tools.
+# Note: Submodules are not required for tools build.
 pushd ..
-git clone --recursive https://github.com/grpc/test-infra.git
+git clone --depth 1 https://github.com/grpc/test-infra.git
 cd test-infra
+git log -1 --oneline
 make GOCMD="${TEST_INFRA_GOVERSION}" all-tools
 popd
 
@@ -72,17 +80,23 @@ popd
 buildConfigs() {
     local -r pool="$1"
     local -r table="$2"
-    shift 2
+    local -r num_cores="$3"
+    shift 3
+    # TODO(jtattermusch): find a better solution for detecting number of cores in java
+    # then setting the "java_worker_command_prefix"
     tools/run_tests/performance/loadtest_config.py "$@" \
         -t ./tools/run_tests/performance/templates/loadtest_template_prebuilt_all_languages.yaml \
         -s driver_pool="${DRIVER_POOL}" -s driver_image= \
         -s client_pool="${pool}" -s server_pool="${pool}" \
         -s big_query_table="${table}" -s timeout_seconds=900 \
         -s prebuilt_image_prefix="${PREBUILT_IMAGE_PREFIX}" \
+        -s java_worker_command_prefix='BENCHMARK_WORKER_OPTS="-XX:ActiveProcessorCount='${num_cores}'"' \
         -a ci_buildNumber="${KOKORO_BUILD_NUMBER}" \
         -a ci_buildUrl="${CLOUD_LOGGING_URL}" \
         -a ci_jobName="${KOKORO_JOB_NAME}" \
         -a ci_gitCommit="${GRPC_GITREF}" \
+        -a ci_gitCommit_go="${GRPC_GO_GITREF}" \
+        -a ci_gitCommit_java="${GRPC_JAVA_GITREF}" \
         -a ci_gitActualCommit="${KOKORO_GIT_COMMIT}" \
         -s prebuilt_image_tag="${UNIQUE_IDENTIFIER}" \
         --prefix="${LOAD_TEST_PREFIX}" -u "${UNIQUE_IDENTIFIER}" -u "${pool}" \
@@ -91,8 +105,8 @@ buildConfigs() {
         -o "./loadtest_with_prebuilt_workers_${pool}.yaml"
 }
 
-buildConfigs "${WORKER_POOL_8CORE}" "${BIGQUERY_TABLE_8CORE}" -l c++ -l csharp -l go -l java -l php7 -l php7_protobuf_c -l python -l ruby
-buildConfigs "${WORKER_POOL_32CORE}" "${BIGQUERY_TABLE_32CORE}" -l c++ -l csharp -l go -l java
+buildConfigs "${WORKER_POOL_8CORE}" "${BIGQUERY_TABLE_8CORE}" "${WORKER_POOL_8CORE_NUM_CORES}" -l c++ -l csharp -l go -l java -l php7 -l php7_protobuf_c -l python -l ruby
+buildConfigs "${WORKER_POOL_32CORE}" "${BIGQUERY_TABLE_32CORE}" "${WORKER_POOL_32CORE_NUM_CORES}" -l c++ -l csharp -l go -l java
 
 # Delete prebuilt images on exit.
 deleteImages() {
@@ -116,13 +130,10 @@ time ../test-infra/bin/prepare_prebuilt_workers \
     -t "${UNIQUE_IDENTIFIER}" \
     -r "${ROOT_DIRECTORY_OF_DOCKERFILES}"
 
-# Create reports directories.
-mkdir -p "runner/${WORKER_POOL_8CORE}" "runner/${WORKER_POOL_32CORE}"
-
-
 # Run tests.
 time ../test-infra/bin/runner \
     -i "../grpc/loadtest_with_prebuilt_workers_${WORKER_POOL_8CORE}.yaml" \
     -i "../grpc/loadtest_with_prebuilt_workers_${WORKER_POOL_32CORE}.yaml" \
+    -delete-successful-tests \
     -c "${WORKER_POOL_8CORE}:2" -c "${WORKER_POOL_32CORE}:2" \
     -o "runner/sponge_log.xml"
diff --git a/tools/internal_ci/linux/grpc_e2e_performance_gke_experiment.cfg b/tools/internal_ci/linux/grpc_e2e_performance_gke_experiment.cfg
new file mode 100644 (file)
index 0000000..4b49380
--- /dev/null
@@ -0,0 +1,25 @@
+# Copyright 2021 The gRPC Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Config file for the internal CI (in protobuf text format)
+
+# Location of the continuous shell script in repository.
+build_file: "grpc/tools/internal_ci/linux/grpc_e2e_performance_gke_experiment.sh"
+timeout_mins: 720
+action {
+  define_artifacts {
+    regex: "**/*sponge_log.*"
+    regex: "**/github/grpc/runner/**"
+  }
+}
diff --git a/tools/internal_ci/linux/grpc_e2e_performance_gke_experiment.sh b/tools/internal_ci/linux/grpc_e2e_performance_gke_experiment.sh
new file mode 100755 (executable)
index 0000000..a831fad
--- /dev/null
@@ -0,0 +1,137 @@
+#!/usr/bin/env bash
+# Copyright 2021 The gRPC Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+set -ex
+
+# Enter the gRPC repo root.
+cd "$(dirname "$0")/../../.."
+
+source tools/internal_ci/helper_scripts/prepare_build_linux_rc
+
+# This is to ensure we can push and pull images from gcr.io. We do not
+# necessarily need it to run load tests, but will need it when we employ
+# pre-built images in the optimization.
+gcloud auth configure-docker
+
+# Connect to benchmarks-prod2 cluster.
+gcloud config set project grpc-testing
+gcloud container clusters get-credentials benchmarks-prod2 \
+    --zone us-central1-b --project grpc-testing
+
+# Set up environment variables.
+LOAD_TEST_PREFIX="${KOKORO_BUILD_INITIATOR}"
+# BEGIN differentiate experimental configuration from master configuration.
+if [[ "${KOKORO_BUILD_INITIATOR%%-*}" == kokoro ]]; then
+    LOAD_TEST_PREFIX=kokoro-test
+fi
+BIGQUERY_TABLE_8CORE=e2e_benchmarks.experimental_results
+BIGQUERY_TABLE_32CORE=e2e_benchmarks.experimental_results_32core
+# END differentiate experimental configuration from master configuration.
+CLOUD_LOGGING_URL="https://source.cloud.google.com/results/invocations/${KOKORO_BUILD_ID}"
+PREBUILT_IMAGE_PREFIX="gcr.io/grpc-testing/e2etesting/pre_built_workers/${LOAD_TEST_PREFIX}"
+UNIQUE_IDENTIFIER="$(date +%Y%m%d%H%M%S)"
+ROOT_DIRECTORY_OF_DOCKERFILES="../test-infra/containers/pre_built_workers/"
+# Head of the workspace checked out by Kokoro.
+GRPC_GITREF="$(git show --format="%H" --no-patch)"
+# Prebuilt workers for core languages are always built from grpc/grpc.
+if [[ "${KOKORO_GITHUB_COMMIT_URL%/*}" == "https://github.com/grpc/grpc/commit" ]]; then
+    GRPC_CORE_GITREF="${KOKORO_GIT_COMMIT}"
+else
+    GRPC_CORE_GITREF="$(git ls-remote https://github.com/grpc/grpc.git master | cut -f1)"
+fi
+GRPC_GO_GITREF="$(git ls-remote https://github.com/grpc/grpc-go.git master | cut -f1)"
+GRPC_JAVA_GITREF="$(git ls-remote https://github.com/grpc/grpc-java.git master | cut -f1)"
+# Kokoro jobs run on dedicated pools.
+DRIVER_POOL=drivers-ci
+WORKER_POOL_8CORE=workers-c2-8core-ci
+WORKER_POOL_8CORE_NUM_CORES=8
+# c2-standard-30 is the closest machine spec to 32 core there is
+WORKER_POOL_32CORE=workers-c2-30core-ci
+WORKER_POOL_32CORE_NUM_CORES=30
+
+# Update go version.
+TEST_INFRA_GOVERSION=go1.17.1
+go get "golang.org/dl/${TEST_INFRA_GOVERSION}"
+"${TEST_INFRA_GOVERSION}" download
+
+# Fetch test-infra repository and build all tools.
+# Note: Submodules are not required for tools build.
+pushd ..
+git clone --depth 1 https://github.com/grpc/test-infra.git
+cd test-infra
+git log -1 --oneline
+make GOCMD="${TEST_INFRA_GOVERSION}" all-tools
+popd
+
+# Build test configurations.
+buildConfigs() {
+    local -r pool="$1"
+    local -r table="$2"
+    local -r num_cores="$3"
+    shift 3
+    # TODO(jtattermusch): find a better solution for detecting number of cores in java
+    # then setting the "java_worker_command_prefix"
+    tools/run_tests/performance/loadtest_config.py "$@" \
+        -t ./tools/run_tests/performance/templates/loadtest_template_prebuilt_all_languages.yaml \
+        -s driver_pool="${DRIVER_POOL}" -s driver_image= \
+        -s client_pool="${pool}" -s server_pool="${pool}" \
+        -s big_query_table="${table}" -s timeout_seconds=900 \
+        -s prebuilt_image_prefix="${PREBUILT_IMAGE_PREFIX}" \
+        -s prebuilt_image_tag="${UNIQUE_IDENTIFIER}" \
+        -s java_worker_command_prefix='BENCHMARK_WORKER_OPTS="-XX:ActiveProcessorCount='${num_cores}'"' \
+        -a ci_buildNumber="${KOKORO_BUILD_NUMBER}" \
+        -a ci_buildUrl="${CLOUD_LOGGING_URL}" \
+        -a ci_jobName="${KOKORO_JOB_NAME}" \
+        -a ci_gitCommit="${GRPC_GITREF}" \
+        -a ci_gitCommit_go="${GRPC_GO_GITREF}" \
+        -a ci_gitCommit_java="${GRPC_JAVA_GITREF}" \
+        -a ci_gitActualCommit="${KOKORO_GIT_COMMIT}" \
+        --prefix="${LOAD_TEST_PREFIX}" -u "${UNIQUE_IDENTIFIER}" -u "${pool}" \
+        -a pool="${pool}" --category=scalable \
+        --allow_client_language=c++ --allow_server_language=c++ \
+        -o "./loadtest_with_prebuilt_workers_${pool}.yaml"
+}
+
+buildConfigs "${WORKER_POOL_8CORE}" "${BIGQUERY_TABLE_8CORE}" "${WORKER_POOL_8CORE_NUM_CORES}" -l c++ -l csharp -l go -l java -l php7 -l php7_protobuf_c -l python -l ruby
+buildConfigs "${WORKER_POOL_32CORE}" "${BIGQUERY_TABLE_32CORE}" "${WORKER_POOL_32CORE_NUM_CORES}" -l c++ -l csharp -l go -l java
+
+# Delete prebuilt images on exit.
+deleteImages() {
+    echo "deleting images on exit"
+    ../test-infra/bin/delete_prebuilt_workers \
+    -p "${PREBUILT_IMAGE_PREFIX}" \
+    -t "${UNIQUE_IDENTIFIER}"
+}
+trap deleteImages EXIT
+
+# Build and push prebuilt images for running tests.
+time ../test-infra/bin/prepare_prebuilt_workers \
+    -l "cxx:${GRPC_CORE_GITREF}" \
+    -l "csharp:${GRPC_CORE_GITREF}" \
+    -l "go:${GRPC_GO_GITREF}" \
+    -l "java:${GRPC_JAVA_GITREF}" \
+    -l "php7:${GRPC_CORE_GITREF}" \
+    -l "python:${GRPC_CORE_GITREF}" \
+    -l "ruby:${GRPC_CORE_GITREF}" \
+    -p "${PREBUILT_IMAGE_PREFIX}" \
+    -t "${UNIQUE_IDENTIFIER}" \
+    -r "${ROOT_DIRECTORY_OF_DOCKERFILES}"
+
+# Run tests.
+time ../test-infra/bin/runner \
+    -i "../grpc/loadtest_with_prebuilt_workers_${WORKER_POOL_8CORE}.yaml" \
+    -i "../grpc/loadtest_with_prebuilt_workers_${WORKER_POOL_32CORE}.yaml" \
+    -delete-successful-tests \
+    -c "${WORKER_POOL_8CORE}:2" -c "${WORKER_POOL_32CORE}:2" \
+    -o "runner/sponge_log.xml"
index 781544b..4b49380 100644 (file)
 # Config file for the internal CI (in protobuf text format)
 
 # Location of the continuous shell script in repository.
-build_file: "grpc/tools/internal_ci/linux/grpc_e2e_performance_v2.sh"
+build_file: "grpc/tools/internal_ci/linux/grpc_e2e_performance_gke_experiment.sh"
 timeout_mins: 720
 action {
   define_artifacts {
     regex: "**/*sponge_log.*"
-    regex: "**/perf_reports/**"
+    regex: "**/github/grpc/runner/**"
   }
 }
diff --git a/tools/internal_ci/linux/grpc_e2e_performance_v2.sh b/tools/internal_ci/linux/grpc_e2e_performance_v2.sh
deleted file mode 100755 (executable)
index ed0089a..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-#!/usr/bin/env bash
-# Copyright 2021 The gRPC Authors
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-set -ex
-
-# Enter the gRPC repo root.
-cd "$(dirname "$0")/../../.."
-
-source tools/internal_ci/helper_scripts/prepare_build_linux_rc
-
-# This is to ensure we can push and pull images from gcr.io. We do not
-# necessarily need it to run load tests, but will need it when we employ
-# pre-built images in the optimization.
-gcloud auth configure-docker
-
-# Connect to benchmarks-prod2 cluster.
-gcloud config set project grpc-testing
-gcloud container clusters get-credentials benchmarks-prod2 \
-    --zone us-central1-b --project grpc-testing
-
-# Set up environment variables.
-LOAD_TEST_PREFIX="${KOKORO_BUILD_INITIATOR}"
-# BEGIN differentiate experimental configuration from master configuration.
-if [[ "${KOKORO_BUILD_INITIATOR}" == kokoro ]]; then
-    LOAD_TEST_PREFIX=kokoro-test
-fi
-BIGQUERY_TABLE_8CORE=e2e_benchmarks.experimental_results
-BIGQUERY_TABLE_32CORE=e2e_benchmarks.experimental_results_32core
-# END differentiate experimental configuration from master configuration.
-CLOUD_LOGGING_URL="https://source.cloud.google.com/results/invocations/${KOKORO_BUILD_ID}"
-PREBUILT_IMAGE_PREFIX="gcr.io/grpc-testing/e2etesting/pre_built_workers/${LOAD_TEST_PREFIX}"
-UNIQUE_IDENTIFIER="$(date +%Y%m%d%H%M%S)"
-ROOT_DIRECTORY_OF_DOCKERFILES="../test-infra/containers/pre_built_workers/"
-# Head of the workspace checked out by Kokoro.
-GRPC_GITREF="$(git show --format="%H" --no-patch)"
-# Prebuilt workers for core languages are always built from grpc/grpc.
-if [[ "${KOKORO_GITHUB_COMMIT_URL%/*}" == "https://github.com/grpc/grpc/commit" ]]; then
-    GRPC_CORE_GITREF="${KOKORO_GIT_COMMIT}"
-else
-    GRPC_CORE_GITREF="$(git ls-remote https://github.com/grpc/grpc.git master | cut -f1)"
-fi
-GRPC_GO_GITREF="$(git ls-remote https://github.com/grpc/grpc-go.git master | cut -f1)"
-GRPC_JAVA_GITREF="$(git ls-remote https://github.com/grpc/grpc-java.git master | cut -f1)"
-# Kokoro jobs run on dedicated pools.
-DRIVER_POOL=drivers-ci
-WORKER_POOL_8CORE=workers-8core-ci
-WORKER_POOL_32CORE=workers-32core-ci
-
-# Update go version.
-TEST_INFRA_GOVERSION=go1.17
-go get "golang.org/dl/${TEST_INFRA_GOVERSION}"
-"${TEST_INFRA_GOVERSION}" download
-
-# Clone test-infra repository to one upper level directory than grpc.
-pushd ..
-git clone --recursive https://github.com/grpc/test-infra.git
-cd test-infra
-make GOCMD="${TEST_INFRA_GOVERSION}" all-tools
-popd
-
-# Build test configurations.
-buildConfigs() {
-    local -r pool="$1"
-    local -r table="$2"
-    shift 2
-    tools/run_tests/performance/loadtest_config.py "$@" \
-        -t ./tools/run_tests/performance/templates/loadtest_template_prebuilt_all_languages.yaml \
-        -s driver_pool="${DRIVER_POOL}" -s driver_image= \
-        -s client_pool="${pool}" -s server_pool="${pool}" \
-        -s big_query_table="${table}" -s timeout_seconds=900 \
-        -s prebuilt_image_prefix="${PREBUILT_IMAGE_PREFIX}" \
-        -s prebuilt_image_tag="${UNIQUE_IDENTIFIER}" \
-        -a ci_buildNumber="${KOKORO_BUILD_NUMBER}" \
-        -a ci_buildUrl="${CLOUD_LOGGING_URL}" \
-        -a ci_jobName="${KOKORO_JOB_NAME}" \
-        -a ci_gitCommit="${GRPC_GITREF}" \
-        -a ci_gitActualCommit="${KOKORO_GIT_COMMIT}" \
-        --prefix="${LOAD_TEST_PREFIX}" -u "${UNIQUE_IDENTIFIER}" -u "${pool}" \
-        -a pool="${pool}" --category=scalable \
-        --allow_client_language=c++ --allow_server_language=c++ \
-        -o "./loadtest_with_prebuilt_workers_${pool}.yaml"
-}
-
-buildConfigs "${WORKER_POOL_8CORE}" "${BIGQUERY_TABLE_8CORE}" -l c++ -l csharp -l go -l java -l php7 -l php7_protobuf_c -l python -l ruby
-buildConfigs "${WORKER_POOL_32CORE}" "${BIGQUERY_TABLE_32CORE}" -l c++ -l csharp -l go -l java
-
-# Delete prebuilt images on exit.
-deleteImages() {
-    echo "deleting images on exit"
-    ../test-infra/bin/delete_prebuilt_workers \
-    -p "${PREBUILT_IMAGE_PREFIX}" \
-    -t "${UNIQUE_IDENTIFIER}"
-}
-trap deleteImages EXIT
-
-# Build and push prebuilt images for running tests.
-time ../test-infra/bin/prepare_prebuilt_workers \
-    -l "cxx:${GRPC_CORE_GITREF}" \
-    -l "csharp:${GRPC_CORE_GITREF}" \
-    -l "go:${GRPC_GO_GITREF}" \
-    -l "java:${GRPC_JAVA_GITREF}" \
-    -l "php7:${GRPC_CORE_GITREF}" \
-    -l "python:${GRPC_CORE_GITREF}" \
-    -l "ruby:${GRPC_CORE_GITREF}" \
-    -p "${PREBUILT_IMAGE_PREFIX}" \
-    -t "${UNIQUE_IDENTIFIER}" \
-    -r "${ROOT_DIRECTORY_OF_DOCKERFILES}"
-
-# Create reports directories.
-mkdir -p "runner/${WORKER_POOL_8CORE}" "runner/${WORKER_POOL_32CORE}"
-
-# Run tests.
-time ../test-infra/bin/runner \
-    -i "../grpc/loadtest_with_prebuilt_workers_${WORKER_POOL_8CORE}.yaml" \
-    -i "../grpc/loadtest_with_prebuilt_workers_${WORKER_POOL_32CORE}.yaml" \
-    -c "${WORKER_POOL_8CORE}:2" -c "${WORKER_POOL_32CORE}:2" \
-    -o "runner/sponge_log.xml"
diff --git a/tools/internal_ci/linux/grpc_line_count.cfg b/tools/internal_ci/linux/grpc_line_count.cfg
deleted file mode 100644 (file)
index 5854d9c..0000000
+++ /dev/null
@@ -1,19 +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.
-
-# Config file for the internal CI (in protobuf text format)
-
-# Location of the continuous shell script in repository.
-build_file: "grpc/tools/internal_ci/linux/grpc_line_count.sh"
-timeout_mins: 30
diff --git a/tools/internal_ci/linux/grpc_line_count.sh b/tools/internal_ci/linux/grpc_line_count.sh
deleted file mode 100755 (executable)
index 22e484b..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/usr/bin/env bash
-# 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 script counts the numbers of line in gRPC's repo and uploads to BQ
-set -ex
-
-# Enter the gRPC repo root
-cd $(dirname $0)/../../..
-
-git submodule update --init
-
-# Install cloc
-git clone -b v1.72 https://github.com/AlDanial/cloc/ ~/cloc
-PERL_MM_USE_DEFAULT=1 sudo perl -MCPAN -e 'install Regexp::Common; install Algorithm::Diff'
-sudo make install -C ~/cloc/Unix
-
-./tools/line_count/collect-now.sh
index c4fa6c6..3771bdd 100644 (file)
@@ -26,5 +26,5 @@ action {
 
 env_vars {
   key: "RUN_TESTS_FLAGS"
-  value: "-f portability linux --inner_jobs 8 -j 4 --internal_ci --build_only"
+  value: "-f portability linux c++ --inner_jobs 8 -j 4 --internal_ci --build_only --extra_args -r xds_end2end_test"
 }
index a0ce71a..7c5b07a 100755 (executable)
@@ -22,7 +22,7 @@ source tools/internal_ci/helper_scripts/prepare_build_linux_rc
 
 # If this is a PR using RUN_TESTS_FLAGS var, then add flags to filter tests
 if [ -n "$KOKORO_GITHUB_PULL_REQUEST_NUMBER" ] && [ -n "$RUN_TESTS_FLAGS" ]; then
-  export RUN_TESTS_FLAGS="$RUN_TESTS_FLAGS --filter_pr_tests --base_branch origin/$KOKORO_GITHUB_PULL_REQUEST_TARGET_BRANCH"
+  export RUN_TESTS_FLAGS="--filter_pr_tests --base_branch origin/$KOKORO_GITHUB_PULL_REQUEST_TARGET_BRANCH $RUN_TESTS_FLAGS"
 fi
 
 tools/run_tests/run_tests_matrix.py $RUN_TESTS_FLAGS || FAILED="true"
index 640e66e..4d8daff 100755 (executable)
@@ -68,7 +68,7 @@ export PYTHONUNBUFFERED=true
 GRPC_VERBOSITY=debug GRPC_TRACE=xds_client,xds_resolver,xds_cluster_manager_lb,cds_lb,xds_cluster_resolver_lb,priority_lb,xds_cluster_impl_lb,weighted_target_lb "$PYTHON" \
   tools/run_tests/run_xds_tests.py \
     --halt_after_fail \
-    --test_case="all,circuit_breaking,timeout,fault_injection" \
+    --test_case="ping_pong" \
     --project_id=grpc-testing \
     --project_num=830293263384 \
     --source_image=projects/grpc-testing/global/images/xds-test-server-4 \
index e462cae..b820193 100755 (executable)
@@ -70,7 +70,7 @@ bazel build test/cpp/interop:xds_interop_client
 GRPC_VERBOSITY=debug GRPC_TRACE=xds_client,xds_resolver,xds_cluster_manager_lb,cds_lb,xds_cluster_resolver_lb,priority_lb,xds_cluster_impl_lb,weighted_target_lb "$PYTHON" \
   tools/run_tests/run_xds_tests.py \
     --halt_after_fail \
-    --test_case="all,circuit_breaking,timeout,fault_injection,csds" \
+    --test_case="ping_pong" \
     --project_id=grpc-testing \
     --project_num=830293263384 \
     --source_image=projects/grpc-testing/global/images/xds-test-server-4 \
diff --git a/tools/internal_ci/linux/grpc_xds_csharp.cfg b/tools/internal_ci/linux/grpc_xds_csharp.cfg
deleted file mode 100644 (file)
index 0208f9b..0000000
+++ /dev/null
@@ -1,25 +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.
-
-# Config file for the internal CI (in protobuf text format)
-
-# Location of the continuous shell script in repository.
-build_file: "grpc/tools/internal_ci/linux/grpc_xds_csharp.sh"
-timeout_mins: 360
-action {
-  define_artifacts {
-    regex: "**/*sponge_log.*"
-    regex: "github/grpc/reports/**"
-  }
-}
diff --git a/tools/internal_ci/linux/grpc_xds_csharp.sh b/tools/internal_ci/linux/grpc_xds_csharp.sh
deleted file mode 100755 (executable)
index 3767a60..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/usr/bin/env bash
-# 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
-
-# change to grpc repo root
-cd $(dirname $0)/../../..
-
-source tools/internal_ci/helper_scripts/prepare_build_linux_rc
-
-export DOCKERFILE_DIR=tools/dockerfile/test/csharp_buster_x64
-export DOCKER_RUN_SCRIPT=tools/internal_ci/linux/grpc_xds_csharp_test_in_docker.sh
-export OUTPUT_DIR=reports
-exec tools/run_tests/dockerize/build_and_run_docker.sh
diff --git a/tools/internal_ci/linux/grpc_xds_csharp_test_in_docker.sh b/tools/internal_ci/linux/grpc_xds_csharp_test_in_docker.sh
deleted file mode 100755 (executable)
index 300f466..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-#!/usr/bin/env bash
-# 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.
-
-set -ex -o igncr || set -ex
-
-mkdir -p /var/local/git
-git clone /var/local/jenkins/grpc /var/local/git/grpc
-(cd /var/local/jenkins/grpc/ && git submodule foreach 'cd /var/local/git/grpc \
-&& git submodule update --init --reference /var/local/jenkins/grpc/${name} \
-${name}')
-cd /var/local/git/grpc
-
-VIRTUAL_ENV=$(mktemp -d)
-virtualenv "$VIRTUAL_ENV" -p python3
-PYTHON="$VIRTUAL_ENV"/bin/python
-"$PYTHON" -m pip install --upgrade pip==19.3.1
-"$PYTHON" -m pip install --upgrade grpcio grpcio-tools google-api-python-client google-auth-httplib2 oauth2client xds-protos
-
-# Prepare generated Python code.
-TOOLS_DIR=tools/run_tests
-PROTO_SOURCE_DIR=src/proto/grpc/testing
-PROTO_DEST_DIR="$TOOLS_DIR"/"$PROTO_SOURCE_DIR"
-mkdir -p "$PROTO_DEST_DIR"
-touch "$TOOLS_DIR"/src/__init__.py
-touch "$TOOLS_DIR"/src/proto/__init__.py
-touch "$TOOLS_DIR"/src/proto/grpc/__init__.py
-touch "$TOOLS_DIR"/src/proto/grpc/testing/__init__.py
-
-"$PYTHON" -m grpc_tools.protoc \
-    --proto_path=. \
-    --python_out="$TOOLS_DIR" \
-    --grpc_python_out="$TOOLS_DIR" \
-    "$PROTO_SOURCE_DIR"/test.proto \
-    "$PROTO_SOURCE_DIR"/messages.proto \
-    "$PROTO_SOURCE_DIR"/empty.proto
-
-HEALTH_PROTO_SOURCE_DIR=src/proto/grpc/health/v1
-HEALTH_PROTO_DEST_DIR=${TOOLS_DIR}/${HEALTH_PROTO_SOURCE_DIR}
-mkdir -p ${HEALTH_PROTO_DEST_DIR}
-touch "$TOOLS_DIR"/src/proto/grpc/health/__init__.py
-touch "$TOOLS_DIR"/src/proto/grpc/health/v1/__init__.py
-
-"$PYTHON" -m grpc_tools.protoc \
-    --proto_path=. \
-    --python_out=${TOOLS_DIR} \
-    --grpc_python_out=${TOOLS_DIR} \
-    ${HEALTH_PROTO_SOURCE_DIR}/health.proto
-
-python tools/run_tests/run_tests.py -l csharp -c opt --build_only
-
-# Test cases "path_matching" and "header_matching" are not included in "all",
-# because not all interop clients in all languages support these new tests.
-#
-# TODO(jtattermusch): remove "path_matching" and "header_matching" from
-# --test_case after they are added into "all".
-GRPC_VERBOSITY=debug GRPC_TRACE=xds_client,xds_resolver,xds_cluster_manager_lb,cds_lb,xds_cluster_resolver_lb,priority_lb,xds_cluster_impl_lb,weighted_target_lb "$PYTHON" \
-  tools/run_tests/run_xds_tests.py \
-    --halt_after_fail \
-    --test_case="all,path_matching,header_matching" \
-    --project_id=grpc-testing \
-    --project_num=830293263384 \
-    --source_image=projects/grpc-testing/global/images/xds-test-server-2 \
-    --path_to_server_binary=/java_server/grpc-java/interop-testing/build/install/grpc-interop-testing/bin/xds-test-server \
-    --gcp_suffix=$(date '+%s') \
-    --verbose \
-    ${XDS_V3_OPT-} \
-    --client_cmd='dotnet exec src/csharp/Grpc.IntegrationTesting.XdsClient/bin/Release/netcoreapp2.1/Grpc.IntegrationTesting.XdsClient.dll -- --server=xds:///{server_uri} --stats_port={stats_port} --qps={qps} {rpcs_to_send} {metadata_to_send}'
diff --git a/tools/internal_ci/linux/grpc_xds_k8s.cfg b/tools/internal_ci/linux/grpc_xds_k8s.cfg
deleted file mode 100644 (file)
index c59a357..0000000
+++ /dev/null
@@ -1,26 +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.
-
-# Config file for the internal CI (in protobuf text format)
-
-# Location of the continuous shell script in repository.
-build_file: "grpc/tools/internal_ci/linux/grpc_xds_k8s.sh"
-timeout_mins: 120
-action {
-  define_artifacts {
-    regex: "artifacts/**/*sponge_log.xml"
-    regex: "artifacts/**/*sponge_log.log"
-    strip_prefix: "artifacts"
-  }
-}
index 6ec4fa7..6b38cae 100644 (file)
@@ -16,7 +16,7 @@
 
 # Location of the continuous shell script in repository.
 build_file: "grpc/tools/internal_ci/linux/grpc_xds_k8s_lb.sh"
-timeout_mins: 90
+timeout_mins: 180
 action {
   define_artifacts {
     regex: "artifacts/**/*sponge_log.xml"
index fd8a984..606a254 100755 (executable)
@@ -101,7 +101,14 @@ run_test() {
     --secondary_kube_context="${SECONDARY_KUBE_CONTEXT}" \
     --server_image="${SERVER_IMAGE_NAME}:${GIT_COMMIT}" \
     --client_image="${CLIENT_IMAGE_NAME}:${GIT_COMMIT}" \
-    --xml_output_file="${TEST_XML_OUTPUT_DIR}/${test_name}/sponge_log.xml"
+    --xml_output_file="${TEST_XML_OUTPUT_DIR}/${test_name}/sponge_log.xml" \
+    ${@:2}
+}
+
+run_alpha_test() {
+  local test_name=$1
+  run_test ${test_name} \
+    --compute_api_version="v1alpha"
 }
 
 #######################################
@@ -147,6 +154,7 @@ main() {
   # Run tests
   cd "${TEST_DRIVER_FULL_DIR}"
   local failed_tests=0
+  run_alpha_test subsetting_test || (( failed_tests++ ))
   test_suites=("change_backend_service_test" "failover_test" "remove_neg_test" "round_robin_test" "affinity_test")
   for test in "${test_suites[@]}"; do
     run_test $test || (( failed_tests++ ))
index 6b7c6d7..01fc641 100644 (file)
@@ -16,7 +16,7 @@
 
 # Location of the continuous shell script in repository.
 build_file: "grpc/tools/internal_ci/linux/grpc_xds_k8s_xlang.sh"
-timeout_mins: 420
+timeout_mins: 540
 action {
   define_artifacts {
     regex: "artifacts/**/*sponge_log.xml"
index faf4c9e..abf4fad 100755 (executable)
@@ -22,7 +22,7 @@ readonly TEST_DRIVER_INSTALL_SCRIPT_URL="https://raw.githubusercontent.com/${TES
 readonly IMAGE_REPO="gcr.io/grpc-testing/xds-interop"
 readonly SERVER_LANG="cpp go java"
 readonly CLIENT_LANG="cpp go java"
-readonly VERSION_TAG="v1.40.x"
+readonly VERSION_TAG="v1.41.x"
 
 #######################################
 # Executes the test case
@@ -57,7 +57,6 @@ run_test() {
     --xml_output_file="${TEST_XML_OUTPUT_DIR}/${tag}/${clang}-${slang}/sponge_log.xml" \
     --force_cleanup \
     --nocheck_local_certs
-  set +x
 }
 
 #######################################
@@ -100,6 +99,8 @@ main() {
   fi
 
   local failed_tests=0
+  local successful_string
+  local failed_string
   # Run tests
   for TAG in ${VERSION_TAG}
   do
@@ -108,12 +109,20 @@ main() {
     for SLANG in ${SERVER_LANG}
     do
       if [ "${CLANG}" != "${SLANG}" ]; then
-        run_test "${TAG}" "${SLANG}" "${CLANG}" || (( failed_tests++ ))
+        if run_test "${TAG}" "${SLANG}" "${CLANG}"; then
+          successful_string="${successful_string} ${TAG}/${CLANG}-${SLANG}"
+        else
+          failed_tests=$((failed_tests+1))
+          failed_string="${failed_string} ${TAG}/${CLANG}-${SLANG}"
+        fi
       fi
     done
     echo "Failed test suites: ${failed_tests}"
     done
   done
+  set +x
+  echo "Failed test suites list: ${failed_string}"
+  echo "Successful test suites list: ${successful_string}"
   if (( failed_tests > 0 )); then
     exit 1
   fi
diff --git a/tools/internal_ci/linux/grpc_xds_v3_csharp.cfg b/tools/internal_ci/linux/grpc_xds_v3_csharp.cfg
deleted file mode 100644 (file)
index 5ca9153..0000000
+++ /dev/null
@@ -1,25 +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.
-
-# Config file for the internal CI (in protobuf text format)
-
-# Location of the continuous shell script in repository.
-build_file: "grpc/tools/internal_ci/linux/grpc_xds_v3_csharp.sh"
-timeout_mins: 360
-action {
-  define_artifacts {
-    regex: "**/*sponge_log.*"
-    regex: "github/grpc/reports/**"
-  }
-}
diff --git a/tools/internal_ci/linux/grpc_xds_v3_csharp.sh b/tools/internal_ci/linux/grpc_xds_v3_csharp.sh
deleted file mode 100755 (executable)
index 0286581..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/usr/bin/env bash
-# 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.
-
-set -ex
-
-# change to grpc repo root
-cd $(dirname $0)/../../..
-
-source tools/internal_ci/helper_scripts/prepare_build_linux_rc
-
-export DOCKERFILE_DIR=tools/dockerfile/test/csharp_buster_x64
-export DOCKER_RUN_SCRIPT=tools/internal_ci/linux/grpc_xds_v3_csharp_test_in_docker.sh
-export OUTPUT_DIR=reports
-exec tools/run_tests/dockerize/build_and_run_docker.sh
diff --git a/tools/internal_ci/linux/grpc_xds_v3_csharp_test_in_docker.sh b/tools/internal_ci/linux/grpc_xds_v3_csharp_test_in_docker.sh
deleted file mode 100755 (executable)
index 6ea3d41..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/usr/bin/env bash
-# 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.
-
-XDS_V3_OPT="--xds_v3_support" `dirname $0`/grpc_xds_csharp_test_in_docker.sh
diff --git a/tools/internal_ci/linux/psm-security.cfg b/tools/internal_ci/linux/psm-security.cfg
new file mode 100644 (file)
index 0000000..5c58f17
--- /dev/null
@@ -0,0 +1,26 @@
+# 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.
+
+# Config file for the internal CI (in protobuf text format)
+
+# Location of the continuous shell script in repository.
+build_file: "grpc/tools/internal_ci/linux/psm-security.sh"
+timeout_mins: 120
+action {
+  define_artifacts {
+    regex: "artifacts/**/*sponge_log.xml"
+    regex: "artifacts/**/*sponge_log.log"
+    strip_prefix: "artifacts"
+  }
+}
index b26b09e..e2ad932 100644 (file)
@@ -14,7 +14,7 @@
 
 @rem TODO(jtattermusch): make this generate less output
 @rem TODO(jtattermusch): use tools/bazel script to keep the versions in sync
-choco install bazel -y --version 3.7.1 --limit-output
+choco install bazel -y --version 4.2.1 --limit-output
 
 cd github/grpc
 set PATH=C:\tools\msys64\usr\bin;C:\Python27;%PATH%
index 17a362f..459f3c6 100644 (file)
@@ -16,7 +16,7 @@
 
 # Location of the continuous shell script in repository.
 build_file: "grpc/tools/internal_ci/windows/grpc_run_tests_matrix.bat"
-timeout_mins: 60
+timeout_mins: 90
 action {
   define_artifacts {
     regex: "**/*sponge_log.*"
index c68e0ff..2d75778 100644 (file)
@@ -16,7 +16,7 @@
 
 # Location of the continuous shell script in repository.
 build_file: "grpc/tools/internal_ci/windows/grpc_run_tests_matrix.bat"
-timeout_mins: 90
+timeout_mins: 180
 action {
   define_artifacts {
     regex: "**/*sponge_log.*"
index e1c5af1..e5815b3 100644 (file)
@@ -16,7 +16,7 @@
 
 # Location of the continuous shell script in repository.
 build_file: "grpc/tools/internal_ci/windows/grpc_run_tests_matrix.bat"
-timeout_mins: 60
+timeout_mins: 90
 action {
   define_artifacts {
     regex: "**/*sponge_log.*"
index 5e58bdb..b9f7aa3 100644 (file)
@@ -192,6 +192,7 @@ LANG_RELEASE_MATRIX = {
             ('v1.38.1', ReleaseInfo(runtimes=['go1.16'])),
             ('v1.39.1', ReleaseInfo(runtimes=['go1.16'])),
             ('v1.40.0', ReleaseInfo(runtimes=['go1.16'])),
+            ('v1.41.0', ReleaseInfo(runtimes=['go1.16'])),
         ]),
     'java':
         OrderedDict([
@@ -266,6 +267,7 @@ LANG_RELEASE_MATRIX = {
             ('v1.38.1', ReleaseInfo()),
             ('v1.39.0', ReleaseInfo()),
             ('v1.40.1', ReleaseInfo()),
+            ('v1.41.0', ReleaseInfo()),
         ]),
     'python':
         OrderedDict([
diff --git a/tools/line_count/collect-history.py b/tools/line_count/collect-history.py
deleted file mode 100755 (executable)
index 6e21aaf..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/usr/bin/env python
-# 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.
-
-import datetime
-import subprocess
-
-# this script is only of historical interest: it's the script that was used to
-# bootstrap the dataset
-
-
-def daterange(start, end):
-    for n in range(int((end - start).days)):
-        yield start + datetime.timedelta(n)
-
-
-start_date = datetime.date(2017, 3, 26)
-end_date = datetime.date(2017, 3, 29)
-
-for dt in daterange(start_date, end_date):
-    dmy = dt.strftime('%Y-%m-%d')
-    sha1 = subprocess.check_output(
-        ['git', 'rev-list', '-n', '1',
-         '--before=%s' % dmy, 'master']).strip()
-    subprocess.check_call(['git', 'checkout', sha1])
-    subprocess.check_call(['git', 'submodule', 'update'])
-    subprocess.check_call(['git', 'clean', '-f', '-x', '-d'])
-    subprocess.check_call([
-        'cloc', '--vcs=git', '--by-file', '--yaml',
-        '--out=../count/%s.yaml' % dmy, '.'
-    ])
diff --git a/tools/line_count/collect-now.sh b/tools/line_count/collect-now.sh
deleted file mode 100755 (executable)
index a577529..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/bin/bash
-# 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
-
-cloc --vcs=git --by-file --yaml --out=cloc.yaml .
-tools/line_count/yaml2csv.py -i cloc.yaml -d `date +%Y-%m-%d` -o cloc.csv
-bq load line_counts.grpc cloc.csv
-
diff --git a/tools/line_count/summarize-history.py b/tools/line_count/summarize-history.py
deleted file mode 100755 (executable)
index b173b5e..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/usr/bin/env python
-# 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.
-
-import datetime
-import subprocess
-
-# this script is only of historical interest: it's the script that was used to
-# bootstrap the dataset
-
-
-def daterange(start, end):
-    for n in range(int((end - start).days)):
-        yield start + datetime.timedelta(n)
-
-
-start_date = datetime.date(2017, 3, 26)
-end_date = datetime.date(2017, 3, 29)
-
-for dt in daterange(start_date, end_date):
-    dmy = dt.strftime('%Y-%m-%d')
-    print dmy
-    subprocess.check_call([
-        'tools/line_count/yaml2csv.py', '-i',
-        '../count/%s.yaml' % dmy, '-d', dmy, '-o',
-        '../count/%s.csv' % dmy
-    ])
diff --git a/tools/line_count/yaml2csv.py b/tools/line_count/yaml2csv.py
deleted file mode 100755 (executable)
index 98d42a3..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/usr/bin/env python
-# 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.
-
-import argparse
-import csv
-import datetime
-
-import yaml
-
-argp = argparse.ArgumentParser(description='Convert cloc yaml to bigquery csv')
-argp.add_argument('-i', '--input', type=str)
-argp.add_argument('-d',
-                  '--date',
-                  type=str,
-                  default=datetime.date.today().strftime('%Y-%m-%d'))
-argp.add_argument('-o', '--output', type=str, default='out.csv')
-args = argp.parse_args()
-
-data = yaml.load(open(args.input).read())
-with open(args.output, 'w') as outf:
-    writer = csv.DictWriter(
-        outf, ['date', 'name', 'language', 'code', 'comment', 'blank'])
-    for key, value in data.iteritems():
-        if key == 'header':
-            continue
-        if key == 'SUM':
-            continue
-        if key.startswith('third_party/'):
-            continue
-        row = {'name': key, 'date': args.date}
-        row.update(value)
-        writer.writerow(row)
index b6bd1de..9d1d015 100755 (executable)
 # limitations under the License.
 
 import argparse
+import csv
 import glob
+import math
 import multiprocessing
 import os
+import pathlib
 import shutil
 import subprocess
 import sys
@@ -71,27 +74,48 @@ if args.diff_base:
         subprocess.check_call(['git', 'checkout', where_am_i])
         subprocess.check_call(['git', 'submodule', 'update'])
 
-subprocess.check_call('make -j%d' % args.jobs,
-                      shell=True,
-                      cwd='third_party/bloaty')
+pathlib.Path('bloaty-build').mkdir(exist_ok=True)
+subprocess.check_call(
+    ['cmake', '-G', 'Unix Makefiles', '../third_party/bloaty'],
+    cwd='bloaty-build')
+subprocess.check_call('make -j%d' % args.jobs, shell=True, cwd='bloaty-build')
 
 text = ''
+diff_size = 0
 for lib in LIBS:
     text += '****************************************************************\n\n'
     text += lib + '\n\n'
     old_version = glob.glob('bloat_diff_old/%s' % lib)
     new_version = glob.glob('bloat_diff_new/%s' % lib)
     assert len(new_version) == 1
-    cmd = 'third_party/bloaty/bloaty -d compileunits,symbols'
+    cmd = 'bloaty-build/bloaty -d compileunits,symbols'
     if old_version:
         assert len(old_version) == 1
         text += subprocess.check_output('%s %s -- %s' %
                                         (cmd, new_version[0], old_version[0]),
                                         shell=True).decode()
+        for filename in [old_version, new_version]:
+            subprocess.check_call('strip %s' % filename[0], shell=True)
+        sections = [
+            x for x in csv.reader(
+                subprocess.check_output('bloaty-build/bloaty --csv %s -- %s' %
+                                        (old_version[0], new_version[0]),
+                                        shell=True).decode().splitlines())
+        ]
+        print(sections)
+        for section in sections[1:]:
+            diff_size += int(section[2])
     else:
         text += subprocess.check_output('%s %s' % (cmd, new_version[0]),
                                         shell=True).decode()
     text += '\n\n'
 
+severity = int(
+    math.copysign(max(0, math.log(abs(diff_size) / 1000, 10),
+                      diff_size))) if diff_size != 0 else 0
+
+print("SEVERITY: %d" % severity)
+
 print(text)
 check_on_pr.check_on_pr('Bloat Difference', '```\n%s\n```' % text)
+check_on_pr.label_significance_on_pr('bloat', severity)
index 0f5aab5..cfba62a 100644 (file)
@@ -81,7 +81,7 @@ _BM_SPECS = {
         'dyn': ['end_of_stream', 'request_size'],
     },
     'BM_HpackParserParseHeader': {
-        'tpl': ['fixture', 'on_header'],
+        'tpl': ['fixture'],
         'dyn': [],
     },
     'BM_CallCreateDestroy': {
index 5b5dcdf..f8369ec 100644 (file)
@@ -87,8 +87,3 @@ build:ubsan --copt=-gmlt
 # use double the default value for "moderate" and "long" timeout as sanitizer
 # tests tend to be slower
 build:ubsan --test_timeout=60,600,1800,3600
-# override the config-agnostic crosstool_top
-# how to update the bazel toolchain for ubsan:
-# - check for the latest released version in https://github.com/bazelbuild/bazel-toolchains/tree/master/configs/experimental/ubuntu16_04_clang
-# - you might need to update the bazel_toolchains dependency in grpc_deps.bzl
-build:ubsan --crosstool_top=@bazel_toolchains//configs/experimental/ubuntu16_04_clang/1.3/bazel_0.29.1/ubsan:toolchain
index ad46605..6980e60 100644 (file)
@@ -353,10 +353,10 @@ def targets():
         PythonDistribTest('linux', 'x64', 'ubuntu1804'),
         PythonDistribTest('linux', 'aarch64', 'python38_buster'),
         PythonDistribTest('linux', 'x64', 'alpine3.7', source=True),
-        PythonDistribTest('linux', 'x64', 'jessie', source=True),
-        PythonDistribTest('linux', 'x86', 'jessie', source=True),
+        PythonDistribTest('linux', 'x64', 'buster', source=True),
+        PythonDistribTest('linux', 'x86', 'buster', source=True),
         PythonDistribTest('linux', 'x64', 'centos7', source=True),
-        PythonDistribTest('linux', 'x64', 'fedora23', source=True),
+        PythonDistribTest('linux', 'x64', 'fedora34', source=True),
         PythonDistribTest('linux', 'x64', 'arch', source=True),
         PythonDistribTest('linux', 'x64', 'ubuntu1804', source=True),
         # Ruby
index acf0571..bac4b22 100644 (file)
     "flaky": false,
     "gtest": false,
     "language": "c",
-    "name": "channel_stack_builder_test",
-    "platforms": [
-      "linux",
-      "mac",
-      "posix",
-      "windows"
-    ],
-    "uses_polling": true
-  },
-  {
-    "args": [],
-    "benchmark": false,
-    "ci_platforms": [
-      "linux",
-      "mac",
-      "posix",
-      "windows"
-    ],
-    "cpu_cost": 1.0,
-    "exclude_configs": [],
-    "exclude_iomgrs": [],
-    "flaky": false,
-    "gtest": false,
-    "language": "c",
     "name": "channel_stack_test",
     "platforms": [
       "linux",
     "ci_platforms": [
       "linux",
       "mac",
-      "posix",
-      "windows"
-    ],
-    "cpu_cost": 1.0,
-    "exclude_configs": [],
-    "exclude_iomgrs": [],
-    "flaky": false,
-    "gtest": false,
-    "language": "c",
-    "name": "error_test",
-    "platforms": [
-      "linux",
-      "mac",
-      "posix",
-      "windows"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [],
-    "benchmark": false,
-    "ci_platforms": [
-      "linux",
-      "mac",
       "posix"
     ],
     "cpu_cost": 1.0,
     "ci_platforms": [
       "linux",
       "mac",
-      "posix",
-      "windows"
-    ],
-    "cpu_cost": 1.0,
-    "exclude_configs": [],
-    "exclude_iomgrs": [],
-    "flaky": false,
-    "gtest": false,
-    "language": "c",
-    "name": "hpack_parser_table_test",
-    "platforms": [
-      "linux",
-      "mac",
-      "posix",
-      "windows"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [],
-    "benchmark": false,
-    "ci_platforms": [
-      "linux",
-      "mac",
-      "posix",
-      "windows"
-    ],
-    "cpu_cost": 1.0,
-    "exclude_configs": [],
-    "exclude_iomgrs": [],
-    "flaky": false,
-    "gtest": false,
-    "language": "c",
-    "name": "hpack_parser_test",
-    "platforms": [
-      "linux",
-      "mac",
-      "posix",
-      "windows"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [],
-    "benchmark": false,
-    "ci_platforms": [
-      "linux",
-      "mac",
       "posix"
     ],
     "cpu_cost": 1.0,
     "benchmark": false,
     "ci_platforms": [
       "linux",
+      "posix"
+    ],
+    "cpu_cost": 1.0,
+    "exclude_configs": [],
+    "exclude_iomgrs": [],
+    "flaky": false,
+    "gtest": false,
+    "language": "c",
+    "name": "memory_quota_stress_test",
+    "platforms": [
+      "linux",
+      "posix"
+    ],
+    "uses_polling": false
+  },
+  {
+    "args": [],
+    "benchmark": false,
+    "ci_platforms": [
+      "linux",
       "mac",
       "posix",
       "windows"
     "flaky": false,
     "gtest": false,
     "language": "c",
-    "name": "resource_quota_test",
+    "name": "secure_channel_create_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": false,
     "language": "c",
-    "name": "secure_channel_create_test",
+    "name": "secure_endpoint_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": false,
     "language": "c",
-    "name": "secure_endpoint_test",
+    "name": "security_connector_test",
     "platforms": [
       "linux",
       "mac",
     "ci_platforms": [
       "linux",
       "mac",
+      "posix"
+    ],
+    "cpu_cost": 1.0,
+    "exclude_configs": [],
+    "exclude_iomgrs": [],
+    "flaky": false,
+    "gtest": false,
+    "language": "c",
+    "name": "server_ssl_test",
+    "platforms": [
+      "linux",
+      "mac",
+      "posix"
+    ],
+    "uses_polling": true
+  },
+  {
+    "args": [],
+    "benchmark": false,
+    "ci_platforms": [
+      "linux",
+      "mac",
       "posix",
       "windows"
     ],
     "flaky": false,
     "gtest": false,
     "language": "c",
-    "name": "security_connector_test",
+    "name": "server_test",
     "platforms": [
       "linux",
       "mac",
     "ci_platforms": [
       "linux",
       "mac",
-      "posix"
+      "posix",
+      "windows"
     ],
     "cpu_cost": 1.0,
     "exclude_configs": [],
     "flaky": false,
     "gtest": false,
     "language": "c",
-    "name": "server_ssl_test",
+    "name": "slice_buffer_test",
     "platforms": [
       "linux",
       "mac",
-      "posix"
+      "posix",
+      "windows"
     ],
-    "uses_polling": true
+    "uses_polling": false
   },
   {
     "args": [],
     "flaky": false,
     "gtest": false,
     "language": "c",
-    "name": "server_test",
+    "name": "slice_intern_test",
     "platforms": [
       "linux",
       "mac",
       "posix",
       "windows"
     ],
-    "uses_polling": true
+    "uses_polling": false
   },
   {
     "args": [],
     "flaky": false,
     "gtest": false,
     "language": "c",
-    "name": "slice_buffer_test",
+    "name": "slice_split_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": false,
     "language": "c",
-    "name": "test_core_security_credentials_test",
+    "name": "test_core_iomgr_resource_quota_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": false,
     "language": "c",
-    "name": "test_core_slice_slice_test",
+    "name": "test_core_security_credentials_test",
     "platforms": [
       "linux",
       "mac",
       "posix",
       "windows"
     ],
-    "uses_polling": false
+    "uses_polling": true
   },
   {
     "args": [],
     "flaky": false,
     "gtest": false,
     "language": "c",
-    "name": "thd_test",
+    "name": "test_core_slice_slice_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": false,
     "language": "c",
-    "name": "threadpool_test",
+    "name": "thd_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": false,
     "language": "c",
-    "name": "time_averaged_stats_test",
+    "name": "threadpool_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": false,
     "language": "c",
-    "name": "timeout_encoding_test",
+    "name": "time_averaged_stats_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": false,
     "language": "c",
-    "name": "timer_heap_test",
+    "name": "timeout_encoding_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": false,
     "language": "c",
-    "name": "timer_list_test",
+    "name": "timer_heap_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": false,
     "language": "c",
-    "name": "transport_security_common_api_test",
+    "name": "timer_list_test",
     "platforms": [
       "linux",
       "mac",
       "posix",
       "windows"
     ],
-    "uses_polling": true
+    "uses_polling": false
   },
   {
     "args": [],
     "flaky": false,
     "gtest": false,
     "language": "c",
-    "name": "transport_security_test",
+    "name": "transport_security_common_api_test",
     "platforms": [
       "linux",
       "mac",
     "ci_platforms": [
       "linux",
       "mac",
-      "posix"
-    ],
-    "cpu_cost": 1.0,
-    "exclude_configs": [],
-    "exclude_iomgrs": [],
-    "flaky": false,
-    "gtest": false,
-    "language": "c",
-    "name": "udp_server_test",
-    "platforms": [
-      "linux",
-      "mac",
-      "posix"
-    ],
-    "uses_polling": true
-  },
-  {
-    "args": [],
-    "benchmark": false,
-    "ci_platforms": [
-      "linux",
-      "mac",
       "posix",
       "windows"
     ],
     "flaky": false,
     "gtest": false,
     "language": "c",
-    "name": "useful_test",
+    "name": "transport_security_test",
     "platforms": [
       "linux",
       "mac",
       "posix",
       "windows"
     ],
-    "uses_polling": false
+    "uses_polling": true
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "binder_server_test",
+    "name": "binder_resolver_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "binder_transport_test",
+    "name": "binder_server_test",
     "platforms": [
       "linux",
       "mac",
       "posix",
       "windows"
     ],
-    "uses_polling": false
+    "uses_polling": true
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "bitset_test",
+    "name": "binder_transport_test",
     "platforms": [
       "linux",
       "mac",
   },
   {
     "args": [],
-    "benchmark": true,
+    "benchmark": false,
     "ci_platforms": [
       "linux",
-      "posix"
+      "mac",
+      "posix",
+      "windows"
     ],
     "cpu_cost": 1.0,
     "exclude_configs": [],
     "exclude_iomgrs": [],
     "flaky": false,
-    "gtest": false,
+    "gtest": true,
     "language": "c++",
-    "name": "bm_alarm",
+    "name": "bitset_test",
     "platforms": [
       "linux",
-      "posix"
+      "mac",
+      "posix",
+      "windows"
     ],
-    "uses_polling": true
+    "uses_polling": false
   },
   {
     "args": [],
-    "benchmark": true,
+    "benchmark": false,
     "ci_platforms": [
       "linux",
-      "posix"
+      "mac",
+      "posix",
+      "windows"
     ],
     "cpu_cost": 1.0,
     "exclude_configs": [],
     "exclude_iomgrs": [],
     "flaky": false,
-    "gtest": false,
+    "gtest": true,
     "language": "c++",
-    "name": "bm_arena",
+    "name": "byte_buffer_test",
     "platforms": [
       "linux",
-      "posix"
+      "mac",
+      "posix",
+      "windows"
     ],
     "uses_polling": false
   },
   {
     "args": [],
-    "benchmark": true,
+    "benchmark": false,
     "ci_platforms": [
       "linux",
-      "posix"
+      "mac",
+      "posix",
+      "windows"
     ],
     "cpu_cost": 1.0,
     "exclude_configs": [],
     "exclude_iomgrs": [],
     "flaky": false,
-    "gtest": false,
+    "gtest": true,
     "language": "c++",
-    "name": "bm_byte_buffer",
+    "name": "byte_stream_test",
     "platforms": [
       "linux",
-      "posix"
+      "mac",
+      "posix",
+      "windows"
     ],
     "uses_polling": false
   },
   {
     "args": [],
-    "benchmark": true,
+    "benchmark": false,
     "ci_platforms": [
       "linux",
-      "posix"
+      "mac",
+      "posix",
+      "windows"
     ],
     "cpu_cost": 1.0,
     "exclude_configs": [],
     "exclude_iomgrs": [],
     "flaky": false,
-    "gtest": false,
+    "gtest": true,
     "language": "c++",
-    "name": "bm_call_create",
+    "name": "cancel_ares_query_test",
     "platforms": [
       "linux",
-      "posix"
+      "mac",
+      "posix",
+      "windows"
     ],
-    "uses_polling": false
+    "uses_polling": true
   },
   {
     "args": [],
-    "benchmark": true,
+    "benchmark": false,
     "ci_platforms": [
       "linux",
-      "posix"
+      "mac",
+      "posix",
+      "windows"
     ],
     "cpu_cost": 1.0,
     "exclude_configs": [],
     "exclude_iomgrs": [],
     "flaky": false,
-    "gtest": false,
+    "gtest": true,
     "language": "c++",
-    "name": "bm_channel",
+    "name": "capture_test",
     "platforms": [
       "linux",
-      "posix"
+      "mac",
+      "posix",
+      "windows"
     ],
     "uses_polling": false
   },
   {
     "args": [],
-    "benchmark": true,
+    "benchmark": false,
     "ci_platforms": [
       "linux",
-      "posix"
+      "mac",
+      "posix",
+      "windows"
     ],
     "cpu_cost": 1.0,
     "exclude_configs": [],
     "exclude_iomgrs": [],
     "flaky": false,
-    "gtest": false,
+    "gtest": true,
     "language": "c++",
-    "name": "bm_chttp2_hpack",
+    "name": "cel_authorization_engine_test",
     "platforms": [
       "linux",
-      "posix"
+      "mac",
+      "posix",
+      "windows"
     ],
-    "uses_polling": false
+    "uses_polling": true
   },
   {
     "args": [],
-    "benchmark": true,
+    "benchmark": false,
     "ci_platforms": [
       "linux",
-      "posix"
+      "mac",
+      "posix",
+      "windows"
     ],
     "cpu_cost": 1.0,
     "exclude_configs": [],
     "exclude_iomgrs": [],
     "flaky": false,
-    "gtest": false,
+    "gtest": true,
     "language": "c++",
-    "name": "bm_chttp2_transport",
+    "name": "certificate_provider_registry_test",
     "platforms": [
       "linux",
-      "posix"
+      "mac",
+      "posix",
+      "windows"
     ],
     "uses_polling": true
   },
   {
     "args": [],
-    "benchmark": true,
+    "benchmark": false,
     "ci_platforms": [
       "linux",
-      "posix"
+      "mac",
+      "posix",
+      "windows"
     ],
     "cpu_cost": 1.0,
     "exclude_configs": [],
     "exclude_iomgrs": [],
     "flaky": false,
-    "gtest": false,
+    "gtest": true,
     "language": "c++",
-    "name": "bm_closure",
+    "name": "certificate_provider_store_test",
     "platforms": [
       "linux",
-      "posix"
+      "mac",
+      "posix",
+      "windows"
     ],
     "uses_polling": true
   },
   {
     "args": [],
-    "benchmark": true,
+    "benchmark": false,
     "ci_platforms": [
       "linux",
-      "posix"
+      "mac",
+      "posix",
+      "windows"
     ],
     "cpu_cost": 1.0,
     "exclude_configs": [],
     "exclude_iomgrs": [],
     "flaky": false,
-    "gtest": false,
+    "gtest": true,
     "language": "c++",
-    "name": "bm_cq",
+    "name": "channel_arguments_test",
     "platforms": [
       "linux",
-      "posix"
+      "mac",
+      "posix",
+      "windows"
     ],
-    "uses_polling": true
+    "uses_polling": false
   },
   {
     "args": [],
-    "benchmark": true,
+    "benchmark": false,
     "ci_platforms": [
       "linux",
-      "posix"
+      "mac",
+      "posix",
+      "windows"
     ],
     "cpu_cost": 1.0,
     "exclude_configs": [],
     "exclude_iomgrs": [],
     "flaky": false,
-    "gtest": false,
+    "gtest": true,
     "language": "c++",
-    "name": "bm_cq_multiple_threads",
+    "name": "channel_filter_test",
     "platforms": [
       "linux",
-      "posix"
+      "mac",
+      "posix",
+      "windows"
     ],
     "uses_polling": false
   },
   {
     "args": [],
-    "benchmark": true,
+    "benchmark": false,
     "ci_platforms": [
       "linux",
-      "posix"
+      "mac",
+      "posix",
+      "windows"
     ],
     "cpu_cost": 1.0,
     "exclude_configs": [],
     "exclude_iomgrs": [],
     "flaky": false,
-    "gtest": false,
+    "gtest": true,
     "language": "c++",
-    "name": "bm_error",
+    "name": "channel_stack_builder_test",
     "platforms": [
       "linux",
-      "posix"
+      "mac",
+      "posix",
+      "windows"
     ],
-    "uses_polling": false
+    "uses_polling": true
   },
   {
     "args": [],
-    "benchmark": true,
+    "benchmark": false,
     "ci_platforms": [
       "linux",
-      "posix"
+      "mac",
+      "posix",
+      "windows"
     ],
     "cpu_cost": 1.0,
     "exclude_configs": [],
     "exclude_iomgrs": [],
     "flaky": false,
-    "gtest": false,
+    "gtest": true,
     "language": "c++",
-    "name": "bm_fullstack_streaming_ping_pong",
+    "name": "channel_trace_test",
     "platforms": [
       "linux",
-      "posix"
+      "mac",
+      "posix",
+      "windows"
     ],
     "uses_polling": true
   },
   {
     "args": [],
-    "benchmark": true,
+    "benchmark": false,
     "ci_platforms": [
       "linux",
-      "posix"
+      "mac",
+      "posix",
+      "windows"
     ],
     "cpu_cost": 1.0,
     "exclude_configs": [],
     "exclude_iomgrs": [],
     "flaky": false,
-    "gtest": false,
+    "gtest": true,
     "language": "c++",
-    "name": "bm_fullstack_streaming_pump",
+    "name": "channelz_registry_test",
     "platforms": [
       "linux",
-      "posix"
+      "mac",
+      "posix",
+      "windows"
     ],
-    "uses_polling": true
+    "uses_polling": false
   },
   {
     "args": [],
-    "benchmark": true,
+    "benchmark": false,
     "ci_platforms": [
       "linux",
-      "posix"
+      "mac",
+      "posix",
+      "windows"
     ],
     "cpu_cost": 1.0,
     "exclude_configs": [],
     "exclude_iomgrs": [],
     "flaky": false,
-    "gtest": false,
+    "gtest": true,
     "language": "c++",
-    "name": "bm_fullstack_unary_ping_pong",
+    "name": "channelz_service_test",
     "platforms": [
       "linux",
-      "posix"
+      "mac",
+      "posix",
+      "windows"
     ],
     "uses_polling": true
   },
   {
     "args": [],
-    "benchmark": true,
+    "benchmark": false,
     "ci_platforms": [
       "linux",
-      "posix"
+      "mac",
+      "posix",
+      "windows"
     ],
     "cpu_cost": 1.0,
     "exclude_configs": [],
     "exclude_iomgrs": [],
     "flaky": false,
-    "gtest": false,
+    "gtest": true,
     "language": "c++",
-    "name": "bm_metadata",
+    "name": "channelz_test",
     "platforms": [
       "linux",
-      "posix"
+      "mac",
+      "posix",
+      "windows"
     ],
-    "uses_polling": false
+    "uses_polling": true
   },
   {
     "args": [],
-    "benchmark": true,
+    "benchmark": false,
     "ci_platforms": [
       "linux",
-      "posix"
+      "mac",
+      "posix",
+      "windows"
     ],
     "cpu_cost": 1.0,
     "exclude_configs": [],
     "exclude_iomgrs": [],
     "flaky": false,
-    "gtest": false,
+    "gtest": true,
     "language": "c++",
-    "name": "bm_pollset",
+    "name": "chunked_vector_test",
     "platforms": [
       "linux",
-      "posix"
+      "mac",
+      "posix",
+      "windows"
     ],
-    "uses_polling": true
+    "uses_polling": false
   },
   {
     "args": [],
-    "benchmark": true,
+    "benchmark": false,
     "ci_platforms": [
       "linux",
-      "posix"
+      "mac",
+      "posix",
+      "windows"
     ],
     "cpu_cost": 1.0,
     "exclude_configs": [],
     "exclude_iomgrs": [],
     "flaky": false,
-    "gtest": false,
+    "gtest": true,
     "language": "c++",
-    "name": "bm_timer",
+    "name": "cli_call_test",
     "platforms": [
       "linux",
-      "posix"
+      "mac",
+      "posix",
+      "windows"
     ],
-    "uses_polling": false
+    "uses_polling": true
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "byte_buffer_test",
+    "name": "client_callback_end2end_test",
     "platforms": [
       "linux",
       "mac",
       "posix",
       "windows"
     ],
-    "uses_polling": false
+    "uses_polling": true
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "byte_stream_test",
+    "name": "client_context_test_peer_test",
     "platforms": [
       "linux",
       "mac",
       "posix",
       "windows"
     ],
-    "uses_polling": false
+    "uses_polling": true
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "cancel_ares_query_test",
+    "name": "client_interceptors_end2end_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "capture_test",
+    "name": "codegen_test_full",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "cel_authorization_engine_test",
+    "name": "codegen_test_minimal",
     "platforms": [
       "linux",
       "mac",
       "posix",
       "windows"
     ],
-    "uses_polling": true
+    "uses_polling": false
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "certificate_provider_registry_test",
+    "name": "connection_prefix_bad_client_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "certificate_provider_store_test",
+    "name": "connectivity_state_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "channel_arguments_test",
+    "name": "context_allocator_end2end_test",
     "platforms": [
       "linux",
       "mac",
       "posix",
       "windows"
     ],
-    "uses_polling": false
+    "uses_polling": true
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "channel_filter_test",
+    "name": "context_list_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "channel_trace_test",
+    "name": "context_test",
     "platforms": [
       "linux",
       "mac",
       "posix",
       "windows"
     ],
-    "uses_polling": true
+    "uses_polling": false
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "channelz_registry_test",
+    "name": "core_configuration_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "channelz_service_test",
+    "name": "delegating_channel_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "channelz_test",
+    "name": "destroy_grpclb_channel_with_active_connect_stress_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "cli_call_test",
+    "name": "dual_ref_counted_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "client_callback_end2end_test",
+    "name": "duplicate_header_bad_client_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "client_context_test_peer_test",
+    "name": "end2end_binder_transport_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "client_interceptors_end2end_test",
+    "name": "endpoint_binder_pool_test",
     "platforms": [
       "linux",
       "mac",
       "posix",
       "windows"
     ],
-    "uses_polling": true
+    "uses_polling": false
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "codegen_test_full",
+    "name": "endpoint_config_test",
     "platforms": [
       "linux",
       "mac",
       "posix",
       "windows"
     ],
-    "uses_polling": false
+    "uses_polling": true
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "codegen_test_minimal",
+    "name": "error_details_test",
     "platforms": [
       "linux",
       "mac",
       "posix",
       "windows"
     ],
-    "uses_polling": false
+    "uses_polling": true
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "connection_prefix_bad_client_test",
+    "name": "error_test",
     "platforms": [
       "linux",
       "mac",
       "posix",
       "windows"
     ],
-    "uses_polling": true
+    "uses_polling": false
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "connectivity_state_test",
+    "name": "error_utils_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "context_allocator_end2end_test",
+    "name": "evaluate_args_test",
     "platforms": [
       "linux",
       "mac",
     "ci_platforms": [
       "linux",
       "mac",
-      "posix",
-      "windows"
+      "posix"
     ],
     "cpu_cost": 1.0,
     "exclude_configs": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "context_list_test",
+    "name": "examine_stack_test",
     "platforms": [
       "linux",
       "mac",
-      "posix",
-      "windows"
+      "posix"
     ],
     "uses_polling": false
   },
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "context_test",
+    "name": "exception_test",
     "platforms": [
       "linux",
       "mac",
       "posix",
       "windows"
     ],
-    "uses_polling": false
+    "uses_polling": true
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "core_configuration_test",
+    "name": "exec_ctx_wakeup_scheduler_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "delegating_channel_test",
+    "name": "fake_binder_test",
     "platforms": [
       "linux",
       "mac",
       "posix",
       "windows"
     ],
-    "uses_polling": true
+    "uses_polling": false
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "destroy_grpclb_channel_with_active_connect_stress_test",
+    "name": "file_watcher_certificate_provider_factory_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "dual_ref_counted_test",
+    "name": "filter_end2end_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "duplicate_header_bad_client_test",
+    "name": "flow_control_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "end2end_binder_transport_test",
+    "name": "for_each_test",
     "platforms": [
       "linux",
       "mac",
       "posix",
       "windows"
     ],
-    "uses_polling": true
+    "uses_polling": false
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "endpoint_config_test",
+    "name": "generic_end2end_test",
     "platforms": [
       "linux",
       "mac",
     "ci_platforms": [
       "linux",
       "mac",
-      "posix",
-      "windows"
+      "posix"
     ],
     "cpu_cost": 1.0,
     "exclude_configs": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "error_details_test",
+    "name": "global_config_env_test",
     "platforms": [
       "linux",
       "mac",
-      "posix",
-      "windows"
+      "posix"
     ],
-    "uses_polling": true
+    "uses_polling": false
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "error_utils_test",
+    "name": "global_config_test",
     "platforms": [
       "linux",
       "mac",
       "posix",
       "windows"
     ],
-    "uses_polling": true
+    "uses_polling": false
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "evaluate_args_test",
+    "name": "google_mesh_ca_certificate_provider_factory_test",
     "platforms": [
       "linux",
       "mac",
     "ci_platforms": [
       "linux",
       "mac",
-      "posix"
+      "posix",
+      "windows"
     ],
     "cpu_cost": 1.0,
     "exclude_configs": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "examine_stack_test",
+    "name": "grpc_authorization_engine_test",
     "platforms": [
       "linux",
       "mac",
-      "posix"
+      "posix",
+      "windows"
     ],
-    "uses_polling": false
+    "uses_polling": true
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "exception_test",
+    "name": "grpc_authorization_policy_provider_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "fake_binder_test",
+    "name": "grpc_tls_certificate_distributor_test",
     "platforms": [
       "linux",
       "mac",
       "posix",
       "windows"
     ],
-    "uses_polling": false
+    "uses_polling": true
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "file_watcher_certificate_provider_factory_test",
+    "name": "grpc_tls_certificate_provider_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "filter_end2end_test",
+    "name": "grpc_tls_credentials_options_test",
     "platforms": [
       "linux",
       "mac",
     "ci_platforms": [
       "linux",
       "mac",
-      "posix",
-      "windows"
+      "posix"
     ],
     "cpu_cost": 1.0,
     "exclude_configs": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "flow_control_test",
+    "name": "grpc_tool_test",
     "platforms": [
       "linux",
       "mac",
-      "posix",
-      "windows"
+      "posix"
     ],
     "uses_polling": true
   },
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "for_each_test",
+    "name": "grpclb_api_test",
     "platforms": [
       "linux",
       "mac",
       "posix",
       "windows"
     ],
-    "uses_polling": false
+    "uses_polling": true
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "generic_end2end_test",
+    "name": "h2_ssl_session_reuse_test",
     "platforms": [
       "linux",
       "mac",
     "ci_platforms": [
       "linux",
       "mac",
-      "posix"
+      "posix",
+      "windows"
     ],
     "cpu_cost": 1.0,
     "exclude_configs": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "global_config_env_test",
+    "name": "head_of_line_blocking_bad_client_test",
     "platforms": [
       "linux",
       "mac",
-      "posix"
+      "posix",
+      "windows"
     ],
-    "uses_polling": false
+    "uses_polling": true
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "global_config_test",
+    "name": "headers_bad_client_test",
     "platforms": [
       "linux",
       "mac",
       "posix",
       "windows"
     ],
-    "uses_polling": false
+    "uses_polling": true
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "google_mesh_ca_certificate_provider_factory_test",
+    "name": "health_service_end2end_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "grpc_authorization_engine_test",
+    "name": "hpack_encoder_index_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "grpc_authorization_policy_provider_test",
+    "name": "hpack_parser_table_test",
     "platforms": [
       "linux",
       "mac",
       "posix",
       "windows"
     ],
-    "uses_polling": true
+    "uses_polling": false
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "grpc_tls_certificate_distributor_test",
+    "name": "hpack_parser_test",
     "platforms": [
       "linux",
       "mac",
       "posix",
       "windows"
     ],
-    "uses_polling": true
+    "uses_polling": false
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "grpc_tls_certificate_provider_test",
+    "name": "hybrid_end2end_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "grpc_tls_credentials_options_test",
+    "name": "idle_filter_state_test",
     "platforms": [
       "linux",
       "mac",
       "posix",
       "windows"
     ],
-    "uses_polling": true
+    "uses_polling": false
   },
   {
     "args": [],
     "ci_platforms": [
       "linux",
       "mac",
-      "posix"
+      "posix",
+      "windows"
     ],
     "cpu_cost": 1.0,
     "exclude_configs": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "grpc_tool_test",
+    "name": "if_test",
     "platforms": [
       "linux",
       "mac",
-      "posix"
+      "posix",
+      "windows"
     ],
-    "uses_polling": true
+    "uses_polling": false
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "grpclb_api_test",
+    "name": "init_test",
     "platforms": [
       "linux",
       "mac",
       "posix",
       "windows"
     ],
-    "uses_polling": true
+    "uses_polling": false
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "h2_ssl_session_reuse_test",
+    "name": "initial_settings_frame_bad_client_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "head_of_line_blocking_bad_client_test",
+    "name": "insecure_security_connector_test",
     "platforms": [
       "linux",
       "mac",
     "ci_platforms": [
       "linux",
       "mac",
-      "posix",
-      "windows"
+      "posix"
     ],
     "cpu_cost": 1.0,
     "exclude_configs": [],
     "exclude_iomgrs": [],
     "flaky": false,
-    "gtest": true,
+    "gtest": false,
     "language": "c++",
-    "name": "headers_bad_client_test",
+    "name": "interop_test",
     "platforms": [
       "linux",
       "mac",
-      "posix",
-      "windows"
+      "posix"
     ],
     "uses_polling": true
   },
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "health_service_end2end_test",
+    "name": "join_test",
     "platforms": [
       "linux",
       "mac",
       "posix",
       "windows"
     ],
-    "uses_polling": true
+    "uses_polling": false
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "hpack_encoder_index_test",
+    "name": "json_test",
     "platforms": [
       "linux",
       "mac",
       "posix",
       "windows"
     ],
-    "uses_polling": true
+    "uses_polling": false
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "hybrid_end2end_test",
+    "name": "large_metadata_bad_client_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "if_test",
+    "name": "latch_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "init_test",
+    "name": "lb_get_cpu_stats_test",
     "platforms": [
       "linux",
       "mac",
       "posix",
       "windows"
     ],
-    "uses_polling": false
+    "uses_polling": true
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "initial_settings_frame_bad_client_test",
+    "name": "lb_load_data_store_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "insecure_security_connector_test",
+    "name": "linux_system_roots_test",
     "platforms": [
       "linux",
       "mac",
     "ci_platforms": [
       "linux",
       "mac",
-      "posix"
+      "posix",
+      "windows"
     ],
     "cpu_cost": 1.0,
     "exclude_configs": [],
     "exclude_iomgrs": [],
     "flaky": false,
-    "gtest": false,
+    "gtest": true,
     "language": "c++",
-    "name": "interop_test",
+    "name": "log_test",
     "platforms": [
       "linux",
       "mac",
-      "posix"
+      "posix",
+      "windows"
     ],
-    "uses_polling": true
+    "uses_polling": false
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "join_test",
+    "name": "loop_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "json_test",
+    "name": "match_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "large_metadata_bad_client_test",
+    "name": "matchers_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "latch_test",
+    "name": "memory_quota_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "lb_get_cpu_stats_test",
+    "name": "message_allocator_end2end_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "lb_load_data_store_test",
+    "name": "metadata_map_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "linux_system_roots_test",
+    "name": "miscompile_with_no_unique_address_test",
     "platforms": [
       "linux",
       "mac",
       "posix",
       "windows"
     ],
-    "uses_polling": true
+    "uses_polling": false
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "log_test",
+    "name": "mock_stream_test",
     "platforms": [
       "linux",
       "mac",
       "posix",
       "windows"
     ],
-    "uses_polling": false
+    "uses_polling": true
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "loop_test",
+    "name": "mock_test",
     "platforms": [
       "linux",
       "mac",
       "posix",
       "windows"
     ],
-    "uses_polling": false
+    "uses_polling": true
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "match_test",
+    "name": "nonblocking_test",
     "platforms": [
       "linux",
       "mac",
       "posix",
       "windows"
     ],
-    "uses_polling": false
+    "uses_polling": true
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "matchers_test",
+    "name": "observable_test",
     "platforms": [
       "linux",
       "mac",
       "posix",
       "windows"
     ],
-    "uses_polling": true
+    "uses_polling": false
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "message_allocator_end2end_test",
+    "name": "orphanable_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "miscompile_with_no_unique_address_test",
+    "name": "out_of_bounds_bad_client_test",
     "platforms": [
       "linux",
       "mac",
       "posix",
       "windows"
     ],
-    "uses_polling": false
+    "uses_polling": true
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "mock_stream_test",
+    "name": "overload_test",
     "platforms": [
       "linux",
       "mac",
       "posix",
       "windows"
     ],
-    "uses_polling": true
+    "uses_polling": false
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "mock_test",
+    "name": "parsed_metadata_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "nonblocking_test",
+    "name": "pid_controller_test",
     "platforms": [
       "linux",
       "mac",
   },
   {
     "args": [],
-    "benchmark": true,
+    "benchmark": false,
     "ci_platforms": [
       "linux",
       "mac",
     "exclude_configs": [],
     "exclude_iomgrs": [],
     "flaky": false,
-    "gtest": false,
+    "gtest": true,
     "language": "c++",
-    "name": "noop-benchmark",
+    "name": "pipe_test",
     "platforms": [
       "linux",
       "mac",
       "posix",
       "windows"
     ],
-    "uses_polling": true
+    "uses_polling": false
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "observable_test",
+    "name": "poll_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "orphanable_test",
+    "name": "popularity_count_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "out_of_bounds_bad_client_test",
+    "name": "port_sharing_end2end_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "overload_test",
+    "name": "promise_factory_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "pid_controller_test",
+    "name": "promise_map_test",
     "platforms": [
       "linux",
       "mac",
       "posix",
       "windows"
     ],
-    "uses_polling": true
+    "uses_polling": false
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "pipe_test",
+    "name": "promise_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "poll_test",
+    "name": "proto_server_reflection_test",
     "platforms": [
       "linux",
       "mac",
       "posix",
       "windows"
     ],
-    "uses_polling": false
+    "uses_polling": true
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "popularity_count_test",
+    "name": "proto_utils_test",
     "platforms": [
       "linux",
       "mac",
       "posix",
       "windows"
     ],
-    "uses_polling": true
+    "uses_polling": false
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "port_sharing_end2end_test",
+    "name": "race_test",
     "platforms": [
       "linux",
       "mac",
       "posix",
       "windows"
     ],
-    "uses_polling": true
+    "uses_polling": false
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "promise_factory_test",
+    "name": "raw_end2end_test",
     "platforms": [
       "linux",
       "mac",
       "posix",
       "windows"
     ],
-    "uses_polling": false
+    "uses_polling": true
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "promise_map_test",
+    "name": "rbac_translator_test",
     "platforms": [
       "linux",
       "mac",
       "posix",
       "windows"
     ],
-    "uses_polling": false
+    "uses_polling": true
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "promise_test",
+    "name": "ref_counted_ptr_test",
     "platforms": [
       "linux",
       "mac",
       "posix",
       "windows"
     ],
-    "uses_polling": false
+    "uses_polling": true
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "proto_server_reflection_test",
+    "name": "ref_counted_test",
     "platforms": [
       "linux",
       "mac",
     "ci_platforms": [
       "linux",
       "mac",
-      "posix",
-      "windows"
+      "posix"
     ],
     "cpu_cost": 1.0,
     "exclude_configs": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "proto_utils_test",
+    "name": "remove_stream_from_stalled_lists_test",
     "platforms": [
       "linux",
       "mac",
-      "posix",
-      "windows"
+      "posix"
     ],
-    "uses_polling": false
+    "uses_polling": true
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "race_test",
+    "name": "retry_throttle_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "raw_end2end_test",
+    "name": "rls_end2end_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "rbac_translator_test",
+    "name": "rls_lb_config_parser_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "ref_counted_ptr_test",
+    "name": "sdk_authz_end2end_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "ref_counted_test",
+    "name": "secure_auth_context_test",
     "platforms": [
       "linux",
       "mac",
     "ci_platforms": [
       "linux",
       "mac",
-      "posix"
-    ],
-    "cpu_cost": 1.0,
-    "exclude_configs": [],
-    "exclude_iomgrs": [],
-    "flaky": false,
-    "gtest": true,
-    "language": "c++",
-    "name": "remove_stream_from_stalled_lists_test",
-    "platforms": [
-      "linux",
-      "mac",
-      "posix"
-    ],
-    "uses_polling": true
-  },
-  {
-    "args": [],
-    "benchmark": false,
-    "ci_platforms": [
-      "linux",
-      "mac",
       "posix",
       "windows"
     ],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "retry_throttle_test",
+    "name": "seq_test",
     "platforms": [
       "linux",
       "mac",
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "sdk_authz_end2end_test",
+    "name": "server_builder_plugin_test",
     "platforms": [
       "linux",
       "mac",
     "ci_platforms": [
       "linux",
       "mac",
-      "posix",
-      "windows"
+      "posix"
     ],
     "cpu_cost": 1.0,
     "exclude_configs": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "secure_auth_context_test",
+    "name": "server_builder_test",
     "platforms": [
       "linux",
       "mac",
-      "posix",
-      "windows"
+      "posix"
     ],
     "uses_polling": true
   },
     "ci_platforms": [
       "linux",
       "mac",
-      "posix",
-      "windows"
+      "posix"
     ],
     "cpu_cost": 1.0,
     "exclude_configs": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "seq_test",
+    "name": "server_builder_with_socket_mutator_test",
     "platforms": [
       "linux",
       "mac",
-      "posix",
-      "windows"
+      "posix"
     ],
-    "uses_polling": false
+    "uses_polling": true
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "server_builder_plugin_test",
+    "name": "server_chttp2_test",
     "platforms": [
       "linux",
       "mac",
     "ci_platforms": [
       "linux",
       "mac",
-      "posix"
-    ],
-    "cpu_cost": 1.0,
-    "exclude_configs": [],
-    "exclude_iomgrs": [],
-    "flaky": false,
-    "gtest": true,
-    "language": "c++",
-    "name": "server_builder_test",
-    "platforms": [
-      "linux",
-      "mac",
-      "posix"
-    ],
-    "uses_polling": true
-  },
-  {
-    "args": [],
-    "benchmark": false,
-    "ci_platforms": [
-      "linux",
-      "mac",
-      "posix"
-    ],
-    "cpu_cost": 1.0,
-    "exclude_configs": [],
-    "exclude_iomgrs": [],
-    "flaky": false,
-    "gtest": true,
-    "language": "c++",
-    "name": "server_builder_with_socket_mutator_test",
-    "platforms": [
-      "linux",
-      "mac",
-      "posix"
-    ],
-    "uses_polling": true
-  },
-  {
-    "args": [],
-    "benchmark": false,
-    "ci_platforms": [
-      "linux",
-      "mac",
       "posix",
       "windows"
     ],
     "flaky": false,
     "gtest": true,
     "language": "c++",
-    "name": "server_chttp2_test",
+    "name": "server_config_selector_test",
     "platforms": [
       "linux",
       "mac",
       "posix",
       "windows"
     ],
-    "uses_polling": true
+    "uses_polling": false
   },
   {
     "args": [],
     "flaky": false,
     "gtest": true,
     "language": "c++",
+    "name": "test_core_resource_quota_resource_quota_test",
+    "platforms": [
+      "linux",
+      "mac",
+      "posix",
+      "windows"
+    ],
+    "uses_polling": false
+  },
+  {
+    "args": [],
+    "benchmark": false,
+    "ci_platforms": [
+      "linux",
+      "mac",
+      "posix",
+      "windows"
+    ],
+    "cpu_cost": 1.0,
+    "exclude_configs": [],
+    "exclude_iomgrs": [],
+    "flaky": false,
+    "gtest": true,
+    "language": "c++",
     "name": "test_cpp_client_credentials_test",
     "platforms": [
       "linux",
     "ci_platforms": [
       "linux",
       "mac",
+      "posix",
+      "windows"
+    ],
+    "cpu_cost": 1.0,
+    "exclude_configs": [],
+    "exclude_iomgrs": [],
+    "flaky": false,
+    "gtest": true,
+    "language": "c++",
+    "name": "thread_quota_test",
+    "platforms": [
+      "linux",
+      "mac",
+      "posix",
+      "windows"
+    ],
+    "uses_polling": false
+  },
+  {
+    "args": [],
+    "benchmark": false,
+    "ci_platforms": [
+      "linux",
+      "mac",
       "posix"
     ],
     "cpu_cost": 1.0,
     "flaky": false,
     "gtest": true,
     "language": "c++",
+    "name": "useful_test",
+    "platforms": [
+      "linux",
+      "mac",
+      "posix",
+      "windows"
+    ],
+    "uses_polling": false
+  },
+  {
+    "args": [],
+    "benchmark": false,
+    "ci_platforms": [
+      "linux",
+      "mac",
+      "posix",
+      "windows"
+    ],
+    "cpu_cost": 1.0,
+    "exclude_configs": [],
+    "exclude_iomgrs": [],
+    "flaky": false,
+    "gtest": true,
+    "language": "c++",
     "name": "window_overflow_bad_client_test",
     "platforms": [
       "linux",
       "posix",
       "windows"
     ]
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/0149b46b88d583e05be0fb1423d10f2a14d36c48"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/047fc351e73f760d329d5a8845944720be9ce773"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/04ef96c66d8222d1a2c07e6b2a6548e6a527042b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/05a7e16c1d7f92111f43e9c777421879920e79a4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/063eb46f202fdfe7935c30ca38d7eb81c82db419"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/064773597c295fa871c184fc12d17b6de8aab31b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/087449740758b114d16790067707934479946bd6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/0a5d068feb57a2782c6eba57b637abe8668ac82f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/0b81e6d89bf7df80e87e5ee7c49f7cc1431f77e8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/11409339cec708a5e353893101bfe76364337d5c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/147696a264cd6f197adb7c68aff834c30b1b77f8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/160e5cac38c5c9e919ed6e4fbafee76907d63044"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/173d02167db431040b0540d98f6fc5e8b456587d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/18a3fe239806b3c7d1af24bcd2bd23aeeb072d5c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/195abd83b2e9d32b1b5b854fe33da44b6db40880"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/19af2509c7d84334b9ec64de4767a07d5294fd72"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/1b9864b948fcf08b062fd4401ef55b214c259535"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/1edddfa67de854d7faaba41418fda845e9c6a89d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/20031bb00e6608e1b570aa96e6afb9de06d42167"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/22b4c7ce7db99b0df63c9eae9265de484b695922"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/27416437ad287bd3cc1c5efdecebc39f20df73c1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/27e8cd785c2b9346f68dba75761b52fbabaf2b72"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/28236f860d3d8e5ea11176746cb4c1c5c4f1f6c0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/29e15b492c5a409938092a30c003c5c34df7e283"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/2a47864d77749aa042b772895dbdf46f608ccc6d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/2cca5cb1b135c35f6e5e1ec4c37deb9e12d37dc0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/2df27b6c42dbaee382a29a87338d64ee87354acb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/2e9ddd1339d8e599cef658a08965985c4f45e428"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/31a2d12a84a7a56ace831a9668d6ab4847390679"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/33cb9ec0ce3538ed6079b5fcb127649a5d05955b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/348d9ae6eebb2e1644addf7f07231d108cf6f3b8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/359f76f3c802292e92b0640de2bfe051e780a3b6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/35a479988e965a6e3e75138b64b0bd1f45073e2f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/362b00d713686ff70cb0199f3d7d0058e5a1a27a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/3849c1625071791ceae709b9c6c705b28d099d67"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/39ef03c66ee2d4bcfb6c8da50486dcd40f02fb12"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/3a3ca061863499ebc171a4f910fa1b49523baad4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/3a890f3fd01b048ac9db65a9a9b4f4443268b91a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/3b9554038a425bd1fae057ba41f9366bb467e946"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/3ce0ae4aa226f205a3a4e66bbb253419d9d754bf"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/3dccc5523986c37e27684659bba8a1037e7a92e8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/3e0908c15b1cede4541d25f388b1345e8641e221"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/3fcb181ff6a8c8e2ba38ed34cf78f7482eb55cb7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/41c9b5f720eb8f8fa04c840375a881781a849b43"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/4257a018f08f13a3a9adc848ef808e1be50bc4cf"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/42dfc5c4d13261b7259e65cd692df9c9d607194e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/43144664aedb585d45d42aa5249ddbfe81afe470"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/43e5ad495a47593b17dbcbd3e70c2e25a417bb6e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/446614e45b7bef49118b17e031c48faf167ebe3e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/46492477fa84ca88e85df914801af0b09b0939f6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/47157f83b166b57e0052c98a65c6db864fa6cb9b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/473fc9b6d768a925527d3ad805ca363d490dc741"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/483c0b4015100eee00f6b23d1100d8c4953dd3b1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/48be2dc4cdc5462407b319caa855d976cda88153"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/4e84eb54a0e438052b0c2e83653135042d9eb59a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/50839d5c8bf33f0970986dcc4b73b024f11a95b7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/523d964986d8ad966ae07e540a608681098813f9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/5410b8190c95dacd36d6e6ec75b7538a630e08de"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/549b2891ac79f504a7c9ea00f6d7527c34ce04e6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/55321649e7b7f1b5664ae20724e683c930643fc4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/55cc52f25865baee3e6e52c3110a9723caa2b3cb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/56c22410e3295ad03aa31552ab888f581756cc17"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/5724a705b62a7548ba2df1abe4ef0c970c4e1bd2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/576a148c107d56861d1611641a6f7c7921061c5c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/5a6b8263e8939f851cf5b1e347a33d97253b7b3d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/5ba93c9db0cff93f52b521d7420e43f6eda2784f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/5bd02a339fd7705449388580c75bfcc597aba954"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/5bd6fb6fc4163bf3a9db6ddaf509dce8df8a5000"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/5d06fc38005503af3d084721c60e574fb9d2f370"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/5ddc10489ff3269bdaa3051b70fb7af455ee1104"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/5ea9d515f0d10b04f1356b9463139bfe121a6e4a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/61c449793347cf2e1ed0c38d54d23c63dfaabeb8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/6287389c373e9788dcc04f9747b4be1fd1ef3028"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/64d4de4d5aafab7ec388a7fe83066c1a4d1d9d68"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/651c37806d2ac579dcfc97643c3c1ea74dbb8774"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/6551d02d20573cfa2944ec1f12b0c01f264a1326"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/65f029414ee10e45ff4b9f305f7b472364cea538"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/68b75a17fe2db060df3e61a597650ba99079abbf"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/69e80594dbc5c4c648e39883a650b1760f20ab63"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/6cb47d0e640b4c41e32f13c0d64ee46eae1b80b5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/6da5fe063432cb9094c7c083efdbbe5ba4246d18"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/6dd140da774d85f272fb587dc1b2a85d881a7c21"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/6ddab273597d73be49e2307d68e00fa18bba4765"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/6eaf85d84fbf47ea0619d0dba8d366f4e3ff0be6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/6f751cc09af8113f6ecd491b1830bd8454c4738d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/70d9eb29a70d483d07e2faca6b00098af78d1fff"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/7192effa1058382b379fb7b87f1acad5ac554d05"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/730e85d6a62e70cb6721009b903782ade4ff73a2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/74002471a854059cb29de7cad8f9fb7adc3c5ec2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/747f2330cd1fc4a06d54b376a9a6528d0364f0ac"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/749d5d7a9e0b1545b297117e834462af32b3e230"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/77de0b1de120ac702ca45868b1008a48626daf12"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/792c67398bce19a4eeda32653c994436e79456e5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/7a3022b248c8960289e4c80c7cc8df409499e5da"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/7a9372081294a6fbd3fecdd91b99589c98d4948e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/7bbe4ba828947550f4ad089d5989cb695ecbdb1b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/7f1ad514a96f0c3d5ca5d6f7880b929a65eeae96"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/7f2b075f0b6707c38db851747e2578343eeab286"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/81ebc64bfde3fad37af5a58ef7f1c5c3c54c4b5d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/82fae081afaea13831404024d39658344d56e1c6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/83ba41cea1adab707f7f213af5e2ed734bdddc25"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/841a3f66c94e5acd836a44cd5a8514d4ad45d83e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/841ef94ee0f1b0b45983d95b75aba25421d73f2c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/843b0aad4a9707c5dcc92d12d876b78675cfcb65"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/8483e3d92eda8df504b1d1d0d012f4bcd778cd33"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/876830fdff4e59038fa2173b700faef5bffe61de"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/87ca3342fdce0c1f678a3f1b62428032ef51442d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/87d044027cdb7d35fadb56532f497764246946a6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/88ce75ba18bdb7e93a81197d850f4e792f6a8155"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/89dc55e8e20e811e78c952c8bd2c16f55fe72f57"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/8a215a58908f44bdced595ceb01a81977f1d72f0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/8ac7459e918304ca40b1cf29a3ac0f555eada678"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/8b93e50a911f3ea0e0b0377ba4636574f2ee9a5e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/8c9ec0ffd803505772693833d56e7a02110645b3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/8e4b361a530dc6825afcfb4106bd482c3fd010fa"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/8f6690d97bcda890f2a5b2930a2b7a4d7b56c6e7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/917636de2c14dce2580d4308249a94d61d62c305"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/91f11008defda918951bda868cc68c6373fb0e6a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/92e01a34047b660a798086d55a3d8d7100a01939"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/963fafadb4de09dee0e6a852bd61b1740039a465"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/97bf33ec97b93fcc2449431915911a55b906e3b6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/99e31e12b02b02479d10b2c08426906bd93a0840"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/9a75ce693e7259d4d3bb9203dfc0a65f8bbaa466"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/9ac0d956f9743e026baad7319ba2a75d9f1a534f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/9ae56d4451dd3e1b66ddc250d84dbf6d8cae0dbd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/9b9a3a1e4023c9b172060249752a482a3437ef2a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/9c81164e10bf612c352dca3ecabf57743b451d42"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/9d8b420b5d32deb0140ab91eeebba58ca6163722"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/9de687bf1e2cfac54c3b2e2eb85b53014a460ff7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/9f3cda19a186bd11bfac361b464f92daa129a33b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/a14fc6a608121f8abf0fe25cf466720f00f25653"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/a39906074669a6b76a35b0adf2bf36ad751f3b35"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/a454ca483b4a66b83826d061be2859dd79ff0d6c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/a52df5607370ff0f56d821000f3d5e386a01d489"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/a56eaf47f7c7263e53efdc55ec39063dbb4ae71c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/a79249fb8f7d53f0a280359d2d9df31594adbdfc"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/aa98a46f25004f7436aadb36ff8b7f07ed7bfce1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/adc83b19e793491b1c6ea0fd8b46cd9f32e592fc"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/afd8e19f7bfd6c963f1856be59b75627864821dc"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/b3966239b8568442baecbeb0f8a1aa29dcdfd7ed"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/b430d41ef65493b3e917182c23ce90df983e01ab"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/b44e715e0cfe05f0c92a9e000ac3c36aae17df9d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/b4cf4ef7b3f64eff76cf99091fddc04411774708"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/b53d84468ea93620a9824ca65acf1179f431e763"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/b6ac4831cc5baabee9c8ab9af9ca3923f91097a0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/b7f4a484866a8050dbc63bc905c9803c6964eda5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/b8f21e59f90431c982d5ec3fb54ae4605f102252"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/bad10b6581cdead8e7cb96e4f544dcf0ea650fbc"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/bb01bed86b43257be9f527388e1183f52438c473"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/bb7497b00f0d999ef39dbf81c6bd0441e32723b6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/bf01b72e635deda1b4a8468f1cc36f01a54e1338"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/bf8b4530d8d246dd74ac53a13471bba17941dff7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/c08bc84ab6a512b901bb730beb05c8394e4f1c5d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/c244b635d94e6f5d6b344887434be3e001a04b41"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/c281efe9620da999a637ff6e9b3279ec613fb992"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/c30a212824ee71e215f475f453de17c65a200101"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/c449427f35b7ecdf5641073629f7723df52c4cb0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/c60240cd3b02eb71e2bf5ebd59afa3a5dc9b5e4d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/c60cdf9c3fb9060838f445b3bc3852b6f81e1e4c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/c72d0501bacadb45242c553ba292591302f12a6a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/c739e7b5ad999edbdeffdab672dbc30deb3959a0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/c7d73b12a7108d82f8dac6d8a6a34f838601aca6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/ca781e1add632433293e847ae9e71649c217ee5f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/cc48e916f40e8d69c2d07cfda42c7d3b7fe3447a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/cca1aff4c08ee4ccbcb6f80e1cd1480a0a093cfd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/cf6ae8bf1d08d25e235b7bee0839984bbc04edf6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/cfc52fa086292c699efd7bf41d2fae3deb449536"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/cfe13ef3c6c713a059f231f0001ecec97e2a932d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/d14026ac6421bca7161024f4e735cb80a1068d01"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/d2fb6e8f7867fc1e2ebe723da2b5246dc9cc6b14"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/d4db7d51bdaa4781cf12c3b59914bad414d2a41e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/d533da0e7f8c1e39bb025b4d7a89613142a6f54e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/d5cf489d01a1b847a7aac5dddabff23fdc218e1e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/d686f8561a249c7c15c78f76a5fceb884286e070"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/d92424daad9d96a40e5ab177e3824c36ef51dc0f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/db242a11ed88b2b26af46770dd1927d9f35301fb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/db32eb04db13d58f65f46d262608bd088987c063"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/db39a953317951759e40734de6607a0b4457728e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/dc5e8f3102456bed90d17303bc4cff1a7e076d5d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/dd9542bbed8e5dc58da2789edbfb9c38d578d3b4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/de2ebb1ed324385de500a1a3308846239857c3c7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/de8ba9158254c1cd84b53df1e4cdf1757b1392f1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/e1dd260746f50024822a8b729b89545d26decfb8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/e29add81b20dc570fdc885782689f6dccb1c5fad"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/e2e99af62843cd3b29d50daeb118e58830784da9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/e46611c5daf99662e1576147c1623409752a1f39"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/e5a1ba11af830e9d2db201c5164f75747a85fe9b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/e6026ee0badf216b326443a5f708446b2f2e579f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/e6c7d2c0038fa1f03fc6590a726abc98f4c641f3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/eafdef6a630bed71bd0e4f3d4a16b5fa0c920651"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/ece985b9b82e27281514d460709d7edf8203ded7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/edb8f4259f756c2c4bc731f05beaa36f992cf079"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/edce7778c2e1adb81dda3d057a6536759a7cb293"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/ee4040c0dd406dd616c49ed2c37b40478dabfe0f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/ee69f2b380663d051a70f30fcfce9f79f5341e5a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/efc6743e47274058771bb6eda1fefa017bde4a95"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/f0038e54162000694d882b1acb80930c807b41d2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/f1deb9e388c877337dabe92f31b01e2a019a10f4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/f3a09373e4d3c7310d372089e6deb15d6b22c198"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/f3db7ef6495fa1ac5bb4db293fb38dd59122bb7c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/f434bb4ceecc573e085d4c3ef453ef01e93d9c89"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/f55bceaad42ddf9d2b37fdfca68255d29a696109"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/f62ca5321428a5d23f3c804fb51eb4e65bc58716"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/f7c6a558b8d0af64db2b139371a7af7068b01b92"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/faa1781e1444bba5b8c677bc5e2a38d023a1ec65"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/fceba33ada1dda05fccedfefd331c9a201f1a2e5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/fd668bef6fdaf7f3ffd58d8c60ce550476652e60"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/fdf06b928e37e7c4ae59a568b5723ad98bbed6e5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/fe2fc5d499aeb2762387ef2e3ce939280813dec0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/alts_credentials_corpus/ff548d368b090409a138e5cc4afc7f43b4a3fbbd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "alts_credentials_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/001946397b463a3562c5951f6325069d8a3a2ded"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/0083d5addbeca55271ed7ef93c8016bf7ca76903"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/00c8446b230bebbae2b473552b174a06b446337a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/01b05a9eaa95950f697627264bbd5006060f68e5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/01c9569f5835a576fc50ea03141662c7ef1aa088"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/025215e11687c7d2e0055e5b2b902d08e0436f78"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/02ba99615d1d69eb328adce99670f659959c1bc1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/03abf728ac1d833c2d4a9ff7e0c912b949edc04c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/03beeae554ed6952e94a0bf32cdbe9f97eb3ba43"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/0458afa7b507195f5d2cb51e887324d6361eb0c4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/04bef86965e816c0cd330896ecd981dd3b14275c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/050b79c8bf73ec690aca18072cdf95810c2efe8f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/05b4eaa1e1a759aa6b23521c06d915174e8fec88"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/05cfa5deaead322efce84b710758a24440cef16e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/07048654244e377ddf246e8cc18f71443035cd2b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/078232947d7ff25557e836b4e9e907214e99b320"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/07b0bed3226eefac4a84000ec584e4ce06ebf1bf"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/07c4d3b37e850941d04ee067fcd356cf9bb4e0d7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/07cec5c8d9c856a910c6fb57da2ae954f44beed0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/08a8a647b6a8f47ae10852322d14832fc15021f1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/0949f4ac376808482be6ab2dcb18a2ecb08d9a52"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/0b6fa6330bce65dfe7f758bcbfca2a2844dd07a6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/0c0169947924a15b1b5fbe8f9013fd94d1931a36"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/0c27c9999302b39bf2256a90b0cdb767fb2b6fe3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/0c30868720d5e1a19ff23c53740749c37a43540d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/0c5e0660ddf5f14af8f3fbcc754a967506994c9b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/0c6f2e0a2232788cb20c4f52ffa18d7ab8f0b938"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/0d36da88698737ec1ca7b55b30fe2b2036de7e19"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/0d407f099f8418de3dd94bd2146c858a8c6575ad"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/0d4d486aa9fd6e9c10cc9ca8967e922cadddb2fe"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/0d8c547f1d261ba07c2648bae009636c17709600"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/0d9ba07b57eb0e076b187c4455f662db085e730b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/0dd33527db106a3e84172e8f2189734b00ced4ed"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/0e354d89d02c6c5cbba2f140dab7b609bf00793e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/0e3a18f0f08dcb9dd174627bc997f74a5c7a1390"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/0f6b989cec08ef9da603dc83704d85900bd22f1f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/0f7480eb0099b7706b221f610d2613b401d6d3eb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/0f83cbec19c834f534f353f4fce20c0cd88231f5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/0f98d7d56e9a99b97e5dc7eb122ef22e9684077b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/0fd8859246740606c498755ab00d6147abcfec00"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/100bb8f2e6a0b41da13f4edb5c15d4a04e564840"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/101305ccd08c7a8bd0c2913c37d3dd0d39d4bb64"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/10b25b0726cb6d820165699e5a453691c7a9c343"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/10f5d1937cb068fee7f85e2654be2bfe77498bb9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/110074f658208166d52897c9266fc46cbaa8af36"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/1160214cdb23e8fc187078a8d6796656c1ade925"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/118ffddb43ccf9dae8bdb4702232d1dc39b021f7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/1231c6d007d9e43d169122348363e20d9f25ee93"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/1306c4c6ea714d4db0e4d814c944d8d40335e0fa"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/13a9b61e431c20734c19bb36d85883b6a501284e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/1402bbcac6fa24eeb0475250e33f704096e2fb45"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/143e0d4f546bbb984a7c3ac1c60a37dcf85ea58d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/1526ac4266e152b029b7c283255fe4fb6507f726"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/1576c915ee38f5bd19f285ed0ed47e36026518f2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/15c8bfec99ff18b11211d464c824fc139cc791fd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/1602788cf33d0354d6d48ead549e5137cd211979"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/1698ec182fad9d973b84615da3a683ecdf2d0b3b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/169f579e66b4b8ff423891a40380e648e8d45247"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/16c85fba7b4510ac26c0fb91886d8bd166a7e780"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/175f16901997fdee41ac9ec88f7e018d46d774e7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/17b1758fc7cd69a00d140f113b1ac894023ff20b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/18185cbf9e9cfc1fd28d27ed0d651d7cee6a2c06"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/1859e2ee759e20fe195f67615a1576ce2b7d5bbd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/1875a4acdcffe505ca92ea8af8d9d6b174736e80"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/18850965807039500c7f5450a907e86825cf823d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/18926cdc608599e8df6b0f4df99d4ad856ef4373"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/1965cd58fc41578a837231c69075994da2e871d9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/19876f91bd6e71eb4caf6748425ac645f3e73c5d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/19e984af62c36fe982284c87421d8ee46173e9f0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/1a9017db5ad8a9dc6cfe72305da1683a87a73452"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/1aee32faadffa3c2ec508e8fd30006423665488f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/1ba08b63181066ffab948eb301a6a2363a81872d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/1bd90335afc9e0a1e6a9296e3cc27c03c1201886"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/1be157b0fc79f0e7e1e05dfa3cbbe1ad71528bc2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/1c222dae4e2cde1fca9f9bf6226200f70d625342"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/1ca51ab2fefef4f549c4a8e7f4910c6b5a4b4b1d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/1cbcaad71950c62d41bab50f9c242d014cc0d904"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/1d19042e6db2a90c52fcc3cb0aa76f2fd335014e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/1d458954e8174bbb5dd4d0053df47d6b7adf290a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/1dc86d0febe4adc5353230cea24b5f7cce829283"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/1dfbb6d67ad8d2513a1841ca6f82faacc3783b61"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/1e64080289ea4168304417f3fbd86b01d7d6f431"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/1e84d42fcf18bbf81ef6e8a16a0c57abbf8d292a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/1f040e756f76357979f317e0c6541f72fd93df06"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/1fe7d16ffc2084d5d3c5f23d16902ae8810a5393"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/1ffc4952225dda41de59603e487ff7fd3026b958"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/20216d27af2b3dcc83d944e5f7a489ed2eff98fd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/204093594b568ada9c7857a971f2a4b42123ee1c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/20539e464ced1a0a63d74bae731ca0a75db05967"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/205cf2b6994f10b783aa0a06938a5e47cb581126"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/207e12d6a84dc8fa020b3a60b3f75932ca4f8fa5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/2086f83879663d7fd7fbd9a5b96ab6b5a555858e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/20ea73876cc9cd5b3d3efa1bda21deb5eac2d61e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/20ee437b7f456ebb19d98d94d9feb1d5e9174c65"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/20f43d29547f865e9832fd567c2a5a5899512c4d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/2166c7093c424a2136c4cb8b10d0b124047320d4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/2185f411bdb1edc610f16ffc86836ae366193e03"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/2197f63b9ae90f5374726d0c5b252e729014a9cd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/21a6a133f3d1e06c077032ba56a7df4161f62efe"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/224fa2e83fd8ecaa9059ad37a55238f74b8e0829"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/22661803bd1c7198df4be6e08924ef6a48af9cd4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/22741b8aa6129655a8130305da40ae1d1500b844"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/230527b90b0179139c961aca426187893191fdf2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/23066692f06a4802954b513a98546b3ac9b9ab85"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/23e8c1377addaf67019ea36a084e0b68ca7a33db"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/2467fa0f8a9f4bd121f544892f0782498b2df533"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/246dcf347eba7f4d4e04d97dabc002f0acf2164e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/252de25a5237c830ad8c5e4732c176e03785042b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/25761748660a64111a8daa46f72ea1f336c2046a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/2585dc7b6c095e978b56e0249fe9b5c61a4840af"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/25949b623930511f9d43fea4aa56a4389a28e11a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/25d2969baf8bd256e15b2ab72707682b2d18b40a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/26110f21dcb0fde99942e631366ebbd9d895860d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/2663ce44ca5832381cbbdf7b252e39d6df021a93"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/269afce3bfff993c05c2a3b28c6cf3dfb3f461d7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/26b8a9d27cef1ce4c3c5aefa2dee50001aab4b13"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/26f250ae38865f030176a8801ce992536351a326"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/2717067bbc0e9bfc1d90d15cddf6154800a25ec6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/27bb1ffec59d4475dd9076b408b2cc4e4e17d229"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/27f37037525aac7a41ffbadd6ce52e5a1851a2b7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/2825cfc19c9371f4fe70851283c68d49470d4d55"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/2862adc802092f1a422416a1666a5142f71d5d7f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/28680d04887f96a1167dd913573ec8daa2a39625"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/289cdf83f89f70a13e9078259f764a339617c827"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/28ee8cae75efa07da9649933a9482d00643b5395"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/28f54e558b181e294e101447c7a79d976fe36fcb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/29303c16f3afa18c2c0b84e77e587535a705a74c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/299034b9e0cc8d91c049c489dca6d1a2b8b08959"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/29952a15459cce9c647255ab5d7486df0507eff4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/299faa82b90ef12421d160148dfb6cd0077b57c0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/29be7d33920998bae7329d77d4c81989eae91647"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/2a8260b23460f90f770cedcafa14868d24db201e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/2b230a7b55b17f2f8e89c4be73a662d781f7fb3c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/2b5eb5aac77af905877bd98ec2c4d746b247abb6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/2b71439e9ebf611a92386b9f21ad44bde7926184"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/2c1c3047f9ca95e64cb158c09eac2ba17455e918"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/2c1ecf05c5dde692ed16502294e9570ac3b02600"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/2c342f8715556398d49bcf3343b5a249d968e19e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/2c452818a10ddef09b90c89a53db14b9b56b21f3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/2c6e69067c68c145dc5d3a60b86d8081fdf95d0d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/2c79128c697b53256c56b9c57c7259866e0e2347"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/2cc43573f271ecd332551c1fb34ebc8645eaefe8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/2d83097b3cbd2245b085e749fe923fb590790e0c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/2dce4a1fc4bb00bfcd43d549a3785913c9280369"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/2deb1aeb93c2abca4177b1fe886eb354c83fe8af"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/2e888bda20346a2e19379e72ff04aa063897bf0c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/2e9860242d55a74cec244bb5c5445eb2797a3157"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/2f288409c5f3cf2a10b3e1970a9c3d037dabe080"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/2f5f6d281a3d0473a04a17cbcbc6fd06cb73fd8b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/2feb41037f5dd34e9f3465a2fbf1a6d355c8ce9d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/300998021c7f743ff49d9cc192343ffd43eb47f2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/301e10bb6d9f60d91efde4e0c48893203a5b8b88"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/302a11eb9b9687464b88c9a670da371f6a6c57e7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/3104e3fcf2fe43d5a748772a04ae32a1c828e6d9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/310b2aff5e2ec78b6004630bed39d49f8d13bb21"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/3128887b8e02f1873ed6b36766a870543269ea00"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/31545e9fe4c6aa43329dc0d4a735842574fcaaed"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/31d12a2b1378120d15b4097371d792daa95de0a9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/320dc10f64b59b0eb0ae140912eded1ef9276556"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/3233f2ab3b6c9431289ef7dc4f40676d0128bcad"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/330dd22142ff48078b189f4533ccc56878d88f92"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/3336748264594689041e4080b51bc56f716d0689"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/333d0554d91872e693d118d6988132d95b7920ae"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/337d579ab5eb157d7d58e9287d447976062cbd8d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/33c32a80db0ec311ee8744991c5b19345bfd8fe9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/35fbd748458e3fd6068957d46a9fbb2b0113d2b3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/3608078afee69879bcdbc2278e6f314469426bde"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/361c6f4374443671f039fd9659577e4460178020"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/3656614c7b0dc11d4dd7e1826f77fa96a88c420f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/368c75135a7341a96627d0dcfc4b2081003d8979"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/370b2c16cc353621091eda4964d4c4329205ffc3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/370f893353f792c99754ece93baed2105decd71e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/375c2462d6ae891222686f9519294811fa5de010"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/379b177d55b1eb86ddb66dc3a037fd8283ee07c0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/37c4aa3ff3947065ea7850574a82a29af35c1a39"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/3a01c85934363bd2067f76d0d40c491f9f846c8a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/3a3eb65d51f30f4cd16cc6f8436a5b00702a5712"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/3ae87e3150628c422ada13002b08f2d9c5a9d78e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/3afbc4c35885b79c6e6628afce93ce852d7767de"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/3b3b4f9a985ec49f6c54bae798208625e5adb777"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/3bb052abecc1b916cc869b9aad29c9dd55a95068"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/3c01b1f89d50fa37fcb3457cd3dd6502fe84e25b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/3c5fa483ebfabe6e684831ce7c413176bc998c33"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/3c6444b64ace5cd6c145614ad4412382271a6120"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/3c7b516e302ad3503a933b5dcfb8c58acaea07a0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/3d4d961511c1de95a81b129f2fe96390209de2e7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/3da7577acd806e1d92d48211b22fd9db352fd834"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/3dec1981e8677ec6ad2517feba29869d53f8d884"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/3e8f531043a07df2280bca73fe4a7987d82ce67e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/3fc7331ba0cf4e65fd120c9925ec0134fe683b22"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/3fcc2da89f438b247cb5b4b41e15aceccfa75b36"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/400e6759ebf559748bde92047368f7c612457edd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/4040224f3df361afe45bce682d56d26f13829413"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/4045d25f065bb1d70a8b9c3751f7453d4b0625b9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/407cedf992b14edac6e19f7d440ab73c88e72465"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/40948412b61caddaf558a73661caa8c1d2f858a4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/4097094277bc09981f428280fc0cc0f590f20ded"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/411966ea7d9164fc432eeab55a55248ad808bb01"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/415dde26637ed3c0e803111c532a1a9ea9c49092"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/41aad2f11a7ab418213352e84de872d9997db8d2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/41b499e86caed7b48c59aaaf51360c3c71029400"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/42554ddbe59429d30d718282ca606ed8b5a90eb3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/42c395ab373346fb283ace021bdc1f6428f92f80"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/42ead79c94eccdf8a8c3d8036be73e14fa260dd5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/43202ad9b1a689d919ab9ae91c2d0223394867bf"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/438789ebe8a5d676f6f03ef8329c3d77579aeba4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/44153f8b7af5a3b27625a46af89e1712daa3ae8a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/4492f9d9339873fc83bf248e392b0dcbe28c0f6f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/44b6be630161765a3de5872629602ca14789c3bd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/44d64196fb2e8d9506734a81304f6ef17b9bc29d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/44f0973ec77d6fb9eac931e84fa7ec6fdadccca6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/450f9f56c80c8b71e37302a254ba7c3f7298dfd7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/451e69ab65e0fe0a5731622ed21ab2b5380df677"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/46dcb1c399e5a514267fbbd5a50939f34e0ad6be"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/4740e1ad2320dc991596716087180e2965a38863"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/47e8aee44c2c7bd870f15b50fc085c5a8030edfc"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/48521eae3d7e3f60237d1ed792a3c0f141919a19"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/489e9830136adcc53f4b191199c33504685b3737"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/48a3f2938fe5c8e383cbb028a36a943a64800f03"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/49112bf1277d93601eb6526fe9ee9d45864d759e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/49c5568cb0de363bc9f9298f1eacaace6c8a268a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/4a11af9ef42aeb36691185520be281c4760ad27b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/4a4553c2e939cd50981bc38e8ddb1f2109ddb3a4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/4b2ce115b15082ed951f4dc0b432da6a9d37bf85"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/4b585eb75ebca2187c0aa5a6abe4c8125aa80127"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/4b611a3748757e2fa89fcd2fb22d34444fbf5b42"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/4bed84590a55b06d7eb30d8faa4b00a881ba9b2c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/4e05d6cf1c3f0c04f6ee92d09a53ee0fe35c085a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/4e21c4b5c454df51c102f09ea1ba78c42133ee16"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/4eaff3c3515a1ca019d46b9be0b7318eaffb63d1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/4ec113a0126fc5746fa3f955727d009040e8377f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/4f5b9d5c707a35084918c272efd1295d301ca0b5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/4f8b5b7489cca36225acec0f9aa7f5c556d79d8d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/4fc34239f220392581520aa8cebc659daa65a7a6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/50ece7ea16659b4e1a2284cea963fab662c19e6b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/514c9cd7b6519b596900d924ff2caa173d688f4b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/51c6c5297acebf9d21a8a7d6261d0a17c2adfb56"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/52939682304314f04897deddfbc9c7afa8ee50a9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/52c00bde7f4af95a86deb0a6717d1faf2828a939"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/5323af7bd1b45a816c8f8e5c689f5a44fbb14a01"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/534c900ade27c8f7fccb1f3b7e7703f77f13a8f5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/5360327e8bc8969f31b364df3081b51a1e03900c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/5369926a559827d08bccf264876d592c7cae660d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/53ef530f65b0cff2e338a51b469c224f53b628d7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/542c958c84d1e319b9ba23c52de2c4bca08a8dc7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/54555ceac4403855f4cf20367f7be05714c46c51"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/5482dc4af170def9c183315efaa48f9c186926a1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/54d1bf3559344653a4f758f7360c46307cdad159"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/54e67ed1036f3f5b315e0e3c02948c30eba900fd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/55ca8f6d9928c239a7abb32554463e6e1e1ee084"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/560c1057487e6b0d2d457748c3ad8434423eb263"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/564f203f678fb333c7b1f8f4df79237589ce346d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/569d50f1d1307e63a549a8a8fa677c2a77acc0ac"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/56b0ac0636c57838f63415082b3ae2ec7a93f017"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/570ca8d2555dde94aa3b3121e8f5256e83eabe5e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/578ef036a0278e79f7b935293be37bc8c0467269"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/57e7cb796ac65d2e3ea2255b162da4b9873c83f4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/57ee6efc38f4c544a3ea3e5e73987e825bdf2980"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/5821752bf8923fdaebc8484662624d8acd382716"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/58a067ec6eda7191a5a910d8120633271d3af074"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/58bcbd601894835bb3312d2a0bc56f2e0f65984c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/58d6dffb65a1fe1bc4e3fa970a15459587a32f77"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/58f6d7756d89ac2eaebb50c6d1d0b9f5fa0ce357"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/591d46b83d2e6babc0ce3c753c4606a10c46d7ce"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/591ef436ef8cc982b48fd827a4555b57cd9780e5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/593792bfb0489b02828c93278cf869e6fc8bc230"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/598d346f284bcff26d1de997c4ba5c4794c90b68"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/59d28886db21f371ac9d999b68b116bcf425d971"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/59d78f6397f0483d139f5bd0a9f264156f34acc4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/5a2447fdfdbf123f4592c1284007b7d50a01750b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/5a52d683c9342dd301b0e699db36175aad715e1d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/5a8cbd42a033b7899383d48c3929e517dafbb995"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/5b7ff7c113c2bcf125271d22c937f758a0cd2ee4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/5c14b48da74ab06b3cc20c4fe355e24f7dd7852a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/5ca233a53e3e425cc12e04b466a49789291eaa00"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/5dc7b2086a39f56d8b9135f524d34a01fcabafd8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/5de72e607205dc17a45df703ec4e9b63c36821ec"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/5e1659e7cd840ab3f958273ebffdd215f2c81da6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/5e25cf639ba8ea37543d944f5efa94824c6272ff"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/5f247d7b6753f7a8798cf952f49f303c532e017c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/5f3fc3d381f07c2593cd70d9889182fe67ded2cf"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/605e474e9d9436488dfe084d348908e4dfab81a3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/6066fc9e28b4ce704230f0e8cf21e7c3195aa2a3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/607dac8012f188cb035b189fc3637028137023e0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/60ece7fac04e244655a6091a7fc6eb76f07c7192"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/611343a6b8879b393ba2f38ed41c7f5355355920"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/616e55354ba3517ce6762d6cd56600f97915e646"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/622d46854c2d38b5fe632649d58a69b7da0803c0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/629dd62ac0c44a5bb49a5b4b5e4d3f15852a0991"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/62c843359941660da3fc9eea62a5732aaa3be283"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/6353376941f932ad6ea7620be8673c27ec106aba"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/636a19b8f50c4efccccea83ab78a933d999e41fa"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/63a1cb41d219394c9bab947202921506f3574ad0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/64696e93ead18265cdac3fb37dae29ad3be6d764"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/64af31c3b16ccf2e182998ef7739bc3d33781d8f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/64c0e0b4d9c2d25fdcb1e2bdcb999487fc096dad"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/64cad305e1858eae27cd723778fb9f4b7052eaa5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/64d27dc9f984c49d421a5b0cb0391992d5aac1a4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/650f74738d3961af2d1fe85ad8fc8212ea13cbbf"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/653ec14661c40ea25bdbab4a7cb9371c669d10d9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/65c7a3ead9676f7669f0e93c432af714c232e5d1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/65cc92868683dcf3c5d1bd1a73db9473d6594bcf"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/65dff388749da6a44926b491cdc555f61d708171"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/66145518601b1405361df12570f6e0b2b9a2e5b3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/662d81374a2c96f867ccd88a4295190827c45453"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/667ce3f1c874125b7106bd5520e60e865442a712"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/669256f857011c32f5757ec19b2e5b9a372f6c23"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/6749752b02f7d14fff9ac35f6b68dd62f5b49fcd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/676adbb1e5b3f4f9e3cba51d3d4ef963ba4ea7e3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/67e72cea2b7042f08e8dfba5191d27bb390e4d00"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/67f160446ded73c408f4e5a0665731b642b6edd4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/6856c7cb02d2ba74a60fd47140f042701dda63b3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/685fbddd9ea612b25e325a50bd659997b4d77da1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/690158fb146f7f3b3ea820979307a8d8e6f38314"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/69542ed81b00a5ec8daaf4e8d509201eecd502c5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/69be4179b28e408a0574935e893c6986bbca0de9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/69e14b73af03e8f2d998cfcf16215f65bf589efb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/69e52eef5dd0c51012b5c974cf70f4074ba814a9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/6b1698d096095d4035ce67a8680b52eada00cce2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/6bfd3679f4e30aaaa1808e96c980edcfa9cac1c0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/6ca3910d5f4f7967311853724b072750716dcb48"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/6d054bad0bd3c522d23221d71e3987a0e6875150"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/6d1509889d26c2ea16f5d12d5f6490dba7f1565a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/6e2796549e29e5066f780a5e926fd6e3bb362450"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/6e71553967212dfea2c9995f3641e582d8c2105b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/6f30de3096eb71f697885fdd9cbddd9ee6ce46c4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/70b8a3a8621ae1ede2b8a4a263060fc2e277bf2e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/71106770243ccca03f5025aadb298ee3a825824b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/717695057d76b81c344ed8c23cc024195caa9405"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/7353a7b2ea9f61325728b2f118416549e89dd79b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/739228a1400cd69c47f110002c34dbe1661e8c41"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/7465a4955a064e8f1bb777d4b0de5b3df8469831"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/748c538708f0a2f586d7ff5f662643b8f9137a01"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/74e6831be67485fb59b8e226fb8a48d88faf57d6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/74f8cfb3d1b8422927edac90107aa280a8a2a19c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/753efc088d6023ca113a12acc54015a22f7daf9f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/759a1e2e34cad14321a5e5790b1e6a783312fea1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/77cff7548cafe87410e4a0dde3ba6892b25594d3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/77ea9180617391d8503427a1c060538182f7729f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/7885df741c88ca4b539798d9985c445f41cc2929"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/78abacff5d3a1e826a30f278ad52237661018a67"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/7a7e42cad11ed5ac39966d23efd04777265fc50f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/7a9a12b15c798b88f1a599779f52d14edf9f4ef5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/7af3156d286a32a6a6fede46d93ec12ded1ac138"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/7af41e5391204f4596cb1461792e2e23f9390b7b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/7b8922ed2aef31167d305571a4ebbf7c182c502a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/7beeb19272131701f3a0d1dd633f1b1969899366"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/7c2e48b0d08aaeb95b5ca26036384aa2cec9de77"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/7c73c0671308e37a8075a20863e70e180ef8b6ea"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/7e0e459a0794d4f91954eb6e0b6a09685fa71c78"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/7e18989175bba8d9aea34413d6f328549e1c6825"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/7f1530d4b702e68d043f89d9e63d314319dcd803"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/8021c689f0078c5c59419c9959f5c58472245bc7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/807b8c4ca068cff4bc0fc8e854c1215a2fe65960"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/80bd4827db81a1da28fae8c150f5e2d46651c598"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/813d2c34c0df8d4a918e68e58cf0ae3703d0d46f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/822cae715352b8551c840be2c7e2f98df455c9c4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/824152f7bd022996b41327002f6971cd9900b265"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/829a1dc2bcb22a230df8aa20540def0e16864983"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/82c0e02a867a5fdfb805e01ebf1a008220311e27"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/83019387566fd48738546cdae398f750cccdc437"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/831248cea079b629bf0ef6d9d02c159d6f8ed41b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/834527ef0bc1572c584938ca7fe5336961754708"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/8382c249fc9c7a248833d89de554e63807c475f7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/83baac5cfbec61ec277114aae4384a11a576b8f7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/83baaee9b46770d9eef0e161a6e52cda76e3b043"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/842cea88bccc41d7e2625dae8ff7268ee79e9f57"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/850c639595eae3cc9c2cfef473e28fd4e8174dc8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/857ce08213a5106c746767352c6863d7bd134208"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/85a7e47ef707d3b31cad924ed6c697c3678ab569"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/86eb156ff8ddd7edc535840d412342ada6f3b184"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/871a2e4d73a7fbb50f71558517a2f704b7fdb868"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/8795e24f23db36e4f9ab609c9faff601b984eb6f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/87967bf3b1412ff60c5bec8815f4b031aec26b4c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/87c8549a5e524609c29e6a6ae32a3a301b72c286"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/87e97b460042d045629263ad10ff3de7b000f0a1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/89cf42c02d7135afa6c81d8a0c2bc4c3df557769"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/8b0cf53ac17015fe066002cb3814933df9ee96be"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/8b5c4543923da5e468aca1de1ab880aed2ac4451"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/8b7b914723bfc23ec650cb91d209141641fba09f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/8b8b9fcdfff1f891b1694614b7309cb4a2098f4b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/8b8f6d58dff9ab0c37183ec93c9a600d5ba5d9e6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/8ba00963037c9ff548b7a702497441799075f14b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/8bacacba71bfa5c74fd74cb6577a49a7aec9cf1f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/8c527bdf0f304a31866f71cdb298511041ecd320"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/8d352ea63259e26e1bb61f5a8f78254be4e3e7b1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/8d9784f85e9662734e180ca8bec2164425ae8a87"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/8dfc4e78007040009f37109f9ca928c31b3ebb49"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/8e3f138d163022d6e105ab595788f4cfdd9b9db3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/8ea624983d766ed45780378a3eec24eb2faeb229"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/8ecf066a6728b30e1153ad875562165db07b0d0a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/8eeb8cf054ebd546ca0555ef1cd4ac6a08628917"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/8f05b8da748cc04e64b688c4b435fe64699bd481"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/8f980dd25f1c77e3536131c2c620aa32e8c13180"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/8fd4873d307af2d217f5d2bf02b495ba681fad74"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/8fd758e2603f1e3772cfcd295ff0f951988d7648"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/9018925b5e791ae4b3ae9c84b8a4d47d86671c2d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/90a9c3390752b94ca19a58cb2fe6267bc818f718"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/911e2ea20b6c10431e48f70d9933987815926a9d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/9125277ed9ec5d59e51f3e1a8d97d25ef88a5d4f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/914464d372dcccf31ed5331293d84121e17616bb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/91916df7c8f04d8c2b6b8f4aeaeee6972ce0de74"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/92cce6dc5c31acd62347b15d89d52ab94b507e0f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/92ea0d3200665e1836ac12bed0837425cb9f43de"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/9329b80d0125cc994d7ad36540c7a8265d76983c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/934a41b5027d1c5cca27ebda57560c38cb9e09ea"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/9354652806d96b09c8e7082b1b7d22e7c3fb9f0b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/9398ac1c2b4015792661266a9c84b6d7a68c3155"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/93ac93b7deabdfb4f86eb37a1e9f6669957d14a6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/94108ac8420347598c7cee743b2a158b1270fb8f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/94cb0b9e26e4a800f3d413f3617111bde2438009"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/954ea72fdbeaf5b46d18c6d5bb77fc1a0f97569d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/9552c3f6304af40224b800f3a3a5df3887a530f6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/96e5126447131d3d59cc6547f6b91d3433ce37c8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/970fccda0b34b59ade44d52e1212699b4d2419a8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/97c4b73f72b248b4ebf4bf30892d0db828a85297"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/98c0c0a3c8c05aec3082755a4635e65baecf4752"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/98da5edafac67704810f093b38c86e4c77b75349"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/98dddd3f679af150e9933bd864ae20e20b7aa25a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/99099024a3f3e389f57cb7b697eb34485846f316"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/9912de197918ac0e305f0c0107f863823e8ae818"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/998a54dc94ab6e7d6a6066415fb0dd9b52356171"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/999d0995c2f09beda8783eac95d7643a11d5c89a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/9a21cda420d50994a8ed56e147f8316b75514db1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/9a3f9531b10e8e0874699ce3e35031a35feee5d5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/9a43f48d4f6219618f8cc9e876880fe81109ad72"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/9a4da2a37a26c114e1226bfbe1cf80ec5ca99a66"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/9abf980e8909aeb31936553ca22ccfd8680c4dab"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/9ad011d38bed7470e7f60780faf64d8f008b9b04"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/9b1355c6e2c43ce83001bbead09a79852e04feef"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/9b4d4ce0457f5300d6b4b309762acfdbc41e3965"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/9bd059ff0a90e86ada1ba7e5b90ae04637ae9e90"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/9c4eac3dd734a74673c76e6b21fd9c18cdfa831c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/9d2dd744ba59c1e8ec091e23938e46d1bb5ee519"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/9d362d2aaeee243a5b54621d8187c4b16f87c9f5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/9d43a08a964c82abba4a47246b1955d9e3609f6e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/9d6947df24c9ebcbec72c568d9708d7b1ecae63c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/9dfdce1b090a559a14f9a5852f78547413b1d1ed"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/9e2ab07030bd35a4c31df32c79aca5e76c1d04f8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/9eaf2ad607a943141c29f334b2c66c2e59e99980"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/9f0ab521c728be21e93112b2730c52bc1d6c0021"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/9f2316ddcea948c947fbbf35ae87b767b8c1dc55"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/9f8e14ee5b4a2095f917084b60b5fda33f21d9fd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/9f9ed47f98b4905f1f6ef2b552a66905bdf79b1b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/9fee3212240d4bccfdab3696dbbc579b06d39982"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/a09ef34c93fe0ffc13045f67b7ecec683fb72e98"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/a210d629c305b89a34b7ff3c41ae4566cd22186b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/a25b31398669b585ccab97bceadc31994de7ead7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/a29a547671badd3154789e1a02bdb87332fcd6a4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/a30fc2605f4e74f7003f902ea4a4c994e3ce9bfd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/a33e1b28074a41fc5c2611a67161ae5638a47dd5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/a39ac9e92b41d1889096ed415b4c2eb1aba6ed50"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/a3cd54d43d3b3bdfcf224d636dc11ce1b5ee4d30"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/a4874327383ca168f9d9d59cffe327f61e9a6610"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/a4e4a0473ac1f2b8de86efdf00fcb382a343126d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/a502dbaf3c842bd86e9ae513e8782eb23c70ad7a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/a5592f15d5424ab7e16a18e77027ab91c846d90a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/a5c2fdae1a1c0487d00db0eec6e3429b12244b1f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/a5cf80b996b2ba8c9580f8ecd22720c48de41044"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/a60ae4e21a913e84405814f18555f0c179c24167"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/a649093880c2a2f143f861893eaff5d30be95eb7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/a6603e797695274d10bce000f66ca0a715f7d8c0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/a6d4b6043d86c376e9b166d5ca395f3e099ae229"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/a6f0d1ed80393ec0a884718b44fe2dc9f852d38a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/a706f2067bfbda7837eaad68972d60547e2957c3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/a814c5743d492b96d2b402f9e819bf8406262224"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/a8249ebfe91327806446f14a6b2e7d9c8440257f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/a8e306820fb76566b522c23ec68bdce0ad0536f2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/a8e67676784506d2e6eab3a0dfa25e53a80b40a0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/a97dbb159ef9bc6e39c9c25e04315752e871e739"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/a9d71e1ff2912d8874e38fc61cbd9a8ef28af4a9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/aa878edb0100e876e00e310ae221b220fdb5e028"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/aaada46c7f3bff58c2dd6f4a8394135ed5f253ee"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/ab27fb527771c7d86f74afb6864e95402328ec0e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/ab8d6e1ecbd80c6223b8623a386c61023502a57c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/ab90bebd4c017827a6d5de61511445df81169eb6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/abd52da5882855a63632a6917df3639538928cd3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/ac38a6572f8420b4df37d9e39088d1905fced71d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/ac727124e46a249419f088c8665324a11b357b84"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/adb9bf315315338bcad85929917b9def2aa098cb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/ade2d2f0e120a9527487e9b92458ee6844800e4e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/ae448bfe17f9a3a6eff074d4caa9f7261c94d2d5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/ae8c538d4ad7f2996ac724bad7a075e1aea32556"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/ae8cdc02275a1436bc131bee52a17ee797e2e6c9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/aef36c49d7dec0dcf8cdc224d9e9221fa2cb1db0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/af8b24ffaecdfaf96c0cd7c76f31dc9e1b4d0935"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/afcce9e02e0696a2af073855a386f589cc12c94d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/b00a32e8bfb75e75f31410dfe3592da6248275c6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/b09f98e13e5b67a4dd7f74eff00bb247b9967844"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/b0af44b49dd7c2b2e02ed4fbc7658975338e352d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/b10353c265bef989d8909055fd6cd52e49eef3e6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/b24a0dd1bc0bfabb832f0d1c8410c018c4ddaf4e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/b24c25c6d4b57a5f3d64a0adb205bf4f150c9138"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/b26a3a83d0b319ce13a9ae164e90fa6da1b05a57"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/b283eb8884c98dd50523995ce221aa1ecb3ca182"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/b2a79b262ee3966c5ce7c7b42dcffd55d7d0956b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/b2aa4861b5104e8bb8bb173f4b023a2172a7b9a2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/b306bbbf43b343ce3ea91f3ecf08501411c57e9d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/b3376cb338d9ff88fdef2f8670a09e973f28f6c6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/b33eb7e1bde4c69671dbbf9489b4d4b87c5d23fd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/b387e46c23912785e6c353ab49b8ea4a92c2c2e5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/b39bfaf6a3072d8a50984dcc54967e9246f8d3e5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/b3cfcd55b0331ab0c931b8c61d4df41464587f10"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/b3f33b78433af7f607bc99b569b0cef95a1a6ca0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/b46e762671a5e28c7061da3baee6fc41dcc0122b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/b6d86bedf3cf19441114e463458a454709e627b4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/b755933ad6e318ee9e0c430ff69be7a515d44def"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/b758f5c019696f33c50895168219c0e6cb04e11d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/b7b664a39372dd6142b8ef7906857e4ab3f1fc84"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/b7c31bb5f6acc65b88e31400dcae71f7be392c86"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/b93fd0a15287dd035eac86e547e3ce42183bdb28"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/ba25be123c630bd3e4aeb9bda6304dd1a7e51365"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/ba3566735888b53712c6b2e6d52ff5f2197afd6a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/ba942f8fb244b60561a067129c242c4bc4fdd5e1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/baa28a5baedb645f4430940a4b4b1142f4b03e0f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/baf7839388e10ff0c410a58797482cb83693b309"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/bbc03bf6274a79528d43e200e8f1aaa770a155d6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/bc9e17fed43c5d0668a87e8d6354c344c5b4d00b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/bcc7340f8876a7dff381ca676efc39d30eed9f48"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/bd0bef14e73aa1073eb5acb6e4cc901c976335f5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/bd275178fd473028a5cedf7d5780b27e809882ee"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/be1208404991b11ef9e246d2f3537ffd65a57824"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/be3237e72b3d8d56eec0520145dd7d1a5064eede"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/be8cc5bab95e0ea7af538ca11175d710da6207d9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/be988fc0c00a8422020dea3dc72451b09e25e1ad"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/beabbe93f1e9b2e56f729af30559ec03a00f53fa"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/c0deaead93c9b3f2fc211fb7f0711ac192715a40"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/c24143cf5f6f77f002e0ab82e3060906e2e7d062"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/c2f666569d0c6fbec701fc6772433afa22a1dad0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/c3afa705dab02fea4d892134e7c01c3af270cb6e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/c3de41124a14ea562360aabc9e12666851bff2fe"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/c4c53b4727e9e1f040c5d7870639dd3daa184ddb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/c4e60ae7c05b12a90dd7c43fbc85ae4be7540f18"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/c5d0c169d326d79fc4ee8521b282dbcbf33c1d5c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/c5dc5f5ba9c2a2af7e91e200a8e82ea2c44f3a56"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/c5dfb4a82f91d07041d4b0ca6cc34cfa1e9c7199"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/c685689a9d5b259afe237d857b7c6551dc95c176"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/c77087b4651f4c62a780d77a3b4c233490244e8a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/c77ee0b6cb21ab7b7cf222c7f6563b3b1b1b6eed"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/c784ad2e205ba49b5bb1302746723dbc57320981"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/c7b17d6ae5f3b155532a5a9bf0239c098c35eec1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/c84da54dacf04445b50448a70fb0ecdd08e9234a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/c8b79e05649da58817a10ee6160a00d80b4a217c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/c8cb20176e427d2e108187924f570ef1df6d440c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/c916ea9c6901c1e77af764773bd2843baa2ebdc6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/c97ebf43d8a5ce5cdb8e93a5d0362239c284ab4d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/c9b92995f282262c51aa7106608eee6cade3245b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/c9e2cf8be8a4dc2294020026c62840ef1fb4853b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/ca0db313bf949ba3f87a5254646a7a7dc8a7f89d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/caaf9a7751c0eccc34f0fc00a048012ab5ed2f37"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/cae3827ca308a477c16852cf8a435881a4058719"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/cb49955601d171fd14c9ac21137b221392c7dab1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/cbaabef34763f2fd922e67ff5f2ea283347e9823"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/cbe59c62c6d36c7307c438159327e320cd2fcf57"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/cc4197d2381a75b674fe4944b8c690fe69a0b3b1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/ccc36ee2c6a0daad65a4d929599fda5cd38b8fd1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/cceb4c620c02337138e489383db0d4f4e2c7a722"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/cd4be18b1ae872c40580edc4fe8cbdf1fe2a3881"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/cd76ed6aff7e074b0cfdcc6305ec4e453d8304bb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/cdb000a2d87e073efc9491c59707289f6bc18fd9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/cdd1a4e358ee2396ece54b32c1f0a8d0a2e3f3dc"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/ce1c326f3b0147841550ce3b5126390764bae8e8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/ce990633c0f2b2a2ddb66144ed942d4bc9bcd8fb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/ceb297908903ba0fc24982ad4e6010e79dfbdd5e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/cedd54df6d34491dbf7843c2621d6818418aca02"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/cf75632ee185df2cbbbe148e2e1ad5410f11d361"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/cf922d44bf08d223d3ebcd37a7e77d3e43555d08"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/cfa40fccc5ea4304e83ca26f4e567765c2c08627"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/clusterfuzz-testcase-minimized-grpc_client_fuzzer-5765697914404864"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/crash-12b69708d452b3cefe2da4a708a1030a661d37fc"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/crash-133500314833c9037b34a4c34ad779dd78a0fa8d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/crash-14ed70cd9ea7987cdd0c8f6e39398ee7c60ee2ff"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/crash-17d5b79ce495f7d3f2e33d95588457281a5e8965"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/crash-3bd02c98286bfa7be8e13c5500ddb587bba74fbb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/crash-3e52af52deb0ed5d6ef06487d7e475e8fb616972"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/crash-53e93a1906d8442d058500e7107929cdd3e84ff8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/crash-570c79624a2e4d36be107745d2b25e74464553af"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/crash-8e546795782dffa5d5f5e94c9510aac178fcee39"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/crash-d5af12c391b7bf0ce63ee3dc656ee4410fe496eb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/crash-d92bb454bbbd415175df541661e3696453ce3e43"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/crash-e470e9fd09a5c9ef303813a40361c897650289fd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/crash-ff53a3d713e83ae945b8dd1782e21f5b51aa649a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/d10f52ffae7857c5989e16960942179856f308f6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/d17e9507af1855fcf9eca78e2d25c8fb2c40a34c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/d194592e6f471dd487ca2625e6c3da7802ea372f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/d1b1863b478e1ea71eafac9e03256080c8f0d1c5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/d1cabc19ce0f9fbe365d96db68eda9f86e005eef"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/d21ca2b01baa21a666257d1a1e0275587eeb565d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/d24d1b9d754391fd0b11b0456a2e8c6050cadee6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/d250e525e8ff2ae4a9bddb2e478a90a1242155f0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/d257c41db22b60cd937de16b9d90a44b9fa8e426"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/d2b5fa141432c1894be8b8242c27c248fd55cddd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/d2df8e95436cf98ef2189191a75a3d9c78b1be6c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/d2f71a800612876010558ce804c9a72ad0a1b9fc"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/d3141a71cdaa7a0915c8c55abf2c940b0fd00172"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/d3386702918881101368cdba2c4967e86ff3a7b9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/d363f288f48fba8fde401978b7e764295735645e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/d36e015b1e14ecb9559d67bb09c2851699f0aa35"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/d3d7a110638c6814e7bc8b388d25891349de14e4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/d46c3dcede830286dd9f4a1ba02a20a0b1430664"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/d49450b97f489f0dea74a9f83c71abeba1066d3c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/d4a72650e8218ec551fef6560ddd136d52828a4e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/d4a744ef6dcef5cf08d5289e167b26270d39e9f2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/d5a85ad91cfde27a96960b2e783d2ee43c50dcb9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/d60440ebffe00597bedf89a47b7cac3346823a20"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/d60469c0b5b385f20d55aa5cca55bc2c801f3b95"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/d637cc9387087de633b9db535d19f64795c43be1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/d70b2046ee62676b525490b70812c2157e5a3585"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/d727b7edb460c549d7b12b90f581048c9f4747e5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/d86820c738718311fc75191b5a35cbe7029aaf18"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/d88bb0b7ff687af84f33e6af22d3516fcdac5534"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/d89026894e6c5f8b5c88dec12950f56c4b6924ba"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/d895ece988ad4712b87de8aa9bc273eee315e8b8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/d90c312791129dee8c5f85cb3308323d0c39b70d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/d91281daad9b821294db204dfc244b2d0d5496e4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/da2ec14db88e6f93bb19ba2f0a7306408de37cf9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/da322a6b88da87babb52d1527fe54cb4ac214b32"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/da424090e1b94c5d0e91e26f3f3dd6c4af18fcd5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/da4d300d0a8e6f803ec053e3e7689c4b91eaef90"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/da538941f1613c627523cb1be71eb220d1ca2579"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/da8d4c7f02dbeaa543c159b3a4e527059978a429"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/daa680dc94232de7a6949ca6610eddcdbf13152c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/data_frame.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/db3a30a6d8e605dd587e51b214c42f68bc43cf19"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/dbe415d09cd20abd88c858b8c9b2a9e552fbd8d8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/dc45008d5a94beeb4aba87c4b26ac6f87df1490e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/dc4a248fa4c903ce3a571dd18aea575019445740"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/dc7ebba06558484af10b5aafd01ec4fd59276b12"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/dc815fd6d5e817898238481472f359bc50b510c4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/dcb06a6e34cbed15515e5b3581ca666f704777bd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/dccd1fd6d3394f5f68c87950ed7356a2e9ef0f6f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/dd5ac34f5b220970447b2733848de78570c47883"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/dd662353bad317cee7d16191a39e094bfa4898f2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/ddb283529bf32a85a79a57ac2f2f2d5f18631d92"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/de06dde2c760a56f63bafe6ff102663bf2d9339b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/de9b9a35e1e7040e842b597b8d2fe4cd602e67f1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/df20bbbb854cb997a73285ef30d227aa12d90e4e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/df684493457bc8d87dec2ca0825f7b43978fecfd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/e0375839ce86fa191b85662247d9b0598ec35a5d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/e0aa94f5a63cea106ff86739ff2bd85115fd3df0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/e0d1ee5e2e169dcae87f790f5c27e84a3453cedb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/e13b774309bbdec8e9d3b1d3f6dbf7d6851e30ac"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/e18cab69ad5cc17c88f8b56ca9929ca8af3eed30"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/e1bd70aa5c802cd4462ff4833c09ed432ce4c9fa"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/e1f2e203d39ab2509d4a67f7a44265b1e6364334"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/e262f378a3d27bc519d472ce3650bdffcd48a055"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/e309e21c69e4b96ab37f675f4e87a52453512ef8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/e30c4ef6423bd4d872792fbd6954ff8e47d31a97"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/e3422e8f5d63a9ef180aab552353955c7aba90b0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/e3d12a2385b75443fe38d989e77c252e1f3cdb6d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/e40b0fa5d814be8f2081ca2c8e0a4090d4893831"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/e442f9fd63bc5345de1c14803d4ca4bb6f1152cf"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/e4c0e27cfd3690b8255a8214d6dd055385d1d24e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/e4dc0a111e77dc495c5db07df5e2917adb674697"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/e4f55281c481484bd9edc28fd10df0c2e0f7d546"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/e5319a8570a762bbdd67135b49579097324e369a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/e5a7c086208248a15ee6fa5195fc4ce22469de15"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/e5ac3394971400b6636d029aec7ec665a94ecf29"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/e5e276acd665ccb47f868fe3bc36e647bbb840bd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/e61f728210ce72ed8b2c066bd1b1ecf9e6824b77"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/e6a08259a7d47601eab5c0249cb6547024e002c7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/e6b3c920b47e00055226d49b9f715c5d4353e3e5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/e6c52f2f31db7595d1ecde2939a7390777f15182"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/e6f5cc0702a5f38b9e7339849e1dd2e4001e547d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/e7c26599fb2e2b031346ff1ba09294fd758f7abe"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/e8323c817d18f0c920d3cf53be41a9bc0fd64b76"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/e969affd8af10a1b87dc63afd3b29cce3e58fbb2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/e9f7f7f258c72222397a960652c01d2a37e2afe3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/ea46b684f1e67a27c231f2d536c41da631189b9c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/eb591d069d89f44150c17082e83c48c66c8e7fe3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/eb969b9ab1b0d6b5d197795223ba7a091ebd8460"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/ebb0786acc21c6185356eae9a62490a03fddd1f2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/ec180175f0edea0a6c3eea2ae719b006bc029ff8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/ed6358fbe6721c9ac01a6f4cab4d2df377eb1f11"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/edee7f771a04e8ced659e7a5ddd6139e75055a7f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/ee436743977b8e31feec22a91b1ce23dee96665e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/ef1984d6146670122c7a7246374bca460e7284e5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/ef2ae7dd190fdf0bd4cc2ae53c5cf1ea7db877fc"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/efdf3f43fb29720dde23c3335cce7be48b761fb7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/eff9ad9144a2953fadc019fe72eb1cc3447c33fb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/empty"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/error_refcount"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/f03120d1a8376638e071735bf4746454b6ede389"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/f09410ab7bc19ee1ff206f94e8eec2931faef15f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/f09cd3e3a16658174717668e51e7382e491df1da"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/f11abb090bae8cdac1f7d9a2e344f2def0e50066"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/f1a5f3011be9748fb83e392e334e46c629a04379"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/f1b9b6803e41beabb1a762d511fc148116e09e78"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/f24f925945aaf5e8b5ee470935e5aa7f847e7a72"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/f2a6bb4e0137541e2b140b976764377d07d822d6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/f391771de2dfbf761a3eb70af7aa5f0af4446116"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/f41f9319bda14ef21b925c46945b30728503dfaf"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/f4499e3d4bf60ae3ae929c485a13ea4dc2713369"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/f4ae2a2b692bfa83cdde75d007813426e14daef7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/f4da422d640232e22f2613ebdacff33cecd61aea"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/f5a629c8fd5720236b66a875e96ea22e29c45965"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/f5b1eab444efb2664a295d4e6d087eb209c0c480"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/f6627c55881fe4f0c8e6999980fb226836e6f5ce"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/f66305230042fa83fcd1b98c469d90ffef3ff6da"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/f69aa5666fd60c1b6814198f12d049abb0e9f148"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/f6af3f46aacee395877d7f7909f8e412a6538efb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/f74143e8160754e40eb4d21a182c970210707979"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/f7812b2aca4d12ffbdac67bcacc41b34524de6cb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/f7aeceaf0b6d971038a677994b5d080fa0e18011"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/f803c87a92662898e2c8c847787b56d2c31f63b3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/f81814b5f0191729c62ee5717775e1bb532efe7e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/f8467d9574de94b9bb904f75a6a7e2405c36f105"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/f84f5d6188cf099465f0b70337b87ad8aa8efb78"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/f8981798dab237ea34051d18b5e903f2300a0653"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/f89ad475ff51a5a9fe18603df833453bed320f36"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/f8fb1348ec3ceeb75c2a03df6a2ead0de6f4127a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/f91f76fa45a23adfed48a10ec9512cf16bfb6636"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/f9583b3a39c1aecbba6e81d71e7fe9b9519c8b08"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/f96843fdf2d6fdd661c26201d96ae7bec72c6c3d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/f9940356ee9b212849fbdf0d818b17af1a4f3c6c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/f9c875c00b7327df5bf21c3e051b55b0d2ed3cc8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/fb340fff42a4d7ebf6b82adb9345655ffeeb05d9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/fc3ef8b3cb43e4d2721b252e7fb578d83ed6605f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/fcc557c9844892675be823fac8788eb694a3a118"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/fcefef90833e6ba74d3e74756105e1f32d985162"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/fda07f0de15cac77ccc54ec221d81cdade189bfd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/fdb553b8d82e68270a7345b048772bf8367b1224"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/fe1390762579b5c335bbdea73e251b95b979c3c9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/fea99272cd661a5fde2707e350d67a683a7c21a2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/fecccfc70b1cf1a524b9f28a9ba2c153c8e14d0e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/fef80aa34c31700ac8e53bede4a97131176ceef0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/ffd52d31f9c59a346aa195a683f077dda5ecef6b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/hdr_frame.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/server_hanging_response_1_header"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/server_hanging_response_2_header2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/settings_frame_1.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/slow-unit-2b505c78b53599040622864c18644b32c345884f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/slow-unit-53cf4d25741d5f6e7ad9147b286ff0b40cb500a9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/slow-unit-82794c7583f365eece6a10ce776d59874490a2e7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/slow-unit-96939ec880829d76392ba9de2c6ac5b3ff78d20a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/slow-unit-bf008b5bfe748d33669c905f9b84be60856e57c8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/slow-unit-d446c0fd59ce5bd844a954f0c4f7e40a891135d9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/slow-unit-ff38df2c9451c2fd00fd746c53adef87a495da9d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/timeout-6b847dcc217d2c51134ddf8939e3fe5153153ba5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/timeout-76a0fb5e7896bbc694a45e713f9729248455aec5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/client_fuzzer_corpus/timeout-e4cc5c1a9ab8c5f3f7ae3ca97e395beb682d65b0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "client_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/0141fcddc9807ee093313b2256f1306fbbdc6cda"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/0255050a9ccb25f46d6c1bf6a5a8a4c0c7635599"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/0320a995a8c76c64c8a0e0297f632b76d9bc92d6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/042091aeac4cc255506b96fa11c7354e699fde76"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/051268ade45dbed0aab896d7d9f4d10ba89d3b09"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/0696e7bf7837d98de01c915d3c9d80e5d21b30d2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/06995c2f3f01c7ec50547415dc324c64030b7a3e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/06f7ce769fe07804fc842462d4be8c1aa2ba82c2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/0781b055c85ab8fbd0a3d0080a32e394af8761c4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/080e1f19e6061c5bcac31add2095f87f6ce46129"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/0828169ba82152a8907f1001e3d98804397d4610"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/08ffc4a4160e9fe6f322c28870a89a41fd9c37d7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/090a7a758898a6e7c9108b7e8a1cb9cda383e707"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/0940663729501b750a18542e1041cc26385c6148"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/0a10bd140c6c5fb109a0816ca061739688a6db9a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/0a4d3fda02cdcb7adad1daa80d65780c9c8d1464"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/0ad812832efa33e086874fbf3496664d3f1b4dbe"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/0c9996d4fef87bacd7a001e99a515b3ba3d5788f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/0d6210208831fe55951af56cdeee3d54a91a5361"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/0d784965b2262df7ed7a1eb57b92a718cc76bde8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/0dc9e41eedf35ccedf4e2b0d230ead7c4d72fdb2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/0dd470c8939ed535de6b36f7b7bfb68aeace493e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/0e61e471fa6d3405daef4276ee00cf5fc189f378"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/0e9196f951874edbb5ed098739ea5c8b6c0751c2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/11442d93a554b9e7f9ab02782bbf9443bf6e1ddc"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/11833b795d04eda5a3af56ef7b3c3a26a8ee3444"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/141272316382b0f3e9ec841c735b84e7aa517c3e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/15ae43369798e48c396dfe7d53a21878b96e66c8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/166bf1843c229d34a2880d234dd166c27bdc11fd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/179e8ac763b4051a953a38b6b3b1f1e1f6cc6c9e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/17faf0ba8a491a835d35977a9007b90ab7d30d2a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/188f6cf2470e95b228341de305ef839b27f01a5c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/1ab3e52adace335d02e2b5130eb4f7c918add7fd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/1b5150514364e2c17f5a4edac1b7af99b936f55a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/1e8befb98cbaba059d6771abd1680e19484e7723"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/1e9b962969c359bc2ff766704c8ca8e25f5eccfc"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/1f80af104acf41b912bf4a48fb938267e3718719"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/1fcc4afd6f48e83d61ea74970df3ca9dcd8ec291"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/213a734ccdb813b18ad9f2dd99b7f9967ee1460b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/2151945f43991c27e123c45dc72b93752a47e65f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/21545d998c27a5a1572a89a552937752432b1c14"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/23c7443fa1ab713e7c34ec50222b1b8cceaedc65"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/2445bb2c6779712dc9e14c01fecb7103f8732858"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/244b0a20500e31d3c538418800db816b07f4d210"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/2461b9fa6b5bc4b6424dec5b9a18d4ec7c309112"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/24ec2f3e17d3850564788f3fed17a5c586c44658"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/2537b8d6b902b8dfc6e17f194cf7d05ddecf74cf"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/253ad01acea4b7038edc3f2a8c4a0c0f5c4dcd05"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/256d0bbdbed22f5867a6f503bf082011e61ee12b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/26f0e88adbd8f8cdf778131a35b33ecf8711fa49"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/2e5dd8fb9d2a31fad9d681eda697d085b647b57c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/2fdfd2abf30c636ec8c841f1ac26594e25664f0f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/311dac5092e36134d3490f98aa4207425e0ee941"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/320fe6224a5b691c0425e34b6b14e8c6fe9f9620"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/3255f1c7441a7150dc3c33022bfbe8c956c7b7b1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/33bc9db104eb72891fb096f34cbac191b3f9918d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/342ff1db70a7616b4ef76c03a42802c6702c18cb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/344c011df992ccfc0ec682c14a1cb2d7959998c7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/35775efb9d0d68fa07987b9a84934389b528e436"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/3650168db6fe115fb1e73eed4b76cd224d977d01"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/38228bf98cdb50fd3fa830ba5a9d4c7399063dff"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/38717bee901151b22a10beb12c6623ccc844d3c2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/3a4bb427a85bdc5bf66ac71db073c99e0dc9f881"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/3ab48621d9b8f075369099a8ec7517bd23fd6e70"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/3aec8d9311130dfbb6584fe6e619579c21992b5f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/3b14837f22905dcb04f93aed2aa69bf95924fb9d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/3be63c163805927e04fd7f84d96122c48240e601"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/3bf2e349747c0f539181e0d4084a5fe506811a9e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/3c5af4d73e94d0e8ad5666b6acb340f929031e95"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/3d2b25346a9671d83bd082d170a45eed739bae6b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/3de7b860c3fba2bc55707fd6875dce276f2f249b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/3e2004ff9f40e398e0f41138a25a8b66e3d843d9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/3f8983e457033cc85997c356935ba9c21460e86b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/4105669086d83a20f8d991088553ba08202478cd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/4180619316eef7912d1cf52ffe85897242e1ae88"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/420291d7139d9246de747739fd98102434a742dd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/4256437fc5897c0cd5d755816e4e68c7be326849"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/42b25a5413c536478a3e63da5adef4250babf2f4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/42bef44ae751a45c671d9da5b1231d2ac747a48d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/438c3c9045c3cf7910aceec34f77b47a70ca4abd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/43af96b4f65ed0ace7236427f2f8833c4835989e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/44c6119bb91a452d6128ce0ea0d62938800779ea"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/46d595331689ae01d77aff387747a98ff3480096"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/471a307b81dc37459087d41532741c5c9d7ba836"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/48900b4a5557530922ce45c15ad0d3b0a337520d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/48bcce2c6487b18706ef0c609ca39c456215bac8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/49027bbd3f3f3cafa315843c8fe8280f86985273"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/499376c5e291da2f9c25999abf4960fab5a92ec8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/4a3b7ce0cdf217963a0b692769e5d6f4befe73b8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/4a3fdb96bc8c80f1992f0f72f963f84856cbade8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/4aae80e05793d7adb42a7e6e8a5283b677318777"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/4c7a034d3a3b4f29d99caf021a0e9bbb89706c2e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/4ce8a43fb17a075627160812ad26c25210d8a82d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/5032a75a98cd14d4dab75c1c5e2cd981abb19dcf"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/50b3f4b6aed97f442496d27f3b4315a18ba76d5f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/51064b88a98658d48a0da7f1545c2d1293ad9538"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/51752f12d59fadaaa0dc72e6370612b84ee1555b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/51eff6fcbfe1a51ceb3f5f2140c01eea89b4313d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/51f65f681cf3a1218d83ad58642c06deaea86210"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/521809903d36db80b1ccd707f354361f2bf05075"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/5278e3581c069624157fd9176eddf52c0e58df67"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/52fe8f0e1fa270ea16f66c93f2ffab265ce059e8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/53de87ae94acdc8e58a369459c12a3240f1294fe"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/54a2b3993c3483745f6314c870a038a8e58f97a7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/55d60c2e5040a38be8ca41de63e137e3fef892a4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/5653c44a5b520bdf2bdc599b7966f1d7c44950b3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/5838b5a683229ebb6e6277e2810863e642b8afc2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/588d225784891ac88e30ac6eb5651d63fac34083"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/58d51c21a20b6549567a0ab8fee29d162dd3fc5a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/58f1036d8ff855841ec25b3c33e85a8fec0d94b7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/5a99df42fb7bbafa2d55714ee235b1c46776b2ad"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/5b42793550699b2c015bed677cfcddc052f73513"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/5b8ca72ba00231c38b19f582127e6a146eba4282"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/5baa13dc95da05e7ba02bbe9583ea24517a29a1a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/5bab61eb53176449e25c2c82f172b82cb13ffb9d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/5c6f6b6f7f3e7b435f060abb73c20d2b773a7f56"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/5c9fd9cc7100feaeead1e0e45201945a6e76fd85"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/5ff49c9edc7361797a951585f3e180222c8dd95d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/6129954942e26c2a9ec071b6659675745613cf3c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/61fa69b6b51b0ed91914fe48779173f8d26a1d54"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/6362ac61cfb6e964aff78f3cd648475dfd5fd4e9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/644deba51c79b6ebd470bd4367452941045d112a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/64beae98e2276749b133e6368c9e0f19a79eba96"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/64d7add9192301fd878854dc96f9fa9053f03992"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/65566df65e8f55428b6672cc351df414fa8f936c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/65bb703af35d5afb824cd68c41d7a1aeb3848d35"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/66c537bf59cb3667c037b3517be3d31245c9da8a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/66f576baeb0c9435a56eb7375dadc5b5d630ed87"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/67b4cec5183659aeae0f5bc71b3adf0542a11828"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/68c94721eda2f62481bff9f1d183df70498d0c5b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/68ee8169a65d58edb9fc1c752ea81dfec383203c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/6b203d49bbba6ee74def0d35c2266e06ad3c45d9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/6d580f28d785c0bf87ac351a31a89289449feadb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/6f231dec759eb2105e09263d53e171de19a92c74"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/70ff6621a09e4f641538cb1b27e8b382b2f56a94"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/71981b55f27a1eb6274eda247048fa2c597f5004"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/71c2b0bebf7f0e916e4ab7eb36d47ccca2b9101c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/74610e278a5b90aa12ce1beaf222c4306b02ed43"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/748ee9817eba56ec9938601a0e380c74bad4563f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/7727e3eeb2a48c46bf5a678c300ff8a38b8ffe3a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/78176d80c1d74c4b1b820d386ae483ac4d1d92b7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/789abb571563a6795220046f76b7cf0ade90743c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/78f5ff40e5554aa9c31b45f79a7ae9699f93e7fd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/7a28fc2e9c72d51d29e87eed63ed405c9779b5e1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/7a42083be21dce7f96edef1f3b3b2fea0bcaeb3f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/7a51275b11ecb1efec9251390531681c8d6f2481"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/7b9682cd7a3984698f6eac034c59c0f91b4fb83d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/7ba7239a29d6183960e3986abc8f19cfb548b905"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/7d3b3d5f23d0ede9f7e5dbd1115db58c8a54a213"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/7ff3b6239b04479a9caf67f45b2d0c619f712815"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/8035c81c95dedfc27c3649064f98f49e3e72c21f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/804e1052842ce4d44b9c775ade2b18fcb8ce7bcf"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/80514b85933ea9bdd3462595f949c5af24409b87"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/8057c32b8bd28a5ec2105d62f2abe8cf69c9f5fc"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/806a3bd4e078d91adeacedfd3e47ef8ae229244a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/8090444f98218e65ff9594789ff22bbea3c0497c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/80e516692955d5f224706f268e247858858e16d8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/810a1372fa97380265f5529c5043ae96f007f5bb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/8127597d3c146b2a89579e44daef9d03a0f941ec"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/82ed571f8922caa572d13b4cc9b5c5fabafaade9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/8328e86178800f87a3bf6f80749984f45b0cd0e8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/84441efd7d8bdb0ce2fac28f218d3d5d4d77f1d4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/84cbf70f45a64d5a01d1c96367b6d6160134f1ad"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/85eb0f4502a51e646dab4ae08eabd90613cdf8e1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/86080f33e4eae21b37863c253ce61eaa13021a97"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/862e3ccf601ee0f7fbd8b23e6811fd50485a118f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/86bae059b18af8ae263e5ae0022b67da0cfc0fbe"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/870f9cc4bd89c6c04c6a51ceae1efa8634627cd6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/8762a523cdb78d2344d553fa52a229bd63c44e51"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/894211571f9153c3c2ea4102541dac69be8aaa9c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/894e9b7832c52acb04bfa994ef53c7105d8db206"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/8b0e12978b8e2eecf62346e438e47d0993845693"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/8b3fa0bd4f289eff6a04a5205e04baaeafbdf637"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/8d1deedd1e463f8c95129a6f839c380a7c83ab04"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/8d1e029bd72381e382c87e61b4c5a9741d80d644"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/8dd1983889b6632228d4897c365a1e6124d101e1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/8dfc2183691385432f92957cff0b2538e5a0ebfa"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/8eb9b86b4f0aa79b8ef84b44e1fb03094e7bb426"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/8ec540c36da3814e93da765bf2ff0825b59c1bd0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/8f1bec32f4b8e64062f5405a096543e61d771076"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/8f3e48c49d0794909f6e8e61e5a4312edf484c33"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/8fbbf3c0eaa25b64d0a97a8ee08006539e649199"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/907d0021d42d0fdc867fd02d3609cdce13c8a055"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/919511c217a3427c22cad4a71aae31a6cd47b193"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/9267c81c3283da8193c198de05e05fa30631a453"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/92e80997a4237d76f10b70dae2870b7255c97435"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/935322db76f5d4c74c2dc68fc4631915b8e24323"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/939f2627ef6263d0176566de267ff3eb910e6a60"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/94adea6a0d9a44bee6f5e88adcee57be9e9e3597"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/94dcbe0d3352bd9b230096b8dce9c6d8d63f9d51"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/95dad738f60e3e5eb0f1cdafd91ad461f4418e8f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/960c0a21c9e5c1a61b93b34da3189b0de1c264df"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/96903512b1f1dec08206123f024b62d0e31cd4dc"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/96a89c005e8d9992e34cc149b0be096ad0051446"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/97db8a66dd513eea47a5a25115508f4e59984854"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/98f2cb84ad89550cf56ee54e11f1448ae7287247"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/993497422a59b7f9f0f6db8c867339b5c9e4c978"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/999821e3750a7f2c9db663d2d100b4404c225040"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/99b2ed83be40cab431d1940e8de2dc3ebfe9352f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/99e888b7372b29256dbefd476855ff73584cc00f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/9b18087deb3cfafa1b964aa65d8ee980bc61404e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/9b3c745ea3e313909a228a07b49aae110b02ae4a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/9be1ce0ba77758928ff5e9c45139b1624cbe9c2d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/9c703141efd69eb8f32a58133c8035fb585e0f4c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/9c7f77981677499f0426a0ffb5cb79d5fe55dcb2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/9ca59e6cadaa5be9af30dfe5620d1bcd70f442e5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/9d139835d91474e8d8361d65698a31b8b38c4f7b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/9e2179564a99e96e179c96f28802a0a2759b581c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/9e56bb3b68d2e2617cb2d2f0f3941f7fc832e462"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/9f318b2c2ff9cf4615bd06ba13bdd086b4ad08c6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/9f8d90b1480989fc46ea2f1c66cf687638994587"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/a09db5715f0bc3879a0e18e4db5a6b5640b254a3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/a0c59a090818bca29d76ccf9843f7e2faf330ddf"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/a1cf10478e5e01a0d951c743a3dd45aa5fc409f2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/a22c0f03f8c005a4612a9dcbcd6a643334c35d2f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/a3154b8ed26b3461f2b091c732da00b63ce8bed3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/a84a1ed1a24e753a27adfd3ba806f06fc44f899f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/a871e7ce66afd4f57702cd1299de06cd08995561"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/a8dc736ea964586b7dcbf2bc065ec4675d1daba3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/a91a835836c72217824f0b63491d9b623130502a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/ab97c1f6033dc7d96f69b9e1461fd594c16f4ebf"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/ac8a8c23acd8c290a11dc7828f7f397957fa6400"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/ac94b2788f5252f9e2e8502c7c75e04bef4c0b76"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/ad03b4f58470c43db6593a35be48989486d754f9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/af417c83e831a96fda1bdde99a1af6509ef2df3d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/affd292cd2ce3306b4651cc7ec0ec0524cbbae3d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/b0587e6e319f4b56d877e7ed46bc7da9b1e7249c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/b166aa66b5b3ad178bc38aee5768226c8adc082f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/b1ade0571262c6e5f1d72f6d25ebb513d2055bc9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/b244c690157ff21d073940ef8c77d1898f37cf8e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/b523091ee4f17d20f51f9b5cf82293465cf61780"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/b7d4d49ac2c530eb8444a449feb689ee50fd210d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/b855c161121bfa29c6fb22d3c0236fae4af6984e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/bc4263a92952d56168b354f723eaa43a33cd0b35"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/bcaa71abf23b2e5130e0cc464755fe769bf4aaa7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/bcf4684ce097faa7e9d99b6e93cc2de24f57aee3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/bdca6504d2ee7925f62e176355bb481344772075"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/beb208fd8675ba7de2ecb12998d2d628d579ca7c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/bf0c98689ab81fc32787023300caf9a4175583dc"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/bf479e97b39b697e715663de6a1e78dd58d64122"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/bf826c96be94d1b42eea0666f7239cc5f699a375"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/c17650d19ae4a48abb36739c83d8979453f5705f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/c1e5307d88feda2c3b15fc221cba92bcf41622bf"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/c249f408c552a0408eab3fe1d1cbeca95cd537c1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/c26b460aebc9082c519539069f7e060042989696"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/c2eae71daad0d3561ab4d09b8b85372b8d790bc1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/c37fda8d02e99132a1de99f959596c784ab8a53c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/c4836760377a7091fb20f4afa9c712875792b9a7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/c48caad597176404f776d532d4baf9faf7655ee2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/c4eff0f59986fc5ab09d5bd95f394292f2882659"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/c5fc2086d167c8c3a7d9ec778db69c5fa14a59fe"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/c600877ce547166eb1b9d83afbe128d98767f8a3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/c6a98fdaf6de78e59e1a149a43f3e42222d650b7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/c8d22f7fb4f37f2d8cc7953fa2d599d38d899aec"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/c90951c19b24bac84296e3ec32cdeafe99e99cfb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/c95ff2a172626efb50e94aa6781feba609820076"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/ca6c557afb9c571de62e9b65ca6469a6133760da"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/cb2d0fb23f66c968af2e80d59f71d4c1aed96fbd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/cc60a642cc2037ad3c459a57381b8f65d8d7aa35"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/ccd3b8aa26c52f6d9c607c26ebdf621142aff745"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/ccdfd1354997eb117bd76b75440a7e4ff20bf564"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/cd7a7b8f08c189e95ae3e2ea44b9015000e823f3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/ce05678d812a5f8ae8e115938410116ce9169456"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/ce6b642b81373f05baa2a6fe6e9d5d1387046285"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/cf84d06e4dddb997a79a41f9b6122bf620bbdb4b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/cfbcc3e8cd65aa8b654688145ade34b8789468a6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/clusterfuzz-testcase-5298216461402112"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/clusterfuzz-testcase-minimized-4857057310146560"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/crash-5ac3e1ea7764cfb6383629574262f82dc7b3cada"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/d000502f32ca5620d7745f39ff6be3b547e26a6d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/d131f83ee73450ff45565d0c638be7d8beeb30d9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/d1c7ae01a81a122c2fd7c5d8debcae7566e9ee2f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/d2817b89d7aaa7fa880c077b1a67168ec2f4f0f7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/d3ccd7039dd34baef465c4b78baa7a30312a8f07"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/d4cfaf3b59b22b654d7af80ee6715ce5015bfdc0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/d5670827c8e8d4c95ac0f738c0790c19916c0336"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/d59d7e94863f1ed89cacfbaabf7bc59946036c8f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/d6d8b478e6d13945f7a6f7d27f424ff57ca12f7f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/d76d0c7f24ae3cc3f530d5306b8dcc15290c7ff2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/d8b15e9e555ad9900ba4be8cc9f87bef75725b24"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/d9748abd540810c2449c3dd39a0ebb62754e520f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/da9fc821f0c1e00728b139b36269bc3d21c0a8cc"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/dcd1bd94ad97b4e67fd7e12ff1bf7c039eb17f66"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/dd3ba9b139e13324fc76cd62af84b00ca8b87205"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/de0a9dce0ea4e4bfdcb13f788ae728bf979fed25"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/deb6f9a930d9b31586ede19fd8fd3caae0e5b1f2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/dee95e0280b70681eddfb68e3b418126c5661e18"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/df01203edfa2dfe9e108ddde786ae48235624fef"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/df0adbe2523508e9afb42a58d98c2657710d6033"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/e05fcba1b22f658c8bd6f3c330b2b3c9faebf977"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/e145caa75d73e3d819a9cb4b6217f1f53112f3f8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/e1d86c0094657386197d191855b5645ac1dd5936"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/e25adf8de44f5978d00b7e8c52aee89c5cd1fe93"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/e29f05162e3d96d5549f96aa4a54c868535b2847"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/e3a970ac8636d29da3ded328b876ed3550cb3209"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/e3cfdc862187b4ec28bd4fb2ced5094bb5b09909"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/e4ce52007d001806fc9368b62c124dfc56e8471c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/e52173f0bc3325629046e85e2dc41acc6ba7d1c3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/e6589006e3bda4c57247ad66fcd73ac00ee2cbe2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/e67c79d0ed89ab2d5e8d81127df22876e636ac44"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/e6fab7572fb2a1c6e107b6f83cffd103a233d021"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/e790f5d312957dbfd20abdefe4b1735779ff9689"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/e8809017a4cf6c1e80a93f661166ead961f26bb4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/e9733e973c33b38c2087b7f1deb36688b3b14259"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/ea8134769855d574f6673bf0301eb2e24632c6eb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/eb489536e4e5589a93a17cd36669475b8f2a5e1b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/eb48ebd4d01e5623dd16ae61938b3333fab3ce78"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/eb6ca7624384239c7f7e0d83edb7cc334b7926d7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/ec9457ad41ed745ea9377ffdb16ad09f981daa7f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/edff5256a2d60d0e51caef25dc1d6f1643dad6d5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/ee4d9c5d22512da42726f47213ff56404d1d81d1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/eef2f30b5e2ecd98ebefb12d57aba8b4ad52d904"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/ef23911de1a27d03d2d4983ca1527e17d6a7092b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/ef5b7fc62a2daecf1e8f928b1fa3ebd028413a41"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/ef718258ca1870198e91a2fbc1eaa90b620673fb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/efb46deb37a78f41dd760f6b7203b20956eb114e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/efdd6824bd2456e3e408e0e84369c4fa3aa14f41"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/efec040a5de1969df5e37e4bc50a0a8f0de341d8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/f1e30464c24dc1d7cec7ec1dd2adec8512232b43"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/f27a617b936814476770a3b31a5afb80d0f3b423"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/f3f0d99ac2962f8fddb25c65fb4c8c6eb63518a9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/f4628084cf46f139babb886a782b4ab5977d5d2e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/f4753e8881e4b3c71f2728149be7d04cc648f6a6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/f4b48c4f3f310ed767755267210f212dd62bd715"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/f4d6ff635ae4fda497221da4bfa3e593df59a44e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/f52f4d51aaaed0f9c3a20936cf5efd25d0692f67"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/f7cf30724ab740918eee6e4a6b6658ae3d7706e8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/f823828ffd2a60efee36f1de52cb0f024ac5b4bb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/f8760761bd5ab7b47376bfbc5a44e16b2d5ca800"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/fb15042c268625089ef6c8aa3d8a6f12d1d02c74"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/fc3dd4292d6884a770199596f5e9cbc1e869e5fb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/fcc06696e641a7743bfd2f3b7ecd88e7b727e00a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/fd34ec90fe8f9218fd25c3eac151aec998cff6d8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/fdf548cde981fab4fb17bd63a124b75eddc5c836"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/fe47fb18b064e26479c3c3140082bd01065e897a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/ff2097734bd7bb8451aece13c9336c4624735170"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/ff2c949863eb4e14d9e835c51591304403d91b6c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/transport/chttp2/hpack_parser_corpus/ff7d6ff060e63355701b2e655c802902338497de"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "hpack_parser_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/0299ca2580e4398d170c4a336e0c33eb2cd9d427"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/05e613853d64a9669ea3cf41b0de777dc24931ba"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/069352518a1d1baa05f317c677d275cefda2ac97"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/0925527c9358b1e10ec0f0387cd99f35204d9a34"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/0c5b7c2569410b526605e308309a7f36574e530d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/0ef3d0a84360bb5ad66274f1226f5cb273ecdbcf"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/1e1273f90187fdf5df3625764245610f86af6aa4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/1fbc57d118f3733287e9a9d808bb8947b3260e55"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/24756c396bc72894fd720092bb6f9c03e66b469f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/276def41311933421ae7a9ee42e906c85b6a4d3f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/29daa75432381937fd005cb25e314e328de6e9f9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/2a75204bc492084ad853682f8de3fb137d5907bc"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/2d34ba249b755a880525cf53c665633a5e359305"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/33f4ea0c7ea27c37d8f95cfa64d282370efdafd2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/35554617ea6418bd43161fe9a2c337ed82d7ec5b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/35f0c561297cfc840ddaeebb9fc61091f4eadece"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/3787bcc22ef645e665cc5f722b8a633af86de9cf"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/3953688866ccb3b4f371f1a858570d6afdb6452d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/39b19c41ba537f37511eff7727733715db432e76"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/3e3c4756d5e40b5aa250954cbac86b826e70a7ac"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/3f03265921120c6ffa61b944e213e062a5538d4b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/3fb034e66ee5494a67acae1b4e6ff64ba92a2046"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/466059ed07a0d55d6ad5e522c7d367cbf278eaf9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/487725eb38511c79a9340bf4560a1411061fa6fa"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/48b9b205cae8ac21512a3f26f49fd53e21ee13c5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/4b1f1f79a0bfa3f942479dd5f8edb59a7c257c55"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/5028c56a5116a186b7343ff59567b47347a0796d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/533f62b3f495ce704babf3ee8d840f196a714dff"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/5892cbb284771fc9761caae37b19cd6e27dbc104"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/5aeab6e4f7c2a1c09d4ac0dbdb3beac4893607ee"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/5b6292bdf009b0daecbc90b85cca30a88c36eec5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/5c1659b77678b41faa4fa13df7772dae3238d1c0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/5c81f61621e29ec9c6a64ac3af9b3b216141618e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/657368df512ca6294b9df16adf935a3f374a8be2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/7fc4520094902ce2c760d70eaad5b674d2817337"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/81f59a12b458ec3604035cb962165c604d1355e6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/8f41c50e88ee8c17ecad3d41d63d38fb12aca0b9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/97c16de7fe3c390a2e6c09ff5c28f17d5c67542c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/97e4499d450c95660de86747f527e670f2012548"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/9a996857196e0998a1278994a9bab3d35526e7f1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/9b7e00049ec356ecd84b1747e4e1941140139ae8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/9f0c38ec455cc363369b3674a2d32bc21c206de1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/a1dc7bc235e46eb21d91084d7b52d5ff9f45df85"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/aa3bbb876eafa8ad8ca4ff2eabc6dd94341d2441"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/ae8ba95d7dbe99926a8f5bfd80347fd6a4b616a0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/b04fea5c041c707db0ad9c09a81672557b52cc47"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/c4acff8aa2ff886f35439f72625d05002990c940"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/c55ce9995b002e88a102ae2891a71e8bacb346c8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/ca5a0c00b8969310acb73d15ad0d0c602f1bd0c2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/cce734f1b263de6994f7950e0df7bf0c81449f70"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/d39c8ee11a697634a09b309460c0bbd967e7effa"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/d4c3e4cf5d035596433c30eaabbd2b2925f4b453"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/d51f7fcc089f269c7afecaaca51966bab5fde629"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/d936dad71c129cf659097dc3db64550c4dd467f4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/e275b0466a8fb8d9e0e15856e343ddc7112ae66b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/e5c364b205855a2991ce07482aebb2a3a6147089"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/ee2077e08c3cfccd9bd82adb574ac4fc7d429afb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/fc5d4b9117ba9e87388174aee4f4970bdfe8d066"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/fdeb2c7daa9e7704f67e141106384e6dd0042c0b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/request1.txt"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/request2.txt"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/request3.txt"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/request4.txt"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/request5.txt"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/response1.txt"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/response2.txt"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/response3.txt"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/response4.txt"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/response5.txt"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/response6.txt"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/request_corpus/toolong.txt"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_request_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/0299ca2580e4398d170c4a336e0c33eb2cd9d427"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/05e613853d64a9669ea3cf41b0de777dc24931ba"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/069352518a1d1baa05f317c677d275cefda2ac97"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/0925527c9358b1e10ec0f0387cd99f35204d9a34"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/0c5b7c2569410b526605e308309a7f36574e530d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/0ef3d0a84360bb5ad66274f1226f5cb273ecdbcf"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/1e1273f90187fdf5df3625764245610f86af6aa4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/1fbc57d118f3733287e9a9d808bb8947b3260e55"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/24756c396bc72894fd720092bb6f9c03e66b469f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/276def41311933421ae7a9ee42e906c85b6a4d3f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/29daa75432381937fd005cb25e314e328de6e9f9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/2a75204bc492084ad853682f8de3fb137d5907bc"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/2d34ba249b755a880525cf53c665633a5e359305"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/33f4ea0c7ea27c37d8f95cfa64d282370efdafd2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/35554617ea6418bd43161fe9a2c337ed82d7ec5b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/35f0c561297cfc840ddaeebb9fc61091f4eadece"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/3787bcc22ef645e665cc5f722b8a633af86de9cf"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/3953688866ccb3b4f371f1a858570d6afdb6452d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/39b19c41ba537f37511eff7727733715db432e76"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/3e3c4756d5e40b5aa250954cbac86b826e70a7ac"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/3f03265921120c6ffa61b944e213e062a5538d4b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/3fb034e66ee5494a67acae1b4e6ff64ba92a2046"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/466059ed07a0d55d6ad5e522c7d367cbf278eaf9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/487725eb38511c79a9340bf4560a1411061fa6fa"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/48b9b205cae8ac21512a3f26f49fd53e21ee13c5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/4b1f1f79a0bfa3f942479dd5f8edb59a7c257c55"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/5028c56a5116a186b7343ff59567b47347a0796d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/533f62b3f495ce704babf3ee8d840f196a714dff"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/5892cbb284771fc9761caae37b19cd6e27dbc104"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/5aeab6e4f7c2a1c09d4ac0dbdb3beac4893607ee"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/5b6292bdf009b0daecbc90b85cca30a88c36eec5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/5c1659b77678b41faa4fa13df7772dae3238d1c0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/5c81f61621e29ec9c6a64ac3af9b3b216141618e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/657368df512ca6294b9df16adf935a3f374a8be2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/7fc4520094902ce2c760d70eaad5b674d2817337"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/81f59a12b458ec3604035cb962165c604d1355e6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/8f41c50e88ee8c17ecad3d41d63d38fb12aca0b9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/97c16de7fe3c390a2e6c09ff5c28f17d5c67542c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/97e4499d450c95660de86747f527e670f2012548"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/9a996857196e0998a1278994a9bab3d35526e7f1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/9b7e00049ec356ecd84b1747e4e1941140139ae8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/9f0c38ec455cc363369b3674a2d32bc21c206de1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/a1dc7bc235e46eb21d91084d7b52d5ff9f45df85"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/aa3bbb876eafa8ad8ca4ff2eabc6dd94341d2441"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/ae8ba95d7dbe99926a8f5bfd80347fd6a4b616a0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/b04fea5c041c707db0ad9c09a81672557b52cc47"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/c4acff8aa2ff886f35439f72625d05002990c940"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/c55ce9995b002e88a102ae2891a71e8bacb346c8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/ca5a0c00b8969310acb73d15ad0d0c602f1bd0c2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/cce734f1b263de6994f7950e0df7bf0c81449f70"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/d39c8ee11a697634a09b309460c0bbd967e7effa"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/d4c3e4cf5d035596433c30eaabbd2b2925f4b453"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/d51f7fcc089f269c7afecaaca51966bab5fde629"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/d936dad71c129cf659097dc3db64550c4dd467f4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/e275b0466a8fb8d9e0e15856e343ddc7112ae66b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/e5c364b205855a2991ce07482aebb2a3a6147089"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/ee2077e08c3cfccd9bd82adb574ac4fc7d429afb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/fc5d4b9117ba9e87388174aee4f4970bdfe8d066"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/fdeb2c7daa9e7704f67e141106384e6dd0042c0b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/request1.txt"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/request2.txt"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/request3.txt"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/request4.txt"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/request5.txt"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/response1.txt"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/response2.txt"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/response3.txt"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/response4.txt"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/response5.txt"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/response6.txt"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/http/response_corpus/toolong.txt"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "http_response_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/006d552e952c42b5340baaeb85c2cb80c81e78dd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/007eb985c44b6089a34995a7d9ebf349f1c2bf18"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/03b74a08f23734691512cb12d0b38d189a8df905"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/0495693af07325fb0d52eafd2d4c4d802c6457c6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/05454ab015cf74e9c3e8574d995517e05dd56751"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/0716d9708d321ffb6a00818614779e779925365c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/0a9b3522a8e711e3bd53e2c2eb9d28b34a003acc"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/0ade7c2cf97f75d009975f4d720d1fa6c19f4897"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/0b1fcf0ac07e1e50cfe27316c7e1c8cc997f1318"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/0bc13548356d08009703d35e9c8d74397367bdfb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/0ea9a160c57f2c705dce037196e360bf9be739c5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/0f20d9c46991c0e97419e2cca07c7389f1d6bdf8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/0f2e2e6346f70c419300b661251754d50f7ca8ea"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/108b310facc1a193833fc2971fd83081f775ea0c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/108e5bcd69b19ad0df743641085163b84f376fe8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/10e3ecd5624465020fdf0662a67e0f0885536cae"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/113c8c97cbb0a2b6176d75eaa9ac9baaa7ccddcc"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/11479d936dd006410a5946b6081a94d573bf8efd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/11aa091189b78d1cc35c7ff4907ac16a73aba547"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/1227907b2ee5a9492a890beed55332e4560834c8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/134d65130947ec69cf8df8483424b45e99cf04e3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/13584505caa892d94982a968bbc4391ebcfe0d06"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/137f554ee0f6b903acb81ab4e1f98c11fe92b008"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/1401ea03ec78b8f20dc7be952555004d7147f0f5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/141d45a59b073aeec4443cd7bcf20f7833ddbc95"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/15a8f2e7f94aa00b46f1b991416aa015dd633580"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/15c9c1284c27c8893559e15c9b2a50cbd5bbb56f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/15d1a6cda48ef569b368a0c4627435bc2c80a988"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/17a29f2ac6df774585d7713091b299729738030c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/17b815f1f72cb64481bc40263e91ce063040f739"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/182d57403d2c973a394055017d35b7621aa0aa05"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/190fbe2da448f6bdec0706c5301ad13363ae3ad9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/1b045a24b8f1f1fd6e8234d5019952ee7713a8b7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/1b6453892473a467d07372d45eb05abc2031647a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/1c6463aa2dabcb4fadc8e5441d8b418535e768af"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/1dea95b5050b766274ef80847505c0e4f47f3ebb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/1df0754d3e7970b3afe549b11ca128dcd0d4832b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/1dfe267b623b20cd97c6e8969d8b9148af9f4a2c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/1e5c2f367f02e47a8c160cda1cd9d91decbac441"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/20efdba13ca7a3657d071b3d56997aa3b083068a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/215a956168f77421253e947c2436371d56aa7ea1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/2174b9ab6bf4f7c21fe1ed56957f1776ef611959"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/232f4bced4075545bb1469d5c2360f083ec7ec65"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/26aca41ee8f199e7c0c7cf31d979952571c53fc9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/27d84210636e9e83786be9e9b96b69f70b743b86"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/27da426a5883662d19ea78f306d7a992be52f827"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/296dcda6f7e6979e68ddef7cbc1206a355084ad3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/29b08c03ca5a6851fa4604a984cb7ff44433a5a5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/2a3d964ec4527ad9f02129fcbf087b67a6ea6444"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/2b04974149815b143afb17af4388d751217e54ec"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/2b3b1ad952e3acb566e32a84e2d503acde13eb53"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/2cc301a6ed7f01e2cd339f02bd0fda20c227a17e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/2d3d5b9275553430b4cfa68114099120ad7809ee"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/2d5dbf403e0c12e2fe21b04ca3daff171c028ab7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/2d7c769bed62004270034b976b1d940a5686106b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/2db120231eea12d9cdc6a00f30839b3cef2046be"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/2db610e1a230409a205cf22fbad3348a54cbe703"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/2df1dd2e2f5d57e7d9d4e60a756a86e603573225"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/2e32faacd3ea4461ec7aace297b4be6904d9a389"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/2e756d91759d7e74f5b776c0d2a1935292f576d1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/2f09b24f9f5fa0af2c29b604b4b0f97fa6163895"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/3027d901361162b38fcaf17f97ba7d9646e32495"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/30d4467ecb771ece9ed6c78a46adc299072d9db9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/311048bbf4c4bbabcde73607d7e76915cee9312e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/323b48969d7bf9a50aacf0912f1b5cb02119e2ab"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/33400a242baeb5c46ddb1578c28b10d32a9c3cd3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/356a192b7913b04c54574d18c28d46e6395428ab"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/35e995c107a71caeb833bb3b79f9f54781b33fa1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/373769c15c145472c8ec3bdde8fc84e85ec79211"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/3795d911970a1fd8416b93649051b418948e3edf"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/37d3333e1e2a384c3ba14a52682ca29f061d1ac7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/38cd33bb390445e35b6514024b1317902cb7ba1b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/3a90c688f44447a78efc111872b061a001f04d2b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/3b1e7b56ad4465d126ea994d34d20dcecbb3a50a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/3c0a8d6c31edaca124714624eb64cb8ec0cbab13"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/3cc0c9adcf3882f01409c70391c3cd30588ef34c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/3d0d9878b812ce4634962ba3dd755c0953550200"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/3d4d5887a2fcdc5dd360b8a6f89dbce6500d8580"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/3efb5b7ff94c5b9d411c93da9a70e1cc547f4c59"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/421b7e8ea86e3c07474af16ab3ccef55d1857205"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/428d051e437dd260f2a2f7ed920d9734ca34dc90"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/42adc281578ffb1b8684b78b47aa40a16d10b6e7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/43620ecd2e2fd58fe5650da2e9783f980f29ec07"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/43b1ffcda49477adb1632822202631990ed3a269"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/45279f85bf2f533a629073caf89403006279fab2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/455d9bb597f08bf698454157ecd86647b5dec4e0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/4561eb5c7e43cae048c06aaaad3d5f5218b376e9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/46417b001eeb87c32b642499fd5e1690d5d88c7f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/468af040024e96e9878ef33cc52755c5e7f5cbd5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/469e5ed2547e9e55a96e96eb832c615631e3b576"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/472b07b9fcf2c2451e8781e944bf5f77cd8457c8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/486da8aff04083c5e0fe112e733f2ae510e312a1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/488a5ed641e340ae51992e04ce6590bdec587218"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/4a0a19218e082a343a1b17e5333409af9d98f0f5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/4a6644a1a3d5218f4bbd60220cab79c0b7bef45e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/4b39d4b8a9a04b9469e8fe4016322327fe540882"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/4bb0294e14946fb1f64213384097a676d3ef94f0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/4cd66dfabbd964f8c6c4414b07cdb45dae692e19"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/4d134bc072212ace2df385dae143139da74ec0ef"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/4efa35221b2088e785048d0ff8fd99b03d5316fc"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/4fa2a4a5a2f7dc4ddbdecae3ee85c787817b4cf8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/4fed4bf2dc6259d9de54e9fa7db4fd5a61f2535e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/4ff800de0863adb5851fa26935159aa53b11cba7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/4ff99a030518a132748c44bc1d836018e5b82cd0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/531c87b9772e54e3e183ef729f0a7d5a0d584f46"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/534d66e7b0709d1e7692faae9e7f7299c92bba4b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/548775f9d7d13339dba3001f8238b84e9a457533"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/54ec3b2d8a9b7a6d8204712eb1b90da703cf8a79"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/552cfe1d8958e6d003ec8e883c4983dd67ef255e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/55f0c61d096a08506076489ded3b868db4086770"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/56cd60743c2cee939f5f357905bd36ec9363f441"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/56e5f35e3d08b4e17e3558cacddf9e5ed13a0159"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/580b03c49fba02bb8e399500eb66f2ff0482b22a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/5852643fbbcf92b0181327b69b4874c6ba6fa9f4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/58f497e5efaf9f69080f9eef63b0b9dabcfdbc0d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/59129aacfb6cebbe2c52f30ef3424209f7252e82"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/598a287a3e56caae23ed63abc95d5f3457165eef"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/5a37a26dd2482226f534f79d321d28e7a615ab72"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/5a710dcd4c78ca1a74ceb9fbfb011f7ac86a5f7b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/5ae7b87f5377d5ffc16fd3f69b4a4aa7be8b1184"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/5b3fe86d5a309a6ba745881bd220fe1100b271ce"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/5c38b7da113ab4535dbc22777ce8a1480c1c9d1e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/5ca6c45a8d2e11c782806df43e7668beb4aba8f5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/5da7b543313339f84fd52e96bacf3a73368a1d2c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/5e12ae9117668bcc22832640cc626315940aeba8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/5e397439a2680ed827c46704969c6711dabbda84"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/5e629dfb8b7533c7c2d173d4c3d587c88112cc29"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/5e785c7c26813577f3e30ef8f7e37ab2a9ffe39c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/5f3394f5058822cc044b92654837625897176480"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/5fb9bcbbb30a377209eab0541d144e44e71508d7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/6008213a61d06b4382b223768530c3452968b7b3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/60ba4b2daa4ed4d070fec06687e249e0e6f9ee45"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/625ed64c30c8ab2f0b3bc75690f9faa4270f0041"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/6314c2b304d04dc0108a95d29a93515e85e2b0b0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/6462d8079d2ea921617e7d073b85cfab706800d3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/6474383282788e556aa86f57fc8650137ad264d0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/648c3f58ecc8fb4b8c779e6b11006ab5b1986dad"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/66328e03a2ccd5e54dab23b816182786e6f518b6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/683e9045bc95e0cb5fc16ec64b118433475ba559"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/689f13680f4682303c8aa6828b67955959dc9669"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/68c6ba7f0602a5410d1fa3c5de24fe264436b993"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/699cafde80b1e1777306f781186d1253f018ab23"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/69ab053b59e235fd6af246c5180f15bd95295113"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/69afa12510b2e653b0af7c7030832647b2d63c37"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/6b75857f86be5c51b21a97f4a61e69e8bb6cd698"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/6c75e71ecde9f073a7bad89f4831c8cde0bc1830"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/6ce5170dc4f2eee3b31a875b6a41f2444959f3dd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/6d2859436fbbee637f0a5981ca82e8f88a1d0d28"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/6d63e39f56d1d537bab9c2830303cabab3cd9035"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/6e05a0a240fe2974e14527bbe390d294564156e2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/6e6c9d301adb0f0ddffd79cdf3426a2de99bad48"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/6e989edf725ec64849377681ce02641c3d1870e8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/70142f66475ae2fb33722d8d4750f386ecfefe7b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/719edbe667ce2729ac78a22dac29263c91144029"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/71f99ca2bda6ef2e15b965479a79587f9d794be0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/743e89b768af4bd591ea7228118550b1bfb8e7d1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/7714a1a32872442a2eaff472685f3ea69451a732"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/7719a1c782a1ba91c031a682a0a2f8658209adbf"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/775e8ffda1f5d340dba472d06dc7c8bf8159e379"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/77de68daecd823babbb58edb1c8e14d7106e83bb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/7957dc9aac31e6a6783fb3a6ee073688fed6cf9d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/7ae893cbbf9b11ff411640b80985ce618907559c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/7b20ac50954063e3ad00813acab4a98b2bfdb858"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/7b6273145fb090de1c6163586f884a1da4b5cfbf"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/7cf84b5a78281e6c6b5a9884110f3dbc6a40e310"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/7ef13b83e6bde582d9000be043e729cd3221c150"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/82059e250904b478f65daa0e647c1647ba6d6a3d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/8207fdf4bd302d6b6b1894990b353944a8716aa7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/831a49ad81b59025c241ac9e58bd88463fd798eb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/84582c1dbe026475319df14c19967d1dd0bf751f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/860d4ad0b7c026d1fcf51932b5e46500be7860a6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/865c7cf36a4f4499a6242e51b77b58b868a7447b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/87a2b80f9272583517c0207af176fc40ea55022c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/887309d048beef83ad3eabf2a79a64a389ab1c9f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/88d89860ccaf21e5f0f002303a2cd853ecbb2acb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/88f658400b1870ddf081fb03020c3098b0b1e083"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/88f8b0984bb2f081918ad883c8f0ffacb5a8ff0a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/89304953495f060c7abd3584d83cb1c8e6d6653b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/8a5f6dc6873e3fd51fd866854d85258f8aa83a02"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/8a87261277c15667e2957dd52c5db6757ebc8e88"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/8aa61d8bd260942521bb1ba82cd4cce2324fdbee"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/8d8874439569824e371a0284460440175cdb8a27"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/8d952ec2e33b2a6a1c7876898719a610f5546388"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/8e6fec8a05b24f221b6e94fdfe205e5bf7709a2c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/8e7fda77644ff91578d25243fad51a3cd6d60860"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/8ea6295ff82bb119acd44a91b463b19fedafb226"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/8ee51caaa2c2f4ee2e5b4b7ef5a89db7df1068d7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/8ef4dd9f2d0f9d770c937d9a43413d24df83f09b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/8efd86fb78a56a5145ed7739dcb00c78581c5375"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/8f0ba762c2fed0fc993feb91948902ac397b0919"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/8fe81e450694cac1eb4c4a5c966ffbc56ade3513"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/902ba3cda1883801594b6e1b452790cc53948fda"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/910a1528b28ebc6ff2f2a4fedb013c86de4103e2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/92049bf3d8a0ec93c2d1633631c0082e66ca69e7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/920a3c318f3127b9c30ab02a077555c7dfbb6edb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/925fc05dd661aeb4a776dcbc5df3dcb2cefaf0a6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/9367ba65affd5bf7aabf79c28e783cc5d93518e8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/939f5049b1eefb91ccbd3fcecaed8cb21ea6b285"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/9405c2b00eaa5526f71cc78914dbd3ecaf093b6e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/94d3598751569d2a5be258e59665cbbf0692dfbe"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/94f96d95d01e98fd2f04ce26c0913e5f9a882fb4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/95b54a84db75abab401d282fdb04440a879a9708"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/96189202e587ec951d5795da3e03062f2fb5d708"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/9711703428704ce2827a719eddb9d54be23a0cb7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/9734597e96eebe99b2243121a51d178a338ec46f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/9747c85a9510011bf87c23a80b029b9f2d04c37d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/97d170e1550eee4afc0af065b78cda302a97674c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/98e02e7fc96479e8d10ff2cc7610be772e2d6fba"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/996156b191b619eff79b2fcbb7598518a09b06bc"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/99667fcfa6d583a742fb5450527fc86dfb78ebbf"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/9b1ead2dbeeb1a3e9a7bebcf6964c3cfbc7e8867"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/9b7669e201574bfb979d56110539a90da5aca2c0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/9c24b456af3cb51a1ff2780c2d9cbdd7d93f6c76"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/9d0441f23ae7d5a3a5b1140497868ee6eeab656b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/9d890bd3139a8f9a44d435ff8edfbeb5b072ded0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/9e6a55b6b4563e652a23be9d623ca5055c356940"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/9ec88420ef0408642f6930996e35f5b9f18ec88c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/9edd067c569315d5e93b0d14c7eac9fa6d81d3cd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/9fbda4f714043d975389b536b4497c6d713452e5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/9fc8cb8ab3b05e306e5e81d9d949e69f931244ea"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/a02b857f2eff73e8e188f35529dd91f8144b23b9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/a060d5bfd1235cbbe4bcecf332fa3b03bc2282e3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/a0931fae1d43e7887c1cabde83fdfc52eaeedba8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/a0d4af29c6c223b48fe34d6a09b3a7466242f33c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/a1abe8a785030d475a7350438fd23a05c382c110"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/a1fb86293eac950c2b4f5182d9e4b5d9e0982ef6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/a2d4e3d6f5ba43c9199d5d2011678f82cfd55afc"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/a39653cb3d97c58c44013197f4d7557577700177"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/a4c74ad56ae0e94e96101a8f2ce9b1e588df5e44"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/a6b34b06b00e9226f2bd961483f9da81d8de99a8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/a72c3b9cc71eb7f0e0e4dabcd2dcd2b997f21c07"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/a749d24bac55bc19465acc92b12244c56ca0f20d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/a78009ff8b3f4d722ee0eb84795e857e74a58aea"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/a7ae4b16677806d78d0016c276b6722eba8eef3c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/a806f43dd48e35e75c27814c13a2a96c12449bd1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/a90a858013f90d2a94e0d62a7156ffd6848bf238"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/a94bfbfe16d026b52d7f73cf78fdf7d6a6c5c58b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/a9718f029d11a9335ef596cbd42794de5b0b18b5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/aa6e08a488d1ed00aa51f20c2477fc89e7b0a852"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/aaa038513c192fec501e4e7302156872ce2fde37"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/ac2686c095a5a1c92a1d4209a6c287778720c86d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/ac9231da4082430afe8f4d40127814c613648d8e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/adc83b19e793491b1c6ea0fd8b46cd9f32e592fc"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/aff25e569bd8c93157e08cd18ebcd896438e34c9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/affced8168ec801de89deac663f708f0c96cf1a4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/b015dfc2f62b640d7c25adab7b38c5fcb5cb64c8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/b021dd7cd98b63092685ea092df0dc01c8f63334"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/b17485b8bdec8809b3819a83753ca893871df403"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/b32ef51eca9c6c658e6fb75fdf96bbba066404e7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/b3f0c7f6bb763af1be91d9e74eabfeb199dc1f1f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/b45a1635ec526bcc890f9d735976704e516c5f19"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/b50ce51a7baa28cd298ebd05b4a3b9b70f9d4370"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/b5126721812b925426b30d283d2bb8b6969f230a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/b57af943a3ee411bffeaa3872eec9c6fb01569a4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/b5abf6fd22ed0f852781de35d043059d0f86f3cd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/b6589fc6ab0dc82cf12099d1c2d40ab994e8410c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/b6f19238d2b04c5b86a17369093dafda34f332e7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/b858cb282617fb0956d960215c8e84d1ccf909c6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/b9c38fad09c80db7781fefbe51039752de575ecc"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/bb407c8992800444201dccfe744dac49c0295fde"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/bc335734f73502b92d2bd3587259ce915985f0ee"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/bd113c2c8a2328e3674c680c7cff829a6c8ab924"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/be051d58015d4af1977a5dfd14ef3fd070ecc9d2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/be461a0cd1fda052a69c3fd94f8cf5f6f86afa34"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/bef524502f8dbbc45af717ece01ec88edd7f903b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/bf21a9e8fbc5a3846fb05b4fa0859e0917b2202f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/c0b6a90832b78ed5f6d129d3640c612540527c85"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/c18d315f0d35849b2aae4a47cab4608204b85d76"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/c257fd6bc9e5254a733378ab4ddd39629c4a3069"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/c2bf7f49d8f2e13a60af4473b3b3451b65b3aa9a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/c308517acf6f7088634d491a1608240f83a3ac95"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/c3badd71ef8a51b97ce93cbfe99f6778048f2128"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/c482a632702ae7f532d126e70149dda4fadc3cd7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/c541bb86e55b98e083b141114066f9c17d853374"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/c5b50b9015b6aaedd7eb1077b1204858f837b53c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/c62ef0dbd1350da9ea5a32e56672d385837643e7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/c7a34d6d49e1da1ccd490350c2df3a168ed09ae8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/c88c4bec8d440c56d3ea7abce39276f0927dbe0a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/c92f147bfc034003ac42ed9e62a16c84102ab417"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/c96b0fe6034668edf37ef0f5f391d5107953dc06"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/cac74aa5d7aab7fce0253f00c1a025980c1f9b7a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/caea0a0e6d8708cf682eaa446c344da56a7d5515"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/cc8a3dd2678d4b400ad630f402012b894e841b05"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/cd851bec7adad52f79777fb9347d5fd2f9486aa7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/ce3899b62ba3efe00eb31ddad2861ffe16a30d06"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/ce8b76fdcdbf1c951afc2b115be9acc8a6358b32"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/cec87b67871fc7a59652bc3546fbbb68e4d31e28"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/cf32406111908544e504c84731147f072cdf2fbd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/cf35dc76bf9a2052636c1ecc92942161830dcdc3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/cf6a5e6bfe4f15b43e411dd2782e10f1670c9767"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/cfc45616f5f0e7c25df91f6984ff5f6f1648beab"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/cff891e5858ae68d08ecc8470ca6a68c9438bfa3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/cfff4e9d08cba81b663dd1999710008342851e19"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/crash-f21867fe8b6df0b54c13e2e6e613dce871ecf0f0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/d1db03c626fb16c3b9cd44cc38cf40ebd355a194"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/d85ca051da784c0441898c5affbf11a2ae8f56bc"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/da03f536ceaf609972aa2a699687cc6f73ac0dcd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/da4b9237bacccdf19c0760cab7aec4a8359010b0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/dcc45e405208d7a2db33d0b5b9da2a2f1b034957"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/dcc60d3aaa1fc4d00201a3512284fcb79b5b68ef"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/dd0567ae57bf3cc85891a1ca988c2945d9186678"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/dd890a5a32e9f0489c6c77695f2155041f00fc9a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/df88e2baf7b76ffb2e94b9da57fd8d137f44b1ef"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/e00ee378c3f6e0b3cd89bd6e7517478d093f73dd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/e0c124e90d068e2a70a3e148052869033453ec58"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/e0d87b1f3e54e5adc5c2205f9e14772822a25766"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/e1199df649697c570db5d6b2ea09d755eddd32b7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/e235f6f2a8b6a22117f1baa932fb6c69799e1136"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/e3a654055a867ae62d8e68fa2c410228ac55cb6d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/e3c680aac46b9c46392e3b2c43ecdcc1547f2023"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/e3d134b35cc25a4861d90023c95988ec6103ddd5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/e3ff65de4b1622315c3b34b7a5e39bffb275489d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/e4a4085cc31476f5de9047422851d8ccf86339df"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/e4e3c69da200af932c8a79fa055d7aeea28eb1d1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/e6c3dd630428fd54834172b8fd2735fed9416da4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/e71eb37fca2070521e1e07c503c2bcd6445b35ea"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/e760e6e22ae8cd1ea78fe28b5eb1f3d7b5fdc536"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/e95ff1142118a2ca5b84935612a8a64d55360e64"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/e9c5e2c67930513941753c2d54591c7098c82f6c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/eb26070d17ffa908204912e75cb4313835042038"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/ebc6aee49e5ae57722df86e7fa33c420f045a449"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/ed1dc11d713e7487de18ce8317b62916959206d0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/ede3f66106acd7796da8b3942d029fe213058286"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/eed7bd220cd511b6d42ce6553019266a22a3d56a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/f090932162756b798b1a050b05e3d36a3437c4fc"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/f1905eaa84ba6a3593ec6ac0486a5b42893c01f1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/f4635fbbf765ead81a261ca152df02622e182d2c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/f46eeb1020c7c4153e742a50bc24c2c6939dab1e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/f473451610783521d51bc08cdd920ddd97f8a71f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/f63aa599600f6e7d648c4287905e16e8e6e479fd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/f667dcf1c06e87db2dc49d86ea1c285e796f8f8c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/f8d0f85975e49b959799cc52847110cc940b9db1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/f92c47e35da42d79a48beff54b93cd28f55f05fb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/f9a33bb8bd78d869fbafa402d9be58940ce2c318"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/fbf6f3156c1bd4bb701839bc0e26533bdccd1c9a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/fe2ef495a1152561572949784c16bf23abb28057"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/fe5dbbcea5ce7e2988b8c69bcfdfde8904aabc1f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/ff8fb34603c7f772768d61504954553e6bed173c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/test1.json"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/test2.json"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/test3.json"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/test4.json"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/test5.json"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/test6.json"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/test7.json"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/test8.json"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/json/corpus/test9.json"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "json_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/0052f8fb6a7884ced8a6754aa13441be1f7dcd51"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/0c35544f40d428d103e9c5b969ad9cd16767b110"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/0c60ee9ed55c9af6190b132ef6636c1d2abe4540"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/0ecb3e69889c036a86d21eb942077dc9abd649be"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/1324c95dafe597fe05f9babe92fe6fbf181c1897"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/14eb42f7423081b455820daa2c02b358315dc0fa"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/1e2dd3a96d4c5142da19b2dd64014d9358504536"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/2277a90ab01e3f27a4a8caf34ecd9997f3ffbf19"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/23121c5f633db5d7c1a9f2225240754246fee513"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/235548307ee9f2b0855fded42a871990d9ade956"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/28ed3a797da3c48c309a4ef792147f3c56cfec40"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/2bf123dbfa1d37a04493b5662a4b3b9c147485fc"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/2d4c0908ecc0310ea234d10b6bdb4f4ca3c41dd1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/30084b06df1cfb2bf2e1cfa8f8024c5af47a4d80"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/304e8cdc9122b709ec2c063a5c8c38489a788033"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/324d4a2aed8bc1840fee212fd38dadec80a72ea2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/32d5dad0f831572fbbd32ea3de5df43e27568f34"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/33353a0b011901a13d010c6b165074ccdaa717ac"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/37dfead09389fcd9b9d24ef817a0fed13d8ff2b0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/47879cc364be304754f6af15563ad6f9a538da41"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/49a5cef4c730ecab22712b156ddba5106f165afd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/4bbbbb794a098deeacff73b774c30f12c54ceacb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/4bd815b34ddfbbc45c780d1e7a97341796ee8471"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/4c498ce69c8476f745693deb23272930e05cad60"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/4fb5e3085c32e9bccac9e18343cca07017d037de"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/4fe5e46c1299e7f3e8a41dde3ae1bf1b60b4a43c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/595b8d51971c1d15146909567e539a1bb39b1af5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/670cc6bae958cb4f15e7297fe63959ac5799aa42"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/675f3263af7d1bbb084872f2b23f6d363227e85d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/67fe0d2acc727c8a39a707b92c6cebda9bd20986"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/6995dd153f712ad257ab5a365e5a4b84dc676ed3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/6d15065785eb8f4b5f17357a520cb4815a2cb355"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/706b579bfc3db01ef7216d77ce231ea477c2fae2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/71ec91b3a142105bc25dfa5b84ca0bd893e1db28"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/73285d7a70d73b517648067520d921e4477dbbfa"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/747d1ed8bee4c6f0438beaf88ae76d8ef9f63da2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/74c9d6b5d7d31a7c48c842311857c319fafedd64"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/763878a34b3adeb99a03b54d09768a4451617016"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/7b4b0c2555178333ba15203a930c88ef7e7500e7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/7b8a91aa46e370eb61307b4998889dc89775462f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/7cd11836c64f98742fa7beccec5c981ef4dd62ae"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/7d8f4f045e70e8a2cb45dc3c001504f5c2614b16"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/7e9848558fb004e14795b3ebd3e1488dcde1db8c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/8707d3367be279eba1ddb5ffb990e40a3141c7d0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/89734c37ee267e69a6950c6d60ee541c1be5ccff"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/899ef237274b4a44b5478d7ec880680a0cb7dd88"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/9034aaf45143996a2b14465c352ab0c6fa26b221"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/91e3b6a3484ab4b95cdeecc5aefe1291824060e8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/95cd94c858e5e97f7df4a5eb7552e5e0d5ce1ec4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/971f42d5a4d9816145ebc9dd28ba33ed3f5860b0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/9849ff4673525f3c6ad567fc681b224a818da732"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/9db3a1854de87fd643b910aeab50553afc73e667"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/a10e7effe8b9a50ef55b5e0244ea4dba5c48e9f3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/a147873135c6c52d4da03c260a0165bc0ab1b979"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/a20fa4d2633e9a401cb765470913483b848721d1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/a710eead945dabbbffa213a980c75f9463a27398"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/a72406e3ca06d941fe8e168bbf67da88a81c947b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/a8a62a7ebb7d68b211ae319e082575935c07d188"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/a8abd012eb59b862bf9bc1ea443d2f35a1a2e222"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/aab56035a3533b5d83a32a439f179eb678250113"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/ac174acef2c5da26fadc7270bab9c8c4e938c463"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/acbbd60eeb76e41ce254d0fef353b92abe69c831"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/b24237aa77b5f09208a7eb80b6178aeb2d53d24a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/b8e1c06314e52491ba955b72e13161c74e9b1422"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/c1eed32e1e353737987da851ad760312ea8e557c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/c4214ace2c4bab24bb356f71aedca08544baad70"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/c4f87a6290aee1acfc1f26083974ce94621fca64"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/c6fa750d7de79b2547531ed597ab7f1c4cd74193"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/d285d78d3ba966b4b199453d38ead1aa36a7484f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/df5200f371cff3cae0e1595cd86d641725f5d1ba"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/dfc66cb172919102f3ba14f6816228aa46f78154"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/e53e789a4c175c6a2c468472f1047d0fe8db1177"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/e67fe6794e755ea801272980f2c272edb027f6dc"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/ead61e86fedf118df8e44ed70ce002be651cf291"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/eced8b29efbdc82eb8a1d0865c5f382f0ff78446"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/f107c60f00da44a2c412c5b89c733efe5f9be4aa"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/f58a9135d07ea9a5e3e710f6b3bf6d48d5942dfd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/f70e0dfc4185374b764189b1a96f3b4b7581ce0c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/f8c2c4ddd2f474b4839f13a9be862c00ab0ece77"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/faa1781e1444bba5b8c677bc5e2a38d023a1ec65"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/fb60def26b39a737e29e850194a0c2047e378900"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/fccda587af845f0685275960649d8f4a45272a95"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/timeout-3ec5d82cc22b6f35ab7d281faf1cc5e66f0e3bfb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/timeout-6995dd153f712ad257ab5a365e5a4b84dc676ed3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_response/timeout-e5609086439f47e81c775bf80a7213fb73eb028c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_response_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/000def12957806bb0d40005cb651d35b4cde7b4e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/0068af2acc3020f344ee84b2c8adfb90492354c3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/009132022c3a1660b701728ac92e26baf82e8eac"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/00bf0233aa1155b34a3081e4a2b7a1c9cdf8ea1e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/013197cfb12b59755b807501c6d6615859f9cd3f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/018a4332eb19f2398162317cb6ad2e8cf700dfd6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/0273d3496bf5f4594e59083ac319f8f863a15be0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/0355002521e74dcdb3a0c633338bd02ab1d85312"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/053d8d6ceeba9453c97d0ee5374db863e6f77ad4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/0628c29e3ae264f8fa08652435bb3e61afe60883"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/065e91578e5359b70a668164310af6f0dd40e922"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/06b4b617d5937da8a7b58aed5341dc5ef6d1bcd7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/07216a4f5934890b89d845f6256546c2681350ce"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/08584e8308b7f52f0fe380358800d7f585cba89c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/085a37568e99ec5855bd96affd259921515479e8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/0903d1e9297179c18de6a3707b16f27d0d54ed67"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/0aa20a75bff4e8af10330c66d288e900146f1a39"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/0ae76e2b24ca999bd5e09e517aa4d88f5b5f58a4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/0c3025fdfb008a6563ea2a2bb6cbc79b8ccbf8f3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/0d219165cd317142afa36b8b5476cc022c95c4e6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/0e053123dd6256de5aff55b0731f913de250c18e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/0e065f98325849ac05eed515865b33dba0264cd4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/0e4ff715d491c9f0b471c400b71804739b6d400a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/0ec94942046cd7e00bc058204c1d046075ca9531"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/0f0e8da530eb8c924cee6985d9c3dfd93274ef8c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/0ff365225c981d74b89499d1e708684ed4d0b570"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/113b1efff1677c1b9a24f89aec0c3ecc228ddf62"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/11697d621eab6743ba22715722d5b23830b79075"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/12463318b795c756f389bc0fb1cca9645eafef28"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/12784250cf16ec999529f601ae5c5798e853d34a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/13122d08c1cee0dae6434605917d4cc6d8ea8cc5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/148a1118649dd8aa9b4ed778efdf7c1611aa5d27"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/15dea2bb5fb36a3dd5172796da66a821a32918e7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/16488fe15a7e33cb41f2b7c159c99154464b3fd3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/1870a48a3c9c1dd9027cbd85beb503b43cff6e89"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/1900b6a9123667a79020319aa7fd54d230bc7073"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/1a000f1cbccd2ab6f7e623e015ed2e84284c9dbf"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/1c1d403f6175d52ac4430d1ef2401b549761707e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/1c2ae0e1915e18dffc2215e9121f1afe0e4335c4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/1c5d2eef52426db9d0842f3d57b27a219434c512"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/1d0676867c1ebce84531035fa7eb86ed00762df5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/1d92b263fa70450b0d0aeb81bf5d2f69eefbbd99"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/1e843ed4864d6a808b671dd6769ae191ac8a13ad"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/1eb06a34ee568d584c4b33472788889bc68af3f5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/2169c2b4d560d74a5487df68b56f3af1d648f544"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/21f8f7583e58c1c81a3ac8237b5fa58071edf8a4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/231e348407fdcb14412c691b0b20982940160ccd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/27b8f060e3296eaef77dcdd4c2cd11d5650604ac"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/28ed3a797da3c48c309a4ef792147f3c56cfec40"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/291fcc6e043942638fa3c865c0a1be5e4dcc0e70"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/2a7f6c1f8fdc090b24ceb90ab4f3a7b331c06c86"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/2b85f180fe56f84925b274819ce10a8972a594e7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/2dea73d7d10ba0dcfd103f7542bdf7458e772b2b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/2e9c19f98ef88b83ec2dea8b1b7f92b8337f757b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/2fbd59ffb74aba392b86f4fe2ff8067b6d45cce8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/31059c32ea28d37b7442f51b20e966665662783c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/31f78e35feb36037864df5f8f47136f8e6e4768a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/326d322d1aa31696a14518830e544770f12146ee"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/337df26552e0884ff133cc1be8e72020be38f457"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/33a2a0aa86956097e034b5ee16aeceacee7efc34"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/33d175d1ecb3a85be7dd93d24efc3ddda0a85ad6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/3718a1b790db16bcfc4ec30691fab24ea7bb0b74"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/37aa3946054035b712102a62b71c94747dfd1491"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/37b697adc0708ad12e4ed7355f3f8fdf1b7919ca"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/37bf4642c5e5a806e2042cdf5ead9bf3c97b9ac1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/37d94ca6a20303389b35404f3dfd20aaa9ff0851"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/39278604f6a1102366464bbe769ae846e542bc56"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/396b57d9a11a1b135e36ad266e155cc0c3b77d21"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/39a49db120a807fe4e80c502254a5009625c7599"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/39f04d1c6d4beefa3e3d6eae3a5317d969787055"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/3b199b80209fa0b8ffedba4381019f8729cc09d6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/3ccf7ffb96c3e4789409db33cc12bfd8ddc24c1a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/3d04382d1fe11ff3b717100aece7f9eff2d04b9b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/3d4eb9f836bb40cf4c734073bcba8b73e4cc93ae"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/41dc8c55e41d32c30865f9761931ddd4c5b740f8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/41ef7b74d212f8f7f6681edcffd0db719030d31d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/431187b5926fa7d0823305a9f87635616ea3ef27"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/44c6da04b8378986721f7225e70a1514695c176c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/450161236e37a1dfc0da6398c4876df82ff640ac"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/45257a176ca6a05ec65a6df430bbb6b85d0a676f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/46d1c2f2edcc9cdc0d1698fa0c8853cb19a6e7d9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/4764bd4297bf0c405348d2bb87b8fbc02beadcb8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/48199bfd0e2c160f56d03e881bb5dfe276eec462"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/48e865c56e8db13640d6ecbfc0f2486eb77e07d1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/499b003b8b98edd9dbe2668c8c6af948769d7e87"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/4a55591c4b390c5a36cecc6f1b6f5105300b546b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/4d33f97ec69c64e14dcf205be36a6319ddb8a20d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/4dbfb08904739928e19c2f459040b35ac410f699"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/501bd6fe1de2719cf8d2c517a071e5d883fbe766"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/5208871ea8948223b64b304336cea41ac3240244"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/5348c71be34967458403bd4b58bb2a8a744d35ee"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/54362c2f6965268d0835a992c3ba656171b8f044"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/54411aa13f6d9118028171935322bbbc74c15329"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/54c50af22d147f192918499b4b3819eb389468a4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/55441aac903d96b36bf8a11bc804234bcf0c04da"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/56e1a7c279482a57fcbca43468df96a791ee22b4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/57cbea7c563d5c4b6b290271b0009c3f348d92da"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/57e11c7a62f0fc807d7b51bb1ef0f0e22f43795b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/585183c1a240df6926689fe1bd8cb434664db4d8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/5b2ee8ca40508bf108a729dcb228191670ec34d6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/5b47eabaf74479348fd0318f174d649dbe96e7d2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/5ba93c9db0cff93f52b521d7420e43f6eda2784f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/5cc827e33932ccf8c72c6a839074e856d93463d8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/5cc89bbf687f94ff87241a8f935905e1c441de33"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/5ec6596f12462fe9f36924c262f97408b54bbba8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/5f8f3af69295223fb04c37d28035bb75b4cbd705"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/5fd76d48b9fefecbdabd4511decc161b25db79dd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/614cf839ccac2d896d61a0ba0ab1f42b2fabafea"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/618305cc2d3d3814d78b77ffbf421b769bd862cf"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/61dfcd913c4f0a8d005bd089c34e95d8dbbf1897"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/65a89e10aab00039680e1f7d014737b634c74d8d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/66a273dbf5e37410efd45518a42b06a65cffe1f0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/673ff0de0702e8098892060a5365c175d8ef18fc"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/68465c782c37bfdd98ac493b0458444bb94336e5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/688451dee13d0be420598c6e205a3bc419173e18"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/68a1d9150e1380c219e0a1deb3993f321e000ecd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/69f49bf7ae8886f5b4c6296fdb1c570256919604"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/6a425f414cd69ffffdbaa34d03eb43841b432e11"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/6ca9e6e85f9b007a0920b0112decbd1403d506da"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/6cd62e3d67b4154639adbe753115bfdd770edddb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/6d4f2de4cc427417d6335ff5396ea2588509bb5b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/6ea84030dd0b5b03e4720c244ea8b4ec65e1f236"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/710c1fc8cf7dc1386312c34de5057933fcf868b3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/720e81dcaf83f867288a90293c5de3b088d5c556"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/72cdc8f78ab5237f96ed354264c726ac79ec429c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/73535a4f7af7e4c6aa23556cacd63f6929ac33fe"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/73d7b933a5673a4d6f5905006ef6266dda1e4fba"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/753aea13c82d1f8841c2bd4309b1b55d0ae2ba8d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/754428e00e8a1d0471e00bd9e8f060ab88ab640e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/761c29151b23b4d14ce6261626641df1182f7a96"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/7658451dd805f277a5b1c3d4065d752d2d8de5f4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/767e91cedcd9bc1bdac882acc34a53cc23cf4d02"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/77d3754bdd4ea358369c936ed36b974b4181f6ab"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/7a95295bebe6237f65deb15ffeccab22716d574d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/7ad88b82e87fbfb3d4bddaa2f6e201a151e3a007"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/7b1010cc012e34af1d03e8845868ff0e1db3a601"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/7d3ddbd11e82807321c9a53835ea897cf43aa7f2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/7da9c5ab5f049da297b0f4c1322edd696202d02a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/7e265a019c02e5d089152849ac00bb005fa644f5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/7f33bff4f740eb898b908374b0c1badd47566947"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/81f13b9b65891f2bfce77cb183a06045c461fee6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/846a14a480ffa1ad0f6333f3ecf2be3057ce6aed"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/87373a7f89feba2d50591b433f69877044155af2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/8833ba4c780c94fc6c3c466f849c0387acefdb20"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/8c23a5ecd20db4da2c061f3463254e9de104c8b9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/8d883f1577ca8c334b7c6d75ccb71209d71ced13"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/8dc80bd5f5d1fea64412203e304432edcf5f52c4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/8fc9a9ea6ad7d6d51e770076eaddacad9f970c6f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/8fd167de17534776ef57aba2f27675789a11b8db"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/9117d3e51560813b3ce4615dced18fa0e4d0a25a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/921c68eaa8776f7544e195ae52224355d08a2d4d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/9293945411fca2dc81fc34b36b575a384e6d489e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/933287d66c3ff3f0a21f2c583c763f2f65872ef8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/933d1d91283403f0a56571f533f482e9744eb735"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/93855fc41b3e3004ca6ba85f34b985042d4c9869"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/9544f445c39470f05785b52cfc31bb73bda22659"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/97757217fde05ff4fc15c864bf29e9f560fd1c62"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/9877c0f2d40dd43878bb0209bbc4b5fa93bec55a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/98bc5065f79dd9d20cdac14ba28f0cf39908cb5f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/992860817f7fb0e49423607355dab973aa7ab815"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/995ee3d74bc6042fd6a8908c9df5a4cb530378d8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/9a38c24a6e87e99a72a3a4f007b117ec191a1705"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/9aa97a0ffcdc37a8ef487355fb7271eb6891deaa"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/9b9fddc17ed7bc05a81c18f01e800a4e9efd0c8d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/a0d4cb9a5a30bb01e8e4f68d636fb173632ed29d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/a1e070288ec564d10a8c59779aa07fa771fa1d4f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/a23d10723415d20f4ef1ed9b14d9dc24494856a0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/a245750cfe4212dca7bfde918de85f64eb053232"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/a24bbe3600f4dfd61bb8415c6a291e0521e4f267"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/a25104d039a549c8d457ecea3b55369ed312f086"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/a33c4fcabe6aebe012cd01c8cb851a9ab0a12098"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/a393e1727b0decca9f193179765c3a83d7096437"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/a5507f06be4735a3a9e416ea986d52c1a6a20909"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/a5adf028c902d17dd6a7ddeadabbed2b36420313"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/a6aa1237a282ee3a93f2544bb6bb7704e565209e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/a871185cabce7b96c9e2f6ffb40d9901c774b335"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/a89d0e67bf53e22533a635f103d1fd400969ad56"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/a8d1b4e5672a501d7a6cd14b2929297f3a82e035"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/aa614cc8d05a3a58c30a890c10b9a0c1d609b228"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/aa65320376f63805cc82b247612b2e05b87bdbee"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/abd3f6e2cc8887942de20e1c257427b825aed0ad"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/ad0653a3a63675a7ce797e69b4673866b88ace33"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/ae2ce27806f67312e0d0e29a492db9ab9cb9bf4e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/ae4c0e671bd004165a1e7877d9c67249a165d2df"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/af75c24dff7e22948ed141c763a1309e6f540bcc"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/b0f228c6d0cbbc9f10117f344d5aae6f001d00fa"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/b2c6eab05580b85cda591093d3f05c44bf453fce"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/b35281c0aae174d1ddc8999d97b9713f8004f285"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/b484ae40795cf9730ba94d5a4ca40aa47b88eacb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/b49c2fed1417a981ba29b32be73ee1700bea7ec9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/b68542373c05c0ed25231d09955b2c699d37c45b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/b6d42cbe913f7275b574a71f0768781bdb6f45b7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/b80b6c2cae83c2097c7e4c1fb181d47cb8fd0519"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/b90ab62d8591182fd90cd21cdb893178d97f7e0e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/ba45c93ee6b8b286798d8791ec049207c448f7cd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/ba67e81ef0f9a14bf5a1ca228bff87c681e83a44"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/bbd1f06ddee4fbbd0e5c9c915889862e5df34f9c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/bd982feb5dd4362e6bd9746ed216c25ce2749df4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/be77053335e6496288fcf8b6c4d0b4abf86493ff"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/bfb53203499969fac4f4be48e1bcd9235c2fa101"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/c143576bdb5b34ad89fa3319507ae382a721f587"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/c1ac502a15c53a90a1934f4a31d30f93db36dc8a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/c1b29883768551fa5aadc38ba6eaad8007b9b85b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/c2331fe0660ab5e411f6d38968c706aed390d8f6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/c32647119c244cc018bb1863853d5c7bd37090df"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/c4098733900c27861bbf74a71afcbbd93d62f8ee"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/c4f5769bf3b4f2a55c006b4cf5a3bba44b347241"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/c6ea7b2d47402a458d5d03235bb042b61e05b2e8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/c7255dc48b42d44f6c0676d6009051b7e1aa885b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/c7d77af55176ae0ae5e59f46e48e1e6ea108d799"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/c80827341dcdf1c21b303b82ec7e6df7eaf63f3d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/c9501031a75c067b6602e2831f03421b87be4496"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/c98f88d962dfbc2a83e08bfbd8a87b0cc5a8b330"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/ccd33fa22b2983978f9617b3cde76ea05b683c2c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/cd0e7701fd79879c56f680817a0d2705751b1f44"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/cd1c2b5c2684d831aab5265e9cd6f1ee045dab9b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/cf98e8b01e7a759f28a9c5f59c896317d74ac47c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/d1d171589e035be85dc347278f0735151a342d68"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/d243143bf9b8adf6be92a157428ec6cbfd785423"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/d2cd278979f2842ebd890f1d84712750273ad0fc"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/d2e96eb2699c7dd4a183f13d3a063a1aa9c192fd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/d3178f8b0d26275667c27bb8533a61643213e4d8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/d46f536ea4b601c0ff313a5eb5b47e2b55aa9eb0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/d4be3038631eac422022ee23f43b47905a15b2b5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/d56b30a2d1b5a2a13ae00392bcb4ca72085310d9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/d67f85948143218d11e2fb7936a119741036045d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/d6930ea81dfd91856a06a0c16483e47616642b4b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/d737c10038a92add90e2ebea5c174ed249de8018"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/d758a67f018b176dfc7d29630cf8cb587f5b2a6b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/dc7139105787f3ba67d7971d80796e9cf5786a91"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/dc8ec35f43e994b9c4ac61275d6b934990d42181"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/dd2694fe12a018bc6af6f288b5c22a030eec8049"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/de7424f44508582a953f137195533b7a0191eda7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/de91a02040d792dfcb71a4cb5aa4c1c006201273"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/deb576067b11f6e2a3a39b0f2ef38ddae5c67b18"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/df58248c414f342c81e056b40bee12d17a08bf61"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/e076020b2826abd3a4b960fb33a35fd7d0606dd8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/e0bcf682342967c002621acd2563a2157826d156"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/e1edca08a7654b42a64647abb0e773eddddb580b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/e2fa528289b5971f5b40b3687a2a6f0d17348de6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/e52af0ba8750572b98f3a8968de77811ddff0893"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/e5a0f40647f805b5001645ce2d94505e72fa64f3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/e69762f0c6a2750c0b03503a6aec90ffc94bcb72"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/e7064f0b80f61dbc65915311032d27baa569ae2a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/e863a4420854c36168d2b8dd39ce474ebe11cd26"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/e8993f97bb9c83f87c64cfc429095eeaccf32953"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/e9875d9a54b3ebc57df4da886cd30a39252ac666"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/e98a9d92bbbac9b1e64c0641e967adebd681b2aa"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/eb7c31f48c77b742fa29126ac78a2c06c41208e8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/ec174492517f988010ed3ddbd003cb388f477bb6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/ec4d6a393be7ec80ccb8c531337a7fc3ef140e66"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/ecd40909ab5e2c61841d9fb95b8aacc87651100c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/ed17c8ddb6cc8a0b653dc87aca999d31e80c781a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/ee0b476126bb1c2249b299323718ecef1250645e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/ee1fb6a0b4139c07f1cf6bce850eaac9a2db29ba"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/eeac145c017ed35305f0ae69f820fc41e26e7997"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/efac7390c6e3a653d3ce93c3d6902f2f1c281ce0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/f0f0dace93d51cd8e045aeacca89424fc836eebc"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/f3341b8cc55c0bb6e2d0a1f7f06d68e4f04057f5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/f59ff56e341b94f2bddfd718b48ae9ab1692d720"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/f5a1824b9fd9f124df8097017607bcfa00eccfce"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/f5b92b69853a5d123bffdc6b0ab093f767ec30ad"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/f6aea4c380e41ddef2489ee581ab35e17fa3e8dd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/f7b7254a3af7c41cb86e4b23bb93c5a6d55e2583"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/f7bdc1b174f53a49c6ef8f8cdb9b8e74e0a5d4ab"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/f98c78c028baf22f39c77faf6e70edb86ac1d927"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/fb440171bca6ff922727e9ff2a4ac40d8d7905ff"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/fc76cc4030b422e4cb5c145c3e8ed122e242acf0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/fcab3b80624b431e464dc12d3b6da1cf538bd15e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/fdb3a9b59798d7e851d9074db69422b1d2df38dd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/fe5de5f387e31b029d589d9b1777fd0d6b3e47b3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/nanopb/corpus_serverlist/ff52d938aaa10c08b2eb0830fc0066c3b57e040f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "nanopb_fuzzer_serverlist_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/slice/percent_decode_corpus/04cb8ccc553f9b2f5e52c421aff6d1c954d3dae6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "percent_decode_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/slice/percent_decode_corpus/0dd8f3a63745b3a2d39791559b5c1b311447b537"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "percent_decode_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/slice/percent_decode_corpus/17eeaca784409adbe43365c32ac87915d736bba3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "percent_decode_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/slice/percent_decode_corpus/2040c1ff65f52a7ae668c2c8f324de5dacc9d695"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "percent_decode_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/slice/percent_decode_corpus/26b0d1da23027ae54db96e125e4a9e98842d77fb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "percent_decode_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/slice/percent_decode_corpus/2a089c0db45acdb4c6ed8e7ff81ca7235792c0b9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "percent_decode_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/slice/percent_decode_corpus/35b7b3bc3a740d5c3abca0d75b53f0e1e1ee998a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "percent_decode_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/slice/percent_decode_corpus/36367ba1adba47a1cbc3a88707fde8cc7abdc248"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "percent_decode_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/slice/percent_decode_corpus/39c2ba51548a0beaf0d6d1164531f1447dc311b5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "percent_decode_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/slice/percent_decode_corpus/56d08fea787c041395c6697ce26cfbc0decbe688"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "percent_decode_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/slice/percent_decode_corpus/678d981fdabb9f0d6640235cf1719dd1e1e66ae9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "percent_decode_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/slice/percent_decode_corpus/68751961609ec010565de0aa87521dcbf0722c5d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "percent_decode_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/slice/percent_decode_corpus/7875c06c6f03c9aa2f8e9c59f8d8957c8a32e759"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "percent_decode_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/slice/percent_decode_corpus/7b302090e090a5829b6d1dd7be30bd4e36a7e60f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "percent_decode_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/slice/percent_decode_corpus/875e1022169c9e4c541a9ad894e69e989df22ba1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "percent_decode_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/slice/percent_decode_corpus/8c1051ce066f5a26de9a9d133180621d0da957b4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "percent_decode_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/slice/percent_decode_corpus/8e084e628ab83a18ac7ca7cb3506525263655c63"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "percent_decode_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/slice/percent_decode_corpus/9d316c4675f40ddccaf8f1cc7aea94170b1e4223"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "percent_decode_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/slice/percent_decode_corpus/ad1c7c11d18a7d116e2c2ef4d4c5afb1270836ae"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "percent_decode_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/slice/percent_decode_corpus/b471f94aa4facf502e622e4a248f1ba4063ae681"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "percent_decode_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/slice/percent_decode_corpus/bf52ece030f16136d46e0dc97f58d60a0d8a1f0b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "percent_decode_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/slice/percent_decode_corpus/clusterfuzz-testcase-minimized-grpc_percent_decode_fuzzer-5652313562808320"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "percent_decode_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/slice/percent_decode_corpus/d5b2a7177339ba2b7ce2f60e5f4459bef1e72758"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "percent_decode_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/slice/percent_decode_corpus/de867b64c54a7ed773dc611fc5cd2f17c5433113"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "percent_decode_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/slice/percent_decode_corpus/e3948dbe004950591630dd5c52f4e0fcbd5e388a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "percent_decode_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/slice/percent_decode_corpus/e7064f0b80f61dbc65915311032d27baa569ae2a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "percent_decode_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/slice/percent_decode_corpus/xyz"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "percent_decode_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/slice/percent_encode_corpus/0d3ee7fa54e6c66103965fd4409b044ba7db6c3f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "percent_encode_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/slice/percent_encode_corpus/2e7ccf75e27b9501e3b28cf1c50ed0c45ab7c226"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "percent_encode_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/slice/percent_encode_corpus/55bb859f3942c462b03b7cbcf22ab4a0ac9705cf"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "percent_encode_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/slice/percent_encode_corpus/56070cecd54c845b6d4334953b17b712eb000d93"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "percent_encode_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/slice/percent_encode_corpus/61f50e891bf7ff5eb7a7af206f1e25d77f8756e7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "percent_encode_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/slice/percent_encode_corpus/6e0c60cefc704c7940e475a87dd9ae423061cb5a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "percent_encode_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/slice/percent_encode_corpus/7271ebcc6d22a0f186f7bc3c1973a7ed1bec8d8e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "percent_encode_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/slice/percent_encode_corpus/74c83ece3e2920a67593a9be9c82468f16cbb969"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "percent_encode_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/slice/percent_encode_corpus/98e004fd2a9f141a7a019720820080e12d637c06"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "percent_encode_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/slice/percent_encode_corpus/ba2c1e98227aa21ea3bb2ca4d0e504119717da8b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "percent_encode_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/slice/percent_encode_corpus/c16b9fd45370d4afb5d3ebd307a6e263c25ffd45"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "percent_encode_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/slice/percent_encode_corpus/d58c3cd4eab9b6d2343abfa1c25c90a383fe0ec3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "percent_encode_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/slice/percent_encode_corpus/e2619218ede30d2b7b8ecd601a9f0ae754b728b4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "percent_encode_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/slice/percent_encode_corpus/f93b3653e453f0e3eea3198001be6ce46e64bd21"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "percent_encode_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/slice/percent_encode_corpus/fd41d029c7682ad3d1c40a9fd017a4c85b673a54"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "percent_encode_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/slice/percent_encode_corpus/xyz"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "percent_encode_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/01c008fa.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/021ec59f.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/023517819bc642abe41d8735112fcacaf018c0cc"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/02918e4ad9e8928845f232c0cb043057add3c9a9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/0336e1ff71939de9e2007fdb4aba891e35a37488"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/033dd2f6.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/0384345c.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/03a304b82629155af693978c2b53439e553f6450"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/03a72675e1969f836094f1ecfec2a7b34418e306"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/03b9be1fa172dff5d1543be079b9c64fa2c9a278"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/0416afd6875d9ba55f1e5f86a6456a5445d5e576"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/052c8f28e5884bb48f0d504461272cd3a5893215"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/05551028437699c8650f5d08eb5f95ee25adf436"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/05c3a0390d0f52d241728926fa901599a47e4606"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/05efe6d81ce606557691432634e81f61e68b0b81"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/06285b50669cc16463db009ac821f99cf1ec2e24"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/06bd2f82fefb9943787d63ea359f9b77072380c2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/0766afc7c27c06ea18d896083470d587a380de3c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/07ad7e0ea2aaecba37f2429a64e946fc6e2556f1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/07c96c06eddbed5a3ce050436bc805f6821cbc9b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/081e56ce6f6b1c57adb806fbc5baa9f93f87513a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/08492d3d0994005206d1d3213b8747d1026ae1eb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/084e9e02b8f2ed41ff9c22fef80e522e491227c5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/08c42ef29eff83052c5887855f2fa3e07ebe470c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/09938e3256d06a8e168eb038d8a58b8462f7f697"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/0aa599e20761777c2cb9b41cd89e5c2e18f82d9e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/0aa7b949.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/0ab8698b211ee696f35f20a25c27e9429235fa41"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/0abd533e.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/0b275a7f.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/0c129f78eacfb0d0d3c89dd4e578724096a3cea0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/0c413d2b361b2221585026d42f3046ff4135d2ff"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/0d10bb63.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/0e349b8762703d080b3a696600e21d64c23a2ed3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/0f700e05.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/0ff4d220.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/10724098.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/108e270a272e312fc97ec23004b80fdc7bad3906"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/11516d58.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/11cda3f70be4b507ea936bca93af9ce5aaab3be7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/11e90d0f3ecbf72ad5027051d476a31b8d7e0671"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/129382aa11fa2922053fa47ba691dddb98901260"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/13501419f349b7855d2e94060bd08b28923d1f37"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/1353e447b7b10fb3eabb02863a1fc5bc9bb50460"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/1421a8e9f045ac65a0f6938fae93fece1060c41d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/146b7d66ad932c4b623eec8004e286d3705697d3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/14f9a0cda0d64590430218aaf6dedd9be2a3533f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/15ae78a8543a4794a27e6c79b0d34540322b97fd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/15afdcf2cadb93f56dbe36233d8cd7ea9d2bd6fe"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/1650b19093c56a1e86ee192bd9cd8d2266a9e353"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/16753235697083ecc45c117287f1d8ce6ad1ad1a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/1703a8f0c3b3c9dda9eba8d3850e69536436d57a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/17d7c718ec2597353a5dd2c78d6717a3d6aabfae"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/18d8d274aa7c163fd6d0084d5c25c8623e10c541"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/18f00b5f.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/1928c455f3685f4abe7a04697f571ab864cae02e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/1939a9021aba59ea2e49d3d0909e6fdf86ac3f9e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/1a69d5fc.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/1aa6897b6eebb8c68c972cc5025b39c7e60c17fe"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/1ba889ea1543297824e99e641e6ca8b91f45732e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/1cf17783de9e662f3720847f2d83d86dcdcab500"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/1cfdde7a.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/1d614f3d6b826f844178a77094bedb534748a362"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/1e92aaa5.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/1ea5651f.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/1f992057.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/20fd12d3670571283dc0c5dbb3fc139a8e943790"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/21475569.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/218c1b123428a07622570947e9b7cdb48c310ca5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/21a2dcda.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/22ad891a.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/23c582f6e23c7bbc9ae7b039b3b4e2ccdea3d5d2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/23f261e44d54a2736f6e288128d98db9e5015206"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/2463aea879c5ab49f8409d0e5c062c7e086b034b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/24ed80095e58199c52997f174046272f61ce4a8d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/25ab638f.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/26048c58bd5f2a94843f6fd1e4ab0be04b232636"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/26870785fd0564f552af4e0ca418738a85b21086"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/2701d1669c2996c097a74c5255d569615357b916"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/27ac2ae2.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/2814d70c.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/282b6585.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/29a8346696d6f0962072714b9626966c81dcef0c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/2a688fd507072e1cfa2e3bc58652a7cd82dface3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/2abe64b96e5e72adcf2dcc43444a69d0fb664b66"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/2ad6cedd32cd646ba8e25226c7c13a107c1d6447"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/2b14c6e618ec95754ea7e24fe6bc5a3a97df6897"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/2b40aa21723c7e67e92e74a3083df008461d591c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/2bf69fe6b40734cc3f0abdd765757809b14b0b88"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/2c4c7e2ed6d977ec119b040b328ad09808909a70"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/2c6660ba.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/2cc6d1f3ee8933518e91b8410781fa6e105b3a15"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/2e4805c3.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/2f20e2decd09b6f211a5469c67efbada355e6c04"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/2f3b1cd6780fe475f76f17e9e36541963d993165"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/2fb017cd4c34f4af183d03c4a219d2bb36ee2dd6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/30bba77d0f420c4f454011476f3c94e31c50c161"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/3224e6cd.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/326ec4d5.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/3292129aa7f6eba86b70fff64408f18fff895c12"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/32b11997.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/32cecacca27b249bd764f852168036c5f962bd16"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/330ad4b6.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/33b4cf1ac251f0ba0c014005ef8207afe1dea623"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/33e2ecd5c9bbc1f1dcab29d00195e0ab6d04642d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/340b032d39e2b212828a2bd1a97e2b6b81dcd41b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/34bba9e4.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/374262a5acf9cde1f480e7b7254c788e1936a4de"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/37ec9df8.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/38df7e63181cbd045e5af9dbee463360c8254618"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/395aea4fcfea081fc0d2733fff2d14405439fa72"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/39ea47bb.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/3aa82376296ab5a33f2921d7705b75b78b683c2d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/3b09bf453c6f93983c24c4d5481e55d66213f93a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/3b55d09b98e3982d6f80913a792463c3974766db"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/3ca5da2f.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/3d7ef8c7b05f26e914c479dedb1bef5e378d2d94"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/3dc665f93db294b9ccb8fcec94bcc2a91f3a04e7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/3de41f3f.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/3e2077a4fd2def7b11e618d46245d0aa85824317"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/3e3ae35a.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/3e787760.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/3efcff3d4ca529a89061c05ef9e8035f36d564b1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/3f3069cf26f761366f947e025f7049254d555e7f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/3fd914fc88fbf1a8804c6715100793d27fefd21d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/3ff171516486f77dda57bec1f757da1691547b9c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/404e234751b01dd0b51f9e7610f787253b074528"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/407607d2.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/40af8d589c76d7912bec06c2ae1f2466065018e7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/4123bd764c04385191342ea64918408140313714"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/416160124b3b64fc9355f24dd789b3d1fd097b8b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/418f392319c44d06a018ce4c62569d527829177a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/41b31ef0.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/422708b4.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/422fa704.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/4271fbb36e03cee79b21a4a5a65f37ceef58a8cd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/42b0afca.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/43fc6abab9840be5ee614211f17395b5966f6070"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/44516839d35af9ccaf8a2c62f3ce6a723482445e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/44f342a6.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/4558ddeb.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/459c0bf6.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/468cf8bf3e31e1013c7c6d2288baac47ff90aa63"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/47563391b73b6ef4bf987014c3e631fe2555a377"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/49cb33cbb60f041e8e99dd718993acd2c3354416"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/4aa883d0.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/4b7bcb4ae6c0222a1a24d1fb1a5d96519750ca5e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/4c412cc1a775cea041fa270483d610afb72f463b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/4d55d5ae.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/4d982c41efad2242f8c06630c23c68146153b47b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/4db3d4075ed27f2a2311f85dd1d6df028cc5d083"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/4eb269c3.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/4ecfe1be695df0d2489dddb52da8bcdeb6ed779d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/4f96a5fba4d11401eb22d4b1e365fbbb2d684f24"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/4f97bd97ab5dc6b4c0f62f8459be8a9593dc83b3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/4ff50e49865768323f94116bd98d2314455273cc"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/508def44e4d60f237f18a40d7058e58a752a74e1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/51a1abd1.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/52b5478161de7b2eba0f7bfbc29aea985c8d9ee7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/52ecfedca3b2b26e6999b6afc846f3dbd5d35130"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/53d18398c0d484de00afd8d583fe802d55d4da44"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/53de507f.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/540ada69.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/5413b531fe06923ddf2c9e3eb958769374bc2445"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/5429f0da.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/5435005f.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/546367bfdd2b9464fbfe5d74f55d8cd220accbab"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/54aca6c103dbdf019a2bf45506786c095e470de1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/54d0fc6c.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/552199651d942e7220141a93ec33dd8256210a18"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/55af20415ead0ddd417f37fa91a4c767b749ee34"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/55f6fb1a.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/5780565e.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/57918260.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/5841d898d2cd804f2d6373538e341dfba8a4dfab"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/58b88a24.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/59743fe120be6ae1aed1c02230ee1bb460f621ee"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/597fdab5.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/59ce7091c00075943d79e857c01ad1af5f38c78e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/59d0b24d1acd01c749fb4bd6802a5f4dd003ce75"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/59dcfde4.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/5ac92c4a7fb476393f8275fe4b79a2b13e3bcad9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/5d43ac923d7607a16e3d7bf8b838f52622871251"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/5d817877.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/5db8b96291c7ee12141eafc925be845c4f5ea069"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/5e2508e15c79fbe9c2e6c1a393b490356a17efbc"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/5f758756.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/5f820fa8d44229219d0b7c4724e3e40a2ace97f4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/609706c57e848ea58d7ca14fe6cc253322f3e8ce"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/61e798bdd49b339983fea4ccfe18efe44afbd69b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/62d05f336176a10a2c339c04d818f23b6e9a2637"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/6499e2db.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/64cdbb31d5eda779d07885fa7881812db7800c05"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/65077d2946cfb822cf92c9dfc44517a34589f277"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/65099066.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/652bfdce.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/65d5ae42e6acb429459a1e1a5fb35f09c0f95de2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/65fd6cb3058ee0baae854cc7859b7c0c1e1c1166"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/6652f7be83a876214affc3f230040757f7db4ea8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/67b04816.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/67ebf074c7f928c4fe32fef44e5c958cf441c93c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/68f564fd8064233897ff704b5955b33a2e29293a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/69891e9f.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/6c0ec181e81b915071766762f5d78e9b1ccc9128"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/6c5bb78b51cf5006c92258292de19550985c00ba"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/6c66271b74a11f4e7065a6acbc86e4611e7e0dcc"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/6db42d0c5471ac697d82e882c01867b73f71c71f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/6dc4455c.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/6e050e98.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/6f3bd9f33ca05bebe3811f7b3ae6ed112e1e45b9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/6f9d75e1af7ae7010d32872da888a582a25fddb4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/70ebe7f32c63ca8940017eb83e6db4d8b39ee03c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/712300b98afdb5f0d15c657c13cea76841164b13"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/71ab07577909ca4b766f8ea0c6b8ec2bc395fc66"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/72296cf9e1052ced4b60e2053aba9f1a569144e9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/72db978194609ac138bca393650740a3eae8f448"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/7342b3febb07521e39abdf4ee976d16199d51239"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/746715fe.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/76294f12a5974e9f87d8f092d0df5429cf6c0466"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/769f5d079151d1b5cab388c47a74f3c297c18d58"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/7839f12a8410a73d66e191cb5183d36d09a375e8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/7a946bf3cd91b63001f2cf3f40c515c747f2ecde"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/7b453adcb9c4bf31dbc448ff32c2bc90ebcbdf0f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/7d25c28298fb4d0fe41209d0d14307e4aa67c59e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/7ddfac7d7845b424bf670070781ca6ff8586c63b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/7df75412d12894fc501bd2d8493fe9e5a753ad88"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/7f15bbce.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/7ffd05db.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/8138b18a9a743659befc2f2b23d23cb9c3086a09"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/8164d3c4af043c47cfd6966873bccd2353d072bf"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/81fb19dfcb3c3a18fd9e7c177356479503e75e6f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/82dda42ddde662192ebaa96788945b7673bb486b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/830e3f794c53f7b284eb5c635b2943db9ee9aaee"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/8338ebee.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/84a3c6cf853ff318ae163231ce295171a59d5871"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/86478f200fa3602b9859597fd1ae56a04027d7e9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/8694fdefd4ed3d3fdb30fe1d7595f6ea6f5f5054"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/86a19d13cc65790696299c819cac17b14e337647"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/86e6dbf2.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/87155c97c3fc6276f7b8f13b50a50e2307b2d397"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/87e6640111fb02fa4cda7db9c1d51432b3b06212"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/88017b0894db1e6f4e3a6640ffe2876d31a54723"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/8846918f967dd6513040c6d382fcd68ff7099873"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/885fe25a0b441ef46ab176b88771c133e530cb73"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/88e1329b.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/89cd90fb47bb9eb289e8126b26021ee00d572d95"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/8b186384.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/8c04817a75fddd71f13779f2ad5b994f45c333a2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/8c72c3f35e9b9fd168ad9024c953a703f33ae3c1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/8c760938a2a72fa92b27e00e05005e2e4c429359"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/8da521d9.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/8de81717.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/8ec00f45afb097066f47d0bad256a8b856b1efe8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/90224b8e.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/90240c7c.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/9099ac4e83f6460c80b5557c87f653e4c65aa091"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/914ed07570b6441365a3636d05850f7316c7f2a8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/916b825da0ffc46fdb6120b1044e98ae158fce70"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/925011abb99fd56bb0f425ae5e0d92e6d341f804"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/92f1df2266f34a097e96dd22188d8633832d37b1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/93beeba2.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/93c3ffcb7e3bcb5ed7e37a5b3dfb97b43ca42718"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/947f53c0978672e59be452395670fa949a33cb4f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/9540d3ad3fa75bfb95c0d57cefd737611c7069a5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/954337ef.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/95d25ba2e190fafa2b3ca1e1c467b9ef64868962"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/9764015f89a0b7a59f3b5359b0a037b38d6e39d7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/97aed4bd.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/984886f71bcbb9e5c224ca15165d5c21d9daf13e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/986c9ca7db83b2cddbae2a0db2dca87f52277074"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/9953eb28aa1ed661612a4710a9d16a15de4ae353"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/99a1acc96512c1155f91afa378e2345726d307c3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/9a176b6f7e0dc5f681a1788d8954f76fabd08cad"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/9a6963b0d0fcb0e91a31748c47c6f0e1e842fea9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/9bf7553a.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/9d2d18fce18c790035d8f67ed798703bdda0a949"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/9d7b307bf4ef07f46b2c99311b4486bf40884b1a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/a112d484b70e778835fcd478fd651828720791e5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/a24bf2dc.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/a32be0653ccc65463445b4aaf24a7a1164d5c642"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/a357658d.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/a3a2b1af.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/a40c3ba87b4206142b134f67485859b7c9b7c75c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/a5348197.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/a5b529754606b96a8c801615ac12a1f6ee5c3f54"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/a5cc3762cb2b2cac316c60ddee794016057fb4ff"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/a5ccb8f124d8ddb5350b90bc0d6b96db280cb7c9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/a7e64803.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/a7fac1265a384fe9e45a9ee3d708b79c4e80505e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/a8305e9bb4a544eaef27e8bd21b4faabf524a84e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/a8b4049240b53947a8bc76cadf8d4ff9a802c783"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/a8d229374635fa6f2a75ca1669892e1bc244e719"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/a8f2345b2c949e9e32a434c99accf771f405eb65"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/a9463428cdc47d37efb6e3c5633d1e5e78911f16"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/a9966f7181d08f6a9ff8158736ad77a285d743a6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/a9e22d93.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/a9fc296cc61d020bc9afbdd0e7e5e3031e884176"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/aa3c8974.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/aa825693.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/aa8729d7.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/aaafca90a7f59184f3d768a1d6f9093e8f737b8a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/aaf049720c707d4e14e47e7eb31d6a2dda60e66a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/ab41d96d82d2dd3f41cd495c53ea031d7979b47a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/ac4e19c9fe290afc54bbb1e5f6cfe84a9c1f3c29"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/ad810f7f.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/ae297426638eb5a0611324f403c3189515274f1b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/aedefcd9bd7fc10b7bf60372da54c43e953523bd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/aefcbc29f2caea5038cda4dbc927cdadd9b844c4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/b06ce623.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/b1128694.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/b220d23a13d98d4815b1f7a3e4fe7dd8672b1c83"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/b28959dd.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/b431df13.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/b5acaa52.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/b74dcd9c2780f145e09a27d2e03119576889a301"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/b7ce4a4f6eea20c0b83d9f7fa8406a0730ee0040"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/b829143b.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/b887097732b9c30719f6c7ea7a7cbac531512a31"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/b924c842.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/bad4f467.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/bc9545cebdcb3af82406a5f0c1b286d28f9d4f5a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/bd63e44a3b004e7ed471c2367c3efae2c58a676d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/be9b6e78.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/bf5e21c32becb5839deeb81e9174cf6478a25473"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/bfb55acd5b66521eb5bd8ce6b57b3b6895883675"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/bfcbffa9.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/c004455e9d60bc2fff094e79cd0b38507023e018"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/c039ac9a5a570f8fd9064df9320890b885edf9c3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/c1188b44.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/c12835aa9f3513d3f7179ee4f9976292713f7cb9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/c13188118af1634061b6a3947b81618891aeb6a3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/c2d2aa1977b17d6e38f906968aa756e98dd09ffa"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/c35968bf.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/c39c0192d0d4f2b24f05c25a9e669cc091bff9e9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/c43d97f2.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/c4534867.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/c4a71cdd29759b51f9cc54175ad69c44b4ab6eb6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/c4e4c7572e005e18d56eac407033da058737a5ab"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/c559f565.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/c56fada76f5c198232201a608072a1a63e3d3785"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/c5ff50ae447ac7a0c8fb3363b2458824d405e64c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/c66e84d1.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/c6a1d2cc8935808b6e317a69baec1c3cb87cac94"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/c7c44b98faa21c8f0645a818a65b60d956d15952"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/c8073f5f41970fab4738215e42ec97a4383855e5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/c81dec02.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/c8812dc8a1ab1592a2d7b71300e1a0a5da6a6382"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/ca843c66c4c4807ccb1615b472c79bc459e5c6cb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/cbb04be69714f81f5cd09e36e8ea4e69ea73d618"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/cc97ece92b72cc2a4d045e16c0e2f2021bc014f8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/cca29902.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/cdba6c45.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/clusterfuzz-testcase-5417405008314368"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/clusterfuzz-testcase-5595941564317696"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/clusterfuzz-testcase-6312731374256128"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/crash-0f4b135c0242669ce425d2662168e9440f8a628d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/crash-239cc27a23827ea53b60ccbaee0ecc64dad2bff0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/crash-41ab0e868e84612275f77118f9e832bc94ff45c5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/crash-73923add5066617ae08f187b79d2639b4fd96138"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/crash-7af5da2a8da23d197d9336e32da72c9ff64c15b3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/crash-7e121dd3be057176369bea160d873040b32a03dc"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/crash-901723090ff2042ecc5a008ccd7ae0845c1681cb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/crash-c1f66840627e3bfdedf2e4c225bc4de0c267ed37"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/crash-ccf36bef9318fe6d5e5e1560c5485cdc87d0a701"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/crash-dae0f07934a527989f23f06e630710ff6ca8c809"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/crash-e097bf07afa8e55d7dd5f5df3569e34903ccf9a7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/crash-e34b0a9a428001cb4094a9ebca76329f578811a4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/d0f7eebc.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/d2031009d3783fcf083963fa30bb493f7f935541"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/d28155c6c92642c61dfb097f7b2eb1d6ced272c0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/d297b3f84e3dee9f74bf1162718aff66a11a7f5c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/d44d94764e1761cb7278ffe5cb17871abab7ed89"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/d6979f0f.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/d6bed9cc3c10338a8c5f41064ff8bec0bbc267ce"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/d8a1d141a9e3876b71c7decbe6e3affccf6de397"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/d9074e68.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/d95556cac07e720909aaf2ac09d876106420463f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/d96da249094db51ea92b1413907abfd27a4f2426"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/da7e44a9.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/dab172ff.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/dad922e2daf84cf039f50cf8636eaa9dbd01ff83"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/db33559d4afb4c32e68525c000fde16a4c3300f5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/dcabac1ef8b197ef39b188bcf5dc470f9749e903"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/dda9643679f8c8b796e64232a7d153e447d64991"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/df5d3cf5f05eab65ef9d385e263780ae73c42b19"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/df80b527a003e47a26099088a283228ec62a61c7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/e021c5b9815f02ee9d1e5a003cbf3500e19db13c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/e0d9a9a7.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/e2652fbb.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/e2c954e1.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/e3bab014.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/e7ad0c4b7d0f289c90a3988309e9e03b78f7eea3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/e7b08e36420fa107f0aee652e62158af85a4ef15"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/e96ad9c17795e52edc810a08d4fc61fe8790002a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/e9bbe2fe47b7b9c2683e7f17f4a33625c6ffbd8c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/e9d96662.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/eb66106b.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/eba8472a.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/ec4949487fa84f0cead39521b51f837af9dc784a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/ed8da77f.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/ee64e1ba4897bfd7c6baa1fb72d4c5f83b5654e4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/f0387dfdd6b8c925d958113e669ec4a1897034b4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/f1121b952e75463cc71137683dc2528f9cbc19b7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/f3220426.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/f3a092425c89f49b50469d522c99abbdb1b6dedf"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/f3d084cf20b92a5f026fe7cc6e5af49bde28693d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/f4024b01.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/f541d27e.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/f5424a9d7bd14317b6de7b15587df28bfde8362d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/f5c877c4.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/f5f0615030439dda162e8862b6bbd09f81f14d81"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/f74b9428.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/f7bf0d7bb0dd6e1866ccef9fafc3cb295db2f07f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/f826100f.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/f88ffb7f3066f2706cfcd9be077595e07834cc15"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/f8b46e92c7ceb4c2f2cdcb3452a6d8c58768eaa2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/fa202a5f51cd49f8ea5af60c5f403f797c01c504"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/fa36b4280d9e28edd81c5e4d192d1a5c2765e5e4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/fb3b0d80.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/fb84edfa9e8cbddba26a7184e7fdc219bde556c0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/fc162db40f87facb73cff20751e23af2e1f5296e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/fcb1dea251d1ce74e30351f13a3f71e3debec3d2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/fd14bea45ecaf13af0053900edb2f17b71a0bf09"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/fd26e0a6.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/fd943e69304dffebf47e1e40b0849e12abeee287"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/fdf67df81857577361d319e76559c5e85a257b07"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/fe17c07ffbaa67f1165938d2578038637b93cf57"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/fe1957b9bc7c6bf9d8b6089c422d72a0f444da6e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/fe66893c.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/fe69ddfa5827dd560bb0b5d4da7d982273f17ef9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/fe740f8c4ffd07f79456c8cee24ef556ee348f55"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/ff227015.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/ff898c08.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/ff902ef808e01b0b2d167c1c7e8e263d6f561941"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/hope.bin"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-0292270056246b7a4ccd2e7d0356665cef307ef2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-03c6f209b2f144734c83d81ed452839d9e244fe9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-082763e16153cb6b8f3f5308cd060e822f475e5a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-098ec93ded3a20e6043d11e9cc6066351e257f8e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-0aa52e00ddd54f8e129430852c2da95650c354b0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-129ecb5e7b80616f36791e3580844e520f2ba7d3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-13501419f349b7855d2e94060bd08b28923d1f37"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-14862768a1fe076896fd37e2543ddd23192a9e3c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-1a3ebf8f8bb0b5a0109a5ef44734cc64170377f9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-1ae0ed17a042aab8a3c3199c83a809b0243d1424"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-1b6c4b5c1949adae3efd5e3264bb32a40eea524e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-1dc659f500e7bee41a4fee4423ade8332c162cc0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-30408c9d13f29804168fc62a0818cc894c6375ae"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-33d8bf197de7131be78244e10fbb0da5055cf266"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-350b5da741597222c98fe86768432507850317f5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-395aea4fcfea081fc0d2733fff2d14405439fa72"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-3991c873ba814d0cd03a67d25fff0c8fe8713aca"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-3cec540a680b108dda1e0a8e0bfb2d44e5a4a4e8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-45cf8ac5faa9c7b15baf9281e8d7e0b4e103f0e0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-4c6da955e4c101b81a62b2f8e934d94a62ae534b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-51cdbfa3e97a46ceefde405e6ab087a109c26907"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-523cb1bca5ad56690c618b4ceac7fceca1113b9d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-58f116dfba8d428a01ca596174fca63f4ac523f0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-59f6edc7cf4aeed49b4dc024052db4846d5d7fc8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-60a9f77951c5059616764894e1963d83d478edfe"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-63ebf780ee6c2003eba622686a4bf94c503ad96e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-68ed2d33c9d32f73343c097303c3d5a6a3467c83"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-6d37c5e6d7efee56319b1316725fdc5aee5a52c3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-6e980a9d12c392175b5f66683e608626ae983276"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-7233d53f94386b0339b2c2b01ef2d348f5862f1f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-7281d9eaed0d20b0b6b5e7709c57e78fefe9c315"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-73e0a41066bc09c8e3fbd0dd7628445bcdaabb4a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-84f22ffca68c6e1590a44aa9f6dd0cef1f680c77"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-93cd6b3f9786ee107a0e2d135b40d13f96e652ed"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-97a338fa892093ed5013a76b96b35dd112df3342"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-9a176b6f7e0dc5f681a1788d8954f76fabd08cad"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-9de2e92150e54982d4e502b18f374f8cd8fd453b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-a1b2cfcf0997acb13a32fc5c004f57d9e9bc4275"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-a1ed26e6f82ca0e81e3f415bd8b0b8b520d3927b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-a61a28cf78149518466b87e5463ec5c771dc504e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-a877fe99fd0e92721d162bc252bf72a4f67ba1ea"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-aa23c18f6badd88a7bec65e8b04f7801ba624ec6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-adaac86cf1aa1e98e95240c5f92c3708456c3624"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-b281f018cc919301131cf3ed28449cfbd24b6bbf"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-ba0016a62a8576a57f000b90c364847ef6b12dcc"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-ba17346b8e46e6a05aaa7342a959a7c5ab0f1471"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-ba2b1fde90cc70d9abae22c4c4cb051aae8aa148"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-bd9d24f5c7c915174b6ca9d1a3573e16e0edee12"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-bda43d420a3e5d5228a5f5130207a1f11fc1c81f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-c05c239719a7beeca2c126b7e5ef7251fa615b54"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-c151762e5f37e233142059c1b269ce55434cf6a6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-cacd0e0c5f7d4169085735400100da4d36397185"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-ccafab6afdc6474610023b47bd7b3e1b9ea4647b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-d3c3cba3897fafec97665411ea1f94a89bb4de7b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-d3fcd80cd6f1bb05f5e5084ebb2ee801067863fb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-dc57e96cd02ba32fa4a99c97b6490e9879d30be5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-ddfe613d8791b2d377e14fbdffb18b84a89d49b6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-f3c688876395bf7a529f29f7b91532726cf5cbce"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-f412afea6b01aa53da919a41a65ffbf9885f2d65"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-f67be653815f6c2c10eea55c8009e1167ac9c20b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-f6c1042f96e15183dcc13b9658d971cc29426d53"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-f9a2773d6502fd4b1ffa73df3c550b0da63af833"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/05cda1e986096f42698ee2d86ab0a4a3f6a6690b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/0f65ef472e8308561c77ada56afd4de5932d950a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/128915cb83e66a736f8a1833c8901eccb81e0656"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/134d3a5e7a1609a583f6282c48ef9b871e0fdc15"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/13fccd43a6b52c62851ea24e8be4f8cfe6c0103d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/171bc6b14b94c72435d2da2e31e9682f12a3f13c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/17dea38d21e9282ecd062466cf287ecf5b30c1cf"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/1961eb9d4dd4bf21cbcd9c45a17b1d025eb0d200"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/226ebb5cc16ac42fae3be273de533ac79759ae01"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/2333cf428cb1e2976679ac84e64873bf76c6595e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/2885553a9e6829265d5f44ea4e24fcf7d6513436"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/28bce9a7cb21f3232239b9b71ef568137bf801f4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/2a0286615be426d1e7fd5894aadf1a503df05a0a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/2b4a1f3ebe223d91c042a5e86aff31e460f6cc3f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/2cfbe809bcf53160ecc0109b2df01a8696a226fd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/2f770de96db36ef9a71f7eb09b2e8695ac1f0655"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/30ba8ad171657470b5312232387b7da70c387219"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/36548a97a8b847e17a77d1e646c6eb5ec001d84a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/3c442804f73cfe826a609d97c12ef87852742883"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/3dad758011b16a3771376f9af91242953be3e47b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/43b56a1adffaf2c3c994679bf2b6fe6414e13df4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/4446c60ab89c34e5ccc26bec18d7e7d21fe5aec1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/44924b3866956d0668ec65750c3663279ac84a36"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/44e4370a4eafde61f8e7dc7e4542e0ad5ecf5253"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/44fb8c02117ebd75c97e517624c0abc9f9a76aa7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/45d76dd1f0a29fce3f8d289b5177263871eb3f83"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/4fcbf18c4135352539eaf445c26f2f8a5da9b68e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/508ca86c6f4e6ecc30c252ccf74e78256a893b17"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/515d240b860fcd1e77d4a5af291aa4a667d9b609"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/528e9738d5016f01cf59d74f20a8aa3f341ad89e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/54b636a2bb66ccf8247b53ff76a6400e9f1355d0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/5cc337c4b33cd703cd354804530f5b72684260d0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/5ce3ec59111bf328044e41fcf26b3bc542df527e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/5eaac270339f19cfce4eafa2e69d62adf100ad1c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/6129382083353687a5c3acb3d4274b811227bf3d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/616a25f7c4557ef9eb33d4367c6884abc336802d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/6214e558afbfdb8451e49b62619896492f1a8972"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/6c6a6b2ce74acf8a8b90fc0b268ecc7dc992cd60"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/6f72309e1b23b824e9bbb9abf74a014b78be038e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/7137ffad853e4dd76c6d6490f37b36e20de7ede0"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/71c9356b6b6c5a3a07033d0fa4ed417fa74a77e5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/7414938799ed61282f41d5fb1474751ca52b2682"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/75e853eb2ff7e78efb327e114b39baff5a1dd5bb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/7607c92952b4429e350260d8074c3c460468fd49"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/7677373c082fee56d8cdde009d9db5b117a4c8de"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/76abde5c970743f9fb8bc781e46c431dee2aa104"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/77e0b4e2066853df9d32d475b8788e3d7d19329b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/78e66840048ddc3c75e0e4abffbb3109af0d750e"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/7dc620eb45764390c7b106362fc4922227415407"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/82ca7a52d589e9dbae37ebf1c59fac7ad876eb7c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/8997d472f73eec84fea712638abd762818ec92ec"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/933bc3fdc56718d7ac0486c26eecddb6db1c5ba2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/94431bda60ddc175cf86273ddc07cb41ecf45fa1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/94c4272b2bb4fa9178eb4ae7dcf4b796fdcb22ac"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/9551c32a794250fb425005d8faf4bd24475acd41"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/9677da7c82f18cec3e0ed2e78aadd6e590271a52"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/9c2e6291aff608f3f5307a7c80db6b17107f0575"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/9c39dc04c7414ca0bb64fb942422bebe83ed8e8f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/9cc8547d183a4f2ab7022b36376ca4a6230726c6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/9e19e5e77789c34f99bbe1e6de198610d6765806"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/9f0853ccf6912df9fba2d5fc3a1ddece41c377ac"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/a6d521e501322f052df5a81ee622e0e4942ddcda"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/a9dc20f09890403be510357a7665a8f0db2468a4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/ac1c60970910880558ae7a2ca2e155cfd7772e05"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/afe36d0187a155fc6e4e5c055c0ed0f3802cf696"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/b12b5fc39edc5407b4a525c414ff6b5e116eee05"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/b5b088c6e3a96f88119a940874ab04cb954797ae"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/b65ad77a43ede3394ba714238829860c4ef4bc9f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/b6f265cad9d47e2ccd17a73a6d309d8898dc5428"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/b7ca5868bca7ae7d1952f44ca966218b26fb7207"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/bd20809eacabadb9bcc77d31e42d3359117b03f2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/c328623c4ce12505a54cf1a7a1606e1db36e870d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/c823e8bd5526d9fe7d51319737f51bd18bdd75e8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/c9394095d86ff36b69d90f7122592bf51cafe7dd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/cdbf0d2ae953bec07a67b7152785b548e55f85a4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/cef06f9c35ee338998703555847d70c26bfc9474"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/cfb40ab8eb7031e978bed2418cdc2f0b8a8d8ec7"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/d30840c3f48f11179ef976ada30477045c6d1e98"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/d5afef69141edc7f4911243cf2deb19c912999cf"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/d5cf71396e1a04da1a7ec266957ffd2de29d6a57"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/d6dd8a2b085db5d33ef24b23502293ce1ce906a3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/d7676dcd39b7c7cfaac513a98b56fe4ac8ea27d8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/d8c9e9ef14abc23b36cb493283ba3e2812d9e537"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/d9edb0aa5d2fe4af26ac861770c1530a4075f919"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/da1b52041957334b9ea1371bd2993013118bc82d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/dca7861424c8f92d3720de5c4488454cde1c39df"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/df3755e257d024ef8ab08f6d5cefcf28148ea4b1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/e360a49faefb87d671edb99e777f528f52cac9ae"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/e5e789605744d47e5a5d433bb04db1b413bc91a8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/e6e44a6aa0ece409450c85e43d02c57e338ce1da"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/e8ebd49ee98cf57ca7eb35b6e96ef8866270aac6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/ea0645f46ccd233337a8389b6118db5b0289f040"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/f6f7687df6b7056d3c819c03c9268e22a956b6b5"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/f725caa73aa9467c5e934c49780fc409b36b251c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/f8d3326a860091edd4d60725f96f429d13f3abe6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/f9261344b4049e90e88b5af784dd29b938c5c838"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/f95b97ece3b46815204a8e6d6e94f92ec40a9672"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/f97db29497e4e3225016a6ced837e20a13622f16"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/security/corpus/ssl_server_corpus/ff1a900b12f19772f9a86bd5f560a754cdb18d1a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "ssl_server_fuzzer_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/02d156dc5e6f2c11c90c2e06fcee04adf036a342"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/042dc4512fa3d391c5170cf3aa61e6a638f84342"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/0e9bbe975f2027e8c39c89f85f667530368e7d11"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/1155aa6ea7ef262a81a63692513ea395f84dad6f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/13856a5569ffd085a4d5c07af5f8e9310835a118"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/14b57bcbf1e17b1db1de491ef2ba3768f704b7dc"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/1794310671a060eead6e5ee66ac978a18ec7e84f"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/1d30b2a79afbaf2828ff42b9a9647e942ba1ab80"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/1fcf5d9c333b70596cf5ba04d1f7affdf445b971"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/23162c8a8936e20b195404c21337ee734d02a6bc"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/23f3198b815ca60bdadcaae682b9f965dda387f1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/2ef3893b43f1f60b77b59ce06a6bce9815d78eaf"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/356c3c129e203b5c74550b4209764d74b9caefce"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/396568fc41c8ccb31ec925b4a862e4d29ead1327"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/3b1e7526a99918006b87e499d2beb6c4ac9c3c0c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/3b58860f3451d3e7aad99690a8d39782ca5116fc"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/41963cc10752f70c3af7e3d85868efb097a0ea9c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/47b5228404451fc9d4071fa69192514bb4ce33c1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/56a2da4b2e6fb795243901023ed8d0aa083d1aab"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/574c2f13858a9a6d724654bd913ede9ae3abf822"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/582f789c19033a152094cbf8565f14154a778ddb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/636c5606fc23713a1bae88c8899c0541cfad4fd8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/63fe493b270b17426d77a27cbf3abac5b2c2794a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/655300a902b62662296a8e46bfb04fbcb07182cb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/6ae3acd9d8507b61bf235748026080a4138dba58"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/6b70979a70a038ff6607d6cf85485ee95baf58e6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/7314ab3545a7535a26e0e8aad67caea5534d68b1"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/7ff4d8b8d1ffd0d42c48bbb91e5856a9ec31aecb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/87daa131e0973b77a232a870ed749ef29cf58e6d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/884dcaee2908ffe5f12b65b8eba81016099c4266"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/8d7e944fd5d0ede94097fcc98b47b09a3f9c76cb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/9671149af0b444f59bbdf71340d3441dadd8a7b4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/96c8d266b7dc037288ef305c996608270f72e7fb"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/975536c71ade4800415a7e9c2f1b45c35a6d5ea8"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/99750aa67d30beaea8af565c829d4999aa8cb91b"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/a1140f3f8b5cffc1010221b9a4084a25fb75c1f6"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/a1f0f9b75bb354eb063d7cba4fcfa2d0b88d63de"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/a296eb3d1d436ed7df7195b10aa3c4de3896f98d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/a8b8e66050b424f1b8c07d46f868199fb7f60e38"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/aba1472880406a318ce207ee79815b7acf087757"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/af55baf8c8855e563befdf1eefbcbd46c5ddb8d2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/b3c0bf66c2bf5d24ef1daf4cc5a9d6d5bd0e8bfd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/c28a47409cf5d95bb372238d01e73d8b831408e4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/c3ef1d41888063a08700c3add1e4465aabcf8807"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/c550a76af21f9b9cc92a386d5c8998b26f8f2e4d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/c79721406d0ab80495f186fd88e37fba98637ae9"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/ceb4e2264ba7a8d5be47d276b37ec09489e00245"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/cf4395958f5bfb46fd6f535a39657d016c75114c"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/d46668372b7e20154a89409a7430a28e642afdca"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/d6fe7412a0a1d1c733160246f3fa425f4f97682a"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/dns.txt"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/e241f29957b0e30ec11aaaf91b2339f7015fa5fd"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/ea02d9fea9bad5b89cf353a0169238f584177e71"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/ec4731dddf94ed3ea92ae4d5a71f145ab6e3f6ee"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/ed2f78646f19fc47dd85ff0877c232b71913ece2"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/f6889f4a6350fea1596a3adea5cdac02bd5d1ff3"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/f6f3bd030f0d321efe7c51ca3f057de23509af67"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/f97598cff03306af3c70400608fec47268b5075d"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/f9e1ec1fc642b575bc9955618b7065747f56b101"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/fe0630a3aeed2ec6f474f362e4c839478290d5c4"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/ipv4.txt"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/ipv6.txt"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
-  },
-  {
-    "args": [
-      "test/core/uri/uri_corpus/unix.txt"
-    ],
-    "ci_platforms": [
-      "linux"
-    ],
-    "cpu_cost": 0.1,
-    "exclude_configs": [
-      "tsan"
-    ],
-    "flaky": false,
-    "language": "c++",
-    "name": "uri_fuzzer_test_one_entry",
-    "platforms": [
-      "mac",
-      "linux"
-    ],
-    "uses_polling": false
   }
 ]
index 569e7a8..ecf0284 100644 (file)
-# Overview of performance test suite, with steps for manual runs:
+# Overview of performance test suite
 
 For design of the tests, see https://grpc.io/docs/guides/benchmarking.
 
-For scripts related to the GKE-based performance test suite (in development),
-see [gRPC OSS benchmarks](#grpc-oss-benchmarks).
+This document contains documentation of on how to run gRPC end-to-end benchmarks
+using the gRPC OSS benchmarks framework (recommended) or how to run them
+manually (for experts only).
 
-## Pre-reqs for running these manually:
+## Approach 1: Use gRPC OSS benchmarks framework (Recommended)
 
-In general the benchmark workers and driver build scripts expect
-[linux_performance_worker_init.sh](../../gce/linux_performance_worker_init.sh)
-to have been ran already.
-
-### To run benchmarks locally:
-
-- From the grpc repo root, start the
-  [run_performance_tests.py](../run_performance_tests.py) runner script.
-
-### On remote machines, to start the driver and workers manually:
-
-The [run_performance_test.py](../run_performance_tests.py) top-level runner
-script can also be used with remote machines, but for e.g., profiling the
-server, it might be useful to run workers manually.
-
-1. You'll need a "driver" and separate "worker" machines. For example, you might
-   use one GCE "driver" machine and 3 other GCE "worker" machines that are in
-   the same zone.
-
-2. Connect to each worker machine and start up a benchmark worker with a
-   "driver_port".
-
-- For example, to start the grpc-go benchmark worker:
-  [grpc-go worker main.go](https://github.com/grpc/grpc-go/blob/master/benchmark/worker/main.go)
-  --driver_port <driver_port>
-
-#### Commands to start workers in different languages:
-
-- Note that these commands are what the top-level
-  [run_performance_test.py](../run_performance_tests.py) script uses to build
-  and run different workers through the
-  [build_performance.sh](./build_performance.sh) script and "run worker" scripts
-  (such as the [run_worker_java.sh](./run_worker_java.sh)).
-
-##### Running benchmark workers for C-core wrapped languages (C++, Python, C#, Node, Ruby):
-
-- These are more simple since they all live in the main grpc repo.
-
-```
-$ cd <grpc_repo_root>
-$ tools/run_tests/performance/build_performance.sh
-$ tools/run_tests/performance/run_worker_<language>.sh
-```
-
-- Note that there is one "run_worker" script per language, e.g.,
-  [run_worker_csharp.sh](./run_worker_csharp.sh) for c#.
-
-##### Running benchmark workers for gRPC-Java:
-
-- You'll need the [grpc-java](https://github.com/grpc/grpc-java) repo.
-
-```
-$ cd <grpc-java-repo>
-$ ./gradlew -PskipCodegen=true -PskipAndroid=true :grpc-benchmarks:installDist
-$ benchmarks/build/install/grpc-benchmarks/bin/benchmark_worker --driver_port <driver_port>
-```
-
-##### Running benchmark workers for gRPC-Go:
-
-- You'll need the [grpc-go repo](https://github.com/grpc/grpc-go)
-
-```
-$ cd <grpc-go-repo>/benchmark/worker && go install
-$ # if profiling, it might be helpful to turn off inlining by building with "-gcflags=-l"
-$ $GOPATH/bin/worker --driver_port <driver_port>
-```
-
-#### Build the driver:
-
-- Connect to the driver machine (if using a remote driver) and from the grpc
-  repo root:
-
-```
-$ tools/run_tests/performance/build_performance.sh
-```
-
-#### Run the driver:
-
-1. Get the 'scenario_json' relevant for the scenario to run. Note that "scenario
-   json" configs are generated from [scenario_config.py](./scenario_config.py).
-   The [driver](../../../test/cpp/qps/qps_json_driver.cc) takes a list of these
-   configs as a json string of the form: `{scenario: <json_list_of_scenarios> }`
-   in its `--scenarios_json` command argument. One quick way to get a valid json
-   string to pass to the driver is by running the
-   [run_performance_tests.py](./run_performance_tests.py) locally and copying
-   the logged scenario json command arg.
-
-2. From the grpc repo root:
-
-- Set `QPS_WORKERS` environment variable to a comma separated list of worker
-  machines. Note that the driver will start the "benchmark server" on the first
-  entry in the list, and the rest will be told to run as clients against the
-  benchmark server.
-
-Example running and profiling of go benchmark server:
-
-```
-$ export QPS_WORKERS=<host1>:<10000>,<host2>,10000,<host3>:10000
-$ bins/opt/qps_json_driver --scenario_json='<scenario_json_scenario_config_string>'
-```
-
-### Example profiling commands
-
-While running the benchmark, a profiler can be attached to the server.
-
-Example to count syscalls in grpc-go server during a benchmark:
-
-- Connect to server machine and run:
-
-```
-$ netstat -tulpn | grep <driver_port> # to get pid of worker
-$ perf stat -p <worker_pid> -e syscalls:sys_enter_write # stop after test complete
-```
-
-Example memory profile of grpc-go server, with `go tools pprof`:
-
-- After a run is done on the server, see its alloc profile with:
-
-```
-$ go tool pprof --text --alloc_space http://localhost:<pprof_port>/debug/heap
-```
-
-### Configuration environment variables:
-
-- QPS_WORKER_CHANNEL_CONNECT_TIMEOUT
-
-  Consuming process: qps_worker
-
-  Type: integer (number of seconds)
-
-  This can be used to configure the amount of time that benchmark clients wait
-  for channels to the benchmark server to become ready. This is useful in
-  certain benchmark environments in which the server can take a long time to
-  become ready. Note: if setting this to a high value, then the scenario config
-  under test should probably also have a large "warmup_seconds".
-
-- QPS_WORKERS
-
-  Consuming process: qps_json_driver
-
-  Type: comma separated list of host:port
-
-  Set this to a comma separated list of QPS worker processes/machines. Each
-  scenario in a scenario config has specifies a certain number of servers,
-  `num_servers`, and the driver will start "benchmark servers"'s on the first
-  `num_server` `host:port` pairs in the comma separated list. The rest will be
-  told to run as clients against the benchmark server.
-
-## gRPC OSS benchmarks
+### gRPC OSS benchmarks
 
 The scripts in this section generate LoadTest configurations for the GKE-based
 gRPC OSS benchmarks framework. This framework is stored in a separate
@@ -163,9 +16,9 @@ repository, [grpc/test-infra].
 
 These scripts, together with tools defined in [grpc/test-infra], are used in the
 continuous integration setup defined in [grpc_e2e_performance_gke.sh] and
-[grpc_e2e_performance_v2.sh].
+[grpc_e2e_performance_gke_experiment.sh].
 
-### Generating scenarios
+#### Generating scenarios
 
 The benchmarks framework uses the same test scenarios as the legacy one. The
 script [scenario_config_exporter.py](./scenario_config_exporter.py) can be used
@@ -204,7 +57,7 @@ Count  Language         Client   Server   Categories
 Client and server languages are only set for cross-language scenarios, where the
 client or server language do not match the scenario language.
 
-### Generating load test configurations
+#### Generating load test configurations
 
 The benchmarks framework uses LoadTest resources configured by YAML files. Each
 LoadTest resource specifies a driver, a server, and one or more clients to run
@@ -332,7 +185,7 @@ script) but is not indexed and cannot be used to select objects. Scenario name
 and uniquifier are added to provide the elements of the LoadTest name uuid in
 human-readable form. Additional annotations may be added later for automation.
 
-### Concatenating load test configurations
+#### Concatenating load test configurations
 
 The LoadTest configuration generator can process multiple languages at a time,
 assuming that they are supported by the template. The convenience script
@@ -345,7 +198,7 @@ script can be invoked as follows:
 $ loadtest_concat_yaml.py -i infile1.yaml infile2.yaml -o outfile.yaml
 ```
 
-### Generating load test examples
+#### Generating load test examples
 
 The script [loadtest_examples.sh](./loadtest_examples.sh) is provided to
 generate example load test configurations in all supported languages. This
@@ -357,7 +210,7 @@ with prebuilt images.
 The [examples](https://github.com/grpc/test-infra/tree/master/config/samples) in
 the repository [grpc/test-infra] are generated by this script.
 
-### Generating configuration templates
+#### Generating configuration templates
 
 The script [loadtest_template.py](./loadtest_template.py) generates a load test
 configuration template from a set of load test configurations. The source files
@@ -430,7 +283,7 @@ may be set to values or to substitution keys in themselves, allowing future
 automation scripts to process the tests generated from these configurations in
 different ways.
 
-### Running tests
+#### Running tests
 
 Collections of tests generated by `loadtest_config.py` are intended to be run
 with a test runner. The code for the test runner is stored in a separate
@@ -446,8 +299,164 @@ For more information, see the
 in [grpc/test-infra].
 
 For usage examples, see the continuous integration setup defined in
-[grpc_e2e_performance_gke.sh] and [grpc_e2e_performance_v2.sh].
+[grpc_e2e_performance_gke.sh] and [grpc_e2e_performance_gke_experiment.sh].
 
 [grpc/test-infra]: https://github.com/grpc/test-infra
 [grpc_e2e_performance_gke.sh]: ../../internal_ci/linux/grpc_e2e_performance_gke.sh
-[grpc_e2e_performance_v2.sh]: ../../internal_ci/linux/grpc_e2e_performance_v2.sh
+[grpc_e2e_performance_gke_experiment.sh]: ../../internal_ci/linux/grpc_e2e_performance_gke_experiment.sh
+
+## Approach 2: Running benchmarks locally via legacy tooling (still useful sometimes)
+
+This approach is much more involved than using the gRPC OSS benchmarks framework
+(see above), but can still be useful for hands-on low-level experiments
+(especially when you know what you are doing).
+
+### Prerequisites for running benchmarks manually:
+
+In general the benchmark workers and driver build scripts expect
+[linux_performance_worker_init.sh](../../gce/linux_performance_worker_init.sh)
+to have been ran already.
+
+### To run benchmarks locally:
+
+- From the grpc repo root, start the
+  [run_performance_tests.py](../run_performance_tests.py) runner script.
+
+### On remote machines, to start the driver and workers manually:
+
+The [run_performance_test.py](../run_performance_tests.py) top-level runner
+script can also be used with remote machines, but for e.g., profiling the
+server, it might be useful to run workers manually.
+
+1. You'll need a "driver" and separate "worker" machines. For example, you might
+   use one GCE "driver" machine and 3 other GCE "worker" machines that are in
+   the same zone.
+
+2. Connect to each worker machine and start up a benchmark worker with a
+   "driver_port".
+
+- For example, to start the grpc-go benchmark worker:
+  [grpc-go worker main.go](https://github.com/grpc/grpc-go/blob/master/benchmark/worker/main.go)
+  --driver_port <driver_port>
+
+#### Commands to start workers in different languages:
+
+- Note that these commands are what the top-level
+  [run_performance_test.py](../run_performance_tests.py) script uses to build
+  and run different workers through the
+  [build_performance.sh](./build_performance.sh) script and "run worker" scripts
+  (such as the [run_worker_java.sh](./run_worker_java.sh)).
+
+##### Running benchmark workers for C-core wrapped languages (C++, Python, C#, Node, Ruby):
+
+- These are more simple since they all live in the main grpc repo.
+
+```
+$ cd <grpc_repo_root>
+$ tools/run_tests/performance/build_performance.sh
+$ tools/run_tests/performance/run_worker_<language>.sh
+```
+
+- Note that there is one "run_worker" script per language, e.g.,
+  [run_worker_csharp.sh](./run_worker_csharp.sh) for c#.
+
+##### Running benchmark workers for gRPC-Java:
+
+- You'll need the [grpc-java](https://github.com/grpc/grpc-java) repo.
+
+```
+$ cd <grpc-java-repo>
+$ ./gradlew -PskipCodegen=true -PskipAndroid=true :grpc-benchmarks:installDist
+$ benchmarks/build/install/grpc-benchmarks/bin/benchmark_worker --driver_port <driver_port>
+```
+
+##### Running benchmark workers for gRPC-Go:
+
+- You'll need the [grpc-go repo](https://github.com/grpc/grpc-go)
+
+```
+$ cd <grpc-go-repo>/benchmark/worker && go install
+$ # if profiling, it might be helpful to turn off inlining by building with "-gcflags=-l"
+$ $GOPATH/bin/worker --driver_port <driver_port>
+```
+
+#### Build the driver:
+
+- Connect to the driver machine (if using a remote driver) and from the grpc
+  repo root:
+
+```
+$ tools/run_tests/performance/build_performance.sh
+```
+
+#### Run the driver:
+
+1. Get the 'scenario_json' relevant for the scenario to run. Note that "scenario
+   json" configs are generated from [scenario_config.py](./scenario_config.py).
+   The [driver](../../../test/cpp/qps/qps_json_driver.cc) takes a list of these
+   configs as a json string of the form: `{scenario: <json_list_of_scenarios> }`
+   in its `--scenarios_json` command argument. One quick way to get a valid json
+   string to pass to the driver is by running the
+   [run_performance_tests.py](./run_performance_tests.py) locally and copying
+   the logged scenario json command arg.
+
+2. From the grpc repo root:
+
+- Set `QPS_WORKERS` environment variable to a comma separated list of worker
+  machines. Note that the driver will start the "benchmark server" on the first
+  entry in the list, and the rest will be told to run as clients against the
+  benchmark server.
+
+Example running and profiling of go benchmark server:
+
+```
+$ export QPS_WORKERS=<host1>:<10000>,<host2>,10000,<host3>:10000
+$ bins/opt/qps_json_driver --scenario_json='<scenario_json_scenario_config_string>'
+```
+
+### Example profiling commands
+
+While running the benchmark, a profiler can be attached to the server.
+
+Example to count syscalls in grpc-go server during a benchmark:
+
+- Connect to server machine and run:
+
+```
+$ netstat -tulpn | grep <driver_port> # to get pid of worker
+$ perf stat -p <worker_pid> -e syscalls:sys_enter_write # stop after test complete
+```
+
+Example memory profile of grpc-go server, with `go tools pprof`:
+
+- After a run is done on the server, see its alloc profile with:
+
+```
+$ go tool pprof --text --alloc_space http://localhost:<pprof_port>/debug/heap
+```
+
+### Configuration environment variables:
+
+- QPS_WORKER_CHANNEL_CONNECT_TIMEOUT
+
+  Consuming process: qps_worker
+
+  Type: integer (number of seconds)
+
+  This can be used to configure the amount of time that benchmark clients wait
+  for channels to the benchmark server to become ready. This is useful in
+  certain benchmark environments in which the server can take a long time to
+  become ready. Note: if setting this to a high value, then the scenario config
+  under test should probably also have a large "warmup_seconds".
+
+- QPS_WORKERS
+
+  Consuming process: qps_json_driver
+
+  Type: comma separated list of host:port
+
+  Set this to a comma separated list of QPS worker processes/machines. Each
+  scenario in a scenario config has specifies a certain number of servers,
+  `num_servers`, and the driver will start "benchmark servers"'s on the first
+  `num_server` `host:port` pairs in the comma separated list. The rest will be
+  told to run as clients against the benchmark server.
index 14a68ef..a3f1be3 100755 (executable)
@@ -111,10 +111,10 @@ def gen_run_indices(runs_per_test: int) -> Iterable[str]:
     if runs_per_test < 2:
         yield ''
         return
-    prefix_length = len('{:d}'.format(runs_per_test - 1))
-    prefix_fmt = '{{:{:d}d}}'.format(prefix_length)
+    index_length = len('{:d}'.format(runs_per_test - 1))
+    index_fmt = '{{:0{:d}d}}'.format(index_length)
     for i in range(runs_per_test):
-        yield prefix_fmt.format(i)
+        yield index_fmt.format(i)
 
 
 def gen_loadtest_configs(
index 0315da3..21338c4 100644 (file)
@@ -267,7 +267,7 @@ class CXXLanguage(Language):
             channels=1,
             num_clients=1,
             secure=False,
-            categories=[INPROC] + [SCALABLE])
+            categories=[SWEEP])
 
         yield _ping_pong_scenario(
             'cpp_protobuf_async_streaming_from_client_1channel_1MB',
@@ -281,8 +281,10 @@ class CXXLanguage(Language):
             channels=1,
             num_clients=1,
             secure=False,
-            categories=[SMOKETEST] + [INPROC] + [SCALABLE])
+            categories=[SWEEP])
 
+        # Scenario was added in https://github.com/grpc/grpc/pull/12987, but its purpose is unclear
+        # (beyond excercising some params that other scenarios don't)
         yield _ping_pong_scenario(
             'cpp_protobuf_async_unary_75Kqps_600channel_60Krpcs_300Breq_50Bresp',
             rpc_type='UNARY',
@@ -323,11 +325,13 @@ class CXXLanguage(Language):
                 unconstrained_client='async',
                 use_generic_payload=True,
                 secure=secure,
+                client_threads_per_cq=2,
+                server_threads_per_cq=2,
                 minimal_stack=not secure,
                 categories=smoketest_categories + inproc_categories +
                 [SCALABLE])
 
-            for mps in geometric_progression(1, 20, 10):
+            for mps in geometric_progression(10, 20, 10):
                 yield _ping_pong_scenario(
                     'cpp_generic_async_streaming_qps_unconstrained_%smps_%s' %
                     (mps, secstr),
@@ -395,21 +399,7 @@ class CXXLanguage(Language):
                 secure=secure,
                 client_threads_per_cq=1000000,
                 server_threads_per_cq=1000000,
-                categories=smoketest_categories + inproc_categories +
-                [SCALABLE])
-
-            yield _ping_pong_scenario(
-                'cpp_generic_async_streaming_qps_unconstrained_2waysharedcq_%s'
-                % secstr,
-                rpc_type='STREAMING',
-                client_type='ASYNC_CLIENT',
-                server_type='ASYNC_GENERIC_SERVER',
-                unconstrained_client='async',
-                use_generic_payload=True,
-                secure=secure,
-                client_threads_per_cq=2,
-                server_threads_per_cq=2,
-                categories=inproc_categories + [SCALABLE])
+                categories=[SWEEP])
 
             yield _ping_pong_scenario(
                 'cpp_protobuf_async_streaming_qps_unconstrained_1cq_%s' %
@@ -424,18 +414,6 @@ class CXXLanguage(Language):
                 categories=inproc_categories + [SCALABLE])
 
             yield _ping_pong_scenario(
-                'cpp_protobuf_async_streaming_qps_unconstrained_2waysharedcq_%s'
-                % secstr,
-                rpc_type='STREAMING',
-                client_type='ASYNC_CLIENT',
-                server_type='ASYNC_SERVER',
-                unconstrained_client='async',
-                secure=secure,
-                client_threads_per_cq=2,
-                server_threads_per_cq=2,
-                categories=inproc_categories + [SCALABLE])
-
-            yield _ping_pong_scenario(
                 'cpp_protobuf_async_unary_qps_unconstrained_1cq_%s' % secstr,
                 rpc_type='UNARY',
                 client_type='ASYNC_CLIENT',
@@ -444,19 +422,6 @@ class CXXLanguage(Language):
                 secure=secure,
                 client_threads_per_cq=1000000,
                 server_threads_per_cq=1000000,
-                categories=smoketest_categories + inproc_categories +
-                [SCALABLE])
-
-            yield _ping_pong_scenario(
-                'cpp_protobuf_async_unary_qps_unconstrained_2waysharedcq_%s' %
-                secstr,
-                rpc_type='UNARY',
-                client_type='ASYNC_CLIENT',
-                server_type='ASYNC_SERVER',
-                unconstrained_client='async',
-                secure=secure,
-                client_threads_per_cq=2,
-                server_threads_per_cq=2,
                 categories=inproc_categories + [SCALABLE])
 
             yield _ping_pong_scenario(
@@ -468,7 +433,8 @@ class CXXLanguage(Language):
                 use_generic_payload=True,
                 async_server_threads=1,
                 minimal_stack=not secure,
-                secure=secure)
+                secure=secure,
+                categories=[SWEEP])
 
             yield _ping_pong_scenario(
                 'cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_%s'
@@ -505,8 +471,7 @@ class CXXLanguage(Language):
                 unconstrained_client='async',
                 secure=secure,
                 minimal_stack=not secure,
-                categories=smoketest_categories + inproc_categories +
-                [SCALABLE])
+                categories=[SWEEP])
 
             yield _ping_pong_scenario(
                 'cpp_protobuf_async_unary_ping_pong_%s_1MB' % secstr,
@@ -550,6 +515,13 @@ class CXXLanguage(Language):
                             minimal_stack=not secure,
                             categories=[SWEEP])
 
+                    maybe_scalable = [SCALABLE]
+                    if rpc_type == 'streaming_from_server' and synchronicity == 'async' and secure:
+                        # protobuf_async_streaming_from_server_qps_unconstrained_secure is very flaky
+                        # and has extremely high variance so running it isn't really useful.
+                        # see b/198275705
+                        maybe_scalable = [SWEEP]
+
                     yield _ping_pong_scenario(
                         'cpp_protobuf_%s_%s_qps_unconstrained_%s' %
                         (synchronicity, rpc_type, secstr),
@@ -559,9 +531,9 @@ class CXXLanguage(Language):
                         unconstrained_client=synchronicity,
                         secure=secure,
                         minimal_stack=not secure,
-                        server_threads_per_cq=3,
-                        client_threads_per_cq=3,
-                        categories=inproc_categories + [SCALABLE])
+                        server_threads_per_cq=2,
+                        client_threads_per_cq=2,
+                        categories=inproc_categories + maybe_scalable)
 
                     # TODO(vjpai): Re-enable this test. It has a lot of timeouts
                     # and hasn't yet been conclusively identified as a test failure
@@ -577,7 +549,7 @@ class CXXLanguage(Language):
                     #     resource_quota_size=500*1024)
 
                     if rpc_type == 'streaming':
-                        for mps in geometric_progression(1, 20, 10):
+                        for mps in geometric_progression(10, 20, 10):
                             yield _ping_pong_scenario(
                                 'cpp_protobuf_%s_%s_qps_unconstrained_%smps_%s'
                                 % (synchronicity, rpc_type, mps, secstr),
index 7fd3418..7075753 100644 (file)
@@ -35,6 +35,8 @@ spec:
   - build:
       args:
       - build
+      - --config
+      - opt
       - //test/cpp/qps:qps_worker
       command:
       - bazel
@@ -148,6 +150,8 @@ spec:
   - build:
       args:
       - build
+      - --compilation_mode
+      - opt
       - //src/python/grpcio_tests/tests/qps:qps_worker
       command:
       - bazel
@@ -168,6 +172,8 @@ spec:
   - build:
       args:
       - build
+      - --compilation_mode
+      - opt
       - //src/python/grpcio_tests/tests_aio/benchmark:worker
       command:
       - bazel
@@ -229,6 +235,8 @@ spec:
   - build:
       args:
       - build
+      - --config
+      - opt
       - //test/cpp/qps:qps_worker
       command:
       - bazel
@@ -309,6 +317,8 @@ spec:
   - build:
       args:
       - build
+      - --compilation_mode
+      - opt
       - //src/python/grpcio_tests/tests/qps:qps_worker
       command:
       - bazel
@@ -329,6 +339,8 @@ spec:
   - build:
       args:
       - build
+      - --compilation_mode
+      - opt
       - //src/python/grpcio_tests/tests_aio/benchmark:worker
       command:
       - bazel
index 1d0b71c..842febe 100644 (file)
@@ -56,7 +56,7 @@ spec:
       args:
       - -c
       - |
-        timeout --kill-after="${KILL_AFTER}" "${POD_TIMEOUT}" \
+        ${java_worker_command_prefix} timeout --kill-after="${KILL_AFTER}" "${POD_TIMEOUT}" \
             /execute/bin/benchmark_worker \
             --driver_port="${DRIVER_PORT}"
       command:
@@ -182,7 +182,7 @@ spec:
       args:
       - -c
       - |
-        timeout --kill-after="${KILL_AFTER}" "${POD_TIMEOUT}" \
+        ${java_worker_command_prefix} timeout --kill-after="${KILL_AFTER}" "${POD_TIMEOUT}" \
             /execute/bin/benchmark_worker \
             --driver_port="${DRIVER_PORT}"
       command:
index 12db1c4..7bd91fe 100644 (file)
@@ -33,6 +33,14 @@ _ACCESS_TOKEN_CACHE = None
 _ACCESS_TOKEN_FETCH_RETRIES = 6
 _ACCESS_TOKEN_FETCH_RETRIES_INTERVAL_S = 15
 
+_CHANGE_LABELS = {
+    -1: 'improvement',
+    0: 'none',
+    1: 'low',
+    2: 'medium',
+    3: 'high',
+}
+
 
 def _jwt_token():
     github_app_key = open(
@@ -139,3 +147,42 @@ def check_on_pr(name, summary, success=True):
                  })
     print('Result of Creating/Updating Check on PR:',
           json.dumps(resp.json(), indent=2))
+
+
+def label_significance_on_pr(name, change):
+    """Add a label to the PR indicating the significance of the check.
+
+    Requires environment variable 'KOKORO_GITHUB_PULL_REQUEST_NUMBER' to indicate which pull request
+    should be updated.
+
+    Args:
+      name: The name of the label.
+      value: A str in Markdown to be used as the detail information of the label.
+    """
+    if change < min(list(_CHANGE_LABELS.keys())):
+        change = min(list(_CHANGE_LABELS.keys()))
+    if change > max(list(_CHANGE_LABELS.keys())):
+        change = max(list(_CHANGE_LABELS.keys()))
+    value = _CHANGE_LABELS[change]
+    if 'KOKORO_GIT_COMMIT' not in os.environ:
+        print('Missing KOKORO_GIT_COMMIT env var: not checking')
+        return
+    if 'KOKORO_KEYSTORE_DIR' not in os.environ:
+        print('Missing KOKORO_KEYSTORE_DIR env var: not checking')
+        return
+    if 'KOKORO_GITHUB_PULL_REQUEST_NUMBER' not in os.environ:
+        print('Missing KOKORO_GITHUB_PULL_REQUEST_NUMBER env var: not checking')
+        return
+    existing = _call(
+        '/repos/%s/issues/%s/labels' %
+        (_GITHUB_REPO, os.environ['KOKORO_GITHUB_PULL_REQUEST_NUMBER']),
+        method='GET').json()
+    print('Result of Deleting Labels on PR:', existing)
+    new = [x['name'] for x in existing if not x['name'].startswith(name + '/')]
+    new.append(name + '/' + value)
+    resp = _call(
+        '/repos/%s/issues/%s/labels' %
+        (_GITHUB_REPO, os.environ['KOKORO_GITHUB_PULL_REQUEST_NUMBER']),
+        method='POST',
+        json=new)
+    print('Result of Adding Label on PR:', resp.text)
index a8bbf65..48503d3 100755 (executable)
@@ -357,7 +357,7 @@ class Job(object):
                 if measure_cpu_costs:
                     m = re.search(
                         r'real\s+([0-9.]+)\nuser\s+([0-9.]+)\nsys\s+([0-9.]+)',
-                        stdout())
+                        (stdout()).decode("utf8", errors="replace"))
                     real = float(m.group(1))
                     user = float(m.group(2))
                     sys = float(m.group(3))
index e3a63a3..615c94b 100644 (file)
@@ -88,7 +88,7 @@ def _get_build_metadata(test_results):
 def _insert_rows_with_retries(bq, bq_table, bq_rows):
     """Insert rows to bq table. Retry on error."""
     # BigQuery sometimes fails with large uploads, so batch 1,000 rows at a time.
-    for i in range((len(bq_rows) / 1000) + 1):
+    for i in range((len(bq_rows) // 1000) + 1):
         max_retries = 3
         for attempt in range(max_retries):
             if big_query_utils.insert_rows(bq, _PROJECT_ID, _DATASET_ID,
index 04473ab..9fa3b4b 100755 (executable)
@@ -464,24 +464,20 @@ class CLanguage(object):
             return ('jessie', [])
         elif compiler == 'gcc5.3':
             return ('ubuntu1604', [])
-        elif compiler == 'gcc7.4':
-            return ('ubuntu1804', [])
         elif compiler == 'gcc8.3':
             return ('buster', [])
         elif compiler == 'gcc8.3_openssl102':
             return ('buster_openssl102', [
                 "-DgRPC_SSL_PROVIDER=package",
             ])
+        elif compiler == 'gcc11':
+            return ('gcc_11', [])
         elif compiler == 'gcc_musl':
             return ('alpine', [])
-        elif compiler == 'clang4.0':
-            return ('ubuntu1604',
-                    self._clang_cmake_configure_extra_args(
-                        version_suffix='-4.0'))
-        elif compiler == 'clang5.0':
-            return ('ubuntu1604',
-                    self._clang_cmake_configure_extra_args(
-                        version_suffix='-5.0'))
+        elif compiler == 'clang4':
+            return ('clang_4', self._clang_cmake_configure_extra_args())
+        elif compiler == 'clang12':
+            return ('clang_12', self._clang_cmake_configure_extra_args())
         else:
             raise Exception('Compiler %s not supported.' % compiler)
 
@@ -594,7 +590,7 @@ class Php7Language(object):
         return 'Makefile'
 
     def dockerfile_dir(self):
-        return 'tools/dockerfile/test/php7_jessie_%s' % _docker_arch_suffix(
+        return 'tools/dockerfile/test/php7_debian9_%s' % _docker_arch_suffix(
             self.args.arch)
 
     def __str__(self):
@@ -679,9 +675,7 @@ class PythonLanguage(object):
 
     def _python_manager_name(self):
         """Choose the docker image to use based on python version."""
-        if self.args.compiler in [
-                'python2.7', 'python3.5', 'python3.6', 'python3.7', 'python3.8'
-        ]:
+        if self.args.compiler in ['python3.6', 'python3.7', 'python3.8']:
             return 'stretch_' + self.args.compiler[len('python'):]
         elif self.args.compiler == 'python_alpine':
             return 'alpine'
@@ -733,16 +727,6 @@ class PythonLanguage(object):
                                         builder_prefix_arguments,
                                         venv_relative_python, toolchain, runner,
                                         test_command, args.iomgr_platform)
-        python27_config = _python_config_generator(name='py27',
-                                                   major='2',
-                                                   minor='7',
-                                                   bits=bits,
-                                                   config_vars=config_vars)
-        python35_config = _python_config_generator(name='py35',
-                                                   major='3',
-                                                   minor='5',
-                                                   bits=bits,
-                                                   config_vars=config_vars)
         python36_config = _python_config_generator(name='py36',
                                                    major='3',
                                                    minor='6',
@@ -772,7 +756,7 @@ class PythonLanguage(object):
 
         if args.iomgr_platform in ('asyncio', 'gevent'):
             if args.compiler not in ('default', 'python3.6', 'python3.7',
-                                     'python3.8'):
+                                     'python3.8', 'python3.9'):
                 raise Exception(
                     'Compiler %s not supported with IO Manager platform: %s' %
                     (args.compiler, args.iomgr_platform))
@@ -795,14 +779,9 @@ class PythonLanguage(object):
                     return (python38_config,)
                 else:
                     return (
-                        python35_config,
                         python37_config,
                         python38_config,
                     )
-        elif args.compiler == 'python2.7':
-            return (python27_config,)
-        elif args.compiler == 'python3.5':
-            return (python35_config,)
         elif args.compiler == 'python3.6':
             return (python36_config,)
         elif args.compiler == 'python3.7':
@@ -816,11 +795,9 @@ class PythonLanguage(object):
         elif args.compiler == 'pypy3':
             return (pypy32_config,)
         elif args.compiler == 'python_alpine':
-            return (python27_config,)
+            return (python38_config,)
         elif args.compiler == 'all_the_cpythons':
             return (
-                python27_config,
-                python35_config,
                 python36_config,
                 python37_config,
                 python38_config,
@@ -1417,12 +1394,12 @@ argp.add_argument(
         'default',
         'gcc4.9',
         'gcc5.3',
-        'gcc7.4',
         'gcc8.3',
         'gcc8.3_openssl102',
+        'gcc11',
         'gcc_musl',
-        'clang4.0',
-        'clang5.0',
+        'clang4',
+        'clang12',
         'python2.7',
         'python3.5',
         'python3.6',
index 7e3d96c..72051e5 100755 (executable)
@@ -266,8 +266,8 @@ def _create_portability_test_jobs(extra_args=[],
 
     # portability C and C++ on x64
     for compiler in [
-            'gcc4.9', 'gcc5.3', 'gcc7.4', 'gcc8.3', 'gcc8.3_openssl102',
-            'gcc_musl', 'clang4.0', 'clang5.0'
+            'gcc4.9', 'gcc5.3', 'gcc8.3', 'gcc8.3_openssl102', 'gcc11',
+            'gcc_musl', 'clang4', 'clang12'
     ]:
         test_jobs += _generate_jobs(languages=['c', 'c++'],
                                     configs=['dbg'],
@@ -320,6 +320,7 @@ def _create_portability_test_jobs(extra_args=[],
                                 labels=['portability', 'corelang'],
                                 extra_args=extra_args,
                                 extra_envs={'GRPC_DNS_RESOLVER': 'ares'},
+                                inner_jobs=inner_jobs,
                                 timeout_seconds=_CPP_RUNTESTS_TIMEOUT)
 
     # C and C++ with no-exceptions on Linux
@@ -328,6 +329,7 @@ def _create_portability_test_jobs(extra_args=[],
                                 platforms=['linux'],
                                 labels=['portability', 'corelang'],
                                 extra_args=extra_args,
+                                inner_jobs=inner_jobs,
                                 timeout_seconds=_CPP_RUNTESTS_TIMEOUT)
 
     test_jobs += _generate_jobs(languages=['python'],
index c46f9dd..0c145bf 100755 (executable)
@@ -20,6 +20,7 @@ import json
 import logging
 import os
 import random
+import re
 import shlex
 import socket
 import subprocess
@@ -2264,7 +2265,7 @@ def test_csds(gcp, original_backend_service, instance_group, server_uri):
                                 args.zone)
                     ok = False
                 seen = set()
-                for xds_config in client_config['xds_config']:
+                for xds_config in client_config.get('xds_config', []):
                     if 'listener_config' in xds_config:
                         listener_name = xds_config['listener_config'][
                             'dynamic_listeners'][0]['active_state']['listener'][
@@ -2304,6 +2305,41 @@ def test_csds(gcp, original_backend_service, instance_group, server_uri):
                             ok = False
                         else:
                             seen.add('eds')
+                for generic_xds_config in client_config.get(
+                        'generic_xds_configs', []):
+                    if re.search(r'\.Listener$',
+                                 generic_xds_config['type_url']):
+                        seen.add('lds')
+                        listener = generic_xds_config["xds_config"]
+                        if listener['name'] != server_uri:
+                            logger.info('Invalid Listener name %s != %s',
+                                        listener_name, server_uri)
+                            ok = False
+                    elif re.search(r'\.RouteConfiguration$',
+                                   generic_xds_config['type_url']):
+                        seen.add('rds')
+                        route_config = generic_xds_config["xds_config"]
+                        if not len(route_config['virtual_hosts']):
+                            logger.info('Invalid number of VirtualHosts %s',
+                                        num_vh)
+                            ok = False
+                    elif re.search(r'\.Cluster$',
+                                   generic_xds_config['type_url']):
+                        seen.add('cds')
+                        cluster = generic_xds_config["xds_config"]
+                        if cluster['type'] != 'EDS':
+                            logger.info('Invalid cluster type %s != EDS',
+                                        cluster_type)
+                            ok = False
+                    elif re.search(r'\.ClusterLoadAssignment$',
+                                   generic_xds_config['type_url']):
+                        seen.add('eds')
+                        endpoint = generic_xds_config["xds_config"]
+                        if args.zone not in endpoint["endpoints"][0][
+                                "locality"]["sub_zone"]:
+                            logger.info('Invalid endpoint sub_zone %s',
+                                        sub_zone)
+                            ok = False
                 want = {'lds', 'rds', 'cds', 'eds'}
                 if seen != want:
                     logger.info('Incomplete xDS config dump, seen=%s', seen)
@@ -2685,11 +2721,10 @@ def get_url_map(gcp, url_map_name, record_error=True):
         result = gcp.compute.urlMaps().get(project=gcp.project,
                                            urlMap=url_map_name).execute()
         url_map = GcpResource(url_map_name, result['selfLink'])
+        gcp.url_maps.append(url_map)
     except Exception as e:
         if record_error:
             gcp.errors.append(e)
-        url_map = GcpResource(url_map_name, None)
-    gcp.url_maps.append(url_map)
 
 
 def get_target_proxy(gcp, target_proxy_name, record_error=True):
@@ -2703,11 +2738,10 @@ def get_target_proxy(gcp, target_proxy_name, record_error=True):
                 project=gcp.project,
                 targetHttpProxy=target_proxy_name).execute()
         target_proxy = GcpResource(target_proxy_name, result['selfLink'])
+        gcp.target_proxies.append(target_proxy)
     except Exception as e:
         if record_error:
             gcp.errors.append(e)
-        target_proxy = GcpResource(target_proxy_name, None)
-    gcp.target_proxies.append(target_proxy)
 
 
 def get_global_forwarding_rule(gcp, forwarding_rule_name, record_error=True):
@@ -2716,11 +2750,10 @@ def get_global_forwarding_rule(gcp, forwarding_rule_name, record_error=True):
             project=gcp.project, forwardingRule=forwarding_rule_name).execute()
         global_forwarding_rule = GcpResource(forwarding_rule_name,
                                              result['selfLink'])
+        gcp.global_forwarding_rules.append(global_forwarding_rule)
     except Exception as e:
         if record_error:
             gcp.errors.append(e)
-        global_forwarding_rule = GcpResource(forwarding_rule_name, None)
-    gcp.global_forwarding_rules.append(global_forwarding_rule)
 
 
 def get_instance_template(gcp, template_name):
@@ -2770,7 +2803,8 @@ def delete_global_forwarding_rule(gcp, forwarding_rule_to_delete=None):
 
 
 def delete_global_forwarding_rules(gcp):
-    for forwarding_rule in gcp.global_forwarding_rules:
+    forwarding_rules_to_delete = gcp.global_forwarding_rules.copy()
+    for forwarding_rule in forwarding_rules_to_delete:
         delete_global_forwarding_rule(gcp, forwarding_rule)
 
 
@@ -2801,7 +2835,8 @@ def delete_target_proxy(gcp, proxy_to_delete=None):
 
 
 def delete_target_proxies(gcp):
-    for target_proxy in gcp.target_proxies:
+    target_proxies_to_delete = gcp.target_proxies.copy()
+    for target_proxy in target_proxies_to_delete:
         delete_target_proxy(gcp, target_proxy)
 
 
@@ -2824,7 +2859,8 @@ def delete_url_map(gcp, url_map_to_delete=None):
 
 
 def delete_url_maps(gcp):
-    for url_map in gcp.url_maps:
+    url_maps_to_delete = gcp.url_maps.copy()
+    for url_map in url_maps_to_delete:
         delete_url_map(gcp, url_map)
 
 
diff --git a/tools/run_tests/sanity/build_banned_constructs.sh b/tools/run_tests/sanity/build_banned_constructs.sh
new file mode 100755 (executable)
index 0000000..9286fbc
--- /dev/null
@@ -0,0 +1,31 @@
+#!/bin/sh
+# Copyright 2019 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 -e
+
+cd "$(dirname "$0")/../../.."
+
+#
+# Prevent the use of single line comments after license clauses, since this
+# chokes the internal import process.
+#
+
+regex='^licenses\(.*#'
+for dir in bazel examples src test tools; do
+  for file in BUILD BUILD.bazel; do
+    git grep -EIrn "$regex" "$dir/**$file" | diff - /dev/null
+  done
+done
+
index c87892a..57e3da5 100755 (executable)
@@ -50,7 +50,8 @@ _GRPC_DEP_NAMES = [
     _TWISTED_CONSTANTLY_DEP_NAME, 'io_bazel_rules_go',
     'build_bazel_rules_apple', 'build_bazel_apple_support', 'libuv',
     'com_googlesource_code_re2', 'bazel_gazelle', 'opencensus_proto',
-    'com_envoyproxy_protoc_gen_validate', 'com_google_googleapis'
+    'com_envoyproxy_protoc_gen_validate', 'com_google_googleapis',
+    'com_google_libprotobuf_mutator'
 ]
 
 _GRPC_BAZEL_ONLY_DEPS = [
@@ -74,6 +75,7 @@ _GRPC_BAZEL_ONLY_DEPS = [
     'opencensus_proto',
     'com_envoyproxy_protoc_gen_validate',
     'com_google_googleapis',
+    'com_google_libprotobuf_mutator'
 ]
 
 
diff --git a/tools/run_tests/sanity/check_package_name.py b/tools/run_tests/sanity/check_package_name.py
new file mode 100755 (executable)
index 0000000..e0396ac
--- /dev/null
@@ -0,0 +1,74 @@
+#!/usr/bin/env python3
+
+# 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.
+
+import os
+import sys
+
+os.chdir(os.path.join(os.path.dirname(sys.argv[0]), '../../..'))
+
+# Allowance for overrides for specific files
+EXPECTED_NAMES = {
+    'src/proto/grpc/channelz': 'channelz',
+    'src/proto/grpc/status': 'status',
+    'src/proto/grpc/testing': 'testing',
+    'src/proto/grpc/testing/duplicate': 'duplicate',
+    'src/proto/grpc/lb/v1': 'lb',
+    'src/proto/grpc/testing/xds': 'xds',
+    'src/proto/grpc/testing/xds/v3': 'xds_v3',
+    'src/proto/grpc/core': 'core',
+    'src/proto/grpc/http_over_grpc': 'http_over_grpc',
+    'src/proto/grpc/health/v1': 'health',
+    'src/proto/grpc/reflection/v1alpha': 'reflection',
+}
+
+errors = 0
+for root, dirs, files in os.walk('.'):
+    if root.startswith('./'):
+        root = root[len('./'):]
+    # don't check third party
+    if root.startswith('third_party/'):
+        continue
+    # only check BUILD files
+    if 'BUILD' not in files:
+        continue
+    text = open('%s/BUILD' % root).read()
+    # find a grpc_package clause
+    pkg_start = text.find('grpc_package(')
+    if pkg_start == -1:
+        continue
+    # parse it, taking into account nested parens
+    pkg_end = pkg_start + len('grpc_package(')
+    level = 1
+    while level == 1:
+        if text[pkg_end] == ')':
+            level -= 1
+        elif text[pkg_end] == '(':
+            level += 1
+        pkg_end += 1
+    # it's a python statement, so evaluate it to pull out the name of the package
+    name = eval(text[pkg_start:pkg_end],
+                {'grpc_package': lambda name, **kwargs: name})
+    # the name should be the path within the source tree, excepting some special
+    # BUILD files (really we should normalize them too at some point)
+    # TODO(ctiller): normalize all package names
+    expected_name = EXPECTED_NAMES.get(root, root)
+    if name != expected_name:
+        print("%s/BUILD should define a grpc_package with name=%r, not %r" %
+              (root, expected_name, name))
+        errors += 1
+
+if errors != 0:
+    sys.exit(1)
index ba95911..fb6b68c 100755 (executable)
@@ -20,7 +20,7 @@ import sys
 os.chdir(os.path.join(os.path.dirname(sys.argv[0]), '../../..'))
 
 
-def check_port_platform_inclusion(directory_root):
+def check_port_platform_inclusion(directory_root, legal_list):
     bad_files = []
     for root, dirs, files in os.walk(directory_root):
         for filename in files:
@@ -45,10 +45,7 @@ def check_port_platform_inclusion(directory_root):
                 all_lines_in_file = f.readlines()
                 for index, l in enumerate(all_lines_in_file):
                     if '#include' in l:
-                        if l not in [
-                                '#include <grpc/support/port_platform.h>\n',
-                                '#include <grpc/impl/codegen/port_platform.h>\n'
-                        ]:
+                        if l not in legal_list:
                             bad_files.append(path)
                         elif all_lines_in_file[index + 1] != '\n':
                             # Require a blank line after including port_platform.h in
@@ -60,8 +57,14 @@ def check_port_platform_inclusion(directory_root):
 
 
 all_bad_files = []
-all_bad_files += check_port_platform_inclusion(os.path.join('src', 'core'))
-all_bad_files += check_port_platform_inclusion(os.path.join('include', 'grpc'))
+all_bad_files += check_port_platform_inclusion(os.path.join('src', 'core'), [
+    '#include <grpc/support/port_platform.h>\n',
+])
+all_bad_files += check_port_platform_inclusion(os.path.join(
+    'include', 'grpc'), [
+        '#include <grpc/support/port_platform.h>\n',
+        '#include <grpc/impl/codegen/port_platform.h>\n',
+    ])
 
 if sys.argv[1:] == ['--fix']:
     for path in all_bad_files:
@@ -70,7 +73,7 @@ if sys.argv[1:] == ['--fix']:
         with open(path) as f:
             for l in f.readlines():
                 if not found and '#include' in l:
-                    text += '#include <grpc/impl/codegen/port_platform.h>\n\n'
+                    text += '#include <grpc/support/port_platform.h>\n\n'
                     found = True
                 text += l
         with open(path, 'w') as f:
index 7fc055d..fd5a12d 100755 (executable)
@@ -19,9 +19,9 @@ import subprocess
 import sys
 
 os.chdir(os.path.join(os.path.dirname(sys.argv[0]), '../../../test/cpp/qps'))
-subprocess.call(['./json_run_localhost_scenario_gen.py'])
-subprocess.call(['./qps_json_driver_scenario_gen.py'])
-subprocess.call(['buildifier', '-v', '-r', '.'])
+subprocess.check_call(['./json_run_localhost_scenario_gen.py'])
+subprocess.check_call(['./qps_json_driver_scenario_gen.py'])
+subprocess.check_call(['buildifier', '-v', '-r', '.'])
 
 output = subprocess.check_output(['git', 'status', '--porcelain'])
 qps_json_driver_bzl = 'test/cpp/qps/qps_json_driver_scenarios.bzl'
index d0a018f..c779fda 100755 (executable)
@@ -14,7 +14,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-
 set -e
 
 export TEST=true
@@ -24,23 +23,23 @@ cd "$(dirname "$0")/../../.."
 submodules=$(mktemp /tmp/submXXXXXX)
 want_submodules=$(mktemp /tmp/submXXXXXX)
 
-git submodule | awk '{ print $2 " " $1 }' | sort > "$submodules"
-cat << EOF | sort > "$want_submodules"
-third_party/abseil-cpp 997aaf3a28308eba1b9156aa35ab7bca9688e9f6
-third_party/benchmark 73d4d5e8d6d449fc8663765a42aa8aeeee844489
-third_party/bloaty 73594cde8c9a52a102c4341c244c833aa61b9c06
-third_party/boringssl-with-bazel 340faef0ad19283e985ce7fff0dec73ba4022c8d
+git submodule | awk '{ print $2 " " $1 }' | sort >"$submodules"
+cat <<EOF | sort >"$want_submodules"
+third_party/abseil-cpp 278e0a071885a22dcd2fd1b5576cc44757299343
+third_party/benchmark 0baacde3618ca617da95375e0af13ce1baadea47
+third_party/bloaty 60209eb1ccc34d5deefb002d1b7f37545204f7f2
+third_party/boringssl-with-bazel 95b3ed1b01f2ef1d72fed290ed79fe1b0e7dafc0
 third_party/cares/cares e982924acee7f7313b4baa4ee5ec000c5e373c30
-third_party/envoy-api 2f0d081fab0b0823f088c6e368f40e1992f46fcd
+third_party/envoy-api 20b1b5fcee88a20a08b71051a961181839ec7268
 third_party/googleapis 2f9af297c84c55c8b871ba4495e01ade42476c92
 third_party/googletest c9ccac7cb7345901884aabf5d1a786cfa6e2f397
-third_party/libuv 15ae750151ac9341e5945eb38f8982d59fb99201
+third_party/libuv 02a9e1be252b623ee032a3137c0b0c94afbe6809
 third_party/opencensus-proto 4aa53e15cbf1a47bc9087e6cfdca214c1eea4e89
 third_party/opentelemetry 60fa8754d890b5c55949a8c68dcfd7ab5c2395df
-third_party/protobuf 909a0f36a10075c4b4bc70fdee2c7e32dd612a72
+third_party/protobuf 0dab03ba7bc438d7ba3eac2b2c1eb39ed520f928
 third_party/protoc-gen-validate 59da36e59fef2267fc2b1849a05159e3ecdf24f3
-third_party/re2 aecba11114cf1fac5497aeb844b6966106de3eb6
-third_party/udpa 6414d713912e988471d192940b62bf552b11793a
+third_party/re2 8e08f47b11b413302749c0d8b17a1c94777495d5
+third_party/xds cb28da3451f158a947dfc45090fe92b07b243bc1
 third_party/zlib cacf7f1d4e3d44d871b605da3b647f07d718623f
 EOF
 
index aa18806..c88db69 100755 (executable)
@@ -33,8 +33,8 @@ BANNED_EXCEPT = {
     'grpc_slice_buffer_reset_and_unref(': [
         'src/core/lib/slice/slice_buffer.cc'
     ],
-    'grpc_slice_ref(': ['src/core/lib/slice/slice.cc'],
-    'grpc_slice_unref(': ['src/core/lib/slice/slice.cc'],
+    'grpc_slice_ref(': ['src/core/lib/slice/slice_api.cc'],
+    'grpc_slice_unref(': ['src/core/lib/slice/slice_api.cc'],
     'grpc_error_create(': [
         'src/core/lib/iomgr/error.cc', 'src/core/lib/iomgr/error_cfstream.cc'
     ],
@@ -50,6 +50,8 @@ BANNED_EXCEPT = {
     'grpc_closure_sched(': ['src/core/lib/iomgr/closure.cc'],
     'grpc_closure_run(': ['src/core/lib/iomgr/closure.cc'],
     'grpc_closure_list_sched(': ['src/core/lib/iomgr/closure.cc'],
+    'grpc_error*': ['src/core/lib/iomgr/error.cc'],
+    'grpc_error_string': ['src/core/lib/iomgr/error.cc'],
 }
 
 errors = 0
index 9d8d50c..712b94c 100644 (file)
@@ -18,6 +18,7 @@
 - script: tools/run_tests/sanity/core_banned_functions.py
 - script: tools/run_tests/sanity/core_untyped_structs.sh
 - script: tools/run_tests/sanity/cpp_banned_constructs.sh
+- script: tools/run_tests/sanity/check_package_name.py
 - script: tools/buildgen/generate_projects.sh -j 3
   cpu_cost: 3
 - script: tools/distrib/check_copyright.py
@@ -38,3 +39,5 @@
   cpu_cost: 1000
 - script: tools/distrib/check_protobuf_pod_version.sh
 - script: tools/distrib/check_boringssl_prefix_symbol.sh
+- script: tools/run_tests/sanity/build_banned_constructs.sh
+
index 5d34464..2cd0238 100644 (file)
@@ -26,7 +26,9 @@ changes to this codebase at the moment.
 #### Requirements
 1. Python v3.6+
 2. [Google Cloud SDK](https://cloud.google.com/sdk/docs/install)
-3. Configured GKE cluster
+3. `kubectl`
+
+`kubectl` can be installed via `gcloud components install kubectl`, or system package manager: https://kubernetes.io/docs/tasks/tools/#kubectl
 
 #### Configure GKE cluster
 This is an example outlining minimal requirements to run `tests.baseline_test`.  
@@ -67,7 +69,7 @@ gcloud container clusters create "${CLUSTER_NAME}" \
  --zone="${ZONE}" \
  --enable-ip-alias \
  --workload-pool="${PROJECT_ID}.svc.id.goog" \
- --enable-workload-certificates \
+ --enable-mesh-certificates \
  --workload-metadata=GKE_METADATA \
  --tags=allow-health-checks
 ```
@@ -147,6 +149,9 @@ END
 
 ##### Configure GKE cluster access
 ```shell
+# Unless you're using GCP VM with preconfigured Application Default Credentials, acquire them for your user
+gcloud auth application-default login
+
 # Configuring GKE cluster access for kubectl
 gcloud container clusters get-credentials "your_gke_cluster_name" --zone "your_gke_cluster_zone"
 
@@ -332,7 +337,7 @@ XDS_K8S_CONFIG=./path-to-flagfile.cfg ./run.sh bin/run_td_setup.py --resource_su
 # Client: all services always on port 8079
 kubectl port-forward deployment.apps/psm-grpc-client 8079
 
-# Server regular mode: all grpc services on port 8079
+# Server regular mode: all grpc services on port 8080
 kubectl port-forward deployment.apps/psm-grpc-server 8080
 # OR
 # Server secure mode: TestServiceImpl is on 8080, 
index c9e18c7..07cf15a 100644 (file)
@@ -115,6 +115,8 @@ class GcpApiManager:
                 return self._build_from_file(self.compute_v1_discovery_file)
             else:
                 return self._build_from_discovery_v1(api_name, version)
+        elif version == 'v1alpha':
+            return self._build_from_discovery_v1(api_name, 'alpha')
 
         raise NotImplementedError(f'Compute {version} not supported')
 
index c17f4c7..c8a408f 100644 (file)
@@ -40,8 +40,11 @@ class ComputeV1(gcp.api.GcpProjectApiResource):
     class ZonalGcpResource(GcpResource):
         zone: str
 
-    def __init__(self, api_manager: gcp.api.GcpApiManager, project: str):
-        super().__init__(api_manager.compute('v1'), project)
+    def __init__(self,
+                 api_manager: gcp.api.GcpApiManager,
+                 project: str,
+                 version: str = 'v1'):
+        super().__init__(api_manager.compute(version), project)
 
     class HealthCheckProtocol(enum.Enum):
         TCP = enum.auto()
index e97b177..225969f 100644 (file)
@@ -68,6 +68,26 @@ class ClientTlsPolicy:
                    update_time=response['updateTime'])
 
 
+@dataclasses.dataclass(frozen=True)
+class AuthorizationPolicy:
+    url: str
+    name: str
+    update_time: str
+    create_time: str
+    action: str
+    rules: list
+
+    @classmethod
+    def from_response(cls, name: str,
+                      response: Dict[str, Any]) -> 'AuthorizationPolicy':
+        return cls(name=name,
+                   url=response['name'],
+                   create_time=response['createTime'],
+                   update_time=response['updateTime'],
+                   action=response['action'],
+                   rules=response.get('rules', []))
+
+
 class _NetworkSecurityBase(gcp.api.GcpStandardCloudApiResource,
                            metaclass=abc.ABCMeta):
     """Base class for NetworkSecurity APIs."""
@@ -103,6 +123,7 @@ class NetworkSecurityV1Beta1(_NetworkSecurityBase):
 
     SERVER_TLS_POLICIES = 'serverTlsPolicies'
     CLIENT_TLS_POLICIES = 'clientTlsPolicies'
+    AUTHZ_POLICIES = 'authorizationPolicies'
 
     @property
     def api_version(self) -> str:
@@ -142,6 +163,23 @@ class NetworkSecurityV1Beta1(_NetworkSecurityBase):
             collection=self._api_locations.clientTlsPolicies(),
             full_name=self.resource_full_name(name, self.CLIENT_TLS_POLICIES))
 
+    def create_authz_policy(self, name: str, body: dict) -> GcpResource:
+        return self._create_resource(
+            collection=self._api_locations.authorizationPolicies(),
+            body=body,
+            authorizationPolicyId=name)
+
+    def get_authz_policy(self, name: str) -> ClientTlsPolicy:
+        response = self._get_resource(
+            collection=self._api_locations.authorizationPolicies(),
+            full_name=self.resource_full_name(name, self.AUTHZ_POLICIES))
+        return ClientTlsPolicy.from_response(name, response)
+
+    def delete_authz_policy(self, name: str) -> bool:
+        return self._delete_resource(
+            collection=self._api_locations.authorizationPolicies(),
+            full_name=self.resource_full_name(name, self.AUTHZ_POLICIES))
+
 
 class NetworkSecurityV1Alpha1(NetworkSecurityV1Beta1):
     """NetworkSecurity API v1alpha1.
index 326b23d..9611bc2 100644 (file)
@@ -35,6 +35,7 @@ _HealthCheckGRPC = HealthCheckProtocol.GRPC
 _NetworkSecurityV1Beta1 = gcp.network_security.NetworkSecurityV1Beta1
 ServerTlsPolicy = gcp.network_security.ServerTlsPolicy
 ClientTlsPolicy = gcp.network_security.ClientTlsPolicy
+AuthorizationPolicy = gcp.network_security.AuthorizationPolicy
 
 # Network Services
 _NetworkServicesV1Alpha1 = gcp.network_services.NetworkServicesV1Alpha1
@@ -68,9 +69,12 @@ class TrafficDirectorManager:
         resource_prefix: str,
         resource_suffix: str,
         network: str = 'default',
+        compute_api_version: str = 'v1',
     ):
         # API
-        self.compute = _ComputeV1(gcp_api_manager, project)
+        self.compute = _ComputeV1(gcp_api_manager,
+                                  project,
+                                  version=compute_api_version)
 
         # Settings
         self.project: str = project
@@ -553,12 +557,14 @@ class TrafficDirectorAppNetManager(TrafficDirectorManager):
                  *,
                  resource_prefix: str,
                  resource_suffix: Optional[str] = None,
-                 network: str = 'default'):
+                 network: str = 'default',
+                 compute_api_version: str = 'v1'):
         super().__init__(gcp_api_manager,
                          project,
                          resource_prefix=resource_prefix,
                          resource_suffix=resource_suffix,
-                         network=network)
+                         network=network,
+                         compute_api_version=compute_api_version)
 
         # API
         self.netsvc = _NetworkServicesV1Alpha1(gcp_api_manager, project)
@@ -639,6 +645,7 @@ class TrafficDirectorAppNetManager(TrafficDirectorManager):
 class TrafficDirectorSecureManager(TrafficDirectorManager):
     SERVER_TLS_POLICY_NAME = "server-tls-policy"
     CLIENT_TLS_POLICY_NAME = "client-tls-policy"
+    AUTHZ_POLICY_NAME = "authz-policy"
     ENDPOINT_POLICY = "endpoint-policy"
     CERTIFICATE_PROVIDER_INSTANCE = "google_cloud_private_spiffe"
 
@@ -653,12 +660,14 @@ class TrafficDirectorSecureManager(TrafficDirectorManager):
         resource_prefix: str,
         resource_suffix: Optional[str] = None,
         network: str = 'default',
+        compute_api_version: str = 'v1',
     ):
         super().__init__(gcp_api_manager,
                          project,
                          resource_prefix=resource_prefix,
                          resource_suffix=resource_suffix,
-                         network=network)
+                         network=network,
+                         compute_api_version=compute_api_version)
 
         # API
         self.netsec = _NetworkSecurityV1Beta1(gcp_api_manager, project)
@@ -667,6 +676,7 @@ class TrafficDirectorSecureManager(TrafficDirectorManager):
         # Managed resources
         self.server_tls_policy: Optional[ServerTlsPolicy] = None
         self.client_tls_policy: Optional[ClientTlsPolicy] = None
+        self.authz_policy: Optional[AuthorizationPolicy] = None
         self.endpoint_policy: Optional[EndpointPolicy] = None
 
     def setup_server_security(self,
@@ -697,6 +707,7 @@ class TrafficDirectorSecureManager(TrafficDirectorManager):
         self.delete_endpoint_policy(force=force)
         self.delete_server_tls_policy(force=force)
         self.delete_client_tls_policy(force=force)
+        self.delete_authz_policy(force=force)
 
     def create_server_tls_policy(self, *, tls, mtls):
         name = self.make_resource_name(self.SERVER_TLS_POLICY_NAME)
@@ -731,6 +742,29 @@ class TrafficDirectorSecureManager(TrafficDirectorManager):
         self.netsec.delete_server_tls_policy(name)
         self.server_tls_policy = None
 
+    def create_authz_policy(self, *, action: str, rules: list):
+        name = self.make_resource_name(self.AUTHZ_POLICY_NAME)
+        logger.info('Creating Authz Policy %s', name)
+        policy = {
+            "action": action,
+            "rules": rules,
+        }
+
+        self.netsec.create_authz_policy(name, policy)
+        self.authz_policy = self.netsec.get_authz_policy(name)
+        logger.debug('Authz Policy loaded: %r', self.authz_policy)
+
+    def delete_authz_policy(self, force=False):
+        if force:
+            name = self.make_resource_name(self.AUTHZ_POLICY_NAME)
+        elif self.authz_policy:
+            name = self.authz_policy.name
+        else:
+            return
+        logger.info('Deleting Authz Policy %s', name)
+        self.netsec.delete_authz_policy(name)
+        self.authz_policy = None
+
     def create_endpoint_policy(self, *, server_namespace: str, server_name: str,
                                server_port: int) -> None:
         name = self.make_resource_name(self.ENDPOINT_POLICY)
@@ -757,6 +791,8 @@ class TrafficDirectorSecureManager(TrafficDirectorManager):
             logger.warning(
                 'Creating Endpoint Policy %s with '
                 'no Server TLS policy attached', name)
+        if self.authz_policy:
+            config["authorizationPolicy"] = self.authz_policy.name
 
         self.netsvc.create_endpoint_policy(name, config)
         self.endpoint_policy = self.netsvc.get_endpoint_policy(name)
index 59068a8..578f4e3 100644 (file)
@@ -36,6 +36,10 @@ RESOURCE_SUFFIX = flags.DEFINE_string(
 NETWORK = flags.DEFINE_string("network",
                               default="default",
                               help="GCP Network ID")
+COMPUTE_API_VERSION = flags.DEFINE_string(
+    "compute_api_version",
+    default='v1',
+    help="The version of the GCP Compute API, e.g., v1, v1alpha")
 # Mirrors --xds-server-uri argument of Traffic Director gRPC Bootstrap
 XDS_SERVER_URI = flags.DEFINE_string(
     "xds_server_uri",
@@ -109,6 +113,12 @@ CLIENT_PORT = flags.DEFINE_integer(
         "XdsStats, XdsUpdateClientConfigure, and ProtoReflection (optional).\n"
         "Doesn't have to be within --firewall_allowed_ports."))
 
+# Testing metadata
+TESTING_VERSION = flags.DEFINE_string(
+    "testing_version",
+    default="master",
+    help="The testing gRPC version branch name. Like master, v1.41.x, v1.37.x")
+
 flags.adopt_module_key_flags(highlighter)
 
 flags.mark_flags_as_required([
index 0e8bef8..8c8e83d 100644 (file)
@@ -16,12 +16,14 @@ import datetime
 import enum
 import hashlib
 import logging
+import re
 import time
 from typing import List, Optional, Tuple
 
 from absl import flags
 from absl.testing import absltest
 from google.protobuf import json_format
+import grpc
 
 from framework import xds_flags
 from framework import xds_k8s_flags
@@ -90,6 +92,7 @@ class XdsKubernetesTestCase(absltest.TestCase, metaclass=abc.ABCMeta):
         cls.xds_server_uri = xds_flags.XDS_SERVER_URI.value
         cls.ensure_firewall = xds_flags.ENSURE_FIREWALL.value
         cls.firewall_allowed_ports = xds_flags.FIREWALL_ALLOWED_PORTS.value
+        cls.compute_api_version = xds_flags.COMPUTE_API_VERSION.value
 
         # Resource names.
         cls.resource_prefix = xds_flags.RESOURCE_PREFIX.value
@@ -239,6 +242,46 @@ class XdsKubernetesTestCase(absltest.TestCase, metaclass=abc.ABCMeta):
             0,
             msg=f'Expected all RPCs to succeed: {failed} of {num_rpcs} failed')
 
+    @staticmethod
+    def diffAccumulatedStatsPerMethod(
+            before: grpc_testing.LoadBalancerAccumulatedStatsResponse,
+            after: grpc_testing.LoadBalancerAccumulatedStatsResponse):
+        """Only diffs stats_per_method, as the other fields are deprecated."""
+        diff = grpc_testing.LoadBalancerAccumulatedStatsResponse()
+        for method, method_stats in after.stats_per_method.items():
+            for status, count in method_stats.result.items():
+                count -= before.stats_per_method[method].result[status]
+                if count < 0:
+                    raise AssertionError("Diff of count shouldn't be negative")
+                if count > 0:
+                    diff.stats_per_method[method].result[status] = count
+        return diff
+
+    def assertRpcStatusCodes(self, test_client: XdsTestClient, *,
+                             status_code: grpc.StatusCode, duration: _timedelta,
+                             method: str) -> None:
+        """Assert all RPCs for a method are completing with a certain status."""
+        # Sending with pre-set QPS for a period of time
+        before_stats = test_client.get_load_balancer_accumulated_stats()
+        logging.info(
+            'Received LoadBalancerAccumulatedStatsResponse from test client %s: before:\n%s',
+            test_client.ip, before_stats)
+        time.sleep(duration.total_seconds())
+        after_stats = test_client.get_load_balancer_accumulated_stats()
+        logging.info(
+            'Received LoadBalancerAccumulatedStatsResponse from test client %s: after:\n%s',
+            test_client.ip, after_stats)
+
+        diff_stats = self.diffAccumulatedStatsPerMethod(before_stats,
+                                                        after_stats)
+        stats = diff_stats.stats_per_method[method]
+        status = status_code.value[0]
+        for found_status, count in stats.result.items():
+            if found_status != status and count > 0:
+                self.fail(f"Expected only status {status} but found status "
+                          f"{found_status} for method {method}:\n{diff_stats}")
+        self.assertGreater(stats.result[status_code.value[0]], 0)
+
     def assertRpcsEventuallyGoToGivenServers(self,
                                              test_client: XdsTestClient,
                                              servers: List[XdsTestServer],
@@ -285,6 +328,17 @@ class XdsKubernetesTestCase(absltest.TestCase, metaclass=abc.ABCMeta):
         ])
         for xds_config in config.xds_config:
             seen.add(xds_config.WhichOneof('per_xds_config'))
+        for generic_xds_config in config.generic_xds_configs:
+            if re.search(r'\.Listener$', generic_xds_config.type_url):
+                seen.add('listener_config')
+            elif re.search(r'\.RouteConfiguration$',
+                           generic_xds_config.type_url):
+                seen.add('route_config')
+            elif re.search(r'\.Cluster$', generic_xds_config.type_url):
+                seen.add('cluster_config')
+            elif re.search(r'\.ClusterLoadAssignment$',
+                           generic_xds_config.type_url):
+                seen.add('endpoint_config')
         logger.debug('Received xDS config dump: %s',
                      json_format.MessageToJson(config, indent=2))
         self.assertSameElements(want, seen)
@@ -329,11 +383,13 @@ class RegularXdsKubernetesTestCase(XdsKubernetesTestCase):
             cls.server_maintenance_port = KubernetesServerRunner.DEFAULT_MAINTENANCE_PORT
 
     def initTrafficDirectorManager(self) -> TrafficDirectorManager:
-        return TrafficDirectorManager(self.gcp_api_manager,
-                                      project=self.project,
-                                      resource_prefix=self.resource_prefix,
-                                      resource_suffix=self.resource_suffix,
-                                      network=self.network)
+        return TrafficDirectorManager(
+            self.gcp_api_manager,
+            project=self.project,
+            resource_prefix=self.resource_prefix,
+            resource_suffix=self.resource_suffix,
+            network=self.network,
+            compute_api_version=self.compute_api_version)
 
     def initKubernetesServerRunner(self) -> KubernetesServerRunner:
         return KubernetesServerRunner(
@@ -400,7 +456,8 @@ class AppNetXdsKubernetesTestCase(RegularXdsKubernetesTestCase):
             project=self.project,
             resource_prefix=self.resource_prefix,
             resource_suffix=self.resource_suffix,
-            network=self.network)
+            network=self.network,
+            compute_api_version=self.compute_api_version)
 
 
 class SecurityXdsKubernetesTestCase(XdsKubernetesTestCase):
@@ -431,7 +488,8 @@ class SecurityXdsKubernetesTestCase(XdsKubernetesTestCase):
             project=self.project,
             resource_prefix=self.resource_prefix,
             resource_suffix=self.resource_suffix,
-            network=self.network)
+            network=self.network,
+            compute_api_version=self.compute_api_version)
 
     def initKubernetesServerRunner(self) -> KubernetesServerRunner:
         return KubernetesServerRunner(
index e3240c7..44d5fad 100644 (file)
@@ -159,6 +159,7 @@ class GcpResourceManager(metaclass=_MetaSingletonAndAbslFlags):
             resource_prefix=self.resource_prefix,
             resource_suffix=(self.resource_suffix or ""),
             network=self.network,
+            compute_api_version=self.compute_api_version,
         )
         # Kubernetes namespace
         self.k8s_namespace = k8s.KubernetesNamespace(self.k8s_api_manager,
index 7e9dfb6..0b02c3e 100644 (file)
@@ -29,6 +29,7 @@ from absl import logging
 from absl.testing import absltest
 from google.protobuf import json_format
 import grpc
+import packaging
 
 from framework import xds_k8s_testcase
 from framework import xds_url_map_test_resources
@@ -62,10 +63,6 @@ JsonType = Any
 RpcTypeUnaryCall = 'UNARY_CALL'
 RpcTypeEmptyCall = 'EMPTY_CALL'
 
-# All client languages
-_CLIENT_LANGUAGES = ('cpp', 'java', 'go', 'python')
-_SERVER_LANGUAGES = _CLIENT_LANGUAGES
-
 
 def _split_camel(s: str, delimiter: str = '-') -> str:
     """Turn camel case name to snake-case-like name."""
@@ -91,7 +88,7 @@ class DumpedXdsConfig(dict):
         self.cds = []
         self.eds = []
         self.endpoints = []
-        for xds_config in self['xdsConfig']:
+        for xds_config in self.get('xdsConfig', []):
             try:
                 if 'listenerConfig' in xds_config:
                     self.lds = xds_config['listenerConfig']['dynamicListeners'][
@@ -108,7 +105,22 @@ class DumpedXdsConfig(dict):
                             'dynamicEndpointConfigs']:
                         self.eds.append(endpoint['endpointConfig'])
             except Exception as e:
-                logging.debug('Parse dumped xDS config failed with %s: %s',
+                logging.debug('Parsing dumped xDS config failed with %s: %s',
+                              type(e), e)
+        for generic_xds_config in self.get('genericXdsConfigs', []):
+            try:
+                if re.search(r'\.Listener$', generic_xds_config['typeUrl']):
+                    self.lds = generic_xds_config["xdsConfig"]
+                elif re.search(r'\.RouteConfiguration$',
+                               generic_xds_config['typeUrl']):
+                    self.rds = generic_xds_config["xdsConfig"]
+                elif re.search(r'\.Cluster$', generic_xds_config['typeUrl']):
+                    self.cds.append(generic_xds_config["xdsConfig"])
+                elif re.search(r'\.ClusterLoadAssignment$',
+                               generic_xds_config['typeUrl']):
+                    self.eds.append(generic_xds_config["xdsConfig"])
+            except Exception as e:
+                logging.debug('Parsing dumped xDS config failed with %s: %s',
                               type(e), e)
         for endpoint_config in self.eds:
             for endpoint in endpoint_config.get('endpoints', {}):
@@ -188,6 +200,27 @@ class ExpectedResult:
     ratio: float = 1
 
 
+@dataclass
+class TestConfig:
+    """Describes the config for the test suite."""
+    client_lang: str
+    server_lang: str
+    version: str
+
+    def version_ge(self, another: str) -> bool:
+        """Returns a bool for whether the version is >= another one.
+
+        A version is greater than or equal to another version means its version
+        number is greater than or equal to another version's number. Version
+        "master" is always considered latest. E.g., master >= v1.41.x >= v1.40.x
+        >= v1.9.x.
+        """
+        if self.version == 'master':
+            return True
+        return packaging.version.parse(
+            self.version) >= packaging.version.parse(another)
+
+
 class _MetaXdsUrlMapTestCase(type):
     """Tracking test case subclasses."""
 
@@ -233,22 +266,13 @@ class XdsUrlMapTestCase(absltest.TestCase, metaclass=_MetaXdsUrlMapTestCase):
     """
 
     @staticmethod
-    def supported_clients() -> Tuple[str]:
-        """Declare supported languages of clients.
+    def is_supported(config: TestConfig) -> bool:
+        """Allow the test case to decide whether it supports the given config.
 
         Returns:
-          A tuple of strings contains the supported languages for this test.
+          A bool indicates if the given config is supported.
         """
-        return _CLIENT_LANGUAGES
-
-    @staticmethod
-    def supported_servers() -> Tuple[str]:
-        """Declare supported languages of servers.
-
-        Returns:
-          A tuple of strings contains the supported languages for this test.
-        """
-        return _SERVER_LANGUAGES
+        return True
 
     @staticmethod
     def client_init_config(rpc: str, metadata: str) -> Tuple[str, str]:
@@ -336,15 +360,12 @@ class XdsUrlMapTestCase(absltest.TestCase, metaclass=_MetaXdsUrlMapTestCase):
         # cannot be used in the built-in test-skipping decorators. See the
         # official FAQs:
         # https://abseil.io/docs/python/guides/flags#faqs
-        client_lang = _get_lang(GcpResourceManager().client_image)
-        server_lang = _get_lang(GcpResourceManager().server_image)
-        if client_lang not in cls.supported_clients():
-            cls.skip_reason = (f'Unsupported client language {client_lang} '
-                               f'not in {cls.supported_clients()}')
-            return
-        elif server_lang not in cls.supported_servers():
-            cls.skip_reason = (f'Unsupported server language {server_lang} '
-                               f'not in {cls.supported_servers()}')
+        test_config = TestConfig(
+            client_lang=_get_lang(GcpResourceManager().client_image),
+            server_lang=_get_lang(GcpResourceManager().server_image),
+            version=GcpResourceManager().testing_version)
+        if not cls.is_supported(test_config):
+            cls.skip_reason = f'Unsupported test config: {test_config}'
             return
         else:
             cls.skip_reason = None
@@ -466,10 +487,11 @@ class XdsUrlMapTestCase(absltest.TestCase, metaclass=_MetaXdsUrlMapTestCase):
             rpc = expected_result.rpc_type
             status = expected_result.status_code.value[0]
             # Compute observation
-            seen_after = after_stats.stats_per_method.get(rpc, {}).result.get(
-                status, 0)
-            seen_before = before_stats.stats_per_method.get(rpc, {}).result.get(
-                status, 0)
+            # ProtoBuf messages has special magic dictionary that we don't need
+            # to catch exceptions:
+            # https://developers.google.com/protocol-buffers/docs/reference/python-generated#undefined
+            seen_after = after_stats.stats_per_method[rpc].result[status]
+            seen_before = before_stats.stats_per_method[rpc].result[status]
             seen = seen_after - seen_before
             # Compute total number of RPC started
             stats_per_method_after = after_stats.stats_per_method.get(
index 151aede..a675b9a 100644 (file)
@@ -42,6 +42,8 @@ spec:
           # TODO(sergiitk): this should be conditional for if version < v1.37.x
           - name: GRPC_XDS_EXPERIMENTAL_NEW_SERVER_API
             value: "true"
+          - name: GRPC_XDS_EXPERIMENTAL_RBAC
+            value: "true"
         volumeMounts:
           - mountPath: /tmp/grpc-xds/
             name: grpc-td-conf
diff --git a/tools/run_tests/xds_k8s_test_driver/tests/authz_test.py b/tools/run_tests/xds_k8s_test_driver/tests/authz_test.py
new file mode 100644 (file)
index 0000000..15c52c0
--- /dev/null
@@ -0,0 +1,314 @@
+# 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.
+
+import datetime
+from typing import Optional
+
+from absl import flags
+from absl.testing import absltest
+import grpc
+
+from framework import xds_k8s_testcase
+
+flags.adopt_module_key_flags(xds_k8s_testcase)
+
+# Type aliases
+_XdsTestServer = xds_k8s_testcase.XdsTestServer
+_XdsTestClient = xds_k8s_testcase.XdsTestClient
+_SecurityMode = xds_k8s_testcase.SecurityXdsKubernetesTestCase.SecurityMode
+
+_SAMPLE_DURATION = datetime.timedelta(seconds=0.5)
+
+
+class AuthzTest(xds_k8s_testcase.SecurityXdsKubernetesTestCase):
+    RPC_TYPE_CYCLE = {
+        'UNARY_CALL': 'EMPTY_CALL',
+        'EMPTY_CALL': 'UNARY_CALL',
+    }
+
+    def setUp(self):
+        super().setUp()
+        self.next_rpc_type: Optional[int] = None
+
+    def authz_rules(self):
+        return [
+            {
+                "destinations": {
+                    "hosts": [f"*:{self.server_xds_port}"],
+                    "ports": [self.server_port],
+                    "httpHeaderMatch": {
+                        "headerName": "test",
+                        "regexMatch": "host-wildcard",
+                    },
+                },
+            },
+            {
+                "destinations": {
+                    "hosts": [f"*:{self.server_xds_port}"],
+                    "ports": [self.server_port],
+                    "httpHeaderMatch": {
+                        "headerName": "test",
+                        "regexMatch": "header-regex-a+",
+                    },
+                },
+            },
+            {
+                "destinations": [{
+                    "hosts": [f"{self.server_xds_host}:{self.server_xds_port}"],
+                    "ports": [self.server_port],
+                    "httpHeaderMatch": {
+                        "headerName": "test",
+                        "regexMatch": "host-match1",
+                    },
+                }, {
+                    "hosts": [
+                        f"a-not-it.com:{self.server_xds_port}",
+                        f"{self.server_xds_host}:{self.server_xds_port}",
+                        "z-not-it.com:1",
+                    ],
+                    "ports": [1, self.server_port, 65535],
+                    "httpHeaderMatch": {
+                        "headerName": "test",
+                        "regexMatch": "host-match2",
+                    },
+                }],
+            },
+            {
+                "destinations": {
+                    "hosts": [
+                        f"not-the-host:{self.server_xds_port}",
+                        "not-the-host",
+                    ],
+                    "ports": [self.server_port],
+                    "httpHeaderMatch": {
+                        "headerName": "test",
+                        "regexMatch": "never-match-host",
+                    },
+                },
+            },
+            {
+                "destinations": {
+                    "hosts": [f"*:{self.server_xds_port}"],
+                    "ports": [1],
+                    "httpHeaderMatch": {
+                        "headerName": "test",
+                        "regexMatch": "never-match-port",
+                    },
+                },
+            },
+            {
+                "sources": {
+                    "principals": ["*"],
+                },
+                "destinations": {
+                    "hosts": [f"*:{self.server_xds_port}"],
+                    "ports": [self.server_port],
+                    "httpHeaderMatch": {
+                        "headerName": "test",
+                        "regexMatch": "principal-present",
+                    },
+                },
+            },
+            {
+                "sources": [{
+                    "principals": [
+                        f"spiffe://{self.project}.svc.id.goog/not/the/client",
+                    ],
+                }, {
+                    "principals": [
+                        f"spiffe://{self.project}.svc.id.goog/not/the/client",
+                        f"spiffe://{self.project}.svc.id.goog/ns/"
+                        f"{self.client_namespace}/sa/{self.client_name}",
+                    ],
+                }],
+                "destinations": {
+                    "hosts": [f"*:{self.server_xds_port}"],
+                    "ports": [self.server_port],
+                    "httpHeaderMatch": {
+                        "headerName": "test",
+                        "regexMatch": "match-principal",
+                    },
+                },
+            },
+            {
+                "sources": {
+                    "principals": [
+                        f"spiffe://{self.project}.svc.id.goog/not/the/client",
+                    ],
+                },
+                "destinations": {
+                    "hosts": [f"*:{self.server_xds_port}"],
+                    "ports": [self.server_port],
+                    "httpHeaderMatch": {
+                        "headerName": "test",
+                        "regexMatch": "never-match-principal",
+                    },
+                },
+            },
+        ]
+
+    def configure_and_assert(self, test_client: _XdsTestClient,
+                             test_metadata_val: Optional[str],
+                             status_code: grpc.StatusCode) -> None:
+        # Swap method type every sub-test to avoid mixing results
+        rpc_type = self.next_rpc_type
+        if rpc_type is None:
+            stats = test_client.get_load_balancer_accumulated_stats()
+            for t in self.RPC_TYPE_CYCLE:
+                if not stats.stats_per_method[t].rpcs_started:
+                    rpc_type = t
+            self.assertIsNotNone(rpc_type, "All RPC types already used")
+        self.next_rpc_type = self.RPC_TYPE_CYCLE[rpc_type]
+
+        metadata = None
+        if test_metadata_val is not None:
+            metadata = ((rpc_type, "test", test_metadata_val),)
+        test_client.update_config.configure(rpc_types=[rpc_type],
+                                            metadata=metadata)
+        self.assertRpcStatusCodes(test_client,
+                                  status_code=status_code,
+                                  duration=_SAMPLE_DURATION,
+                                  method=rpc_type)
+
+    def test_plaintext_allow(self) -> None:
+        self.setupTrafficDirectorGrpc()
+        self.td.create_authz_policy(action='ALLOW', rules=self.authz_rules())
+        self.setupSecurityPolicies(server_tls=False,
+                                   server_mtls=False,
+                                   client_tls=False,
+                                   client_mtls=False)
+
+        test_server: _XdsTestServer = self.startSecureTestServer()
+        self.setupServerBackends()
+        test_client: _XdsTestClient = self.startSecureTestClient(test_server)
+
+        with self.subTest('01_host_wildcard'):
+            self.configure_and_assert(test_client, 'host-wildcard',
+                                      grpc.StatusCode.OK)
+
+        with self.subTest('02_no_match'):
+            self.configure_and_assert(test_client, 'no-such-rule',
+                                      grpc.StatusCode.PERMISSION_DENIED)
+            self.configure_and_assert(test_client, None,
+                                      grpc.StatusCode.PERMISSION_DENIED)
+
+        with self.subTest('03_header_regex'):
+            self.configure_and_assert(test_client, 'header-regex-a',
+                                      grpc.StatusCode.OK)
+            self.configure_and_assert(test_client, 'header-regex-aa',
+                                      grpc.StatusCode.OK)
+            self.configure_and_assert(test_client, 'header-regex-',
+                                      grpc.StatusCode.PERMISSION_DENIED)
+            self.configure_and_assert(test_client, 'header-regex-ab',
+                                      grpc.StatusCode.PERMISSION_DENIED)
+            self.configure_and_assert(test_client, 'aheader-regex-a',
+                                      grpc.StatusCode.PERMISSION_DENIED)
+
+        with self.subTest('04_host_match'):
+            self.configure_and_assert(test_client, 'host-match1',
+                                      grpc.StatusCode.OK)
+            self.configure_and_assert(test_client, 'host-match2',
+                                      grpc.StatusCode.OK)
+
+        with self.subTest('05_never_match_host'):
+            self.configure_and_assert(test_client, 'never-match-host',
+                                      grpc.StatusCode.PERMISSION_DENIED)
+
+        with self.subTest('06_never_match_port'):
+            self.configure_and_assert(test_client, 'never-match-port',
+                                      grpc.StatusCode.PERMISSION_DENIED)
+
+        with self.subTest('07_principal_present'):
+            self.configure_and_assert(test_client, 'principal-present',
+                                      grpc.StatusCode.PERMISSION_DENIED)
+
+    def test_tls_allow(self) -> None:
+        self.setupTrafficDirectorGrpc()
+        self.td.create_authz_policy(action='ALLOW', rules=self.authz_rules())
+        self.setupSecurityPolicies(server_tls=True,
+                                   server_mtls=False,
+                                   client_tls=True,
+                                   client_mtls=False)
+
+        test_server: _XdsTestServer = self.startSecureTestServer()
+        self.setupServerBackends()
+        test_client: _XdsTestClient = self.startSecureTestClient(test_server)
+
+        with self.subTest('01_host_wildcard'):
+            self.configure_and_assert(test_client, 'host-wildcard',
+                                      grpc.StatusCode.OK)
+
+        with self.subTest('02_no_match'):
+            self.configure_and_assert(test_client, None,
+                                      grpc.StatusCode.PERMISSION_DENIED)
+
+        # b/202058316
+        # with self.subTest('03_principal_present'):
+        #     self.configure_and_assert(test_client, 'principal-present',
+        #                               grpc.StatusCode.PERMISSION_DENIED)
+
+    def test_mtls_allow(self) -> None:
+        self.setupTrafficDirectorGrpc()
+        self.td.create_authz_policy(action='ALLOW', rules=self.authz_rules())
+        self.setupSecurityPolicies(server_tls=True,
+                                   server_mtls=True,
+                                   client_tls=True,
+                                   client_mtls=True)
+
+        test_server: _XdsTestServer = self.startSecureTestServer()
+        self.setupServerBackends()
+        test_client: _XdsTestClient = self.startSecureTestClient(test_server)
+
+        with self.subTest('01_host_wildcard'):
+            self.configure_and_assert(test_client, 'host-wildcard',
+                                      grpc.StatusCode.OK)
+
+        with self.subTest('02_no_match'):
+            self.configure_and_assert(test_client, None,
+                                      grpc.StatusCode.PERMISSION_DENIED)
+
+        with self.subTest('03_principal_present'):
+            self.configure_and_assert(test_client, 'principal-present',
+                                      grpc.StatusCode.OK)
+
+        with self.subTest('04_match_principal'):
+            self.configure_and_assert(test_client, 'match-principal',
+                                      grpc.StatusCode.OK)
+
+        with self.subTest('05_never_match_principal'):
+            self.configure_and_assert(test_client, 'never-match-principal',
+                                      grpc.StatusCode.PERMISSION_DENIED)
+
+    def test_plaintext_deny(self) -> None:
+        self.setupTrafficDirectorGrpc()
+        self.td.create_authz_policy(action='DENY', rules=self.authz_rules())
+        self.setupSecurityPolicies(server_tls=False,
+                                   server_mtls=False,
+                                   client_tls=False,
+                                   client_mtls=False)
+
+        test_server: _XdsTestServer = self.startSecureTestServer()
+        self.setupServerBackends()
+        test_client: _XdsTestClient = self.startSecureTestClient(test_server)
+
+        with self.subTest('01_host_wildcard'):
+            self.configure_and_assert(test_client, 'host-wildcard',
+                                      grpc.StatusCode.PERMISSION_DENIED)
+
+        with self.subTest('02_no_match'):
+            self.configure_and_assert(test_client, None, grpc.StatusCode.OK)
+
+
+if __name__ == '__main__':
+    absltest.main()
index fdbad45..504126e 100644 (file)
@@ -31,6 +31,7 @@ GcpResourceManager = xds_url_map_testcase.GcpResourceManager
 DumpedXdsConfig = xds_url_map_testcase.DumpedXdsConfig
 RpcTypeUnaryCall = xds_url_map_testcase.RpcTypeUnaryCall
 RpcTypeEmptyCall = xds_url_map_testcase.RpcTypeEmptyCall
+TestConfig = xds_url_map_testcase.TestConfig
 XdsTestClient = client_app.XdsTestClient
 
 logger = logging.getLogger(__name__)
@@ -56,8 +57,12 @@ _ChannelzChannelState = grpc_channelz.ChannelState
 class TestHeaderBasedAffinity(xds_url_map_testcase.XdsUrlMapTestCase):
 
     @staticmethod
-    def supported_clients() -> Tuple[str]:
-        return 'cpp', 'java'
+    def is_supported(config: TestConfig) -> bool:
+        if config.client_lang in ['cpp', 'java']:
+            return config.version_ge('v1.40.x')
+        if config.client_lang in ['go']:
+            return config.version_ge('v1.41.x')
+        return False
 
     @staticmethod
     def client_init_config(rpc: str, metadata: str):
@@ -121,8 +126,12 @@ class TestHeaderBasedAffinityMultipleHeaders(
         xds_url_map_testcase.XdsUrlMapTestCase):
 
     @staticmethod
-    def supported_clients() -> Tuple[str]:
-        return 'cpp', 'java'
+    def is_supported(config: TestConfig) -> bool:
+        if config.client_lang in ['cpp', 'java']:
+            return config.version_ge('v1.40.x')
+        if config.client_lang in ['go']:
+            return config.version_ge('v1.41.x')
+        return False
 
     @staticmethod
     def client_init_config(rpc: str, metadata: str):
index ab0a2c6..b3eef2d 100644 (file)
@@ -31,6 +31,7 @@ DumpedXdsConfig = xds_url_map_testcase.DumpedXdsConfig
 RpcTypeUnaryCall = xds_url_map_testcase.RpcTypeUnaryCall
 XdsTestClient = client_app.XdsTestClient
 ExpectedResult = xds_url_map_testcase.ExpectedResult
+TestConfig = xds_url_map_testcase.TestConfig
 
 logger = logging.getLogger(__name__)
 flags.adopt_module_key_flags(xds_url_map_testcase)
@@ -66,8 +67,12 @@ def _build_retry_route_rule(retryConditions, num_retries):
 class TestRetryUpTo3AttemptsAndFail(xds_url_map_testcase.XdsUrlMapTestCase):
 
     @staticmethod
-    def supported_clients() -> Tuple[str]:
-        return 'cpp', 'java'
+    def is_supported(config: TestConfig) -> bool:
+        if config.client_lang in ['cpp', 'java', 'python']:
+            return config.version_ge('v1.40.x')
+        elif config.client_lang == 'go':
+            return config.version_ge('v1.41.x')
+        return False
 
     @staticmethod
     def url_map_change(
@@ -105,8 +110,12 @@ class TestRetryUpTo3AttemptsAndFail(xds_url_map_testcase.XdsUrlMapTestCase):
 class TestRetryUpTo4AttemptsAndSucceed(xds_url_map_testcase.XdsUrlMapTestCase):
 
     @staticmethod
-    def supported_clients() -> Tuple[str]:
-        return 'cpp', 'java'
+    def is_supported(config: TestConfig) -> bool:
+        if config.client_lang in ['cpp', 'java', 'python']:
+            return config.version_ge('v1.40.x')
+        elif config.client_lang == 'go':
+            return config.version_ge('v1.41.x')
+        return False
 
     @staticmethod
     def url_map_change(
index dd81306..33f4f43 100644 (file)
@@ -34,6 +34,7 @@ RpcTypeEmptyCall = xds_url_map_testcase.RpcTypeEmptyCall
 ExpectedResult = xds_url_map_testcase.ExpectedResult
 XdsTestClient = client_app.XdsTestClient
 XdsUrlMapTestCase = xds_url_map_testcase.XdsUrlMapTestCase
+TestConfig = xds_url_map_testcase.TestConfig
 
 logger = logging.getLogger(__name__)
 flags.adopt_module_key_flags(xds_url_map_testcase)
@@ -81,10 +82,10 @@ class _BaseXdsTimeOutTestCase(XdsUrlMapTestCase):
 class TestTimeoutInRouteRule(_BaseXdsTimeOutTestCase):
 
     @staticmethod
-    def supported_servers() -> Tuple[str]:
+    def is_supported(config: TestConfig) -> bool:
         # TODO(lidiz) either add support for rpc-behavior to other languages, or we
         # should always use Java server as backend.
-        return 'java',
+        return config.server_lang == 'java'
 
     def rpc_distribution_validate(self, test_client: XdsTestClient):
         rpc_distribution = self.configure_and_send(
@@ -112,8 +113,8 @@ class TestTimeoutInRouteRule(_BaseXdsTimeOutTestCase):
 class TestTimeoutInApplication(_BaseXdsTimeOutTestCase):
 
     @staticmethod
-    def supported_servers() -> Tuple[str]:
-        return 'java',
+    def is_supported(config: TestConfig) -> bool:
+        return config.server_lang == 'java'
 
     def rpc_distribution_validate(self, test_client: XdsTestClient):
         rpc_distribution = self.configure_and_send(